fix(core): remove slot dirtyness if it's set back to origin value #29731 #31874 (#2080)

This commit is contained in:
Daniel Liu 2026-03-06 15:55:30 +08:00 committed by GitHub
parent 92ffb4dba7
commit 4f599282b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 29 deletions

View file

@ -141,7 +141,8 @@ type (
storageChange struct { storageChange struct {
account common.Address account common.Address
key common.Hash key common.Hash
prevvalue *common.Hash prevvalue common.Hash
origvalue common.Hash
} }
codeChange struct { codeChange struct {
account common.Address account common.Address
@ -287,7 +288,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.prevvalue) s.getStateObject(ch.account).setState(ch.key, ch.prevvalue, ch.origvalue)
} }
func (ch storageChange) dirtied() *common.Address { func (ch storageChange) dirtied() *common.Address {
@ -295,15 +296,11 @@ func (ch storageChange) dirtied() *common.Address {
} }
func (ch storageChange) copy() journalEntry { func (ch storageChange) copy() journalEntry {
var prevvalue *common.Hash
if ch.prevvalue != nil {
copied := *ch.prevvalue
prevvalue = &copied
}
return storageChange{ return storageChange{
account: ch.account, account: ch.account,
key: ch.key, key: ch.key,
prevvalue: prevvalue, prevvalue: ch.prevvalue,
origvalue: ch.origvalue,
} }
} }

View file

@ -137,16 +137,15 @@ func (s *stateObject) GetState(key common.Hash) common.Hash {
return value return value
} }
// getState retrieves a value from the account storage trie and also returns if // getState retrieves a value associated with the given storage key, along with
// the slot is already dirty or not. // its original value.
func (s *stateObject) getState(key common.Hash) (common.Hash, bool) { func (s *stateObject) getState(key common.Hash) (common.Hash, common.Hash) {
// If we have a dirty value for this state entry, return it origin := s.GetCommittedState(key)
value, dirty := s.dirtyStorage[key] value, dirty := s.dirtyStorage[key]
if dirty { if dirty {
return value, true return value, origin
} }
// Otherwise return the entry's original value return origin, origin
return s.GetCommittedState(key), false
} }
func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
@ -190,34 +189,30 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
func (s *stateObject) SetState(key, value common.Hash) common.Hash { func (s *stateObject) SetState(key, value common.Hash) common.Hash {
// If the new value is the same as old, don't set. Otherwise, track only the // If the new value is the same as old, don't set. Otherwise, track only the
// dirty changes, supporting reverting all of it back to no change. // dirty changes, supporting reverting all of it back to no change.
prev, dirty := s.getState(key) prev, origin := s.getState(key)
if prev == value { if prev == value {
return prev return prev
} }
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,
prevvalue: prevvalue, prevvalue: prev,
origvalue: origin,
}) })
s.setState(key, &value) s.setState(key, value, origin)
return prev return prev
} }
// setState updates a value in account dirty storage. If the value being set is // setState updates a value in account dirty storage. The dirtiness will be
// nil (assuming journal revert), the dirtiness is removed. // removed if the value being set equals to the original value.
func (s *stateObject) setState(key common.Hash, value *common.Hash) { func (s *stateObject) setState(key common.Hash, value common.Hash, origin common.Hash) {
// If the first set is being reverted, undo the dirty marker // Storage slot is set back to its original value, undo the dirty marker
if value == nil { if value == origin {
delete(s.dirtyStorage, key) delete(s.dirtyStorage, key)
return return
} }
// Otherwise set/update the dirty slot value (or restore it when invoked from a revert) s.dirtyStorage[key] = 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