mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
core/state: avoid polluting EIP-7928 read list in SelfDestructRefundB… (#34848)
…ytes SelfDestructRefundBytes iterates s.stateObjects and previously called IsNewContract / HasSelfDestructed on each entry to filter for accounts that were both created and selfdestructed in the current transaction. Both helpers go through StateDB.getStateObject, which unconditionally records an EIP-7928 account read via s.stateReadList.AddAccount(addr). The effect is that *every* live entry in the stateObjects cache gets added to the per-tx read list whenever a tx triggers the EIP-8037 selfdestruct refund check (i.e. on every successful tx post-Amsterdam). This pollutes the BAL with addresses the tx never actually touched. In the miner, the cache may contain accounts loaded by earlier failed-tx attempts (preCheck via getStateObject loaded them; RevertToSnapshot does not evict the cache because reads aren't journaled). Validators re-executing the sealed block don't have those cached entries, so they don't reproduce the reads. Result: BAL hash mismatch on otherwise deterministic execution. Use direct field access on the already-iterated *stateObject so the filter doesn't go through getStateObject. Functionally equivalent -- newContract and selfDestructed are the same fields the helpers consult -- but with no read-list side effect.
This commit is contained in:
parent
f59ec20794
commit
e079c9353a
1 changed files with 4 additions and 2 deletions
|
|
@ -810,10 +810,12 @@ func (s *StateDB) StateChangedBytes(revid int, excludeSubcalls bool) int64 {
|
|||
// for accounts that were both created and selfdestructed during this
|
||||
// transaction.
|
||||
func (s *StateDB) SelfDestructRefundBytes() int64 {
|
||||
// Collect addresses created and selfdestructed in this tx.
|
||||
// Read fields directly off the iterated obj. Routing through
|
||||
// IsNewContract / HasSelfDestructed would call getStateObject for
|
||||
// every cached entry, adding it to the EIP-7928 read list.
|
||||
targets := make(map[common.Address]*stateObject)
|
||||
for addr, obj := range s.stateObjects {
|
||||
if s.IsNewContract(addr) && s.HasSelfDestructed(addr) {
|
||||
if obj.newContract && obj.selfDestructed {
|
||||
targets[addr] = obj
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue