mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
core/state: storage journal entry should revert dirtyness too
This commit is contained in:
parent
ac21f9bfb5
commit
23f4f7e708
2 changed files with 37 additions and 16 deletions
|
|
@ -129,8 +129,9 @@ type (
|
||||||
prev uint64
|
prev uint64
|
||||||
}
|
}
|
||||||
storageChange struct {
|
storageChange struct {
|
||||||
account *common.Address
|
account *common.Address
|
||||||
key, prevalue common.Hash
|
key common.Hash
|
||||||
|
prevvalue *common.Hash
|
||||||
}
|
}
|
||||||
codeChange struct {
|
codeChange struct {
|
||||||
account *common.Address
|
account *common.Address
|
||||||
|
|
@ -277,7 +278,7 @@ func (ch codeChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch storageChange) revert(s *StateDB) {
|
func (ch storageChange) revert(s *StateDB) {
|
||||||
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
|
s.getStateObject(*ch.account).setState(ch.key, ch.prevvalue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch storageChange) dirtied() *common.Address {
|
func (ch storageChange) dirtied() *common.Address {
|
||||||
|
|
@ -286,9 +287,9 @@ func (ch storageChange) dirtied() *common.Address {
|
||||||
|
|
||||||
func (ch storageChange) copy() journalEntry {
|
func (ch storageChange) copy() journalEntry {
|
||||||
return storageChange{
|
return storageChange{
|
||||||
account: ch.account,
|
account: ch.account,
|
||||||
key: ch.key,
|
key: ch.key,
|
||||||
prevalue: ch.prevalue,
|
prevvalue: ch.prevvalue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,13 +140,20 @@ func (s *stateObject) getTrie() (Trie, error) {
|
||||||
|
|
||||||
// GetState retrieves a value from the account storage trie.
|
// GetState retrieves a value from the account storage trie.
|
||||||
func (s *stateObject) GetState(key common.Hash) common.Hash {
|
func (s *stateObject) GetState(key common.Hash) common.Hash {
|
||||||
|
value, _ := s.getState(key)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// getState retrieves a value from the account storage trie and also returns if
|
||||||
|
// the slot is already dirty or not.
|
||||||
|
func (s *stateObject) getState(key common.Hash) (common.Hash, bool) {
|
||||||
// If we have a dirty value for this state entry, return it
|
// If we have a dirty value for this state entry, return it
|
||||||
value, dirty := s.dirtyStorage[key]
|
value, dirty := s.dirtyStorage[key]
|
||||||
if dirty {
|
if dirty {
|
||||||
return value
|
return value, true
|
||||||
}
|
}
|
||||||
// Otherwise return the entry's original value
|
// Otherwise return the entry's original value
|
||||||
return s.GetCommittedState(key)
|
return s.GetCommittedState(key), false
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommittedState retrieves a value from the committed account storage trie.
|
// GetCommittedState retrieves a value from the committed account storage trie.
|
||||||
|
|
@ -209,25 +216,38 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
||||||
|
|
||||||
// SetState updates a value in account storage.
|
// SetState updates a value in account storage.
|
||||||
func (s *stateObject) SetState(key, value common.Hash) {
|
func (s *stateObject) SetState(key, value common.Hash) {
|
||||||
// If the new value is the same as old, don't set
|
// If the new value is the same as old, don't set. Otherwise, track only the
|
||||||
prev := s.GetState(key)
|
// dirty changes, supporting reverting all of it back to no change.
|
||||||
|
prev, dirty := s.getState(key)
|
||||||
if prev == value {
|
if prev == value {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var prevvalue *common.Hash
|
||||||
|
if dirty {
|
||||||
|
prevvalue = &prev
|
||||||
|
}
|
||||||
// New value is different, update and journal the change
|
// New value is different, update and journal the change
|
||||||
s.db.journal.append(storageChange{
|
s.db.journal.append(storageChange{
|
||||||
account: &s.address,
|
account: &s.address,
|
||||||
key: key,
|
key: key,
|
||||||
prevalue: prev,
|
prevvalue: prevvalue,
|
||||||
})
|
})
|
||||||
if s.db.logger != nil && s.db.logger.OnStorageChange != nil {
|
if s.db.logger != nil && s.db.logger.OnStorageChange != nil {
|
||||||
s.db.logger.OnStorageChange(s.address, key, prev, value)
|
s.db.logger.OnStorageChange(s.address, key, prev, value)
|
||||||
}
|
}
|
||||||
s.setState(key, value)
|
s.setState(key, &value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stateObject) setState(key, value common.Hash) {
|
// setState updates a value in account dirty storage. If the value being set is
|
||||||
s.dirtyStorage[key] = value
|
// nil (assuming journal revert), the dirtyness is removed.
|
||||||
|
func (s *stateObject) setState(key common.Hash, value *common.Hash) {
|
||||||
|
// If the first set is being reverted, undo the dirty marker
|
||||||
|
if value == nil {
|
||||||
|
delete(s.dirtyStorage, key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Otherwise restore the previous value
|
||||||
|
s.dirtyStorage[key] = *value
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalise moves all dirty storage slots into the pending area to be hashed or
|
// finalise moves all dirty storage slots into the pending area to be hashed or
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue