diff options
author | Jeffrey Wilcke <jeffrey@ethereum.org> | 2017-02-23 06:29:59 +0800 |
---|---|---|
committer | Felix Lange <fjl@users.noreply.github.com> | 2017-02-23 06:29:59 +0800 |
commit | 024d41d0c2660d8f1dfbeb14921c7109e30493a2 (patch) | |
tree | a2b4ed630b84084c7f439d1539ed0551ec729cbd /core/state | |
parent | 46ec4357e73dd0c43951d11638d9aed94f8ffd29 (diff) | |
download | go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.tar go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.tar.gz go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.tar.bz2 go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.tar.lz go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.tar.xz go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.tar.zst go-tangerine-024d41d0c2660d8f1dfbeb14921c7109e30493a2.zip |
core, core/state, core/vm: remove exported account getters (#3618)
Removed exported statedb object accessors, reducing the chance for nasty
bugs to creep in. It's also ugly and unnecessary to have these methods.
Diffstat (limited to 'core/state')
-rw-r--r-- | core/state/journal.go | 12 | ||||
-rw-r--r-- | core/state/managed_state.go | 6 | ||||
-rw-r--r-- | core/state/managed_state_test.go | 2 | ||||
-rw-r--r-- | core/state/state_object.go | 84 | ||||
-rw-r--r-- | core/state/state_test.go | 12 | ||||
-rw-r--r-- | core/state/statedb.go | 77 | ||||
-rw-r--r-- | core/state/statedb_test.go | 7 |
7 files changed, 99 insertions, 101 deletions
diff --git a/core/state/journal.go b/core/state/journal.go index 68d07fa03..5cd41477d 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -34,7 +34,7 @@ type ( account *common.Address } resetObjectChange struct { - prev *StateObject + prev *stateObject } suicideChange struct { account *common.Address @@ -86,7 +86,7 @@ func (ch resetObjectChange) undo(s *StateDB) { } func (ch suicideChange) undo(s *StateDB) { - obj := s.GetStateObject(*ch.account) + obj := s.getStateObject(*ch.account) if obj != nil { obj.suicided = ch.prev obj.setBalance(ch.prevbalance) @@ -103,19 +103,19 @@ func (ch touchChange) undo(s *StateDB) { } func (ch balanceChange) undo(s *StateDB) { - s.GetStateObject(*ch.account).setBalance(ch.prev) + s.getStateObject(*ch.account).setBalance(ch.prev) } func (ch nonceChange) undo(s *StateDB) { - s.GetStateObject(*ch.account).setNonce(ch.prev) + s.getStateObject(*ch.account).setNonce(ch.prev) } func (ch codeChange) undo(s *StateDB) { - s.GetStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) + s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) } func (ch storageChange) undo(s *StateDB) { - s.GetStateObject(*ch.account).setState(ch.key, ch.prevalue) + s.getStateObject(*ch.account).setState(ch.key, ch.prevalue) } func (ch refundChange) undo(s *StateDB) { diff --git a/core/state/managed_state.go b/core/state/managed_state.go index 0d8f9dd28..1390ef4a0 100644 --- a/core/state/managed_state.go +++ b/core/state/managed_state.go @@ -23,7 +23,7 @@ import ( ) type account struct { - stateObject *StateObject + stateObject *stateObject nstart uint64 nonces []bool } @@ -128,7 +128,7 @@ func (ms *ManagedState) getAccount(addr common.Address) *account { } else { // Always make sure the state account nonce isn't actually higher // 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() { ms.accounts[addr] = newAccount(so) } @@ -138,6 +138,6 @@ func (ms *ManagedState) getAccount(addr common.Address) *account { return ms.accounts[addr] } -func newAccount(so *StateObject) *account { +func newAccount(so *stateObject) *account { return &account{so, so.Nonce(), nil} } diff --git a/core/state/managed_state_test.go b/core/state/managed_state_test.go index 0a3be9f5a..ea5737a08 100644 --- a/core/state/managed_state_test.go +++ b/core/state/managed_state_test.go @@ -30,7 +30,7 @@ func create() (*ManagedState, *account) { statedb, _ := New(common.Hash{}, db) ms := ManageState(statedb) ms.StateDB.SetNonce(addr, 100) - ms.accounts[addr] = newAccount(ms.StateDB.GetStateObject(addr)) + ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr)) return ms, ms.accounts[addr] } diff --git a/core/state/state_object.go b/core/state/state_object.go index da1914c9b..4fb69b646 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -57,13 +57,13 @@ func (self Storage) Copy() Storage { return cpy } -// StateObject represents an Ethereum account which is being modified. +// 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 { address common.Address // Ethereum address of this account data Account db *StateDB @@ -93,7 +93,7 @@ type StateObject struct { } // empty returns whether the account is considered empty. -func (s *StateObject) empty() bool { +func (s *stateObject) empty() bool { return s.data.Nonce == 0 && s.data.Balance.BitLen() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) } @@ -107,29 +107,29 @@ type Account struct { } // newObject creates a state object. -func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *StateObject { +func newObject(db *StateDB, 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{db: db, address: address, data: data, cachedStorage: make(Storage), dirtyStorage: make(Storage), onDirty: onDirty} + return &stateObject{db: db, address: address, data: data, cachedStorage: make(Storage), dirtyStorage: make(Storage), onDirty: onDirty} } // EncodeRLP implements rlp.Encoder. -func (c *StateObject) EncodeRLP(w io.Writer) error { +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) { +func (self *stateObject) setError(err error) { if self.dbErr == nil { self.dbErr = err } } -func (self *StateObject) markSuicided() { +func (self *stateObject) markSuicided() { self.suicided = true if self.onDirty != nil { self.onDirty(self.Address()) @@ -140,7 +140,7 @@ func (self *StateObject) markSuicided() { } } -func (c *StateObject) touch() { +func (c *stateObject) touch() { c.db.journal = append(c.db.journal, touchChange{ account: &c.address, prev: c.touched, @@ -152,7 +152,7 @@ func (c *StateObject) touch() { c.touched = true } -func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie { +func (c *stateObject) getTrie(db trie.Database) *trie.SecureTrie { if c.trie == nil { var err error c.trie, err = trie.NewSecure(c.data.Root, db, 0) @@ -165,7 +165,7 @@ func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie { } // GetState returns a value in account storage. -func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash { +func (self *stateObject) GetState(db trie.Database, key common.Hash) common.Hash { value, exists := self.cachedStorage[key] if exists { return value @@ -185,7 +185,7 @@ func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash } // SetState updates a value in account storage. -func (self *StateObject) SetState(db trie.Database, key, value common.Hash) { +func (self *stateObject) SetState(db trie.Database, key, value common.Hash) { self.db.journal = append(self.db.journal, storageChange{ account: &self.address, key: key, @@ -194,7 +194,7 @@ func (self *StateObject) SetState(db trie.Database, key, value common.Hash) { self.setState(key, value) } -func (self *StateObject) setState(key, value common.Hash) { +func (self *stateObject) setState(key, value common.Hash) { self.cachedStorage[key] = value self.dirtyStorage[key] = value @@ -205,7 +205,7 @@ func (self *StateObject) setState(key, value common.Hash) { } // updateTrie writes cached storage modifications into the object's storage trie. -func (self *StateObject) updateTrie(db trie.Database) { +func (self *stateObject) updateTrie(db trie.Database) { tr := self.getTrie(db) for key, value := range self.dirtyStorage { delete(self.dirtyStorage, key) @@ -220,14 +220,14 @@ func (self *StateObject) updateTrie(db trie.Database) { } // UpdateRoot sets the trie root to the current root hash of -func (self *StateObject) updateRoot(db trie.Database) { +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 { +func (self *stateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) error { self.updateTrie(db) if self.dbErr != nil { return self.dbErr @@ -241,7 +241,7 @@ func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) e // AddBalance removes amount from c's balance. // It is used to add funds to the destination account of a transfer. -func (c *StateObject) AddBalance(amount *big.Int) { +func (c *stateObject) AddBalance(amount *big.Int) { // EIP158: We must check emptiness for the objects such that the account // clearing (0,0,0 objects) can take effect. if amount.Cmp(common.Big0) == 0 { @@ -260,7 +260,7 @@ func (c *StateObject) AddBalance(amount *big.Int) { // SubBalance removes amount from c's balance. // It is used to remove funds from the origin account of a transfer. -func (c *StateObject) SubBalance(amount *big.Int) { +func (c *stateObject) SubBalance(amount *big.Int) { if amount.Cmp(common.Big0) == 0 { return } @@ -271,7 +271,7 @@ func (c *StateObject) SubBalance(amount *big.Int) { } } -func (self *StateObject) SetBalance(amount *big.Int) { +func (self *stateObject) SetBalance(amount *big.Int) { self.db.journal = append(self.db.journal, balanceChange{ account: &self.address, prev: new(big.Int).Set(self.data.Balance), @@ -279,7 +279,7 @@ func (self *StateObject) SetBalance(amount *big.Int) { self.setBalance(amount) } -func (self *StateObject) setBalance(amount *big.Int) { +func (self *stateObject) setBalance(amount *big.Int) { self.data.Balance = amount if self.onDirty != nil { self.onDirty(self.Address()) @@ -288,9 +288,9 @@ func (self *StateObject) setBalance(amount *big.Int) { } // Return the gas back to the origin. Used by the Virtual machine or Closures -func (c *StateObject) ReturnGas(gas *big.Int) {} +func (c *stateObject) ReturnGas(gas *big.Int) {} -func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *StateObject { +func (self *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *stateObject { stateObject := newObject(db, self.address, self.data, onDirty) stateObject.trie = self.trie stateObject.code = self.code @@ -307,12 +307,12 @@ func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address) // // Returns the address of the contract/account -func (c *StateObject) Address() common.Address { +func (c *stateObject) Address() common.Address { return c.address } // Code returns the contract code associated with this object, if any. -func (self *StateObject) Code(db trie.Database) []byte { +func (self *stateObject) Code(db trie.Database) []byte { if self.code != nil { return self.code } @@ -327,7 +327,7 @@ func (self *StateObject) Code(db trie.Database) []byte { return code } -func (self *StateObject) SetCode(codeHash common.Hash, code []byte) { +func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { prevcode := self.Code(self.db.db) self.db.journal = append(self.db.journal, codeChange{ account: &self.address, @@ -337,7 +337,7 @@ func (self *StateObject) SetCode(codeHash common.Hash, code []byte) { self.setCode(codeHash, code) } -func (self *StateObject) setCode(codeHash common.Hash, code []byte) { +func (self *stateObject) setCode(codeHash common.Hash, code []byte) { self.code = code self.data.CodeHash = codeHash[:] self.dirtyCode = true @@ -347,7 +347,7 @@ func (self *StateObject) setCode(codeHash common.Hash, code []byte) { } } -func (self *StateObject) SetNonce(nonce uint64) { +func (self *stateObject) SetNonce(nonce uint64) { self.db.journal = append(self.db.journal, nonceChange{ account: &self.address, prev: self.data.Nonce, @@ -355,7 +355,7 @@ func (self *StateObject) SetNonce(nonce uint64) { self.setNonce(nonce) } -func (self *StateObject) setNonce(nonce uint64) { +func (self *stateObject) setNonce(nonce uint64) { self.data.Nonce = nonce if self.onDirty != nil { self.onDirty(self.Address()) @@ -363,37 +363,21 @@ func (self *StateObject) setNonce(nonce uint64) { } } -func (self *StateObject) CodeHash() []byte { +func (self *stateObject) CodeHash() []byte { return self.data.CodeHash } -func (self *StateObject) Balance() *big.Int { +func (self *stateObject) Balance() *big.Int { return self.data.Balance } -func (self *StateObject) Nonce() uint64 { +func (self *stateObject) Nonce() uint64 { 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 // as a vm.Account interface that also satisfies the vm.ContractRef // interface. Interfaces are awesome. -func (self *StateObject) Value() *big.Int { - panic("Value on StateObject should never be called") -} - -func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) { - // When iterating over the storage check the cache first - for h, value := range self.cachedStorage { - cb(h, value) - } - - it := self.getTrie(self.db.db).Iterator() - for it.Next() { - // ignore cached values - key := common.BytesToHash(self.trie.GetKey(it.Key)) - if _, ok := self.cachedStorage[key]; !ok { - cb(key, common.BytesToHash(it.Value)) - } - } +func (self *stateObject) Value() *big.Int { + panic("Value on stateObject should never be called") } diff --git a/core/state/state_test.go b/core/state/state_test.go index 435d1d829..3bc63c148 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -152,7 +152,7 @@ func TestSnapshot2(t *testing.T) { state.SetState(stateobjaddr1, storageaddr, data1) // db, trie are already non-empty values - so0 := state.GetStateObject(stateobjaddr0) + so0 := state.getStateObject(stateobjaddr0) so0.SetBalance(big.NewInt(42)) so0.SetNonce(43) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) @@ -164,7 +164,7 @@ func TestSnapshot2(t *testing.T) { state.Reset(root) // and one with deleted == true - so1 := state.GetStateObject(stateobjaddr1) + so1 := state.getStateObject(stateobjaddr1) so1.SetBalance(big.NewInt(52)) so1.SetNonce(53) so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}) @@ -172,7 +172,7 @@ func TestSnapshot2(t *testing.T) { so1.deleted = true state.setStateObject(so1) - so1 = state.GetStateObject(stateobjaddr1) + so1 = state.getStateObject(stateobjaddr1) if so1 != nil { t.Fatalf("deleted object not nil when getting") } @@ -180,7 +180,7 @@ func TestSnapshot2(t *testing.T) { snapshot := state.Snapshot() state.RevertToSnapshot(snapshot) - so0Restored := state.GetStateObject(stateobjaddr0) + so0Restored := state.getStateObject(stateobjaddr0) // Update lazily-loaded values before comparing. so0Restored.GetState(db, storageaddr) so0Restored.Code(db) @@ -188,13 +188,13 @@ func TestSnapshot2(t *testing.T) { compareStateObjects(so0Restored, so0, t) // deleted should be nil, both before and after restore of state copy - so1Restored := state.GetStateObject(stateobjaddr1) + so1Restored := state.getStateObject(stateobjaddr1) if so1Restored != nil { 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() { t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address) } 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)), diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 874317300..597de3be5 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -331,12 +331,11 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) // Check storage. - if obj := state.GetStateObject(addr); obj != nil { - obj.ForEachStorage(func(key, val common.Hash) bool { + if obj := state.getStateObject(addr); obj != nil { + state.ForEachStorage(addr, func(key, val common.Hash) bool { return checkeq("GetState("+key.Hex()+")", val, checkstate.GetState(addr, key)) }) - checkobj := checkstate.GetStateObject(addr) - checkobj.ForEachStorage(func(key, checkval common.Hash) bool { + checkstate.ForEachStorage(addr, func(key, checkval common.Hash) bool { return checkeq("GetState("+key.Hex()+")", state.GetState(addr, key), checkval) }) } |