Merge pull request #3038 from fjl/release/1.4
[release/1.4.13] core/state: track all accounts in canon state
This commit is contained in:
		@@ -95,10 +95,11 @@ type BlockChain struct {
 | 
				
			|||||||
	currentBlock     *types.Block // Current head of the block chain
 | 
						currentBlock     *types.Block // Current head of the block chain
 | 
				
			||||||
	currentFastBlock *types.Block // Current head of the fast-sync chain (may be above the block chain!)
 | 
						currentFastBlock *types.Block // Current head of the fast-sync chain (may be above the block chain!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bodyCache    *lru.Cache // Cache for the most recent block bodies
 | 
						stateCache   *state.StateDB // State database to reuse between imports (contains state cache)
 | 
				
			||||||
	bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format
 | 
						bodyCache    *lru.Cache     // Cache for the most recent block bodies
 | 
				
			||||||
	blockCache   *lru.Cache // Cache for the most recent entire blocks
 | 
						bodyRLPCache *lru.Cache     // Cache for the most recent block bodies in RLP encoded format
 | 
				
			||||||
	futureBlocks *lru.Cache // future blocks are blocks added for later processing
 | 
						blockCache   *lru.Cache     // Cache for the most recent entire blocks
 | 
				
			||||||
 | 
						futureBlocks *lru.Cache     // future blocks are blocks added for later processing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	quit    chan struct{} // blockchain quit channel
 | 
						quit    chan struct{} // blockchain quit channel
 | 
				
			||||||
	running int32         // running must be called atomically
 | 
						running int32         // running must be called atomically
 | 
				
			||||||
@@ -198,11 +199,18 @@ func (self *BlockChain) loadLastState() error {
 | 
				
			|||||||
			self.currentFastBlock = block
 | 
								self.currentFastBlock = block
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// Initialize a statedb cache to ensure singleton account bloom filter generation
 | 
				
			||||||
 | 
						statedb, err := state.New(self.currentBlock.Root(), self.chainDb)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						self.stateCache = statedb
 | 
				
			||||||
 | 
						self.stateCache.GetAccount(common.Address{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Issue a status log and return
 | 
						// Issue a status log and return
 | 
				
			||||||
	headerTd := self.GetTd(self.hc.CurrentHeader().Hash())
 | 
						headerTd := self.GetTd(self.hc.CurrentHeader().Hash())
 | 
				
			||||||
	blockTd := self.GetTd(self.currentBlock.Hash())
 | 
						blockTd := self.GetTd(self.currentBlock.Hash())
 | 
				
			||||||
	fastTd := self.GetTd(self.currentFastBlock.Hash())
 | 
						fastTd := self.GetTd(self.currentFastBlock.Hash())
 | 
				
			||||||
 | 
					 | 
				
			||||||
	glog.V(logger.Info).Infof("Last header: #%d [%x…] TD=%v", self.hc.CurrentHeader().Number, self.hc.CurrentHeader().Hash().Bytes()[:4], headerTd)
 | 
						glog.V(logger.Info).Infof("Last header: #%d [%x…] TD=%v", self.hc.CurrentHeader().Number, self.hc.CurrentHeader().Hash().Bytes()[:4], headerTd)
 | 
				
			||||||
	glog.V(logger.Info).Infof("Last block: #%d [%x…] TD=%v", self.currentBlock.Number(), self.currentBlock.Hash().Bytes()[:4], blockTd)
 | 
						glog.V(logger.Info).Infof("Last block: #%d [%x…] TD=%v", self.currentBlock.Number(), self.currentBlock.Hash().Bytes()[:4], blockTd)
 | 
				
			||||||
	glog.V(logger.Info).Infof("Fast block: #%d [%x…] TD=%v", self.currentFastBlock.Number(), self.currentFastBlock.Hash().Bytes()[:4], fastTd)
 | 
						glog.V(logger.Info).Infof("Fast block: #%d [%x…] TD=%v", self.currentFastBlock.Number(), self.currentFastBlock.Hash().Bytes()[:4], fastTd)
 | 
				
			||||||
@@ -817,7 +825,6 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
 | 
				
			|||||||
		tstart        = time.Now()
 | 
							tstart        = time.Now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nonceChecked = make([]bool, len(chain))
 | 
							nonceChecked = make([]bool, len(chain))
 | 
				
			||||||
		statedb      *state.StateDB
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start the parallel nonce verifier.
 | 
						// Start the parallel nonce verifier.
 | 
				
			||||||
@@ -884,29 +891,30 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// Create a new statedb using the parent block and report an
 | 
							// Create a new statedb using the parent block and report an
 | 
				
			||||||
		// error if it fails.
 | 
							// error if it fails.
 | 
				
			||||||
		if statedb == nil {
 | 
							switch {
 | 
				
			||||||
			statedb, err = state.New(self.GetBlock(block.ParentHash()).Root(), self.chainDb)
 | 
							case i == 0:
 | 
				
			||||||
		} else {
 | 
								err = self.stateCache.Reset(self.GetBlock(block.ParentHash()).Root())
 | 
				
			||||||
			err = statedb.Reset(chain[i-1].Root())
 | 
							default:
 | 
				
			||||||
 | 
								err = self.stateCache.Reset(chain[i-1].Root())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			reportBlock(block, err)
 | 
								reportBlock(block, err)
 | 
				
			||||||
			return i, err
 | 
								return i, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Process block using the parent state as reference point.
 | 
							// Process block using the parent state as reference point.
 | 
				
			||||||
		receipts, logs, usedGas, err := self.processor.Process(block, statedb, self.config.VmConfig)
 | 
							receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, self.config.VmConfig)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			reportBlock(block, err)
 | 
								reportBlock(block, err)
 | 
				
			||||||
			return i, err
 | 
								return i, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Validate the state using the default validator
 | 
							// Validate the state using the default validator
 | 
				
			||||||
		err = self.Validator().ValidateState(block, self.GetBlock(block.ParentHash()), statedb, receipts, usedGas)
 | 
							err = self.Validator().ValidateState(block, self.GetBlock(block.ParentHash()), self.stateCache, receipts, usedGas)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			reportBlock(block, err)
 | 
								reportBlock(block, err)
 | 
				
			||||||
			return i, err
 | 
								return i, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Write state changes to database
 | 
							// Write state changes to database
 | 
				
			||||||
		_, err = statedb.Commit()
 | 
							_, err = self.stateCache.Commit()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return i, err
 | 
								return i, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,7 @@ func ExampleGenerateChain() {
 | 
				
			|||||||
	evmux := &event.TypeMux{}
 | 
						evmux := &event.TypeMux{}
 | 
				
			||||||
	blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
 | 
						blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
 | 
				
			||||||
	if i, err := blockchain.InsertChain(chain); err != nil {
 | 
						if i, err := blockchain.InsertChain(chain); err != nil {
 | 
				
			||||||
		fmt.Printf("insert error (block %d): %v\n", i, err)
 | 
							fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,9 +21,10 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/rlp"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Account struct {
 | 
					type DumpAccount struct {
 | 
				
			||||||
	Balance  string            `json:"balance"`
 | 
						Balance  string            `json:"balance"`
 | 
				
			||||||
	Nonce    uint64            `json:"nonce"`
 | 
						Nonce    uint64            `json:"nonce"`
 | 
				
			||||||
	Root     string            `json:"root"`
 | 
						Root     string            `json:"root"`
 | 
				
			||||||
@@ -32,40 +33,41 @@ type Account struct {
 | 
				
			|||||||
	Storage  map[string]string `json:"storage"`
 | 
						Storage  map[string]string `json:"storage"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type World struct {
 | 
					type Dump struct {
 | 
				
			||||||
	Root     string             `json:"root"`
 | 
						Root     string                 `json:"root"`
 | 
				
			||||||
	Accounts map[string]Account `json:"accounts"`
 | 
						Accounts map[string]DumpAccount `json:"accounts"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) RawDump() World {
 | 
					func (self *StateDB) RawDump() Dump {
 | 
				
			||||||
	world := World{
 | 
						dump := Dump{
 | 
				
			||||||
		Root:     common.Bytes2Hex(self.trie.Root()),
 | 
							Root:     common.Bytes2Hex(self.trie.Root()),
 | 
				
			||||||
		Accounts: make(map[string]Account),
 | 
							Accounts: make(map[string]DumpAccount),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	it := self.trie.Iterator()
 | 
						it := self.trie.Iterator()
 | 
				
			||||||
	for it.Next() {
 | 
						for it.Next() {
 | 
				
			||||||
		addr := self.trie.GetKey(it.Key)
 | 
							addr := self.trie.GetKey(it.Key)
 | 
				
			||||||
		stateObject, err := DecodeObject(common.BytesToAddress(addr), self.db, it.Value)
 | 
							var data Account
 | 
				
			||||||
		if err != nil {
 | 
							if err := rlp.DecodeBytes(it.Value, &data); err != nil {
 | 
				
			||||||
			panic(err)
 | 
								panic(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		account := Account{
 | 
							obj := NewObject(common.BytesToAddress(addr), data, nil)
 | 
				
			||||||
			Balance:  stateObject.balance.String(),
 | 
							account := DumpAccount{
 | 
				
			||||||
			Nonce:    stateObject.nonce,
 | 
								Balance:  data.Balance.String(),
 | 
				
			||||||
			Root:     common.Bytes2Hex(stateObject.Root()),
 | 
								Nonce:    data.Nonce,
 | 
				
			||||||
			CodeHash: common.Bytes2Hex(stateObject.codeHash),
 | 
								Root:     common.Bytes2Hex(data.Root[:]),
 | 
				
			||||||
			Code:     common.Bytes2Hex(stateObject.Code()),
 | 
								CodeHash: common.Bytes2Hex(data.CodeHash),
 | 
				
			||||||
 | 
								Code:     common.Bytes2Hex(obj.Code(self.db)),
 | 
				
			||||||
			Storage:  make(map[string]string),
 | 
								Storage:  make(map[string]string),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		storageIt := stateObject.trie.Iterator()
 | 
							storageIt := obj.getTrie(self.db).Iterator()
 | 
				
			||||||
		for storageIt.Next() {
 | 
							for storageIt.Next() {
 | 
				
			||||||
			account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value)
 | 
								account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		world.Accounts[common.Bytes2Hex(addr)] = account
 | 
							dump.Accounts[common.Bytes2Hex(addr)] = account
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return world
 | 
						return dump
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) Dump() []byte {
 | 
					func (self *StateDB) Dump() []byte {
 | 
				
			||||||
@@ -76,12 +78,3 @@ func (self *StateDB) Dump() []byte {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return json
 | 
						return json
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Debug stuff
 | 
					 | 
				
			||||||
func (self *StateObject) CreateOutputForDiff() {
 | 
					 | 
				
			||||||
	fmt.Printf("%x %x %x %x\n", self.Address(), self.Root(), self.balance.Bytes(), self.nonce)
 | 
					 | 
				
			||||||
	it := self.trie.Iterator()
 | 
					 | 
				
			||||||
	for it.Next() {
 | 
					 | 
				
			||||||
		fmt.Printf("%x %x\n", it.Key, it.Value)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,14 +33,14 @@ type ManagedState struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	mu sync.RWMutex
 | 
						mu sync.RWMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	accounts map[string]*account
 | 
						accounts map[common.Address]*account
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ManagedState returns a new managed state with the statedb as it's backing layer
 | 
					// ManagedState returns a new managed state with the statedb as it's backing layer
 | 
				
			||||||
func ManageState(statedb *StateDB) *ManagedState {
 | 
					func ManageState(statedb *StateDB) *ManagedState {
 | 
				
			||||||
	return &ManagedState{
 | 
						return &ManagedState{
 | 
				
			||||||
		StateDB:  statedb.Copy(),
 | 
							StateDB:  statedb.Copy(),
 | 
				
			||||||
		accounts: make(map[string]*account),
 | 
							accounts: make(map[common.Address]*account),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -103,7 +103,7 @@ func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) {
 | 
				
			|||||||
	so := ms.GetOrNewStateObject(addr)
 | 
						so := ms.GetOrNewStateObject(addr)
 | 
				
			||||||
	so.SetNonce(nonce)
 | 
						so.SetNonce(nonce)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ms.accounts[addr.Str()] = newAccount(so)
 | 
						ms.accounts[addr] = newAccount(so)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HasAccount returns whether the given address is managed or not
 | 
					// HasAccount returns whether the given address is managed or not
 | 
				
			||||||
@@ -114,29 +114,28 @@ func (ms *ManagedState) HasAccount(addr common.Address) bool {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (ms *ManagedState) hasAccount(addr common.Address) bool {
 | 
					func (ms *ManagedState) hasAccount(addr common.Address) bool {
 | 
				
			||||||
	_, ok := ms.accounts[addr.Str()]
 | 
						_, ok := ms.accounts[addr]
 | 
				
			||||||
	return ok
 | 
						return ok
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// populate the managed state
 | 
					// populate the managed state
 | 
				
			||||||
func (ms *ManagedState) getAccount(addr common.Address) *account {
 | 
					func (ms *ManagedState) getAccount(addr common.Address) *account {
 | 
				
			||||||
	straddr := addr.Str()
 | 
						if account, ok := ms.accounts[addr]; !ok {
 | 
				
			||||||
	if account, ok := ms.accounts[straddr]; !ok {
 | 
					 | 
				
			||||||
		so := ms.GetOrNewStateObject(addr)
 | 
							so := ms.GetOrNewStateObject(addr)
 | 
				
			||||||
		ms.accounts[straddr] = newAccount(so)
 | 
							ms.accounts[addr] = newAccount(so)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// Always make sure the state account nonce isn't actually higher
 | 
							// Always make sure the state account nonce isn't actually higher
 | 
				
			||||||
		// than the tracked one.
 | 
							// than the tracked one.
 | 
				
			||||||
		so := ms.StateDB.GetStateObject(addr)
 | 
							so := ms.StateDB.GetStateObject(addr)
 | 
				
			||||||
		if so != nil && uint64(len(account.nonces))+account.nstart < so.nonce {
 | 
							if so != nil && uint64(len(account.nonces))+account.nstart < so.Nonce() {
 | 
				
			||||||
			ms.accounts[straddr] = newAccount(so)
 | 
								ms.accounts[addr] = newAccount(so)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ms.accounts[straddr]
 | 
						return ms.accounts[addr]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newAccount(so *StateObject) *account {
 | 
					func newAccount(so *StateObject) *account {
 | 
				
			||||||
	return &account{so, so.nonce, nil}
 | 
						return &account{so, so.Nonce(), nil}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,11 +29,12 @@ func create() (*ManagedState, *account) {
 | 
				
			|||||||
	db, _ := ethdb.NewMemDatabase()
 | 
						db, _ := ethdb.NewMemDatabase()
 | 
				
			||||||
	statedb, _ := New(common.Hash{}, db)
 | 
						statedb, _ := New(common.Hash{}, db)
 | 
				
			||||||
	ms := ManageState(statedb)
 | 
						ms := ManageState(statedb)
 | 
				
			||||||
	so := &StateObject{address: addr, nonce: 100}
 | 
						so := &StateObject{address: addr}
 | 
				
			||||||
	ms.StateDB.stateObjects[addr.Str()] = so
 | 
						so.SetNonce(100)
 | 
				
			||||||
	ms.accounts[addr.Str()] = newAccount(so)
 | 
						ms.StateDB.stateObjects[addr] = so
 | 
				
			||||||
 | 
						ms.accounts[addr] = newAccount(so)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ms, ms.accounts[addr.Str()]
 | 
						return ms, ms.accounts[addr]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewNonce(t *testing.T) {
 | 
					func TestNewNonce(t *testing.T) {
 | 
				
			||||||
@@ -92,7 +93,7 @@ func TestRemoteNonceChange(t *testing.T) {
 | 
				
			|||||||
	account.nonces = append(account.nonces, nn...)
 | 
						account.nonces = append(account.nonces, nn...)
 | 
				
			||||||
	nonce := ms.NewNonce(addr)
 | 
						nonce := ms.NewNonce(addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ms.StateDB.stateObjects[addr.Str()].nonce = 200
 | 
						ms.StateDB.stateObjects[addr].data.Nonce = 200
 | 
				
			||||||
	nonce = ms.NewNonce(addr)
 | 
						nonce = ms.NewNonce(addr)
 | 
				
			||||||
	if nonce != 200 {
 | 
						if nonce != 200 {
 | 
				
			||||||
		t.Error("expected nonce after remote update to be", 201, "got", nonce)
 | 
							t.Error("expected nonce after remote update to be", 201, "got", nonce)
 | 
				
			||||||
@@ -100,7 +101,7 @@ func TestRemoteNonceChange(t *testing.T) {
 | 
				
			|||||||
	ms.NewNonce(addr)
 | 
						ms.NewNonce(addr)
 | 
				
			||||||
	ms.NewNonce(addr)
 | 
						ms.NewNonce(addr)
 | 
				
			||||||
	ms.NewNonce(addr)
 | 
						ms.NewNonce(addr)
 | 
				
			||||||
	ms.StateDB.stateObjects[addr.Str()].nonce = 200
 | 
						ms.StateDB.stateObjects[addr].data.Nonce = 200
 | 
				
			||||||
	nonce = ms.NewNonce(addr)
 | 
						nonce = ms.NewNonce(addr)
 | 
				
			||||||
	if nonce != 204 {
 | 
						if nonce != 204 {
 | 
				
			||||||
		t.Error("expected nonce after remote update to be", 201, "got", nonce)
 | 
							t.Error("expected nonce after remote update to be", 201, "got", nonce)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,110 +57,163 @@ func (self Storage) Copy() Storage {
 | 
				
			|||||||
	return cpy
 | 
						return cpy
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StateObject represents an Ethereum account which is being modified.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The usage pattern is as follows:
 | 
				
			||||||
 | 
					// First you need to obtain a state object.
 | 
				
			||||||
 | 
					// Account values can be accessed and modified through the object.
 | 
				
			||||||
 | 
					// Finally, call CommitTrie to write the modified storage trie into a database.
 | 
				
			||||||
type StateObject struct {
 | 
					type StateObject struct {
 | 
				
			||||||
	db   trie.Database // State database for storing state changes
 | 
						address common.Address // Ethereum address of this account
 | 
				
			||||||
	trie *trie.SecureTrie
 | 
						data    Account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Address belonging to this account
 | 
						// DB error.
 | 
				
			||||||
	address common.Address
 | 
						// State objects are used by the consensus core and VM which are
 | 
				
			||||||
	// The balance of the account
 | 
						// unable to deal with database-level errors. Any error that occurs
 | 
				
			||||||
	balance *big.Int
 | 
						// during a database read is memoized here and will eventually be returned
 | 
				
			||||||
	// The nonce of the account
 | 
						// by StateDB.Commit.
 | 
				
			||||||
	nonce uint64
 | 
						dbErr error
 | 
				
			||||||
	// The code hash if code is present (i.e. a contract)
 | 
					 | 
				
			||||||
	codeHash []byte
 | 
					 | 
				
			||||||
	// The code for this account
 | 
					 | 
				
			||||||
	code Code
 | 
					 | 
				
			||||||
	// Temporarily initialisation code
 | 
					 | 
				
			||||||
	initCode Code
 | 
					 | 
				
			||||||
	// Cached storage (flushed when updated)
 | 
					 | 
				
			||||||
	storage Storage
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Mark for deletion
 | 
						// Write caches.
 | 
				
			||||||
 | 
						trie    *trie.SecureTrie // storage trie, which becomes non-nil on first access
 | 
				
			||||||
 | 
						code    Code             // contract bytecode, which gets set when code is loaded
 | 
				
			||||||
 | 
						storage Storage          // Cached storage (flushed when updated)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Cache flags.
 | 
				
			||||||
	// When an object is marked for deletion it will be delete from the trie
 | 
						// When an object is marked for deletion it will be delete from the trie
 | 
				
			||||||
	// during the "update" phase of the state transition
 | 
						// during the "update" phase of the state transition
 | 
				
			||||||
	remove  bool
 | 
						dirtyCode bool // true if the code was updated
 | 
				
			||||||
	deleted bool
 | 
						remove    bool
 | 
				
			||||||
	dirty   bool
 | 
						deleted   bool
 | 
				
			||||||
 | 
						onDirty   func(addr common.Address) // Callback method to mark a state object newly dirty
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewStateObject(address common.Address, db trie.Database) *StateObject {
 | 
					// Account is the Ethereum consensus representation of accounts.
 | 
				
			||||||
	object := &StateObject{
 | 
					// These objects are stored in the main account trie.
 | 
				
			||||||
		db:       db,
 | 
					type Account struct {
 | 
				
			||||||
		address:  address,
 | 
						Nonce    uint64
 | 
				
			||||||
		balance:  new(big.Int),
 | 
						Balance  *big.Int
 | 
				
			||||||
		dirty:    true,
 | 
						Root     common.Hash // merkle root of the storage trie
 | 
				
			||||||
		codeHash: emptyCodeHash,
 | 
						CodeHash []byte
 | 
				
			||||||
		storage:  make(Storage),
 | 
					
 | 
				
			||||||
 | 
						codeSize *int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewObject creates a state object.
 | 
				
			||||||
 | 
					func NewObject(address common.Address, data Account, onDirty func(addr common.Address)) *StateObject {
 | 
				
			||||||
 | 
						if data.Balance == nil {
 | 
				
			||||||
 | 
							data.Balance = new(big.Int)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if data.CodeHash == nil {
 | 
				
			||||||
 | 
							data.CodeHash = emptyCodeHash
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &StateObject{address: address, data: data, storage: make(Storage), onDirty: onDirty}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EncodeRLP implements rlp.Encoder.
 | 
				
			||||||
 | 
					func (c *StateObject) EncodeRLP(w io.Writer) error {
 | 
				
			||||||
 | 
						return rlp.Encode(w, c.data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// setError remembers the first non-nil error it is called with.
 | 
				
			||||||
 | 
					func (self *StateObject) setError(err error) {
 | 
				
			||||||
 | 
						if self.dbErr == nil {
 | 
				
			||||||
 | 
							self.dbErr = err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	object.trie, _ = trie.NewSecure(common.Hash{}, db)
 | 
					 | 
				
			||||||
	return object
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) MarkForDeletion() {
 | 
					func (self *StateObject) MarkForDeletion() {
 | 
				
			||||||
	self.remove = true
 | 
						self.remove = true
 | 
				
			||||||
	self.dirty = true
 | 
						if self.onDirty != nil {
 | 
				
			||||||
 | 
							self.onDirty(self.Address())
 | 
				
			||||||
 | 
							self.onDirty = nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if glog.V(logger.Core) {
 | 
						if glog.V(logger.Core) {
 | 
				
			||||||
		glog.Infof("%x: #%d %v X\n", self.Address(), self.nonce, self.balance)
 | 
							glog.Infof("%x: #%d %v X\n", self.Address(), self.Nonce(), self.Balance())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *StateObject) getAddr(addr common.Hash) common.Hash {
 | 
					func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie {
 | 
				
			||||||
	var ret []byte
 | 
						if c.trie == nil {
 | 
				
			||||||
	rlp.DecodeBytes(c.trie.Get(addr[:]), &ret)
 | 
							var err error
 | 
				
			||||||
	return common.BytesToHash(ret)
 | 
							c.trie, err = trie.NewSecure(c.data.Root, db)
 | 
				
			||||||
}
 | 
							if err != nil {
 | 
				
			||||||
 | 
								c.trie, _ = trie.NewSecure(common.Hash{}, db)
 | 
				
			||||||
func (c *StateObject) setAddr(addr, value common.Hash) {
 | 
								c.setError(fmt.Errorf("can't create storage trie: %v", err))
 | 
				
			||||||
	v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		// if RLPing failed we better panic and not fail silently. This would be considered a consensus issue
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	c.trie.Update(addr[:], v)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (self *StateObject) Storage() Storage {
 | 
					 | 
				
			||||||
	return self.storage
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (self *StateObject) GetState(key common.Hash) common.Hash {
 | 
					 | 
				
			||||||
	value, exists := self.storage[key]
 | 
					 | 
				
			||||||
	if !exists {
 | 
					 | 
				
			||||||
		value = self.getAddr(key)
 | 
					 | 
				
			||||||
		if (value != common.Hash{}) {
 | 
					 | 
				
			||||||
			self.storage[key] = value
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return c.trie
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetState returns a value in account storage.
 | 
				
			||||||
 | 
					func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash {
 | 
				
			||||||
 | 
						value, exists := self.storage[key]
 | 
				
			||||||
 | 
						if exists {
 | 
				
			||||||
 | 
							return value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Load from DB in case it is missing.
 | 
				
			||||||
 | 
						tr := self.getTrie(db)
 | 
				
			||||||
 | 
						var ret []byte
 | 
				
			||||||
 | 
						rlp.DecodeBytes(tr.Get(key[:]), &ret)
 | 
				
			||||||
 | 
						value = common.BytesToHash(ret)
 | 
				
			||||||
 | 
						if (value != common.Hash{}) {
 | 
				
			||||||
 | 
							self.storage[key] = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return value
 | 
						return value
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetState updates a value in account storage.
 | 
				
			||||||
func (self *StateObject) SetState(key, value common.Hash) {
 | 
					func (self *StateObject) SetState(key, value common.Hash) {
 | 
				
			||||||
	self.storage[key] = value
 | 
						self.storage[key] = value
 | 
				
			||||||
	self.dirty = true
 | 
						if self.onDirty != nil {
 | 
				
			||||||
 | 
							self.onDirty(self.Address())
 | 
				
			||||||
 | 
							self.onDirty = nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Update updates the current cached storage to the trie
 | 
					// updateTrie writes cached storage modifications into the object's storage trie.
 | 
				
			||||||
func (self *StateObject) Update() {
 | 
					func (self *StateObject) updateTrie(db trie.Database) {
 | 
				
			||||||
 | 
						tr := self.getTrie(db)
 | 
				
			||||||
	for key, value := range self.storage {
 | 
						for key, value := range self.storage {
 | 
				
			||||||
		if (value == common.Hash{}) {
 | 
							if (value == common.Hash{}) {
 | 
				
			||||||
			self.trie.Delete(key[:])
 | 
								tr.Delete(key[:])
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		self.setAddr(key, value)
 | 
							// Encoding []byte cannot fail, ok to ignore the error.
 | 
				
			||||||
 | 
							v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
 | 
				
			||||||
 | 
							tr.Update(key[:], v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateRoot sets the trie root to the current root hash of
 | 
				
			||||||
 | 
					func (self *StateObject) UpdateRoot(db trie.Database) {
 | 
				
			||||||
 | 
						self.updateTrie(db)
 | 
				
			||||||
 | 
						self.data.Root = self.trie.Hash()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CommitTrie the storage trie of the object to dwb.
 | 
				
			||||||
 | 
					// This updates the trie root.
 | 
				
			||||||
 | 
					func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) error {
 | 
				
			||||||
 | 
						self.updateTrie(db)
 | 
				
			||||||
 | 
						if self.dbErr != nil {
 | 
				
			||||||
 | 
							fmt.Println("dbErr:", self.dbErr)
 | 
				
			||||||
 | 
							return self.dbErr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						root, err := self.trie.CommitTo(dbw)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							self.data.Root = root
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *StateObject) AddBalance(amount *big.Int) {
 | 
					func (c *StateObject) AddBalance(amount *big.Int) {
 | 
				
			||||||
	if amount.Cmp(common.Big0) == 0 {
 | 
						if amount.Cmp(common.Big0) == 0 {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.SetBalance(new(big.Int).Add(c.balance, amount))
 | 
						c.SetBalance(new(big.Int).Add(c.Balance(), amount))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if glog.V(logger.Core) {
 | 
						if glog.V(logger.Core) {
 | 
				
			||||||
		glog.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
 | 
							glog.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce(), c.Balance(), amount)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -168,38 +221,32 @@ func (c *StateObject) SubBalance(amount *big.Int) {
 | 
				
			|||||||
	if amount.Cmp(common.Big0) == 0 {
 | 
						if amount.Cmp(common.Big0) == 0 {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.SetBalance(new(big.Int).Sub(c.balance, amount))
 | 
						c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if glog.V(logger.Core) {
 | 
						if glog.V(logger.Core) {
 | 
				
			||||||
		glog.Infof("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
 | 
							glog.Infof("%x: #%d %v (- %v)\n", c.Address(), c.Nonce(), c.Balance(), amount)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *StateObject) SetBalance(amount *big.Int) {
 | 
					func (self *StateObject) SetBalance(amount *big.Int) {
 | 
				
			||||||
	c.balance = amount
 | 
						self.data.Balance = amount
 | 
				
			||||||
	c.dirty = true
 | 
						if self.onDirty != nil {
 | 
				
			||||||
}
 | 
							self.onDirty(self.Address())
 | 
				
			||||||
 | 
							self.onDirty = nil
 | 
				
			||||||
func (c *StateObject) St() Storage {
 | 
						}
 | 
				
			||||||
	return c.storage
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Return the gas back to the origin. Used by the Virtual machine or Closures
 | 
					// Return the gas back to the origin. Used by the Virtual machine or Closures
 | 
				
			||||||
func (c *StateObject) ReturnGas(gas, price *big.Int) {}
 | 
					func (c *StateObject) ReturnGas(gas, price *big.Int) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Copy() *StateObject {
 | 
					func (self *StateObject) Copy(db trie.Database, onDirty func(addr common.Address)) *StateObject {
 | 
				
			||||||
	stateObject := NewStateObject(self.Address(), self.db)
 | 
						stateObject := NewObject(self.address, self.data, onDirty)
 | 
				
			||||||
	stateObject.balance.Set(self.balance)
 | 
					 | 
				
			||||||
	stateObject.codeHash = common.CopyBytes(self.codeHash)
 | 
					 | 
				
			||||||
	stateObject.nonce = self.nonce
 | 
					 | 
				
			||||||
	stateObject.trie = self.trie
 | 
						stateObject.trie = self.trie
 | 
				
			||||||
	stateObject.code = self.code
 | 
						stateObject.code = self.code
 | 
				
			||||||
	stateObject.initCode = common.CopyBytes(self.initCode)
 | 
					 | 
				
			||||||
	stateObject.storage = self.storage.Copy()
 | 
						stateObject.storage = self.storage.Copy()
 | 
				
			||||||
	stateObject.remove = self.remove
 | 
						stateObject.remove = self.remove
 | 
				
			||||||
	stateObject.dirty = self.dirty
 | 
						stateObject.dirtyCode = self.dirtyCode
 | 
				
			||||||
	stateObject.deleted = self.deleted
 | 
						stateObject.deleted = self.deleted
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return stateObject
 | 
						return stateObject
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -207,40 +254,66 @@ func (self *StateObject) Copy() *StateObject {
 | 
				
			|||||||
// Attribute accessors
 | 
					// Attribute accessors
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Balance() *big.Int {
 | 
					 | 
				
			||||||
	return self.balance
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Returns the address of the contract/account
 | 
					// Returns the address of the contract/account
 | 
				
			||||||
func (c *StateObject) Address() common.Address {
 | 
					func (c *StateObject) Address() common.Address {
 | 
				
			||||||
	return c.address
 | 
						return c.address
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Trie() *trie.SecureTrie {
 | 
					// Code returns the contract code associated with this object, if any.
 | 
				
			||||||
	return self.trie
 | 
					func (self *StateObject) Code(db trie.Database) []byte {
 | 
				
			||||||
 | 
						if self.code != nil {
 | 
				
			||||||
 | 
							return self.code
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if bytes.Equal(self.CodeHash(), emptyCodeHash) {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						code, err := db.Get(self.CodeHash())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						self.code = code
 | 
				
			||||||
 | 
						return code
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Root() []byte {
 | 
					// CodeSize returns the size of the contract code associated with this object.
 | 
				
			||||||
	return self.trie.Root()
 | 
					func (self *StateObject) CodeSize(db trie.Database) int {
 | 
				
			||||||
}
 | 
						if self.data.codeSize == nil {
 | 
				
			||||||
 | 
							self.data.codeSize = new(int)
 | 
				
			||||||
func (self *StateObject) Code() []byte {
 | 
							*self.data.codeSize = len(self.Code(db))
 | 
				
			||||||
	return self.code
 | 
						}
 | 
				
			||||||
 | 
						return *self.data.codeSize
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) SetCode(code []byte) {
 | 
					func (self *StateObject) SetCode(code []byte) {
 | 
				
			||||||
	self.code = code
 | 
						self.code = code
 | 
				
			||||||
	self.codeHash = crypto.Keccak256(code)
 | 
						self.data.CodeHash = crypto.Keccak256(code)
 | 
				
			||||||
	self.dirty = true
 | 
						self.data.codeSize = new(int)
 | 
				
			||||||
 | 
						*self.data.codeSize = len(code)
 | 
				
			||||||
 | 
						self.dirtyCode = true
 | 
				
			||||||
 | 
						if self.onDirty != nil {
 | 
				
			||||||
 | 
							self.onDirty(self.Address())
 | 
				
			||||||
 | 
							self.onDirty = nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) SetNonce(nonce uint64) {
 | 
					func (self *StateObject) SetNonce(nonce uint64) {
 | 
				
			||||||
	self.nonce = nonce
 | 
						self.data.Nonce = nonce
 | 
				
			||||||
	self.dirty = true
 | 
						if self.onDirty != nil {
 | 
				
			||||||
 | 
							self.onDirty(self.Address())
 | 
				
			||||||
 | 
							self.onDirty = nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *StateObject) CodeHash() []byte {
 | 
				
			||||||
 | 
						return self.data.CodeHash
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *StateObject) Balance() *big.Int {
 | 
				
			||||||
 | 
						return self.data.Balance
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Nonce() uint64 {
 | 
					func (self *StateObject) Nonce() uint64 {
 | 
				
			||||||
	return self.nonce
 | 
						return self.data.Nonce
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Never called, but must be present to allow StateObject to be used
 | 
					// Never called, but must be present to allow StateObject to be used
 | 
				
			||||||
@@ -265,39 +338,3 @@ func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
type extStateObject struct {
 | 
					 | 
				
			||||||
	Nonce    uint64
 | 
					 | 
				
			||||||
	Balance  *big.Int
 | 
					 | 
				
			||||||
	Root     common.Hash
 | 
					 | 
				
			||||||
	CodeHash []byte
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// EncodeRLP implements rlp.Encoder.
 | 
					 | 
				
			||||||
func (c *StateObject) EncodeRLP(w io.Writer) error {
 | 
					 | 
				
			||||||
	return rlp.Encode(w, []interface{}{c.nonce, c.balance, c.Root(), c.codeHash})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DecodeObject decodes an RLP-encoded state object.
 | 
					 | 
				
			||||||
func DecodeObject(address common.Address, db trie.Database, data []byte) (*StateObject, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		obj = &StateObject{address: address, db: db, storage: make(Storage)}
 | 
					 | 
				
			||||||
		ext extStateObject
 | 
					 | 
				
			||||||
		err error
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	if err = rlp.DecodeBytes(data, &ext); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if obj.trie, err = trie.NewSecure(ext.Root, db); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !bytes.Equal(ext.CodeHash, emptyCodeHash) {
 | 
					 | 
				
			||||||
		if obj.code, err = db.Get(ext.CodeHash); err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("can't get code for hash %x: %v", ext.CodeHash, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	obj.nonce = ext.Nonce
 | 
					 | 
				
			||||||
	obj.balance = ext.Balance
 | 
					 | 
				
			||||||
	obj.codeHash = ext.CodeHash
 | 
					 | 
				
			||||||
	return obj, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,23 +146,23 @@ func TestSnapshot2(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// db, trie are already non-empty values
 | 
						// db, trie are already non-empty values
 | 
				
			||||||
	so0 := state.GetStateObject(stateobjaddr0)
 | 
						so0 := state.GetStateObject(stateobjaddr0)
 | 
				
			||||||
	so0.balance = big.NewInt(42)
 | 
						so0.SetBalance(big.NewInt(42))
 | 
				
			||||||
	so0.nonce = 43
 | 
						so0.SetNonce(43)
 | 
				
			||||||
	so0.SetCode([]byte{'c', 'a', 'f', 'e'})
 | 
						so0.SetCode([]byte{'c', 'a', 'f', 'e'})
 | 
				
			||||||
	so0.remove = false
 | 
						so0.remove = false
 | 
				
			||||||
	so0.deleted = false
 | 
						so0.deleted = false
 | 
				
			||||||
	so0.dirty = true
 | 
					 | 
				
			||||||
	state.SetStateObject(so0)
 | 
						state.SetStateObject(so0)
 | 
				
			||||||
	state.Commit()
 | 
					
 | 
				
			||||||
 | 
						root, _ := state.Commit()
 | 
				
			||||||
 | 
						state.Reset(root)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// and one with deleted == true
 | 
						// and one with deleted == true
 | 
				
			||||||
	so1 := state.GetStateObject(stateobjaddr1)
 | 
						so1 := state.GetStateObject(stateobjaddr1)
 | 
				
			||||||
	so1.balance = big.NewInt(52)
 | 
						so1.SetBalance(big.NewInt(52))
 | 
				
			||||||
	so1.nonce = 53
 | 
						so1.SetNonce(53)
 | 
				
			||||||
	so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'})
 | 
						so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'})
 | 
				
			||||||
	so1.remove = true
 | 
						so1.remove = true
 | 
				
			||||||
	so1.deleted = true
 | 
						so1.deleted = true
 | 
				
			||||||
	so1.dirty = true
 | 
					 | 
				
			||||||
	state.SetStateObject(so1)
 | 
						state.SetStateObject(so1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	so1 = state.GetStateObject(stateobjaddr1)
 | 
						so1 = state.GetStateObject(stateobjaddr1)
 | 
				
			||||||
@@ -174,44 +174,50 @@ func TestSnapshot2(t *testing.T) {
 | 
				
			|||||||
	state.Set(snapshot)
 | 
						state.Set(snapshot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	so0Restored := state.GetStateObject(stateobjaddr0)
 | 
						so0Restored := state.GetStateObject(stateobjaddr0)
 | 
				
			||||||
	so0Restored.GetState(storageaddr)
 | 
						// Update lazily-loaded values before comparing.
 | 
				
			||||||
	so1Restored := state.GetStateObject(stateobjaddr1)
 | 
						so0Restored.GetState(db, storageaddr)
 | 
				
			||||||
 | 
						so0Restored.Code(db)
 | 
				
			||||||
	// non-deleted is equal (restored)
 | 
						// non-deleted is equal (restored)
 | 
				
			||||||
	compareStateObjects(so0Restored, so0, t)
 | 
						compareStateObjects(so0Restored, so0, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// deleted should be nil, both before and after restore of state copy
 | 
						// deleted should be nil, both before and after restore of state copy
 | 
				
			||||||
 | 
						so1Restored := state.GetStateObject(stateobjaddr1)
 | 
				
			||||||
	if so1Restored != nil {
 | 
						if so1Restored != nil {
 | 
				
			||||||
		t.Fatalf("deleted object not nil after restoring snapshot")
 | 
							t.Fatalf("deleted object not nil after restoring snapshot: %+v", so1Restored)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
 | 
					func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
 | 
				
			||||||
	if so0.address != so1.address {
 | 
						if so0.Address() != so1.Address() {
 | 
				
			||||||
		t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
 | 
							t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if so0.balance.Cmp(so1.balance) != 0 {
 | 
						if so0.Balance().Cmp(so1.Balance()) != 0 {
 | 
				
			||||||
		t.Fatalf("Balance mismatch: have %v, want %v", so0.balance, so1.balance)
 | 
							t.Fatalf("Balance mismatch: have %v, want %v", so0.Balance(), so1.Balance())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if so0.nonce != so1.nonce {
 | 
						if so0.Nonce() != so1.Nonce() {
 | 
				
			||||||
		t.Fatalf("Nonce mismatch: have %v, want %v", so0.nonce, so1.nonce)
 | 
							t.Fatalf("Nonce mismatch: have %v, want %v", so0.Nonce(), so1.Nonce())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !bytes.Equal(so0.codeHash, so1.codeHash) {
 | 
						if so0.data.Root != so1.data.Root {
 | 
				
			||||||
		t.Fatalf("CodeHash mismatch: have %v, want %v", so0.codeHash, so1.codeHash)
 | 
							t.Errorf("Root mismatch: have %x, want %x", so0.data.Root[:], so1.data.Root[:])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !bytes.Equal(so0.CodeHash(), so1.CodeHash()) {
 | 
				
			||||||
 | 
							t.Fatalf("CodeHash mismatch: have %v, want %v", so0.CodeHash(), so1.CodeHash())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !bytes.Equal(so0.code, so1.code) {
 | 
						if !bytes.Equal(so0.code, so1.code) {
 | 
				
			||||||
		t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
 | 
							t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !bytes.Equal(so0.initCode, so1.initCode) {
 | 
					 | 
				
			||||||
		t.Fatalf("InitCode mismatch: have %v, want %v", so0.initCode, so1.initCode)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(so1.storage) != len(so0.storage) {
 | 
				
			||||||
 | 
							t.Errorf("Storage size mismatch: have %d, want %d", len(so1.storage), len(so0.storage))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for k, v := range so1.storage {
 | 
						for k, v := range so1.storage {
 | 
				
			||||||
		if so0.storage[k] != v {
 | 
							if so0.storage[k] != v {
 | 
				
			||||||
			t.Fatalf("Storage key %s mismatch: have %v, want %v", k, so0.storage[k], v)
 | 
								t.Errorf("Storage key %x mismatch: have %v, want %v", k, so0.storage[k], v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k, v := range so0.storage {
 | 
						for k, v := range so0.storage {
 | 
				
			||||||
		if so1.storage[k] != v {
 | 
							if so1.storage[k] != v {
 | 
				
			||||||
			t.Fatalf("Storage key %s mismatch: have %v, want none.", k, v)
 | 
								t.Errorf("Storage key %x mismatch: have %v, want none.", k, v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -221,7 +227,4 @@ func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
 | 
				
			|||||||
	if so0.deleted != so1.deleted {
 | 
						if so0.deleted != so1.deleted {
 | 
				
			||||||
		t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
 | 
							t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if so0.dirty != so1.dirty {
 | 
					 | 
				
			||||||
		t.Fatalf("Dirty mismatch: have %v, want %v", so0.dirty, so1.dirty)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,8 +43,14 @@ type StateDB struct {
 | 
				
			|||||||
	db   ethdb.Database
 | 
						db   ethdb.Database
 | 
				
			||||||
	trie *trie.SecureTrie
 | 
						trie *trie.SecureTrie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stateObjects map[string]*StateObject
 | 
						// This map caches canon state accounts.
 | 
				
			||||||
 | 
						all map[common.Address]Account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This map holds 'live' objects, which will get modified while processing a state transition.
 | 
				
			||||||
 | 
						stateObjects      map[common.Address]*StateObject
 | 
				
			||||||
 | 
						stateObjectsDirty map[common.Address]struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The refund counter, also used by state transitioning.
 | 
				
			||||||
	refund *big.Int
 | 
						refund *big.Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	thash, bhash common.Hash
 | 
						thash, bhash common.Hash
 | 
				
			||||||
@@ -60,32 +66,36 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &StateDB{
 | 
						return &StateDB{
 | 
				
			||||||
		db:           db,
 | 
							db:                db,
 | 
				
			||||||
		trie:         tr,
 | 
							trie:              tr,
 | 
				
			||||||
		stateObjects: make(map[string]*StateObject),
 | 
							all:               make(map[common.Address]Account),
 | 
				
			||||||
		refund:       new(big.Int),
 | 
							stateObjects:      make(map[common.Address]*StateObject),
 | 
				
			||||||
		logs:         make(map[common.Hash]vm.Logs),
 | 
							stateObjectsDirty: make(map[common.Address]struct{}),
 | 
				
			||||||
 | 
							refund:            new(big.Int),
 | 
				
			||||||
 | 
							logs:              make(map[common.Hash]vm.Logs),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Reset clears out all emphemeral state objects from the state db, but keeps
 | 
					// Reset clears out all emphemeral state objects from the state db, but keeps
 | 
				
			||||||
// the underlying state trie to avoid reloading data for the next operations.
 | 
					// the underlying state trie to avoid reloading data for the next operations.
 | 
				
			||||||
func (self *StateDB) Reset(root common.Hash) error {
 | 
					func (self *StateDB) Reset(root common.Hash) error {
 | 
				
			||||||
	var (
 | 
						tr, err := trie.NewSecure(root, self.db)
 | 
				
			||||||
		err error
 | 
						if err != nil {
 | 
				
			||||||
		tr  = self.trie
 | 
							return err
 | 
				
			||||||
	)
 | 
						}
 | 
				
			||||||
 | 
						all := self.all
 | 
				
			||||||
	if self.trie.Hash() != root {
 | 
						if self.trie.Hash() != root {
 | 
				
			||||||
		if tr, err = trie.NewSecure(root, self.db); err != nil {
 | 
							// The root has changed, invalidate canon state.
 | 
				
			||||||
			return err
 | 
							all = make(map[common.Address]Account)
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	*self = StateDB{
 | 
						*self = StateDB{
 | 
				
			||||||
		db:           self.db,
 | 
							db:                self.db,
 | 
				
			||||||
		trie:         tr,
 | 
							trie:              tr,
 | 
				
			||||||
		stateObjects: make(map[string]*StateObject),
 | 
							all:               all,
 | 
				
			||||||
		refund:       new(big.Int),
 | 
							stateObjects:      make(map[common.Address]*StateObject),
 | 
				
			||||||
		logs:         make(map[common.Hash]vm.Logs),
 | 
							stateObjectsDirty: make(map[common.Address]struct{}),
 | 
				
			||||||
 | 
							refund:            new(big.Int),
 | 
				
			||||||
 | 
							logs:              make(map[common.Hash]vm.Logs),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -137,7 +147,7 @@ func (self *StateDB) GetAccount(addr common.Address) vm.Account {
 | 
				
			|||||||
func (self *StateDB) GetBalance(addr common.Address) *big.Int {
 | 
					func (self *StateDB) GetBalance(addr common.Address) *big.Int {
 | 
				
			||||||
	stateObject := self.GetStateObject(addr)
 | 
						stateObject := self.GetStateObject(addr)
 | 
				
			||||||
	if stateObject != nil {
 | 
						if stateObject != nil {
 | 
				
			||||||
		return stateObject.balance
 | 
							return stateObject.Balance()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return common.Big0
 | 
						return common.Big0
 | 
				
			||||||
@@ -146,7 +156,7 @@ func (self *StateDB) GetBalance(addr common.Address) *big.Int {
 | 
				
			|||||||
func (self *StateDB) GetNonce(addr common.Address) uint64 {
 | 
					func (self *StateDB) GetNonce(addr common.Address) uint64 {
 | 
				
			||||||
	stateObject := self.GetStateObject(addr)
 | 
						stateObject := self.GetStateObject(addr)
 | 
				
			||||||
	if stateObject != nil {
 | 
						if stateObject != nil {
 | 
				
			||||||
		return stateObject.nonce
 | 
							return stateObject.Nonce()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return StartingNonce
 | 
						return StartingNonce
 | 
				
			||||||
@@ -155,18 +165,24 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 {
 | 
				
			|||||||
func (self *StateDB) GetCode(addr common.Address) []byte {
 | 
					func (self *StateDB) GetCode(addr common.Address) []byte {
 | 
				
			||||||
	stateObject := self.GetStateObject(addr)
 | 
						stateObject := self.GetStateObject(addr)
 | 
				
			||||||
	if stateObject != nil {
 | 
						if stateObject != nil {
 | 
				
			||||||
		return stateObject.code
 | 
							return stateObject.Code(self.db)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *StateDB) GetCodeSize(addr common.Address) int {
 | 
				
			||||||
 | 
						stateObject := self.GetStateObject(addr)
 | 
				
			||||||
 | 
						if stateObject != nil {
 | 
				
			||||||
 | 
							return stateObject.CodeSize(self.db)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
 | 
					func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
 | 
				
			||||||
	stateObject := self.GetStateObject(a)
 | 
						stateObject := self.GetStateObject(a)
 | 
				
			||||||
	if stateObject != nil {
 | 
						if stateObject != nil {
 | 
				
			||||||
		return stateObject.GetState(b)
 | 
							return stateObject.GetState(self.db, b)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return common.Hash{}
 | 
						return common.Hash{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -214,8 +230,7 @@ func (self *StateDB) Delete(addr common.Address) bool {
 | 
				
			|||||||
	stateObject := self.GetStateObject(addr)
 | 
						stateObject := self.GetStateObject(addr)
 | 
				
			||||||
	if stateObject != nil {
 | 
						if stateObject != nil {
 | 
				
			||||||
		stateObject.MarkForDeletion()
 | 
							stateObject.MarkForDeletion()
 | 
				
			||||||
		stateObject.balance = new(big.Int)
 | 
							stateObject.data.Balance = new(big.Int)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -242,35 +257,47 @@ 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. Returns nil if not found.
 | 
				
			||||||
func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) {
 | 
					func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) {
 | 
				
			||||||
	stateObject = self.stateObjects[addr.Str()]
 | 
						// Prefer 'live' objects.
 | 
				
			||||||
	if stateObject != nil {
 | 
						if obj := self.stateObjects[addr]; obj != nil {
 | 
				
			||||||
		if stateObject.deleted {
 | 
							if obj.deleted {
 | 
				
			||||||
			stateObject = nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return obj
 | 
				
			||||||
		return stateObject
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data := self.trie.Get(addr[:])
 | 
						// Use cached account data from the canon state if possible.
 | 
				
			||||||
	if len(data) == 0 {
 | 
						if data, ok := self.all[addr]; ok {
 | 
				
			||||||
 | 
							obj := NewObject(addr, data, self.MarkStateObjectDirty)
 | 
				
			||||||
 | 
							self.SetStateObject(obj)
 | 
				
			||||||
 | 
							return obj
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Load the object from the database.
 | 
				
			||||||
 | 
						enc := self.trie.Get(addr[:])
 | 
				
			||||||
 | 
						if len(enc) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	stateObject, err := DecodeObject(addr, self.db, data)
 | 
						var data Account
 | 
				
			||||||
	if err != nil {
 | 
						if err := rlp.DecodeBytes(enc, &data); err != nil {
 | 
				
			||||||
		glog.Errorf("can't decode object at %x: %v", addr[:], err)
 | 
							glog.Errorf("can't decode object at %x: %v", addr[:], err)
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	self.SetStateObject(stateObject)
 | 
						// Update the all cache. Content in DB always corresponds
 | 
				
			||||||
	return stateObject
 | 
						// to the current head state so this is ok to do here.
 | 
				
			||||||
 | 
						// The object we just loaded has no storage trie and code yet.
 | 
				
			||||||
 | 
						self.all[addr] = data
 | 
				
			||||||
 | 
						// Insert into the live set.
 | 
				
			||||||
 | 
						obj := NewObject(addr, data, self.MarkStateObjectDirty)
 | 
				
			||||||
 | 
						self.SetStateObject(obj)
 | 
				
			||||||
 | 
						return obj
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) SetStateObject(object *StateObject) {
 | 
					func (self *StateDB) SetStateObject(object *StateObject) {
 | 
				
			||||||
	self.stateObjects[object.Address().Str()] = object
 | 
						self.stateObjects[object.Address()] = object
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Retrieve a state object or create a new state object if nil
 | 
					// Retrieve a state object or create a new state object if nil
 | 
				
			||||||
@@ -288,15 +315,19 @@ func (self *StateDB) newStateObject(addr common.Address) *StateObject {
 | 
				
			|||||||
	if glog.V(logger.Core) {
 | 
						if glog.V(logger.Core) {
 | 
				
			||||||
		glog.Infof("(+) %x\n", addr)
 | 
							glog.Infof("(+) %x\n", addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						obj := NewObject(addr, Account{}, self.MarkStateObjectDirty)
 | 
				
			||||||
	stateObject := NewStateObject(addr, self.db)
 | 
						obj.SetNonce(StartingNonce) // sets the object to dirty
 | 
				
			||||||
	stateObject.SetNonce(StartingNonce)
 | 
						self.stateObjects[addr] = obj
 | 
				
			||||||
	self.stateObjects[addr.Str()] = stateObject
 | 
						return obj
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return stateObject
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Creates creates a new state object and takes ownership. This is different from "NewStateObject"
 | 
					// MarkStateObjectDirty adds the specified object to the dirty map to avoid costly
 | 
				
			||||||
 | 
					// state object cache iteration to find a handful of modified ones.
 | 
				
			||||||
 | 
					func (self *StateDB) MarkStateObjectDirty(addr common.Address) {
 | 
				
			||||||
 | 
						self.stateObjectsDirty[addr] = struct{}{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Creates creates a new state object and takes ownership.
 | 
				
			||||||
func (self *StateDB) CreateStateObject(addr common.Address) *StateObject {
 | 
					func (self *StateDB) CreateStateObject(addr common.Address) *StateObject {
 | 
				
			||||||
	// Get previous (if any)
 | 
						// Get previous (if any)
 | 
				
			||||||
	so := self.GetStateObject(addr)
 | 
						so := self.GetStateObject(addr)
 | 
				
			||||||
@@ -305,7 +336,7 @@ func (self *StateDB) CreateStateObject(addr common.Address) *StateObject {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// If it existed set the balance to the new account
 | 
						// If it existed set the balance to the new account
 | 
				
			||||||
	if so != nil {
 | 
						if so != nil {
 | 
				
			||||||
		newSo.balance = so.balance
 | 
							newSo.data.Balance = so.data.Balance
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return newSo
 | 
						return newSo
 | 
				
			||||||
@@ -320,29 +351,34 @@ func (self *StateDB) CreateAccount(addr common.Address) vm.Account {
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) Copy() *StateDB {
 | 
					func (self *StateDB) Copy() *StateDB {
 | 
				
			||||||
	// ignore error - we assume state-to-be-copied always exists
 | 
						// Copy all the basic fields, initialize the memory ones
 | 
				
			||||||
	state, _ := New(common.Hash{}, self.db)
 | 
						state := &StateDB{
 | 
				
			||||||
	state.trie = self.trie
 | 
							db:                self.db,
 | 
				
			||||||
	for k, stateObject := range self.stateObjects {
 | 
							trie:              self.trie,
 | 
				
			||||||
		if stateObject.dirty {
 | 
							all:               self.all,
 | 
				
			||||||
			state.stateObjects[k] = stateObject.Copy()
 | 
							stateObjects:      make(map[common.Address]*StateObject, len(self.stateObjectsDirty)),
 | 
				
			||||||
		}
 | 
							stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
 | 
				
			||||||
 | 
							refund:            new(big.Int).Set(self.refund),
 | 
				
			||||||
 | 
							logs:              make(map[common.Hash]vm.Logs, len(self.logs)),
 | 
				
			||||||
 | 
							logSize:           self.logSize,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Copy the dirty states and logs
 | 
				
			||||||
 | 
						for addr, _ := range self.stateObjectsDirty {
 | 
				
			||||||
 | 
							state.stateObjects[addr] = self.stateObjects[addr].Copy(self.db, state.MarkStateObjectDirty)
 | 
				
			||||||
 | 
							state.stateObjectsDirty[addr] = struct{}{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	state.refund.Set(self.refund)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for hash, logs := range self.logs {
 | 
						for hash, logs := range self.logs {
 | 
				
			||||||
		state.logs[hash] = make(vm.Logs, len(logs))
 | 
							state.logs[hash] = make(vm.Logs, len(logs))
 | 
				
			||||||
		copy(state.logs[hash], logs)
 | 
							copy(state.logs[hash], logs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	state.logSize = self.logSize
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return state
 | 
						return state
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) Set(state *StateDB) {
 | 
					func (self *StateDB) Set(state *StateDB) {
 | 
				
			||||||
	self.trie = state.trie
 | 
						self.trie = state.trie
 | 
				
			||||||
	self.stateObjects = state.stateObjects
 | 
						self.stateObjects = state.stateObjects
 | 
				
			||||||
 | 
						self.stateObjectsDirty = state.stateObjectsDirty
 | 
				
			||||||
 | 
						self.all = state.all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	self.refund = state.refund
 | 
						self.refund = state.refund
 | 
				
			||||||
	self.logs = state.logs
 | 
						self.logs = state.logs
 | 
				
			||||||
@@ -358,14 +394,13 @@ func (self *StateDB) GetRefund() *big.Int {
 | 
				
			|||||||
// goes into transaction receipts.
 | 
					// goes into transaction receipts.
 | 
				
			||||||
func (s *StateDB) IntermediateRoot() common.Hash {
 | 
					func (s *StateDB) IntermediateRoot() common.Hash {
 | 
				
			||||||
	s.refund = new(big.Int)
 | 
						s.refund = new(big.Int)
 | 
				
			||||||
	for _, stateObject := range s.stateObjects {
 | 
						for addr, _ := range s.stateObjectsDirty {
 | 
				
			||||||
		if stateObject.dirty {
 | 
							stateObject := s.stateObjects[addr]
 | 
				
			||||||
			if stateObject.remove {
 | 
							if stateObject.remove {
 | 
				
			||||||
				s.DeleteStateObject(stateObject)
 | 
								s.DeleteStateObject(stateObject)
 | 
				
			||||||
			} else {
 | 
							} else {
 | 
				
			||||||
				stateObject.Update()
 | 
								stateObject.UpdateRoot(s.db)
 | 
				
			||||||
				s.UpdateStateObject(stateObject)
 | 
								s.UpdateStateObject(stateObject)
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return s.trie.Hash()
 | 
						return s.trie.Hash()
 | 
				
			||||||
@@ -380,15 +415,15 @@ func (s *StateDB) DeleteSuicides() {
 | 
				
			|||||||
	// Reset refund so that any used-gas calculations can use
 | 
						// Reset refund so that any used-gas calculations can use
 | 
				
			||||||
	// this method.
 | 
						// this method.
 | 
				
			||||||
	s.refund = new(big.Int)
 | 
						s.refund = new(big.Int)
 | 
				
			||||||
	for _, stateObject := range s.stateObjects {
 | 
						for addr, _ := range s.stateObjectsDirty {
 | 
				
			||||||
		if stateObject.dirty {
 | 
							stateObject := s.stateObjects[addr]
 | 
				
			||||||
			// If the object has been removed by a suicide
 | 
					
 | 
				
			||||||
			// flag the object as deleted.
 | 
							// If the object has been removed by a suicide
 | 
				
			||||||
			if stateObject.remove {
 | 
							// flag the object as deleted.
 | 
				
			||||||
				stateObject.deleted = true
 | 
							if stateObject.remove {
 | 
				
			||||||
			}
 | 
								stateObject.deleted = true
 | 
				
			||||||
			stateObject.dirty = false
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							delete(s.stateObjectsDirty, addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -407,46 +442,44 @@ func (s *StateDB) CommitBatch() (root common.Hash, batch ethdb.Batch) {
 | 
				
			|||||||
	return root, batch
 | 
						return root, batch
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *StateDB) commit(db trie.DatabaseWriter) (common.Hash, error) {
 | 
					func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error) {
 | 
				
			||||||
	s.refund = new(big.Int)
 | 
						s.refund = new(big.Int)
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								// Committing failed, any updates to the canon state are invalid.
 | 
				
			||||||
 | 
								s.all = make(map[common.Address]Account)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, stateObject := range s.stateObjects {
 | 
						// Commit objects to the trie.
 | 
				
			||||||
 | 
						for addr, stateObject := range s.stateObjects {
 | 
				
			||||||
		if stateObject.remove {
 | 
							if stateObject.remove {
 | 
				
			||||||
			// If the object has been removed, don't bother syncing it
 | 
								// If the object has been removed, don't bother syncing it
 | 
				
			||||||
			// and just mark it for deletion in the trie.
 | 
								// and just mark it for deletion in the trie.
 | 
				
			||||||
			s.DeleteStateObject(stateObject)
 | 
								s.DeleteStateObject(stateObject)
 | 
				
			||||||
		} else {
 | 
								delete(s.all, addr)
 | 
				
			||||||
 | 
							} else if _, ok := s.stateObjectsDirty[addr]; ok {
 | 
				
			||||||
			// Write any contract code associated with the state object
 | 
								// Write any contract code associated with the state object
 | 
				
			||||||
			if len(stateObject.code) > 0 {
 | 
								if stateObject.code != nil && stateObject.dirtyCode {
 | 
				
			||||||
				if err := db.Put(stateObject.codeHash, stateObject.code); err != nil {
 | 
									if err := dbw.Put(stateObject.CodeHash(), stateObject.code); err != nil {
 | 
				
			||||||
					return common.Hash{}, err
 | 
										return common.Hash{}, err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									stateObject.dirtyCode = false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Write any storage changes in the state object to its trie.
 | 
								// Write any storage changes in the state object to its storage trie.
 | 
				
			||||||
			stateObject.Update()
 | 
								if err := stateObject.CommitTrie(s.db, dbw); err != nil {
 | 
				
			||||||
 | 
					 | 
				
			||||||
			// 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
 | 
									return common.Hash{}, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Update the object in the account trie.
 | 
								// Update the object in the main account trie.
 | 
				
			||||||
			s.UpdateStateObject(stateObject)
 | 
								s.UpdateStateObject(stateObject)
 | 
				
			||||||
 | 
								s.all[addr] = stateObject.data
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		stateObject.dirty = false
 | 
							delete(s.stateObjectsDirty, addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return s.trie.CommitTo(db)
 | 
						// Write trie changes.
 | 
				
			||||||
 | 
						return s.trie.CommitTo(dbw)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) Refunds() *big.Int {
 | 
					func (self *StateDB) Refunds() *big.Int {
 | 
				
			||||||
	return self.refund
 | 
						return self.refund
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Debug stuff
 | 
					 | 
				
			||||||
func (self *StateDB) CreateOutputForDiff() {
 | 
					 | 
				
			||||||
	for _, stateObject := range self.stateObjects {
 | 
					 | 
				
			||||||
		stateObject.CreateOutputForDiff()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,6 +94,7 @@ type Database interface {
 | 
				
			|||||||
	GetNonce(common.Address) uint64
 | 
						GetNonce(common.Address) uint64
 | 
				
			||||||
	SetNonce(common.Address, uint64)
 | 
						SetNonce(common.Address, uint64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetCodeSize(common.Address) int
 | 
				
			||||||
	GetCode(common.Address) []byte
 | 
						GetCode(common.Address) []byte
 | 
				
			||||||
	SetCode(common.Address, []byte)
 | 
						SetCode(common.Address, []byte)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -363,7 +363,7 @@ func opCalldataCopy(instr instruction, pc *uint64, env Environment, contract *Co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func opExtCodeSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
 | 
					func opExtCodeSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
 | 
				
			||||||
	addr := common.BigToAddress(stack.pop())
 | 
						addr := common.BigToAddress(stack.pop())
 | 
				
			||||||
	l := big.NewInt(int64(len(env.Db().GetCode(addr))))
 | 
						l := big.NewInt(int64(env.Db().GetCodeSize(addr)))
 | 
				
			||||||
	stack.push(l)
 | 
						stack.push(l)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1575,14 +1575,14 @@ func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DumpBlock retrieves the entire state of the database at a given block.
 | 
					// DumpBlock retrieves the entire state of the database at a given block.
 | 
				
			||||||
func (api *PublicDebugAPI) DumpBlock(number uint64) (state.World, error) {
 | 
					func (api *PublicDebugAPI) DumpBlock(number uint64) (state.Dump, error) {
 | 
				
			||||||
	block := api.eth.BlockChain().GetBlockByNumber(number)
 | 
						block := api.eth.BlockChain().GetBlockByNumber(number)
 | 
				
			||||||
	if block == nil {
 | 
						if block == nil {
 | 
				
			||||||
		return state.World{}, fmt.Errorf("block #%d not found", number)
 | 
							return state.Dump{}, fmt.Errorf("block #%d not found", number)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	stateDb, err := state.New(block.Root(), api.eth.ChainDb())
 | 
						stateDb, err := state.New(block.Root(), api.eth.ChainDb())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return state.World{}, err
 | 
							return state.Dump{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return stateDb.RawDump(), nil
 | 
						return stateDb.RawDump(), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,7 +62,7 @@ func makeTestState() (common.Hash, ethdb.Database) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		so.AddBalance(big.NewInt(int64(i)))
 | 
							so.AddBalance(big.NewInt(int64(i)))
 | 
				
			||||||
		so.SetCode([]byte{i, i, i})
 | 
							so.SetCode([]byte{i, i, i})
 | 
				
			||||||
		so.Update()
 | 
							so.UpdateRoot(sdb)
 | 
				
			||||||
		st.UpdateStateObject(so)
 | 
							st.UpdateStateObject(so)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	root, _ := st.Commit()
 | 
						root, _ := st.Commit()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -514,12 +514,32 @@ func TestAPIGather(t *testing.T) {
 | 
				
			|||||||
	}{
 | 
						}{
 | 
				
			||||||
		"Zero APIs": {[]rpc.API{}, InstrumentedServiceMakerA},
 | 
							"Zero APIs": {[]rpc.API{}, InstrumentedServiceMakerA},
 | 
				
			||||||
		"Single API": {[]rpc.API{
 | 
							"Single API": {[]rpc.API{
 | 
				
			||||||
			{"single", "1", &OneMethodApi{fun: func() { calls <- "single.v1" }}, true},
 | 
								{
 | 
				
			||||||
 | 
									Namespace: "single",
 | 
				
			||||||
 | 
									Version:   "1",
 | 
				
			||||||
 | 
									Service:   &OneMethodApi{fun: func() { calls <- "single.v1" }},
 | 
				
			||||||
 | 
									Public:    true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}, InstrumentedServiceMakerB},
 | 
							}, InstrumentedServiceMakerB},
 | 
				
			||||||
		"Many APIs": {[]rpc.API{
 | 
							"Many APIs": {[]rpc.API{
 | 
				
			||||||
			{"multi", "1", &OneMethodApi{fun: func() { calls <- "multi.v1" }}, true},
 | 
								{
 | 
				
			||||||
			{"multi.v2", "2", &OneMethodApi{fun: func() { calls <- "multi.v2" }}, true},
 | 
									Namespace: "multi",
 | 
				
			||||||
			{"multi.v2.nested", "2", &OneMethodApi{fun: func() { calls <- "multi.v2.nested" }}, true},
 | 
									Version:   "1",
 | 
				
			||||||
 | 
									Service:   &OneMethodApi{fun: func() { calls <- "multi.v1" }},
 | 
				
			||||||
 | 
									Public:    true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Namespace: "multi.v2",
 | 
				
			||||||
 | 
									Version:   "2",
 | 
				
			||||||
 | 
									Service:   &OneMethodApi{fun: func() { calls <- "multi.v2" }},
 | 
				
			||||||
 | 
									Public:    true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Namespace: "multi.v2.nested",
 | 
				
			||||||
 | 
									Version:   "2",
 | 
				
			||||||
 | 
									Service:   &OneMethodApi{fun: func() { calls <- "multi.v2.nested" }},
 | 
				
			||||||
 | 
									Public:    true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}, InstrumentedServiceMakerC},
 | 
							}, InstrumentedServiceMakerC},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for id, config := range services {
 | 
						for id, config := range services {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,7 +97,7 @@ func benchStateTest(ruleSet RuleSet, test VmTest, env map[string]string, b *test
 | 
				
			|||||||
	db, _ := ethdb.NewMemDatabase()
 | 
						db, _ := ethdb.NewMemDatabase()
 | 
				
			||||||
	statedb, _ := state.New(common.Hash{}, db)
 | 
						statedb, _ := state.New(common.Hash{}, db)
 | 
				
			||||||
	for addr, account := range test.Pre {
 | 
						for addr, account := range test.Pre {
 | 
				
			||||||
		obj := StateObjectFromAccount(db, addr, account)
 | 
							obj := StateObjectFromAccount(db, addr, account, statedb.MarkStateObjectDirty)
 | 
				
			||||||
		statedb.SetStateObject(obj)
 | 
							statedb.SetStateObject(obj)
 | 
				
			||||||
		for a, v := range account.Storage {
 | 
							for a, v := range account.Storage {
 | 
				
			||||||
			obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
								obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
				
			||||||
@@ -136,7 +136,7 @@ func runStateTest(ruleSet RuleSet, test VmTest) error {
 | 
				
			|||||||
	db, _ := ethdb.NewMemDatabase()
 | 
						db, _ := ethdb.NewMemDatabase()
 | 
				
			||||||
	statedb, _ := state.New(common.Hash{}, db)
 | 
						statedb, _ := state.New(common.Hash{}, db)
 | 
				
			||||||
	for addr, account := range test.Pre {
 | 
						for addr, account := range test.Pre {
 | 
				
			||||||
		obj := StateObjectFromAccount(db, addr, account)
 | 
							obj := StateObjectFromAccount(db, addr, account, statedb.MarkStateObjectDirty)
 | 
				
			||||||
		statedb.SetStateObject(obj)
 | 
							statedb.SetStateObject(obj)
 | 
				
			||||||
		for a, v := range account.Storage {
 | 
							for a, v := range account.Storage {
 | 
				
			||||||
			obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
								obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
				
			||||||
@@ -187,7 +187,7 @@ func runStateTest(ruleSet RuleSet, test VmTest) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for addr, value := range account.Storage {
 | 
							for addr, value := range account.Storage {
 | 
				
			||||||
			v := obj.GetState(common.HexToHash(addr))
 | 
								v := statedb.GetState(obj.Address(), common.HexToHash(addr))
 | 
				
			||||||
			vexp := common.HexToHash(value)
 | 
								vexp := common.HexToHash(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if v != vexp {
 | 
								if v != vexp {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,16 +103,17 @@ func (self Log) Topics() [][]byte {
 | 
				
			|||||||
	return t
 | 
						return t
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func StateObjectFromAccount(db ethdb.Database, addr string, account Account) *state.StateObject {
 | 
					func StateObjectFromAccount(db ethdb.Database, addr string, account Account, onDirty func(common.Address)) *state.StateObject {
 | 
				
			||||||
	obj := state.NewStateObject(common.HexToAddress(addr), db)
 | 
					 | 
				
			||||||
	obj.SetBalance(common.Big(account.Balance))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if common.IsHex(account.Code) {
 | 
						if common.IsHex(account.Code) {
 | 
				
			||||||
		account.Code = account.Code[2:]
 | 
							account.Code = account.Code[2:]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	obj.SetCode(common.Hex2Bytes(account.Code))
 | 
						code := common.Hex2Bytes(account.Code)
 | 
				
			||||||
	obj.SetNonce(common.Big(account.Nonce).Uint64())
 | 
						obj := state.NewObject(common.HexToAddress(addr), state.Account{
 | 
				
			||||||
 | 
							Balance:  common.Big(account.Balance),
 | 
				
			||||||
 | 
							CodeHash: crypto.Keccak256(code),
 | 
				
			||||||
 | 
							Nonce:    common.Big(account.Nonce).Uint64(),
 | 
				
			||||||
 | 
						}, onDirty)
 | 
				
			||||||
 | 
						obj.SetCode(code)
 | 
				
			||||||
	return obj
 | 
						return obj
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,7 @@ func benchVmTest(test VmTest, env map[string]string, b *testing.B) {
 | 
				
			|||||||
	db, _ := ethdb.NewMemDatabase()
 | 
						db, _ := ethdb.NewMemDatabase()
 | 
				
			||||||
	statedb, _ := state.New(common.Hash{}, db)
 | 
						statedb, _ := state.New(common.Hash{}, db)
 | 
				
			||||||
	for addr, account := range test.Pre {
 | 
						for addr, account := range test.Pre {
 | 
				
			||||||
		obj := StateObjectFromAccount(db, addr, account)
 | 
							obj := StateObjectFromAccount(db, addr, account, statedb.MarkStateObjectDirty)
 | 
				
			||||||
		statedb.SetStateObject(obj)
 | 
							statedb.SetStateObject(obj)
 | 
				
			||||||
		for a, v := range account.Storage {
 | 
							for a, v := range account.Storage {
 | 
				
			||||||
			obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
								obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
				
			||||||
@@ -154,7 +154,7 @@ func runVmTest(test VmTest) error {
 | 
				
			|||||||
	db, _ := ethdb.NewMemDatabase()
 | 
						db, _ := ethdb.NewMemDatabase()
 | 
				
			||||||
	statedb, _ := state.New(common.Hash{}, db)
 | 
						statedb, _ := state.New(common.Hash{}, db)
 | 
				
			||||||
	for addr, account := range test.Pre {
 | 
						for addr, account := range test.Pre {
 | 
				
			||||||
		obj := StateObjectFromAccount(db, addr, account)
 | 
							obj := StateObjectFromAccount(db, addr, account, statedb.MarkStateObjectDirty)
 | 
				
			||||||
		statedb.SetStateObject(obj)
 | 
							statedb.SetStateObject(obj)
 | 
				
			||||||
		for a, v := range account.Storage {
 | 
							for a, v := range account.Storage {
 | 
				
			||||||
			obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
								obj.SetState(common.HexToHash(a), common.HexToHash(v))
 | 
				
			||||||
@@ -205,11 +205,9 @@ func runVmTest(test VmTest) error {
 | 
				
			|||||||
		if obj == nil {
 | 
							if obj == nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		for addr, value := range account.Storage {
 | 
							for addr, value := range account.Storage {
 | 
				
			||||||
			v := obj.GetState(common.HexToHash(addr))
 | 
								v := statedb.GetState(obj.Address(), common.HexToHash(addr))
 | 
				
			||||||
			vexp := common.HexToHash(value)
 | 
								vexp := common.HexToHash(value)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if v != vexp {
 | 
								if v != vexp {
 | 
				
			||||||
				return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big())
 | 
									return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user