diff options
Diffstat (limited to 'core/state/statedb.go')
-rw-r--r-- | core/state/statedb.go | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/core/state/statedb.go b/core/state/statedb.go index 68009deec..cae2dc4b2 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" @@ -64,7 +63,7 @@ type StateDB struct { codeSizeCache *lru.Cache // This map holds 'live' objects, which will get modified while processing a state transition. - stateObjects map[common.Address]*StateObject + stateObjects map[common.Address]*stateObject stateObjectsDirty map[common.Address]struct{} // The refund counter, also used by state transitioning. @@ -97,7 +96,7 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) { db: db, trie: tr, codeSizeCache: csc, - stateObjects: make(map[common.Address]*StateObject), + stateObjects: make(map[common.Address]*stateObject), stateObjectsDirty: make(map[common.Address]struct{}), refund: new(big.Int), logs: make(map[common.Hash][]*types.Log), @@ -119,7 +118,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) { db: self.db, trie: tr, codeSizeCache: self.codeSizeCache, - stateObjects: make(map[common.Address]*StateObject), + stateObjects: make(map[common.Address]*stateObject), stateObjectsDirty: make(map[common.Address]struct{}), refund: new(big.Int), logs: make(map[common.Hash][]*types.Log), @@ -138,7 +137,7 @@ func (self *StateDB) Reset(root common.Hash) error { return err } self.trie = tr - self.stateObjects = make(map[common.Address]*StateObject) + self.stateObjects = make(map[common.Address]*stateObject) self.stateObjectsDirty = make(map[common.Address]struct{}) self.thash = common.Hash{} self.bhash = common.Hash{} @@ -227,23 +226,19 @@ func (self *StateDB) AddRefund(gas *big.Int) { // Exist reports whether the given account address exists in the state. // Notably this also returns true for suicided accounts. func (self *StateDB) Exist(addr common.Address) bool { - return self.GetStateObject(addr) != nil + return self.getStateObject(addr) != nil } // Empty returns whether the state object is either non-existent // or empty according to the EIP161 specification (balance = nonce = code = 0) func (self *StateDB) Empty(addr common.Address) bool { - so := self.GetStateObject(addr) + so := self.getStateObject(addr) return so == nil || so.empty() } -func (self *StateDB) GetAccount(addr common.Address) vm.Account { - return self.GetStateObject(addr) -} - // Retrieve the balance from the given address or 0 if object not found func (self *StateDB) GetBalance(addr common.Address) *big.Int { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject != nil { return stateObject.Balance() } @@ -251,7 +246,7 @@ func (self *StateDB) GetBalance(addr common.Address) *big.Int { } func (self *StateDB) GetNonce(addr common.Address) uint64 { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject != nil { return stateObject.Nonce() } @@ -260,7 +255,7 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 { } func (self *StateDB) GetCode(addr common.Address) []byte { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject != nil { code := stateObject.Code(self.db) key := common.BytesToHash(stateObject.CodeHash()) @@ -271,7 +266,7 @@ func (self *StateDB) GetCode(addr common.Address) []byte { } func (self *StateDB) GetCodeSize(addr common.Address) int { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject == nil { return 0 } @@ -287,7 +282,7 @@ func (self *StateDB) GetCodeSize(addr common.Address) int { } func (self *StateDB) GetCodeHash(addr common.Address) common.Hash { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject == nil { return common.Hash{} } @@ -295,7 +290,7 @@ func (self *StateDB) GetCodeHash(addr common.Address) 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 { return stateObject.GetState(self.db, b) } @@ -303,7 +298,7 @@ func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { } func (self *StateDB) HasSuicided(addr common.Address) bool { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject != nil { return stateObject.suicided } @@ -362,9 +357,9 @@ func (self *StateDB) SetState(addr common.Address, key common.Hash, value common // This clears the account balance. // // The account's state object is still available until the state is committed, -// GetStateObject will return a non-nil account after Suicide. +// getStateObject will return a non-nil account after Suicide. func (self *StateDB) Suicide(addr common.Address) bool { - stateObject := self.GetStateObject(addr) + stateObject := self.getStateObject(addr) if stateObject == nil { return false } @@ -383,7 +378,7 @@ func (self *StateDB) Suicide(addr common.Address) bool { // // updateStateObject writes the given object to the trie. -func (self *StateDB) updateStateObject(stateObject *StateObject) { +func (self *StateDB) updateStateObject(stateObject *stateObject) { addr := stateObject.Address() data, err := rlp.EncodeToBytes(stateObject) if err != nil { @@ -393,14 +388,14 @@ func (self *StateDB) updateStateObject(stateObject *StateObject) { } // deleteStateObject removes the given object from the state trie. -func (self *StateDB) deleteStateObject(stateObject *StateObject) { +func (self *StateDB) deleteStateObject(stateObject *stateObject) { stateObject.deleted = true addr := stateObject.Address() self.trie.Delete(addr[:]) } // 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) { // Prefer 'live' objects. if obj := self.stateObjects[addr]; obj != nil { if obj.deleted { @@ -425,13 +420,13 @@ func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObje return obj } -func (self *StateDB) setStateObject(object *StateObject) { +func (self *StateDB) setStateObject(object *stateObject) { self.stateObjects[object.Address()] = object } // Retrieve a state object or create a new state object if nil -func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject { - stateObject := self.GetStateObject(addr) +func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { + stateObject := self.getStateObject(addr) if stateObject == nil || stateObject.deleted { stateObject, _ = self.createObject(addr) } @@ -446,8 +441,8 @@ func (self *StateDB) MarkStateObjectDirty(addr common.Address) { // createObject creates a new state object. If there is an existing account with // the given address, it is overwritten and returned as the second return value. -func (self *StateDB) createObject(addr common.Address) (newobj, prev *StateObject) { - prev = self.GetStateObject(addr) +func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { + prev = self.getStateObject(addr) newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty) newobj.setNonce(0) // sets the object to dirty if prev == nil { @@ -472,12 +467,32 @@ func (self *StateDB) createObject(addr common.Address) (newobj, prev *StateObjec // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) // // Carrying over the balance ensures that Ether doesn't disappear. -func (self *StateDB) CreateAccount(addr common.Address) vm.Account { +func (self *StateDB) CreateAccount(addr common.Address) { new, prev := self.createObject(addr) if prev != nil { new.setBalance(prev.data.Balance) } - return new +} + +func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) { + so := db.getStateObject(addr) + if so == nil { + return + } + + // When iterating over the storage check the cache first + for h, value := range so.cachedStorage { + cb(h, value) + } + + it := so.getTrie(db.db).Iterator() + for it.Next() { + // ignore cached values + key := common.BytesToHash(db.trie.GetKey(it.Key)) + if _, ok := so.cachedStorage[key]; !ok { + cb(key, common.BytesToHash(it.Value)) + } + } } // Copy creates a deep, independent copy of the state. @@ -492,7 +507,7 @@ func (self *StateDB) Copy() *StateDB { trie: self.trie, pastTries: self.pastTries, codeSizeCache: self.codeSizeCache, - stateObjects: make(map[common.Address]*StateObject, len(self.stateObjectsDirty)), + 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][]*types.Log, len(self.logs)), |