Files
reth/crates/evm/src/lib.rs
2024-06-18 16:07:36 +00:00

127 lines
4.5 KiB
Rust

//! 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)]
#[cfg(not(feature = "std"))]
extern crate alloc;
use reth_chainspec::ChainSpec;
use reth_primitives::{revm::env::fill_block_env, Address, Header, TransactionSigned, U256};
use revm::{inspector_handle_register, Database, Evm, EvmBuilder, GetInspector};
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, SpecId, TxEnv};
pub mod either;
pub mod execute;
pub mod noop;
pub mod provider;
#[cfg(any(test, feature = "test-utils"))]
/// test helpers for mocking executor
pub mod test_utils;
/// Trait for configuring the EVM for executing full blocks.
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<'a, DB: Database + 'a>(
&'a self,
db: DB,
) -> Evm<'a, Self::DefaultExternalContext<'a>, DB>;
/// 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<'a, DB: Database + 'a>(
&'a self,
db: DB,
env: EnvWithHandlerCfg,
) -> Evm<'a, Self::DefaultExternalContext<'a>, 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<'a, DB, I>(
&'a self,
db: DB,
env: EnvWithHandlerCfg,
inspector: I,
) -> Evm<'a, I, DB>
where
DB: Database + 'a,
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<'a, DB, I>(&'a self, db: DB, inspector: I) -> Evm<'a, I, DB>
where
DB: Database + 'a,
I: GetInspector<DB>,
{
EvmBuilder::default()
.with_db(db)
.with_external_context(inspector)
.append_handler_register(inspector_handle_register)
.build()
}
}
/// This represents the set of methods used to configure the EVM's environment before block
/// execution.
pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
/// Fill transaction environment from a [`TransactionSigned`] and the given sender address.
fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address);
/// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header
fn fill_cfg_env(
cfg_env: &mut CfgEnvWithHandlerCfg,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
);
/// Convenience function to call both [`fill_cfg_env`](ConfigureEvmEnv::fill_cfg_env) and
/// [`fill_block_env`].
fn fill_cfg_and_block_env(
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
) {
Self::fill_cfg_env(cfg, chain_spec, header, total_difficulty);
let after_merge = cfg.handler_cfg.spec_id >= SpecId::MERGE;
fill_block_env(block_env, chain_spec, header, after_merge);
}
}