,
- overlay_factory: OverlayStateProviderFactory,
- config: &'a TreeConfig,
-}
-
-impl fmt::Debug for PayloadStateRootJobContext<'_, N, P, Evm>
-where
- N: NodePrimitives,
- Evm: ConfigureEvm,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("PayloadStateRootJobContext")
- .field("parent_hash", &self.parent_hash)
- .field("parent_state_root", &self.parent_state_root())
- .field("timestamp", &self.timestamp)
- .finish_non_exhaustive()
- }
-}
-
-impl<'a, N, P, Evm> PayloadStateRootJobContext<'a, N, P, Evm>
-where
- N: NodePrimitives,
- Evm: ConfigureEvm,
-{
- /// Creates a new payload-builder state-root job context.
- pub(crate) const fn new(
- payload_processor: &'a PayloadProcessor,
- parent_hash: B256,
- parent_header: &'a N::BlockHeader,
- timestamp: u64,
- provider_builder: StateProviderBuilder,
- overlay_factory: OverlayStateProviderFactory,
- config: &'a TreeConfig,
- ) -> Self {
- Self {
- payload_processor,
- parent_hash,
- parent_header,
- timestamp,
- provider_builder,
- overlay_factory,
- config,
- }
- }
-
- /// Returns the parent block hash for the payload being built.
- pub const fn parent_hash(&self) -> B256 {
- self.parent_hash
- }
-
- /// Returns the parent block header for the payload being built.
- ///
- /// This is the chain's concrete header type, so chain-specific strategies can read
- /// chain-specific fields, and number-activated forks can dispatch on the parent number.
- pub const fn parent_header(&self) -> &N::BlockHeader {
- self.parent_header
- }
-
- /// Returns the parent state root for the payload being built.
- pub fn parent_state_root(&self) -> B256 {
- self.parent_header.state_root()
- }
-
- /// Returns the timestamp of the payload being built, taken from the payload attributes.
- ///
- /// Strategies that switch behavior at a fork activation can dispatch on this value.
- pub const fn timestamp(&self) -> u64 {
- self.timestamp
- }
-
- /// Returns the task runtime used by payload processing.
- pub const fn executor(&self) -> &reth_tasks::Runtime {
- self.payload_processor.executor()
- }
-
- /// Returns a clone of the state provider builder.
- pub fn provider_builder(&self) -> StateProviderBuilder
- where
- P: Clone,
- {
- self.provider_builder.clone()
- }
-}
-
-/// Data available while preparing one state-root job.
-pub struct StateRootJobContext<'a, N, P, Evm>
-where
- N: NodePrimitives,
- Evm: ConfigureEvm,
-{
- payload_processor: &'a PayloadProcessor,
- env: &'a ExecutionEnv,
- provider_builder: StateProviderBuilder,
- overlay_factory: OverlayStateProviderFactory,
- config: &'a TreeConfig,
- parallel_bal_execution: bool,
- pending_sparse_trie_prune: Option,
-}
-
-impl fmt::Debug for StateRootJobContext<'_, N, P, Evm>
-where
- N: NodePrimitives,
- Evm: ConfigureEvm,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("StateRootJobContext")
- .field("parallel_bal_execution", &self.parallel_bal_execution)
- .field("has_pending_sparse_trie_prune", &self.pending_sparse_trie_prune.is_some())
- .finish_non_exhaustive()
- }
-}
-
-impl<'a, N, P, Evm> StateRootJobContext<'a, N, P, Evm>
-where
- N: NodePrimitives,
- Evm: ConfigureEvm,
-{
- /// Creates a new state-root job context.
- pub(crate) const fn new(
- payload_processor: &'a PayloadProcessor,
- env: &'a ExecutionEnv,
- provider_builder: StateProviderBuilder,
- overlay_factory: OverlayStateProviderFactory,
- config: &'a TreeConfig,
- parallel_bal_execution: bool,
- pending_sparse_trie_prune: Option,
- ) -> Self {
- Self {
- payload_processor,
- env,
- provider_builder,
- overlay_factory,
- config,
- parallel_bal_execution,
- pending_sparse_trie_prune,
- }
- }
-
- /// Returns the execution environment for the block.
- pub const fn env(&self) -> &ExecutionEnv {
- self.env
- }
-
- /// Returns the task runtime used by payload processing.
- pub const fn executor(&self) -> &reth_tasks::Runtime {
- self.payload_processor.executor()
- }
-
- /// Returns true when validation will use the parallel BAL execution path.
- pub const fn parallel_bal_execution(&self) -> bool {
- self.parallel_bal_execution
- }
-
- /// Returns a clone of the state provider builder.
- pub fn provider_builder(&self) -> StateProviderBuilder
- where
- P: Clone,
- {
- self.provider_builder.clone()
- }
-}
-
-/// Prepared per-block state-root work and its stream wiring.
-pub struct PreparedStateRootJob {
- job: Box>,
- streams: StateRootStreams,
- hashed_state_rx: Option>,
-}
-
-impl fmt::Debug for PreparedStateRootJob {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("PreparedStateRootJob")
- .field("name", &self.job.name())
- .field("streams", &self.streams)
- .field("has_hashed_state_rx", &self.hashed_state_rx.is_some())
- .finish()
- }
-}
-
-impl PreparedStateRootJob {
- /// Creates a prepared state-root job.
- pub const fn new(
- job: Box>,
- streams: StateRootStreams,
- hashed_state_rx: Option>,
- ) -> Self {
- Self { job, streams, hashed_state_rx }
- }
-
- /// Returns the job name used in logs.
- pub fn name(&self) -> &'static str {
- self.job.name()
- }
-
- /// Returns stream views used by prewarm.
- pub fn streams(&self) -> StateRootStreams {
- self.streams.clone()
- }
-
- /// Takes the execution hook, if the job wants normal execution updates.
- pub fn take_execution_hook(&mut self) -> Option> {
- self.streams
- .take_execution_stream()
- .map(|stream| Box::new(stream.state_hook()) as Box)
- }
-
- /// Takes the optional hashed-state receiver produced by the job.
- ///
- /// The sender behind a returned receiver must either deliver one value or be dropped;
- /// validation blocks on it while hashing the post state, so a job that keeps the sender
- /// alive without sending stalls block validation.
- pub const fn take_hashed_state_rx(&mut self) -> Option> {
- self.hashed_state_rx.take()
- }
-
- /// Completes the job after execution.
- pub fn finish(
- &mut self,
- block: &RecoveredBlock,
- output: Arc>,
- hashed_state: &LazyHashedPostState,
- ) -> ProviderResult {
- self.job.finish(block, output, hashed_state)
- }
-}
-
-/// Per-block state-root job prepared before execution and finished after execution.
-pub trait StateRootJob: Send {
- /// Human-readable strategy name used in logs.
- fn name(&self) -> &'static str;
-
- /// Completes the job after execution.
- ///
- /// Called at most once per prepared job; implementations may panic if called again.
- fn finish(
- &mut self,
- block: &RecoveredBlock,
- output: Arc>,
- hashed_state: &LazyHashedPostState,
- ) -> ProviderResult;
-}
-
-/// Outcome of a per-block state-root job.
-#[derive(Debug)]
-pub struct StateRootJobOutcome {
- /// Computed state root.
- pub state_root: B256,
- /// Trie updates associated with the computed state root.
- pub trie_updates: Arc,
- /// Changed trie node base paths retained while computing the root, if the job tracks them.
- pub changed_paths: Option>,
- /// Hashed post state recomputed by a fallback path.
- ///
- /// When set, the root was not derived from the streamed updates, so validation replaces its
- /// streaming-derived hashed post state with this one and re-runs hashed-state checks.
- pub hashed_state: Option>,
-}
-
-impl StateRootJobOutcome {
- /// Creates a state-root job outcome without changed paths.
- pub const fn new(state_root: B256, trie_updates: Arc) -> Self {
- Self { state_root, trie_updates, changed_paths: None, hashed_state: None }
- }
-
- /// Sets the changed trie node base paths retained while computing the root.
- pub fn with_changed_paths(mut self, changed_paths: Option>) -> Self {
- self.changed_paths = changed_paths;
- self
- }
-
- /// Sets the hashed post state recomputed by a fallback path.
- pub fn with_hashed_state(mut self, hashed_state: Option>) -> Self {
- self.hashed_state = hashed_state;
- self
- }
-}
-
-/// Receiver for the raced serial state-root fallback: root, trie updates, and the hashed
-/// post state the fallback recomputed.
-type SerialFallbackRx = mpsc::Receiver)>>;
-
-/// Default state-root strategy used by engine-tree validation.
-///
-/// Covers the built-in modes: the sparse-trie state-root task, plus the skipped and
-/// synchronous modes selected by [`TreeConfig`].
-///
-/// Custom strategies can hold this type and delegate to it for blocks where they want the
-/// default behavior.
-#[derive(Debug, Default)]
-pub struct DefaultStateRootStrategy;
-
-impl StateRootStrategy for DefaultStateRootStrategy
-where
- N: NodePrimitives,
- P: DatabaseProviderFactory
- + BlockReader
- + StateProviderFactory
- + StateReader
- + Clone
- + 'static,
- OverlayStateProviderFactory: DatabaseProviderROFactory
- + Clone
- + Send
- + Sync
- + 'static,
- Evm: ConfigureEvm + 'static,
-{
- fn prepare(
- &self,
- ctx: StateRootJobContext<'_, N, P, Evm>,
- ) -> ProviderResult> {
- let StateRootJobContext {
- payload_processor,
- env,
- provider_builder,
- overlay_factory,
- config,
- parallel_bal_execution,
- pending_sparse_trie_prune,
- } = ctx;
-
- if config.skip_state_root() {
- return Ok(PreparedStateRootJob::new(
- Box::new(SkippedStateRootJob {}),
- StateRootStreams::empty(),
- None,
- ))
- }
-
- // `state_root_fallback` forces serial computation for tests and debugging. Hosts
- // without enough parallelism for the state-root task pipeline also compute the root
- // synchronously, since the pipeline's threads can starve each other there; see
- // [`TreeConfig::use_state_root_task`].
- if config.state_root_fallback() || !config.use_state_root_task() {
- return Ok(PreparedStateRootJob::new(
- Box::new(SynchronousStateRootJob { provider_builder }),
- StateRootStreams::empty(),
- None,
- ))
- }
-
- let mut handle = payload_processor.spawn_state_root(
- overlay_factory.clone(),
- env.parent_state_root,
- Some(env.transaction_count),
- config,
- pending_sparse_trie_prune,
- );
- let streams = handle.streams(!parallel_bal_execution);
- let hashed_state_rx = Some(handle.take_hashed_state_rx());
-
- Ok(PreparedStateRootJob::new(
- Box::new(SparseTrieStateRootJob {
- handle,
- provider_builder,
- overlay_factory,
- executor: payload_processor.executor().clone(),
- timeout: config.state_root_task_timeout(),
- compare_trie_updates: config.always_compare_trie_updates(),
- metrics: BlockValidationMetrics::default(),
- }),
- streams,
- hashed_state_rx,
- ))
- }
-
- fn prepare_payload_builder(
- &self,
- ctx: PayloadStateRootJobContext<'_, N, P, Evm>,
- ) -> ProviderResult