From ef4b1a577d2c28b0edb966c408a06f0f150f3448 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 20 Sep 2023 00:44:39 +0200 Subject: [PATCH] style: change type and impl order --- crates/primitives/src/env.rs | 680 ++++++++++++++++++----------------- 1 file changed, 342 insertions(+), 338 deletions(-) diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 71096b1b98..2f607b549b 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -5,185 +5,177 @@ use crate::{ use bytes::Bytes; use core::cmp::{min, Ordering}; +/// EVM environment configuration. #[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Env { + /// Configuration of the EVM itself. pub cfg: CfgEnv, + /// Configuration of the block the transaction is in. pub block: BlockEnv, + /// Configuration of the transaction that is being executed. pub tx: TxEnv, } -/// The block environment. -#[derive(Clone, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct BlockEnv { - /// The number of ancestor blocks of this block (block height). - pub number: U256, - /// Coinbase or miner or address that created and signed the block. - /// - /// This is the receiver address of all the gas spent in the block. - pub coinbase: B160, - /// The timestamp of the block in seconds since the UNIX epoch. - pub timestamp: U256, - /// The gas limit of the block. - pub gas_limit: U256, - - /// The base fee per gas, added in the London upgrade with [EIP-1559]. - /// - /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 - pub basefee: U256, - - /// The difficulty of the block. - /// - /// Unused after the Paris (AKA the merge) upgrade, and replaced by `prevrandao`. - pub difficulty: U256, - /// The output of the randomness beacon provided by the beacon chain. - /// - /// Replaces `difficulty` after the Paris (AKA the merge) upgrade with [EIP-4399]. - /// - /// NOTE: `prevrandao` can be found in a block in place of `mix_hash`. - /// - /// [EIP-4399]: https://eips.ethereum.org/EIPS/eip-4399 - pub prevrandao: Option, - - /// Excess blob gas. See also [`calc_excess_blob_gas`](crate::calc_excess_blob_gas). - /// - /// Incorporated as part of the Cancun upgrade via [EIP-4844]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 - pub excess_blob_gas: Option, -} +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 + } + } -impl BlockEnv { - /// See [EIP-4844] and [`Env::calc_data_fee`]. + /// 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 get_blob_gasprice(&self) -> Option { - self.excess_blob_gas.map(calc_blob_fee) + pub fn calc_data_fee(&self) -> Option { + self.block + .get_blob_gasprice() + .map(|blob_gas_price| blob_gas_price * self.tx.get_total_blob_gas()) } -} -/// The transaction environment. -#[derive(Clone, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct TxEnv { - /// The caller, author or signer of the transaction. - pub caller: B160, - /// The gas limit of the transaction. - pub gas_limit: u64, - /// The gas price of the transaction. - pub gas_price: U256, - /// The destination of the transaction. - pub transact_to: TransactTo, - /// The value sent to `transact_to`. - pub value: U256, - /// The data of the transaction. - #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] - pub data: Bytes, - /// The nonce of the transaction. If set to `None`, no checks are performed. - pub nonce: Option, + /// Validate the block environment. + #[inline] + pub fn validate_block_env(&self) -> Result<(), EVMError> { + // `prevrandao` is required for the merge + if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao.is_none() { + return Err(EVMError::PrevrandaoNotSet); + } + // `excess_blob_gas` is required for Cancun + if SPEC::enabled(SpecId::CANCUN) && self.block.excess_blob_gas.is_none() { + return Err(EVMError::ExcessBlobGasNotSet); + } + Ok(()) + } - /// The chain ID of the transaction. If set to `None`, no checks are performed. - /// - /// Incorporated as part of the Spurious Dragon upgrade via [EIP-155]. + /// Validate transaction data that is set inside ENV and return error if something is wrong. /// - /// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 - pub chain_id: Option, + /// Return initial spend gas (Gas needed to execute transaction). + #[inline] + pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { + let gas_limit = self.tx.gas_limit; + let effective_gas_price = self.effective_gas_price(); + let is_create = self.tx.transact_to.is_create(); - /// A list of addresses and storage keys that the transaction plans to access. - /// - /// Added in [EIP-2930]. - /// - /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 - pub access_list: Vec<(B160, Vec)>, + // 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::GasMaxFeeGreaterThanPriorityFee); + } + } + let basefee = self.block.basefee; - /// The priority fee per gas. - /// - /// Incorporated as part of the London upgrade via [EIP-1559]. - /// - /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 - pub gas_priority_fee: Option, + // check minimal cost against basefee + if !self.cfg.is_base_fee_check_disabled() && effective_gas_price < basefee { + return Err(InvalidTransaction::GasPriceLessThanBasefee); + } + } - /// The list of blob versioned hashes. - /// - /// Incorporated as part of the Cancun upgrade via [EIP-4844]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 - pub blob_hashes: Vec, - /// The max fee per blob gas. - /// - /// Incorporated as part of the Cancun upgrade via [EIP-4844]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 - pub max_fee_per_blob_gas: Option, -} + // 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); + } -impl TxEnv { - /// See [EIP-4844] and [`Env::calc_data_fee`]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 - #[inline] - pub fn get_total_blob_gas(&self) -> u64 { - GAS_PER_BLOB * self.blob_hashes.len() as u64 - } -} + // 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); + } + } -/// Transaction destination. -#[derive(Clone, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum TransactTo { - /// Simple call to an address. - Call(B160), - /// Contract creation. - Create(CreateScheme), -} + // 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); + } + } -impl TransactTo { - /// Calls the given address. - #[inline] - pub fn call(address: B160) -> Self { - Self::Call(address) - } + // 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); + } - /// Creates a contract. - #[inline] - pub fn create() -> Self { - Self::Create(CreateScheme::Create) - } + // - 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) { + if let Some(max) = self.tx.max_fee_per_blob_gas { + let price = self.block.get_blob_gasprice().expect("already checked"); + if U256::from(price) > max { + return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); + } + } + } 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); + } + } - /// Creates a contract with the given salt using `CREATE2`. - #[inline] - pub fn create2(salt: U256) -> Self { - Self::Create(CreateScheme::Create2 { salt }) + Ok(()) } - /// Returns `true` if the transaction is `Call`. + /// Validate transaction against state. #[inline] - pub fn is_call(&self) -> bool { - matches!(self, Self::Call(_)) - } + pub fn validate_tx_against_state(&self, account: &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); + } - /// Returns `true` if the transaction is `Create` or `Create2`. - #[inline] - pub fn is_create(&self) -> bool { - matches!(self, Self::Create(_)) - } -} + // 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 }); + } + _ => {} + } + } -/// Create scheme. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum CreateScheme { - /// Legacy create scheme of `CREATE`. - Create, - /// Create scheme of `CREATE2`. - Create2 { - /// Salt. - salt: U256, - }, + 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)?; + } + + // Check if account has enough balance for gas_limit*gas_price and value transfer. + // Transfer will be done inside `*_inner` functions. + if !self.cfg.is_balance_check_disabled() && balance_check > account.info.balance { + return Err(InvalidTransaction::LackOfFundForMaxFee { + fee: self.tx.gas_limit, + balance: account.info.balance, + }); + } + + Ok(()) + } } /// EVM configuration. @@ -291,57 +283,162 @@ impl CfgEnv { } } -/// What bytecode analysis to perform. -#[derive(Clone, Default, Debug, Eq, PartialEq)] +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, + disable_coinbase_tip: false, + #[cfg(feature = "std")] + 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, + } + } +} + +/// The block environment. +#[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum AnalysisKind { - /// Do not perform bytecode analysis. - Raw, - /// Check the bytecode for validity. - Check, - /// Perform bytecode analysis. - #[default] - Analyse, +pub struct BlockEnv { + /// The number of ancestor blocks of this block (block height). + pub number: U256, + /// Coinbase or miner or address that created and signed the block. + /// + /// This is the receiver address of all the gas spent in the block. + pub coinbase: B160, + /// The timestamp of the block in seconds since the UNIX epoch. + pub timestamp: U256, + /// The gas limit of the block. + pub gas_limit: U256, + + /// The base fee per gas, added in the London upgrade with [EIP-1559]. + /// + /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + pub basefee: U256, + + /// The difficulty of the block. + /// + /// Unused after the Paris (AKA the merge) upgrade, and replaced by `prevrandao`. + pub difficulty: U256, + /// The output of the randomness beacon provided by the beacon chain. + /// + /// Replaces `difficulty` after the Paris (AKA the merge) upgrade with [EIP-4399]. + /// + /// NOTE: `prevrandao` can be found in a block in place of `mix_hash`. + /// + /// [EIP-4399]: https://eips.ethereum.org/EIPS/eip-4399 + pub prevrandao: Option, + + /// Excess blob gas. See also [`calc_excess_blob_gas`](crate::calc_excess_blob_gas). + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + pub excess_blob_gas: Option, } -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, - disable_coinbase_tip: false, - #[cfg(feature = "std")] - 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, - } - } +impl BlockEnv { + /// See [EIP-4844] and [`Env::calc_data_fee`]. + /// + /// 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 get_blob_gasprice(&self) -> Option { + self.excess_blob_gas.map(calc_blob_fee) + } +} + +impl Default for BlockEnv { + fn default() -> Self { + Self { + number: U256::ZERO, + coinbase: B160::zero(), + timestamp: U256::from(1), + gas_limit: U256::MAX, + basefee: U256::ZERO, + difficulty: U256::ZERO, + prevrandao: Some(B256::zero()), + excess_blob_gas: Some(0), + } + } +} + +/// The transaction environment. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TxEnv { + /// The caller, author or signer of the transaction. + pub caller: B160, + /// The gas limit of the transaction. + pub gas_limit: u64, + /// The gas price of the transaction. + pub gas_price: U256, + /// The destination of the transaction. + pub transact_to: TransactTo, + /// The value sent to `transact_to`. + pub value: U256, + /// The data of the transaction. + #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] + pub data: Bytes, + /// The nonce of the transaction. If set to `None`, no checks are performed. + pub nonce: Option, + + /// The chain ID of the transaction. If set to `None`, no checks are performed. + /// + /// Incorporated as part of the Spurious Dragon upgrade via [EIP-155]. + /// + /// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 + pub chain_id: Option, + + /// A list of addresses and storage keys that the transaction plans to access. + /// + /// Added in [EIP-2930]. + /// + /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 + pub access_list: Vec<(B160, Vec)>, + + /// The priority fee per gas. + /// + /// Incorporated as part of the London upgrade via [EIP-1559]. + /// + /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + pub gas_priority_fee: Option, + + /// The list of blob versioned hashes. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + pub blob_hashes: Vec, + /// The max fee per blob gas. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + pub max_fee_per_blob_gas: Option, } -impl Default for BlockEnv { - fn default() -> Self { - Self { - number: U256::ZERO, - coinbase: B160::zero(), - timestamp: U256::from(1), - gas_limit: U256::MAX, - basefee: U256::ZERO, - difficulty: U256::ZERO, - prevrandao: Some(B256::zero()), - excess_blob_gas: Some(0), - } +impl TxEnv { + /// See [EIP-4844] and [`Env::calc_data_fee`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + #[inline] + pub fn get_total_blob_gas(&self) -> u64 { + GAS_PER_BLOB * self.blob_hashes.len() as u64 } } @@ -364,163 +461,70 @@ impl Default for TxEnv { } } -impl Env { - /// Calculates the effective gas price of the transaction. +/// Transaction destination. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TransactTo { + /// Simple call to an address. + Call(B160), + /// Contract creation. + Create(CreateScheme), +} + +impl TransactTo { + /// Calls the given address. #[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 - } + pub fn call(address: B160) -> Self { + Self::Call(address) } - /// 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 + /// Creates a contract. #[inline] - pub fn calc_data_fee(&self) -> Option { - self.block - .get_blob_gasprice() - .map(|blob_gas_price| blob_gas_price * self.tx.get_total_blob_gas()) + pub fn create() -> Self { + Self::Create(CreateScheme::Create) } - /// Validate the block environment. + /// Creates a contract with the given salt using `CREATE2`. #[inline] - pub fn validate_block_env(&self) -> Result<(), EVMError> { - // `prevrandao` is required for the merge - if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao.is_none() { - return Err(EVMError::PrevrandaoNotSet); - } - // `excess_blob_gas` is required for Cancun - if SPEC::enabled(SpecId::CANCUN) && self.block.excess_blob_gas.is_none() { - return Err(EVMError::ExcessBlobGasNotSet); - } - Ok(()) + pub fn create2(salt: U256) -> Self { + Self::Create(CreateScheme::Create2 { salt }) } - /// Validate transaction data that is set inside ENV and return error if something is wrong. - /// - /// Return initial spend gas (Gas needed to execute transaction). + /// Returns `true` if the transaction is `Call`. #[inline] - pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { - 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::GasMaxFeeGreaterThanPriorityFee); - } - } - 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) { - if let Some(max) = self.tx.max_fee_per_blob_gas { - let price = self.block.get_blob_gasprice().expect("already checked"); - if U256::from(price) > max { - return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); - } - } - } 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(()) + pub fn is_call(&self) -> bool { + matches!(self, Self::Call(_)) } - /// Validate transaction against state. + /// Returns `true` if the transaction is `Create` or `Create2`. #[inline] - pub fn validate_tx_against_state(&self, account: &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); - } - - // 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)?; - } + pub fn is_create(&self) -> bool { + matches!(self, Self::Create(_)) + } +} - // Check if account has enough balance for gas_limit*gas_price and value transfer. - // Transfer will be done inside `*_inner` functions. - if !self.cfg.is_balance_check_disabled() && balance_check > account.info.balance { - return Err(InvalidTransaction::LackOfFundForMaxFee { - fee: self.tx.gas_limit, - balance: account.info.balance, - }); - } +/// Create scheme. +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum CreateScheme { + /// Legacy create scheme of `CREATE`. + Create, + /// Create scheme of `CREATE2`. + Create2 { + /// Salt. + salt: U256, + }, +} - Ok(()) - } +/// What bytecode analysis to perform. +#[derive(Clone, Default, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AnalysisKind { + /// Do not perform bytecode analysis. + Raw, + /// Check the bytecode for validity. + Check, + /// Perform bytecode analysis. + #[default] + Analyse, }