Skip to content

core/state: track the block-level accessList#34803

Merged
rjl493456442 merged 12 commits into
ethereum:masterfrom
rjl493456442:journal-mutset
May 13, 2026
Merged

core/state: track the block-level accessList#34803
rjl493456442 merged 12 commits into
ethereum:masterfrom
rjl493456442:journal-mutset

Conversation

@rjl493456442
Copy link
Copy Markdown
Member

@rjl493456442 rjl493456442 commented Apr 23, 2026

This PR extends the journal to track the pre-transaction values of mutated balances, nonces, and code.

At the end of the transaction, these values are used to filter out no-op changes, such as balance transitions from a-> b->a. These changes are excluded from the block-level access list.

Additionally, there is a dedicated bal.ConstructionBlockAccessList objects for gathering the state reads and writes within the current transaction. These state writes will be keyed by the block accessList index.

Comment thread core/state_processor.go
Comment thread core/state/journal.go Outdated
Comment thread core/state/statedb.go
// code and storage is guaranteed to be empty, leaving nothing to
// clean up here.
balance := uint256.NewInt(0)
if state.balanceSet && balance.Cmp(state.balance) != 0 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It correctly catches the edge-case of a selfdestructing initcode in a prefunded account: a balance subtraction happens at the time the selfdestruct opcode is invoked.

Comment thread core/state/statedb.go
s.stateAccessList.NonceChange(addr, s.blockAccessIndex, nonce)
}
if state.codeSet {
if code := obj.Code(); !bytes.Equal(code, state.code) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth it to compare by hash here. I'm not sure how much performance difference it makes in practice.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good point.

In practice, the code change can be categorized as:

  • nil -> contract code
  • nil -> delegation
  • delegation -> nil
  • delegation a -> delegation b

for all these cases, the byte comparison is not expensive.

@jwasinger
Copy link
Copy Markdown
Contributor

Did a first pass through this. tentatively LGTM but would be good to get more eyes on it.

@jwasinger
Copy link
Copy Markdown
Contributor

Can you remind me what the plan was to track storage mutations?

@rjl493456442
Copy link
Copy Markdown
Member Author

Can you remind me what the plan was to track storage mutations?

stateObject.dirtyStorage is exactly what we want.

		// Aggregate storage writes into the block-level access list.
		// All slots in the dirtyStorage set must have post-transaction
		// values that differ from their pre-transaction values.
		if s.db.stateAccessList != nil {
			s.db.stateAccessList.StorageWrite(s.db.blockAccessIndex, s.address, key, value)
		}

Comment thread core/state/journal.go Outdated
Comment thread core/state/journal.go Outdated
@rjl493456442 rjl493456442 added this to the 1.17.4 milestone May 13, 2026
@rjl493456442 rjl493456442 merged commit b2aa698 into ethereum:master May 13, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants