Skip to main content

reth_evm/
lib.rs

1//! Traits for configuring EVM specifics.
2
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
5    html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
6    issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
7)]
8#![cfg_attr(not(test), warn(unused_crate_dependencies))]
9#![cfg_attr(docsrs, feature(doc_cfg))]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12extern crate alloc;
13
14#[cfg(feature = "std")]
15use crate::execute::{BasicBlockBuilder, BasicBlockExecutor};
16use alloc::string::String;
17use alloy_eips::eip4895::Withdrawals;
18use alloy_primitives::{Address, Bytes, B256};
19use core::{error::Error, fmt::Debug};
20use reth_primitives_traits::{
21    BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
22};
23
24pub use evm2::{
25    debug_unreachable,
26    evm::{Database, DynDatabase},
27};
28
29/// Cached database adapters for payload building.
30pub mod cached;
31/// Database adapters for EVM execution.
32pub mod database;
33pub mod either;
34/// EVM environment configuration.
35pub mod execute;
36/// precompile cache provider.
37#[cfg(feature = "std")]
38pub mod precompile_cache;
39
40mod aliases;
41pub use aliases::*;
42pub use execute::{
43    BlockAssembler, BlockAssemblerInput, BlockBuilder, BlockBuilderOutcome, BlockExecutionError,
44    BlockExecutionOutput, BlockExecutor, BlockExecutorFactory, BlockTransactionResult,
45    BlockValidationError, CommitChanges, Evm, ExecutableTxFor, ExecutableTxParts, Executor,
46    ExecutorTx, FromRecoveredTx, FromTxWithEncoded, GasOutput, InternalBlockExecutionError,
47    IntoTxEnv, InvalidTxError, ReceiptBuilder, ReceiptBuilderCtx, RecoveredTx, TransactionEnvMut,
48    WithTxEnv,
49};
50pub use reth_execution_types::{OnStateHook, StateUpdate};
51pub use reth_trie_common::bundle_state::BundleState;
52
53/// Transaction validation limits resolved for an EVM environment.
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub struct EvmTransactionValidationLimits {
56    /// Maximum contract creation initcode size.
57    pub max_initcode_size: usize,
58    /// Transaction gas limit cap. `0` disables the txpool-level cap check.
59    pub tx_gas_limit_cap: u64,
60}
61
62/// Transaction validation gas rules resolved for an EVM environment.
63#[derive(Debug, Clone, Copy)]
64pub struct EvmTransactionValidationGasRules {
65    /// The configured native gas schedule and enabled features.
66    pub version: evm2::Version,
67}
68
69/// Transaction validation gas resolved for a transaction.
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub struct EvmTransactionValidationGas {
72    /// Transaction intrinsic gas.
73    pub intrinsic_gas: u64,
74    /// Transaction floor gas.
75    pub floor_gas: u64,
76}
77
78impl EvmTransactionValidationGasRules {
79    /// Returns the intrinsic regular gas cap, or zero when EIP-8037 is disabled.
80    pub const fn regular_gas_cap(&self) -> u64 {
81        if self.version.feature(evm2::EvmFeatures::EIP8037) {
82            self.version.tx_gas_limit_cap
83        } else {
84            0
85        }
86    }
87
88    /// Calculates validation gas with the same native rules used during execution.
89    #[expect(clippy::too_many_arguments)]
90    pub fn calculate(
91        &self,
92        caller: alloy_primitives::Address,
93        to: alloy_primitives::TxKind,
94        value: alloy_primitives::U256,
95        input: &alloy_primitives::Bytes,
96        access_list_accounts: u64,
97        access_list_storage_keys: u64,
98        authorization_list_len: u64,
99    ) -> EvmTransactionValidationGas {
100        let (mut intrinsic_gas, floor_gas) = evm2::ethereum::intrinsic_and_floor_gas(
101            &self.version,
102            caller,
103            to,
104            input,
105            access_list_accounts,
106            access_list_storage_keys,
107            value,
108        );
109        if self.version.feature(evm2::EvmFeatures::EIP7702) {
110            intrinsic_gas += authorization_list_len *
111                self.version.gas_params.get(evm2::version::GasId::TxEip7702PerEmptyAccountCost);
112        }
113        EvmTransactionValidationGas { intrinsic_gas, floor_gas }
114    }
115}
116
117/// Resolved EVM environment data needed by the EVM execution path.
118pub trait EvmEnv: Debug + Clone + Send + Sync + 'static {
119    /// Runtime EVM type family.
120    type EvmTypes: evm2::EvmTypes;
121
122    /// Returns the active EVM specification.
123    fn spec_id(&self) -> <Self::EvmTypes as evm2::EvmTypesHost>::SpecId;
124
125    /// Returns the active chain ID.
126    fn chain_id(&self) -> u64;
127
128    /// Returns the configured block environment.
129    fn block_env(&self) -> &evm2::env::BlockEnv<Self::EvmTypes>;
130
131    /// Returns the configured block environment mutably.
132    fn block_env_mut(&mut self) -> &mut evm2::env::BlockEnv<Self::EvmTypes>;
133
134    /// Returns the active EVM version.
135    fn version(&self) -> &evm2::Version;
136
137    /// Returns the active EVM version mutably.
138    fn version_mut(&mut self) -> &mut evm2::Version;
139
140    /// Returns the block base fee resolved for this environment.
141    fn block_base_fee(&self) -> u64;
142
143    /// Returns the block blob base fee resolved for this environment.
144    fn block_blob_base_fee(&self) -> u64;
145
146    /// Returns transaction validation limits active in this environment.
147    fn transaction_validation_limits(&self) -> EvmTransactionValidationLimits;
148
149    /// Returns transaction validation gas rules active in this environment.
150    fn transaction_validation_gas_rules(&self) -> EvmTransactionValidationGasRules;
151
152    /// Returns whether the block uses independent regular and state gas capacity.
153    fn uses_separate_block_gas(&self) -> bool {
154        false
155    }
156
157    /// Returns the transaction limit used to reserve regular block gas.
158    fn regular_gas_limit_cap(&self) -> u64 {
159        u64::MAX
160    }
161
162    /// Returns this environment with transaction nonce checks disabled.
163    fn with_nonce_check_disabled(self) -> Self;
164
165    /// Returns this environment with transaction balance checks disabled.
166    fn with_balance_check_disabled(self) -> Self;
167}
168
169#[cfg(feature = "std")]
170mod engine;
171#[cfg(feature = "std")]
172pub use engine::{ConfigureEngineEvm, ConvertTx, ExecutableTxIterator, ExecutableTxTuple};
173mod sender_recovery;
174pub use sender_recovery::SenderRecoveryCache;
175
176#[cfg(feature = "metrics")]
177pub mod metrics;
178pub mod noop;
179/// Helper types for execution witness generation.
180#[cfg(feature = "witness")]
181pub mod witness;
182
183/// A complete configuration of EVM for Reth.
184///
185/// This trait encapsulates complete configuration required for transaction execution and block
186/// execution/building, providing a unified interface for EVM operations.
187///
188/// # Architecture Overview
189///
190/// The EVM abstraction consists of the following layers:
191///
192/// 1. **[`Evm`] (created by [`BlockExecutorFactory::evm_with_env`])**: The core EVM implementation
193///    responsible for executing individual transactions and producing outputs including state
194///    changes, logs, gas usage, etc. The factory that configures it is
195///    [`BlockExecutorFactory::EvmFactory`].
196///
197/// 2. **[`BlockExecutor`] (created by [`BlockExecutorFactory::create_executor`])**: A higher-level
198///    component that operates on top of [`Evm`] to execute entire blocks. This involves:
199///    - Executing all transactions in sequence
200///    - Building receipts from transaction outputs
201///    - Applying block rewards to the beneficiary
202///    - Executing system calls (e.g., EIP-4788 beacon root updates)
203///    - Managing state changes and bundle accumulation
204///
205/// 3. **[`BlockAssembler`]**: Responsible for assembling valid blocks from executed transactions.
206///    It takes the output from [`BlockExecutor`] along with execution context and produces a
207///    complete block ready for inclusion in the chain.
208///
209/// # Usage Patterns
210///
211/// The abstraction supports two primary use cases:
212///
213/// ## 1. Executing Externally Provided Blocks (e.g., during sync)
214///
215/// ```rust,ignore
216/// use reth_evm::ConfigureEvm;
217///
218/// // Execute a received block
219/// let mut executor = evm_config.executor(state_db);
220/// let output = executor.execute(&block)?;
221///
222/// // Access the execution results
223/// println!("Gas used: {}", output.result.gas_used);
224/// println!("Receipts: {:?}", output.result.receipts);
225/// ```
226///
227/// ## 2. Building New Blocks (e.g., payload building)
228///
229/// Payload building is slightly different as it doesn't have the block's header yet, but rather
230/// attributes for the block's environment, such as timestamp, fee recipient, and randomness value.
231/// The block's header will be the outcome of the block building process.
232///
233/// ```rust,ignore
234/// use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};
235///
236/// // Create attributes for the next block
237/// let attributes = NextBlockEnvAttributes {
238///     timestamp: current_time + 12,
239///     suggested_fee_recipient: beneficiary_address,
240///     prev_randao: randomness_value,
241///     gas_limit: 30_000_000,
242///     withdrawals: Some(withdrawals),
243///     parent_beacon_block_root: Some(beacon_root),
244///     extra_data: Bytes::new(),
245///     slot_number: None,
246/// };
247///
248/// // Build a new block on top of parent
249/// let mut builder = evm_config.builder_for_next_block(
250///     state_db,
251///     &parent_header,
252///     attributes
253/// )?;
254///
255/// // Apply pre-execution changes (e.g., beacon root update)
256/// builder.apply_pre_execution_changes()?;
257///
258/// // Execute transactions
259/// for tx in pending_transactions {
260///     match builder.execute_transaction(tx) {
261///         Ok(gas_output) => {
262///             println!("Transaction executed, gas used: {}", gas_output.tx_gas_used());
263///         }
264///         Err(e) => {
265///             println!("Transaction failed: {:?}", e);
266///         }
267///     }
268/// }
269///
270/// // Finish block building and get the outcome (block)
271/// let outcome = builder.finish(state_provider, None)?;
272/// let block = outcome.block;
273/// ```
274///
275/// # Key Components
276///
277/// ## [`NextBlockEnvCtx`]
278///
279/// Contains attributes needed to configure the next block that cannot be derived from the
280/// parent block alone. This includes data typically provided by the consensus layer:
281/// - `timestamp`: Block timestamp
282/// - `suggested_fee_recipient`: Beneficiary address
283/// - `prev_randao`: Randomness value
284/// - `gas_limit`: Block gas limit
285/// - `withdrawals`: Consensus layer withdrawals
286/// - `parent_beacon_block_root`: EIP-4788 beacon root
287///
288/// ## [`BlockAssembler`]
289///
290/// Takes the execution output and produces a complete block. It receives:
291/// - Transaction execution results (receipts, gas used)
292/// - Final state root after all executions
293/// - Bundle state with all changes
294/// - Execution context and environment
295///
296/// The assembler is responsible for:
297/// - Setting the correct block header fields
298/// - Including executed transactions
299/// - Setting gas used and receipts root
300/// - Applying any chain-specific rules
301///
302/// [`ExecutionCtx`]: BlockExecutorFactory::ExecutionCtx
303/// [`NextBlockEnvCtx`]: ConfigureEvm::NextBlockEnvCtx
304#[auto_impl::auto_impl(&, Arc)]
305pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
306    /// The primitives type used by the EVM.
307    type Primitives: NodePrimitives;
308
309    /// The error type that is returned by [`Self::next_evm_env`].
310    type Error: Error + Send + Sync + 'static;
311
312    /// Context required for configuring next block environment.
313    ///
314    /// Contains values that can't be derived from the parent block.
315    type NextBlockEnvCtx: Debug + Clone;
316
317    /// Configured [`BlockExecutorFactory`], contains the EVM factory internally.
318    type BlockExecutorFactory: crate::execute::BlockExecutorFactory<
319        Transaction = TxTy<Self::Primitives>,
320        Receipt = ReceiptTy<Self::Primitives>,
321        EvmTypes: evm2::EvmTypes<
322            Tx: crate::execute::FromTxWithEncoded<TxTy<Self::Primitives>>
323                    + crate::execute::TransactionEnvMut,
324        >,
325    >;
326
327    /// A type that knows how to build a block.
328    #[cfg(feature = "std")]
329    type BlockAssembler: crate::execute::BlockAssembler<
330        Self::BlockExecutorFactory,
331        Block = BlockTy<Self::Primitives>,
332    >;
333
334    /// Returns reference to the configured [`BlockExecutorFactory`].
335    #[cfg(feature = "std")]
336    fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
337
338    /// Returns reference to the configured [`BlockAssembler`].
339    #[cfg(feature = "std")]
340    fn block_assembler(&self) -> &Self::BlockAssembler;
341
342    /// Creates a new [`EvmEnv`] for the given header.
343    fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> Result<EvmEnvFor<Self>, Self::Error>;
344
345    /// Returns the configured [`EvmEnv`] for `parent + 1` block.
346    ///
347    /// This is intended for usage in block building after the merge and requires additional
348    /// attributes that can't be derived from the parent block: attributes that are determined by
349    /// the CL, such as the timestamp, suggested fee recipient, and randomness value.
350    ///
351    /// # Example
352    ///
353    /// ```rust,ignore
354    /// let evm_env = evm_config.next_evm_env(&parent_header, &attributes)?;
355    /// // evm_env now contains:
356    /// // - Correct spec ID based on timestamp and block number
357    /// // - Block environment with next block's parameters
358    /// // - Configuration like chain ID and blob parameters
359    /// ```
360    fn next_evm_env(
361        &self,
362        parent: &HeaderTy<Self::Primitives>,
363        attributes: &Self::NextBlockEnvCtx,
364    ) -> Result<EvmEnvFor<Self>, Self::Error>;
365
366    /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for a given block.
367    fn context_for_block<'a>(
368        &self,
369        block: &'a SealedBlock<BlockTy<Self::Primitives>>,
370    ) -> Result<ExecutionCtxFor<'a, Self>, Self::Error>
371    where
372        Self: 'a;
373
374    /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for `parent + 1`
375    /// block.
376    fn context_for_next_block(
377        &self,
378        parent: &SealedHeader<HeaderTy<Self::Primitives>>,
379        attributes: Self::NextBlockEnvCtx,
380    ) -> Result<ExecutionCtxFor<'_, Self>, Self::Error>;
381
382    /// Returns a transaction environment from a transaction.
383    fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
384        transaction.into_tx_env()
385    }
386
387    /// Provides a reference to the configured EVM factory state.
388    #[cfg(feature = "std")]
389    fn evm_factory(&self) -> &EvmFactoryFor<Self> {
390        self.block_executor_factory().evm_factory()
391    }
392
393    /// Returns a config with JIT support enabled for subsequently created EVMs, if supported.
394    ///
395    /// This is one of three gates required before an EVM can execute JIT-compiled code: the binary
396    /// must be built with the `jit` feature, runtime compilation must be enabled by `--jit` or the
397    /// `reth_jit` RPC method, and this local support flag must be enabled for the config that
398    /// creates the EVM.
399    #[auto_impl(keep_default_for(&, Arc))]
400    fn with_jit_support_enabled(self, _enabled: bool) -> Self
401    where
402        Self: Sized,
403    {
404        self
405    }
406
407    /// Returns a config with local JIT support enabled for subsequently created EVMs, if supported.
408    #[auto_impl(keep_default_for(&, Arc))]
409    fn with_jit_support(self) -> Self
410    where
411        Self: Sized,
412    {
413        self.with_jit_support_enabled(true)
414    }
415
416    /// Creates an EVM whose precompile results are cached in `cache_map`.
417    ///
418    /// Only the engine calls this, for the EVMs it executes and prewarms blocks with. Configs that
419    /// do not support precompile caching create an uncached EVM. `metrics_enabled` selects whether
420    /// the cache records hit, miss, and size metrics.
421    #[cfg(feature = "std")]
422    fn evm_with_precompile_cache<'a, DB>(
423        &self,
424        db: DB,
425        evm_env: EvmEnvFor<Self>,
426        _cache_map: precompile_cache::PrecompileCacheMap<SpecFor<Self>>,
427        _metrics_enabled: bool,
428    ) -> EvmFor<'a, Self>
429    where
430        DB: Database + 'a,
431    {
432        self.evm_with_env(db, evm_env)
433    }
434
435    /// Returns the JIT backend, if supported.
436    fn jit_backend(&self) -> Option<&dyn JitBackend> {
437        None
438    }
439
440    /// Returns a new [`Executor`] for executing blocks.
441    ///
442    /// The executor processes complete blocks including:
443    /// - All transactions in order
444    /// - Block rewards and fees
445    /// - Block level system calls
446    /// - State transitions
447    ///
448    /// # Example
449    ///
450    /// ```rust,ignore
451    /// // Create an executor
452    /// let mut executor = evm_config.executor(state_db);
453    ///
454    /// // Execute a single block
455    /// let output = executor.execute(&block)?;
456    ///
457    /// // Execute multiple blocks
458    /// let batch_output = executor.execute_batch(&blocks)?;
459    /// ```
460    #[auto_impl(keep_default_for(&, Arc))]
461    fn executor<DB>(
462        &self,
463        db: DB,
464    ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>
465    where
466        DB: Database,
467    {
468        #[cfg(feature = "std")]
469        {
470            BasicBlockExecutor::new(self, db)
471        }
472
473        #[cfg(not(feature = "std"))]
474        {
475            let _ = db;
476            crate::execute::UnsupportedExecutor::default()
477        }
478    }
479
480    /// Returns a new [`BasicBlockExecutor`].
481    #[auto_impl(keep_default_for(&, Arc))]
482    fn batch_executor<DB>(
483        &self,
484        db: DB,
485    ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>
486    where
487        DB: Database,
488    {
489        #[cfg(feature = "std")]
490        {
491            BasicBlockExecutor::new(self, db)
492        }
493
494        #[cfg(not(feature = "std"))]
495        {
496            let _ = db;
497            crate::execute::UnsupportedExecutor::default()
498        }
499    }
500
501    /// Creates a block executor for the given block.
502    #[cfg(feature = "std")]
503    fn executor_for_block<'a, DB>(
504        &'a self,
505        db: DB,
506        block: &'a SealedBlock<BlockTy<Self::Primitives>>,
507    ) -> Result<crate::BlockExecutorFor<'a, Self>, Self::Error>
508    where
509        Self: 'a,
510        DB: Database + 'a,
511    {
512        let evm = self.evm_for_block(db, block.header())?;
513        let ctx = self.context_for_block(block)?;
514        Ok(self.block_executor_factory().create_executor(evm, ctx))
515    }
516
517    /// Creates an EVM instance for single-transaction execution with the configured environment.
518    #[cfg(feature = "std")]
519    #[auto_impl(keep_default_for(&, Arc))]
520    fn evm_with_env<'a, DB>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<'a, Self>
521    where
522        DB: Database + 'a,
523    {
524        self.block_executor_factory().evm_with_database(db, evm_env)
525    }
526
527    /// Creates an EVM instance for the given block.
528    #[cfg(feature = "std")]
529    fn evm_for_block<'a, DB>(
530        &self,
531        db: DB,
532        header: &HeaderTy<Self::Primitives>,
533    ) -> Result<EvmFor<'a, Self>, Self::Error>
534    where
535        DB: Database + 'a,
536    {
537        let evm_env = self.evm_env(header)?;
538        Ok(self.evm_with_env(db, evm_env))
539    }
540
541    /// Creates a [`BlockBuilder`]. Should be used when building a new block.
542    ///
543    /// Block builder wraps an inner [`BlockExecutor`] and has a similar interface. Builder
544    /// collects all of the executed transactions, and once [`BlockBuilder::finish`] is called, it
545    /// invokes the configured [`BlockAssembler`] to create a block.
546    ///
547    /// # Example
548    ///
549    /// ```rust,ignore
550    /// // Create a builder with specific EVM configuration
551    /// let evm = evm_config.evm_with_env(state_db, evm_env.clone());
552    /// let ctx = evm_config.context_for_next_block(&parent, attributes);
553    /// let builder = evm_config.create_block_builder(evm, evm_env, &parent, ctx);
554    /// ```
555    #[cfg(feature = "std")]
556    fn create_block_builder<'a>(
557        &'a self,
558        evm: EvmFor<'a, Self>,
559        evm_env: EvmEnvFor<Self>,
560        parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
561        ctx: ExecutionCtxFor<'a, Self>,
562    ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor = crate::BlockExecutorFor<'a, Self>>
563    where
564        Self: 'a,
565    {
566        self.create_block_builder_with(evm, evm_env, parent, ctx, |executor| executor)
567    }
568
569    /// Creates a [`BlockBuilder`] like [`ConfigureEvm::create_block_builder`], with a customized
570    /// executor.
571    #[cfg(feature = "std")]
572    fn create_block_builder_with<'a, E>(
573        &'a self,
574        evm: EvmFor<'a, Self>,
575        evm_env: EvmEnvFor<Self>,
576        parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
577        ctx: ExecutionCtxFor<'a, Self>,
578        f: impl FnOnce(BlockExecutorFor<'a, Self>) -> E,
579    ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor = E>
580    where
581        Self: 'a,
582        E: BlockExecutor<
583            Evm = EvmFor<'a, Self>,
584            Transaction = TxTy<Self::Primitives>,
585            Receipt = ReceiptTy<Self::Primitives>,
586        >,
587    {
588        BasicBlockBuilder {
589            executor: f(self.block_executor_factory().create_executor(evm, ctx.clone())),
590            evm_env,
591            transactions: Default::default(),
592            ctx,
593            parent,
594            assembler: self.block_assembler(),
595        }
596    }
597
598    /// Creates a [`BlockBuilder`] for building of a new block. This is a helper to invoke
599    /// [`ConfigureEvm::create_block_builder`].
600    ///
601    /// This is the primary method for building new blocks. It combines:
602    /// 1. Creating the EVM environment for the next block
603    /// 2. Setting up the execution context from attributes
604    /// 3. Initializing the block builder with proper configuration
605    ///
606    /// # Example
607    ///
608    /// ```rust,ignore
609    /// // Build a block with specific attributes
610    /// let mut builder = evm_config.builder_for_next_block(
611    ///     state_db,
612    ///     &parent_header,
613    ///     attributes
614    /// )?;
615    ///
616    /// // Execute system calls (e.g., beacon root update)
617    /// builder.apply_pre_execution_changes()?;
618    ///
619    /// // Execute transactions
620    /// for tx in transactions {
621    ///     builder.execute_transaction(tx)?;
622    /// }
623    ///
624    /// // Complete block building
625    /// let outcome = builder.finish(state_provider, None)?;
626    /// ```
627    #[cfg(feature = "std")]
628    fn builder_for_next_block<'a, DB>(
629        &'a self,
630        db: DB,
631        parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
632        attributes: Self::NextBlockEnvCtx,
633    ) -> Result<
634        impl BlockBuilder<Primitives = Self::Primitives, Executor = crate::BlockExecutorFor<'a, Self>>,
635        Self::Error,
636    >
637    where
638        Self: 'a,
639        DB: Database + 'a,
640    {
641        let evm_env = self.next_evm_env(parent, &attributes)?;
642        let evm = self.evm_with_env(db, evm_env.clone());
643        let ctx = self.context_for_next_block(parent, attributes)?;
644        Ok(self.create_block_builder(evm, evm_env, parent, ctx))
645    }
646
647    /// Applies block-level state changes required before transaction execution using the configured
648    /// block executor.
649    #[cfg(feature = "std")]
650    fn pre_block_state_changes<'a, DB>(
651        &'a self,
652        db: DB,
653        evm_env: EvmEnvFor<Self>,
654        ctx: ExecutionCtxFor<'a, Self>,
655    ) -> Result<BundleState, Box<dyn Error + Send + Sync>>
656    where
657        Self: 'a,
658        DB: DynDatabase + 'a,
659    {
660        let factory = self.block_executor_factory();
661        let evm = factory.evm_with_env(db, evm_env);
662        let mut executor = factory.create_executor(evm, ctx);
663        executor
664            .apply_pre_execution_changes()
665            .map_err(|err| -> Box<dyn Error + Send + Sync> { Box::new(err) })?;
666        Ok(executor.into_state())
667    }
668
669    /// Returns whether engine validation may commit transaction results from speculative prewarm
670    /// execution instead of executing the transactions again.
671    ///
672    /// Return `true` only if all of these hold, see also [`Self::prewarm_tx_result`]:
673    /// - the block executor executes a transaction by checking that its gas limit, capped by the
674    ///   transaction gas limit cap, fits into the block gas limit minus the last receipt's
675    ///   cumulative gas used, and then running [`Evm::transact`] with the transaction environment;
676    /// - [`Evm::transact`] performs the standard caller nonce and balance validation; speculative
677    ///   results additionally reject the largest nonce before reuse;
678    /// - EVMs created by this configuration with JIT support disabled call inspector hooks for
679    ///   every executed instruction;
680    /// - execution depends only on recorded database reads and the transaction and block
681    ///   environments reproduced during prewarming, with no unrecorded external state.
682    ///
683    /// [`Evm::transact`]: Evm::transact
684    fn reuses_prewarm_results(&self) -> bool {
685        false
686    }
687
688    /// Wraps a speculative prewarm execution result of `tx` into the result consumed by
689    /// [`BlockExecutor::commit_transaction`].
690    ///
691    /// Only called if [`Self::reuses_prewarm_results`] returns `true`.
692    /// Returning `None` rejects and consumes this speculative result; the engine executes the
693    /// transaction normally instead.
694    #[cfg(feature = "std")]
695    fn prewarm_tx_result<'a>(
696        &self,
697        tx: &TxTy<Self::Primitives>,
698        result: TxResultWithStateFor<Self>,
699    ) -> Option<TxExecutionResultFor<'a, Self>>
700    where
701        Self: 'a,
702    {
703        let _ = (tx, result);
704        None
705    }
706
707    /// Returns the predicted environment of the block after `parent` with `beneficiary`, in which
708    /// engine validation speculatively executes pool transactions before the block arrives.
709    ///
710    /// Validation reuses such results only for blocks whose environment matches the predicted
711    /// one, apart from the beneficiary, timestamp, prevrandao and gas limit, which the
712    /// transactions must not have observed. Only called if [`Self::reuses_prewarm_results`]
713    /// returns `true`. Returns `None` if the environment cannot be predicted, which disables
714    /// recording pool transaction results. Custom block environment extensions must remain
715    /// identical to canonical execution; the engine compares only standard environment fields.
716    fn speculative_next_evm_env(
717        &self,
718        parent: &SealedHeader<HeaderTy<Self::Primitives>>,
719        beneficiary: Address,
720    ) -> Option<EvmEnvFor<Self>> {
721        let _ = (parent, beneficiary);
722        None
723    }
724}
725
726/// JIT backend controls exposed by an EVM configuration.
727pub trait JitBackend: Send + Sync {
728    /// Enables or disables JIT compilation.
729    fn set_enabled(&self, enabled: bool) -> Result<(), String>;
730
731    /// Pauses JIT helper execution while keeping queueing and resident compiled code available.
732    fn pause(&self);
733
734    /// Resumes background JIT work.
735    fn resume(&self);
736
737    /// Clears JIT runtime state.
738    fn clear(&self);
739}
740
741/// Represents additional attributes required to configure the next block.
742///
743/// This struct contains all the information needed to build a new block that cannot be
744/// derived from the parent block header alone. These attributes are typically provided
745/// by the consensus layer (CL) through the Engine API during payload building.
746///
747/// # Relationship with [`ConfigureEvm`] and [`BlockAssembler`]
748///
749/// The flow for building a new block involves:
750///
751/// 1. **Receive attributes** from the consensus layer containing:
752///    - Timestamp for the new block
753///    - Fee recipient (coinbase/beneficiary)
754///    - Randomness value (prevRandao)
755///    - Withdrawals to process
756///    - Parent beacon block root for EIP-4788
757///
758/// 2. **Configure EVM environment** using these attributes: ```rust,ignore let evm_env =
759///    evm_config.next_evm_env(&parent, &attributes)?; ```
760///
761/// 3. **Build the block** with transactions: ```rust,ignore let mut builder =
762///    evm_config.builder_for_next_block( state, &parent, attributes )?; ```
763///
764/// 4. **Assemble the final block** using [`BlockAssembler`] which takes:
765///    - Execution results from all transactions
766///    - The attributes used during execution
767///    - Final state root after all changes
768///
769/// This design cleanly separates:
770/// - **Configuration** (what parameters to use) - handled by `NextBlockEnvAttributes`
771/// - **Execution** (running transactions) - handled by [`BlockExecutor`]
772/// - **Assembly** (creating the final block) - handled by [`BlockAssembler`]
773#[derive(Debug, Clone, PartialEq, Eq)]
774pub struct NextBlockEnvAttributes {
775    /// The timestamp of the next block.
776    pub timestamp: u64,
777    /// The suggested fee recipient for the next block.
778    pub suggested_fee_recipient: Address,
779    /// The randomness value for the next block.
780    pub prev_randao: B256,
781    /// Block gas limit.
782    pub gas_limit: u64,
783    /// The parent beacon block root.
784    pub parent_beacon_block_root: Option<B256>,
785    /// Withdrawals
786    pub withdrawals: Option<Withdrawals>,
787    /// Optional extra data.
788    pub extra_data: Bytes,
789    /// Optional slot number for post-Amsterdam payloads.
790    pub slot_number: Option<u64>,
791}