Extracts deferred trie task spawning into a dedicated method for better
code organization and maintainability.
Key change: moves `merge_overlay_trie_input` call OUTSIDE `spawn_blocking`
to prevent deadlocks. Previously, blocking threads could wait on each
other's `trie_data()` calls and deadlock by exhausting the thread pool.
This change introduces the `spawn_deferred_trie_task` method to encapsulate the logic for computing and sorting trie data in a background task. This refactor improves code readability and maintains the validation hot path's efficiency by allowing immediate returns after state root verification. The new method handles merging of trie inputs and manages the deferred computation process, ensuring that consumers only block when they require the sorted trie data.
Encapsulates anchor_hash and trie_input into a single AnchoredTrieInput
struct, and makes it optional in ComputedTrieData. This ensures both
fields are either present together or absent together.
- Some(AnchoredTrieInput): For in-memory blocks that need trie input
anchored to a persisted ancestor (validation, state root computation)
- None: For pending blocks and payload building where anchored trie
input is not needed
The API now makes it explicit which path is safe vs potentially blocking:
- `ExecutedBlock::new()` takes `ComputedTrieData` directly - safe default
for sequencers, payload builders, and other contexts where trie data is
immediately available.
- `ExecutedBlock::with_deferred_trie_data()` takes `DeferredTrieData` -
explicitly signals that the caller MUST call `set_ready()` on the handle,
otherwise `trie_data()` will block forever.
This addresses the API footgun where creating an ExecutedBlock with a
pending DeferredTrieData but never calling set_ready() would cause silent
deadlocks.
The Eq impl is removed because ExecutedBlock contains DeferredTrieData
which uses Mutex internally. This makes equality comparisons potentially
blocking, which is not appropriate for Eq semantics.
and there is a logical error here where the fast path checks blocks.last() which is the oldest in-memory block (not the tip). but blocks_by_hash returns blocks in newest-to-oldest order.
this results in
wrong data: The oldest block's trie_input only has its own overlay, missing all newer blocks' state changes
waiting on the oldest block, blocks the validation thread on the wrong trie_data(), starves the blocking pool, and even when it unblocks the reused trie input is missing newer overlays.
ref 0d8091066e
Consolidate the logic for merging overlay trie inputs into a dedicated function, `merge_overlay_trie_input`, to improve readability and maintainability. Remove redundant code and enhance error handling in deferred trie tasks. Update documentation to clarify the purpose and process of computing `TrieInputSorted` from in-memory blocks.
Remove the manual PartialEq implementation for ComputedTrieData since
the trie_input field was intentionally excluded from comparisons, which
could lead to subtle bugs. Update test assertions to explicitly compare
the relevant fields individually.
Also fix unused import warning for CanonStateSubscriptions in flashblocks.