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