diff options
Diffstat (limited to 'core/types/block.go')
-rw-r--r-- | core/types/block.go | 99 |
1 files changed, 77 insertions, 22 deletions
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() } |