From 4f599282b32cfd668bea556204fcdcf03dce2a67 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Fri, 6 Mar 2026 15:55:30 +0800 Subject: [PATCH] fix(core): remove slot dirtyness if it's set back to origin value #29731 #31874 (#2080) --- core/state/journal.go | 13 +++++-------- core/state/state_object.go | 37 ++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/core/state/journal.go b/core/state/journal.go index 76c2ee93e7..67f658abda 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -141,7 +141,8 @@ type ( storageChange struct { account common.Address key common.Hash - prevvalue *common.Hash + prevvalue common.Hash + origvalue common.Hash } codeChange struct { account common.Address @@ -287,7 +288,7 @@ func (ch codeChange) copy() journalEntry { } 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 { @@ -295,15 +296,11 @@ func (ch storageChange) dirtied() *common.Address { } func (ch storageChange) copy() journalEntry { - var prevvalue *common.Hash - if ch.prevvalue != nil { - copied := *ch.prevvalue - prevvalue = &copied - } return storageChange{ account: ch.account, key: ch.key, - prevvalue: prevvalue, + prevvalue: ch.prevvalue, + origvalue: ch.origvalue, } } diff --git a/core/state/state_object.go b/core/state/state_object.go index 8074a4b57c..6188ac340f 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -137,16 +137,15 @@ func (s *stateObject) GetState(key common.Hash) common.Hash { 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 +// getState retrieves a value associated with the given storage key, along with +// its original value. +func (s *stateObject) getState(key common.Hash) (common.Hash, common.Hash) { + origin := s.GetCommittedState(key) value, dirty := s.dirtyStorage[key] if dirty { - return value, true + return value, origin } - // Otherwise return the entry's original value - return s.GetCommittedState(key), false + return origin, origin } 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 { // 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. - prev, dirty := s.getState(key) + prev, origin := s.getState(key) if prev == value { return prev } - var prevvalue *common.Hash - if dirty { - prevvalue = &prev - } // New value is different, update and journal the change s.db.journal.append(storageChange{ account: s.address, key: key, - prevvalue: prevvalue, + prevvalue: prev, + origvalue: origin, }) - s.setState(key, &value) + s.setState(key, value, origin) return prev } -// setState updates a value in account dirty storage. If the value being set is -// nil (assuming journal revert), the dirtiness 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 { +// setState updates a value in account dirty storage. The dirtiness will be +// removed if the value being set equals to the original value. +func (s *stateObject) setState(key common.Hash, value common.Hash, origin common.Hash) { + // Storage slot is set back to its original value, undo the dirty marker + if value == origin { delete(s.dirtyStorage, key) 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