Skip to content

db/state/execctx: fix AccountsDomain codeHash decode (DeserialiseV3) — correctness#21623

Closed
mh0lt wants to merge 1 commit into
mh/perf-statecache-lru-prfrom
mh/fix-codehash-deserialise-v3
Closed

db/state/execctx: fix AccountsDomain codeHash decode (DeserialiseV3) — correctness#21623
mh0lt wants to merge 1 commit into
mh/perf-statecache-lru-prfrom
mh/fix-codehash-deserialise-v3

Conversation

@mh0lt

@mh0lt mh0lt commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Correctness fix

codeHashForAddr resolves an account's codeHash from the AccountsDomain so the CodeDomain ethHash bypass can serve shared bytecode (proxies, clones, ERC-20 holder sets) without an addr-keyed file read.

decodeAccountCodeHash decoded the account value with acc.DecodeForStorage, but AccountsDomain values are SerialiseV3-encoded. DecodeForStorage is the legacy MDBX bitmask format with an incompatible binary layout — applied to V3 bytes it silently misparses and leaves CodeHash empty.

Consequently codeHashForAddr returned nil for every account, and the ethHash bypass never engaged for any contract: every CodeDomain read that missed the addr cache fell through to a file read. This is a decoding-correctness bug — the wrong decoder applied to the stored encoding.

Fix

Use accounts.DeserialiseV3, the matching decoder for AccountsDomain values. One-function change; no behaviour change for valid encodings other than producing the correct codeHash.

Verification (instrumented mainnet-tip run)

The codeHashForAddr resolve path and ethHash bypass were instrumented:

metric before after
ethHash bypass served% (cache, no file read) 0 56 → 72 → 83% (climbs as dedup warms)
resolve produced no codeHash for a contract-with-code ~99% 0
GetByEthHash calls 0 (never reached) active, 83% hit

Routing

The buggy decodeAccountCodeHash/codeHashForAddr is introduced by #21386 (StateCache LRU) and does not exist on main, so the fix targets #21386 — the appropriate point in the perf stack. It flows up to #21414 / #21416 / #20893 (all stacked on this branch). To be cherry-picked into those branches as needed.

🤖 Generated with Claude Code

codeHashForAddr resolves an account's codeHash from the AccountsDomain so
the CodeDomain ethHash bypass can serve shared bytecode without an
addr-keyed file read. decodeAccountCodeHash decoded the account value with
acc.DecodeForStorage, but AccountsDomain values are SerialiseV3-encoded.
DecodeForStorage is the legacy MDBX bitmask format with an incompatible
binary layout; applied to V3 bytes it silently misparses and leaves
CodeHash empty.

As a result codeHashForAddr returned nil for every account and the ethHash
bypass never engaged for any contract — every CodeDomain read that missed
the addr cache fell through to a file read. This is a decoding-correctness
bug: the wrong decoder is applied to the stored encoding.

Use accounts.DeserialiseV3, the matching decoder for AccountsDomain values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mh0lt

mh0lt commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Folding this fix directly into #21386 instead — the buggy code is introduced there (not on main), so updating the PR branch is cleaner than stacking a separate PR. Same commit (fd74979) pushed to mh/perf-statecache-lru-pr.

@mh0lt mh0lt closed this Jun 4, 2026
@mh0lt mh0lt deleted the mh/fix-codehash-deserialise-v3 branch June 4, 2026 16:15
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.

1 participant