diff --git a/core/state/statedb.go b/core/state/statedb.go index ae5e343c85..6ccbb72511 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -792,6 +792,24 @@ func (s *StateDB) RevertToSnapshot(revid int) { s.journal.revertToSnapshot(revid, s) } +// SnapshotReadList returns a deep copy of the current EIP-7928 state-read list. +// Pair with RestoreReadList: callers that may discard a transaction attempt +// (e.g. the miner reverting a failed tx via RevertToSnapshot) should restore +// the read list as well, since reads are not journaled and would otherwise +// leak into the next BAL emission via engine.Finalize. +func (s *StateDB) SnapshotReadList() *bal.StateAccessList { + if s.stateReadList == nil { + return nil + } + return s.stateReadList.Copy() +} + +// RestoreReadList replaces the current EIP-7928 state-read list with the given +// snapshot. See SnapshotReadList for the motivation. +func (s *StateDB) RestoreReadList(snap *bal.StateAccessList) { + s.stateReadList = snap +} + // GetRefund returns the current value of the refund counter. func (s *StateDB) GetRefund() uint64 { return s.refund diff --git a/miner/worker.go b/miner/worker.go index 0d590e4a3b..8eded33d81 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -444,13 +444,15 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio // applyTransaction runs the transaction. If execution fails, state and gas pool are reverted. func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*types.Receipt, error) { var ( - snap = env.state.Snapshot() - gp = env.gasPool.Snapshot() + snap = env.state.Snapshot() + gp = env.gasPool.Snapshot() + readSnap = env.state.SnapshotReadList() ) txAccesses, txMutations, receipt, err := core.ApplyTransaction(env.evm, env.gasPool, env.state, env.header, tx) if err != nil { env.state.RevertToSnapshot(snap) env.gasPool.Set(gp) + env.state.RestoreReadList(readSnap) return nil, err } if env.accessList != nil {