From aa7d9eb9ea830cbe308c88f05b6ec058a9592c54 Mon Sep 17 00:00:00 2001 From: refcell Date: Tue, 28 Jan 2025 14:41:27 -0500 Subject: [PATCH] fix(executor): refactor tx env stuffing --- crates/executor/src/syscalls/eip2935.rs | 82 +++-------------------- crates/executor/src/syscalls/eip4788.rs | 89 +++---------------------- crates/executor/src/syscalls/eip7002.rs | 82 +++-------------------- crates/executor/src/syscalls/eip7251.rs | 82 +++-------------------- crates/executor/src/syscalls/mod.rs | 3 + crates/executor/src/syscalls/tx_env.rs | 58 ++++++++++++++++ 6 files changed, 101 insertions(+), 295 deletions(-) create mode 100644 crates/executor/src/syscalls/tx_env.rs diff --git a/crates/executor/src/syscalls/eip2935.rs b/crates/executor/src/syscalls/eip2935.rs index ce9c025dc..290335d5b 100644 --- a/crates/executor/src/syscalls/eip2935.rs +++ b/crates/executor/src/syscalls/eip2935.rs @@ -5,18 +5,17 @@ use crate::{ db::TrieDB, errors::{ExecutorError, ExecutorResult}, + syscalls::fill_tx_env_for_contract_call, TrieDBProvider, }; -use alloc::{boxed::Box, vec::Vec}; -use alloy_primitives::{Address, Bytes, B256, U256}; +use alloc::boxed::Box; +use alloy_primitives::B256; use kona_mpt::TrieHinter; use maili_genesis::RollupConfig; use op_alloy_rpc_types_engine::OpPayloadAttributes; use revm::{ db::State, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv, - }, + primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg}, DatabaseCommit, Evm, }; @@ -90,7 +89,12 @@ where let previous_env = Box::new(evm.context.evm.env().clone()); // modify env for pre block call - fill_tx_env_with_block_hash_contract_call(&mut evm.context.evm.env, parent_block_hash); + fill_tx_env_for_contract_call( + &mut evm.context.evm.env, + alloy_eips::eip4788::SYSTEM_ADDRESS, + alloy_eips::eip2935::HISTORY_STORAGE_ADDRESS, + parent_block_hash.into(), + ); let mut state = match evm.transact() { Ok(res) => res.state, @@ -115,69 +119,3 @@ where Ok(()) } - -/// Fill transaction environment with the EIP-2935 system contract message data. -/// -/// This requirements for the beacon root contract call defined by -/// [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) are: -fn fill_tx_env_with_block_hash_contract_call(env: &mut Env, parent_block_hash: B256) { - fill_tx_env_with_system_contract_call( - env, - alloy_eips::eip4788::SYSTEM_ADDRESS, - alloy_eips::eip2935::HISTORY_STORAGE_ADDRESS, - parent_block_hash.into(), - ); -} - -/// Fill transaction environment with the system caller and the system contract address and message -/// data. -/// -/// This is a system operation and therefore: -/// * the call must execute to completion -/// * the call does not count against the block’s gas limit -/// * the call does not follow the EIP-1559 burn semantics - no value should be transferred as part -/// of the call -/// * if no code exists at the provided address, the call will fail silently -fn fill_tx_env_with_system_contract_call( - env: &mut Env, - caller: Address, - contract: Address, - data: Bytes, -) { - env.tx = TxEnv { - caller, - transact_to: TransactTo::Call(contract), - // Explicitly set nonce to None so revm does not do any nonce checks - nonce: None, - gas_limit: 30_000_000, - value: U256::ZERO, - data, - // Setting the gas price to zero enforces that no value is transferred as part of the call, - // and that the call will not count against the block's gas limit - gas_price: U256::ZERO, - // The chain ID check is not relevant here and is disabled if set to None - chain_id: None, - // Setting the gas priority fee to None ensures the effective gas price is derived from the - // `gas_price` field, which we need to be zero - gas_priority_fee: None, - access_list: Vec::new(), - authorization_list: None, - // blob fields can be None for this tx - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - optimism: OptimismFields { - source_hash: None, - mint: None, - is_system_transaction: Some(false), - // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the - // enveloped tx size. - enveloped_tx: Some(Bytes::default()), - }, - }; - - // ensure the block gas limit is >= the tx - env.block.gas_limit = U256::from(env.tx.gas_limit); - - // disable the base fee check for this call by setting the base fee to zero - env.block.basefee = U256::ZERO; -} diff --git a/crates/executor/src/syscalls/eip4788.rs b/crates/executor/src/syscalls/eip4788.rs index 43b90c1b3..8a9ffcd43 100644 --- a/crates/executor/src/syscalls/eip4788.rs +++ b/crates/executor/src/syscalls/eip4788.rs @@ -3,19 +3,17 @@ use crate::{ db::TrieDB, errors::{ExecutorError, ExecutorResult}, + syscalls::fill_tx_env_for_contract_call, TrieDBProvider, }; -use alloc::{boxed::Box, vec::Vec}; -use alloy_eips::eip4788::BEACON_ROOTS_ADDRESS; -use alloy_primitives::{Address, Bytes, B256, U256}; +use alloc::boxed::Box; +use alloy_primitives::B256; use kona_mpt::TrieHinter; use maili_genesis::RollupConfig; use op_alloy_rpc_types_engine::OpPayloadAttributes; use revm::{ db::State, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv, - }, + primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg}, DatabaseCommit, Evm, }; @@ -84,7 +82,12 @@ where let previous_env = Box::new(evm.context.evm.env().clone()); // modify env for pre block call - fill_tx_env_with_beacon_root_contract_call(&mut evm.context.evm.env, parent_beacon_block_root); + fill_tx_env_for_contract_call( + &mut evm.context.evm.env, + alloy_eips::eip4788::SYSTEM_ADDRESS, + alloy_eips::eip4788::BEACON_ROOTS_ADDRESS, + parent_beacon_block_root.0.into(), + ); let mut state = match evm.transact() { Ok(res) => res.state, @@ -104,75 +107,3 @@ where Ok(()) } - -/// Fill transaction environment with the EIP-4788 system contract message data. -/// -/// This requirements for the beacon root contract call defined by -/// [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) are: -/// -/// At the start of processing any execution block where `block.timestamp >= FORK_TIMESTAMP` (i.e. -/// before processing any transactions), call [`BEACON_ROOTS_ADDRESS`] as -/// [`SYSTEM_ADDRESS`](alloy_eips::eip4788::SYSTEM_ADDRESS) with the 32-byte input of -/// `header.parent_beacon_block_root`. This will trigger the `set()` routine of the beacon roots -/// contract. -fn fill_tx_env_with_beacon_root_contract_call(env: &mut Env, parent_beacon_block_root: B256) { - fill_tx_env_with_system_contract_call( - env, - alloy_eips::eip4788::SYSTEM_ADDRESS, - BEACON_ROOTS_ADDRESS, - parent_beacon_block_root.0.into(), - ); -} - -/// Fill transaction environment with the system caller and the system contract address and message -/// data. -/// -/// This is a system operation and therefore: -/// * the call must execute to completion -/// * the call does not count against the block’s gas limit -/// * the call does not follow the EIP-1559 burn semantics - no value should be transferred as part -/// of the call -/// * if no code exists at the provided address, the call will fail silently -fn fill_tx_env_with_system_contract_call( - env: &mut Env, - caller: Address, - contract: Address, - data: Bytes, -) { - env.tx = TxEnv { - caller, - transact_to: TransactTo::Call(contract), - // Explicitly set nonce to None so revm does not do any nonce checks - nonce: None, - gas_limit: 30_000_000, - value: U256::ZERO, - data, - // Setting the gas price to zero enforces that no value is transferred as part of the call, - // and that the call will not count against the block's gas limit - gas_price: U256::ZERO, - // The chain ID check is not relevant here and is disabled if set to None - chain_id: None, - // Setting the gas priority fee to None ensures the effective gas price is derived from the - // `gas_price` field, which we need to be zero - gas_priority_fee: None, - access_list: Vec::new(), - authorization_list: None, - // blob fields can be None for this tx - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - optimism: OptimismFields { - source_hash: None, - mint: None, - is_system_transaction: Some(false), - // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the - // enveloped tx size. - enveloped_tx: Some(Bytes::default()), - }, - }; - - // ensure the block gas limit is >= the tx - env.block.gas_limit = U256::from(env.tx.gas_limit); - - // disable the base fee check for this call by setting the base fee to zero - env.block.basefee = U256::ZERO; -} diff --git a/crates/executor/src/syscalls/eip7002.rs b/crates/executor/src/syscalls/eip7002.rs index 4892c9ed6..c75432502 100644 --- a/crates/executor/src/syscalls/eip7002.rs +++ b/crates/executor/src/syscalls/eip7002.rs @@ -3,18 +3,17 @@ use crate::{ db::TrieDB, errors::{ExecutorError, ExecutorResult}, + syscalls::fill_tx_env_for_contract_call, TrieDBProvider, }; -use alloc::{boxed::Box, vec::Vec}; -use alloy_primitives::{Address, Bytes, U256}; +use alloc::boxed::Box; +use alloy_primitives::Bytes; use kona_mpt::TrieHinter; use maili_genesis::RollupConfig; use op_alloy_rpc_types_engine::OpPayloadAttributes; use revm::{ db::State, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv, - }, + primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg}, DatabaseCommit, Evm, }; @@ -66,7 +65,12 @@ where let previous_env = Box::new(evm.context.evm.env().clone()); // modify env for pre block call - fill_tx_env_with_withdrawals_request_contract_call(&mut evm.context.evm.env); + fill_tx_env_for_contract_call( + &mut evm.context.evm.env, + alloy_eips::eip7002::SYSTEM_ADDRESS, + alloy_eips::eip7002::WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, + Bytes::new(), + ); let mut state = match evm.transact() { Ok(res) => res.state, @@ -86,69 +90,3 @@ where Ok(()) } - -/// Fill transaction environment with the EIP-7002 system contract message data. -/// -/// This requirements for the beacon root contract call are defined by -/// [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002). -fn fill_tx_env_with_withdrawals_request_contract_call(env: &mut Env) { - fill_tx_env_with_system_contract_call( - env, - alloy_eips::eip7002::SYSTEM_ADDRESS, - alloy_eips::eip7002::WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, - Bytes::new(), - ); -} - -/// Fill transaction environment with the system caller and the system contract address and message -/// data. -/// -/// This is a system operation and therefore: -/// * the call must execute to completion -/// * the call does not count against the block’s gas limit -/// * the call does not follow the EIP-1559 burn semantics - no value should be transferred as part -/// of the call -/// * if no code exists at the provided address, the call will fail silently -fn fill_tx_env_with_system_contract_call( - env: &mut Env, - caller: Address, - contract: Address, - data: Bytes, -) { - env.tx = TxEnv { - caller, - transact_to: TransactTo::Call(contract), - // Explicitly set nonce to None so revm does not do any nonce checks - nonce: None, - gas_limit: 30_000_000, - value: U256::ZERO, - data, - // Setting the gas price to zero enforces that no value is transferred as part of the call, - // and that the call will not count against the block's gas limit - gas_price: U256::ZERO, - // The chain ID check is not relevant here and is disabled if set to None - chain_id: None, - // Setting the gas priority fee to None ensures the effective gas price is derived from the - // `gas_price` field, which we need to be zero - gas_priority_fee: None, - access_list: Vec::new(), - authorization_list: None, - // blob fields can be None for this tx - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - optimism: OptimismFields { - source_hash: None, - mint: None, - is_system_transaction: Some(false), - // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the - // enveloped tx size. - enveloped_tx: Some(Bytes::default()), - }, - }; - - // ensure the block gas limit is >= the tx - env.block.gas_limit = U256::from(env.tx.gas_limit); - - // disable the base fee check for this call by setting the base fee to zero - env.block.basefee = U256::ZERO; -} diff --git a/crates/executor/src/syscalls/eip7251.rs b/crates/executor/src/syscalls/eip7251.rs index 8567e71f6..19041e00a 100644 --- a/crates/executor/src/syscalls/eip7251.rs +++ b/crates/executor/src/syscalls/eip7251.rs @@ -3,18 +3,17 @@ use crate::{ db::TrieDB, errors::{ExecutorError, ExecutorResult}, + syscalls::fill_tx_env_for_contract_call, TrieDBProvider, }; -use alloc::{boxed::Box, vec::Vec}; -use alloy_primitives::{Address, Bytes, U256}; +use alloc::boxed::Box; +use alloy_primitives::Bytes; use kona_mpt::TrieHinter; use maili_genesis::RollupConfig; use op_alloy_rpc_types_engine::OpPayloadAttributes; use revm::{ db::State, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv, - }, + primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg}, DatabaseCommit, Evm, }; @@ -65,7 +64,12 @@ where let previous_env = Box::new(evm.context.evm.env().clone()); // modify env for pre block call - fill_tx_env_with_consolidation_requests_contract_call(&mut evm.context.evm.env); + fill_tx_env_for_contract_call( + &mut evm.context.evm.env, + alloy_eips::eip7002::SYSTEM_ADDRESS, + alloy_eips::eip7251::CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, + Bytes::new(), + ); let mut state = match evm.transact() { Ok(res) => res.state, @@ -85,69 +89,3 @@ where Ok(()) } - -/// Fill transaction environment with the EIP-7251 system contract message data. -/// -/// This requirements for the beacon root contract call are defined by -/// [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251). -fn fill_tx_env_with_consolidation_requests_contract_call(env: &mut Env) { - fill_tx_env_with_system_contract_call( - env, - alloy_eips::eip7002::SYSTEM_ADDRESS, - alloy_eips::eip7251::CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, - Bytes::new(), - ); -} - -/// Fill transaction environment with the system caller and the system contract address and message -/// data. -/// -/// This is a system operation and therefore: -/// * the call must execute to completion -/// * the call does not count against the block’s gas limit -/// * the call does not follow the EIP-1559 burn semantics - no value should be transferred as part -/// of the call -/// * if no code exists at the provided address, the call will fail silently -fn fill_tx_env_with_system_contract_call( - env: &mut Env, - caller: Address, - contract: Address, - data: Bytes, -) { - env.tx = TxEnv { - caller, - transact_to: TransactTo::Call(contract), - // Explicitly set nonce to None so revm does not do any nonce checks - nonce: None, - gas_limit: 30_000_000, - value: U256::ZERO, - data, - // Setting the gas price to zero enforces that no value is transferred as part of the call, - // and that the call will not count against the block's gas limit - gas_price: U256::ZERO, - // The chain ID check is not relevant here and is disabled if set to None - chain_id: None, - // Setting the gas priority fee to None ensures the effective gas price is derived from the - // `gas_price` field, which we need to be zero - gas_priority_fee: None, - access_list: Vec::new(), - authorization_list: None, - // blob fields can be None for this tx - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - optimism: OptimismFields { - source_hash: None, - mint: None, - is_system_transaction: Some(false), - // The L1 fee is not charged for the EIP-7251 transaction, submit zero bytes for the - // enveloped tx size. - enveloped_tx: Some(Bytes::default()), - }, - }; - - // ensure the block gas limit is >= the tx - env.block.gas_limit = U256::from(env.tx.gas_limit); - - // disable the base fee check for this call by setting the base fee to zero - env.block.basefee = U256::ZERO; -} diff --git a/crates/executor/src/syscalls/mod.rs b/crates/executor/src/syscalls/mod.rs index ad27bea83..64163a2db 100644 --- a/crates/executor/src/syscalls/mod.rs +++ b/crates/executor/src/syscalls/mod.rs @@ -14,3 +14,6 @@ pub(crate) use eip4788::pre_block_beacon_root_contract_call; mod canyon; pub(crate) use canyon::ensure_create2_deployer_canyon; + +mod tx_env; +pub(crate) use tx_env::fill_tx_env_for_contract_call; diff --git a/crates/executor/src/syscalls/tx_env.rs b/crates/executor/src/syscalls/tx_env.rs new file mode 100644 index 000000000..71bae740a --- /dev/null +++ b/crates/executor/src/syscalls/tx_env.rs @@ -0,0 +1,58 @@ +//! Contains a helper function to fill the [`TxEnv`] for the given system call. + +use alloc::vec::Vec; +use alloy_primitives::{Address, Bytes, U256}; +use revm::primitives::{Env, OptimismFields, TransactTo, TxEnv}; + +/// Fill transaction environment with the system caller and the system +/// contract address and message data. +/// +/// This is a system operation and therefore: +/// * the call must execute to completion +/// * the call does not count against the block’s gas limit +/// * the call does not follow the EIP-1559 burn semantics - no value should be transferred as part +/// of the call +/// * if no code exists at the provided address, the call will fail silently +pub(crate) fn fill_tx_env_for_contract_call( + env: &mut Env, + caller: Address, + contract: Address, + data: Bytes, +) { + env.tx = TxEnv { + caller, + transact_to: TransactTo::Call(contract), + // Explicitly set nonce to None so revm does not do any nonce checks + nonce: None, + gas_limit: 30_000_000, + value: U256::ZERO, + data, + // Setting the gas price to zero enforces that no value is transferred as part of the call, + // and that the call will not count against the block's gas limit + gas_price: U256::ZERO, + // The chain ID check is not relevant here and is disabled if set to None + chain_id: None, + // Setting the gas priority fee to None ensures the effective gas price is derived from the + // `gas_price` field, which we need to be zero + gas_priority_fee: None, + access_list: Vec::new(), + authorization_list: None, + // blob fields can be None for this tx + blob_hashes: Vec::new(), + max_fee_per_blob_gas: None, + optimism: OptimismFields { + source_hash: None, + mint: None, + is_system_transaction: Some(false), + // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the + // enveloped tx size. + enveloped_tx: Some(Bytes::default()), + }, + }; + + // ensure the block gas limit is >= the tx + env.block.gas_limit = U256::from(env.tx.gas_limit); + + // disable the base fee check for this call by setting the base fee to zero + env.block.basefee = U256::ZERO; +}