From 0929f59ec260e2a29863b8764959b271a7f75cc8 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 8 Jan 2014 23:42:11 +0100 Subject: [PATCH] Updated marshalling --- block.go | 89 ++++++++----------------------------- contract.go | 24 ++-------- genesis.go | 2 - rlp.go | 105 ++++++++++++++++++++++++++++++++++++++++++++ transaction.go | 116 +++++++++++++++---------------------------------- 5 files changed, 164 insertions(+), 172 deletions(-) diff --git a/block.go b/block.go index 00317573c5..6ae3cc832a 100644 --- a/block.go +++ b/block.go @@ -74,7 +74,6 @@ func CreateBlock(root string, num int, prevHash string, base string, difficulty block.state.Update(string(addr), string(contract.MarshalRlp())) for i, val := range tx.data { contract.state.Update(string(NumberToBytes(uint64(i), 32)), val) - //contract.state.Update(string(Encode(uint32(i))), val) } block.UpdateContract(addr, contract) } @@ -105,6 +104,7 @@ func (block *Block) PayFee(addr []byte, fee uint64) bool { // If we can't pay the fee return if contract == nil || contract.amount < fee { fmt.Println("Contract has insufficient funds", contract.amount, fee) + return false } @@ -112,7 +112,7 @@ func (block *Block) PayFee(addr []byte, fee uint64) bool { block.state.Update(string(addr), string(contract.MarshalRlp())) data := block.state.Get(string(block.coinbase)) - println(data) + // Get the ether (coinbase) and add the fee (gief fee to miner) ether := NewEtherFromData([]byte(data)) ether.amount += fee @@ -159,75 +159,24 @@ func (block *Block) MarshalRlp() []byte { } func (block *Block) UnmarshalRlp(data []byte) { - t, _ := Decode(data,0) + decoder := NewRlpDecoder(data) - // interface slice assertion - if slice, ok := t.([]interface{}); ok { - // interface slice assertion - if header, ok := slice[0].([]interface{}); ok { - if number, ok := header[0].(uint8); ok { - block.number = uint32(number) - } + header := decoder.Get(0) + block.number = uint32(header.Get(0).AsUint()) + block.prevHash = header.Get(1).AsString() + // sha of uncles is header[2] + block.coinbase = header.Get(3).AsString() + block.state = NewTrie(Db, header.Get(4).AsString()) + block.difficulty = uint32(header.Get(5).AsUint()) + block.time = int64(header.Get(6).AsUint()) + block.nonce = uint32(header.Get(7).AsUint()) + block.extra = header.Get(8).AsString() - if prevHash, ok := header[1].([]uint8); ok { - block.prevHash = string(prevHash) - } - - // sha of uncles is header[2] - - if coinbase, ok := header[3].([]byte); ok { - block.coinbase = string(coinbase) - } - - if state, ok := header[4].([]uint8); ok { - // XXX The database is currently a global variable defined in testing.go - // This will eventually go away and the database will grabbed from the public server - // interface - block.state = NewTrie(Db, string(state)) - } - - // 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) - } - - // It's either 8bit or 64 - if time, ok := header[7].(uint8); ok { - block.time = int64(time) - } - if time, ok := header[7].(uint64); ok { - block.time = int64(time) - } - - if nonce, ok := header[8].(uint8); ok { - block.nonce = uint32(nonce) - } - - if extra, ok := header[9].([]byte); ok { - block.extra = string(extra) - } - } - - if txSlice, ok := slice[1].([]interface{}); ok { - // Create transaction slice equal to decoded tx interface slice - block.transactions = make([]*Transaction, len(txSlice)) - - // Unmarshal transactions - for i, tx := range txSlice { - if t, ok := tx.([]byte); ok { - tx := &Transaction{} - // Use the unmarshaled data to unmarshal the transaction - // t is still decoded. - tx.UnmarshalRlp(t) - - block.transactions[i] = tx - } - } - } + txes := decoder.Get(1) + block.transactions = make([]*Transaction, txes.Length()) + for i := 0; i < txes.Length(); i++ { + tx := &Transaction{} + tx.UnmarshalRlp(txes.Get(i).AsBytes()) + block.transactions[i] = tx } } diff --git a/contract.go b/contract.go index 778f3578d4..a54643f590 100644 --- a/contract.go +++ b/contract.go @@ -22,27 +22,11 @@ func (c *Contract) MarshalRlp() []byte { } func (c *Contract) UnmarshalRlp(data []byte) { - t, _ := Decode(data, 0) + decoder := NewRlpDecoder(data) - if slice, ok := t.([]interface{}); ok { - if t, ok := slice[0].(uint8); ok { - c.t = uint32(t) - } - - if amount, ok := slice[1].(uint8); ok { - c.amount = uint64(amount) - } else if amount, ok := slice[1].(uint16); ok { - c.amount = uint64(amount) - } else if amount, ok := slice[1].(uint32); ok { - c.amount = uint64(amount) - } else if amount, ok := slice[1].(uint64); ok { - c.amount = amount - } - - if root, ok := slice[2].([]uint8); ok { - c.state = NewTrie(Db, string(root)) - } - } + c.t = uint32(decoder.Get(0).AsUint()) + c.amount = decoder.Get(1).AsUint() + c.state = NewTrie(Db, decoder.Get(2).AsString()) } type Ether struct { diff --git a/genesis.go b/genesis.go index aae9cd1cfe..21b8e9998f 100644 --- a/genesis.go +++ b/genesis.go @@ -32,5 +32,3 @@ var GenisisHeader = []interface{}{ } var Genesis = []interface{}{ GenisisHeader, []interface{}{}, []interface{}{} } - -var GenisisBlock = NewBlock( Encode(Genesis) ) diff --git a/rlp.go b/rlp.go index 4db88539dc..5366632f4f 100644 --- a/rlp.go +++ b/rlp.go @@ -4,8 +4,110 @@ import ( "fmt" "bytes" "math" + "math/big" ) +type RlpEncoder struct { + rlpData []byte +} +func NewRlpEncoder() *RlpEncoder { + encoder := &RlpEncoder{} + + return encoder +} +func (coder *RlpEncoder) EncodeData(rlpData []interface{}) []byte { + return nil +} + +// Data attributes are returned by the rlp decoder. The data attributes represents +// one item within the rlp data structure. It's responsible for all the casting +// It always returns something valid +type RlpDataAttribute struct { + dataAttrib interface{} +} + +func NewRlpDataAttribute(attrib interface{}) *RlpDataAttribute { + return &RlpDataAttribute{dataAttrib: attrib} +} + +func (attr *RlpDataAttribute) Length() int { + if data, ok := attr.dataAttrib.([]interface{}); ok { + return len(data) + } + + return 0 +} + +func (attr *RlpDataAttribute) AsUint() uint64 { + if value, ok := attr.dataAttrib.(uint8); ok { + return uint64(value) + } else if value, ok := attr.dataAttrib.(uint16); ok { + return uint64(value) + } else if value, ok := attr.dataAttrib.(uint32); ok { + return uint64(value) + } else if value, ok := attr.dataAttrib.(uint64); ok { + return value + } + + return 0 +} + +func (attr *RlpDataAttribute) AsBigInt() *big.Int { + if a, ok := attr.dataAttrib.([]byte); ok { + return Big(string(a)) + } + + return big.NewInt(0) +} + +func (attr *RlpDataAttribute) AsString() string { + if a, ok := attr.dataAttrib.([]byte); ok { + return string(a) + } + + return "" +} + +func (attr *RlpDataAttribute) AsBytes() []byte { + if a, ok := attr.dataAttrib.([]byte); ok { + return a + } + + return make([]byte, 0) +} + +// Threat the attribute as a slice +func (attr *RlpDataAttribute) Get(idx int) *RlpDataAttribute { + if d, ok := attr.dataAttrib.([]interface{}); ok { + // Guard for oob + if len(d) < idx { + return NewRlpDataAttribute(nil) + } + + return NewRlpDataAttribute(d[idx]) + } + + // If this wasn't a slice you probably shouldn't be using this function + return NewRlpDataAttribute(nil) +} + +type RlpDecoder struct { + rlpData interface{} +} +func NewRlpDecoder(rlpData []byte) *RlpDecoder { + decoder := &RlpDecoder{} + // Decode the data + data, _ := Decode(rlpData,0) + decoder.rlpData = data + + return decoder +} + +func (dec *RlpDecoder) Get(idx int) *RlpDataAttribute { + return NewRlpDataAttribute(dec.rlpData).Get(idx) +} + +/// Raw methods func BinaryLength(n uint64) uint64 { if n == 0 { return 0 } @@ -122,6 +224,9 @@ func Encode(object interface{}) []byte { buff.WriteString(string(len(b2) + 55) + b2 + b) } + case *big.Int: + buff.Write(Encode(t.String())) + case string: if len(t) < 56 { buff.WriteString(string(len(t) + 64) + t) diff --git a/transaction.go b/transaction.go index 168d58566b..90e0d98696 100644 --- a/transaction.go +++ b/transaction.go @@ -2,7 +2,7 @@ package main import ( "math/big" - _"fmt" + "fmt" "github.com/obscuren/secp256k1-go" _"encoding/hex" _"crypto/sha256" @@ -64,7 +64,8 @@ func NewTransaction(to string, value uint64, data []string) *Transaction { tx.data[i] = instr } - tx.SetVRS() + tx.Sign([]byte("privkey")) + tx.Sender() return &tx @@ -86,9 +87,9 @@ func (tx *Transaction) IsContract() bool { return tx.recipient == "" } -func (tx *Transaction) Signature() []byte { +func (tx *Transaction) Signature(key []byte) []byte { hash := tx.Hash() - sec := Sha256Bin([]byte("myprivkey")) + sec := Sha256Bin(key) sig, _ := secp256k1.Sign(hash, sec) @@ -96,29 +97,33 @@ func (tx *Transaction) Signature() []byte { } func (tx *Transaction) PublicKey() []byte { - hash := Sha256Bin(tx.MarshalRlp()) - sig := tx.Signature() + hash := Sha256Bin(tx.Hash()) + sig := append(tx.r, tx.s...) pubkey, _ := secp256k1.RecoverPubkey(hash, sig) return pubkey } -func (tx *Transaction) Address() []byte { - pubk := tx.PublicKey() - // 1 is the marker 04 - key := pubk[1:65] +func (tx *Transaction) Sender() []byte { + pubkey := tx.PublicKey() - return Sha256Bin(key)[12:] + // Validate the returned key. + // Return nil if public key isn't in full format (04 = full, 03 = compact) + if pubkey[0] != 4 { + return nil + } + + return Sha256Bin(pubkey[1:65])[12:] } -func (tx *Transaction) SetVRS() { - // Add 27 so we get either 27 or 28 (for positive and negative) - tx.v = uint32(tx.Signature()[64]) + 27 +func (tx *Transaction) Sign(privk []byte) { + sig := tx.Signature(privk) - pubk := tx.PublicKey()[1:65] - tx.r = pubk[:32] - tx.s = pubk[32:64] + // Add 27 so we get either 27 or 28 (for positive and negative) + tx.v = uint32(sig[64]) + 27 + tx.r = sig[:32] + tx.s = sig[32:65] } func (tx *Transaction) MarshalRlp() []byte { @@ -138,72 +143,23 @@ func (tx *Transaction) MarshalRlp() []byte { } func (tx *Transaction) UnmarshalRlp(data []byte) { - t, _ := Decode(data,0) - if slice, ok := t.([]interface{}); ok { - if nonce, ok := slice[0].(uint8); ok { - tx.nonce = string(nonce) - } + decoder := NewRlpDecoder(data) - if recipient, ok := slice[1].([]byte); ok { - tx.recipient = string(recipient) - } + tx.nonce = decoder.Get(0).AsString() + tx.recipient = decoder.Get(0).AsString() + tx.value = decoder.Get(2).AsUint() + tx.fee = uint32(decoder.Get(3).AsUint()) - // If only I knew of a better way. - if value, ok := slice[2].(uint8); ok { - tx.value = uint64(value) - } - if value, ok := slice[2].(uint16); ok { - tx.value = uint64(value) - } - if value, ok := slice[2].(uint32); ok { - tx.value = uint64(value) - } - if value, ok := slice[2].(uint64); ok { - tx.value = uint64(value) - } - if fee, ok := slice[3].(uint8); ok { - tx.fee = uint32(fee) - } - if fee, ok := slice[3].(uint16); ok { - tx.fee = uint32(fee) - } - if fee, ok := slice[3].(uint32); ok { - tx.fee = uint32(fee) - } - if fee, ok := slice[3].(uint64); ok { - tx.fee = uint32(fee) - } - - // Encode the data/instructions - if data, ok := slice[4].([]interface{}); ok { - tx.data = make([]string, len(data)) - for i, d := range data { - if instr, ok := d.([]byte); ok { - tx.data[i] = string(instr) - } - } - } - - // vrs - if v, ok := slice[5].(uint8); ok { - tx.v = uint32(v) - } - if v, ok := slice[5].(uint16); ok { - tx.v = uint32(v) - } - if v, ok := slice[5].(uint32); ok { - tx.v = uint32(v) - } - if v, ok := slice[5].(uint64); ok { - tx.v = uint32(v) - } - if r, ok := slice[6].([]byte); ok { - tx.r = r - } - if s, ok := slice[7].([]byte); ok { - tx.s = s - } + d := decoder.Get(4) + tx.data = make([]string, d.Length()) + fmt.Println(d.Get(0)) + for i := 0; i < d.Length(); i++ { + tx.data[i] = d.Get(i).AsString() } + + tx.v = uint32(decoder.Get(5).AsUint()) + tx.r = decoder.Get(6).AsBytes() + tx.s = decoder.Get(7).AsBytes() } func InitFees() {