Skip to main content

reth_evm/
lib.rs

1//! Traits for configuring an EVM specifics.
2//!
3//! # Revm features
4//!
5//! This crate does __not__ enforce specific revm features such as `blst` or `c-kzg`, which are
6//! critical for revm's evm internals, it is the responsibility of the implementer to ensure the
7//! proper features are selected.
8
9#![doc(
10    html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
11    html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
12    issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
13)]
14#![cfg_attr(not(test), warn(unused_crate_dependencies))]
15#![cfg_attr(docsrs, feature(doc_cfg))]
16#![cfg_attr(not(feature = "std"), no_std)]
17
18extern crate alloc;
19
20use crate::execute::{BasicBlockBuilder, Executor};
21use alloc::vec::Vec;
22use alloy_eips::eip4895::Withdrawals;
23use alloy_evm::{
24    block::{BlockExecutorFactory, BlockExecutorFor},
25    precompiles::PrecompilesMap,
26};
27use alloy_primitives::{Address, Bytes, B256};
28use core::{error::Error, fmt::Debug};
29use execute::{BasicBlockExecutor, BlockAssembler, BlockBuilder};
30use reth_execution_errors::BlockExecutionError;
31use reth_primitives_traits::{
32    BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
33};
34use revm::{database::State, primitives::hardfork::SpecId};
35
36pub mod either;
37/// EVM environment configuration.
38pub mod execute;
39
40mod aliases;
41pub use aliases::*;
42
43#[cfg(feature = "std")]
44mod engine;
45#[cfg(feature = "std")]
46pub use engine::{ConfigureEngineEvm, ConvertTx, ExecutableTxIterator, ExecutableTxTuple};
47
48#[cfg(feature = "metrics")]
49pub mod metrics;
50pub mod noop;
51#[cfg(any(test, feature = "test-utils"))]
52/// test helpers for mocking executor
53pub mod test_utils;
54
55pub use alloy_evm::{
56    block::{state_changes, system_calls, OnStateHook},
57    *,
58};
59
60/// A complete configuration of EVM for Reth.
61///
62/// This trait encapsulates complete configuration required for transaction execution and block
63/// execution/building, providing a unified interface for EVM operations.
64///
65/// # Architecture Overview
66///
67/// The EVM abstraction consists of the following layers:
68///
69/// 1. **[`Evm`] (produced by [`EvmFactory`])**: The core EVM implementation responsible for
70///    executing individual transactions and producing outputs including state changes, logs, gas
71///    usage, etc.
72///
73/// 2. **[`BlockExecutor`] (produced by [`BlockExecutorFactory`])**: A higher-level component that
74///    operates on top of [`Evm`] to execute entire blocks. This involves:
75///    - Executing all transactions in sequence
76///    - Building receipts from transaction outputs
77///    - Applying block rewards to the beneficiary
78///    - Executing system calls (e.g., EIP-4788 beacon root updates)
79///    - Managing state changes and bundle accumulation
80///
81/// 3. **[`BlockAssembler`]**: Responsible for assembling valid blocks from executed transactions.
82///    It takes the output from [`BlockExecutor`] along with execution context and produces a
83///    complete block ready for inclusion in the chain.
84///
85/// # Usage Patterns
86///
87/// The abstraction supports two primary use cases:
88///
89/// ## 1. Executing Externally Provided Blocks (e.g., during sync)
90///
91/// ```rust,ignore
92/// use reth_evm::ConfigureEvm;
93///
94/// // Execute a received block
95/// let mut executor = evm_config.executor(state_db);
96/// let output = executor.execute(&block)?;
97///
98/// // Access the execution results
99/// println!("Gas used: {}", output.result.gas_used);
100/// println!("Receipts: {:?}", output.result.receipts);
101/// ```
102///
103/// ## 2. Building New Blocks (e.g., payload building)
104///
105/// Payload building is slightly different as it doesn't have the block's header yet, but rather
106/// attributes for the block's environment, such as timestamp, fee recipient, and randomness value.
107/// The block's header will be the outcome of the block building process.
108///
109/// ```rust,ignore
110/// use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};
111///
112/// // Create attributes for the next block
113/// let attributes = NextBlockEnvAttributes {
114///     timestamp: current_time + 12,
115///     suggested_fee_recipient: beneficiary_address,
116///     prev_randao: randomness_value,
117///     gas_limit: 30_000_000,
118///     withdrawals: Some(withdrawals),
119///     parent_beacon_block_root: Some(beacon_root),
120/// };
121///
122/// // Build a new block on top of parent
123/// let mut builder = evm_config.builder_for_next_block(
124///     &mut state_db,
125///     &parent_header,
126///     attributes
127/// )?;
128///
129/// // Apply pre-execution changes (e.g., beacon root update)
130/// builder.apply_pre_execution_changes()?;
131///
132/// // Execute transactions
133/// for tx in pending_transactions {
134///     match builder.execute_transaction(tx) {
135///         Ok(gas_used) => {
136///             println!("Transaction executed, gas used: {}", gas_used);
137///         }
138///         Err(e) => {
139///             println!("Transaction failed: {:?}", e);
140///         }
141///     }
142/// }
143///
144/// // Finish block building and get the outcome (block)
145/// let outcome = builder.finish(state_provider, None)?;
146/// let block = outcome.block;
147/// ```
148///
149/// # Key Components
150///
151/// ## [`NextBlockEnvCtx`]
152///
153/// Contains attributes needed to configure the next block that cannot be derived from the
154/// parent block alone. This includes data typically provided by the consensus layer:
155/// - `timestamp`: Block timestamp
156/// - `suggested_fee_recipient`: Beneficiary address
157/// - `prev_randao`: Randomness value
158/// - `gas_limit`: Block gas limit
159/// - `withdrawals`: Consensus layer withdrawals
160/// - `parent_beacon_block_root`: EIP-4788 beacon root
161///
162/// ## [`BlockAssembler`]
163///
164/// Takes the execution output and produces a complete block. It receives:
165/// - Transaction execution results (receipts, gas used)
166/// - Final state root after all executions
167/// - Bundle state with all changes
168/// - Execution context and environment
169///
170/// The assembler is responsible for:
171/// - Setting the correct block header fields
172/// - Including executed transactions
173/// - Setting gas used and receipts root
174/// - Applying any chain-specific rules
175///
176/// [`ExecutionCtx`]: BlockExecutorFactory::ExecutionCtx
177/// [`NextBlockEnvCtx`]: ConfigureEvm::NextBlockEnvCtx
178/// [`BlockExecutor`]: alloy_evm::block::BlockExecutor
179#[auto_impl::auto_impl(&, Arc)]
180pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
181    /// The primitives type used by the EVM.
182    type Primitives: NodePrimitives;
183
184    /// The error type that is returned by [`Self::next_evm_env`].
185    type Error: Error + Send + Sync + 'static;
186
187    /// Context required for configuring next block environment.
188    ///
189    /// Contains values that can't be derived from the parent block.
190    type NextBlockEnvCtx: Debug + Clone;
191
192    /// Configured [`BlockExecutorFactory`], contains [`EvmFactory`] internally.
193    type BlockExecutorFactory: for<'a> BlockExecutorFactory<
194        Transaction = TxTy<Self::Primitives>,
195        Receipt = ReceiptTy<Self::Primitives>,
196        ExecutionCtx<'a>: Debug + Send,
197        EvmFactory: EvmFactory<
198            Tx: TransactionEnvMut
199                    + FromRecoveredTx<TxTy<Self::Primitives>>
200                    + FromTxWithEncoded<TxTy<Self::Primitives>>,
201            Precompiles = PrecompilesMap,
202            Spec: Into<SpecId>,
203        >,
204    >;
205
206    /// A type that knows how to build a block.
207    type BlockAssembler: BlockAssembler<
208        Self::BlockExecutorFactory,
209        Block = BlockTy<Self::Primitives>,
210    >;
211
212    /// Returns reference to the configured [`BlockExecutorFactory`].
213    fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
214
215    /// Returns reference to the configured [`BlockAssembler`].
216    fn block_assembler(&self) -> &Self::BlockAssembler;
217
218    /// Creates a new [`EvmEnv`] for the given header.
219    fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> Result<EvmEnvFor<Self>, Self::Error>;
220
221    /// Returns the configured [`EvmEnv`] for `parent + 1` block.
222    ///
223    /// This is intended for usage in block building after the merge and requires additional
224    /// attributes that can't be derived from the parent block: attributes that are determined by
225    /// the CL, such as the timestamp, suggested fee recipient, and randomness value.
226    ///
227    /// # Example
228    ///
229    /// ```rust,ignore
230    /// let evm_env = evm_config.next_evm_env(&parent_header, &attributes)?;
231    /// // evm_env now contains:
232    /// // - Correct spec ID based on timestamp and block number
233    /// // - Block environment with next block's parameters
234    /// // - Configuration like chain ID and blob parameters
235    /// ```
236    fn next_evm_env(
237        &self,
238        parent: &HeaderTy<Self::Primitives>,
239        attributes: &Self::NextBlockEnvCtx,
240    ) -> Result<EvmEnvFor<Self>, Self::Error>;
241
242    /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for a given block.
243    fn context_for_block<'a>(
244        &self,
245        block: &'a SealedBlock<BlockTy<Self::Primitives>>,
246    ) -> Result<ExecutionCtxFor<'a, Self>, Self::Error>;
247
248    /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for `parent + 1`
249    /// block.
250    fn context_for_next_block(
251        &self,
252        parent: &SealedHeader<HeaderTy<Self::Primitives>>,
253        attributes: Self::NextBlockEnvCtx,
254    ) -> Result<ExecutionCtxFor<'_, Self>, Self::Error>;
255
256    /// Returns a [`EvmFactory::Tx`] from a transaction.
257    fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
258        transaction.into_tx_env()
259    }
260
261    /// Provides a reference to [`EvmFactory`] implementation.
262    fn evm_factory(&self) -> &EvmFactoryFor<Self> {
263        self.block_executor_factory().evm_factory()
264    }
265
266    /// Returns a new EVM with the given database configured with the given environment settings,
267    /// including the spec id and transaction environment.
268    ///
269    /// This will preserve any handler modifications
270    fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<Self, DB> {
271        self.evm_factory().create_evm(db, evm_env)
272    }
273
274    /// Returns a new EVM with the given database configured with `cfg` and `block_env`
275    /// configuration derived from the given header. Relies on
276    /// [`ConfigureEvm::evm_env`].
277    ///
278    /// # Caution
279    ///
280    /// This does not initialize the tx environment.
281    fn evm_for_block<DB: Database>(
282        &self,
283        db: DB,
284        header: &HeaderTy<Self::Primitives>,
285    ) -> Result<EvmFor<Self, DB>, Self::Error> {
286        let evm_env = self.evm_env(header)?;
287        Ok(self.evm_with_env(db, evm_env))
288    }
289
290    /// Returns a new EVM with the given database configured with the given environment settings,
291    /// including the spec id.
292    ///
293    /// This will use the given external inspector as the EVM external context.
294    ///
295    /// This will preserve any handler modifications
296    fn evm_with_env_and_inspector<DB, I>(
297        &self,
298        db: DB,
299        evm_env: EvmEnvFor<Self>,
300        inspector: I,
301    ) -> EvmFor<Self, DB, I>
302    where
303        DB: Database,
304        I: InspectorFor<Self, DB>,
305    {
306        self.evm_factory().create_evm_with_inspector(db, evm_env, inspector)
307    }
308
309    /// Creates a strategy with given EVM and execution context.
310    fn create_executor<'a, DB, I>(
311        &'a self,
312        evm: EvmFor<Self, &'a mut State<DB>, I>,
313        ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
314    ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, &'a mut State<DB>, I>
315    where
316        DB: Database,
317        I: InspectorFor<Self, &'a mut State<DB>> + 'a,
318    {
319        self.block_executor_factory().create_executor(evm, ctx)
320    }
321
322    /// Creates a strategy for execution of a given block.
323    fn executor_for_block<'a, DB: Database>(
324        &'a self,
325        db: &'a mut State<DB>,
326        block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
327    ) -> Result<impl BlockExecutorFor<'a, Self::BlockExecutorFactory, &'a mut State<DB>>, Self::Error>
328    {
329        let evm = self.evm_for_block(db, block.header())?;
330        let ctx = self.context_for_block(block)?;
331        Ok(self.create_executor(evm, ctx))
332    }
333
334    /// Creates a [`BlockBuilder`]. Should be used when building a new block.
335    ///
336    /// Block builder wraps an inner [`alloy_evm::block::BlockExecutor`] and has a similar
337    /// interface. Builder collects all of the executed transactions, and once
338    /// [`BlockBuilder::finish`] is called, it invokes the configured [`BlockAssembler`] to
339    /// create a block.
340    ///
341    /// # Example
342    ///
343    /// ```rust,ignore
344    /// // Create a builder with specific EVM configuration
345    /// let evm = evm_config.evm_with_env(&mut state_db, evm_env);
346    /// let ctx = evm_config.context_for_next_block(&parent, attributes);
347    /// let builder = evm_config.create_block_builder(evm, &parent, ctx);
348    /// ```
349    fn create_block_builder<'a, DB, I>(
350        &'a self,
351        evm: EvmFor<Self, &'a mut State<DB>, I>,
352        parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
353        ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
354    ) -> impl BlockBuilder<
355        Primitives = Self::Primitives,
356        Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, &'a mut State<DB>, I>,
357    >
358    where
359        DB: Database,
360        I: InspectorFor<Self, &'a mut State<DB>> + 'a,
361    {
362        BasicBlockBuilder {
363            executor: self.create_executor(evm, ctx.clone()),
364            ctx,
365            assembler: self.block_assembler(),
366            parent,
367            transactions: Vec::new(),
368        }
369    }
370
371    /// Creates a [`BlockBuilder`] for building of a new block. This is a helper to invoke
372    /// [`ConfigureEvm::create_block_builder`].
373    ///
374    /// This is the primary method for building new blocks. It combines:
375    /// 1. Creating the EVM environment for the next block
376    /// 2. Setting up the execution context from attributes
377    /// 3. Initializing the block builder with proper configuration
378    ///
379    /// # Example
380    ///
381    /// ```rust,ignore
382    /// // Build a block with specific attributes
383    /// let mut builder = evm_config.builder_for_next_block(
384    ///     &mut state_db,
385    ///     &parent_header,
386    ///     attributes
387    /// )?;
388    ///
389    /// // Execute system calls (e.g., beacon root update)
390    /// builder.apply_pre_execution_changes()?;
391    ///
392    /// // Execute transactions
393    /// for tx in transactions {
394    ///     builder.execute_transaction(tx)?;
395    /// }
396    ///
397    /// // Complete block building
398    /// let outcome = builder.finish(state_provider, None)?;
399    /// ```
400    fn builder_for_next_block<'a, DB: Database + 'a>(
401        &'a self,
402        db: &'a mut State<DB>,
403        parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
404        attributes: Self::NextBlockEnvCtx,
405    ) -> Result<
406        impl BlockBuilder<
407            Primitives = Self::Primitives,
408            Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, &'a mut State<DB>>,
409        >,
410        Self::Error,
411    > {
412        let evm_env = self.next_evm_env(parent, &attributes)?;
413        let evm = self.evm_with_env(db, evm_env);
414        let ctx = self.context_for_next_block(parent, attributes)?;
415        Ok(self.create_block_builder(evm, parent, ctx))
416    }
417
418    /// Returns a new [`Executor`] for executing blocks.
419    ///
420    /// The executor processes complete blocks including:
421    /// - All transactions in order
422    /// - Block rewards and fees
423    /// - Block level system calls
424    /// - State transitions
425    ///
426    /// # Example
427    ///
428    /// ```rust,ignore
429    /// // Create an executor
430    /// let mut executor = evm_config.executor(state_db);
431    ///
432    /// // Execute a single block
433    /// let output = executor.execute(&block)?;
434    ///
435    /// // Execute multiple blocks
436    /// let batch_output = executor.execute_batch(&blocks)?;
437    /// ```
438    #[auto_impl(keep_default_for(&, Arc))]
439    fn executor<DB: Database>(
440        &self,
441        db: DB,
442    ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> {
443        BasicBlockExecutor::new(self, db)
444    }
445
446    /// Returns a new [`BasicBlockExecutor`].
447    #[auto_impl(keep_default_for(&, Arc))]
448    fn batch_executor<DB: Database>(
449        &self,
450        db: DB,
451    ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> {
452        BasicBlockExecutor::new(self, db)
453    }
454}
455
456/// Represents additional attributes required to configure the next block.
457///
458/// This struct contains all the information needed to build a new block that cannot be
459/// derived from the parent block header alone. These attributes are typically provided
460/// by the consensus layer (CL) through the Engine API during payload building.
461///
462/// # Relationship with [`ConfigureEvm`] and [`BlockAssembler`]
463///
464/// The flow for building a new block involves:
465///
466/// 1. **Receive attributes** from the consensus layer containing:
467///    - Timestamp for the new block
468///    - Fee recipient (coinbase/beneficiary)
469///    - Randomness value (prevRandao)
470///    - Withdrawals to process
471///    - Parent beacon block root for EIP-4788
472///
473/// 2. **Configure EVM environment** using these attributes: ```rust,ignore let evm_env =
474///    evm_config.next_evm_env(&parent, &attributes)?; ```
475///
476/// 3. **Build the block** with transactions: ```rust,ignore let mut builder =
477///    evm_config.builder_for_next_block( &mut state, &parent, attributes )?; ```
478///
479/// 4. **Assemble the final block** using [`BlockAssembler`] which takes:
480///    - Execution results from all transactions
481///    - The attributes used during execution
482///    - Final state root after all changes
483///
484/// This design cleanly separates:
485/// - **Configuration** (what parameters to use) - handled by `NextBlockEnvAttributes`
486/// - **Execution** (running transactions) - handled by `BlockExecutor`
487/// - **Assembly** (creating the final block) - handled by `BlockAssembler`
488#[derive(Debug, Clone, PartialEq, Eq)]
489pub struct NextBlockEnvAttributes {
490    /// The timestamp of the next block.
491    pub timestamp: u64,
492    /// The suggested fee recipient for the next block.
493    pub suggested_fee_recipient: Address,
494    /// The randomness value for the next block.
495    pub prev_randao: B256,
496    /// Block gas limit.
497    pub gas_limit: u64,
498    /// The parent beacon block root.
499    pub parent_beacon_block_root: Option<B256>,
500    /// Withdrawals
501    pub withdrawals: Option<Withdrawals>,
502    /// Optional extra data.
503    pub extra_data: Bytes,
504}