execution/execmodule: wire stateCache into canonical UpdateForkChoice#21042
Merged
execution/execmodule: wire stateCache into canonical UpdateForkChoice#21042
Conversation
SetStateCache(e.stateCache) was only called from ValidateChain (fork validation). The canonical execution path in updateForkChoice constructs its own SharedDomains and runs the staged sync pipeline through it without ever wiring the cache, so every Account/Storage/Code read on the canonical path went straight to aggTx (MDBX -> snapshot files) uncached. Effect was invisible because hit/miss counters for the cache layer were not exposed in metrics — only the sd.mem hit count was. Diagnostic log + counter audit on a perf-devnet-3 cold bench confirmed SetStateCache fired zero times across 611 canonical payload validations under EXEC3_PARALLEL=true. After this one-line plumbing fix, the same bench shows the cache absorbing ~23% of CommitmentDomain-adjacent reads on the bloat TEST block, with MDBX read count dropping from 68 to 19. Correctness preserved (0 trie-root divergences across the canonical SETUP+TEST sequence). ValidateChain's own SetStateCache call at exec_module.go:523 is left unchanged — fork validation already had it. This PR is the missing counterpart for the canonical path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
yperbasis
approved these changes
May 8, 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.
Summary
SharedDomains.SetStateCachewas only invoked fromValidateChain(fork-validation path, exec_module.go:523). The canonical execution path inupdateForkChoiceconstructs its ownSharedDomains(forkchoice.go:211) and runs the staged sync pipeline through it without ever wiring the cache, so every Account/Storage/Code read on the canonical path went straight toaggTx(MDBX → snapshot files) uncached.Why it was invisible
Hit/miss counters for the
stateCachelayer aren't surfaced in metrics —sd.metrics.CacheReadCountonly trackssd.memhits, andCacheGetCountis a defined-but-never-incremented field. So a quick glance at[domain reads]log lines (cache=2 puts=8 ... gets=0) gave no signal that the cache layer wasn't being consulted at all on the canonical path.A diagnostic log added inside
SetStateCacheconfirmed it fired zero times across 611 canonicalengine_newPayloadV4 → engine_forkchoiceUpdatedV3calls on a perf-devnet-3 cold bench underEXEC3_PARALLEL=true.Fix
One-line addition in
updateForkChoiceafter the existingSetInMemHistoryReadscall:Mirrors what
ValidateChaindoes.SetStateCacheis already gated ondbg.UseStateCacheand a non-nil cache, so behavior is unchanged when either is false.Effect
After the fix, the same cold bench on perf-devnet-3 shows the cache absorbing ~23% of reads on the SSTORE-bloat TEST block, with MDBX read count dropping from 68 to 19 per block. File-read count is essentially unchanged because cache misses still fall through to the snapshot-file path — but the cache is now actually doing its job on the canonical path, which was its design intent.
Correctness preserved: 0 trie-root divergences across the canonical SETUP+TEST sequence.
Test plan
make lint, unit tests)EXEC3_PARALLEL=true: SETUP 610 blocks + TEST block all VALID, 0 divergences[state-cache] SetStateCache enabled on SD(diagnostic log added during investigation, not part of this PR) confirmed firing 613 times across the bench🤖 Generated with Claude Code