diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index 8d79eed668..6700b6b890 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -87,7 +87,7 @@ impl From for InstructionResult { HaltReason::CallNotAllowedInsideStatic => Self::CallNotAllowedInsideStatic, HaltReason::OutOfFunds => Self::OutOfFunds, HaltReason::CallTooDeep => Self::CallTooDeep, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] HaltReason::FailedDeposit => Self::FatalExternalError, } } diff --git a/crates/interpreter/src/instructions/opcode.rs b/crates/interpreter/src/instructions/opcode.rs index 116353803c..75e319badd 100644 --- a/crates/interpreter/src/instructions/opcode.rs +++ b/crates/interpreter/src/instructions/opcode.rs @@ -857,21 +857,26 @@ pub const fn spec_opcode_gas(spec_id: SpecId) -> &'static [OpInfo; 256] { TABLE } )* - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] SpecId::BEDROCK => { const TABLE: &[OpInfo;256] = &make_gas_table(SpecId::BEDROCK); TABLE } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] SpecId::REGOLITH => { const TABLE: &[OpInfo;256] = &make_gas_table(SpecId::REGOLITH); TABLE } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] SpecId::CANYON => { const TABLE: &[OpInfo;256] = &make_gas_table(SpecId::CANYON); TABLE } + #[cfg(all(feature = "taiko", not(feature = "optimism")))] + SpecId::KATLA => { + const TABLE: &[OpInfo;256] = &make_gas_table(SpecId::KATLA); + TABLE + } } }; } diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 6addef49e2..6bfbf3805c 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -256,8 +256,10 @@ impl PrecompileSpecId { BERLIN | LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE | SHANGHAI => Self::BERLIN, CANCUN => Self::CANCUN, LATEST => Self::LATEST, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] BEDROCK | REGOLITH | CANYON => Self::BERLIN, + #[cfg(all(feature = "taiko", not(feature = "optimism")))] + KATLA => Self::BERLIN, // TODO(Cecilia): what is this? } } } diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 3fcb04ce2b..fc668cf314 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -79,7 +79,7 @@ impl Env { /// Return initial spend gas (Gas needed to execute transaction). #[inline] pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] if self.cfg.optimism { // Do not allow for a system transaction to be processed if Regolith is enabled. if self.tx.optimism.is_system_transaction.unwrap_or(false) @@ -206,7 +206,7 @@ impl Env { // On Optimism, deposit transactions do not have verification on the nonce // nor the balance of the account. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] if self.cfg.optimism && self.tx.optimism.source_hash.is_some() { return Ok(()); } @@ -316,8 +316,10 @@ pub struct CfgEnv { /// allowing for features like multichain fork testing. Setting this field /// to false will disable all optimism execution changes regardless of /// compilation with the optimism feature flag. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] pub optimism: bool, + + #[cfg(all(feature = "taiko", not(feature = "optimism")))] pub taiko: bool, } impl CfgEnv { @@ -381,14 +383,13 @@ impl CfgEnv { false } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] pub fn is_optimism(&self) -> bool { self.optimism } - #[cfg(not(feature = "optimism"))] - pub fn is_optimism(&self) -> bool { - false + #[cfg(all(feature = "taiko", not(feature = "optimism")))] pub fn is_taiko(&self) -> bool { + self.taiko } } @@ -414,8 +415,10 @@ impl Default for CfgEnv { disable_base_fee: false, #[cfg(feature = "optional_beneficiary_reward")] disable_beneficiary_reward: false, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] optimism: false, + #[cfg(all(feature = "taiko", not(feature = "optimism")))] + taiko: false, } } } @@ -466,7 +469,7 @@ pub struct BlockEnv { /// Incorporated as part of the Cancun upgrade via [EIP-4844]. /// /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlobExcessGasAndPrice { pub excess_blob_gas: u64, @@ -484,8 +487,8 @@ impl BlobExcessGasAndPrice { } } -#[cfg(feature = "optimism")] -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct OptimismFields { pub source_hash: Option, @@ -501,7 +504,8 @@ pub struct OptimismFields { pub enveloped_tx: Option, } -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg(all(feature = "taiko", not(feature = "optimism")))] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TaikoFields { pub treasury: Address, @@ -617,12 +621,11 @@ pub struct TxEnv { pub max_fee_per_blob_gas: Option, #[cfg_attr(feature = "serde", serde(flatten))] - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] pub optimism: OptimismFields, #[cfg_attr(feature = "serde", serde(flatten))] - #[cfg(feature = "taiko")] - pub taiko: TaikoFields, + #[cfg(all(feature = "taiko", not(feature = "optimism")))] pub taiko: TaikoFields, } impl TxEnv { @@ -656,71 +659,14 @@ impl Default for TxEnv { access_list: Vec::new(), blob_hashes: Vec::new(), max_fee_per_blob_gas: None, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] optimism: OptimismFields::default(), + #[cfg(all(feature = "taiko", not(feature = "optimism")))] + taiko: TaikoFields::default(), } } } -/// Structure holding block blob excess gas and it calculates blob fee. -/// -/// Incorporated as part of the Cancun upgrade via [EIP-4844]. -/// -/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct BlobExcessGasAndPrice { - /// The excess blob gas of the block. - pub excess_blob_gas: u64, - /// The calculated blob gas price based on the `excess_blob_gas`, See [calc_blob_gasprice] - pub blob_gasprice: u128, -} - -impl BlobExcessGasAndPrice { - /// Creates a new instance by calculating the blob gas price with [`calc_blob_gasprice`]. - pub fn new(excess_blob_gas: u64) -> Self { - let blob_gasprice = calc_blob_gasprice(excess_blob_gas); - Self { - excess_blob_gas, - blob_gasprice, - } - } -} - -/// Additional [TxEnv] fields for optimism. -#[cfg(feature = "optimism")] -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct OptimismFields { - /// The source hash is used to make sure that deposit transactions do - /// not have identical hashes. - /// - /// L1 originated deposit transaction source hashes are computed using - /// the hash of the l1 block hash and the l1 log index. - /// L1 attributes deposit source hashes are computed with the l1 block - /// hash and the sequence number = l2 block number - l2 epoch start - /// block number. - /// - /// These two deposit transaction sources specify a domain in the outer - /// hash so there are no collisions. - pub source_hash: Option, - /// The amount to increase the balance of the `from` account as part of - /// a deposit transaction. This is unconditional and is applied to the - /// `from` account even if the deposit transaction fails since - /// the deposit is pre-paid on L1. - pub mint: Option, - /// Whether or not the transaction is a system transaction. - pub is_system_transaction: Option, - /// An enveloped EIP-2718 typed transaction. This is used - /// to compute the L1 tx cost using the L1 block info, as - /// opposed to requiring downstream apps to compute the cost - /// externally. - /// This field is optional to allow the [TxEnv] to be constructed - /// for non-optimism chains when the `optimism` feature is enabled, - /// but the [CfgEnv] `optimism` field is set to false. - pub enveloped_tx: Option, -} - /// Transaction destination. #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -776,139 +722,6 @@ pub enum CreateScheme { }, } -/// EVM configuration. -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[non_exhaustive] -pub struct CfgEnv { - pub chain_id: u64, - pub spec_id: SpecId, - /// KZG Settings for point evaluation precompile. By default, this is loaded from the ethereum mainnet trusted setup. - #[cfg(feature = "c-kzg")] - #[cfg_attr(feature = "serde", serde(skip))] - pub kzg_settings: crate::kzg::EnvKzgSettings, - /// Bytecode that is created with CREATE/CREATE2 is by default analysed and jumptable is created. - /// This is very beneficial for testing and speeds up execution of that bytecode if called multiple times. - /// - /// Default: Analyse - pub perf_analyse_created_bytecodes: AnalysisKind, - /// If some it will effects EIP-170: Contract code size limit. Useful to increase this because of tests. - /// By default it is 0x6000 (~25kb). - pub limit_contract_code_size: Option, - /// A hard memory limit in bytes beyond which [Memory] cannot be resized. - /// - /// In cases where the gas limit may be extraordinarily high, it is recommended to set this to - /// a sane value to prevent memory allocation panics. Defaults to `2^32 - 1` bytes per - /// EIP-1985. - #[cfg(feature = "memory_limit")] - pub memory_limit: u64, - /// Skip balance checks if true. Adds transaction cost to balance to ensure execution doesn't fail. - #[cfg(feature = "optional_balance_check")] - pub disable_balance_check: bool, - /// There are use cases where it's allowed to provide a gas limit that's higher than a block's gas limit. To that - /// end, you can disable the block gas limit validation. - /// By default, it is set to `false`. - #[cfg(feature = "optional_block_gas_limit")] - pub disable_block_gas_limit: bool, - /// EIP-3607 rejects transactions from senders with deployed code. In development, it can be desirable to simulate - /// calls from contracts, which this setting allows. - /// By default, it is set to `false`. - #[cfg(feature = "optional_eip3607")] - pub disable_eip3607: bool, - /// Disables all gas refunds. This is useful when using chains that have gas refunds disabled e.g. Avalanche. - /// Reasoning behind removing gas refunds can be found in EIP-3298. - /// By default, it is set to `false`. - #[cfg(feature = "optional_gas_refund")] - pub disable_gas_refund: bool, - /// Disables base fee checks for EIP-1559 transactions. - /// This is useful for testing method calls with zero gas price. - #[cfg(feature = "optional_no_base_fee")] - pub disable_base_fee: bool, - /// Enables Optimism's execution changes for deposit transactions and fee - /// collection. Hot toggling the optimism field gives applications built - /// on revm the ability to switch optimism execution on and off at runtime, - /// allowing for features like multichain fork testing. Setting this field - /// to false will disable all optimism execution changes regardless of - /// compilation with the optimism feature flag. - #[cfg(feature = "optimism")] - pub optimism: bool, - - #[cfg(feature = "taiko")] - pub taiko: bool, -} - -impl CfgEnv { - #[cfg(feature = "optional_eip3607")] - pub fn is_eip3607_disabled(&self) -> bool { - self.disable_eip3607 - } - - #[cfg(not(feature = "optional_eip3607"))] - pub fn is_eip3607_disabled(&self) -> bool { - false - } - - #[cfg(feature = "optional_balance_check")] - pub fn is_balance_check_disabled(&self) -> bool { - self.disable_balance_check - } - - #[cfg(not(feature = "optional_balance_check"))] - pub fn is_balance_check_disabled(&self) -> bool { - false - } - - #[cfg(feature = "optional_gas_refund")] - pub fn is_gas_refund_disabled(&self) -> bool { - self.disable_gas_refund - } - - #[cfg(not(feature = "optional_gas_refund"))] - pub fn is_gas_refund_disabled(&self) -> bool { - false - } - - #[cfg(feature = "optional_no_base_fee")] - pub fn is_base_fee_check_disabled(&self) -> bool { - self.disable_base_fee - } - - #[cfg(not(feature = "optional_no_base_fee"))] - pub fn is_base_fee_check_disabled(&self) -> bool { - false - } - - #[cfg(feature = "optional_block_gas_limit")] - pub fn is_block_gas_limit_disabled(&self) -> bool { - self.disable_block_gas_limit - } - - #[cfg(not(feature = "optional_block_gas_limit"))] - pub fn is_block_gas_limit_disabled(&self) -> bool { - false - } - - #[cfg(feature = "optimism")] - pub fn is_optimism(&self) -> bool { - self.optimism - } - - #[cfg(not(feature = "optimism"))] - pub fn is_optimism(&self) -> bool { - false - } - - #[cfg(feature = "taiko")] - pub fn is_taiko(&self) -> bool { - self.taiko - } - - #[cfg(not(feature = "taiko"))] - pub fn is_taiko(&self) -> bool { - false - } -} - /// What bytecode analysis to perform. #[derive(Clone, Default, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -922,308 +735,11 @@ pub enum AnalysisKind { Analyse, } -impl Default for CfgEnv { - fn default() -> Self { - Self { - chain_id: 1, - spec_id: SpecId::LATEST, - perf_analyse_created_bytecodes: AnalysisKind::default(), - limit_contract_code_size: None, - #[cfg(feature = "c-kzg")] - kzg_settings: crate::kzg::EnvKzgSettings::Default, - #[cfg(feature = "memory_limit")] - memory_limit: (1 << 32) - 1, - #[cfg(feature = "optional_balance_check")] - disable_balance_check: false, - #[cfg(feature = "optional_block_gas_limit")] - disable_block_gas_limit: false, - #[cfg(feature = "optional_eip3607")] - disable_eip3607: false, - #[cfg(feature = "optional_gas_refund")] - disable_gas_refund: false, - #[cfg(feature = "optional_no_base_fee")] - disable_base_fee: false, - #[cfg(feature = "optimism")] - optimism: false, - #[cfg(feature = "taiko")] - taiko: false, - } - } -} - -impl Default for BlockEnv { - fn default() -> Self { - Self { - number: U256::ZERO, - coinbase: Address::ZERO, - timestamp: U256::from(1), - gas_limit: U256::MAX, - basefee: U256::ZERO, - difficulty: U256::ZERO, - prevrandao: Some(B256::ZERO), - blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new(0)), - } - } -} - -impl Default for TxEnv { - fn default() -> Self { - Self { - caller: Address::ZERO, - gas_limit: u64::MAX, - gas_price: U256::ZERO, - gas_priority_fee: None, - transact_to: TransactTo::Call(Address::ZERO), // will do nothing - value: U256::ZERO, - data: Bytes::new(), - chain_id: None, - nonce: None, - access_list: Vec::new(), - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - #[cfg(feature = "optimism")] - optimism: OptimismFields::default(), - #[cfg(feature = "taiko")] - taiko: TaikoFields::default(), - } - } -} - -impl Env { - /// Calculates the effective gas price of the transaction. - #[inline] - pub fn effective_gas_price(&self) -> U256 { - if let Some(priority_fee) = self.tx.gas_priority_fee { - min(self.tx.gas_price, self.block.basefee + priority_fee) - } else { - self.tx.gas_price - } - } - - /// Calculates the [EIP-4844] `data_fee` of the transaction. - /// - /// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 - #[inline] - pub fn calc_data_fee(&self) -> Option { - self.block.get_blob_gasprice().map(|blob_gas_price| { - U256::from(blob_gas_price).saturating_mul(U256::from(self.tx.get_total_blob_gas())) - }) - } - - /// Validate the block environment. - #[inline] - pub fn validate_block_env(&self) -> Result<(), InvalidHeader> { - // `prevrandao` is required for the merge - if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao.is_none() { - return Err(InvalidHeader::PrevrandaoNotSet); - } - // `excess_blob_gas` is required for Cancun - if SPEC::enabled(SpecId::CANCUN) && self.block.blob_excess_gas_and_price.is_none() { - return Err(InvalidHeader::ExcessBlobGasNotSet); - } - Ok(()) - } - - /// Validate transaction data that is set inside ENV and return error if something is wrong. - /// - /// Return initial spend gas (Gas needed to execute transaction). - #[inline] - pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { - #[cfg(feature = "optimism")] - if self.cfg.optimism { - // Do not allow for a system transaction to be processed if Regolith is enabled. - if self.tx.optimism.is_system_transaction.unwrap_or(false) - && SPEC::enabled(SpecId::REGOLITH) - { - return Err(InvalidTransaction::DepositSystemTxPostRegolith); - } - - // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. - if self.tx.optimism.source_hash.is_some() { - return Ok(()); - } - } - - #[cfg(feature = "taiko")] - if self.cfg.taiko { - // TODO:(Cecilia) - } - - let gas_limit = self.tx.gas_limit; - let effective_gas_price = self.effective_gas_price(); - let is_create = self.tx.transact_to.is_create(); - - // BASEFEE tx check - if SPEC::enabled(SpecId::LONDON) { - if let Some(priority_fee) = self.tx.gas_priority_fee { - if priority_fee > self.tx.gas_price { - // or gas_max_fee for eip1559 - return Err(InvalidTransaction::PriorityFeeGreaterThanMaxFee); - } - } - let basefee = self.block.basefee; - - // check minimal cost against basefee - if !self.cfg.is_base_fee_check_disabled() && effective_gas_price < basefee { - return Err(InvalidTransaction::GasPriceLessThanBasefee); - } - } - - // Check if gas_limit is more than block_gas_limit - if !self.cfg.is_block_gas_limit_disabled() && U256::from(gas_limit) > self.block.gas_limit { - return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); - } - - // EIP-3860: Limit and meter initcode - if SPEC::enabled(SpecId::SHANGHAI) && is_create { - let max_initcode_size = self - .cfg - .limit_contract_code_size - .map(|limit| limit.saturating_mul(2)) - .unwrap_or(MAX_INITCODE_SIZE); - if self.tx.data.len() > max_initcode_size { - return Err(InvalidTransaction::CreateInitcodeSizeLimit); - } - } - - // Check if the transaction's chain id is correct - if let Some(tx_chain_id) = self.tx.chain_id { - if tx_chain_id != self.cfg.chain_id { - return Err(InvalidTransaction::InvalidChainId); - } - } - - // Check that access list is empty for transactions before BERLIN - if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list.is_empty() { - return Err(InvalidTransaction::AccessListNotSupported); - } - - // - For CANCUN and later, check that the gas price is not more than the tx max - // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set - if SPEC::enabled(SpecId::CANCUN) { - // Presence of max_fee_per_blob_gas means that this is blob transaction. - if let Some(max) = self.tx.max_fee_per_blob_gas { - // ensure that the user was willing to at least pay the current blob gasprice - let price = self.block.get_blob_gasprice().expect("already checked"); - if U256::from(price) > max { - return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); - } - - // there must be at least one blob - // assert len(tx.blob_versioned_hashes) > 0 - if self.tx.blob_hashes.is_empty() { - return Err(InvalidTransaction::EmptyBlobs); - } - - // The field `to` deviates slightly from the semantics with the exception - // that it MUST NOT be nil and therefore must always represent - // a 20-byte address. This means that blob transactions cannot - // have the form of a create transaction. - if self.tx.transact_to.is_create() { - return Err(InvalidTransaction::BlobCreateTransaction); - } - - // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG - for blob in self.tx.blob_hashes.iter() { - if blob[0] != VERSIONED_HASH_VERSION_KZG { - return Err(InvalidTransaction::BlobVersionNotSupported); - } - } - - // ensure the total blob gas spent is at most equal to the limit - // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK - if self.tx.blob_hashes.len() > MAX_BLOB_NUMBER_PER_BLOCK as usize { - return Err(InvalidTransaction::TooManyBlobs); - } - } - } else { - if !self.tx.blob_hashes.is_empty() { - return Err(InvalidTransaction::BlobVersionedHashesNotSupported); - } - if self.tx.max_fee_per_blob_gas.is_some() { - return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); - } - } - - Ok(()) - } - - /// Validate transaction against state. - #[inline] - pub fn validate_tx_against_state( - &self, - account: &mut Account, - ) -> Result<(), InvalidTransaction> { - // EIP-3607: Reject transactions from senders with deployed code - // This EIP is introduced after london but there was no collision in past - // so we can leave it enabled always - if !self.cfg.is_eip3607_disabled() && account.info.code_hash != KECCAK_EMPTY { - return Err(InvalidTransaction::RejectCallerWithCode); - } - - // On Optimism, deposit transactions do not have verification on the nonce - // nor the balance of the account. - #[cfg(feature = "optimism")] - if self.cfg.optimism && self.tx.optimism.source_hash.is_some() { - return Ok(()); - } - - // Check that the transaction's nonce is correct - if let Some(tx) = self.tx.nonce { - let state = account.info.nonce; - match tx.cmp(&state) { - Ordering::Greater => { - return Err(InvalidTransaction::NonceTooHigh { tx, state }); - } - Ordering::Less => { - return Err(InvalidTransaction::NonceTooLow { tx, state }); - } - _ => {} - } - } - - let mut balance_check = U256::from(self.tx.gas_limit) - .checked_mul(self.tx.gas_price) - .and_then(|gas_cost| gas_cost.checked_add(self.tx.value)) - .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; - - if SpecId::enabled(self.cfg.spec_id, SpecId::CANCUN) { - let data_fee = self.calc_data_fee().expect("already checked"); - balance_check = balance_check - .checked_add(U256::from(data_fee)) - .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; - } - - #[cfg(feature = "taiko")] - if self.cfg.taiko && self.tx.taiko.is_anchor { - return Ok(()); - } - - // Check if account has enough balance for gas_limit*gas_price and value transfer. - // Transfer will be done inside `*_inner` functions. - if balance_check > account.info.balance { - if self.cfg.is_balance_check_disabled() { - // Add transaction cost to balance to ensure execution doesn't fail. - account.info.balance = balance_check; - } else { - return Err(InvalidTransaction::LackOfFundForMaxFee { - fee: self.tx.gas_limit, - balance: account.info.balance, - }); - } - } - - Ok(()) - } -} - #[cfg(test)] mod tests { use super::*; - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] #[test] fn test_validate_sys_tx() { // Set the optimism flag to true and mark @@ -1240,7 +756,7 @@ mod tests { assert!(env.validate_tx::().is_ok()); } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] #[test] fn test_validate_deposit_tx() { // Set the optimism flag and source hash. @@ -1250,7 +766,7 @@ mod tests { assert!(env.validate_tx::().is_ok()); } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] #[test] fn test_validate_tx_against_state_deposit_tx() { // Set the optimism flag and source hash. @@ -1266,8 +782,7 @@ mod tests { .is_ok()); } - #[cfg(feature = "taiko")] - #[test] + #[cfg(all(feature = "taiko", not(feature = "optimism")))] #[test] fn test_taiko() { // TODO(Cecilia): taiko tests } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index f2cb525bea..f2a6c049cc 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -19,8 +19,6 @@ pub mod precompile; pub mod result; pub mod specification; pub mod state; -#[cfg(feature = "taiko")] -pub mod taiko; pub mod utilities; pub use alloy_primitives::{ diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 5b00616386..4509393fcc 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -235,7 +235,7 @@ pub enum InvalidTransaction { /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this /// case for failed deposit transactions. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] DepositSystemTxPostRegolith, /// Deposit transaction haults bubble up to the global main return handler, wiping state and /// only increasing the nonce + persisting the mint value. @@ -251,12 +251,11 @@ pub enum InvalidTransaction { /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this /// case for failed deposit transactions. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] HaltedDepositPostRegolith, /// Anchor check failed - #[cfg(feature = "taiko")] - InvalidAnchorTransaction, + #[cfg(all(feature = "taiko", not(feature = "optimism")))] InvalidAnchorTransaction, } #[cfg(feature = "std")] @@ -315,20 +314,27 @@ impl fmt::Display for InvalidTransaction { InvalidTransaction::BlobCreateTransaction => write!(f, "Blob create transaction"), InvalidTransaction::TooManyBlobs => write!(f, "Too many blobs"), InvalidTransaction::BlobVersionNotSupported => write!(f, "Blob version not supported"), - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] InvalidTransaction::DepositSystemTxPostRegolith => { write!( f, "Deposit system transactions post regolith hardfork are not supported" ) } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] InvalidTransaction::HaltedDepositPostRegolith => { write!( f, "Deposit transaction halted post-regolith. Error will be bubbled up to main return handler." ) } + #[cfg(all(feature = "taiko", not(feature = "optimism")))] + InvalidTransaction::InvalidAnchorTransaction => { + write!( + f, + "Invalid Anchor transaction." + ) + } } } } @@ -401,7 +407,7 @@ pub enum HaltReason { CallTooDeep, /* Optimism errors */ - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] FailedDeposit, } diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index 2e8ab380e6..680ff6e84e 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -1,11 +1,10 @@ #![allow(non_camel_case_types)] - pub use SpecId::*; /// Specification IDs and their activation block. /// /// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(not(feature = "optimism"), not(feature = "taiko"))] +#[cfg(all(not(feature = "optimism"), not(feature = "taiko")))] #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, enumn::N)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -34,7 +33,7 @@ pub enum SpecId { /// Specification IDs and their activation block. /// /// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, enumn::N)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -66,8 +65,7 @@ pub enum SpecId { /// Specification IDs and their activation block. /// /// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(feature = "taiko")] -#[repr(u8)] +#[cfg(all(feature = "taiko", not(feature = "optimism")))]#[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, enumn::N)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum SpecId { @@ -126,14 +124,13 @@ impl From<&str> for SpecId { "Merge" => Self::MERGE, "Shanghai" => Self::SHANGHAI, "Cancun" => Self::CANCUN, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] "Bedrock" => SpecId::BEDROCK, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] "Regolith" => SpecId::REGOLITH, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] "Canyon" => SpecId::CANYON, - #[cfg(feature = "taiko")] - "Katla" => SpecId::KATLA, + #[cfg(all(feature = "taiko", not(feature = "optimism")))] "Katla" => SpecId::KATLA, _ => Self::LATEST, } } @@ -183,16 +180,15 @@ spec!(CANCUN, CancunSpec); spec!(LATEST, LatestSpec); // Optimism Hardforks -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] spec!(BEDROCK, BedrockSpec); -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] spec!(REGOLITH, RegolithSpec); // Taiko Hardforks -#[cfg(feature = "taiko")] -spec!(KATLA, KatlaSpec); +#[cfg(all(feature = "taiko", not(feature = "optimism")))]spec!(KATLA, KatlaSpec); -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] spec!(CANYON, CanyonSpec); #[macro_export] @@ -254,17 +250,17 @@ macro_rules! spec_to_generic { use $crate::LatestSpec as SPEC; $e } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] $crate::SpecId::BEDROCK => { use $crate::BedrockSpec as SPEC; $e } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] $crate::SpecId::REGOLITH => { use $crate::RegolithSpec as SPEC; $e } - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] $crate::SpecId::CANYON => { use $crate::CanyonSpec as SPEC; $e @@ -297,19 +293,19 @@ mod tests { spec_to_generic!(ARROW_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); spec_to_generic!(GRAY_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); spec_to_generic!(MERGE, assert_eq!(SPEC::SPEC_ID, MERGE)); - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] spec_to_generic!(BEDROCK, assert_eq!(SPEC::SPEC_ID, BEDROCK)); - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] spec_to_generic!(REGOLITH, assert_eq!(SPEC::SPEC_ID, REGOLITH)); spec_to_generic!(SHANGHAI, assert_eq!(SPEC::SPEC_ID, SHANGHAI)); - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] spec_to_generic!(CANYON, assert_eq!(SPEC::SPEC_ID, CANYON)); spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN)); spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); } } -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] #[cfg(test)] mod optimism_tests { use super::*; @@ -377,8 +373,7 @@ mod optimism_tests { } } -#[cfg(feature = "taiko")] -#[cfg(test)] +#[cfg(all(feature = "taiko", not(feature = "optimism")))]#[cfg(test)] mod tests { use super::*; diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index b0c07472c7..7b7fbc7101 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -58,7 +58,7 @@ pub struct EvmContext { /// Precompiles that are available for evm. pub precompiles: Precompiles, /// Used as temporary value holder to store L1 block info. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] pub l1_block_info: Option, } @@ -70,7 +70,7 @@ impl EvmContext { db, error: None, precompiles: self.precompiles, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] l1_block_info: self.l1_block_info, } } @@ -81,7 +81,7 @@ impl EvmContext { db, error: None, precompiles: Precompiles::default(), - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] l1_block_info: None, } } @@ -94,7 +94,7 @@ impl EvmContext { db, error: None, precompiles: Precompiles::default(), - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] l1_block_info: None, } } @@ -572,7 +572,7 @@ pub(crate) mod test_utils { db, error: None, precompiles: Precompiles::default(), - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] l1_block_info: None, } } @@ -585,7 +585,7 @@ pub(crate) mod test_utils { db, error: None, precompiles: Precompiles::default(), - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] l1_block_info: None, } } diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 041b0e8fab..103ea0579f 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -18,11 +18,10 @@ use revm_interpreter::gas::initial_tx_gas; use revm_interpreter::MAX_CODE_SIZE; use revm_precompile::{Precompile, Precompiles}; -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] use crate::optimism; -#[cfg(feature = "taiko")] -use crate::taiko; +#[cfg(all(feature = "taiko", not(feature = "optimism")))]use crate::taiko; pub struct EVMData<'a, DB: Database> { pub env: &'a mut Env, @@ -31,10 +30,11 @@ pub struct EVMData<'a, DB: Database> { pub error: Option, pub precompiles: Precompiles, /// Used as temporary value holder to store L1 block info. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] pub l1_block_info: Option, } + pub struct EVMImpl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> { data: EVMData<'a, DB>, inspector: &'a mut dyn Inspector, @@ -98,7 +98,7 @@ impl<'a, DB: Database> EVMData<'a, DB> { } } -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, INSPECT> { /// If the transaction is not a deposit transaction, subtract the L1 data fee from the /// caller's balance directly after minting the requested amount of ETH. @@ -196,10 +196,9 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact let tx_value = env.tx.value; let tx_data = env.tx.data.clone(); let tx_gas_limit = env.tx.gas_limit; - #[cfg(feature = "taiko")] - let is_anchor = env.tx.taiko.is_anchor; + #[cfg(all(feature = "taiko", not(feature = "optimism")))] let is_anchor = env.tx.taiko.is_anchor; - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] let tx_l1_cost = { let is_deposit = env.tx.optimism.source_hash.is_some(); @@ -249,7 +248,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact // load acc let journal = &mut self.data.journaled_state; - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] if self.data.env.cfg.optimism { EVMImpl::::commit_mint_value( tx_caller, @@ -283,8 +282,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact gas_cost = gas_cost.saturating_add(data_fee); } - #[cfg(feature = "taiko")] - if !is_anchor { + #[cfg(all(feature = "taiko", not(feature = "optimism")))] if !is_anchor { caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost); } @@ -374,7 +372,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact // Post-regolith, if the transaction is a deposit transaction and the // output is a contract creation, increment the account nonce even if // the transaction halts. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] { let is_deposit = self.data.env.tx.optimism.source_hash.is_some(); let is_creation = matches!(output, Output::Create(_, _)); @@ -415,14 +413,13 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, ) -> Self { let journaled_state = JournaledState::new(precompiles.len(), GSPEC::SPEC_ID); - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] let handler: Handler = if env.cfg.optimism { Handler::optimism::() } else { Handler::mainnet::() }; - #[cfg(feature = "taiko")] - let handler = Handler::taiko::(); + #[cfg(all(feature = "taiko", not(feature = "optimism")))] let handler = Handler::taiko::(); #[cfg(not(any(feature = "optimism", feature = "taiko")))] let handler = Handler::mainnet::(); @@ -433,7 +430,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, db, error: None, precompiles, - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] l1_block_info: None, }, inspector, @@ -1021,7 +1018,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } } -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] #[cfg(test)] mod tests { use super::*; diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 117562d32c..29fa20c8c8 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -52,16 +52,16 @@ impl<'a, H: Host, EXT: 'a, DB: Database + 'a> Handler<'a, H, EXT, DB> { } /// Handler for the taiko - #[cfg(feature = "taiko")] - pub fn taiko() -> Self { - use crate::taiko::handler; - Self { - call_return: mainnet::handle_call_return::, - calculate_gas_refund: mainnet::calculate_gas_refund::, - reimburse_caller: handler::handle_reimburse_caller::, - reward_beneficiary: handler::reward_beneficiary::, - } - } + // #[cfg(all(feature = "taiko", not(feature = "optimism")))] + // pub fn taiko() -> Self { + // use crate::taiko::handler; + // Self { + // call_return: mainnet::handle_call_return::, + // calculate_gas_refund: mainnet::calculate_gas_refund::, + // reimburse_caller: handler::handle_reimburse_caller::, + // reward_beneficiary: handler::reward_beneficiary::, + // } + // } /// Creates handler with variable spec id, inside it will call `mainnet::` for /// appropriate spec. diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 84bd2952f8..ca89104230 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -28,7 +28,7 @@ pub fn load( context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); // the L1-cost fee is only computed for Optimism non-deposit transactions. - #[cfg(feature = "optimism")] + #[cfg(all(feature = "optimism", not(feature = "taiko")))] if context.evm.env.cfg.optimism && context.evm.env.tx.optimism.source_hash.is_none() { let l1_block_info = crate::optimism::L1BlockInfo::try_fetch(&mut context.evm.db) .map_err(EVMError::Database)?; diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 7a060aae75..ac71a6ca07 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -23,10 +23,9 @@ mod frame; pub mod handler; mod inspector; mod journaled_state; -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] pub mod optimism; -#[cfg(feature = "taiko")] -pub mod taiko; +#[cfg(all(feature = "taiko", not(feature = "optimism")))]pub mod taiko; // Export items. @@ -45,7 +44,7 @@ pub use inspector::{ }; pub use journaled_state::{JournalCheckpoint, JournalEntry, JournaledState}; // export Optimism types, helpers, and constants -#[cfg(feature = "optimism")] +#[cfg(all(feature = "optimism", not(feature = "taiko")))] pub use optimism::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; // Reexport libraries