rpc/jsonrpc: source executionWitness codes from pre-state reads#21518
Merged
Conversation
The witness `codes` field was built from RecordingState.GetAccessedCode() — every bytecode reached via GetCode/GetCodeSize during execution, including contracts created in-block. EEST fixtures are filled by Reth's Canonical witness mode, which only emits bytecodes loaded from pre-state by codehash and excludes in-block-created code (a stateless verifier re-derives that code by replaying the block). Sourcing from GetPreStateCode() (inner-reader / pre-block reads only) removes the over-inclusion. The stateless verifier already resolves created code via codeUpdates before consulting the witness codeMap, so nothing in the verify path regresses. Measured against the EEST zkevm@v0.4.0 corpus: codes-witness mismatches drop from 924 to 11, pass rate 94.6% -> 98.5%, zero stateless-execution or state-root regressions. The residual 11 are EEST negative-validation fixtures (deliberately truncated/padded witnesses) plus one same-codehash edge case. Refs #21307.
AskAlexSharov
approved these changes
May 30, 2026
This was referenced May 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
debug_executionWitness'scodesfield is built fromRecordingState.GetAccessedCode()— every bytecode reached viaGetCode/GetCodeSizeduring execution, including contracts created in-block. That matches Geth'switness.AddCodesemantics, but EEST fixtures (and the canonical stateless-witness format) are filled by Reth'sCanonicalmode, which only emits bytecodes loaded from pre-state by codehash and excludes in-block-created code. A stateless verifier re-derives created code by replaying the block, so emitting it is redundant over-inclusion.This is the dominant remaining source of
codes-witness divergence: a per-block +1 (sometimes +2) over-inclusion.Fix
Source the witness
codesfromGetPreStateCode()(inner-reader / pre-block reads only) instead ofGetAccessedCode(). One-line change plus a corrected doc comment.The stateless verifier (
witnessStateless.ReadAccountCode) already resolves in-block-created code fromcodeUpdates(written during re-execution) before consulting the witnesscodeMap, so the verify path does not regress.Evidence (EEST
zkevm@v0.4.0corpus, ~2,881 fixtures)maincodes path)codeswitness mismatchesA static sweep over all 924 pre-fix
codesmismatches found that 100% (925/925) of the over-included bytecodes were absent from pre-state — every one was created in-block (278 survive into post-state, e.g. cross-tx selfdestruct-to-self and in-block EIP-7702 delegation markers; the rest transient). Zero regressions vs the prior best; 111 newly-passing fixtures.The residual 11
codesmismatches are EESTeip8025_optional_proofs/witness_validation_codes/*negative-validation fixtures (deliberately truncated/padded witnesses that test a verifier's rejection path), plus one same-codehash edge case (witness_codes_create_same_hash_then_read).Notes
deleted ∧ ∉ pre-statesubset; the pre-state rule covers all in-block-created code).RecordingState.GetAccessedCode()/OnCodeAccessare now unused by the witness builder but remain wired into the IBS code-read path; removing that machinery is deferred to keep this diff surgical.Refs #21307.