aboutsummaryrefslogtreecommitdiffstats
path: root/block.go
blob: 5c089137d5d83c27e873db0464cee038c5177537 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main

import (
  "fmt"
  "time"
  _"bytes"
)

type Block struct {
  number        uint32
  prevHash      string
  uncles        []*Block
  coinbase      string
  // state xxx
  difficulty    uint32
  time          time.Time
  nonce         uint32
  transactions  []*Transaction
}

func NewBlock(/* TODO use raw data */transactions []*Transaction) *Block {
  block := &Block{
    // Slice of transactions to include in this block
    transactions: transactions,
    number: 1,
    prevHash: "1234",
    coinbase: "me",
    difficulty: 10,
    nonce: 0,

    time: time.Now(),
  }

  return block
}

func (block *Block) Update() {
}

func (block *Block) Hash() string {
  return Sha256Hex(block.MarshalRlp())
}

func (block *Block) MarshalRlp() []byte {
  // Encoding method requires []interface{} type. It's actual a slice of strings
  encTx := make([]string, len(block.transactions))
  for i, tx := range block.transactions {
    encTx[i] = string(tx.MarshalRlp())
  }

  /* I made up the block. It should probably contain different data or types. It sole purpose now is testing */
  header := []interface{}{
    block.number,
    block.prevHash,
    // Sha of uncles
    "",
    block.coinbase,
    // root state
    "",
    string(Sha256Bin([]byte(RlpEncode(encTx)))),
    block.difficulty,
    block.time.String(),
    block.nonce,
    // extra?
  }

  encoded := Encode([]interface{}{header, encTx})

  return encoded
}

func (block *Block) UnmarshalRlp(data []byte) {
  t, _ := Decode(data,0)
  if slice, ok := t.([]interface{}); ok {
    if header, ok := slice[0].([]interface{}); ok {
      if number, ok := header[0].(uint8); ok {
        block.number = uint32(number)
      }

      if prevHash, ok := header[1].([]byte); ok {
        block.prevHash = string(prevHash)
      }

      // sha of uncles is header[2]

      if coinbase, ok := header[3].([]byte); ok {
        block.coinbase = string(coinbase)
      }

      // state is header[header[4]

      // sha is header[5]

      // It's either 8bit or 64
      if difficulty, ok := header[6].(uint8); ok {
        block.difficulty = uint32(difficulty)
      }
      if difficulty, ok := header[6].(uint64); ok {
        block.difficulty = uint32(difficulty)
      }

      if time, ok := header[7].([]byte); ok {
        fmt.Sprintf("Time is: ", string(time))
      }

      if nonce, ok := header[8].(uint8); ok {
        block.nonce = uint32(nonce)
      }
    }

    if txSlice, ok := slice[1].([]interface{}); ok {
      block.transactions = make([]*Transaction, len(txSlice))

      for i, tx := range txSlice {
        if t, ok := tx.([]byte); ok {
          tx := &Transaction{}
          tx.UnmarshalRlp(t)

          block.transactions[i] = tx
        }
      }
    }
  }
}