Skip to content

execution/state: preserve EIP-8246 balance reads after selfdestruct - #24096

Draft
yperbasis wants to merge 1 commit into
mainfrom
fix/eip8246-preserved-balance-read
Draft

yperbasis wants to merge 1 commit into
mainfrom
fix/eip8246-preserved-balance-read

Conversation

@yperbasis

Copy link
Copy Markdown
Member

Fixes #23238.

When a balance-preserving SELFDESTRUCT publishes no BalancePath cell, a later transaction can read zero from an older balance cell while applySubFieldWrites preserves its value. The validator also rejects the preserved nonzero read after the reader is corrected.

Exclude balance cells from both destruct wipe scans. A burning SELFDESTRUCT writes zero explicitly; a preserving one leaves the prior balance intact. Balance version and value checks still detect changed writes.

Add a regression that flushes a real preserving self-destruct write set, verifies the missing balance cell, and checks the later balance against reconstruction, its recorded dependencies, and read-set validation. Update the existing wipe fixtures to use an explicit balance burn or a nonce that SELFDESTRUCT actually clears.

Validation:

  • The regression failed with balance 0 instead of 7 before the fix, then failed validation with only the reader fixed, and passes with both changes.
  • go test ./execution/state -count=1
  • go test -race ./execution/state -count=1
  • make lint
  • make erigon integration

The regression exercises the state APIs directly. Reachability through a valid EVM transaction remains unverified.

Copilot AI left a comment

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.

🔵 Needs a closer look

It changes consensus-critical state-read validation, and valid EVM transaction reachability remains unverified.

Pull request overview

Fixes EIP-8246 balance reads after balance-preserving SELFDESTRUCT.

Changes:

  • Excludes preserved balances from destruct wipe scans and validation.
  • Adds regression coverage for retained balance cells.
  • Updates self-destruct test fixtures.
File summaries
File Description
execution/state/versionmap.go Aligns balance validation with preservation semantics.
execution/state/versionmap_test.go Updates self-destruct validation fixtures.
execution/state/revival_consistency_test.go Changes the synthetic revival fixture.
execution/state/read_paths.go Preserves earlier balance cells during reads.
execution/state/eip8246_selfdestruct_test.go Adds end-to-end state API regression coverage.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +121 to 124
rs.SetNonce(addr, VersionedRead[uint64]{
ReadHeader: ReadHeader{Source: MapRead, Version: Version{TxIndex: 0}},
Val: *uint256.NewInt(1_000),
Val: 1,
})

@AskAlexSharov AskAlexSharov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Lean already.

vm := NewVersionMap(nil)
writeFor(vm, addr, BalancePath, accounts.NilKey, Version{TxIndex: 0, Incarnation: 0}, *uint256.NewInt(1_000), true)
writeFor(vm, addr, SelfDestructPath, accounts.NilKey, Version{TxIndex: 2, Incarnation: 0}, true, true)
vm.WriteBalance(addr, Version{TxIndex: 2}, uint256.Int{}, true)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

L589: test: the new balance write at tx 2 makes this fail on the plain version check, so it no longer reaches the SD-staleness branch it is named after. A nonce read, as in the next test, reaches it again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EIP-8246: versionedReadCore wipes a preserved balance that applySubFieldWrites keeps

3 participants