mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
Force stateObject to update storage trie deterministically
This commit is contained in:
parent
26a37c5351
commit
bab696378c
1 changed files with 21 additions and 9 deletions
|
|
@ -77,8 +77,9 @@ type stateObject struct {
|
||||||
trie Trie // storage trie, which becomes non-nil on first access
|
trie Trie // storage trie, which becomes non-nil on first access
|
||||||
code Code // contract bytecode, which gets set when code is loaded
|
code Code // contract bytecode, which gets set when code is loaded
|
||||||
|
|
||||||
originStorage Storage // Storage cache of original entries to dedup rewrites
|
originStorage Storage // Storage cache of original entries to dedup rewrites
|
||||||
dirtyStorage Storage // Storage entries that need to be flushed to disk
|
dirtyStorage Storage // Storage entries that need to be flushed to disk
|
||||||
|
dirtyStorageKeys []common.Hash // Dirty storage keys in order of insertion into dirtyStorage
|
||||||
|
|
||||||
// Cache flags.
|
// Cache flags.
|
||||||
// When an object is marked suicided it will be delete from the trie
|
// When an object is marked suicided it will be delete from the trie
|
||||||
|
|
@ -111,12 +112,13 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject {
|
||||||
data.CodeHash = emptyCodeHash
|
data.CodeHash = emptyCodeHash
|
||||||
}
|
}
|
||||||
return &stateObject{
|
return &stateObject{
|
||||||
db: db,
|
db: db,
|
||||||
address: address,
|
address: address,
|
||||||
addrHash: crypto.Keccak256Hash(address[:]),
|
addrHash: crypto.Keccak256Hash(address[:]),
|
||||||
data: data,
|
data: data,
|
||||||
originStorage: make(Storage),
|
originStorage: make(Storage),
|
||||||
dirtyStorage: make(Storage),
|
dirtyStorage: make(Storage),
|
||||||
|
dirtyStorageKeys: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,12 +214,21 @@ func (self *stateObject) SetState(db Database, key, value common.Hash) {
|
||||||
|
|
||||||
func (self *stateObject) setState(key, value common.Hash) {
|
func (self *stateObject) setState(key, value common.Hash) {
|
||||||
self.dirtyStorage[key] = value
|
self.dirtyStorage[key] = value
|
||||||
|
for _, k := range self.dirtyStorageKeys {
|
||||||
|
if k == key {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.dirtyStorageKeys = append(self.dirtyStorageKeys, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateTrie writes cached storage modifications into the object's storage trie.
|
// updateTrie writes cached storage modifications into the object's storage trie.
|
||||||
func (self *stateObject) updateTrie(db Database) Trie {
|
func (self *stateObject) updateTrie(db Database) Trie {
|
||||||
tr := self.getTrie(db)
|
tr := self.getTrie(db)
|
||||||
for key, value := range self.dirtyStorage {
|
// Iterate through the storage keys in deterministic order to ensure the storage trie is
|
||||||
|
// identical across machines
|
||||||
|
for _, key := range self.dirtyStorageKeys {
|
||||||
|
value := self.dirtyStorage[key]
|
||||||
delete(self.dirtyStorage, key)
|
delete(self.dirtyStorage, key)
|
||||||
|
|
||||||
// Skip noop changes, persist actual changes
|
// Skip noop changes, persist actual changes
|
||||||
|
|
@ -303,6 +314,7 @@ func (self *stateObject) deepCopy(db *StateDB) *stateObject {
|
||||||
}
|
}
|
||||||
stateObject.code = self.code
|
stateObject.code = self.code
|
||||||
stateObject.dirtyStorage = self.dirtyStorage.Copy()
|
stateObject.dirtyStorage = self.dirtyStorage.Copy()
|
||||||
|
stateObject.dirtyStorageKeys = append([]common.Hash{}, self.dirtyStorageKeys...)
|
||||||
stateObject.originStorage = self.originStorage.Copy()
|
stateObject.originStorage = self.originStorage.Copy()
|
||||||
stateObject.suicided = self.suicided
|
stateObject.suicided = self.suicided
|
||||||
stateObject.dirtyCode = self.dirtyCode
|
stateObject.dirtyCode = self.dirtyCode
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue