Browse Source

converted chain manager

obscuren 10 years ago
parent
commit
8ce6a36478
7 changed files with 63 additions and 57 deletions
  1. 18 20
      core/block_processor.go
  2. 5 5
      core/chain_makers.go
  3. 27 21
      core/chain_manager.go
  4. 4 2
      core/error.go
  5. 1 1
      core/types/receipt.go
  6. 3 3
      state/state_object.go
  7. 5 5
      state/statedb.go

+ 18 - 20
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)
 }

+ 5 - 5
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)

+ 27 - 21
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)
 }
+*/

+ 4 - 2
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 {

+ 1 - 1
core/types/receipt.go

@@ -14,7 +14,7 @@ import (
 type Receipt struct {
 	PostState         []byte
 	CumulativeGasUsed *big.Int
-	Bloom             []byte
+	Bloom             Bloom
 	logs              state.Logs
 }
 

+ 3 - 3
state/state_object.go

@@ -82,7 +82,7 @@ func NewStateObject(address common.Address, db common.Database) *StateObject {
 	//address := common.ToAddress(addr)
 
 	object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true}
-	object.State = New(nil, db) //New(trie.New(common.Config.Db, ""))
+	object.State = New(common.Hash{}, db) //New(trie.New(common.Config.Db, ""))
 	object.storage = make(Storage)
 	object.gasPool = new(big.Int)
 	object.prepaid = new(big.Int)
@@ -109,7 +109,7 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data
 	object.nonce = extobject.Nonce
 	object.balance = extobject.Balance
 	object.codeHash = extobject.CodeHash
-	object.State = New(extobject.Root[:], db)
+	object.State = New(extobject.Root, db)
 	object.storage = make(map[string]*common.Value)
 	object.gasPool = new(big.Int)
 	object.prepaid = new(big.Int)
@@ -339,7 +339,7 @@ func (c *StateObject) RlpDecode(data []byte) {
 	decoder := common.NewValueFromBytes(data)
 	c.nonce = decoder.Get(0).Uint()
 	c.balance = decoder.Get(1).BigInt()
-	c.State = New(decoder.Get(2).Bytes(), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface()))
+	c.State = New(common.BytesToHash(decoder.Get(2).Bytes()), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface()))
 	c.storage = make(map[string]*common.Value)
 	c.gasPool = new(big.Int)
 

+ 5 - 5
state/statedb.go

@@ -28,8 +28,8 @@ type StateDB struct {
 }
 
 // Create a new state from a given trie
-func New(root []byte, db common.Database) *StateDB {
-	trie := trie.NewSecure(common.CopyBytes(root), db)
+func New(root common.Hash, db common.Database) *StateDB {
+	trie := trie.NewSecure(root[:], db)
 	return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int)}
 }
 
@@ -222,7 +222,7 @@ func (s *StateDB) Cmp(other *StateDB) bool {
 }
 
 func (self *StateDB) Copy() *StateDB {
-	state := New(nil, self.db)
+	state := New(common.Hash{}, self.db)
 	state.trie = self.trie.Copy()
 	for k, stateObject := range self.stateObjects {
 		state.stateObjects[k] = stateObject.Copy()
@@ -247,8 +247,8 @@ func (self *StateDB) Set(state *StateDB) {
 	self.logs = state.logs
 }
 
-func (s *StateDB) Root() []byte {
-	return s.trie.Root()
+func (s *StateDB) Root() common.Hash {
+	return common.BytesToHash(s.trie.Root())
 }
 
 func (s *StateDB) Trie() *trie.SecureTrie {