From f486c0ae563eaf89a601ca5d60f30be96db2e69a Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Mar 2015 11:59:52 +0100 Subject: new type + additional methods --- core/types/block.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index 2d65cdca6..fadf67086 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -8,26 +8,26 @@ import ( "sort" "time" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" ) type Header struct { // Hash to the previous block - ParentHash []byte + ParentHash common.Hash // Uncles of this block - UncleHash []byte + UncleHash common.Hash // The coin base address - Coinbase []byte + Coinbase common.Address // Block Trie state - Root []byte + Root common.Hash // Tx sha - TxHash []byte + TxHash common.Hash // Receipt sha - ReceiptHash []byte + ReceiptHash common.Hash // Bloom - Bloom []byte + Bloom [256]byte // Difficulty for the current block Difficulty *big.Int // The block number @@ -41,9 +41,9 @@ type Header struct { // Extra data Extra string // Mix digest for quick checking to prevent DOS - MixDigest []byte + MixDigest common.Hash // Nonce - Nonce []byte + Nonce [8]byte } func (self *Header) rlpData(withNonce bool) []interface{} { @@ -206,13 +206,13 @@ func (self *Block) SetNonce(nonce uint64) { self.header.setNonce(nonce) } -func (self *Block) Bloom() []byte { return self.header.Bloom } -func (self *Block) Coinbase() []byte { return self.header.Coinbase } -func (self *Block) Time() int64 { return int64(self.header.Time) } -func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } -func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } -func (self *Block) Root() []byte { return self.header.Root } -func (self *Block) SetRoot(root []byte) { self.header.Root = root } +func (self *Block) Bloom() []byte { return self.header.Bloom } +func (self *Block) Coinbase() []byte { return self.header.Coinbase } +func (self *Block) Time() int64 { return int64(self.header.Time) } +func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } +func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } +func (self *Block) Root() []byte { return self.header.Root } +func (self *Block) SetRoot(root []byte) { self.header.Root = root } func (self *Block) Size() common.StorageSize { return common.StorageSize(len(common.Encode(self))) } func (self *Block) GetTransaction(i int) *Transaction { if len(self.transactions) > i { -- cgit v1.2.3 From bfcd2cf132c2f1e5c1afe6d71e3d9d9dcee5017b Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Mar 2015 17:27:23 +0100 Subject: block conversion --- core/types/block.go | 61 ++++++++++++++++++++++++------------------------ core/types/block_test.go | 19 +++++++++++++++ core/types/bloom9.go | 6 ++--- core/types/common.go | 19 +++++++++++++++ core/types/derive_sha.go | 6 ++--- 5 files changed, 75 insertions(+), 36 deletions(-) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index fadf67086..9a97061b7 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -27,7 +27,7 @@ type Header struct { // Receipt sha ReceiptHash common.Hash // Bloom - Bloom [256]byte + Bloom Bloom // Difficulty for the current block Difficulty *big.Int // The block number @@ -73,28 +73,30 @@ func (self *Header) RlpData() interface{} { return self.rlpData(true) } -func (self *Header) Hash() []byte { - return crypto.Sha3(common.Encode(self.rlpData(true))) +func (self *Header) Hash() common.Hash { + return common.BytesToHash(crypto.Sha3(common.Encode(self.rlpData(true)))) } -func (self *Header) HashNoNonce() []byte { - return crypto.Sha3(common.Encode(self.rlpData(false))) +func (self *Header) HashNoNonce() common.Hash { + return common.BytesToHash(crypto.Sha3(common.Encode(self.rlpData(false)))) } type Block struct { - // Preset Hash for mock - HeaderHash []byte - ParentHeaderHash []byte - header *Header - uncles []*Header - transactions Transactions - Td *big.Int + // Preset Hash for mock (Tests) + HeaderHash common.Hash + ParentHeaderHash common.Hash + // ^^^^ ignore ^^^^ + + header *Header + uncles []*Header + transactions Transactions + Td *big.Int receipts Receipts Reward *big.Int } -func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.Int, nonce uint64, extra string) *Block { +func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash, difficulty *big.Int, nonce uint64, extra string) *Block { header := &Header{ Root: root, ParentHash: parentHash, @@ -113,8 +115,7 @@ func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.I } func (self *Header) setNonce(nonce uint64) { - self.Nonce = make([]byte, 8) - binary.BigEndian.PutUint64(self.Nonce, nonce) + binary.BigEndian.PutUint64(self.Nonce[:], nonce) } func NewBlockWithHeader(header *Header) *Block { @@ -148,7 +149,7 @@ func (self *Block) Uncles() []*Header { func (self *Block) SetUncles(uncleHeaders []*Header) { self.uncles = uncleHeaders - self.header.UncleHash = crypto.Sha3(common.Encode(uncleHeaders)) + self.header.UncleHash = common.BytesToHash(crypto.Sha3(common.Encode(uncleHeaders))) } func (self *Block) Transactions() Transactions { @@ -196,23 +197,23 @@ func (self *Block) RlpDataForStorage() interface{} { } // Header accessors (add as you need them) -func (self *Block) Number() *big.Int { return self.header.Number } -func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } -func (self *Block) MixDigest() []byte { return self.header.MixDigest } +func (self *Block) Number() *big.Int { return self.header.Number } +func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } +func (self *Block) MixDigest() common.Hash { return self.header.MixDigest } func (self *Block) Nonce() uint64 { - return binary.BigEndian.Uint64(self.header.Nonce) + return binary.BigEndian.Uint64(self.header.Nonce[:]) } func (self *Block) SetNonce(nonce uint64) { self.header.setNonce(nonce) } -func (self *Block) Bloom() []byte { return self.header.Bloom } -func (self *Block) Coinbase() []byte { return self.header.Coinbase } +func (self *Block) Bloom() Bloom { return self.header.Bloom } +func (self *Block) Coinbase() common.Address { return self.header.Coinbase } func (self *Block) Time() int64 { return int64(self.header.Time) } func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } -func (self *Block) Root() []byte { return self.header.Root } -func (self *Block) SetRoot(root []byte) { self.header.Root = root } +func (self *Block) Root() common.Hash { return self.header.Root } +func (self *Block) SetRoot(root common.Hash) { self.header.Root = root } func (self *Block) Size() common.StorageSize { return common.StorageSize(len(common.Encode(self))) } func (self *Block) GetTransaction(i int) *Transaction { if len(self.transactions) > i { @@ -228,19 +229,19 @@ func (self *Block) GetUncle(i int) *Header { } // Implement pow.Block -func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } -func (self *Block) HashNoNonce() []byte { return self.header.HashNoNonce() } +func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } +func (self *Block) HashNoNonce() common.Hash { return self.header.HashNoNonce() } -func (self *Block) Hash() []byte { - if self.HeaderHash != nil { +func (self *Block) Hash() common.Hash { + if (self.HeaderHash != common.Hash{}) { return self.HeaderHash } else { return self.header.Hash() } } -func (self *Block) ParentHash() []byte { - if self.ParentHeaderHash != nil { +func (self *Block) ParentHash() common.Hash { + if (self.ParentHeaderHash != common.Hash{}) { return self.ParentHeaderHash } else { return self.header.ParentHash diff --git a/core/types/block_test.go b/core/types/block_test.go index ab1254f4c..e2fa2cad2 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -1 +1,20 @@ package types + +import ( + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +func TestConversion(t *testing.T) { + var ( + parent common.Hash + coinbase common.Address + hash common.Hash + ) + + block := NewBlock(parent, coinbase, hash, big.NewInt(0), 0, "") + fmt.Println(block) +} diff --git a/core/types/bloom9.go b/core/types/bloom9.go index af76f226f..e5b5e395f 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -3,18 +3,18 @@ package types import ( "math/big" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" ) -func CreateBloom(receipts Receipts) []byte { +func CreateBloom(receipts Receipts) Bloom { bin := new(big.Int) for _, receipt := range receipts { bin.Or(bin, LogsBloom(receipt.logs)) } - return common.LeftPadBytes(bin.Bytes(), 256) + return BytesToBloom(bin.Bytes()) } func LogsBloom(logs state.Logs) *big.Int { diff --git a/core/types/common.go b/core/types/common.go index 795374959..dd5dc00c8 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -5,3 +5,22 @@ import "math/big" type BlockProcessor interface { Process(*Block) (*big.Int, error) } + +type Bloom [256]byte + +func BytesToBloom(b []byte) Bloom { + var bloom Bloom + bloom.SetBytes(b) + return bloom +} + +func (b *Bloom) SetBytes(d []byte) { + if len(b) > len(d) { + panic("bloom bytes too big") + } + + // reverse loop + for i := len(d) - 1; i >= 0; i-- { + b[i] = b[i] + } +} diff --git a/core/types/derive_sha.go b/core/types/derive_sha.go index 593a31f1c..0fc45a508 100644 --- a/core/types/derive_sha.go +++ b/core/types/derive_sha.go @@ -1,8 +1,8 @@ package types import ( - "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/trie" ) @@ -11,12 +11,12 @@ type DerivableList interface { GetRlp(i int) []byte } -func DeriveSha(list DerivableList) []byte { +func DeriveSha(list DerivableList) common.Hash { db, _ := ethdb.NewMemDatabase() trie := trie.New(nil, db) for i := 0; i < list.Len(); i++ { trie.Update(common.Encode(i), list.GetRlp(i)) } - return trie.Root() + return common.BytesToHash(trie.Root()) } -- cgit v1.2.3 From 16df850af2d2da0b7082e246d6f05eb1f1dc0706 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 16 Mar 2015 17:43:42 +0100 Subject: core/types: use common.{Hash,Address} in for transactions --- core/types/block.go | 5 ++- core/types/transaction.go | 89 +++++++++++++---------------------------------- 2 files changed, 26 insertions(+), 68 deletions(-) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index 9a97061b7..80fc238aa 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -1,7 +1,6 @@ package types import ( - "bytes" "encoding/binary" "fmt" "math/big" @@ -156,9 +155,9 @@ func (self *Block) Transactions() Transactions { return self.transactions } -func (self *Block) Transaction(hash []byte) *Transaction { +func (self *Block) Transaction(hash common.Hash) *Transaction { for _, transaction := range self.transactions { - if bytes.Equal(hash, transaction.Hash()) { + if transaction.Hash() == hash { return transaction } } diff --git a/core/types/transaction.go b/core/types/transaction.go index dcd48af11..d55c5d5ae 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -2,13 +2,13 @@ package types import ( "bytes" - "crypto/ecdsa" "fmt" "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/secp256k1" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" ) @@ -20,7 +20,7 @@ type Transaction struct { AccountNonce uint64 Price *big.Int GasLimit *big.Int - Recipient []byte + Recipient common.Address Amount *big.Int Payload []byte V byte @@ -28,31 +28,24 @@ type Transaction struct { } func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Transaction { - return NewTransactionMessage(nil, Amount, gasAmount, price, data) + return NewTransactionMessage(common.Address{}, Amount, gasAmount, price, data) } -func NewTransactionMessage(to []byte, Amount, gasAmount, price *big.Int, data []byte) *Transaction { +func NewTransactionMessage(to common.Address, Amount, gasAmount, price *big.Int, data []byte) *Transaction { return &Transaction{Recipient: to, Amount: Amount, Price: price, GasLimit: gasAmount, Payload: data} } func NewTransactionFromBytes(data []byte) *Transaction { - tx := &Transaction{} - tx.RlpDecode(data) - + tx := new(Transaction) + rlp.Decode(bytes.NewReader(data), tx) return tx } -func NewTransactionFromAmount(val *common.Value) *Transaction { - tx := &Transaction{} - tx.RlpValueDecode(val) - - return tx -} - -func (tx *Transaction) Hash() []byte { - data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload} - - return crypto.Sha3(common.Encode(data)) +func (tx *Transaction) Hash() (a common.Hash) { + h := sha3.NewKeccak256() + rlp.Encode(h, []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}) + h.Sum(a[:]) + return a } func (self *Transaction) Data() []byte { @@ -79,11 +72,11 @@ func (self *Transaction) SetNonce(AccountNonce uint64) { self.AccountNonce = AccountNonce } -func (self *Transaction) From() []byte { +func (self *Transaction) From() common.Address { return self.sender() } -func (self *Transaction) To() []byte { +func (self *Transaction) To() common.Address { return self.Recipient } @@ -97,48 +90,31 @@ func (tx *Transaction) Curve() (v byte, r []byte, s []byte) { func (tx *Transaction) Signature(key []byte) []byte { hash := tx.Hash() - - sig, _ := secp256k1.Sign(hash, key) - + sig, _ := secp256k1.Sign(hash[:], key) return sig } func (tx *Transaction) PublicKey() []byte { hash := tx.Hash() - v, r, s := tx.Curve() - sig := append(r, s...) sig = append(sig, v-27) //pubkey := crypto.Ecrecover(append(hash, sig...)) - pubkey, _ := secp256k1.RecoverPubkey(hash, sig) - + pubkey, _ := secp256k1.RecoverPubkey(hash[:], sig) return pubkey } -func (tx *Transaction) sender() []byte { +func (tx *Transaction) sender() (a common.Address) { pubkey := tx.PublicKey() // Validate the returned key. // Return nil if public key isn't in full format if len(pubkey) == 0 || pubkey[0] != 4 { - return nil + return a } - - return crypto.Sha3(pubkey[1:])[12:] -} - -// TODO: deprecate after new accounts & key stores are integrated -func (tx *Transaction) Sign(privk []byte) error { - - sig := tx.Signature(privk) - - tx.R = sig[:32] - tx.S = sig[32:64] - tx.V = sig[64] + 27 - - return nil + copy(a[:], crypto.Sha3(pubkey[1:])) + return a } func (tx *Transaction) SetSignatureValues(sig []byte) error { @@ -148,36 +124,17 @@ func (tx *Transaction) SetSignatureValues(sig []byte) error { return nil } -func (tx *Transaction) SignECDSA(key *ecdsa.PrivateKey) error { - return tx.Sign(crypto.FromECDSA(key)) -} - +// TODO: remove func (tx *Transaction) RlpData() interface{} { data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload} - return append(data, tx.V, new(big.Int).SetBytes(tx.R).Bytes(), new(big.Int).SetBytes(tx.S).Bytes()) } +// TODO: remove func (tx *Transaction) RlpEncode() []byte { return common.Encode(tx) } -func (tx *Transaction) RlpDecode(data []byte) { - rlp.Decode(bytes.NewReader(data), tx) -} - -func (tx *Transaction) RlpValueDecode(decoder *common.Value) { - tx.AccountNonce = decoder.Get(0).Uint() - tx.Price = decoder.Get(1).BigInt() - tx.GasLimit = decoder.Get(2).BigInt() - tx.Recipient = decoder.Get(3).Bytes() - tx.Amount = decoder.Get(4).BigInt() - tx.Payload = decoder.Get(5).Bytes() - tx.V = decoder.Get(6).Byte() - tx.R = decoder.Get(7).Bytes() - tx.S = decoder.Get(8).Bytes() -} - func (tx *Transaction) String() string { return fmt.Sprintf(` TX(%x) @@ -213,6 +170,7 @@ func (tx *Transaction) String() string { // Transaction slice type for basic sorting type Transactions []*Transaction +// TODO: remove func (self Transactions) RlpData() interface{} { // Marshal the transactions of this block enc := make([]interface{}, len(self)) @@ -223,6 +181,7 @@ func (self Transactions) RlpData() interface{} { return enc } + func (s Transactions) Len() int { return len(s) } func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s Transactions) GetRlp(i int) []byte { return common.Rlp(s[i]) } -- cgit v1.2.3 From 91b0b14845750c81466880f5f877fe3fcbd03b09 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Mar 2015 18:42:18 +0100 Subject: converted vm --- core/types/block_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/types/block_test.go b/core/types/block_test.go index e2fa2cad2..16ba3043f 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -1,13 +1,13 @@ package types import ( - "fmt" "math/big" "testing" "github.com/ethereum/go-ethereum/common" ) +// XXX Tests doesn't really do anything. This tests exists while working on the fixed size conversions func TestConversion(t *testing.T) { var ( parent common.Hash @@ -15,6 +15,5 @@ func TestConversion(t *testing.T) { hash common.Hash ) - block := NewBlock(parent, coinbase, hash, big.NewInt(0), 0, "") - fmt.Println(block) + NewBlock(parent, coinbase, hash, big.NewInt(0), 0, "") } -- cgit v1.2.3 From 843db4978e876674ca111706880a58c84202880d Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Mar 2015 23:10:26 +0100 Subject: updated blockpool --- core/types/block.go | 6 +++--- core/types/bloom9.go | 6 +++--- core/types/receipt.go | 36 ++++++++++++++++++------------------ 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index 80fc238aa..aca23aa04 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -106,14 +106,14 @@ func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash, GasUsed: new(big.Int), GasLimit: new(big.Int), } - header.setNonce(nonce) + header.SetNonce(nonce) block := &Block{header: header, Reward: new(big.Int)} return block } -func (self *Header) setNonce(nonce uint64) { +func (self *Header) SetNonce(nonce uint64) { binary.BigEndian.PutUint64(self.Nonce[:], nonce) } @@ -203,7 +203,7 @@ func (self *Block) Nonce() uint64 { return binary.BigEndian.Uint64(self.header.Nonce[:]) } func (self *Block) SetNonce(nonce uint64) { - self.header.setNonce(nonce) + self.header.SetNonce(nonce) } func (self *Block) Bloom() Bloom { return self.header.Bloom } diff --git a/core/types/bloom9.go b/core/types/bloom9.go index e5b5e395f..b3cab86a0 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -20,15 +20,15 @@ func CreateBloom(receipts Receipts) Bloom { func LogsBloom(logs state.Logs) *big.Int { bin := new(big.Int) for _, log := range logs { - data := make([][]byte, len(log.Topics())+1) - data[0] = log.Address() + data := make([]common.Hash, len(log.Topics())+1) + data[0] = log.Address().Hash() for i, topic := range log.Topics() { data[i+1] = topic } for _, b := range data { - bin.Or(bin, common.BigD(bloom9(crypto.Sha3(b)).Bytes())) + bin.Or(bin, common.BigD(bloom9(crypto.Sha3(b[:])).Bytes())) } } diff --git a/core/types/receipt.go b/core/types/receipt.go index be14d0e0e..d0cb41e25 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -3,9 +3,11 @@ package types import ( "bytes" "fmt" + "io" "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/state" ) @@ -20,34 +22,26 @@ func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt { return &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumalativeGasUsed)} } -func NewRecieptFromValue(val *common.Value) *Receipt { - r := &Receipt{} - r.RlpValueDecode(val) - - return r -} - func (self *Receipt) SetLogs(logs state.Logs) { self.logs = logs } -func (self *Receipt) RlpValueDecode(decoder *common.Value) { - self.PostState = decoder.Get(0).Bytes() - self.CumulativeGasUsed = decoder.Get(1).BigInt() - self.Bloom = decoder.Get(2).Bytes() - - it := decoder.Get(3).NewIterator() - for it.Next() { - self.logs = append(self.logs, state.NewLogFromValue(it.Value())) - } +func (self *Receipt) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs}) } +/* func (self *Receipt) RlpData() interface{} { return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()} } +*/ func (self *Receipt) RlpEncode() []byte { - return common.Encode(self.RlpData()) + bytes, err := rlp.EncodeToBytes(self) + if err != nil { + fmt.Println("TMP -- RECEIPT ENCODE ERROR", err) + } + return bytes } func (self *Receipt) Cmp(other *Receipt) bool { @@ -64,6 +58,7 @@ func (self *Receipt) String() string { type Receipts []*Receipt +/* func (self Receipts) RlpData() interface{} { data := make([]interface{}, len(self)) for i, receipt := range self { @@ -72,9 +67,14 @@ func (self Receipts) RlpData() interface{} { return data } +*/ func (self Receipts) RlpEncode() []byte { - return common.Encode(self.RlpData()) + bytes, err := rlp.EncodeToBytes(self) + if err != nil { + fmt.Println("TMP -- RECEIPTS ENCODE ERROR", err) + } + return bytes } func (self Receipts) Len() int { return len(self) } -- cgit v1.2.3 From 94505146a21cc0aee16d79aebc17c8fcb1f91324 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Mar 2015 23:17:28 +0100 Subject: updated vm env --- core/state_transition.go | 6 +++--- core/vm_env.go | 33 +++++++++++++++++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'core') diff --git a/core/state_transition.go b/core/state_transition.go index 279abee62..575bdf026 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -4,8 +4,8 @@ import ( "fmt" "math/big" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) @@ -45,8 +45,8 @@ type StateTransition struct { } type Message interface { - From() []byte - To() []byte + From() common.Address + To() common.Address GasPrice() *big.Int Gas() *big.Int diff --git a/core/vm_env.go b/core/vm_env.go index c7491bcdc..7a921d7e3 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -3,6 +3,7 @@ package core import ( "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" @@ -27,18 +28,18 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types } } -func (self *VMEnv) Origin() []byte { return self.msg.From() } -func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } -func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } -func (self *VMEnv) Time() int64 { return self.block.Time() } -func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } -func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } -func (self *VMEnv) Value() *big.Int { return self.msg.Value() } -func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) Depth() int { return self.depth } -func (self *VMEnv) SetDepth(i int) { self.depth = i } -func (self *VMEnv) VmType() vm.Type { return self.typ } -func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t } +func (self *VMEnv) Origin() common.Address { return self.msg.From() } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } +func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } +func (self *VMEnv) Time() int64 { return self.block.Time() } +func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } +func (self *VMEnv) Value() *big.Int { return self.msg.Value() } +func (self *VMEnv) State() *state.StateDB { return self.state } +func (self *VMEnv) Depth() int { return self.depth } +func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) VmType() vm.Type { return self.typ } +func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t } func (self *VMEnv) GetHash(n uint64) []byte { if block := self.chain.GetBlockByNumber(n); block != nil { return block.Hash() @@ -57,16 +58,16 @@ func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *Execution return NewExecution(self, addr, data, gas, price, value) } -func (self *VMEnv) Call(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) Call(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(addr, data, gas, price, value) return exe.Call(addr, me) } -func (self *VMEnv) CallCode(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(me.Address(), data, gas, price, value) return exe.Call(addr, me) } -func (self *VMEnv) Create(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { - exe := self.vm(addr, data, gas, price, value) +func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { + exe := self.vm(common.Address{}, data, gas, price, value) return exe.Create(me) } -- cgit v1.2.3 From 8ce6a3647821706cf5e9bb1a9dc13f23c84f6585 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Mar 2015 23:48:18 +0100 Subject: converted chain manager --- core/block_processor.go | 38 ++++++++++++++++++-------------------- core/chain_makers.go | 10 +++++----- core/chain_manager.go | 48 +++++++++++++++++++++++++++--------------------- core/error.go | 6 ++++-- core/types/receipt.go | 2 +- 5 files changed, 55 insertions(+), 49 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index f67d6d006..fd4009037 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -1,14 +1,13 @@ package core import ( - "bytes" "fmt" "math/big" "sync" "time" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/pow" @@ -90,7 +89,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated statedb.Update(nil) cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas)) - receipt := types.NewReceipt(statedb.Root(), cumulative) + receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative) receipt.SetLogs(statedb.Logs()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) chainlogger.Debugln(receipt) @@ -190,7 +189,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big // Validate the received block's bloom with the one derived from the generated receipts. // For valid blocks this should always validate to true. rbloom := types.CreateBloom(receipts) - if bytes.Compare(rbloom, header.Bloom) != 0 { + if rbloom != header.Bloom { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return } @@ -198,14 +197,14 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big // The transactions Trie's root (R = (Tr [[H1, T1], [H2, T2], ... [Hn, Tn]])) // can be used by light clients to make sure they've received the correct Txs txSha := types.DeriveSha(block.Transactions()) - if bytes.Compare(txSha, header.TxHash) != 0 { + if txSha != header.TxHash { err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha) return } // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]])) receiptSha := types.DeriveSha(receipts) - if bytes.Compare(receiptSha, header.ReceiptHash) != 0 { + if receiptSha != header.ReceiptHash { err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha) return } @@ -218,7 +217,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. state.Update(common.Big0) - if !bytes.Equal(header.Root, state.Root()) { + if header.Root != state.Root() { err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return } @@ -234,7 +233,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big putTx(sm.extraDb, tx) } - chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash()[0:4]) + chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash().Bytes()[0:4]) return td, nil } @@ -284,35 +283,34 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren ancestors := set.New() uncles := set.New() - ancestorHeaders := make(map[string]*types.Header) + ancestorHeaders := make(map[common.Hash]*types.Header) for _, ancestor := range sm.bc.GetAncestors(block, 7) { - hash := string(ancestor.Hash()) - ancestorHeaders[hash] = ancestor.Header() - ancestors.Add(hash) + ancestorHeaders[ancestor.Hash()] = ancestor.Header() + ancestors.Add(ancestor.Hash()) // Include ancestors uncles in the uncle set. Uncles must be unique. for _, uncle := range ancestor.Uncles() { - uncles.Add(string(uncle.Hash())) + uncles.Add(uncle.Hash()) } } - uncles.Add(string(block.Hash())) + uncles.Add(block.Hash()) for _, uncle := range block.Uncles() { - if uncles.Has(string(uncle.Hash())) { + if uncles.Has(uncle.Hash()) { // Error not unique return UncleError("Uncle not unique") } - uncles.Add(string(uncle.Hash())) + uncles.Add(uncle.Hash()) - if ancestors.Has(string(uncle.Hash())) { + if ancestors.Has(uncle.Hash()) { return UncleError("Uncle is ancestor") } - if !ancestors.Has(string(uncle.ParentHash)) { + if !ancestors.Has(uncle.ParentHash) { return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } - if err := sm.ValidateHeader(uncle, ancestorHeaders[string(uncle.ParentHash)]); err != nil { + if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash]); err != nil { return ValidationError(fmt.Sprintf("%v", err)) } @@ -358,5 +356,5 @@ func putTx(db common.Database, tx *types.Transaction) { statelogger.Infoln("Failed encoding tx", err) return } - db.Put(tx.Hash(), rlpEnc) + db.Put(tx.Hash().Bytes(), rlpEnc) } diff --git a/core/chain_makers.go b/core/chain_makers.go index 59c297dbe..857af960c 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -4,8 +4,8 @@ import ( "fmt" "math/big" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/state" @@ -29,7 +29,7 @@ var ( // Utility functions for making chains on the fly // Exposed for sake of testing from other packages (eg. go-ethash) -func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block { +func NewBlockFromParent(addr common.Address, parent *types.Block) *types.Block { return newBlockFromParent(addr, parent) } @@ -54,7 +54,7 @@ func NewCanonical(n int, db common.Database) (*BlockProcessor, error) { } // block time is fixed at 10 seconds -func newBlockFromParent(addr []byte, parent *types.Block) *types.Block { +func newBlockFromParent(addr common.Address, parent *types.Block) *types.Block { block := types.NewBlock(parent.Hash(), addr, parent.Root(), common.BigPow(2, 32), 0, "") block.SetUncles(nil) block.SetTransactions(nil) @@ -74,8 +74,8 @@ func newBlockFromParent(addr []byte, parent *types.Block) *types.Block { // Actually make a block by simulating what miner would do // we seed chains by the first byte of the coinbase func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Database, seed int) *types.Block { - addr := common.LeftPadBytes([]byte{byte(i)}, 20) - addr[0] = byte(seed) + var addr common.Address + addr[0], addr[19] = byte(seed), byte(i) block := newBlockFromParent(addr, parent) state := state.New(block.Root(), db) cbase := state.GetOrNewStateObject(addr) diff --git a/core/chain_manager.go b/core/chain_manager.go index ff91b0427..5316a3423 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -6,8 +6,8 @@ import ( "math/big" "sync" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/rlp" @@ -86,7 +86,7 @@ type ChainManager struct { tsmu sync.RWMutex td *big.Int currentBlock *types.Block - lastBlockHash []byte + lastBlockHash common.Hash transState *state.StateDB txState *state.ManagedState @@ -112,7 +112,7 @@ func (self *ChainManager) Td() *big.Int { return self.td } -func (self *ChainManager) LastBlockHash() []byte { +func (self *ChainManager) LastBlockHash() common.Hash { self.mu.RLock() defer self.mu.RUnlock() @@ -126,7 +126,7 @@ func (self *ChainManager) CurrentBlock() *types.Block { return self.currentBlock } -func (self *ChainManager) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) { +func (self *ChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) { self.mu.RLock() defer self.mu.RUnlock() @@ -168,7 +168,7 @@ func (self *ChainManager) setTransState(statedb *state.StateDB) { func (bc *ChainManager) setLastBlock() { data, _ := bc.blockDb.Get([]byte("LastBlock")) if len(data) != 0 { - block := bc.GetBlock(data) + block := bc.GetBlock(common.BytesToHash(data)) bc.currentBlock = block bc.lastBlockHash = block.Hash() @@ -182,12 +182,14 @@ func (bc *ChainManager) setLastBlock() { } // Block creation & chain handling -func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { +func (bc *ChainManager) NewBlock(coinbase common.Address) *types.Block { bc.mu.RLock() defer bc.mu.RUnlock() - var root []byte - parentHash := ZeroHash256 + var ( + root common.Hash + parentHash common.Hash + ) if bc.currentBlock != nil { root = bc.currentBlock.Header().Root @@ -234,7 +236,7 @@ func (bc *ChainManager) Reset() { } func (bc *ChainManager) removeBlock(block *types.Block) { - bc.blockDb.Delete(append(blockHashPre, block.Hash()...)) + bc.blockDb.Delete(append(blockHashPre, block.Hash().Bytes()...)) } func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) { @@ -268,18 +270,18 @@ func (self *ChainManager) Export() []byte { func (bc *ChainManager) insert(block *types.Block) { //encodedBlock := common.Encode(block) - bc.blockDb.Put([]byte("LastBlock"), block.Hash()) + bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes()) bc.currentBlock = block bc.lastBlockHash = block.Hash() key := append(blockNumPre, block.Number().Bytes()...) - bc.blockDb.Put(key, bc.lastBlockHash) + bc.blockDb.Put(key, bc.lastBlockHash.Bytes()) } func (bc *ChainManager) write(block *types.Block) { encodedBlock := common.Encode(block.RlpDataForStorage()) - key := append(blockHashPre, block.Hash()...) + key := append(blockHashPre, block.Hash().Bytes()...) bc.blockDb.Put(key, encodedBlock) } @@ -289,12 +291,12 @@ func (bc *ChainManager) Genesis() *types.Block { } // Block fetching methods -func (bc *ChainManager) HasBlock(hash []byte) bool { - data, _ := bc.blockDb.Get(append(blockHashPre, hash...)) +func (bc *ChainManager) HasBlock(hash common.Hash) bool { + data, _ := bc.blockDb.Get(append(blockHashPre, hash[:]...)) return len(data) != 0 } -func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain [][]byte) { +func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (chain []common.Hash) { block := self.GetBlock(hash) if block == nil { return @@ -317,8 +319,8 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain return } -func (self *ChainManager) GetBlock(hash []byte) *types.Block { - data, _ := self.blockDb.Get(append(blockHashPre, hash...)) +func (self *ChainManager) GetBlock(hash common.Hash) *types.Block { + data, _ := self.blockDb.Get(append(blockHashPre, hash[:]...)) if len(data) == 0 { return nil } @@ -340,7 +342,7 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { return nil } - return self.GetBlock(key) + return self.GetBlock(common.BytesToHash(key)) } func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) { @@ -418,7 +420,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { } h := block.Header() - chainlogger.Infof("INVALID block #%v (%x)\n", h.Number, h.Hash()[:4]) + chainlogger.Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes()[:4]) chainlogger.Infoln(err) chainlogger.Debugln(block) return err @@ -435,7 +437,9 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { // At this point it's possible that a different chain (fork) becomes the new canonical chain. if td.Cmp(self.td) > 0 { if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, common.Big1)) < 0 { - chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td) + chash := cblock.Hash() + hash := block.Hash() + chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, hash[:4], td, cblock.Header().Number, chash[:4], self.td) queue[i] = ChainSplitEvent{block} queueEvent.splitCount++ @@ -507,7 +511,9 @@ out: } } +/* // Satisfy state query interface -func (self *ChainManager) GetAccount(addr []byte) *state.StateObject { +func (self *ChainManager) GetAccount(addr common.Hash) *state.StateObject { return self.State().GetAccount(addr) } +*/ diff --git a/core/error.go b/core/error.go index 69e320eb0..f6ac26cff 100644 --- a/core/error.go +++ b/core/error.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "math/big" + + "github.com/ethereum/go-ethereum/common" ) var ( @@ -21,7 +23,7 @@ func (err *ParentErr) Error() string { return err.Message } -func ParentError(hash []byte) error { +func ParentError(hash common.Hash) error { return &ParentErr{Message: fmt.Sprintf("Block's parent unknown %x", hash)} } @@ -136,7 +138,7 @@ func IsTDError(e error) bool { type KnownBlockError struct { number *big.Int - hash []byte + hash common.Hash } func (self *KnownBlockError) Error() string { diff --git a/core/types/receipt.go b/core/types/receipt.go index d0cb41e25..f88d42b29 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -14,7 +14,7 @@ import ( type Receipt struct { PostState []byte CumulativeGasUsed *big.Int - Bloom []byte + Bloom Bloom logs state.Logs } -- cgit v1.2.3 From d5de6489d7275374a3bb269b07780d6c13b6c3b7 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 17 Mar 2015 01:34:18 +0100 Subject: core/types: fix Transaction.Hash and add support for encoding with package rlp --- core/types/transaction.go | 25 ++++++++++++++----- core/types/transaction_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 6 deletions(-) (limited to 'core') diff --git a/core/types/transaction.go b/core/types/transaction.go index d55c5d5ae..7f1447ef8 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -3,6 +3,7 @@ package types import ( "bytes" "fmt" + "io" "math/big" "github.com/ethereum/go-ethereum/common" @@ -27,12 +28,12 @@ type Transaction struct { R, S []byte } -func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Transaction { - return NewTransactionMessage(common.Address{}, Amount, gasAmount, price, data) +func NewContractCreationTx(amount, gasAmount, price *big.Int, data []byte) *Transaction { + return NewTransactionMessage(common.Address{}, amount, gasAmount, price, data) } -func NewTransactionMessage(to common.Address, Amount, gasAmount, price *big.Int, data []byte) *Transaction { - return &Transaction{Recipient: to, Amount: Amount, Price: price, GasLimit: gasAmount, Payload: data} +func NewTransactionMessage(to common.Address, amount, gasAmount, price *big.Int, data []byte) *Transaction { + return &Transaction{Recipient: to, Amount: amount, Price: price, GasLimit: gasAmount, Payload: data} } func NewTransactionFromBytes(data []byte) *Transaction { @@ -44,7 +45,7 @@ func NewTransactionFromBytes(data []byte) *Transaction { func (tx *Transaction) Hash() (a common.Hash) { h := sha3.NewKeccak256() rlp.Encode(h, []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}) - h.Sum(a[:]) + h.Sum(a[:0]) return a } @@ -84,7 +85,6 @@ func (tx *Transaction) Curve() (v byte, r []byte, s []byte) { v = byte(tx.V) r = common.LeftPadBytes(tx.R, 32) s = common.LeftPadBytes(tx.S, 32) - return } @@ -124,6 +124,19 @@ func (tx *Transaction) SetSignatureValues(sig []byte) error { return nil } +func (tx Transaction) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, []interface{}{ + tx.AccountNonce, + tx.Price, tx.GasLimit, + tx.Recipient, + tx.Amount, + tx.Payload, + tx.V, + tx.R, + tx.S, + }) +} + // TODO: remove func (tx *Transaction) RlpData() interface{} { data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload} diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index ab1254f4c..1af59436e 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -1 +1,57 @@ package types + +import ( + "bytes" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" +) + +// The values in those tests are from the Transaction Tests +// at github.com/ethereum/tests. + +var ( + emptyTx = NewTransactionMessage( + common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), + big.NewInt(0), big.NewInt(0), big.NewInt(0), + nil, + ) + + rightvrsTx = &Transaction{ + Recipient: common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), + AccountNonce: 3, + Price: big.NewInt(1), + GasLimit: big.NewInt(2000), + Amount: big.NewInt(10), + Payload: common.FromHex("5544"), + V: 28, + R: common.FromHex("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a"), + S: common.FromHex("8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"), + } +) + +func TestTransactionHash(t *testing.T) { + // "EmptyTransaction" + if emptyTx.Hash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") { + t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash()) + } + + // "RightVRSTest" + if rightvrsTx.Hash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") { + t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash()) + } +} + +func TestTransactionEncode(t *testing.T) { + // "RightVRSTest" + txb, err := rlp.EncodeToBytes(rightvrsTx) + if err != nil { + t.Fatalf("encode error: %v", err) + } + should := common.FromHex("f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3") + if !bytes.Equal(txb, should) { + t.Errorf("encoded RLP mismatch, got %x", txb) + } +} -- cgit v1.2.3 From 515d9432fcef8c574627049d437d6898b56c2829 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Mar 2015 11:19:23 +0100 Subject: converted vm --- core/execution.go | 27 +++++++++++++-------------- core/filter.go | 24 ++++++++++++------------ core/genesis.go | 7 +++---- core/state_transition.go | 22 +++++++++++++--------- core/types/bloom9.go | 6 +++--- core/types/common.go | 10 +++++++++- core/vm_env.go | 37 +++++++++++++++++++------------------ 7 files changed, 72 insertions(+), 61 deletions(-) (limited to 'core') diff --git a/core/execution.go b/core/execution.go index be45eeeb4..4f15fb42a 100644 --- a/core/execution.go +++ b/core/execution.go @@ -4,6 +4,7 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" @@ -11,26 +12,23 @@ import ( type Execution struct { env vm.Environment - address, input []byte + address *common.Address + input []byte Gas, price, value *big.Int } -func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution { +func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution { return &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value} } -func (self *Execution) Addr() []byte { - return self.address -} - -func (self *Execution) Call(codeAddr []byte, caller vm.ContextRef) ([]byte, error) { +func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]byte, error) { // Retrieve the executing code code := self.env.State().GetCode(codeAddr) - return self.exec(code, codeAddr, caller) + return self.exec(&codeAddr, code, caller) } -func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) { +func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) { env := self.env evm := vm.NewVm(env) if env.Depth() == vm.MaxCallDepth { @@ -40,14 +38,15 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret } vsnapshot := env.State().Copy() - if len(self.address) == 0 { + if self.address == nil { // Generate a new address nonce := env.State().GetNonce(caller.Address()) - self.address = crypto.CreateAddress(caller.Address(), nonce) + addr := crypto.CreateAddress(caller.Address(), nonce) + self.address = &addr env.State().SetNonce(caller.Address(), nonce+1) } - from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(self.address) + from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(*self.address) err = env.Transfer(from, to, self.value) if err != nil { env.State().Set(vsnapshot) @@ -73,8 +72,8 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret } func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) { - ret, err = self.exec(self.input, nil, caller) - account = self.env.State().GetStateObject(self.address) + ret, err = self.exec(nil, self.input, caller) + account = self.env.State().GetStateObject(*self.address) return } diff --git a/core/filter.go b/core/filter.go index d58aa8d7c..e08aac120 100644 --- a/core/filter.go +++ b/core/filter.go @@ -1,9 +1,9 @@ package core import ( - "bytes" "math" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/state" ) @@ -16,8 +16,8 @@ type FilterOptions struct { Earliest int64 Latest int64 - Address [][]byte - Topics [][][]byte + Address []common.Address + Topics [][]common.Hash Skip int Max int @@ -29,9 +29,9 @@ type Filter struct { earliest int64 latest int64 skip int - address [][]byte + address []common.Address max int - topics [][][]byte + topics [][]common.Hash BlockCallback func(*types.Block) PendingCallback func(*types.Block) @@ -67,11 +67,11 @@ func (self *Filter) SetLatestBlock(latest int64) { self.latest = latest } -func (self *Filter) SetAddress(addr [][]byte) { +func (self *Filter) SetAddress(addr []common.Address) { self.address = addr } -func (self *Filter) SetTopics(topics [][][]byte) { +func (self *Filter) SetTopics(topics [][]common.Hash) { self.topics = topics } @@ -131,9 +131,9 @@ func (self *Filter) Find() state.Logs { return logs[skip:] } -func includes(addresses [][]byte, a []byte) bool { +func includes(addresses []common.Address, a common.Address) bool { for _, addr := range addresses { - if !bytes.Equal(addr, a) { + if addr != a { return false } } @@ -151,13 +151,13 @@ Logs: continue } - logTopics := make([][]byte, len(self.topics)) + logTopics := make([]common.Hash, len(self.topics)) copy(logTopics, log.Topics()) for i, topics := range self.topics { for _, topic := range topics { var match bool - if bytes.Equal(log.Topics()[i], topic) { + if log.Topics()[i] == topic { match = true } if !match { @@ -176,7 +176,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { if len(self.address) > 0 { var included bool for _, addr := range self.address { - if types.BloomLookup(block.Bloom(), addr) { + if types.BloomLookup(block.Bloom(), addr.Hash()) { included = true break } diff --git a/core/genesis.go b/core/genesis.go index bfd51f196..70845b502 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -6,9 +6,9 @@ import ( "math/big" "os" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/state" ) @@ -26,12 +26,11 @@ var GenesisDiff = big.NewInt(131072) var GenesisGasLimit = big.NewInt(3141592) func GenesisBlock(db common.Database) *types.Block { - genesis := types.NewBlock(ZeroHash256, ZeroHash160, nil, GenesisDiff, 42, "") + genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, GenesisDiff, 42, "") genesis.Header().Number = common.Big0 genesis.Header().GasLimit = GenesisGasLimit genesis.Header().GasUsed = common.Big0 genesis.Header().Time = 0 - genesis.Header().MixDigest = make([]byte, 32) genesis.Td = common.Big0 @@ -49,7 +48,7 @@ func GenesisBlock(db common.Database) *types.Block { statedb := state.New(genesis.Root(), db) for addr, account := range accounts { codedAddr := common.Hex2Bytes(addr) - accountState := statedb.GetAccount(codedAddr) + accountState := statedb.GetAccount(common.BytesToAddress(codedAddr)) accountState.SetBalance(common.Big(account.Balance)) statedb.UpdateStateObject(accountState) } diff --git a/core/state_transition.go b/core/state_transition.go index 575bdf026..ce9835751 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -31,7 +31,7 @@ var () * 6) Derive new state root */ type StateTransition struct { - coinbase []byte + coinbase common.Address msg Message gas, gasPrice *big.Int initialGas *big.Int @@ -119,7 +119,7 @@ func (self *StateTransition) BuyGas() error { sender := self.From() if sender.Balance().Cmp(MessageGasValue(self.msg)) < 0 { - return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address()[:4], MessageGasValue(self.msg), sender.Balance()) + return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], MessageGasValue(self.msg), sender.Balance()) } coinbase := self.Coinbase() @@ -195,8 +195,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er vmenv := self.env var ref vm.ContextRef if MessageCreatesContract(msg) { - contract := makeContract(msg, self.state) - ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + //contract := makeContract(msg, self.state) + //addr := contract.Address() + ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value) if err == nil { dataGas := big.NewInt(int64(len(ret))) dataGas.Mul(dataGas, vm.GasCreateByte) @@ -230,7 +231,7 @@ func (self *StateTransition) refundGas() { for addr, ref := range self.state.Refunds() { refund := common.BigMin(uhalf, ref) self.gas.Add(self.gas, refund) - self.state.AddBalance([]byte(addr), refund.Mul(refund, self.msg.GasPrice())) + self.state.AddBalance(common.StringToAddress(addr), refund.Mul(refund, self.msg.GasPrice())) } coinbase.RefundGas(self.gas, self.msg.GasPrice()) @@ -242,10 +243,13 @@ func (self *StateTransition) gasUsed() *big.Int { // Converts an message in to a state object func makeContract(msg Message, state *state.StateDB) *state.StateObject { - addr := AddressFromMessage(msg) + /* + addr := AddressFromMessage(msg) - contract := state.GetOrNewStateObject(addr) - contract.SetInitCode(msg.Data()) + contract := state.GetOrNewStateObject(addr) + contract.SetInitCode(msg.Data()) - return contract + return contract + */ + return nil } diff --git a/core/types/bloom9.go b/core/types/bloom9.go index b3cab86a0..55bfe2756 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -47,9 +47,9 @@ func bloom9(b []byte) *big.Int { return r } -func BloomLookup(bin, topic []byte) bool { - bloom := common.BigD(bin) - cmp := bloom9(crypto.Sha3(topic)) +func BloomLookup(bin Bloom, topic common.Hash) bool { + bloom := bin.Big() + cmp := bloom9(crypto.Sha3(topic[:])) return bloom.And(bloom, cmp).Cmp(cmp) == 0 } diff --git a/core/types/common.go b/core/types/common.go index dd5dc00c8..6c5ac06b1 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -1,6 +1,10 @@ package types -import "math/big" +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) type BlockProcessor interface { Process(*Block) (*big.Int, error) @@ -24,3 +28,7 @@ func (b *Bloom) SetBytes(d []byte) { b[i] = b[i] } } + +func (b Bloom) Big() *big.Int { + return common.Bytes2Big(b[:]) +} diff --git a/core/vm_env.go b/core/vm_env.go index 7a921d7e3..fb4253f5b 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -28,24 +28,24 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types } } -func (self *VMEnv) Origin() common.Address { return self.msg.From() } -func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } -func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } -func (self *VMEnv) Time() int64 { return self.block.Time() } -func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } -func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } -func (self *VMEnv) Value() *big.Int { return self.msg.Value() } -func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) Depth() int { return self.depth } -func (self *VMEnv) SetDepth(i int) { self.depth = i } -func (self *VMEnv) VmType() vm.Type { return self.typ } -func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t } -func (self *VMEnv) GetHash(n uint64) []byte { +func (self *VMEnv) Origin() common.Address { return self.msg.From() } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } +func (self *VMEnv) Coinbase() common.Address { return self.block.Coinbase() } +func (self *VMEnv) Time() int64 { return self.block.Time() } +func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } +func (self *VMEnv) Value() *big.Int { return self.msg.Value() } +func (self *VMEnv) State() *state.StateDB { return self.state } +func (self *VMEnv) Depth() int { return self.depth } +func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) VmType() vm.Type { return self.typ } +func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t } +func (self *VMEnv) GetHash(n uint64) common.Hash { if block := self.chain.GetBlockByNumber(n); block != nil { return block.Hash() } - return nil + return common.Hash{} } func (self *VMEnv) AddLog(log state.Log) { self.state.AddLog(log) @@ -54,20 +54,21 @@ func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error { return vm.Transfer(from, to, amount) } -func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *Execution { +func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *Execution { return NewExecution(self, addr, data, gas, price, value) } func (self *VMEnv) Call(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - exe := self.vm(addr, data, gas, price, value) + exe := self.vm(&addr, data, gas, price, value) return exe.Call(addr, me) } func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - exe := self.vm(me.Address(), data, gas, price, value) + maddr := me.Address() + exe := self.vm(&maddr, data, gas, price, value) return exe.Call(addr, me) } func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { - exe := self.vm(common.Address{}, data, gas, price, value) + exe := self.vm(nil, data, gas, price, value) return exe.Create(me) } -- cgit v1.2.3 From e91ab84dbe4ef87b2f182b88e5b252b5d414df28 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 17 Mar 2015 11:58:31 +0100 Subject: core/types: don't use Address zero value for invalid addresses --- core/types/transaction.go | 59 ++++++++++++++++++++++++------------------ core/types/transaction_test.go | 5 ++-- 2 files changed, 37 insertions(+), 27 deletions(-) (limited to 'core') diff --git a/core/types/transaction.go b/core/types/transaction.go index 7f1447ef8..24035a3ae 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "errors" "fmt" "io" "math/big" @@ -21,19 +22,19 @@ type Transaction struct { AccountNonce uint64 Price *big.Int GasLimit *big.Int - Recipient common.Address + Recipient *common.Address // nil means contract creation Amount *big.Int Payload []byte V byte R, S []byte } -func NewContractCreationTx(amount, gasAmount, price *big.Int, data []byte) *Transaction { - return NewTransactionMessage(common.Address{}, amount, gasAmount, price, data) +func NewContractCreationTx(amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { + return &Transaction{Recipient: nil, Amount: amount, GasLimit: gasLimit, Price: gasPrice, Payload: data} } -func NewTransactionMessage(to common.Address, amount, gasAmount, price *big.Int, data []byte) *Transaction { - return &Transaction{Recipient: to, Amount: amount, Price: price, GasLimit: gasAmount, Payload: data} +func NewTransactionMessage(to common.Address, amount, gasAmount, gasPrice *big.Int, data []byte) *Transaction { + return &Transaction{Recipient: &to, Amount: amount, GasLimit: gasAmount, Price: gasPrice, Payload: data} } func NewTransactionFromBytes(data []byte) *Transaction { @@ -73,12 +74,21 @@ func (self *Transaction) SetNonce(AccountNonce uint64) { self.AccountNonce = AccountNonce } -func (self *Transaction) From() common.Address { - return self.sender() +func (self *Transaction) From() (common.Address, error) { + pubkey := self.PublicKey() + if len(pubkey) == 0 || pubkey[0] != 4 { + return common.Address{}, errors.New("invalid public key") + } + var addr common.Address + copy(addr[:], crypto.Sha3(pubkey[1:])) + return addr, nil } -func (self *Transaction) To() common.Address { - return self.Recipient +// To returns the recipient of the transaction. +// If transaction is a contract creation (with no recipient address) +// To returns nil. +func (tx *Transaction) To() *common.Address { + return tx.Recipient } func (tx *Transaction) Curve() (v byte, r []byte, s []byte) { @@ -105,18 +115,6 @@ func (tx *Transaction) PublicKey() []byte { return pubkey } -func (tx *Transaction) sender() (a common.Address) { - pubkey := tx.PublicKey() - - // Validate the returned key. - // Return nil if public key isn't in full format - if len(pubkey) == 0 || pubkey[0] != 4 { - return a - } - copy(a[:], crypto.Sha3(pubkey[1:])) - return a -} - func (tx *Transaction) SetSignatureValues(sig []byte) error { tx.R = sig[:32] tx.S = sig[32:64] @@ -149,11 +147,22 @@ func (tx *Transaction) RlpEncode() []byte { } func (tx *Transaction) String() string { + var from, to string + if f, err := tx.From(); err != nil { + from = "[invalid sender]" + } else { + from = fmt.Sprintf("%x", f[:]) + } + if t := tx.To(); t == nil { + to = "[contract creation]" + } else { + to = fmt.Sprintf("%x", t[:]) + } return fmt.Sprintf(` TX(%x) Contract: %v - From: %x - To: %x + From: %s + To: %s Nonce: %v GasPrice: %v GasLimit %v @@ -166,8 +175,8 @@ func (tx *Transaction) String() string { `, tx.Hash(), len(tx.Recipient) == 0, - tx.From(), - tx.To(), + from, + to, tx.AccountNonce, tx.Price, tx.GasLimit, diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 1af59436e..0b0dfe3ff 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -19,8 +19,9 @@ var ( nil, ) - rightvrsTx = &Transaction{ - Recipient: common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), + rightvrsRecipient = common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b") + rightvrsTx = &Transaction{ + Recipient: &rightvrsRecipient, AccountNonce: 3, Price: big.NewInt(1), GasLimit: big.NewInt(2000), -- cgit v1.2.3 From b95387a0dc0da6198549689e6b03d21a221e813b Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 17 Mar 2015 11:59:26 +0100 Subject: core: convert transaction pool to common.{Address,Hash} --- core/transaction_pool.go | 54 +++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) (limited to 'core') diff --git a/core/transaction_pool.go b/core/transaction_pool.go index 515cc2040..2efc0511c 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -5,8 +5,8 @@ import ( "fmt" "sync" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" ) @@ -20,9 +20,7 @@ var ( const txPoolQueueSize = 50 type TxPoolHook chan *types.Transaction -type TxMsg struct { - Tx *types.Transaction -} +type TxMsg struct{ Tx *types.Transaction } const ( minGasPrice = 1000000 @@ -44,7 +42,7 @@ type TxPool struct { quit chan bool // The actual pool //pool *list.List - txs map[string]*types.Transaction + txs map[common.Hash]*types.Transaction SecondaryProcessor TxProcessor @@ -55,7 +53,7 @@ type TxPool struct { func NewTxPool(eventMux *event.TypeMux) *TxPool { return &TxPool{ - txs: make(map[string]*types.Transaction), + txs: make(map[common.Hash]*types.Transaction), queueChan: make(chan *types.Transaction, txPoolQueueSize), quit: make(chan bool), eventMux: eventMux, @@ -63,21 +61,16 @@ func NewTxPool(eventMux *event.TypeMux) *TxPool { } func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { - if len(tx.To()) != 0 && len(tx.To()) != 20 { - return fmt.Errorf("Invalid recipient. len = %d", len(tx.To())) + // Validate sender + if _, err := tx.From(); err != nil { + return err } - // Validate curve param v, _, _ := tx.Curve() if v > 28 || v < 27 { return fmt.Errorf("tx.v != (28 || 27) => %v", v) } - - // Validate sender address - senderAddr := tx.From() - if senderAddr == nil || len(senderAddr) != 20 { - return ErrInvalidSender - } + return nil /* XXX this kind of validation needs to happen elsewhere in the gui when sending txs. Other clients should do their own validation. Value transfer could throw error @@ -91,19 +84,16 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From()) } */ - - return nil } func (self *TxPool) addTx(tx *types.Transaction) { - self.txs[string(tx.Hash())] = tx + self.txs[tx.Hash()] = tx } func (self *TxPool) add(tx *types.Transaction) error { - if self.txs[string(tx.Hash())] != nil { + if self.txs[tx.Hash()] != nil { return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4]) } - err := self.ValidateTransaction(tx) if err != nil { return err @@ -111,18 +101,16 @@ func (self *TxPool) add(tx *types.Transaction) error { self.addTx(tx) - var to string - if len(tx.To()) > 0 { - to = common.Bytes2Hex(tx.To()[:4]) + var toname string + if to, valid := tx.To(); valid { + toname = common.Bytes2Hex(to[:4]) } else { - to = "[NEW_CONTRACT]" - } - var from string - if len(tx.From()) > 0 { - from = common.Bytes2Hex(tx.From()[:4]) - } else { - return errors.New(fmt.Sprintf("FROM ADDRESS MUST BE POSITIVE (was %v)", tx.From())) + toname = "[NEW_CONTRACT]" } + // we can ignore the error here because From is + // verified in ValidateTransaction. + f, _ := tx.From() + from := common.Bytes2Hex(f[:4]) txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash()) // Notify the subscribers @@ -140,6 +128,7 @@ func (self *TxPool) Add(tx *types.Transaction) error { defer self.mu.Unlock() return self.add(tx) } + func (self *TxPool) AddTransactions(txs []*types.Transaction) { self.mu.Lock() defer self.mu.Unlock() @@ -186,14 +175,13 @@ func (pool *TxPool) RemoveInvalid(query StateQuery) { func (self *TxPool) RemoveSet(txs types.Transactions) { self.mu.Lock() defer self.mu.Unlock() - for _, tx := range txs { - delete(self.txs, string(tx.Hash())) + delete(self.txs, tx.Hash()) } } func (pool *TxPool) Flush() { - pool.txs = make(map[string]*types.Transaction) + pool.txs = make(map[common.Hash]*types.Transaction) } func (pool *TxPool) Start() { -- cgit v1.2.3 From 27f7aa01639696f4afa4233e0a301afafdd7b950 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 17 Mar 2015 12:00:29 +0100 Subject: core: adapt Message for new Transaction.From signature --- core/block_processor.go | 3 ++- core/state_transition.go | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index fd4009037..b12f88c47 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -81,7 +81,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb) if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { // If the account is managed, remove the invalid nonce. - self.bc.TxState().RemoveNonce(tx.From(), tx.Nonce()) + from, _ := tx.From() + self.bc.TxState().RemoveNonce(from, tx.Nonce()) return nil, nil, err } diff --git a/core/state_transition.go b/core/state_transition.go index 575bdf026..ef822e86c 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -44,9 +44,10 @@ type StateTransition struct { env vm.Environment } +// Message represents a message sent to a contract. type Message interface { - From() common.Address - To() common.Address + From() (common.Address, error) + To() *common.Address GasPrice() *big.Int Gas() *big.Int -- cgit v1.2.3 From 17c5ba2b6bfaaeab423f96523b9da13a8fb3febd Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 17 Mar 2015 12:16:21 +0100 Subject: core: actually convert transaction pool --- core/state_transition.go | 19 +++++++++---------- core/transaction_pool.go | 15 +++++++++------ core/vm_env.go | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) (limited to 'core') diff --git a/core/state_transition.go b/core/state_transition.go index 29de501b0..72999de7e 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -5,7 +5,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) @@ -57,13 +56,8 @@ type Message interface { Data() []byte } -func AddressFromMessage(msg Message) []byte { - // Generate a new address - return crypto.Sha3(common.NewValue([]interface{}{msg.From(), msg.Nonce()}).Encode())[12:] -} - func MessageCreatesContract(msg Message) bool { - return len(msg.To()) == 0 + return msg.To() == nil } func MessageGasValue(msg Message) *big.Int { @@ -93,13 +87,18 @@ func (self *StateTransition) Coinbase() *state.StateObject { return self.state.GetOrNewStateObject(self.coinbase) } func (self *StateTransition) From() *state.StateObject { - return self.state.GetOrNewStateObject(self.msg.From()) + f, _ := self.msg.From() + return self.state.GetOrNewStateObject(f) } func (self *StateTransition) To() *state.StateObject { - if self.msg != nil && MessageCreatesContract(self.msg) { + if self.msg == nil { return nil } - return self.state.GetOrNewStateObject(self.msg.To()) + to := self.msg.To() + if to == nil { + return nil // contract creation + } + return self.state.GetOrNewStateObject(*to) } func (self *StateTransition) UseGas(amount *big.Int) error { diff --git a/core/transaction_pool.go b/core/transaction_pool.go index 2efc0511c..7c50e5e53 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -91,8 +91,9 @@ func (self *TxPool) addTx(tx *types.Transaction) { } func (self *TxPool) add(tx *types.Transaction) error { - if self.txs[tx.Hash()] != nil { - return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4]) + hash := tx.Hash() + if self.txs[hash] != nil { + return fmt.Errorf("Known transaction (%x)", hash[0:4]) } err := self.ValidateTransaction(tx) if err != nil { @@ -102,7 +103,7 @@ func (self *TxPool) add(tx *types.Transaction) error { self.addTx(tx) var toname string - if to, valid := tx.To(); valid { + if to := tx.To(); to != nil { toname = common.Bytes2Hex(to[:4]) } else { toname = "[NEW_CONTRACT]" @@ -111,7 +112,7 @@ func (self *TxPool) add(tx *types.Transaction) error { // verified in ValidateTransaction. f, _ := tx.From() from := common.Bytes2Hex(f[:4]) - txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash()) + txplogger.Debugf("(t) %x => %s (%v) %x\n", from, toname, tx.Value, tx.Hash()) // Notify the subscribers go self.eventMux.Post(TxPreEvent{tx}) @@ -137,7 +138,8 @@ func (self *TxPool) AddTransactions(txs []*types.Transaction) { if err := self.add(tx); err != nil { txplogger.Debugln(err) } else { - txplogger.Debugf("tx %x\n", tx.Hash()[0:4]) + h := tx.Hash() + txplogger.Debugf("tx %x\n", h[:4]) } } } @@ -161,7 +163,8 @@ func (pool *TxPool) RemoveInvalid(query StateQuery) { var removedTxs types.Transactions for _, tx := range pool.txs { - sender := query.GetAccount(tx.From()) + from, _ := tx.From() + sender := query.GetAccount(from[:]) err := pool.ValidateTransaction(tx) if err != nil || sender.Nonce() >= tx.Nonce() { removedTxs = append(removedTxs, tx) diff --git a/core/vm_env.go b/core/vm_env.go index fb4253f5b..1ddbd5e5e 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -28,7 +28,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types } } -func (self *VMEnv) Origin() common.Address { return self.msg.From() } +func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f } func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } func (self *VMEnv) Coinbase() common.Address { return self.block.Coinbase() } func (self *VMEnv) Time() int64 { return self.block.Time() } -- cgit v1.2.3 From 0fa7859b94ddb0a35a6fbdb2c29139b0baaa2bfa Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Mar 2015 13:24:12 +0100 Subject: Fixed VM & Tests w/ conversion --- core/state_transition.go | 19 +++++++++---------- core/vm_env.go | 4 ++-- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'core') diff --git a/core/state_transition.go b/core/state_transition.go index 72999de7e..1509a5258 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) @@ -195,9 +196,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er vmenv := self.env var ref vm.ContextRef if MessageCreatesContract(msg) { - //contract := makeContract(msg, self.state) - //addr := contract.Address() - ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value) + contract := makeContract(msg, self.state) + addr := contract.Address() + ret, err, ref = vmenv.Create(sender, &addr, self.msg.Data(), self.gas, self.gasPrice, self.value) if err == nil { dataGas := big.NewInt(int64(len(ret))) dataGas.Mul(dataGas, vm.GasCreateByte) @@ -243,13 +244,11 @@ func (self *StateTransition) gasUsed() *big.Int { // Converts an message in to a state object func makeContract(msg Message, state *state.StateDB) *state.StateObject { - /* - addr := AddressFromMessage(msg) + faddr, _ := msg.From() + addr := crypto.CreateAddress(faddr, msg.Nonce()) - contract := state.GetOrNewStateObject(addr) - contract.SetInitCode(msg.Data()) + contract := state.GetOrNewStateObject(addr) + contract.SetInitCode(msg.Data()) - return contract - */ - return nil + return contract } diff --git a/core/vm_env.go b/core/vm_env.go index 1ddbd5e5e..7845d1cd9 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -68,7 +68,7 @@ func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, return exe.Call(addr, me) } -func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { - exe := self.vm(nil, data, gas, price, value) +func (self *VMEnv) Create(me vm.ContextRef, addr *common.Address, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { + exe := self.vm(addr, data, gas, price, value) return exe.Create(me) } -- cgit v1.2.3 From c21293cd91f5cd95a823065eb2345c840feec1a0 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Mar 2015 16:05:17 +0100 Subject: bloom --- core/types/bloom9.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 55bfe2756..59b6c69c3 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -28,7 +28,7 @@ func LogsBloom(logs state.Logs) *big.Int { } for _, b := range data { - bin.Or(bin, common.BigD(bloom9(crypto.Sha3(b[:])).Bytes())) + bin.Or(bin, bloom9(crypto.Sha3(b[:]))) } } @@ -38,9 +38,10 @@ func LogsBloom(logs state.Logs) *big.Int { func bloom9(b []byte) *big.Int { r := new(big.Int) - for i := 0; i < 16; i += 2 { + for i := 0; i < 6; i += 2 { t := big.NewInt(1) - b := uint(b[i+1]) + 1024*(uint(b[i])&1) + //b := uint(b[i+1]) + 512*(uint(b[i])&1) + b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 511 r.Or(r, t.Lsh(t, b)) } -- cgit v1.2.3 From 86661de07746cd4e4ad8d016afee9fa8074aa141 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Mar 2015 18:00:03 +0100 Subject: Fixed tests and bloom --- core/types/bloom9.go | 17 ++++++++++------- core/types/common.go | 11 +++++++---- 2 files changed, 17 insertions(+), 11 deletions(-) (limited to 'core') diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 59b6c69c3..64a8ff49a 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -20,15 +20,15 @@ func CreateBloom(receipts Receipts) Bloom { func LogsBloom(logs state.Logs) *big.Int { bin := new(big.Int) for _, log := range logs { - data := make([]common.Hash, len(log.Topics())+1) - data[0] = log.Address().Hash() + data := make([]common.Hash, len(log.Topics())) + bin.Or(bin, bloom9(log.Address().Bytes())) for i, topic := range log.Topics() { - data[i+1] = topic + data[i] = topic } for _, b := range data { - bin.Or(bin, bloom9(crypto.Sha3(b[:]))) + bin.Or(bin, bloom9(b[:])) } } @@ -36,21 +36,24 @@ func LogsBloom(logs state.Logs) *big.Int { } func bloom9(b []byte) *big.Int { + b = crypto.Sha3(b[:]) + r := new(big.Int) for i := 0; i < 6; i += 2 { t := big.NewInt(1) - //b := uint(b[i+1]) + 512*(uint(b[i])&1) - b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 511 + b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 2047 r.Or(r, t.Lsh(t, b)) } return r } +var Bloom9 = bloom9 + func BloomLookup(bin Bloom, topic common.Hash) bool { bloom := bin.Big() - cmp := bloom9(crypto.Sha3(topic[:])) + cmp := bloom9(topic[:]) return bloom.And(bloom, cmp).Cmp(cmp) == 0 } diff --git a/core/types/common.go b/core/types/common.go index 6c5ac06b1..cb57ef053 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -10,7 +11,9 @@ type BlockProcessor interface { Process(*Block) (*big.Int, error) } -type Bloom [256]byte +const bloomLength = 256 + +type Bloom [bloomLength]byte func BytesToBloom(b []byte) Bloom { var bloom Bloom @@ -19,13 +22,13 @@ func BytesToBloom(b []byte) Bloom { } func (b *Bloom) SetBytes(d []byte) { - if len(b) > len(d) { - panic("bloom bytes too big") + if len(b) < len(d) { + panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d))) } // reverse loop for i := len(d) - 1; i >= 0; i-- { - b[i] = b[i] + b[bloomLength-len(d)+i] = b[i] } } -- cgit v1.2.3 From 942980609fb8a36873689bd3bd0a15488f327d56 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 18 Mar 2015 11:44:25 +0100 Subject: conversions --- core/types/common.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core') diff --git a/core/types/common.go b/core/types/common.go index cb57ef053..ace9c2c4b 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -35,3 +35,7 @@ func (b *Bloom) SetBytes(d []byte) { func (b Bloom) Big() *big.Int { return common.Bytes2Big(b[:]) } + +func (b Bloom) Bytes() []byte { + return b[:] +} -- cgit v1.2.3 From 0a1eeca41e6ba5920ba65d9b41654768299bc7e3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 18 Mar 2015 13:00:01 +0100 Subject: conversions. -compilable- --- core/state_transition.go | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core') diff --git a/core/state_transition.go b/core/state_transition.go index 1509a5258..d0b2c5d7c 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -57,6 +57,12 @@ type Message interface { Data() []byte } +func AddressFromMessage(msg Message) common.Address { + from, _ := msg.From() + + return crypto.CreateAddress(from, msg.Nonce()) +} + func MessageCreatesContract(msg Message) bool { return msg.To() == nil } -- cgit v1.2.3 From c298148a7f0890cd5ed62d2a91cc81431b2731f1 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 18 Mar 2015 13:24:34 +0100 Subject: core/types: use package rlp instead of common.Decode --- core/types/block.go | 99 ++++++++++++++++++++++++++++++++++++----------- core/types/block_test.go | 57 +++++++++++++++++++++++---- core/types/derive_sha.go | 4 +- core/types/transaction.go | 55 +++++++++++++------------- 4 files changed, 155 insertions(+), 60 deletions(-) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index aca23aa04..6f26358fb 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -3,12 +3,13 @@ package types import ( "encoding/binary" "fmt" + "io" "math/big" "sort" "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" ) @@ -45,6 +46,14 @@ type Header struct { Nonce [8]byte } +func (self *Header) Hash() common.Hash { + return rlpHash(self.rlpData(true)) +} + +func (self *Header) HashNoNonce() common.Hash { + return rlpHash(self.rlpData(false)) +} + func (self *Header) rlpData(withNonce bool) []interface{} { fields := []interface{}{ self.ParentHash, @@ -64,7 +73,6 @@ func (self *Header) rlpData(withNonce bool) []interface{} { if withNonce { fields = append(fields, self.MixDigest, self.Nonce) } - return fields } @@ -72,12 +80,11 @@ func (self *Header) RlpData() interface{} { return self.rlpData(true) } -func (self *Header) Hash() common.Hash { - return common.BytesToHash(crypto.Sha3(common.Encode(self.rlpData(true)))) -} - -func (self *Header) HashNoNonce() common.Hash { - return common.BytesToHash(crypto.Sha3(common.Encode(self.rlpData(false)))) +func rlpHash(x interface{}) (h common.Hash) { + hw := sha3.NewKeccak256() + rlp.Encode(hw, x) + hw.Sum(h[:0]) + return h } type Block struct { @@ -95,6 +102,26 @@ type Block struct { Reward *big.Int } +// StorageBlock defines the RLP encoding of a Block stored in the +// state database. The StorageBlock encoding contains fields that +// would otherwise need to be recomputed. +type StorageBlock Block + +// "external" block encoding. used for eth protocol, etc. +type extblock struct { + Header *Header + Txs []*Transaction + Uncles []*Header +} + +// "storage" block encoding. used for database. +type storageblock struct { + Header *Header + Txs []*Transaction + Uncles []*Header + TD *big.Int +} + func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash, difficulty *big.Int, nonce uint64, extra string) *Block { header := &Header{ Root: root, @@ -107,9 +134,7 @@ func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash, GasLimit: new(big.Int), } header.SetNonce(nonce) - block := &Block{header: header, Reward: new(big.Int)} - return block } @@ -122,22 +147,40 @@ func NewBlockWithHeader(header *Header) *Block { } func (self *Block) DecodeRLP(s *rlp.Stream) error { - var extblock struct { - Header *Header - Txs []*Transaction - Uncles []*Header - TD *big.Int // optional + var eb extblock + if err := s.Decode(&eb); err != nil { + return err } - if err := s.Decode(&extblock); err != nil { + self.header, self.uncles, self.transactions = eb.Header, eb.Uncles, eb.Txs + return nil +} + +func (self Block) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, extblock{ + Header: self.header, + Txs: self.transactions, + Uncles: self.uncles, + }) +} + +func (self *StorageBlock) DecodeRLP(s *rlp.Stream) error { + var sb storageblock + if err := s.Decode(&sb); err != nil { return err } - self.header = extblock.Header - self.uncles = extblock.Uncles - self.transactions = extblock.Txs - self.Td = extblock.TD + self.header, self.uncles, self.transactions, self.Td = sb.Header, sb.Uncles, sb.Txs, sb.TD return nil } +func (self StorageBlock) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, storageblock{ + Header: self.header, + Txs: self.transactions, + Uncles: self.uncles, + TD: self.Td, + }) +} + func (self *Block) Header() *Header { return self.header } @@ -148,7 +191,7 @@ func (self *Block) Uncles() []*Header { func (self *Block) SetUncles(uncleHeaders []*Header) { self.uncles = uncleHeaders - self.header.UncleHash = common.BytesToHash(crypto.Sha3(common.Encode(uncleHeaders))) + self.header.UncleHash = rlpHash(uncleHeaders) } func (self *Block) Transactions() Transactions { @@ -213,7 +256,6 @@ func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } func (self *Block) Root() common.Hash { return self.header.Root } func (self *Block) SetRoot(root common.Hash) { self.header.Root = root } -func (self *Block) Size() common.StorageSize { return common.StorageSize(len(common.Encode(self))) } func (self *Block) GetTransaction(i int) *Transaction { if len(self.transactions) > i { return self.transactions[i] @@ -227,6 +269,19 @@ func (self *Block) GetUncle(i int) *Header { return nil } +func (self *Block) Size() common.StorageSize { + c := writeCounter(0) + rlp.Encode(&c, self) + return common.StorageSize(c) +} + +type writeCounter common.StorageSize + +func (c *writeCounter) Write(b []byte) (int, error) { + *c += writeCounter(len(b)) + return len(b), nil +} + // Implement pow.Block func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } func (self *Block) HashNoNonce() common.Hash { return self.header.HashNoNonce() } diff --git a/core/types/block_test.go b/core/types/block_test.go index 16ba3043f..e4f6c38a5 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -1,19 +1,60 @@ package types import ( + "bytes" "math/big" + "reflect" "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" ) -// XXX Tests doesn't really do anything. This tests exists while working on the fixed size conversions -func TestConversion(t *testing.T) { - var ( - parent common.Hash - coinbase common.Address - hash common.Hash - ) +// from bcValidBlockTest.json, "SimpleTx" +func TestBlockEncoding(t *testing.T) { + blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0") - NewBlock(parent, coinbase, hash, big.NewInt(0), 0, "") + var block Block + if err := rlp.DecodeBytes(blockEnc, &block); err != nil { + t.Fatal("decode error: ", err) + } + + check := func(f string, got, want interface{}) { + if !reflect.DeepEqual(got, want) { + t.Errorf("%s mismatch: got %v, want %v", f, got, want) + } + } + check("Difficulty", block.Difficulty(), big.NewInt(131072)) + check("GasLimit", block.GasLimit(), big.NewInt(3141592)) + check("GasUsed", block.GasUsed(), big.NewInt(21000)) + check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1")) + check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498")) + check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) + check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e")) + check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4)) + check("Time", block.Time(), int64(1426516743)) + check("Size", block.Size(), common.StorageSize(len(blockEnc))) + + to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") + check("Transactions", block.Transactions(), Transactions{ + { + Payload: []byte{}, + Amount: big.NewInt(10), + Price: big.NewInt(10), + GasLimit: big.NewInt(50000), + AccountNonce: 0, + V: 27, + R: common.FromHex("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f"), + S: common.FromHex("8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1"), + Recipient: &to, + }, + }) + + ourBlockEnc, err := rlp.EncodeToBytes(&block) + if err != nil { + t.Fatal("encode error: ", err) + } + if !bytes.Equal(ourBlockEnc, blockEnc) { + t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc) + } } diff --git a/core/types/derive_sha.go b/core/types/derive_sha.go index 0fc45a508..10e3d7446 100644 --- a/core/types/derive_sha.go +++ b/core/types/derive_sha.go @@ -3,6 +3,7 @@ package types import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) @@ -15,7 +16,8 @@ func DeriveSha(list DerivableList) common.Hash { db, _ := ethdb.NewMemDatabase() trie := trie.New(nil, db) for i := 0; i < list.Len(); i++ { - trie.Update(common.Encode(i), list.GetRlp(i)) + key, _ := rlp.EncodeToBytes(i) + trie.Update(key, list.GetRlp(i)) } return common.BytesToHash(trie.Root()) diff --git a/core/types/transaction.go b/core/types/transaction.go index 24035a3ae..391fb46f5 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -1,16 +1,14 @@ package types import ( - "bytes" + "crypto/ecdsa" "errors" "fmt" - "io" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/secp256k1" - "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" ) @@ -38,16 +36,18 @@ func NewTransactionMessage(to common.Address, amount, gasAmount, gasPrice *big.I } func NewTransactionFromBytes(data []byte) *Transaction { + // TODO: remove this function if possible. callers would + // much better off decoding into transaction directly. + // it's not that hard. tx := new(Transaction) - rlp.Decode(bytes.NewReader(data), tx) + rlp.DecodeBytes(data, tx) return tx } -func (tx *Transaction) Hash() (a common.Hash) { - h := sha3.NewKeccak256() - rlp.Encode(h, []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}) - h.Sum(a[:0]) - return a +func (tx *Transaction) Hash() common.Hash { + return rlpHash([]interface{}{ + tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload, + }) } func (self *Transaction) Data() []byte { @@ -122,17 +122,14 @@ func (tx *Transaction) SetSignatureValues(sig []byte) error { return nil } -func (tx Transaction) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, []interface{}{ - tx.AccountNonce, - tx.Price, tx.GasLimit, - tx.Recipient, - tx.Amount, - tx.Payload, - tx.V, - tx.R, - tx.S, - }) +func (tx *Transaction) SignECDSA(prv *ecdsa.PrivateKey) error { + h := tx.Hash() + sig, err := crypto.Sign(h[:], prv) + if err != nil { + return err + } + tx.SetSignatureValues(sig) + return nil } // TODO: remove @@ -141,11 +138,6 @@ func (tx *Transaction) RlpData() interface{} { return append(data, tx.V, new(big.Int).SetBytes(tx.R).Bytes(), new(big.Int).SetBytes(tx.S).Bytes()) } -// TODO: remove -func (tx *Transaction) RlpEncode() []byte { - return common.Encode(tx) -} - func (tx *Transaction) String() string { var from, to string if f, err := tx.From(); err != nil { @@ -158,6 +150,7 @@ func (tx *Transaction) String() string { } else { to = fmt.Sprintf("%x", t[:]) } + enc, _ := rlp.EncodeToBytes(tx) return fmt.Sprintf(` TX(%x) Contract: %v @@ -185,7 +178,7 @@ func (tx *Transaction) String() string { tx.V, tx.R, tx.S, - common.Encode(tx), + enc, ) } @@ -204,9 +197,13 @@ func (self Transactions) RlpData() interface{} { return enc } -func (s Transactions) Len() int { return len(s) } -func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s Transactions) GetRlp(i int) []byte { return common.Rlp(s[i]) } +func (s Transactions) Len() int { return len(s) } +func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func (s Transactions) GetRlp(i int) []byte { + enc, _ := rlp.EncodeToBytes(s[i]) + return enc +} type TxByNonce struct{ Transactions } -- cgit v1.2.3 From b5b83db450974f70f4bc25f280cc6ec9193f8e19 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 18 Mar 2015 13:36:48 +0100 Subject: core: use package rlp to encode blocks This also changes the chain export format so there is no enclosing list around the blocks, which enables streaming export. --- core/chain_manager.go | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 5316a3423..060805428 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -3,6 +3,7 @@ package core import ( "bytes" "fmt" + "io" "math/big" "sync" @@ -254,22 +255,20 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) { bc.currentBlock = bc.genesisBlock } -func (self *ChainManager) Export() []byte { +// Export writes the active chain to the given writer. +func (self *ChainManager) Export(w io.Writer) error { self.mu.RLock() defer self.mu.RUnlock() - chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) - - blocks := make([]*types.Block, int(self.currentBlock.NumberU64())+1) for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) { - blocks[block.NumberU64()] = block + if err := block.EncodeRLP(w); err != nil { + return err + } } - - return common.Encode(blocks) + return nil } func (bc *ChainManager) insert(block *types.Block) { - //encodedBlock := common.Encode(block) bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes()) bc.currentBlock = block bc.lastBlockHash = block.Hash() @@ -279,10 +278,9 @@ func (bc *ChainManager) insert(block *types.Block) { } func (bc *ChainManager) write(block *types.Block) { - encodedBlock := common.Encode(block.RlpDataForStorage()) - + enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block)) key := append(blockHashPre, block.Hash().Bytes()...) - bc.blockDb.Put(key, encodedBlock) + bc.blockDb.Put(key, enc) } // Accessors @@ -324,13 +322,12 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block { if len(data) == 0 { return nil } - var block types.Block + var block types.StorageBlock if err := rlp.Decode(bytes.NewReader(data), &block); err != nil { - fmt.Println(err) + chainlogger.Errorf("invalid block RLP for hash %x: %v", hash, err) return nil } - - return &block + return (*types.Block)(&block) } func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { -- cgit v1.2.3 From a59dd393e71cc52b1f96973aef884af619166f38 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 18 Mar 2015 13:38:47 +0100 Subject: core: fix tests --- core/block_processor_test.go | 5 +++-- core/chain_manager_test.go | 9 ++++----- core/genesis.go | 4 ---- core/transaction_pool.go | 2 +- core/transaction_pool_test.go | 12 +++++------- 5 files changed, 13 insertions(+), 19 deletions(-) (limited to 'core') diff --git a/core/block_processor_test.go b/core/block_processor_test.go index ad29404e1..64add7e8b 100644 --- a/core/block_processor_test.go +++ b/core/block_processor_test.go @@ -4,6 +4,7 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/pow/ezp" @@ -19,7 +20,7 @@ func proc() (*BlockProcessor, *ChainManager) { func TestNumber(t *testing.T) { bp, chain := proc() - block1 := chain.NewBlock(nil) + block1 := chain.NewBlock(common.Address{}) block1.Header().Number = big.NewInt(3) err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header()) @@ -27,7 +28,7 @@ func TestNumber(t *testing.T) { t.Errorf("expected block number error") } - block1 = chain.NewBlock(nil) + block1 = chain.NewBlock(common.Address{}) err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header()) if err == BlockNumberErr { t.Errorf("didn't expect block number error") diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index 898d37f9c..e49e594a3 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -1,7 +1,6 @@ package core import ( - "bytes" "fmt" "math/big" "os" @@ -35,7 +34,7 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big // asert the bmans have the same block at i bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash() bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash() - if bytes.Compare(bi1, bi2) != 0 { + if bi1 != bi2 { t.Fatal("chains do not have the same hash at height", i) } @@ -270,11 +269,11 @@ func TestChainInsertions(t *testing.T) { <-done } - if bytes.Equal(chain2[len(chain2)-1].Hash(), chainMan.CurrentBlock().Hash()) { + if chain2[len(chain2)-1].Hash() != chainMan.CurrentBlock().Hash() { t.Error("chain2 is canonical and shouldn't be") } - if !bytes.Equal(chain1[len(chain1)-1].Hash(), chainMan.CurrentBlock().Hash()) { + if chain1[len(chain1)-1].Hash() != chainMan.CurrentBlock().Hash() { t.Error("chain1 isn't canonical and should be") } } @@ -320,7 +319,7 @@ func TestChainMultipleInsertions(t *testing.T) { <-done } - if !bytes.Equal(chains[longest][len(chains[longest])-1].Hash(), chainMan.CurrentBlock().Hash()) { + if chains[longest][len(chains[longest])-1].Hash() != chainMan.CurrentBlock().Hash() { t.Error("Invalid canonical chain") } } diff --git a/core/genesis.go b/core/genesis.go index 70845b502..3e00533ae 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" ) @@ -19,9 +18,6 @@ import ( var ZeroHash256 = make([]byte, 32) var ZeroHash160 = make([]byte, 20) var ZeroHash512 = make([]byte, 64) -var EmptyShaList = crypto.Sha3(common.Encode([]interface{}{})) -var EmptyListRoot = crypto.Sha3(common.Encode("")) - var GenesisDiff = big.NewInt(131072) var GenesisGasLimit = big.NewInt(3141592) diff --git a/core/transaction_pool.go b/core/transaction_pool.go index 7c50e5e53..f2fe5c748 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -63,7 +63,7 @@ func NewTxPool(eventMux *event.TypeMux) *TxPool { func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { // Validate sender if _, err := tx.From(); err != nil { - return err + return ErrInvalidSender } // Validate curve param v, _, _ := tx.Curve() diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go index 418cb0415..bf9012573 100644 --- a/core/transaction_pool_test.go +++ b/core/transaction_pool_test.go @@ -4,10 +4,10 @@ import ( "crypto/ecdsa" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/state" ) @@ -21,11 +21,11 @@ func SQ() stateQuery { } func (self stateQuery) GetAccount(addr []byte) *state.StateObject { - return state.NewStateObject(addr, self.db) + return state.NewStateObject(common.BytesToAddress(addr), self.db) } func transaction() *types.Transaction { - return types.NewTransactionMessage(make([]byte, 20), common.Big0, common.Big0, common.Big0, nil) + return types.NewTransactionMessage(common.Address{}, common.Big0, common.Big0, common.Big0, nil) } func setup() (*TxPool, *ecdsa.PrivateKey) { @@ -88,10 +88,8 @@ func TestRemoveInvalid(t *testing.T) { func TestInvalidSender(t *testing.T) { pool, _ := setup() - tx := new(types.Transaction) - tx.V = 28 - err := pool.ValidateTransaction(tx) + err := pool.ValidateTransaction(new(types.Transaction)) if err != ErrInvalidSender { - t.Error("expected %v, got %v", ErrInvalidSender, err) + t.Errorf("expected %v, got %v", ErrInvalidSender, err) } } -- cgit v1.2.3 From 48dd601de0ffea4e1bf57a8923f2a6126553b575 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 18 Mar 2015 14:15:48 +0100 Subject: prep template for fixed size hashes --- core/chain_manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 5316a3423..0251f7c72 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -37,8 +37,8 @@ func CalcDifficulty(block, parent *types.Header) *big.Int { diff.Sub(parent.Difficulty, adjust) } - if diff.Cmp(GenesisDiff) < 0 { - return GenesisDiff + if diff.Cmp(min) < 0 { + return min } return diff -- cgit v1.2.3 From 29eb2209101cfec758803bc52582900dad246f7f Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 19 Mar 2015 17:18:55 +0100 Subject: :-) --- core/chain_manager.go | 1 - 1 file changed, 1 deletion(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index ff37ea28a..915fa704f 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -466,7 +466,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { } - // XXX put this in a goroutine? go self.eventMux.Post(queueEvent) return nil -- cgit v1.2.3 From 62236dd95e6d069b8bd9895c9998676b8d946d37 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 19 Mar 2015 23:20:41 +0100 Subject: copy over loop --- core/types/common.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'core') diff --git a/core/types/common.go b/core/types/common.go index 4e885c4c6..ce1090919 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -3,8 +3,8 @@ package types import ( "math/big" - "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/state" "fmt" ) @@ -28,10 +28,7 @@ func (b *Bloom) SetBytes(d []byte) { panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d))) } - // reverse loop - for i := len(d) - 1; i >= 0; i-- { - b[bloomLength-len(d)+i] = b[i] - } + copy(b[bloomLength-len(d):], d) } func (b Bloom) Big() *big.Int { -- cgit v1.2.3 From deee9cb170ff105992ede83c52013d0c2c4ad10d Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 20 Mar 2015 15:54:42 +0100 Subject: Added caching for block chain. Currently set to 10k --- core/block_cache.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++ core/block_cache_test.go | 48 ++++++++++++++++++++++++++++++++ core/chain_manager.go | 20 +++++++++++++- core/chain_manager_test.go | 2 +- 4 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 core/block_cache.go create mode 100644 core/block_cache_test.go (limited to 'core') diff --git a/core/block_cache.go b/core/block_cache.go new file mode 100644 index 000000000..321021eb4 --- /dev/null +++ b/core/block_cache.go @@ -0,0 +1,68 @@ +package core + +import ( + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// BlockCache implements a caching mechanism specifically for blocks and uses FILO to pop +type BlockCache struct { + size int + + hashes []common.Hash + blocks map[common.Hash]*types.Block + + mu sync.RWMutex +} + +// Creates and returns a `BlockCache` with `size`. If `size` is smaller than 1 it will panic +func NewBlockCache(size int) *BlockCache { + if size < 1 { + panic("block cache size not allowed to be smaller than 1") + } + + bc := &BlockCache{size: size} + bc.Clear() + return bc +} + +func (bc *BlockCache) Clear() { + bc.blocks = make(map[common.Hash]*types.Block) + bc.hashes = nil + +} + +func (bc *BlockCache) Push(block *types.Block) { + bc.mu.Lock() + defer bc.mu.Unlock() + + if len(bc.hashes) == bc.size { + delete(bc.blocks, bc.hashes[0]) + + // XXX There are a few other options on solving this + // 1) use a poller / GC like mechanism to clean up untracked objects + // 2) copy as below + // re-use the slice and remove the reference to bc.hashes[0] + // this will allow the element to be garbage collected. + copy(bc.hashes, bc.hashes[1:]) + } else { + bc.hashes = append(bc.hashes, common.Hash{}) + } + + hash := block.Hash() + bc.blocks[hash] = block + bc.hashes[len(bc.hashes)-1] = hash +} + +func (bc *BlockCache) Get(hash common.Hash) *types.Block { + bc.mu.RLock() + defer bc.mu.RUnlock() + + if block, haz := bc.blocks[hash]; haz { + return block + } + + return nil +} diff --git a/core/block_cache_test.go b/core/block_cache_test.go new file mode 100644 index 000000000..d4f610b71 --- /dev/null +++ b/core/block_cache_test.go @@ -0,0 +1,48 @@ +package core + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func newChain(size int) (chain []*types.Block) { + var parentHash common.Hash + for i := 0; i < size; i++ { + block := types.NewBlock(parentHash, common.Address{}, common.Hash{}, new(big.Int), 0, "") + block.Header().Number = big.NewInt(int64(i)) + chain = append(chain, block) + parentHash = block.Hash() + } + return +} + +func insertChainCache(cache *BlockCache, chain []*types.Block) { + for _, block := range chain { + cache.Push(block) + } +} + +func TestNewBlockCache(t *testing.T) { + chain := newChain(3) + cache := NewBlockCache(2) + insertChainCache(cache, chain) + + if cache.hashes[0] != chain[1].Hash() { + t.Error("oldest block incorrect") + } +} + +func TestInclusion(t *testing.T) { + chain := newChain(3) + cache := NewBlockCache(3) + insertChainCache(cache, chain) + + for _, block := range chain { + if b := cache.Get(block.Hash()); b == nil { + t.Errorf("getting %x failed", block.Hash()) + } + } +} diff --git a/core/chain_manager.go b/core/chain_manager.go index 915fa704f..1bc8edea6 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -23,6 +23,8 @@ var ( blockNumPre = []byte("block-num-") ) +const blockCacheLimit = 10000 + type StateQuery interface { GetAccount(addr []byte) *state.StateObject } @@ -92,15 +94,25 @@ type ChainManager struct { transState *state.StateDB txState *state.ManagedState + cache *BlockCache + quit chan struct{} } func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *ChainManager { - bc := &ChainManager{blockDb: blockDb, stateDb: stateDb, genesisBlock: GenesisBlock(stateDb), eventMux: mux, quit: make(chan struct{})} + bc := &ChainManager{blockDb: blockDb, stateDb: stateDb, genesisBlock: GenesisBlock(stateDb), eventMux: mux, quit: make(chan struct{}), cache: NewBlockCache(blockCacheLimit)} bc.setLastBlock() bc.transState = bc.State().Copy() // Take ownership of this particular state bc.txState = state.ManageState(bc.State().Copy()) + + // load in last `blockCacheLimit` - 1 blocks. Last block is the current. + ancestors := bc.GetAncestors(bc.currentBlock, blockCacheLimit-1) + ancestors = append(ancestors, bc.currentBlock) + for _, block := range ancestors { + bc.cache.Push(block) + } + go bc.update() return bc @@ -275,6 +287,8 @@ func (bc *ChainManager) insert(block *types.Block) { key := append(blockNumPre, block.Number().Bytes()...) bc.blockDb.Put(key, bc.lastBlockHash.Bytes()) + // Push block to cache + bc.cache.Push(block) } func (bc *ChainManager) write(block *types.Block) { @@ -318,6 +332,10 @@ func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) ( } func (self *ChainManager) GetBlock(hash common.Hash) *types.Block { + if block := self.cache.Get(hash); block != nil { + return block + } + data, _ := self.blockDb.Get(append(blockHashPre, hash[:]...)) if len(data) == 0 { return nil diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index e49e594a3..bf172f3bf 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -69,7 +69,7 @@ func printChain(bc *ChainManager) { func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { td := new(big.Int) for _, block := range chainB { - td2, err := bman.bc.processor.Process(block) + td2, _, err := bman.bc.processor.Process(block) if err != nil { if IsKnownBlockErr(err) { continue -- cgit v1.2.3 From c28116cb3b485f01aba852fdc9559a2495db6654 Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 21 Mar 2015 14:46:50 +0100 Subject: Fixed incorrect recipient derived --- core/types/transaction.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/types/transaction.go b/core/types/transaction.go index 391fb46f5..7aef5ce94 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -80,7 +80,7 @@ func (self *Transaction) From() (common.Address, error) { return common.Address{}, errors.New("invalid public key") } var addr common.Address - copy(addr[:], crypto.Sha3(pubkey[1:])) + copy(addr[:], crypto.Sha3(pubkey[1:])[12:]) return addr, nil } -- cgit v1.2.3