mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore: trim ConfigureEvm trait (#13807)
This commit is contained in:
@ -26,6 +26,7 @@ use reth_chainspec::ChainSpec;
|
|||||||
use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, NextBlockEnvAttributes};
|
use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, NextBlockEnvAttributes};
|
||||||
use reth_primitives::TransactionSigned;
|
use reth_primitives::TransactionSigned;
|
||||||
use reth_primitives_traits::transaction::execute::FillTxEnv;
|
use reth_primitives_traits::transaction::execute::FillTxEnv;
|
||||||
|
use reth_revm::{inspector_handle_register, EvmBuilder};
|
||||||
use revm_primitives::{
|
use revm_primitives::{
|
||||||
AnalysisKind, BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, Env, SpecId, TxEnv,
|
AnalysisKind, BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, Env, SpecId, TxEnv,
|
||||||
};
|
};
|
||||||
@ -182,24 +183,57 @@ impl ConfigureEvmEnv for EthEvmConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigureEvm for EthEvmConfig {}
|
impl ConfigureEvm for EthEvmConfig {
|
||||||
|
fn evm_with_env<DB: reth_revm::Database>(
|
||||||
|
&self,
|
||||||
|
db: DB,
|
||||||
|
evm_env: EvmEnv,
|
||||||
|
tx: TxEnv,
|
||||||
|
) -> reth_revm::Evm<'_, (), DB> {
|
||||||
|
EvmBuilder::default()
|
||||||
|
.with_db(db)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evm_with_env_and_inspector<DB, I>(
|
||||||
|
&self,
|
||||||
|
db: DB,
|
||||||
|
evm_env: EvmEnv,
|
||||||
|
tx: TxEnv,
|
||||||
|
inspector: I,
|
||||||
|
) -> reth_revm::Evm<'_, I, DB>
|
||||||
|
where
|
||||||
|
DB: reth_revm::Database,
|
||||||
|
I: reth_revm::GetInspector<DB>,
|
||||||
|
{
|
||||||
|
EvmBuilder::default()
|
||||||
|
.with_db(db)
|
||||||
|
.with_external_context(inspector)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
|
.append_handler_register(inspector_handle_register)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use alloy_consensus::{constants::KECCAK_EMPTY, Header};
|
use alloy_consensus::Header;
|
||||||
use alloy_genesis::Genesis;
|
use alloy_genesis::Genesis;
|
||||||
use alloy_primitives::{B256, U256};
|
use alloy_primitives::U256;
|
||||||
use reth_chainspec::{Chain, ChainSpec, MAINNET};
|
use reth_chainspec::{Chain, ChainSpec, MAINNET};
|
||||||
use reth_evm::{env::EvmEnv, execute::ProviderError};
|
use reth_evm::{env::EvmEnv, execute::ProviderError};
|
||||||
use reth_revm::{
|
use reth_revm::{
|
||||||
db::{CacheDB, EmptyDBTyped},
|
db::{CacheDB, EmptyDBTyped},
|
||||||
inspectors::NoOpInspector,
|
inspectors::NoOpInspector,
|
||||||
primitives::{BlockEnv, CfgEnv, SpecId},
|
primitives::{BlockEnv, CfgEnv, SpecId},
|
||||||
JournaledState,
|
|
||||||
};
|
};
|
||||||
use revm_primitives::HandlerCfg;
|
use revm_primitives::HandlerCfg;
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fill_cfg_and_block_env() {
|
fn test_fill_cfg_and_block_env() {
|
||||||
@ -226,45 +260,6 @@ mod tests {
|
|||||||
assert_eq!(cfg_env_with_handler_cfg.chain_id, chain_spec.chain().id());
|
assert_eq!(cfg_env_with_handler_cfg.chain_id, chain_spec.chain().id());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(clippy::needless_update)]
|
|
||||||
fn test_evm_configure() {
|
|
||||||
// Create a default `EthEvmConfig`
|
|
||||||
let evm_config = EthEvmConfig::new(MAINNET.clone());
|
|
||||||
|
|
||||||
// Initialize an empty database wrapped in CacheDB
|
|
||||||
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
|
|
||||||
|
|
||||||
// Create an EVM instance using the configuration and the database
|
|
||||||
let evm = evm_config.evm(db);
|
|
||||||
|
|
||||||
// Check that the EVM environment is initialized with default values
|
|
||||||
assert_eq!(evm.context.evm.inner.env, Box::default());
|
|
||||||
|
|
||||||
// Latest spec ID and no warm preloaded addresses
|
|
||||||
assert_eq!(
|
|
||||||
evm.context.evm.inner.journaled_state,
|
|
||||||
JournaledState::new(SpecId::LATEST, HashSet::default())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ensure that the accounts database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.accounts.is_empty());
|
|
||||||
|
|
||||||
// Ensure that the block hashes database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.block_hashes.is_empty());
|
|
||||||
|
|
||||||
// Verify that there are two default contracts in the contracts database
|
|
||||||
assert_eq!(evm.context.evm.inner.db.contracts.len(), 2);
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&KECCAK_EMPTY));
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&B256::ZERO));
|
|
||||||
|
|
||||||
// Ensure that the logs database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.logs.is_empty());
|
|
||||||
|
|
||||||
// No Optimism
|
|
||||||
assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(clippy::needless_update)]
|
#[allow(clippy::needless_update)]
|
||||||
fn test_evm_with_env_default_spec() {
|
fn test_evm_with_env_default_spec() {
|
||||||
@ -374,57 +369,15 @@ mod tests {
|
|||||||
let evm = evm_config.evm_with_env(db, evm_env, Default::default());
|
let evm = evm_config.evm_with_env(db, evm_env, Default::default());
|
||||||
|
|
||||||
// Check that the spec ID is setup properly
|
// Check that the spec ID is setup properly
|
||||||
assert_eq!(evm.handler.spec_id(), SpecId::CONSTANTINOPLE);
|
assert_eq!(evm.handler.spec_id(), SpecId::PETERSBURG);
|
||||||
|
|
||||||
// No Optimism
|
// No Optimism
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
evm.handler.cfg,
|
evm.handler.cfg,
|
||||||
HandlerCfg { spec_id: SpecId::CONSTANTINOPLE, ..Default::default() }
|
HandlerCfg { spec_id: SpecId::PETERSBURG, ..Default::default() }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(clippy::needless_update)]
|
|
||||||
fn test_evm_with_inspector() {
|
|
||||||
let evm_config = EthEvmConfig::new(MAINNET.clone());
|
|
||||||
|
|
||||||
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
|
|
||||||
|
|
||||||
// No operation inspector
|
|
||||||
let noop = NoOpInspector;
|
|
||||||
|
|
||||||
let evm = evm_config.evm_with_inspector(db, noop);
|
|
||||||
|
|
||||||
// Check that the inspector is set correctly
|
|
||||||
assert_eq!(evm.context.external, noop);
|
|
||||||
|
|
||||||
// Check that the EVM environment is initialized with default values
|
|
||||||
assert_eq!(evm.context.evm.inner.env, Box::default());
|
|
||||||
|
|
||||||
// Latest spec ID and no warm preloaded addresses
|
|
||||||
assert_eq!(
|
|
||||||
evm.context.evm.inner.journaled_state,
|
|
||||||
JournaledState::new(SpecId::LATEST, HashSet::default())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ensure that the accounts database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.accounts.is_empty());
|
|
||||||
|
|
||||||
// Ensure that the block hashes database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.block_hashes.is_empty());
|
|
||||||
|
|
||||||
// Verify that there are two default contracts in the contracts database
|
|
||||||
assert_eq!(evm.context.evm.inner.db.contracts.len(), 2);
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&KECCAK_EMPTY));
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&B256::ZERO));
|
|
||||||
|
|
||||||
// Ensure that the logs database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.logs.is_empty());
|
|
||||||
|
|
||||||
// No Optimism
|
|
||||||
assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(clippy::needless_update)]
|
#[allow(clippy::needless_update)]
|
||||||
fn test_evm_with_env_and_default_inspector() {
|
fn test_evm_with_env_and_default_inspector() {
|
||||||
@ -530,7 +483,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Check that the spec ID is set properly
|
// Check that the spec ID is set properly
|
||||||
assert_eq!(evm.handler.spec_id(), SpecId::CONSTANTINOPLE);
|
assert_eq!(evm.handler.spec_id(), SpecId::PETERSBURG);
|
||||||
assert_eq!(evm.context.evm.env.block, evm_env.block_env);
|
assert_eq!(evm.context.evm.env.block, evm_env.block_env);
|
||||||
assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env);
|
assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env);
|
||||||
assert_eq!(evm.context.evm.env.tx, Default::default());
|
assert_eq!(evm.context.evm.env.tx, Default::default());
|
||||||
@ -539,7 +492,7 @@ mod tests {
|
|||||||
// No Optimism
|
// No Optimism
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
evm.handler.cfg,
|
evm.handler.cfg,
|
||||||
HandlerCfg { spec_id: SpecId::CONSTANTINOPLE, ..Default::default() }
|
HandlerCfg { spec_id: SpecId::PETERSBURG, ..Default::default() }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,141 +0,0 @@
|
|||||||
//! Builder for creating an EVM with a database and environment.
|
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
use revm::{inspector_handle_register, Database, Evm, EvmBuilder, GetInspector};
|
|
||||||
use revm_primitives::EnvWithHandlerCfg;
|
|
||||||
|
|
||||||
/// Builder for creating an EVM with a database and environment.
|
|
||||||
///
|
|
||||||
/// Wrapper around [`EvmBuilder`] that allows for setting the database and environment for the EVM.
|
|
||||||
///
|
|
||||||
/// This is useful for creating an EVM with a custom database and environment without having to
|
|
||||||
/// necessarily rely on Revm inspector.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct RethEvmBuilder<DB, EXT = ()> {
|
|
||||||
/// The database to use for the EVM.
|
|
||||||
db: DB,
|
|
||||||
/// The environment to use for the EVM.
|
|
||||||
env: Option<Box<EnvWithHandlerCfg>>,
|
|
||||||
/// The external context for the EVM.
|
|
||||||
external_context: EXT,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<DB> RethEvmBuilder<DB> {
|
|
||||||
/// Create a new EVM builder with the given database.
|
|
||||||
pub const fn new(db: DB) -> Self {
|
|
||||||
Self { db, env: None, external_context: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<DB, EXT> RethEvmBuilder<DB, EXT>
|
|
||||||
where
|
|
||||||
DB: Database,
|
|
||||||
{
|
|
||||||
/// Set the environment for the EVM.
|
|
||||||
pub fn with_env(mut self, env: Box<EnvWithHandlerCfg>) -> Self {
|
|
||||||
self.env = Some(env);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the external context for the EVM.
|
|
||||||
pub fn with_external_context<EXT1>(self, external_context: EXT1) -> RethEvmBuilder<DB, EXT1> {
|
|
||||||
RethEvmBuilder { db: self.db, env: self.env, external_context }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build the EVM with the given database and environment.
|
|
||||||
pub fn build<'a>(self) -> Evm<'a, EXT, DB> {
|
|
||||||
let mut builder =
|
|
||||||
EvmBuilder::default().with_db(self.db).with_external_context(self.external_context);
|
|
||||||
if let Some(env) = self.env {
|
|
||||||
builder = builder.with_spec_id(env.spec_id());
|
|
||||||
builder = builder.with_env(env.env);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build the EVM with the given database and environment, using the given inspector.
|
|
||||||
pub fn build_with_inspector<'a, I>(self, inspector: I) -> Evm<'a, I, DB>
|
|
||||||
where
|
|
||||||
I: GetInspector<DB>,
|
|
||||||
EXT: 'a,
|
|
||||||
{
|
|
||||||
let mut builder =
|
|
||||||
EvmBuilder::default().with_db(self.db).with_external_context(self.external_context);
|
|
||||||
if let Some(env) = self.env {
|
|
||||||
builder = builder.with_spec_id(env.spec_id());
|
|
||||||
builder = builder.with_env(env.env);
|
|
||||||
}
|
|
||||||
builder
|
|
||||||
.with_external_context(inspector)
|
|
||||||
.append_handler_register(inspector_handle_register)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for configuring an EVM builder.
|
|
||||||
pub trait ConfigureEvmBuilder {
|
|
||||||
/// The type of EVM builder that this trait can configure.
|
|
||||||
type Builder<'a, DB: Database>: EvmFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for configuring the EVM for executing full blocks.
|
|
||||||
pub trait EvmFactory {
|
|
||||||
/// Returns new EVM with the given database
|
|
||||||
///
|
|
||||||
/// This does not automatically configure the EVM with [`crate::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<'static, (), DB>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
RethEvmBuilder::new(db).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<'a, DB: Database + 'a>(
|
|
||||||
&self,
|
|
||||||
db: DB,
|
|
||||||
env: EnvWithHandlerCfg,
|
|
||||||
) -> Evm<'a, (), DB> {
|
|
||||||
RethEvmBuilder::new(db).with_env(env.into()).build()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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>,
|
|
||||||
{
|
|
||||||
RethEvmBuilder::new(db).with_env(env.into()).build_with_inspector(inspector)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new EVM with the given inspector.
|
|
||||||
///
|
|
||||||
/// Caution: This does not automatically configure the EVM with [`crate::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).build_with_inspector(inspector)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<DB: Database, EXT: Clone> EvmFactory for RethEvmBuilder<DB, EXT> {}
|
|
||||||
@ -17,14 +17,12 @@
|
|||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use crate::builder::RethEvmBuilder;
|
|
||||||
use alloy_consensus::BlockHeader as _;
|
use alloy_consensus::BlockHeader as _;
|
||||||
use alloy_primitives::{Address, Bytes, B256, U256};
|
use alloy_primitives::{Address, Bytes, B256, U256};
|
||||||
use reth_primitives_traits::{BlockHeader, SignedTransaction};
|
use reth_primitives_traits::{BlockHeader, SignedTransaction};
|
||||||
use revm::{Database, Evm, GetInspector};
|
use revm::{Database, Evm, GetInspector};
|
||||||
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, Env, SpecId, TxEnv};
|
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, Env, SpecId, TxEnv};
|
||||||
|
|
||||||
pub mod builder;
|
|
||||||
pub mod either;
|
pub mod either;
|
||||||
/// EVM environment configuration.
|
/// EVM environment configuration.
|
||||||
pub mod env;
|
pub mod env;
|
||||||
@ -42,26 +40,11 @@ pub mod test_utils;
|
|||||||
|
|
||||||
/// Trait for configuring the EVM for executing full blocks.
|
/// Trait for configuring the EVM for executing full blocks.
|
||||||
pub trait ConfigureEvm: ConfigureEvmEnv {
|
pub trait ConfigureEvm: ConfigureEvmEnv {
|
||||||
/// 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<'_, (), DB> {
|
|
||||||
RethEvmBuilder::new(db).build()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new EVM with the given database configured with the given environment settings,
|
/// Returns a new EVM with the given database configured with the given environment settings,
|
||||||
/// including the spec id and transaction environment.
|
/// including the spec id and transaction environment.
|
||||||
///
|
///
|
||||||
/// This will preserve any handler modifications
|
/// This will preserve any handler modifications
|
||||||
fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnv, tx: TxEnv) -> Evm<'_, (), DB> {
|
fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnv, tx: TxEnv) -> Evm<'_, (), DB>;
|
||||||
let mut evm = self.evm(db);
|
|
||||||
evm.modify_spec_id(evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id);
|
|
||||||
evm.context.evm.env =
|
|
||||||
Env::boxed(evm_env.cfg_env_with_handler_cfg.cfg_env, evm_env.block_env, tx);
|
|
||||||
evm
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new EVM with the given database configured with `cfg` and `block_env`
|
/// Returns a new EVM with the given database configured with `cfg` and `block_env`
|
||||||
/// configuration derived from the given header. Relies on
|
/// configuration derived from the given header. Relies on
|
||||||
@ -90,27 +73,7 @@ pub trait ConfigureEvm: ConfigureEvmEnv {
|
|||||||
) -> Evm<'_, I, DB>
|
) -> Evm<'_, I, DB>
|
||||||
where
|
where
|
||||||
DB: Database,
|
DB: Database,
|
||||||
I: GetInspector<DB>,
|
I: GetInspector<DB>;
|
||||||
{
|
|
||||||
let mut evm = self.evm_with_inspector(db, inspector);
|
|
||||||
evm.modify_spec_id(evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id);
|
|
||||||
evm.context.evm.env =
|
|
||||||
Env::boxed(evm_env.cfg_env_with_handler_cfg.cfg_env, evm_env.block_env, tx);
|
|
||||||
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).build_with_inspector(inspector)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, T> ConfigureEvm for &'b T
|
impl<'b, T> ConfigureEvm for &'b T
|
||||||
@ -118,10 +81,6 @@ where
|
|||||||
T: ConfigureEvm,
|
T: ConfigureEvm,
|
||||||
&'b T: ConfigureEvmEnv<Header = T::Header>,
|
&'b T: ConfigureEvmEnv<Header = T::Header>,
|
||||||
{
|
{
|
||||||
fn evm<DB: Database>(&self, db: DB) -> Evm<'_, (), DB> {
|
|
||||||
(*self).evm(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn evm_for_block<DB: Database>(&self, db: DB, header: &Self::Header) -> Evm<'_, (), DB> {
|
fn evm_for_block<DB: Database>(&self, db: DB, header: &Self::Header) -> Evm<'_, (), DB> {
|
||||||
(*self).evm_for_block(db, header)
|
(*self).evm_for_block(db, header)
|
||||||
}
|
}
|
||||||
@ -143,14 +102,6 @@ where
|
|||||||
{
|
{
|
||||||
(*self).evm_with_env_and_inspector(db, evm_env, tx_env, inspector)
|
(*self).evm_with_env_and_inspector(db, evm_env, tx_env, inspector)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
|
|
||||||
where
|
|
||||||
DB: Database,
|
|
||||||
I: GetInspector<DB>,
|
|
||||||
{
|
|
||||||
(*self).evm_with_inspector(db, inspector)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This represents the set of methods used to configure the EVM's environment before block
|
/// This represents the set of methods used to configure the EVM's environment before block
|
||||||
|
|||||||
@ -168,19 +168,41 @@ impl ConfigureEvmEnv for OpEvmConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigureEvm for OpEvmConfig {
|
impl ConfigureEvm for OpEvmConfig {
|
||||||
fn evm<DB: Database>(&self, db: DB) -> Evm<'_, (), DB> {
|
fn evm_with_env<DB: Database>(
|
||||||
EvmBuilder::default().with_db(db).optimism().build()
|
&self,
|
||||||
|
db: DB,
|
||||||
|
mut evm_env: EvmEnv,
|
||||||
|
tx: TxEnv,
|
||||||
|
) -> Evm<'_, (), DB> {
|
||||||
|
evm_env.cfg_env_with_handler_cfg.handler_cfg.is_optimism = true;
|
||||||
|
|
||||||
|
EvmBuilder::default()
|
||||||
|
.with_db(db)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
|
fn evm_with_env_and_inspector<DB, I>(
|
||||||
|
&self,
|
||||||
|
db: DB,
|
||||||
|
mut evm_env: EvmEnv,
|
||||||
|
tx: TxEnv,
|
||||||
|
inspector: I,
|
||||||
|
) -> Evm<'_, I, DB>
|
||||||
where
|
where
|
||||||
DB: Database,
|
DB: Database,
|
||||||
I: GetInspector<DB>,
|
I: GetInspector<DB>,
|
||||||
{
|
{
|
||||||
|
evm_env.cfg_env_with_handler_cfg.handler_cfg.is_optimism = true;
|
||||||
|
|
||||||
EvmBuilder::default()
|
EvmBuilder::default()
|
||||||
.with_db(db)
|
.with_db(db)
|
||||||
.with_external_context(inspector)
|
.with_external_context(inspector)
|
||||||
.optimism()
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
.append_handler_register(inspector_handle_register)
|
.append_handler_register(inspector_handle_register)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
@ -189,14 +211,10 @@ impl ConfigureEvm for OpEvmConfig {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use alloy_consensus::{constants::KECCAK_EMPTY, Header, Receipt};
|
use alloy_consensus::{Header, Receipt};
|
||||||
use alloy_eips::eip7685::Requests;
|
use alloy_eips::eip7685::Requests;
|
||||||
use alloy_genesis::Genesis;
|
use alloy_genesis::Genesis;
|
||||||
use alloy_primitives::{
|
use alloy_primitives::{bytes, map::HashMap, Address, LogData, B256, U256};
|
||||||
bytes,
|
|
||||||
map::{HashMap, HashSet},
|
|
||||||
Address, LogData, B256, U256,
|
|
||||||
};
|
|
||||||
use reth_chainspec::ChainSpec;
|
use reth_chainspec::ChainSpec;
|
||||||
use reth_evm::execute::ProviderError;
|
use reth_evm::execute::ProviderError;
|
||||||
use reth_execution_types::{
|
use reth_execution_types::{
|
||||||
@ -209,7 +227,6 @@ mod tests {
|
|||||||
db::{BundleState, CacheDB, EmptyDBTyped},
|
db::{BundleState, CacheDB, EmptyDBTyped},
|
||||||
inspectors::NoOpInspector,
|
inspectors::NoOpInspector,
|
||||||
primitives::{AccountInfo, BlockEnv, CfgEnv, SpecId},
|
primitives::{AccountInfo, BlockEnv, CfgEnv, SpecId},
|
||||||
JournaledState,
|
|
||||||
};
|
};
|
||||||
use revm_primitives::HandlerCfg;
|
use revm_primitives::HandlerCfg;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -244,47 +261,6 @@ mod tests {
|
|||||||
assert_eq!(cfg_env_with_handler_cfg.chain_id, chain_spec.chain().id());
|
assert_eq!(cfg_env_with_handler_cfg.chain_id, chain_spec.chain().id());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_evm_configure() {
|
|
||||||
// Create a default `OpEvmConfig`
|
|
||||||
let evm_config = test_evm_config();
|
|
||||||
|
|
||||||
// Initialize an empty database wrapped in CacheDB
|
|
||||||
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
|
|
||||||
|
|
||||||
// Create an EVM instance using the configuration and the database
|
|
||||||
let evm = evm_config.evm(db);
|
|
||||||
|
|
||||||
// Check that the EVM environment is initialized with default values
|
|
||||||
assert_eq!(evm.context.evm.inner.env, Box::default());
|
|
||||||
|
|
||||||
// Latest spec ID and no warm preloaded addresses
|
|
||||||
assert_eq!(
|
|
||||||
evm.context.evm.inner.journaled_state,
|
|
||||||
JournaledState::new(SpecId::LATEST, HashSet::default())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ensure that the accounts database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.accounts.is_empty());
|
|
||||||
|
|
||||||
// Ensure that the block hashes database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.block_hashes.is_empty());
|
|
||||||
|
|
||||||
// Verify that there are two default contracts in the contracts database
|
|
||||||
assert_eq!(evm.context.evm.inner.db.contracts.len(), 2);
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&KECCAK_EMPTY));
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&B256::ZERO));
|
|
||||||
|
|
||||||
// Ensure that the logs database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.logs.is_empty());
|
|
||||||
|
|
||||||
// Optimism in handler
|
|
||||||
assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true });
|
|
||||||
|
|
||||||
// Default spec ID
|
|
||||||
assert_eq!(evm.handler.spec_id(), SpecId::LATEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_evm_with_env_default_spec() {
|
fn test_evm_with_env_default_spec() {
|
||||||
let evm_config = test_evm_config();
|
let evm_config = test_evm_config();
|
||||||
@ -389,50 +365,6 @@ mod tests {
|
|||||||
assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::ECOTONE, is_optimism: true });
|
assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::ECOTONE, is_optimism: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_evm_with_inspector() {
|
|
||||||
let evm_config = test_evm_config();
|
|
||||||
|
|
||||||
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
|
|
||||||
|
|
||||||
// No operation inspector
|
|
||||||
let noop = NoOpInspector;
|
|
||||||
|
|
||||||
let evm = evm_config.evm_with_inspector(db, noop);
|
|
||||||
|
|
||||||
// Check that the inspector is set correctly
|
|
||||||
assert_eq!(evm.context.external, noop);
|
|
||||||
|
|
||||||
// Check that the EVM environment is initialized with default values
|
|
||||||
assert_eq!(evm.context.evm.inner.env, Box::default());
|
|
||||||
|
|
||||||
// Latest spec ID and no warm preloaded addresses
|
|
||||||
assert_eq!(
|
|
||||||
evm.context.evm.inner.journaled_state,
|
|
||||||
JournaledState::new(SpecId::LATEST, HashSet::default())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ensure that the accounts database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.accounts.is_empty());
|
|
||||||
|
|
||||||
// Ensure that the block hashes database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.block_hashes.is_empty());
|
|
||||||
|
|
||||||
// Verify that there are two default contracts in the contracts database
|
|
||||||
assert_eq!(evm.context.evm.inner.db.contracts.len(), 2);
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&KECCAK_EMPTY));
|
|
||||||
assert!(evm.context.evm.inner.db.contracts.contains_key(&B256::ZERO));
|
|
||||||
|
|
||||||
// Ensure that the logs database is empty
|
|
||||||
assert!(evm.context.evm.inner.db.logs.is_empty());
|
|
||||||
|
|
||||||
// Default spec ID
|
|
||||||
assert_eq!(evm.handler.spec_id(), SpecId::LATEST);
|
|
||||||
|
|
||||||
// Optimism in handler
|
|
||||||
assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_evm_with_env_and_default_inspector() {
|
fn test_evm_with_env_and_default_inspector() {
|
||||||
let evm_config = test_evm_config();
|
let evm_config = test_evm_config();
|
||||||
|
|||||||
@ -55,8 +55,8 @@ impl MyEvmConfig {
|
|||||||
impl MyEvmConfig {
|
impl MyEvmConfig {
|
||||||
/// Sets the precompiles to the EVM handler
|
/// Sets the precompiles to the EVM handler
|
||||||
///
|
///
|
||||||
/// This will be invoked when the EVM is created via [ConfigureEvm::evm] or
|
/// This will be invoked when the EVM is created via [ConfigureEvm::evm_with_env] or
|
||||||
/// [ConfigureEvm::evm_with_inspector]
|
/// [ConfigureEvm::evm_with_env_and_inspector]
|
||||||
///
|
///
|
||||||
/// This will use the default mainnet precompiles and add additional precompiles.
|
/// This will use the default mainnet precompiles and add additional precompiles.
|
||||||
pub fn set_precompiles<EXT, DB>(handler: &mut EvmHandler<EXT, DB>)
|
pub fn set_precompiles<EXT, DB>(handler: &mut EvmHandler<EXT, DB>)
|
||||||
@ -117,15 +117,24 @@ impl ConfigureEvmEnv for MyEvmConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigureEvm for MyEvmConfig {
|
impl ConfigureEvm for MyEvmConfig {
|
||||||
fn evm<DB: Database>(&self, db: DB) -> Evm<'_, (), DB> {
|
fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnv, tx: TxEnv) -> Evm<'_, (), DB> {
|
||||||
EvmBuilder::default()
|
EvmBuilder::default()
|
||||||
.with_db(db)
|
.with_db(db)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
// add additional precompiles
|
// add additional precompiles
|
||||||
.append_handler_register(MyEvmConfig::set_precompiles)
|
.append_handler_register(MyEvmConfig::set_precompiles)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
|
fn evm_with_env_and_inspector<DB, I>(
|
||||||
|
&self,
|
||||||
|
db: DB,
|
||||||
|
evm_env: EvmEnv,
|
||||||
|
tx: TxEnv,
|
||||||
|
inspector: I,
|
||||||
|
) -> Evm<'_, I, DB>
|
||||||
where
|
where
|
||||||
DB: Database,
|
DB: Database,
|
||||||
I: GetInspector<DB>,
|
I: GetInspector<DB>,
|
||||||
@ -133,6 +142,9 @@ impl ConfigureEvm for MyEvmConfig {
|
|||||||
EvmBuilder::default()
|
EvmBuilder::default()
|
||||||
.with_db(db)
|
.with_db(db)
|
||||||
.with_external_context(inspector)
|
.with_external_context(inspector)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
// add additional precompiles
|
// add additional precompiles
|
||||||
.append_handler_register(MyEvmConfig::set_precompiles)
|
.append_handler_register(MyEvmConfig::set_precompiles)
|
||||||
.append_handler_register(inspector_handle_register)
|
.append_handler_register(inspector_handle_register)
|
||||||
|
|||||||
@ -68,8 +68,8 @@ impl MyEvmConfig {
|
|||||||
|
|
||||||
/// Sets the precompiles to the EVM handler
|
/// Sets the precompiles to the EVM handler
|
||||||
///
|
///
|
||||||
/// This will be invoked when the EVM is created via [ConfigureEvm::evm] or
|
/// This will be invoked when the EVM is created via [ConfigureEvm::evm_with_env] or
|
||||||
/// [ConfigureEvm::evm_with_inspector]
|
/// [ConfigureEvm::evm_with_env_and_inspector]
|
||||||
///
|
///
|
||||||
/// This will use the default mainnet precompiles and wrap them with a cache.
|
/// This will use the default mainnet precompiles and wrap them with a cache.
|
||||||
pub fn set_precompiles<EXT, DB>(
|
pub fn set_precompiles<EXT, DB>(
|
||||||
@ -179,10 +179,13 @@ impl ConfigureEvmEnv for MyEvmConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigureEvm for MyEvmConfig {
|
impl ConfigureEvm for MyEvmConfig {
|
||||||
fn evm<DB: Database>(&self, db: DB) -> Evm<'_, (), DB> {
|
fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnv, tx: TxEnv) -> Evm<'_, (), DB> {
|
||||||
let new_cache = self.precompile_cache.clone();
|
let new_cache = self.precompile_cache.clone();
|
||||||
EvmBuilder::default()
|
EvmBuilder::default()
|
||||||
.with_db(db)
|
.with_db(db)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
// add additional precompiles
|
// add additional precompiles
|
||||||
.append_handler_register_box(Box::new(move |handler| {
|
.append_handler_register_box(Box::new(move |handler| {
|
||||||
MyEvmConfig::set_precompiles(handler, new_cache.clone())
|
MyEvmConfig::set_precompiles(handler, new_cache.clone())
|
||||||
@ -190,7 +193,13 @@ impl ConfigureEvm for MyEvmConfig {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
|
fn evm_with_env_and_inspector<DB, I>(
|
||||||
|
&self,
|
||||||
|
db: DB,
|
||||||
|
evm_env: EvmEnv,
|
||||||
|
tx: TxEnv,
|
||||||
|
inspector: I,
|
||||||
|
) -> Evm<'_, I, DB>
|
||||||
where
|
where
|
||||||
DB: Database,
|
DB: Database,
|
||||||
I: GetInspector<DB>,
|
I: GetInspector<DB>,
|
||||||
@ -199,6 +208,9 @@ impl ConfigureEvm for MyEvmConfig {
|
|||||||
EvmBuilder::default()
|
EvmBuilder::default()
|
||||||
.with_db(db)
|
.with_db(db)
|
||||||
.with_external_context(inspector)
|
.with_external_context(inspector)
|
||||||
|
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
|
||||||
|
.with_block_env(evm_env.block_env)
|
||||||
|
.with_tx_env(tx)
|
||||||
// add additional precompiles
|
// add additional precompiles
|
||||||
.append_handler_register_box(Box::new(move |handler| {
|
.append_handler_register_box(Box::new(move |handler| {
|
||||||
MyEvmConfig::set_precompiles(handler, new_cache.clone())
|
MyEvmConfig::set_precompiles(handler, new_cache.clone())
|
||||||
|
|||||||
Reference in New Issue
Block a user