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