core, core/state: batch-based state sync
This commit is contained in:
		@@ -100,10 +100,8 @@ func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update the state with pending changes
 | 
						// Update the state with pending changes
 | 
				
			||||||
	statedb.SyncIntermediate()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usedGas.Add(usedGas, gas)
 | 
						usedGas.Add(usedGas, gas)
 | 
				
			||||||
	receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas)
 | 
						receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
 | 
				
			||||||
	receipt.TxHash = tx.Hash()
 | 
						receipt.TxHash = tx.Hash()
 | 
				
			||||||
	receipt.GasUsed = new(big.Int).Set(gas)
 | 
						receipt.GasUsed = new(big.Int).Set(gas)
 | 
				
			||||||
	if MessageCreatesContract(tx) {
 | 
						if MessageCreatesContract(tx) {
 | 
				
			||||||
@@ -265,16 +263,16 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
 | 
				
			|||||||
	// Accumulate static rewards; block reward, uncle's and uncle inclusion.
 | 
						// Accumulate static rewards; block reward, uncle's and uncle inclusion.
 | 
				
			||||||
	AccumulateRewards(state, header, uncles)
 | 
						AccumulateRewards(state, header, uncles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Commit state objects/accounts to a temporary trie (does not save)
 | 
						// Commit state objects/accounts to a database batch and calculate
 | 
				
			||||||
	// used to calculate the state root.
 | 
						// the state root. The database is not modified if the root
 | 
				
			||||||
	state.SyncObjects()
 | 
						// doesn't match.
 | 
				
			||||||
	if header.Root != state.Root() {
 | 
						root, batch := state.CommitBatch()
 | 
				
			||||||
		err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
 | 
						if header.Root != root {
 | 
				
			||||||
		return
 | 
							return nil, nil, fmt.Errorf("invalid merkle root: header=%x computed=%x", header.Root, root)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Sync the current block's state to the database
 | 
						// Execute the database writes.
 | 
				
			||||||
	state.Sync()
 | 
						batch.Write()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return state.Logs(), receipts, nil
 | 
						return state.Logs(), receipts, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
package core
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
@@ -94,9 +95,9 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	b.statedb.SyncIntermediate()
 | 
						root := b.statedb.IntermediateRoot()
 | 
				
			||||||
	b.header.GasUsed.Add(b.header.GasUsed, gas)
 | 
						b.header.GasUsed.Add(b.header.GasUsed, gas)
 | 
				
			||||||
	receipt := types.NewReceipt(b.statedb.Root().Bytes(), b.header.GasUsed)
 | 
						receipt := types.NewReceipt(root.Bytes(), b.header.GasUsed)
 | 
				
			||||||
	logs := b.statedb.GetLogs(tx.Hash())
 | 
						logs := b.statedb.GetLogs(tx.Hash())
 | 
				
			||||||
	receipt.SetLogs(logs)
 | 
						receipt.SetLogs(logs)
 | 
				
			||||||
	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
 | 
						receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
 | 
				
			||||||
@@ -163,8 +164,11 @@ func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int,
 | 
				
			|||||||
			gen(i, b)
 | 
								gen(i, b)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		AccumulateRewards(statedb, h, b.uncles)
 | 
							AccumulateRewards(statedb, h, b.uncles)
 | 
				
			||||||
		statedb.SyncIntermediate()
 | 
							root, err := statedb.Commit()
 | 
				
			||||||
		h.Root = statedb.Root()
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(fmt.Sprintf("state write error: %v", err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							h.Root = root
 | 
				
			||||||
		return types.NewBlock(h, b.txs, b.uncles, b.receipts)
 | 
							return types.NewBlock(h, b.txs, b.uncles, b.receipts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i := 0; i < n; i++ {
 | 
						for i := 0; i < n; i++ {
 | 
				
			||||||
@@ -184,7 +188,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
 | 
				
			|||||||
		time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
 | 
							time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &types.Header{
 | 
						return &types.Header{
 | 
				
			||||||
		Root:       state.Root(),
 | 
							Root:       state.IntermediateRoot(),
 | 
				
			||||||
		ParentHash: parent.Hash(),
 | 
							ParentHash: parent.Hash(),
 | 
				
			||||||
		Coinbase:   parent.Coinbase(),
 | 
							Coinbase:   parent.Coinbase(),
 | 
				
			||||||
		Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
 | 
							Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -839,8 +839,8 @@ out:
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func blockErr(block *types.Block, err error) {
 | 
					func blockErr(block *types.Block, err error) {
 | 
				
			||||||
	h := block.Header()
 | 
						if glog.V(logger.Error) {
 | 
				
			||||||
	glog.V(logger.Error).Infof("Bad block #%v (%x)\n", h.Number, h.Hash().Bytes())
 | 
							glog.Errorf("Bad block #%v (%s)\n", block.Number(), block.Hash().Hex())
 | 
				
			||||||
	glog.V(logger.Error).Infoln(err)
 | 
							glog.Errorf("    %v", err)
 | 
				
			||||||
	glog.V(logger.Debug).Infoln(verifyNonces)
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,7 +69,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
 | 
				
			|||||||
			statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
 | 
								statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	statedb.SyncObjects()
 | 
						root, stateBatch := statedb.CommitBatch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	difficulty := common.String2Big(genesis.Difficulty)
 | 
						difficulty := common.String2Big(genesis.Difficulty)
 | 
				
			||||||
	block := types.NewBlock(&types.Header{
 | 
						block := types.NewBlock(&types.Header{
 | 
				
			||||||
@@ -81,7 +81,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
 | 
				
			|||||||
		Difficulty: difficulty,
 | 
							Difficulty: difficulty,
 | 
				
			||||||
		MixDigest:  common.HexToHash(genesis.Mixhash),
 | 
							MixDigest:  common.HexToHash(genesis.Mixhash),
 | 
				
			||||||
		Coinbase:   common.HexToAddress(genesis.Coinbase),
 | 
							Coinbase:   common.HexToAddress(genesis.Coinbase),
 | 
				
			||||||
		Root:       statedb.Root(),
 | 
							Root:       root,
 | 
				
			||||||
	}, nil, nil, nil)
 | 
						}, nil, nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if block := GetBlock(chainDb, block.Hash()); block != nil {
 | 
						if block := GetBlock(chainDb, block.Hash()); block != nil {
 | 
				
			||||||
@@ -92,8 +92,10 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return block, nil
 | 
							return block, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	statedb.Sync()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := stateBatch.Write(); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("cannot write state: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := WriteTd(chainDb, block.Hash(), difficulty); err != nil {
 | 
						if err := WriteTd(chainDb, block.Hash(), difficulty); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -115,12 +117,14 @@ func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big
 | 
				
			|||||||
	statedb := state.New(common.Hash{}, db)
 | 
						statedb := state.New(common.Hash{}, db)
 | 
				
			||||||
	obj := statedb.GetOrNewStateObject(addr)
 | 
						obj := statedb.GetOrNewStateObject(addr)
 | 
				
			||||||
	obj.SetBalance(balance)
 | 
						obj.SetBalance(balance)
 | 
				
			||||||
	statedb.SyncObjects()
 | 
						root, err := statedb.Commit()
 | 
				
			||||||
	statedb.Sync()
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("cannot write state: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	block := types.NewBlock(&types.Header{
 | 
						block := types.NewBlock(&types.Header{
 | 
				
			||||||
		Difficulty: params.GenesisDifficulty,
 | 
							Difficulty: params.GenesisDifficulty,
 | 
				
			||||||
		GasLimit:   params.GenesisGasLimit,
 | 
							GasLimit:   params.GenesisGasLimit,
 | 
				
			||||||
		Root:       statedb.Root(),
 | 
							Root:       root,
 | 
				
			||||||
	}, nil, nil, nil)
 | 
						}, nil, nil, nil)
 | 
				
			||||||
	return block
 | 
						return block
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -218,6 +218,7 @@ func (c *StateObject) ReturnGas(gas, price *big.Int) {}
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) SetGasLimit(gasLimit *big.Int) {
 | 
					func (self *StateObject) SetGasLimit(gasLimit *big.Int) {
 | 
				
			||||||
	self.gasPool = new(big.Int).Set(gasLimit)
 | 
						self.gasPool = new(big.Int).Set(gasLimit)
 | 
				
			||||||
 | 
						self.dirty = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if glog.V(logger.Core) {
 | 
						if glog.V(logger.Core) {
 | 
				
			||||||
		glog.Infof("%x: gas (+ %v)", self.Address(), self.gasPool)
 | 
							glog.Infof("%x: gas (+ %v)", self.Address(), self.gasPool)
 | 
				
			||||||
@@ -228,19 +229,14 @@ func (self *StateObject) SubGas(gas, price *big.Int) error {
 | 
				
			|||||||
	if self.gasPool.Cmp(gas) < 0 {
 | 
						if self.gasPool.Cmp(gas) < 0 {
 | 
				
			||||||
		return GasLimitError(self.gasPool, gas)
 | 
							return GasLimitError(self.gasPool, gas)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	self.gasPool.Sub(self.gasPool, gas)
 | 
						self.gasPool.Sub(self.gasPool, gas)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	rGas := new(big.Int).Set(gas)
 | 
					 | 
				
			||||||
	rGas.Mul(rGas, price)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	self.dirty = true
 | 
						self.dirty = true
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) AddGas(gas, price *big.Int) {
 | 
					func (self *StateObject) AddGas(gas, price *big.Int) {
 | 
				
			||||||
	self.gasPool.Add(self.gasPool, gas)
 | 
						self.gasPool.Add(self.gasPool, gas)
 | 
				
			||||||
 | 
						self.dirty = true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Copy() *StateObject {
 | 
					func (self *StateObject) Copy() *StateObject {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,8 +89,7 @@ func TestNull(t *testing.T) {
 | 
				
			|||||||
	//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
 | 
						//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
 | 
				
			||||||
	var value common.Hash
 | 
						var value common.Hash
 | 
				
			||||||
	state.SetState(address, common.Hash{}, value)
 | 
						state.SetState(address, common.Hash{}, value)
 | 
				
			||||||
	state.SyncIntermediate()
 | 
						state.Commit()
 | 
				
			||||||
	state.Sync()
 | 
					 | 
				
			||||||
	value = state.GetState(address, common.Hash{})
 | 
						value = state.GetState(address, common.Hash{})
 | 
				
			||||||
	if !common.EmptyHash(value) {
 | 
						if !common.EmptyHash(value) {
 | 
				
			||||||
		t.Errorf("expected empty hash. got %x", value)
 | 
							t.Errorf("expected empty hash. got %x", value)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,6 @@ import (
 | 
				
			|||||||
type StateDB struct {
 | 
					type StateDB struct {
 | 
				
			||||||
	db   ethdb.Database
 | 
						db   ethdb.Database
 | 
				
			||||||
	trie *trie.SecureTrie
 | 
						trie *trie.SecureTrie
 | 
				
			||||||
	root common.Hash
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stateObjects map[string]*StateObject
 | 
						stateObjects map[string]*StateObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,7 +55,6 @@ func New(root common.Hash, db ethdb.Database) *StateDB {
 | 
				
			|||||||
		glog.Errorf("can't create state trie with root %x: %v", root[:], err)
 | 
							glog.Errorf("can't create state trie with root %x: %v", root[:], err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &StateDB{
 | 
						return &StateDB{
 | 
				
			||||||
		root:         root,
 | 
					 | 
				
			||||||
		db:           db,
 | 
							db:           db,
 | 
				
			||||||
		trie:         tr,
 | 
							trie:         tr,
 | 
				
			||||||
		stateObjects: make(map[string]*StateObject),
 | 
							stateObjects: make(map[string]*StateObject),
 | 
				
			||||||
@@ -204,7 +202,6 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
 | 
				
			|||||||
	if len(stateObject.CodeHash()) > 0 {
 | 
						if len(stateObject.CodeHash()) > 0 {
 | 
				
			||||||
		self.db.Put(stateObject.CodeHash(), stateObject.code)
 | 
							self.db.Put(stateObject.CodeHash(), stateObject.code)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	addr := stateObject.Address()
 | 
						addr := stateObject.Address()
 | 
				
			||||||
	self.trie.Update(addr[:], stateObject.RlpEncode())
 | 
						self.trie.Update(addr[:], stateObject.RlpEncode())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -215,6 +212,7 @@ func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	addr := stateObject.Address()
 | 
						addr := stateObject.Address()
 | 
				
			||||||
	self.trie.Delete(addr[:])
 | 
						self.trie.Delete(addr[:])
 | 
				
			||||||
 | 
						//delete(self.stateObjects, addr.Str())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Retrieve a state object given my the address. Nil if not found
 | 
					// Retrieve a state object given my the address. Nil if not found
 | 
				
			||||||
@@ -311,67 +309,69 @@ func (self *StateDB) Set(state *StateDB) {
 | 
				
			|||||||
	self.logSize = state.logSize
 | 
						self.logSize = state.logSize
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *StateDB) Root() common.Hash {
 | 
					// IntermediateRoot computes the current root hash of the state trie.
 | 
				
			||||||
 | 
					// It is called in between transactions to get the root hash that
 | 
				
			||||||
 | 
					// goes into transaction receipts.
 | 
				
			||||||
 | 
					func (s *StateDB) IntermediateRoot() common.Hash {
 | 
				
			||||||
 | 
						s.refund = new(big.Int)
 | 
				
			||||||
 | 
						for _, stateObject := range s.stateObjects {
 | 
				
			||||||
 | 
							if stateObject.dirty {
 | 
				
			||||||
 | 
								if stateObject.remove {
 | 
				
			||||||
 | 
									s.DeleteStateObject(stateObject)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									stateObject.Update()
 | 
				
			||||||
 | 
									s.UpdateStateObject(stateObject)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								stateObject.dirty = false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return s.trie.Hash()
 | 
						return s.trie.Hash()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Syncs the trie and all siblings
 | 
					// Commit commits all state changes to the database.
 | 
				
			||||||
func (s *StateDB) Sync() {
 | 
					func (s *StateDB) Commit() (root common.Hash, err error) {
 | 
				
			||||||
	// Sync all nested states
 | 
						return s.commit(s.db)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CommitBatch commits all state changes to a write batch but does not
 | 
				
			||||||
 | 
					// execute the batch. It is used to validate state changes against
 | 
				
			||||||
 | 
					// the root hash stored in a block.
 | 
				
			||||||
 | 
					func (s *StateDB) CommitBatch() (root common.Hash, batch ethdb.Batch) {
 | 
				
			||||||
 | 
						batch = s.db.NewBatch()
 | 
				
			||||||
 | 
						root, _ = s.commit(batch)
 | 
				
			||||||
 | 
						return root, batch
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *StateDB) commit(db trie.DatabaseWriter) (common.Hash, error) {
 | 
				
			||||||
 | 
						s.refund = new(big.Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, stateObject := range s.stateObjects {
 | 
						for _, stateObject := range s.stateObjects {
 | 
				
			||||||
		stateObject.trie.Commit()
 | 
							if stateObject.remove {
 | 
				
			||||||
 | 
								// If the object has been removed, don't bother syncing it
 | 
				
			||||||
 | 
								// and just mark it for deletion in the trie.
 | 
				
			||||||
 | 
								s.DeleteStateObject(stateObject)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// Write any storage changes in the state object to its trie.
 | 
				
			||||||
 | 
								stateObject.Update()
 | 
				
			||||||
 | 
								// Commit the trie of the object to the batch.
 | 
				
			||||||
 | 
								// This updates the trie root internally, so
 | 
				
			||||||
 | 
								// getting the root hash of the storage trie
 | 
				
			||||||
 | 
								// through UpdateStateObject is fast.
 | 
				
			||||||
 | 
								if _, err := stateObject.trie.CommitTo(db); err != nil {
 | 
				
			||||||
 | 
									return common.Hash{}, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								// Update the object in the account trie.
 | 
				
			||||||
	s.trie.Commit()
 | 
								s.UpdateStateObject(stateObject)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	s.Empty()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							stateObject.dirty = false
 | 
				
			||||||
func (self *StateDB) Empty() {
 | 
						}
 | 
				
			||||||
	self.stateObjects = make(map[string]*StateObject)
 | 
						return s.trie.CommitTo(db)
 | 
				
			||||||
	self.refund = new(big.Int)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) Refunds() *big.Int {
 | 
					func (self *StateDB) Refunds() *big.Int {
 | 
				
			||||||
	return self.refund
 | 
						return self.refund
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SyncIntermediate updates the intermediate state and all mid steps
 | 
					 | 
				
			||||||
func (self *StateDB) SyncIntermediate() {
 | 
					 | 
				
			||||||
	self.refund = new(big.Int)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, stateObject := range self.stateObjects {
 | 
					 | 
				
			||||||
		if stateObject.dirty {
 | 
					 | 
				
			||||||
			if stateObject.remove {
 | 
					 | 
				
			||||||
				self.DeleteStateObject(stateObject)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				stateObject.Update()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				self.UpdateStateObject(stateObject)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			stateObject.dirty = false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SyncObjects syncs the changed objects to the trie
 | 
					 | 
				
			||||||
func (self *StateDB) SyncObjects() {
 | 
					 | 
				
			||||||
	self.trie, _ = trie.NewSecure(self.root, self.db)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	self.refund = new(big.Int)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, stateObject := range self.stateObjects {
 | 
					 | 
				
			||||||
		if stateObject.remove {
 | 
					 | 
				
			||||||
			self.DeleteStateObject(stateObject)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			stateObject.Update()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			self.UpdateStateObject(stateObject)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		stateObject.dirty = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Debug stuff
 | 
					// Debug stuff
 | 
				
			||||||
func (self *StateDB) CreateOutputForDiff() {
 | 
					func (self *StateDB) CreateOutputForDiff() {
 | 
				
			||||||
	for _, stateObject := range self.stateObjects {
 | 
						for _, stateObject := range self.stateObjects {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -266,7 +266,6 @@ func (self *worker) wait() {
 | 
				
			|||||||
			block := result.Block
 | 
								block := result.Block
 | 
				
			||||||
			work := result.Work
 | 
								work := result.Work
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			work.state.Sync()
 | 
					 | 
				
			||||||
			if self.fullValidation {
 | 
								if self.fullValidation {
 | 
				
			||||||
				if _, err := self.chain.InsertChain(types.Blocks{block}); err != nil {
 | 
									if _, err := self.chain.InsertChain(types.Blocks{block}); err != nil {
 | 
				
			||||||
					glog.V(logger.Error).Infoln("mining err", err)
 | 
										glog.V(logger.Error).Infoln("mining err", err)
 | 
				
			||||||
@@ -274,6 +273,7 @@ func (self *worker) wait() {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				go self.mux.Post(core.NewMinedBlockEvent{block})
 | 
									go self.mux.Post(core.NewMinedBlockEvent{block})
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
 | 
									work.state.Commit()
 | 
				
			||||||
				parent := self.chain.GetBlock(block.ParentHash())
 | 
									parent := self.chain.GetBlock(block.ParentHash())
 | 
				
			||||||
				if parent == nil {
 | 
									if parent == nil {
 | 
				
			||||||
					glog.V(logger.Error).Infoln("Invalid block found during mining")
 | 
										glog.V(logger.Error).Infoln("Invalid block found during mining")
 | 
				
			||||||
@@ -528,8 +528,7 @@ func (self *worker) commitNewWork() {
 | 
				
			|||||||
	if atomic.LoadInt32(&self.mining) == 1 {
 | 
						if atomic.LoadInt32(&self.mining) == 1 {
 | 
				
			||||||
		// commit state root after all state transitions.
 | 
							// commit state root after all state transitions.
 | 
				
			||||||
		core.AccumulateRewards(work.state, header, uncles)
 | 
							core.AccumulateRewards(work.state, header, uncles)
 | 
				
			||||||
		work.state.SyncObjects()
 | 
							header.Root = work.state.IntermediateRoot()
 | 
				
			||||||
		header.Root = work.state.Root()
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// create the new block whose nonce will be mined.
 | 
						// create the new block whose nonce will be mined.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -253,13 +253,13 @@ func (t *BlockTest) InsertPreState(ethereum *eth.Ethereum) (*state.StateDB, erro
 | 
				
			|||||||
			statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v))
 | 
								statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// sync objects to trie
 | 
					 | 
				
			||||||
	statedb.SyncObjects()
 | 
					 | 
				
			||||||
	// sync trie to disk
 | 
					 | 
				
			||||||
	statedb.Sync()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) {
 | 
						root, err := statedb.Commit()
 | 
				
			||||||
		return nil, fmt.Errorf("computed state root does not match genesis block %x %x", t.Genesis.Root().Bytes()[:4], statedb.Root().Bytes()[:4])
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("error writing state: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if t.Genesis.Root() != root {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("computed state root does not match genesis block: genesis=%x computed=%x", t.Genesis.Root().Bytes()[:4], root.Bytes()[:4])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return statedb, nil
 | 
						return statedb, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -200,9 +200,9 @@ func runStateTest(test VmTest) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	statedb.Sync()
 | 
						root, _ := statedb.Commit()
 | 
				
			||||||
	if common.HexToHash(test.PostStateRoot) != statedb.Root() {
 | 
						if common.HexToHash(test.PostStateRoot) != root {
 | 
				
			||||||
		return fmt.Errorf("Post state root error. Expected %s, got %x", test.PostStateRoot, statedb.Root())
 | 
							return fmt.Errorf("Post state root error. Expected %s, got %x", test.PostStateRoot, root)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// check logs
 | 
						// check logs
 | 
				
			||||||
@@ -246,7 +246,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
 | 
				
			|||||||
	if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) {
 | 
						if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) {
 | 
				
			||||||
		statedb.Set(snapshot)
 | 
							statedb.Set(snapshot)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	statedb.SyncObjects()
 | 
						statedb.Commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret, vmenv.state.Logs(), vmenv.Gas, err
 | 
						return ret, vmenv.state.Logs(), vmenv.Gas, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user