[SharovBot] fix: prestate tracer missing zero-codeHash accounts in post diffMode state#20656
[SharovBot] fix: prestate tracer missing zero-codeHash accounts in post diffMode state#20656erigon-copilot[bot] wants to merge 3 commits intorelease/3.4from
Conversation
…fMode
In diffMode, when a non-existent account is touched by a transaction (e.g., as
the target of a CALL), the account should appear in the post state with
codeHash=0x0 — matching go-ethereum's prestateTracer behaviour.
Previously, processDiffState used common.Hash{} (all zeros) as the default
prevCodeHash when no codeHash was stored for a pre-state account. For
non-existent accounts, GetCode returns empty, so newCodeHash was also computed
as common.Hash{} — the comparison prevCodeHash == newCodeHash meant the account
was never marked as modified and thus excluded from the post state.
go-ethereum uses EmptyCodeHash (keccak256("")) as the default prevCodeHash, so
for a non-existent account where GetCodeHash returns 0x0 (NilCodeHash), the
comparison 0x0 != EmptyCodeHash triggers modified=true, and the account appears
in post with codeHash=0x0.
Fix: mirror go-ethereum's logic by:
1. Using Exist() to distinguish non-existent accounts (codeHash=0x0) from
existing codeless accounts (codeHash=EmptyCodeHash).
2. Using accounts.EmptyCodeHash as the default prevCodeHash when no codeHash
is set in the pre-state.
This fixes debug_traceBlockByNumber diffMode prestate tests that expect the
reference implementation output (e.g. test_42 in erigon-qa).
Co-authored-by: Giulio Rebuffo <giulio.rebuffo@gmail.com>
…shing pre-existing codeless accounts from non-existent accounts in lookupAccount Co-authored-by: Giulio Rebuffo <giulio.rebuffo@gmail.com>
|
[SharovBot] pushed a follow-up fix to this branch. Problem: The previous commit changed Root cause: In Fix: Moved the
|
…es that broke unit tests The previous commits introduced Exist() checks in both lookupAccount and processDiffState to distinguish pre-existing codeless accounts from non-existent ones using EmptyCodeHash. This caused codeHash to leak into JSON output for EOAs and produced spurious codeHash diffs for accounts that went from non-existent to existent-but-codeless (e.g. coinbase). The fix simplifies the logic: only compute a non-zero codeHash when there is actual code. For codeless accounts (whether existing or not), codeHash remains zero/nil, which correctly omits it from JSON and avoids false diffs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Giulio Rebuffo <giulio.rebuffo@gmail.com>
[SharovBot]
Problem
In
debug_traceBlockByNumber(and related RPC methods) using theprestateTracerindiffMode, accounts that are touched for the first time during a transaction (e.g. the target of a CALL with zero balance) should appear in thepoststate withcodeHash: 0x0. Erigon was not including these entries, while the reference node (go-ethereum) was.Failing CI test:
mainnet-rpc-integ-tests-latest→debug_traceBlockByNumber/test_42.json(consistent across all 10 recentrelease/3.4commits)Root Cause
In
processDiffState(), the comparison to detect codeHash changes usedcommon.Hash{}(all zeros) as the defaultprevCodeHash. For non-existent accounts,newCodeHashwas also computed ascommon.Hash{}(sinceGetCodereturns empty bytes). This meantprevCodeHash == newCodeHash→modified = false→ the account was pruned from both pre and post.go-ethereum uses
EmptyCodeHash(keccak256("") = 0xc5d246...) as the defaultprevCodeHash. For non-existent accounts,GetCodeHashreturns0x0(NilCodeHash), so0x0 != EmptyCodeHash→modified = true→ the account appears in post withcodeHash: 0x0.Fix
Mirror go-ethereum's logic in
processDiffState():Exist()to distinguish non-existent accounts (codeHash = 0x0) from existing codeless accounts (codeHash = EmptyCodeHash).accounts.EmptyCodeHashas the defaultprevCodeHashwhen no codeHash is stored in the pre-state.Testing
go build ./execution/tracing/tracers/native/✅go test ./execution/tracing/...✅ all passdebug_traceBlockByNumber/test_42failure inmainnet-rpc-integ-tests-latestCI