fix: use cumulative prefix sets for incremental trie state root#445
fix: use cumulative prefix sets for incremental trie state root#445
Conversation
b74a166 to
baa5064
Compare
docs/TRIE_CACHE_BENCHMARK_REPORT.md
Outdated
There was a problem hiding this comment.
We can keep the bench but maybe not the result?
If we choose to keep the result, atleast move it in crates/op-builder/benches/docs or results.
There was a problem hiding this comment.
I will move it to the benches folder, want a template for what the benchmark reports should look like
There was a problem hiding this comment.
Maybe add a template then instead of an example?
akundaz
left a comment
There was a problem hiding this comment.
The benchmark and tests run against replicated state root calculations instead of the actual production code path. Can you extract the code to run this calculation and and update the benchmark and tests to call that directly? Otherwise we can't really draw conclusions about real world performance from these results. And if the code drifts we should be able to catch with our tests and the benchmark.
The incremental trie cache produces wrong state roots when a storage slot modified in flashblock N reverts in flashblock N+1. The reverted slot disappears from the cumulative HashedPostState, so its nibble path is missing from the prefix set. The trie walker skips the subtree and uses the stale cached hash from the previous flashblock's branch node. Fix: track cumulative TriePrefixSetsMut across all flashblocks. Before building TrieInput, extend the current prefix sets with all prior flashblocks' prefix sets. This forces the walker to re-visit every path modified in earlier flashblocks. The fix is also ~30% faster than the unfixed incremental path because descending into cached in-memory nodes is faster than DB cursor seeks for skipped branches. Benchmarks (10 flashblocks, 50k accounts): - Without cache: ~2,200ms (baseline) - Incremental (no fix): ~844ms (2.6x faster, incorrect on reverts) - Incremental (with fix): ~650ms (3.4x faster, correct) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract the incremental state root calculation logic from build_flashblock_payload_inner into builder::state_root::compute_state_root. Tests and benchmarks now call the same function as production code, ensuring they exercise the actual code path rather than replicated logic that could drift. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c866328 to
56da125
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix: track cumulative TriePrefixSetsMut across all flashblocks. Before building TrieInput, extend the current prefix sets with all prior flashblocks' prefix sets. This forces the walker to re-visit every path modified in earlier flashblocks.
The fix is also ~30% faster than the unfixed incremental path because descending into cached in-memory nodes is faster than DB cursor seeks for skipped branches.
Benchmarks (10 flashblocks, 50k accounts):