Skip to content

Commit

Permalink
feat: add Spec generic for EvmEnv (#13975)
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr authored Jan 24, 2025
1 parent 621b30f commit 203fed0
Show file tree
Hide file tree
Showing 19 changed files with 223 additions and 293 deletions.
96 changes: 28 additions & 68 deletions crates/ethereum/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use reth_primitives_traits::transaction::execute::FillTxEnv;
use reth_revm::{inspector_handle_register, Database, EvmBuilder};
use revm_primitives::{
AnalysisKind, BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv, CfgEnvWithHandlerCfg, EVMError,
Env, HandlerCfg, ResultAndState, SpecId, TxEnv, TxKind,
HandlerCfg, ResultAndState, SpecId, TxEnv, TxKind,
};

mod config;
Expand Down Expand Up @@ -58,17 +58,6 @@ impl<EXT, DB: Database> Evm for EthEvm<'_, EXT, DB> {
self.0.block()
}

fn into_env(self) -> EvmEnv {
let Env { cfg, block, tx: _ } = *self.0.context.evm.inner.env;
EvmEnv {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
cfg_env: cfg,
handler_cfg: self.0.handler.cfg,
},
block_env: block,
}
}

fn transact(&mut self, tx: Self::Tx) -> Result<ResultAndState, Self::Error> {
*self.tx_mut() = tx;
self.0.transact()
Expand Down Expand Up @@ -151,6 +140,7 @@ impl ConfigureEvmEnv for EthEvmConfig {
type Transaction = TransactionSigned;
type Error = Infallible;
type TxEnv = TxEnv;
type Spec = revm_primitives::SpecId;

fn tx_env(&self, transaction: &TransactionSigned, sender: Address) -> Self::TxEnv {
let mut tx_env = TxEnv::default();
Expand All @@ -159,33 +149,27 @@ impl ConfigureEvmEnv for EthEvmConfig {
}

fn evm_env(&self, header: &Self::Header) -> EvmEnv {
let spec_id = config::revm_spec(self.chain_spec(), header);
let spec = config::revm_spec(self.chain_spec(), header);

let mut cfg_env = CfgEnv::default();
cfg_env.chain_id = self.chain_spec.chain().id();
cfg_env.perf_analyse_created_bytecodes = AnalysisKind::default();

let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg {
cfg_env,
#[allow(clippy::needless_update)] // side-effect of optimism fields
handler_cfg: HandlerCfg { spec_id, ..Default::default() },
};

let block_env = BlockEnv {
number: U256::from(header.number()),
coinbase: header.beneficiary(),
timestamp: U256::from(header.timestamp()),
difficulty: if spec_id >= SpecId::MERGE { U256::ZERO } else { header.difficulty() },
prevrandao: if spec_id >= SpecId::MERGE { header.mix_hash() } else { None },
difficulty: if spec >= SpecId::MERGE { U256::ZERO } else { header.difficulty() },
prevrandao: if spec >= SpecId::MERGE { header.mix_hash() } else { None },
gas_limit: U256::from(header.gas_limit()),
basefee: U256::from(header.base_fee_per_gas().unwrap_or_default()),
// EIP-4844 excess blob gas of this block, introduced in Cancun
blob_excess_gas_and_price: header.excess_blob_gas.map(|excess_blob_gas| {
BlobExcessGasAndPrice::new(excess_blob_gas, spec_id >= SpecId::PRAGUE)
BlobExcessGasAndPrice::new(excess_blob_gas, spec >= SpecId::PRAGUE)
}),
};

EvmEnv { cfg_env_with_handler_cfg, block_env }
EvmEnv { cfg_env, spec, block_env }
}

fn next_evm_env(
Expand Down Expand Up @@ -255,10 +239,14 @@ impl ConfigureEvm for EthEvmConfig {
type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>;

fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> {
let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg {
cfg_env: evm_env.cfg_env,
handler_cfg: HandlerCfg::new(evm_env.spec),
};
EthEvm(
EvmBuilder::default()
.with_db(db)
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
.with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg)
.with_block_env(evm_env.block_env)
.build(),
)
Expand All @@ -274,11 +262,15 @@ impl ConfigureEvm for EthEvmConfig {
DB: Database,
I: reth_revm::GetInspector<DB>,
{
let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg {
cfg_env: evm_env.cfg_env,
handler_cfg: HandlerCfg::new(evm_env.spec),
};
EthEvm(
EvmBuilder::default()
.with_db(db)
.with_external_context(inspector)
.with_cfg_env_with_handler_cfg(evm_env.cfg_env_with_handler_cfg)
.with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg)
.with_block_env(evm_env.block_env)
.append_handler_register(inspector_handle_register)
.build(),
Expand Down Expand Up @@ -318,12 +310,12 @@ mod tests {

// Use the `EthEvmConfig` to fill the `cfg_env` and `block_env` based on the ChainSpec,
// Header, and total difficulty
let EvmEnv { cfg_env_with_handler_cfg, .. } =
let EvmEnv { cfg_env, .. } =
EthEvmConfig::new(Arc::new(chain_spec.clone())).evm_env(&header);

// Assert that the chain ID in the `cfg_env` is correctly set to the chain ID of the
// ChainSpec
assert_eq!(cfg_env_with_handler_cfg.chain_id, chain_spec.chain().id());
assert_eq!(cfg_env.chain_id, chain_spec.chain().id());
}

#[test]
Expand All @@ -339,7 +331,7 @@ mod tests {

// Check that the EVM environment
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);

// Default spec ID
assert_eq!(evm.handler.spec_id(), SpecId::LATEST);
Expand All @@ -358,13 +350,7 @@ mod tests {
// Create a custom configuration environment with a chain ID of 111
let cfg = CfgEnv::default().with_chain_id(111);

let evm_env = EvmEnv {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
cfg_env: cfg.clone(),
handler_cfg: Default::default(),
},
..Default::default()
};
let evm_env = EvmEnv { cfg_env: cfg.clone(), ..Default::default() };

let evm = evm_config.evm_with_env(db, evm_env);

Expand Down Expand Up @@ -393,13 +379,7 @@ mod tests {
..Default::default()
};

let evm_env = EvmEnv {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
cfg_env: CfgEnv::default(),
handler_cfg: Default::default(),
},
block_env: block,
};
let evm_env = EvmEnv { block_env: block, ..Default::default() };

let evm = evm_config.evm_with_env(db, evm_env.clone());

Expand All @@ -420,15 +400,7 @@ mod tests {

let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();

let handler_cfg = HandlerCfg { spec_id: SpecId::CONSTANTINOPLE, ..Default::default() };

let evm_env = EvmEnv {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
cfg_env: Default::default(),
handler_cfg,
},
..Default::default()
};
let evm_env = EvmEnv { spec: SpecId::CONSTANTINOPLE, ..Default::default() };

let evm = evm_config.evm_with_env(db, evm_env);

Expand All @@ -454,7 +426,7 @@ mod tests {

// Check that the EVM environment is set to default values
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);
assert_eq!(evm.context.external, NoOpInspector);
assert_eq!(evm.handler.spec_id(), SpecId::LATEST);

Expand All @@ -470,13 +442,8 @@ mod tests {

let cfg_env = CfgEnv::default().with_chain_id(111);
let block = BlockEnv::default();
let evm_env = EvmEnv {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
cfg_env: cfg_env.clone(),
handler_cfg: Default::default(),
},
block_env: block,
};
let evm_env =
EvmEnv { cfg_env: cfg_env.clone(), block_env: block, spec: Default::default() };

let evm = evm_config.evm_with_env_and_inspector(db, evm_env, NoOpInspector);

Expand Down Expand Up @@ -521,21 +488,14 @@ mod tests {
let evm_config = EthEvmConfig::new(MAINNET.clone());
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();

let handler_cfg = HandlerCfg { spec_id: SpecId::CONSTANTINOPLE, ..Default::default() };
let evm_env = EvmEnv {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
handler_cfg,
cfg_env: Default::default(),
},
..Default::default()
};
let evm_env = EvmEnv { spec: SpecId::CONSTANTINOPLE, ..Default::default() };

let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector);

// Check that the spec ID is set properly
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.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env);
assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env);
assert_eq!(evm.context.evm.env.tx, Default::default());
assert_eq!(evm.context.external, NoOpInspector);

Expand Down
10 changes: 5 additions & 5 deletions crates/ethereum/payload/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ where
{
/// Returns the configured [`EvmEnv`] for the targeted payload
/// (that has the `parent` as its parent).
fn cfg_and_block_env(
fn evm_env(
&self,
config: &PayloadConfig<EthPayloadBuilderAttributes>,
parent: &Header,
) -> Result<EvmEnv, EvmConfig::Error> {
) -> Result<EvmEnv<EvmConfig::Spec>, EvmConfig::Error> {
let next_attributes = NextBlockEnvAttributes {
timestamp: config.attributes.timestamp(),
suggested_fee_recipient: config.attributes.suggested_fee_recipient(),
Expand All @@ -111,7 +111,7 @@ where
args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,
) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError> {
let evm_env = self
.cfg_and_block_env(&args.config, &args.config.parent_header)
.evm_env(&args.config, &args.config.parent_header)
.map_err(PayloadBuilderError::other)?;

let pool = args.pool.clone();
Expand Down Expand Up @@ -140,7 +140,7 @@ where
);

let evm_env = self
.cfg_and_block_env(&args.config, &args.config.parent_header)
.evm_env(&args.config, &args.config.parent_header)
.map_err(PayloadBuilderError::other)?;

let pool = args.pool.clone();
Expand All @@ -167,7 +167,7 @@ pub fn default_ethereum_payload<EvmConfig, Pool, Client, F>(
evm_config: EvmConfig,
builder_config: EthereumBuilderConfig,
args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,
evm_env: EvmEnv,
evm_env: EvmEnv<EvmConfig::Spec>,
best_txs: F,
) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError>
where
Expand Down
47 changes: 19 additions & 28 deletions crates/evm/src/env.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use revm_primitives::{CfgEnv, SpecId};

/// Container type that holds both the configuration and block environment for EVM execution.
#[derive(Debug, Clone)]
pub struct EvmEnv {
#[derive(Debug, Clone, Default)]
pub struct EvmEnv<Spec = SpecId> {
/// The configuration environment with handler settings
pub cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg,
pub cfg_env: CfgEnv,
/// The block environment containing block-specific data
pub block_env: BlockEnv,
/// The spec id of the chain. Specifies which hardfork is currently active, `Spec` type will
/// most likely be an enum over hardforks.
pub spec: Spec,
}

impl Default for EvmEnv {
fn default() -> Self {
Self {
cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg {
cfg_env: Default::default(),
// Will set `is_optimism` if `revm/optimism-default-handler` is enabled.
handler_cfg: Default::default(),
},
block_env: BlockEnv::default(),
}
}
}

impl EvmEnv {
impl<Spec> EvmEnv<Spec> {
/// Create a new `EvmEnv` from its components.
///
/// # Arguments
///
/// * `cfg_env_with_handler_cfg` - The configuration environment with handler settings
/// * `block` - The block environment containing block-specific data
pub const fn new(cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg, block_env: BlockEnv) -> Self {
Self { cfg_env_with_handler_cfg, block_env }
pub const fn new(cfg_env: CfgEnv, block_env: BlockEnv, spec: Spec) -> Self {
Self { cfg_env, spec, block_env }
}

/// Returns a reference to the block environment.
Expand All @@ -39,19 +30,19 @@ impl EvmEnv {
}

/// Returns a reference to the configuration environment.
pub const fn cfg_env_with_handler_cfg(&self) -> &CfgEnvWithHandlerCfg {
&self.cfg_env_with_handler_cfg
pub const fn cfg_env(&self) -> &CfgEnv {
&self.cfg_env
}
}

impl From<(CfgEnvWithHandlerCfg, BlockEnv)> for EvmEnv {
fn from((cfg_env_with_handler_cfg, block_env): (CfgEnvWithHandlerCfg, BlockEnv)) -> Self {
Self { cfg_env_with_handler_cfg, block_env }
/// Returns the spec id of the chain
pub const fn spec_id(&self) -> &Spec {
&self.spec
}
}

impl From<EvmEnv> for (CfgEnvWithHandlerCfg, BlockEnv) {
fn from(env: EvmEnv) -> Self {
(env.cfg_env_with_handler_cfg, env.block_env)
impl From<(CfgEnvWithHandlerCfg, BlockEnv)> for EvmEnv {
fn from((cfg_env_with_handler_cfg, block_env): (CfgEnvWithHandlerCfg, BlockEnv)) -> Self {
let CfgEnvWithHandlerCfg { cfg_env, handler_cfg } = cfg_env_with_handler_cfg;
Self { cfg_env, spec: handler_cfg.spec_id, block_env }
}
}
Loading

0 comments on commit 203fed0

Please sign in to comment.