1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
//! Traits for configuring an EVM specifics.
#![doc(
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use core::ops::Deref;
use crate::builder::RethEvmBuilder;
use reth_primitives::{Address, TransactionSigned, TransactionSignedEcRecovered, B256, U256};
use revm::{Database, Evm, GetInspector};
use revm_primitives::{
BlockEnv, Bytes, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, SpecId, TxEnv,
};
pub mod builder;
pub mod either;
pub mod execute;
#[cfg(feature = "std")]
pub mod metrics;
pub mod noop;
pub mod provider;
pub mod system_calls;
#[cfg(any(test, feature = "test-utils"))]
/// test helpers for mocking executor
pub mod test_utils;
/// Trait for configuring the EVM for executing full blocks.
#[auto_impl::auto_impl(&, Arc)]
pub trait ConfigureEvm: ConfigureEvmEnv {
/// Associated type for the default external context that should be configured for the EVM.
type DefaultExternalContext<'a>;
/// Returns new EVM with the given database
///
/// This does not automatically configure the EVM with [`ConfigureEvmEnv`] methods. It is up to
/// the caller to call an appropriate method to fill the transaction and block environment
/// before executing any transactions using the provided EVM.
fn evm<DB: Database>(&self, db: DB) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> {
RethEvmBuilder::new(db, self.default_external_context()).build()
}
/// Returns a new EVM with the given database configured with the given environment settings,
/// including the spec id.
///
/// This will preserve any handler modifications
fn evm_with_env<DB: Database>(
&self,
db: DB,
env: EnvWithHandlerCfg,
) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> {
let mut evm = self.evm(db);
evm.modify_spec_id(env.spec_id());
evm.context.evm.env = env.env;
evm
}
/// Returns a new EVM with the given database configured with the given environment settings,
/// including the spec id.
///
/// This will use the given external inspector as the EVM external context.
///
/// This will preserve any handler modifications
fn evm_with_env_and_inspector<DB, I>(
&self,
db: DB,
env: EnvWithHandlerCfg,
inspector: I,
) -> Evm<'_, I, DB>
where
DB: Database,
I: GetInspector<DB>,
{
let mut evm = self.evm_with_inspector(db, inspector);
evm.modify_spec_id(env.spec_id());
evm.context.evm.env = env.env;
evm
}
/// Returns a new EVM with the given inspector.
///
/// Caution: This does not automatically configure the EVM with [`ConfigureEvmEnv`] methods. It
/// is up to the caller to call an appropriate method to fill the transaction and block
/// environment before executing any transactions using the provided EVM.
fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
where
DB: Database,
I: GetInspector<DB>,
{
RethEvmBuilder::new(db, self.default_external_context()).build_with_inspector(inspector)
}
/// Provides the default external context.
fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a>;
}
/// This represents the set of methods used to configure the EVM's environment before block
/// execution.
///
/// Default trait method implementation is done w.r.t. L1.
#[auto_impl::auto_impl(&, Arc)]
pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
/// The header type used by the EVM.
type Header;
/// Returns a [`TxEnv`] from a [`TransactionSignedEcRecovered`].
fn tx_env(&self, transaction: &TransactionSignedEcRecovered) -> TxEnv {
let mut tx_env = TxEnv::default();
self.fill_tx_env(&mut tx_env, transaction.deref(), transaction.signer());
tx_env
}
/// Fill transaction environment from a [`TransactionSigned`] and the given sender address.
fn fill_tx_env(&self, tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address);
/// Fill transaction environment with a system contract call.
fn fill_tx_env_system_contract_call(
&self,
env: &mut Env,
caller: Address,
contract: Address,
data: Bytes,
);
/// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header.
///
/// This must set the corresponding spec id in the handler cfg, based on timestamp or total
/// difficulty
fn fill_cfg_env(
&self,
cfg_env: &mut CfgEnvWithHandlerCfg,
header: &Self::Header,
total_difficulty: U256,
);
/// Fill [`BlockEnv`] field according to the chain spec and given header
fn fill_block_env(&self, block_env: &mut BlockEnv, header: &Self::Header, after_merge: bool);
/// Convenience function to call both [`fill_cfg_env`](ConfigureEvmEnv::fill_cfg_env) and
/// [`ConfigureEvmEnv::fill_block_env`].
///
/// Note: Implementers should ensure that all fields are required fields are filled.
fn fill_cfg_and_block_env(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Self::Header,
total_difficulty: U256,
) {
self.fill_cfg_env(cfg, header, total_difficulty);
let after_merge = cfg.handler_cfg.spec_id >= SpecId::MERGE;
self.fill_block_env(block_env, header, after_merge);
}
/// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for `parent + 1` block.
///
/// This is intended for usage in block building after the merge and requires additional
/// attributes that can't be derived from the parent block: attributes that are determined by
/// the CL, such as the timestamp, suggested fee recipient, and randomness value.
fn next_cfg_and_block_env(
&self,
parent: &Self::Header,
attributes: NextBlockEnvAttributes,
) -> (CfgEnvWithHandlerCfg, BlockEnv);
}
/// Represents additional attributes required to configure the next block.
/// This is used to configure the next block's environment
/// [`ConfigureEvmEnv::next_cfg_and_block_env`] and contains fields that can't be derived from the
/// parent header alone (attributes that are determined by the CL.)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NextBlockEnvAttributes {
/// The timestamp of the next block.
pub timestamp: u64,
/// The suggested fee recipient for the next block.
pub suggested_fee_recipient: Address,
/// The randomness value for the next block.
pub prev_randao: B256,
}