From 637e3d8072a47ba65b20cec0a840ef91074deac8 Mon Sep 17 00:00:00 2001 From: varun-doshi Date: Tue, 21 Jan 2025 12:05:27 +0530 Subject: [PATCH 1/2] feat: replace specId with Fork --- crates/common/types/genesis.rs | 55 +++++++++++++++++-- crates/vm/levm/src/environment.rs | 4 +- crates/vm/levm/src/gas_cost.rs | 22 ++++---- crates/vm/levm/src/opcode_handlers/block.rs | 6 +- crates/vm/levm/src/opcode_handlers/push.rs | 4 +- .../stack_memory_storage_flow.rs | 8 +-- crates/vm/levm/src/opcode_handlers/system.rs | 6 +- crates/vm/levm/src/precompiles.rs | 14 ++--- crates/vm/levm/src/vm.rs | 20 +++---- crates/vm/levm/tests/tests.rs | 6 +- crates/vm/vm.rs | 52 ++++++++++++++++-- 11 files changed, 142 insertions(+), 55 deletions(-) diff --git a/crates/common/types/genesis.rs b/crates/common/types/genesis.rs index 21ed59b0ec..4bebd49ae7 100644 --- a/crates/common/types/genesis.rs +++ b/crates/common/types/genesis.rs @@ -87,11 +87,54 @@ pub struct ChainConfig { pub terminal_total_difficulty_passed: bool, } -#[derive(Debug, PartialEq, PartialOrd)] +#[derive(Debug, PartialEq, PartialOrd, Default, Clone, Copy, Serialize, Deserialize)] pub enum Fork { - Paris = 0, - Shanghai = 1, - Cancun = 2, + Frontier = 0, // Frontier 0 + FrontierThawing = 1, // Frontier Thawing 200000 + Homestead = 2, // Homestead 1150000 + DaoFork = 3, // DAO Fork 1920000 + Tangerine = 4, // Tangerine Whistle 2463000 + SpuriousDragon = 5, // Spurious Dragon 2675000 + Byzantium = 6, // Byzantium 4370000 + Constantinople = 7, // Constantinople 7280000 is overwritten with PETERSBURG + Petersburg = 8, // Petersburg 7280000 + Istanbul = 9, // Istanbul 9069000 + MuirGlacier = 10, // Muir Glacier 9200000 + Berlin = 11, // Berlin 12244000 + London = 12, // London 12965000 + ArrowGlacier = 13, // Arrow Glacier 13773000 + GrayGlacier = 14, // Gray Glacier 15050000 + Paris = 15, // Paris/Merge 15537394 (TTD: 58750000000000000000000) + Shanghai = 16, // Shanghai 17034870 (Timestamp: 1681338455) + #[default] + Cancun = 17, // Cancun 19426587 (Timestamp: 1710338135) + Prague = 18, // Prague TBD +} + +impl From for &str { + fn from(fork: Fork) -> Self { + match fork { + Fork::Frontier => "Frontier", + Fork::FrontierThawing => "FrontierThawing", + Fork::Homestead => "Homestead", + Fork::DaoFork => "DaoFork", + Fork::Tangerine => "Tangerine", + Fork::SpuriousDragon => "SpuriousDragon", + Fork::Byzantium => "Byzantium", + Fork::Constantinople => "Constantinople", + Fork::Petersburg => "Petersburg", + Fork::Istanbul => "Istanbul", + Fork::MuirGlacier => "MuirGlacier", + Fork::Berlin => "Berlin", + Fork::London => "London", + Fork::ArrowGlacier => "ArrowGlacier", + Fork::GrayGlacier => "GrayGlacier", + Fork::Paris => "Paris", + Fork::Shanghai => "Shanghai", + Fork::Cancun => "Cancun", + Fork::Prague => "Prague", + } + } } impl ChainConfig { @@ -122,6 +165,10 @@ impl ChainConfig { } } + pub fn fork(&self, block_timestamp: u64) -> Fork { + self.get_fork(block_timestamp) + } + pub fn gather_forks(&self) -> (Vec>, Vec>) { let block_number_based_forks: Vec> = vec![ self.homestead_block, diff --git a/crates/vm/levm/src/environment.rs b/crates/vm/levm/src/environment.rs index b1e1ae8956..44dff30389 100644 --- a/crates/vm/levm/src/environment.rs +++ b/crates/vm/levm/src/environment.rs @@ -1,4 +1,4 @@ -use ethrex_core::{Address, H256, U256}; +use ethrex_core::{types::Fork, Address, H256, U256}; pub use revm_primitives::SpecId; use std::collections::HashMap; @@ -12,7 +12,7 @@ pub struct Environment { pub origin: Address, pub refunded_gas: u64, pub gas_limit: u64, - pub spec_id: SpecId, + pub spec_id: Fork, pub block_number: U256, pub coinbase: Address, pub timestamp: U256, diff --git a/crates/vm/levm/src/gas_cost.rs b/crates/vm/levm/src/gas_cost.rs index a659876415..a471ba362a 100644 --- a/crates/vm/levm/src/gas_cost.rs +++ b/crates/vm/levm/src/gas_cost.rs @@ -6,7 +6,7 @@ use crate::{ }; use bytes::Bytes; /// Contains the gas costs of the EVM instructions -use ethrex_core::U256; +use ethrex_core::{types::Fork, U256}; use num_bigint::BigUint; use revm_primitives::SpecId; @@ -464,7 +464,7 @@ pub fn create( new_memory_size: usize, current_memory_size: usize, code_size_in_memory: usize, - spec_id: SpecId, + spec_id: Fork, ) -> Result { compute_gas_create( new_memory_size, @@ -479,7 +479,7 @@ pub fn create_2( new_memory_size: usize, current_memory_size: usize, code_size_in_memory: usize, - spec_id: SpecId, + spec_id: Fork, ) -> Result { compute_gas_create( new_memory_size, @@ -495,7 +495,7 @@ fn compute_gas_create( current_memory_size: usize, code_size_in_memory: usize, is_create_2: bool, - spec_id: SpecId, + spec_id: Fork, ) -> Result { let minimum_word_size = (code_size_in_memory .checked_add(31) @@ -508,7 +508,7 @@ fn compute_gas_create( .map_err(|_| VMError::VeryLargeNumber)?; // [EIP-3860] - Apply extra gas cost of 2 for every 32-byte chunk of initcode - let init_code_cost = if spec_id >= SpecId::SHANGHAI { + let init_code_cost = if spec_id >= Fork::Shanghai { minimum_word_size .checked_mul(INIT_CODE_WORD_COST) .ok_or(OutOfGasError::GasCostOverflow)? // will not panic since it's 2 @@ -560,13 +560,13 @@ pub fn selfdestruct( Ok(gas_cost) } -pub fn tx_calldata(calldata: &Bytes, spec_id: SpecId) -> Result { +pub fn tx_calldata(calldata: &Bytes, spec_id: Fork) -> Result { // This cost applies both for call and create // 4 gas for each zero byte in the transaction data 16 gas for each non-zero byte in the transaction. let mut calldata_cost: u64 = 0; for byte in calldata { calldata_cost = if *byte != 0 { - if spec_id >= SpecId::ISTANBUL { + if spec_id >= Fork::Istanbul { calldata_cost .checked_add(CALLDATA_COST_NON_ZERO_BYTE) .ok_or(OutOfGasError::GasUsedOverflow)? @@ -681,7 +681,7 @@ pub fn call( value_to_transfer: U256, gas_from_stack: U256, gas_left: u64, - spec_id: SpecId, + spec_id: Fork, ) -> Result<(u64, u64), VMError> { let memory_expansion_cost = memory::expansion_cost(new_memory_size, current_memory_size)?; @@ -689,7 +689,7 @@ pub fn call( address_was_cold, CALL_STATIC, CALL_COLD_DYNAMIC, - if spec_id >= SpecId::BERLIN { + if spec_id >= Fork::Berlin { CALL_WARM_DYNAMIC } else { //https://eips.ethereum.org/EIPS/eip-2929 @@ -966,7 +966,7 @@ pub fn modexp( base_size: usize, exponent_size: usize, modulus_size: usize, - spec_id: SpecId, + spec_id: Fork, ) -> Result { let base_size: u64 = base_size .try_into() @@ -980,7 +980,7 @@ pub fn modexp( let max_length = base_size.max(modulus_size); - if spec_id >= SpecId::BERLIN { + if spec_id >= Fork::Berlin { modexp_eip2565(max_length, exponent_first_32_bytes, exponent_size) } else { modexp_eip198(max_length, exponent_first_32_bytes, exponent_size) diff --git a/crates/vm/levm/src/opcode_handlers/block.rs b/crates/vm/levm/src/opcode_handlers/block.rs index 3b6e05bcb9..52615b04cb 100644 --- a/crates/vm/levm/src/opcode_handlers/block.rs +++ b/crates/vm/levm/src/opcode_handlers/block.rs @@ -6,7 +6,7 @@ use crate::{ vm::{address_to_word, VM}, }; use ethrex_core::{ - types::{BLOB_BASE_FEE_UPDATE_FRACTION, MIN_BASE_FEE_PER_BLOB_GAS}, + types::{Fork, BLOB_BASE_FEE_UPDATE_FRACTION, MIN_BASE_FEE_PER_BLOB_GAS}, U256, }; use revm_primitives::SpecId; @@ -162,7 +162,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-4844] - BLOBHASH is only available from CANCUN - if self.env.spec_id < SpecId::CANCUN { + if self.env.spec_id < Fork::Cancun { return Err(VMError::InvalidOpcode); } @@ -209,7 +209,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-7516] - BLOBBASEFEE is only available from CANCUN - if self.env.spec_id < SpecId::CANCUN { + if self.env.spec_id < Fork::Cancun { return Err(VMError::InvalidOpcode); } self.increase_consumed_gas(current_call_frame, gas_cost::BLOBBASEFEE)?; diff --git a/crates/vm/levm/src/opcode_handlers/push.rs b/crates/vm/levm/src/opcode_handlers/push.rs index ac4c7ab759..bd109c1dd0 100644 --- a/crates/vm/levm/src/opcode_handlers/push.rs +++ b/crates/vm/levm/src/opcode_handlers/push.rs @@ -5,7 +5,7 @@ use crate::{ gas_cost, vm::VM, }; -use ethrex_core::U256; +use ethrex_core::{types::Fork, U256}; use revm_primitives::SpecId; // Push Operations @@ -38,7 +38,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-3855] - PUSH0 is only available from SHANGHAI - if self.env.spec_id < SpecId::SHANGHAI { + if self.env.spec_id < Fork::Shanghai { return Err(VMError::InvalidOpcode); } diff --git a/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs b/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs index d906e3ec65..d7f8de8bec 100644 --- a/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs +++ b/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs @@ -6,7 +6,7 @@ use crate::{ memory::{self, calculate_memory_size}, vm::VM, }; -use ethrex_core::{H256, U256}; +use ethrex_core::{types::Fork, H256, U256}; use revm_primitives::SpecId; // Stack, Memory, Storage and Flow Operations (15) @@ -26,7 +26,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-1153] - TLOAD is only available from CANCUN - if self.env.spec_id < SpecId::CANCUN { + if self.env.spec_id < Fork::Cancun { return Err(VMError::InvalidOpcode); } @@ -50,7 +50,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-1153] - TLOAD is only available from CANCUN - if self.env.spec_id < SpecId::CANCUN { + if self.env.spec_id < Fork::Cancun { return Err(VMError::InvalidOpcode); } @@ -264,7 +264,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-5656] - MCOPY is only available from CANCUN - if self.env.spec_id < SpecId::CANCUN { + if self.env.spec_id < Fork::Cancun { return Err(VMError::InvalidOpcode); } diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index 884cfff1e2..985f793db4 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -9,7 +9,7 @@ use crate::{ Account, }; use bytes::Bytes; -use ethrex_core::{Address, U256}; +use ethrex_core::{types::Fork, Address, U256}; use revm_primitives::SpecId; // System Operations (10) @@ -468,7 +468,7 @@ impl VM { )?; // [EIP-6780] - SELFDESTRUCT only in same transaction from CANCUN - if self.env.spec_id >= SpecId::CANCUN { + if self.env.spec_id >= Fork::Cancun { self.increase_account_balance(target_address, balance_to_transfer)?; self.decrease_account_balance(current_call_frame.to, balance_to_transfer)?; @@ -512,7 +512,7 @@ impl VM { return Err(VMError::OpcodeNotAllowedInStaticContext); } // 2. [EIP-3860] - Cant exceed init code max size - if code_size_in_memory > INIT_CODE_MAX_SIZE && self.env.spec_id >= SpecId::SHANGHAI { + if code_size_in_memory > INIT_CODE_MAX_SIZE && self.env.spec_id >= Fork::Shanghai { return Err(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow)); } diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 2b0e14132a..80d6817558 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -4,7 +4,7 @@ use bls12_381::{ }; use bytes::Bytes; -use ethrex_core::{serde_utils::bool, Address, H160, H256, U256}; +use ethrex_core::{serde_utils::bool, types::Fork, Address, H160, H256, U256}; use keccak_hash::keccak256; use kzg_rs::{Bytes32, Bytes48, KzgSettings}; use lambdaworks_math::{ @@ -176,14 +176,14 @@ const FP2_ZERO_MAPPED_TO_G2: [u8; 256] = [ pub const G1_POINT_AT_INFINITY: [u8; 128] = [0_u8; 128]; pub const G2_POINT_AT_INFINITY: [u8; 256] = [0_u8; 256]; -pub fn is_precompile(callee_address: &Address, spec_id: SpecId) -> bool { +pub fn is_precompile(callee_address: &Address, spec_id: Fork) -> bool { // Cancun specs is the only one that allows point evaluation precompile - if *callee_address == POINT_EVALUATION_ADDRESS && spec_id < SpecId::CANCUN { + if *callee_address == POINT_EVALUATION_ADDRESS && spec_id < Fork::Cancun { return false; } // Prague or newers forks should only use this precompiles // https://eips.ethereum.org/EIPS/eip-2537 - if PRECOMPILES_POST_CANCUN.contains(callee_address) && spec_id < SpecId::PRAGUE { + if PRECOMPILES_POST_CANCUN.contains(callee_address) && spec_id < Fork::Prague { return false; } @@ -192,7 +192,7 @@ pub fn is_precompile(callee_address: &Address, spec_id: SpecId) -> bool { pub fn execute_precompile( current_call_frame: &mut CallFrame, - spec_id: SpecId, + spec_id: Fork, ) -> Result { let callee_address = current_call_frame.code_address; let gas_for_call = current_call_frame @@ -400,7 +400,7 @@ pub fn modexp( calldata: &Bytes, gas_for_call: u64, consumed_gas: &mut u64, - spec_id: SpecId, + spec_id: Fork, ) -> Result { // If calldata does not reach the required length, we should fill the rest with zeros let calldata = fill_with_zeros(calldata, 96)?; @@ -426,7 +426,7 @@ pub fn modexp( if base_size == U256::zero() && modulus_size == U256::zero() { // On Berlin or newer there is a floor cost for the modexp precompile // On older versions in this return there is no cost added, see more https://eips.ethereum.org/EIPS/eip-2565 - if spec_id >= SpecId::BERLIN { + if spec_id >= Fork::Berlin { increase_precompile_consumed_gas(gas_for_call, MODEXP_STATIC_COST, consumed_gas)?; } return Ok(Bytes::new()); diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index 2656b003d3..f261e525fd 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -24,7 +24,7 @@ use crate::{ AccountInfo, TransientStorage, }; use bytes::Bytes; -use ethrex_core::{types::TxKind, Address, H256, U256}; +use ethrex_core::{types::{Fork, TxKind}, Address, H256, U256}; use ethrex_rlp; use ethrex_rlp::encode::RLPEncode; use keccak_hash::keccak; @@ -155,7 +155,7 @@ impl VM { let mut default_touched_accounts = HashSet::from_iter([env.origin].iter().cloned()); // [EIP-3651] - Add coinbase to cache if the spec is SHANGHAI or higher - if env.spec_id >= SpecId::SHANGHAI { + if env.spec_id >= Fork::Shanghai { default_touched_accounts.insert(env.coinbase); } @@ -174,9 +174,9 @@ impl VM { // Add precompiled contracts addresses to cache. // TODO: Use the addresses from precompiles.rs in a future let max_precompile_address = match env.spec_id { - spec if spec >= SpecId::PRAGUE => SIZE_PRECOMPILES_PRAGUE, - spec if spec >= SpecId::CANCUN => SIZE_PRECOMPILES_CANCUN, - spec if spec < SpecId::CANCUN => SIZE_PRECOMPILES_PRE_CANCUN, + spec if spec >= Fork::Prague => SIZE_PRECOMPILES_PRAGUE, + spec if spec >= Fork::Cancun => SIZE_PRECOMPILES_CANCUN, + spec if spec < Fork::Cancun => SIZE_PRECOMPILES_PRE_CANCUN, _ => return Err(VMError::Internal(InternalError::InvalidSpecId)), }; for i in 1..=max_precompile_address { @@ -636,7 +636,7 @@ impl VM { } fn gas_used(&self, current_call_frame: &mut CallFrame) -> Result { - if self.env.spec_id >= SpecId::PRAGUE { + if self.env.spec_id >= Fork::Prague { // tokens_in_calldata = nonzero_bytes_in_calldata * 4 + zero_bytes_in_calldata // tx_calldata = nonzero_bytes_in_calldata * 16 + zero_bytes_in_calldata * 4 // this is actually tokens_in_calldata * STANDARD_TOKEN_COST @@ -729,7 +729,7 @@ impl VM { let sender_address = self.env.origin; let sender_account = self.get_account(sender_address); - if self.env.spec_id >= SpecId::PRAGUE { + if self.env.spec_id >= Fork::Prague { // check for gas limit is grater or equal than the minimum required let intrinsic_gas: u64 = self.get_intrinsic_gas(initial_call_frame)?; @@ -847,7 +847,7 @@ impl VM { if self.is_create() { // [EIP-3860] - INITCODE_SIZE_EXCEEDED if initial_call_frame.calldata.len() > INIT_CODE_MAX_SIZE - && self.env.spec_id >= SpecId::SHANGHAI + && self.env.spec_id >= Fork::Shanghai { return Err(VMError::TxValidation( TxValidationError::InitcodeSizeExceeded, @@ -889,7 +889,7 @@ impl VM { // Transaction is type 3 if tx_max_fee_per_blob_gas is Some if self.env.tx_max_fee_per_blob_gas.is_some() { // (11) TYPE_3_TX_PRE_FORK - if self.env.spec_id < SpecId::CANCUN { + if self.env.spec_id < Fork::Cancun { return Err(VMError::TxValidation(TxValidationError::Type3TxPreFork)); } @@ -1149,7 +1149,7 @@ impl VM { ) -> Result<(StorageSlot, bool), VMError> { // [EIP-2929] - Introduced conditional tracking of accessed storage slots for Berlin and later specs. let mut storage_slot_was_cold = false; - if self.env.spec_id >= SpecId::BERLIN { + if self.env.spec_id >= Fork::Berlin { storage_slot_was_cold = self .accrued_substate .touched_storage_slots diff --git a/crates/vm/levm/tests/tests.rs b/crates/vm/levm/tests/tests.rs index bae5a8dd98..b1104805b5 100644 --- a/crates/vm/levm/tests/tests.rs +++ b/crates/vm/levm/tests/tests.rs @@ -2,7 +2,7 @@ #![allow(clippy::unwrap_used)] use bytes::Bytes; -use ethrex_core::{types::TxKind, Address, H256, U256}; +use ethrex_core::{types::{Fork, TxKind}, Address, H256, U256}; use ethrex_levm::{ account::Account, constants::*, @@ -4562,7 +4562,7 @@ fn modexp_test() { &calldata, 10000, &mut consumed_gas, - ethrex_levm::SpecId::CANCUN, + Fork::Cancun, ) .unwrap(); @@ -4583,7 +4583,7 @@ fn modexp_test_2() { &calldata, 10000, &mut consumed_gas, - ethrex_levm::SpecId::CANCUN, + Fork::Cancun, ) .unwrap(); diff --git a/crates/vm/vm.rs b/crates/vm/vm.rs index 196fc77693..c21f806c0d 100644 --- a/crates/vm/vm.rs +++ b/crates/vm/vm.rs @@ -94,7 +94,7 @@ cfg_if::cfg_if! { pub fn beacon_root_contract_call_levm( store_wrapper: Arc, block_header: &BlockHeader, - spec_id: SpecId, + spec_id: Fork, ) -> Result { lazy_static! { static ref SYSTEM_ADDRESS: Address = @@ -220,12 +220,12 @@ cfg_if::cfg_if! { }); let mut block_cache: CacheDB = HashMap::new(); let block_header = &block.header; - let spec_id = spec_id(&state.chain_config()?, block_header.timestamp); + let fork=state.chain_config()?.fork(block_header.timestamp); //eip 4788: execute beacon_root_contract_call before block transactions cfg_if::cfg_if! { if #[cfg(not(feature = "l2"))] { - if block_header.parent_beacon_block_root.is_some() && spec_id == SpecId::CANCUN { - let report = beacon_root_contract_call_levm(store_wrapper.clone(), block_header, spec_id)?; + if block_header.parent_beacon_block_root.is_some() && fork == Fork::Cancun { + let report = beacon_root_contract_call_levm(store_wrapper.clone(), block_header, fork)?; block_cache.extend(report.new_state); } } @@ -239,7 +239,7 @@ cfg_if::cfg_if! { let mut cumulative_gas_used = 0; for tx in block.body.transactions.iter() { - let report = execute_tx_levm(tx, block_header, store_wrapper.clone(), block_cache.clone(), spec_id).map_err(EvmError::from)?; + let report = execute_tx_levm(tx, block_header, store_wrapper.clone(), block_cache.clone(), fork).map_err(EvmError::from)?; let mut new_state = report.new_state.clone(); @@ -292,7 +292,7 @@ cfg_if::cfg_if! { block_header: &BlockHeader, db: Arc, block_cache: CacheDB, - spec_id: SpecId + spec_id: Fork ) -> Result { let gas_price : U256 = tx.effective_gas_price(block_header.base_fee_per_gas).ok_or(VMError::InvalidTransaction)?.into(); @@ -985,6 +985,46 @@ pub fn spec_id(chain_config: &ChainConfig, block_timestamp: u64) -> SpecId { Fork::Cancun => SpecId::CANCUN, Fork::Shanghai => SpecId::SHANGHAI, Fork::Paris => SpecId::MERGE, + Fork::Istanbul => SpecId::ISTANBUL, + Fork::Berlin => SpecId::BERLIN, + Fork::Prague => SpecId::PRAGUE, + Fork::Frontier => todo!(), + Fork::FrontierThawing => todo!(), + Fork::Homestead => todo!(), + Fork::DaoFork => todo!(), + Fork::Tangerine => todo!(), + Fork::SpuriousDragon => todo!(), + Fork::Byzantium => todo!(), + Fork::Constantinople => todo!(), + Fork::Petersburg => todo!(), + Fork::MuirGlacier => todo!(), + Fork::London => todo!(), + Fork::ArrowGlacier => todo!(), + Fork::GrayGlacier => todo!(), + } +} + +pub fn fork_to_spec_id(fork: Fork) -> SpecId { + match fork { + Fork::Frontier => SpecId::FRONTIER, + Fork::FrontierThawing => SpecId::FRONTIER_THAWING, + Fork::Homestead => SpecId::HOMESTEAD, + Fork::DaoFork => SpecId::DAO_FORK, + Fork::Tangerine => SpecId::TANGERINE, + Fork::SpuriousDragon => SpecId::SPURIOUS_DRAGON, + Fork::Byzantium => SpecId::BYZANTIUM, + Fork::Constantinople => SpecId::CONSTANTINOPLE, + Fork::Petersburg => SpecId::PETERSBURG, + Fork::Istanbul => SpecId::ISTANBUL, + Fork::MuirGlacier => SpecId::MUIR_GLACIER, + Fork::Berlin => SpecId::BERLIN, + Fork::London => SpecId::LONDON, + Fork::ArrowGlacier => SpecId::ARROW_GLACIER, + Fork::GrayGlacier => SpecId::GRAY_GLACIER, + Fork::Paris => SpecId::MERGE, + Fork::Shanghai => SpecId::SHANGHAI, + Fork::Cancun => SpecId::CANCUN, + Fork::Prague => SpecId::PRAGUE, } } From 3e0f9b96a33f39ed5f352843c1892d6e6714e05f Mon Sep 17 00:00:00 2001 From: varun-doshi Date: Wed, 22 Jan 2025 00:15:18 +0530 Subject: [PATCH 2/2] resolved comments --- cmd/ef_tests/levm/report.rs | 105 +++++++++--------- cmd/ef_tests/levm/runner/levm_runner.rs | 2 +- cmd/ef_tests/levm/runner/revm_runner.rs | 4 +- cmd/ef_tests/levm/types.rs | 27 +++-- crates/common/types/genesis.rs | 66 +++++++---- crates/vm/levm/src/environment.rs | 2 +- crates/vm/levm/src/gas_cost.rs | 25 ++--- crates/vm/levm/src/opcode_handlers/block.rs | 5 +- crates/vm/levm/src/opcode_handlers/push.rs | 3 +- .../stack_memory_storage_flow.rs | 7 +- crates/vm/levm/src/opcode_handlers/system.rs | 11 +- crates/vm/levm/src/precompiles.rs | 17 ++- crates/vm/levm/src/vm.rs | 25 ++--- crates/vm/vm.rs | 30 +---- 14 files changed, 164 insertions(+), 165 deletions(-) diff --git a/cmd/ef_tests/levm/report.rs b/cmd/ef_tests/levm/report.rs index cef2d1b3e3..77df60fed4 100644 --- a/cmd/ef_tests/levm/report.rs +++ b/cmd/ef_tests/levm/report.rs @@ -1,12 +1,11 @@ use crate::runner::{EFTestRunnerError, InternalError}; use colored::Colorize; -use ethrex_core::{Address, H256}; +use ethrex_core::{types::Fork, Address, H256}; use ethrex_levm::{ errors::{TransactionReport, TxResult, VMError}, Account, StorageSlot, }; use ethrex_storage::{error::StoreError, AccountUpdate}; -use ethrex_vm::SpecId; use itertools::Itertools; use revm::primitives::{EVMError, ExecutionResult as RevmExecutionResult}; use serde::{Deserialize, Serialize}; @@ -133,21 +132,21 @@ pub fn summary_for_slack(reports: &[EFTestReport]) -> String { }} ] }}"#, - fork_summary_for_slack(reports, SpecId::PRAGUE), - fork_summary_for_slack(reports, SpecId::CANCUN), - fork_summary_for_slack(reports, SpecId::SHANGHAI), - fork_summary_for_slack(reports, SpecId::HOMESTEAD), - fork_summary_for_slack(reports, SpecId::ISTANBUL), - fork_summary_for_slack(reports, SpecId::LONDON), - fork_summary_for_slack(reports, SpecId::BYZANTIUM), - fork_summary_for_slack(reports, SpecId::BERLIN), - fork_summary_for_slack(reports, SpecId::CONSTANTINOPLE), - fork_summary_for_slack(reports, SpecId::MERGE), - fork_summary_for_slack(reports, SpecId::FRONTIER), + fork_summary_for_slack(reports, Fork::Prague), + fork_summary_for_slack(reports, Fork::Cancun), + fork_summary_for_slack(reports, Fork::Shanghai), + fork_summary_for_slack(reports, Fork::Homestead), + fork_summary_for_slack(reports, Fork::Istanbul), + fork_summary_for_slack(reports, Fork::London), + fork_summary_for_slack(reports, Fork::Byzantium), + fork_summary_for_slack(reports, Fork::Berlin), + fork_summary_for_slack(reports, Fork::Constantinople), + fork_summary_for_slack(reports, Fork::Paris), + fork_summary_for_slack(reports, Fork::Frontier), ) } -fn fork_summary_for_slack(reports: &[EFTestReport], fork: SpecId) -> String { +fn fork_summary_for_slack(reports: &[EFTestReport], fork: Fork) -> String { let fork_str: &str = fork.into(); let (fork_tests, fork_passed_tests, fork_success_percentage) = fork_statistics(reports, fork); format!(r#"*{fork_str}:* {fork_passed_tests}/{fork_tests} ({fork_success_percentage:.2}%)"#) @@ -173,22 +172,22 @@ pub fn summary_for_github(reports: &[EFTestReport]) -> String { let success_percentage = (total_passed as f64 / total_run as f64) * 100.0; format!( r#"Summary: {total_passed}/{total_run} ({success_percentage:.2}%)\n\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n"#, - fork_summary_for_github(reports, SpecId::PRAGUE), - fork_summary_for_github(reports, SpecId::CANCUN), - fork_summary_for_github(reports, SpecId::SHANGHAI), - fork_summary_for_github(reports, SpecId::HOMESTEAD), - fork_summary_for_github(reports, SpecId::ISTANBUL), - fork_summary_for_github(reports, SpecId::LONDON), - fork_summary_for_github(reports, SpecId::BYZANTIUM), - fork_summary_for_github(reports, SpecId::BERLIN), - fork_summary_for_github(reports, SpecId::CONSTANTINOPLE), - fork_summary_for_github(reports, SpecId::MERGE), - fork_summary_for_github(reports, SpecId::FRONTIER), + fork_summary_for_github(reports, Fork::Prague), + fork_summary_for_github(reports, Fork::Cancun), + fork_summary_for_github(reports, Fork::Shanghai), + fork_summary_for_github(reports, Fork::Homestead), + fork_summary_for_github(reports, Fork::Istanbul), + fork_summary_for_github(reports, Fork::London), + fork_summary_for_github(reports, Fork::Byzantium), + fork_summary_for_github(reports, Fork::Berlin), + fork_summary_for_github(reports, Fork::Constantinople), + fork_summary_for_github(reports, Fork::Paris), + fork_summary_for_github(reports, Fork::Frontier), ) } -fn fork_summary_for_github(reports: &[EFTestReport], fork: SpecId) -> String { - let fork_str: &str = fork.into(); +fn fork_summary_for_github(reports: &[EFTestReport], fork: Fork) -> String { + let fork_str:&str = fork.into(); let (fork_tests, fork_passed_tests, fork_success_percentage) = fork_statistics(reports, fork); format!("{fork_str}: {fork_passed_tests}/{fork_tests} ({fork_success_percentage:.2}%)") } @@ -221,22 +220,22 @@ pub fn summary_for_shell(reports: &[EFTestReport]) -> String { } else { format!("{}", total_passed).red() }, - fork_summary_shell(reports, SpecId::PRAGUE), - fork_summary_shell(reports, SpecId::CANCUN), - fork_summary_shell(reports, SpecId::SHANGHAI), - fork_summary_shell(reports, SpecId::MERGE), - fork_summary_shell(reports, SpecId::LONDON), - fork_summary_shell(reports, SpecId::BERLIN), - fork_summary_shell(reports, SpecId::ISTANBUL), - fork_summary_shell(reports, SpecId::CONSTANTINOPLE), - fork_summary_shell(reports, SpecId::BYZANTIUM), - fork_summary_shell(reports, SpecId::HOMESTEAD), - fork_summary_shell(reports, SpecId::FRONTIER), + fork_summary_shell(reports, Fork::Prague), + fork_summary_shell(reports, Fork::Cancun), + fork_summary_shell(reports, Fork::Shanghai), + fork_summary_shell(reports, Fork::Paris), + fork_summary_shell(reports, Fork::London), + fork_summary_shell(reports, Fork::Berlin), + fork_summary_shell(reports, Fork::Istanbul), + fork_summary_shell(reports, Fork::Constantinople), + fork_summary_shell(reports, Fork::Byzantium), + fork_summary_shell(reports, Fork::Homestead), + fork_summary_shell(reports, Fork::Frontier), test_dir_summary_for_shell(reports), ) } -fn fork_summary_shell(reports: &[EFTestReport], fork: SpecId) -> String { +fn fork_summary_shell(reports: &[EFTestReport], fork: Fork) -> String { let fork_str: &str = fork.into(); let (fork_tests, fork_passed_tests, fork_success_percentage) = fork_statistics(reports, fork); format!( @@ -252,7 +251,7 @@ fn fork_summary_shell(reports: &[EFTestReport], fork: SpecId) -> String { ) } -fn fork_statistics(reports: &[EFTestReport], fork: SpecId) -> (usize, usize, f64) { +fn fork_statistics(reports: &[EFTestReport], fork: Fork) -> (usize, usize, f64) { let fork_tests = reports.iter().filter(|report| report.fork == fork).count(); let fork_passed_tests = reports .iter() @@ -312,17 +311,17 @@ impl Display for EFTestsReport { let total_run = self.0.len(); writeln!(f, "Summary: {total_passed}/{total_run}",)?; writeln!(f)?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::PRAGUE))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::CANCUN))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::SHANGHAI))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::HOMESTEAD))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::ISTANBUL))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::LONDON))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::BYZANTIUM))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::BERLIN))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::CONSTANTINOPLE))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::MERGE))?; - writeln!(f, "{}", fork_summary_shell(&self.0, SpecId::FRONTIER))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Prague))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Cancun))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Shanghai))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Homestead))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Istanbul))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::London))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Byzantium))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Berlin))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Constantinople))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Paris))?; + writeln!(f, "{}", fork_summary_shell(&self.0, Fork::Frontier))?; writeln!(f)?; writeln!(f, "Failed tests:")?; writeln!(f)?; @@ -397,14 +396,14 @@ pub struct EFTestReport { pub name: String, pub dir: String, pub test_hash: H256, - pub fork: SpecId, + pub fork: Fork, pub skipped: bool, pub failed_vectors: HashMap, pub re_run_report: Option, } impl EFTestReport { - pub fn new(name: String, dir: String, test_hash: H256, fork: SpecId) -> Self { + pub fn new(name: String, dir: String, test_hash: H256, fork: Fork) -> Self { EFTestReport { name, dir, diff --git a/cmd/ef_tests/levm/runner/levm_runner.rs b/cmd/ef_tests/levm/runner/levm_runner.rs index 44ee12e12b..72ade8ca6f 100644 --- a/cmd/ef_tests/levm/runner/levm_runner.rs +++ b/cmd/ef_tests/levm/runner/levm_runner.rs @@ -110,7 +110,7 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result( .with_block_env(block_env) .with_tx_env(tx_env) .modify_cfg_env(|cfg| cfg.chain_id = chain_spec.chain_id) - .with_spec_id(test.fork()) + .with_spec_id(fork_to_spec_id(test.fork())) .with_external_context( RevmTracerEip3155::new(Box::new(std::io::stderr())).without_summary(), ); diff --git a/cmd/ef_tests/levm/types.rs b/cmd/ef_tests/levm/types.rs index 5295f7f4da..80219ed677 100644 --- a/cmd/ef_tests/levm/types.rs +++ b/cmd/ef_tests/levm/types.rs @@ -11,10 +11,9 @@ use crate::{ }; use bytes::Bytes; use ethrex_core::{ - types::{Genesis, GenesisAccount, TxKind}, + types::{Fork, Genesis, GenesisAccount, TxKind}, Address, H256, U256, }; -use ethrex_vm::SpecId; use serde::Deserialize; use std::collections::HashMap; @@ -33,21 +32,21 @@ pub struct EFTest { } impl EFTest { - pub fn fork(&self) -> SpecId { + pub fn fork(&self) -> Fork { match &self.post { - EFTestPost::Prague(_) => SpecId::PRAGUE, - EFTestPost::Cancun(_) => SpecId::CANCUN, - EFTestPost::Shanghai(_) => SpecId::SHANGHAI, - EFTestPost::Homestead(_) => SpecId::HOMESTEAD, - EFTestPost::Istanbul(_) => SpecId::ISTANBUL, - EFTestPost::London(_) => SpecId::LONDON, - EFTestPost::Byzantium(_) => SpecId::BYZANTIUM, - EFTestPost::Berlin(_) => SpecId::BERLIN, + EFTestPost::Prague(_) => Fork::Prague, + EFTestPost::Cancun(_) => Fork::Cancun, + EFTestPost::Shanghai(_) => Fork::Shanghai, + EFTestPost::Homestead(_) => Fork::Homestead, + EFTestPost::Istanbul(_) => Fork::Istanbul, + EFTestPost::London(_) => Fork::London, + EFTestPost::Byzantium(_) => Fork::Byzantium, + EFTestPost::Berlin(_) => Fork::Berlin, EFTestPost::Constantinople(_) | EFTestPost::ConstantinopleFix(_) => { - SpecId::CONSTANTINOPLE + Fork::Constantinople } - EFTestPost::Paris(_) => SpecId::MERGE, - EFTestPost::Frontier(_) => SpecId::FRONTIER, + EFTestPost::Paris(_) => Fork::Paris, + EFTestPost::Frontier(_) => Fork::Frontier, } } } diff --git a/crates/common/types/genesis.rs b/crates/common/types/genesis.rs index 4bebd49ae7..c00adf0181 100644 --- a/crates/common/types/genesis.rs +++ b/crates/common/types/genesis.rs @@ -87,28 +87,29 @@ pub struct ChainConfig { pub terminal_total_difficulty_passed: bool, } +#[repr(u8)] #[derive(Debug, PartialEq, PartialOrd, Default, Clone, Copy, Serialize, Deserialize)] pub enum Fork { - Frontier = 0, // Frontier 0 - FrontierThawing = 1, // Frontier Thawing 200000 - Homestead = 2, // Homestead 1150000 - DaoFork = 3, // DAO Fork 1920000 - Tangerine = 4, // Tangerine Whistle 2463000 - SpuriousDragon = 5, // Spurious Dragon 2675000 - Byzantium = 6, // Byzantium 4370000 - Constantinople = 7, // Constantinople 7280000 is overwritten with PETERSBURG - Petersburg = 8, // Petersburg 7280000 - Istanbul = 9, // Istanbul 9069000 - MuirGlacier = 10, // Muir Glacier 9200000 - Berlin = 11, // Berlin 12244000 - London = 12, // London 12965000 - ArrowGlacier = 13, // Arrow Glacier 13773000 - GrayGlacier = 14, // Gray Glacier 15050000 - Paris = 15, // Paris/Merge 15537394 (TTD: 58750000000000000000000) - Shanghai = 16, // Shanghai 17034870 (Timestamp: 1681338455) + Frontier = 0, + FrontierThawing = 1, + Homestead = 2, + DaoFork = 3, + Tangerine = 4, + SpuriousDragon = 5, + Byzantium = 6, + Constantinople = 7, + Petersburg = 8, + Istanbul = 9, + MuirGlacier = 10, + Berlin = 11, + London = 12, + ArrowGlacier = 13, + GrayGlacier = 14, + Paris = 15, + Shanghai = 16, #[default] - Cancun = 17, // Cancun 19426587 (Timestamp: 1710338135) - Prague = 18, // Prague TBD + Cancun = 17, + Prague = 18, } impl From for &str { @@ -137,6 +138,33 @@ impl From for &str { } } +impl From<&str> for Fork { + fn from(s: &str) -> Self { + match s { + "Frontier" => Fork::Frontier, + "FrontierThawing" => Fork::FrontierThawing, + "Homestead" => Fork::Homestead, + "DaoFork" => Fork::DaoFork, + "Tangerine" => Fork::Tangerine, + "SpuriousDragon" => Fork::SpuriousDragon, + "Byzantium" => Fork::Byzantium, + "Constantinople" => Fork::Constantinople, + "Petersburg" => Fork::Petersburg, + "Istanbul" => Fork::Istanbul, + "MuirGlacier" => Fork::MuirGlacier, + "Berlin" => Fork::Berlin, + "London" => Fork::London, + "ArrowGlacier" => Fork::ArrowGlacier, + "GrayGlacier" => Fork::GrayGlacier, + "Paris" => Fork::Paris, + "Shanghai" => Fork::Shanghai, + "Cancun" => Fork::Cancun, + "Prague" => Fork::Prague, + _ => Fork::Cancun, + } + } +} + impl ChainConfig { pub fn is_shanghai_activated(&self, block_timestamp: u64) -> bool { self.shanghai_time diff --git a/crates/vm/levm/src/environment.rs b/crates/vm/levm/src/environment.rs index 44dff30389..3600b841c8 100644 --- a/crates/vm/levm/src/environment.rs +++ b/crates/vm/levm/src/environment.rs @@ -12,7 +12,7 @@ pub struct Environment { pub origin: Address, pub refunded_gas: u64, pub gas_limit: u64, - pub spec_id: Fork, + pub fork: Fork, pub block_number: U256, pub coinbase: Address, pub timestamp: U256, diff --git a/crates/vm/levm/src/gas_cost.rs b/crates/vm/levm/src/gas_cost.rs index a471ba362a..9ddaac4b5d 100644 --- a/crates/vm/levm/src/gas_cost.rs +++ b/crates/vm/levm/src/gas_cost.rs @@ -8,7 +8,6 @@ use bytes::Bytes; /// Contains the gas costs of the EVM instructions use ethrex_core::{types::Fork, U256}; use num_bigint::BigUint; -use revm_primitives::SpecId; // Opcodes cost pub const STOP: u64 = 0; @@ -464,14 +463,14 @@ pub fn create( new_memory_size: usize, current_memory_size: usize, code_size_in_memory: usize, - spec_id: Fork, + fork: Fork, ) -> Result { compute_gas_create( new_memory_size, current_memory_size, code_size_in_memory, false, - spec_id, + fork, ) } @@ -479,14 +478,14 @@ pub fn create_2( new_memory_size: usize, current_memory_size: usize, code_size_in_memory: usize, - spec_id: Fork, + fork: Fork, ) -> Result { compute_gas_create( new_memory_size, current_memory_size, code_size_in_memory, true, - spec_id, + fork, ) } @@ -495,7 +494,7 @@ fn compute_gas_create( current_memory_size: usize, code_size_in_memory: usize, is_create_2: bool, - spec_id: Fork, + fork: Fork, ) -> Result { let minimum_word_size = (code_size_in_memory .checked_add(31) @@ -508,7 +507,7 @@ fn compute_gas_create( .map_err(|_| VMError::VeryLargeNumber)?; // [EIP-3860] - Apply extra gas cost of 2 for every 32-byte chunk of initcode - let init_code_cost = if spec_id >= Fork::Shanghai { + let init_code_cost = if fork >= Fork::Shanghai { minimum_word_size .checked_mul(INIT_CODE_WORD_COST) .ok_or(OutOfGasError::GasCostOverflow)? // will not panic since it's 2 @@ -560,13 +559,13 @@ pub fn selfdestruct( Ok(gas_cost) } -pub fn tx_calldata(calldata: &Bytes, spec_id: Fork) -> Result { +pub fn tx_calldata(calldata: &Bytes, fork: Fork) -> Result { // This cost applies both for call and create // 4 gas for each zero byte in the transaction data 16 gas for each non-zero byte in the transaction. let mut calldata_cost: u64 = 0; for byte in calldata { calldata_cost = if *byte != 0 { - if spec_id >= Fork::Istanbul { + if fork >= Fork::Istanbul { calldata_cost .checked_add(CALLDATA_COST_NON_ZERO_BYTE) .ok_or(OutOfGasError::GasUsedOverflow)? @@ -681,7 +680,7 @@ pub fn call( value_to_transfer: U256, gas_from_stack: U256, gas_left: u64, - spec_id: Fork, + fork: Fork, ) -> Result<(u64, u64), VMError> { let memory_expansion_cost = memory::expansion_cost(new_memory_size, current_memory_size)?; @@ -689,7 +688,7 @@ pub fn call( address_was_cold, CALL_STATIC, CALL_COLD_DYNAMIC, - if spec_id >= Fork::Berlin { + if fork >= Fork::Berlin { CALL_WARM_DYNAMIC } else { //https://eips.ethereum.org/EIPS/eip-2929 @@ -966,7 +965,7 @@ pub fn modexp( base_size: usize, exponent_size: usize, modulus_size: usize, - spec_id: Fork, + fork: Fork, ) -> Result { let base_size: u64 = base_size .try_into() @@ -980,7 +979,7 @@ pub fn modexp( let max_length = base_size.max(modulus_size); - if spec_id >= Fork::Berlin { + if fork >= Fork::Berlin { modexp_eip2565(max_length, exponent_first_32_bytes, exponent_size) } else { modexp_eip198(max_length, exponent_first_32_bytes, exponent_size) diff --git a/crates/vm/levm/src/opcode_handlers/block.rs b/crates/vm/levm/src/opcode_handlers/block.rs index 52615b04cb..c310d0ec34 100644 --- a/crates/vm/levm/src/opcode_handlers/block.rs +++ b/crates/vm/levm/src/opcode_handlers/block.rs @@ -9,7 +9,6 @@ use ethrex_core::{ types::{Fork, BLOB_BASE_FEE_UPDATE_FRACTION, MIN_BASE_FEE_PER_BLOB_GAS}, U256, }; -use revm_primitives::SpecId; // Block Information (11) // Opcodes: BLOCKHASH, COINBASE, TIMESTAMP, NUMBER, PREVRANDAO, GASLIMIT, CHAINID, SELFBALANCE, BASEFEE, BLOBHASH, BLOBBASEFEE @@ -162,7 +161,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-4844] - BLOBHASH is only available from CANCUN - if self.env.spec_id < Fork::Cancun { + if self.env.fork < Fork::Cancun { return Err(VMError::InvalidOpcode); } @@ -209,7 +208,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-7516] - BLOBBASEFEE is only available from CANCUN - if self.env.spec_id < Fork::Cancun { + if self.env.fork < Fork::Cancun { return Err(VMError::InvalidOpcode); } self.increase_consumed_gas(current_call_frame, gas_cost::BLOBBASEFEE)?; diff --git a/crates/vm/levm/src/opcode_handlers/push.rs b/crates/vm/levm/src/opcode_handlers/push.rs index bd109c1dd0..fa5cbde2a3 100644 --- a/crates/vm/levm/src/opcode_handlers/push.rs +++ b/crates/vm/levm/src/opcode_handlers/push.rs @@ -6,7 +6,6 @@ use crate::{ vm::VM, }; use ethrex_core::{types::Fork, U256}; -use revm_primitives::SpecId; // Push Operations // Opcodes: PUSH0, PUSH1 ... PUSH32 @@ -38,7 +37,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-3855] - PUSH0 is only available from SHANGHAI - if self.env.spec_id < Fork::Shanghai { + if self.env.fork < Fork::Shanghai { return Err(VMError::InvalidOpcode); } diff --git a/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs b/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs index d7f8de8bec..eb5b0a95f8 100644 --- a/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs +++ b/crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs @@ -7,7 +7,6 @@ use crate::{ vm::VM, }; use ethrex_core::{types::Fork, H256, U256}; -use revm_primitives::SpecId; // Stack, Memory, Storage and Flow Operations (15) // Opcodes: POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE, JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, TLOAD, TSTORE, MCOPY @@ -26,7 +25,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-1153] - TLOAD is only available from CANCUN - if self.env.spec_id < Fork::Cancun { + if self.env.fork < Fork::Cancun { return Err(VMError::InvalidOpcode); } @@ -50,7 +49,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-1153] - TLOAD is only available from CANCUN - if self.env.spec_id < Fork::Cancun { + if self.env.fork < Fork::Cancun { return Err(VMError::InvalidOpcode); } @@ -264,7 +263,7 @@ impl VM { current_call_frame: &mut CallFrame, ) -> Result { // [EIP-5656] - MCOPY is only available from CANCUN - if self.env.spec_id < Fork::Cancun { + if self.env.fork < Fork::Cancun { return Err(VMError::InvalidOpcode); } diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index 985f793db4..12c64b4d02 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -10,7 +10,6 @@ use crate::{ }; use bytes::Bytes; use ethrex_core::{types::Fork, Address, U256}; -use revm_primitives::SpecId; // System Operations (10) // Opcodes: CREATE, CALL, CALLCODE, RETURN, DELEGATECALL, CREATE2, STATICCALL, REVERT, INVALID, SELFDESTRUCT @@ -64,7 +63,7 @@ impl VM { value_to_transfer, gas, gas_left, - self.env.spec_id, + self.env.fork, )?; self.increase_consumed_gas(current_call_frame, cost)?; @@ -342,7 +341,7 @@ impl VM { new_size, current_call_frame.memory.len(), code_size_in_memory, - self.env.spec_id, + self.env.fork, )?, )?; @@ -378,7 +377,7 @@ impl VM { new_size, current_call_frame.memory.len(), code_size_in_memory, - self.env.spec_id, + self.env.fork, )?, )?; @@ -468,7 +467,7 @@ impl VM { )?; // [EIP-6780] - SELFDESTRUCT only in same transaction from CANCUN - if self.env.spec_id >= Fork::Cancun { + if self.env.fork >= Fork::Cancun { self.increase_account_balance(target_address, balance_to_transfer)?; self.decrease_account_balance(current_call_frame.to, balance_to_transfer)?; @@ -512,7 +511,7 @@ impl VM { return Err(VMError::OpcodeNotAllowedInStaticContext); } // 2. [EIP-3860] - Cant exceed init code max size - if code_size_in_memory > INIT_CODE_MAX_SIZE && self.env.spec_id >= Fork::Shanghai { + if code_size_in_memory > INIT_CODE_MAX_SIZE && self.env.fork >= Fork::Shanghai { return Err(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow)); } diff --git a/crates/vm/levm/src/precompiles.rs b/crates/vm/levm/src/precompiles.rs index 80d6817558..8a2d86e3d0 100644 --- a/crates/vm/levm/src/precompiles.rs +++ b/crates/vm/levm/src/precompiles.rs @@ -32,7 +32,6 @@ use lambdaworks_math::{ }; use libsecp256k1::{self, Message, RecoveryId, Signature}; use num_bigint::BigUint; -use revm_primitives::SpecId; use sha3::Digest; use std::ops::Mul; @@ -176,14 +175,14 @@ const FP2_ZERO_MAPPED_TO_G2: [u8; 256] = [ pub const G1_POINT_AT_INFINITY: [u8; 128] = [0_u8; 128]; pub const G2_POINT_AT_INFINITY: [u8; 256] = [0_u8; 256]; -pub fn is_precompile(callee_address: &Address, spec_id: Fork) -> bool { +pub fn is_precompile(callee_address: &Address, fork: Fork) -> bool { // Cancun specs is the only one that allows point evaluation precompile - if *callee_address == POINT_EVALUATION_ADDRESS && spec_id < Fork::Cancun { + if *callee_address == POINT_EVALUATION_ADDRESS && fork < Fork::Cancun { return false; } // Prague or newers forks should only use this precompiles // https://eips.ethereum.org/EIPS/eip-2537 - if PRECOMPILES_POST_CANCUN.contains(callee_address) && spec_id < Fork::Prague { + if PRECOMPILES_POST_CANCUN.contains(callee_address) && fork < Fork::Prague { return false; } @@ -192,7 +191,7 @@ pub fn is_precompile(callee_address: &Address, spec_id: Fork) -> bool { pub fn execute_precompile( current_call_frame: &mut CallFrame, - spec_id: Fork, + fork: Fork, ) -> Result { let callee_address = current_call_frame.code_address; let gas_for_call = current_call_frame @@ -218,7 +217,7 @@ pub fn execute_precompile( ¤t_call_frame.calldata, gas_for_call, consumed_gas, - spec_id, + fork, )?, address if address == ECADD_ADDRESS => { ecadd(¤t_call_frame.calldata, gas_for_call, consumed_gas)? @@ -400,7 +399,7 @@ pub fn modexp( calldata: &Bytes, gas_for_call: u64, consumed_gas: &mut u64, - spec_id: Fork, + fork: Fork, ) -> Result { // If calldata does not reach the required length, we should fill the rest with zeros let calldata = fill_with_zeros(calldata, 96)?; @@ -426,7 +425,7 @@ pub fn modexp( if base_size == U256::zero() && modulus_size == U256::zero() { // On Berlin or newer there is a floor cost for the modexp precompile // On older versions in this return there is no cost added, see more https://eips.ethereum.org/EIPS/eip-2565 - if spec_id >= Fork::Berlin { + if fork >= Fork::Berlin { increase_precompile_consumed_gas(gas_for_call, MODEXP_STATIC_COST, consumed_gas)?; } return Ok(Bytes::new()); @@ -470,7 +469,7 @@ pub fn modexp( base_size, exponent_size, modulus_size, - spec_id, + fork, )?; increase_precompile_consumed_gas(gas_for_call, gas_cost, consumed_gas)?; diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index f261e525fd..81bb584743 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -28,7 +28,6 @@ use ethrex_core::{types::{Fork, TxKind}, Address, H256, U256}; use ethrex_rlp; use ethrex_rlp::encode::RLPEncode; use keccak_hash::keccak; -use revm_primitives::SpecId; use sha3::{Digest, Keccak256}; use std::{ cmp::max, @@ -155,7 +154,7 @@ impl VM { let mut default_touched_accounts = HashSet::from_iter([env.origin].iter().cloned()); // [EIP-3651] - Add coinbase to cache if the spec is SHANGHAI or higher - if env.spec_id >= Fork::Shanghai { + if env.fork >= Fork::Shanghai { default_touched_accounts.insert(env.coinbase); } @@ -173,7 +172,7 @@ impl VM { // Add precompiled contracts addresses to cache. // TODO: Use the addresses from precompiles.rs in a future - let max_precompile_address = match env.spec_id { + let max_precompile_address = match env.fork { spec if spec >= Fork::Prague => SIZE_PRECOMPILES_PRAGUE, spec if spec >= Fork::Cancun => SIZE_PRECOMPILES_CANCUN, spec if spec < Fork::Cancun => SIZE_PRECOMPILES_PRE_CANCUN, @@ -280,8 +279,8 @@ impl VM { self.env.transient_storage.clone(), ); - if is_precompile(¤t_call_frame.code_address, self.env.spec_id) { - let precompile_result = execute_precompile(current_call_frame, self.env.spec_id); + if is_precompile(¤t_call_frame.code_address, self.env.fork) { + let precompile_result = execute_precompile(current_call_frame, self.env.fork); match precompile_result { Ok(output) => { @@ -574,7 +573,7 @@ impl VM { // Calldata Cost // 4 gas for each zero byte in the transaction data 16 gas for each non-zero byte in the transaction. - let calldata_cost = gas_cost::tx_calldata(&initial_call_frame.calldata, self.env.spec_id) + let calldata_cost = gas_cost::tx_calldata(&initial_call_frame.calldata, self.env.fork) .map_err(VMError::OutOfGas)?; intrinsic_gas = intrinsic_gas @@ -636,13 +635,13 @@ impl VM { } fn gas_used(&self, current_call_frame: &mut CallFrame) -> Result { - if self.env.spec_id >= Fork::Prague { + if self.env.fork >= Fork::Prague { // tokens_in_calldata = nonzero_bytes_in_calldata * 4 + zero_bytes_in_calldata // tx_calldata = nonzero_bytes_in_calldata * 16 + zero_bytes_in_calldata * 4 // this is actually tokens_in_calldata * STANDARD_TOKEN_COST // see it in https://eips.ethereum.org/EIPS/eip-7623 let tokens_in_calldata: u64 = - gas_cost::tx_calldata(¤t_call_frame.calldata, self.env.spec_id) + gas_cost::tx_calldata(¤t_call_frame.calldata, self.env.fork) .map_err(VMError::OutOfGas)? .checked_div(STANDARD_TOKEN_COST) .ok_or(VMError::Internal(InternalError::DivisionError))?; @@ -729,13 +728,13 @@ impl VM { let sender_address = self.env.origin; let sender_account = self.get_account(sender_address); - if self.env.spec_id >= Fork::Prague { + if self.env.fork >= Fork::Prague { // check for gas limit is grater or equal than the minimum required let intrinsic_gas: u64 = self.get_intrinsic_gas(initial_call_frame)?; // calldata_cost = tokens_in_calldata * 4 let calldata_cost: u64 = - gas_cost::tx_calldata(&initial_call_frame.calldata, self.env.spec_id) + gas_cost::tx_calldata(&initial_call_frame.calldata, self.env.fork) .map_err(VMError::OutOfGas)?; // same as calculated in gas_used() @@ -847,7 +846,7 @@ impl VM { if self.is_create() { // [EIP-3860] - INITCODE_SIZE_EXCEEDED if initial_call_frame.calldata.len() > INIT_CODE_MAX_SIZE - && self.env.spec_id >= Fork::Shanghai + && self.env.fork >= Fork::Shanghai { return Err(VMError::TxValidation( TxValidationError::InitcodeSizeExceeded, @@ -889,7 +888,7 @@ impl VM { // Transaction is type 3 if tx_max_fee_per_blob_gas is Some if self.env.tx_max_fee_per_blob_gas.is_some() { // (11) TYPE_3_TX_PRE_FORK - if self.env.spec_id < Fork::Cancun { + if self.env.fork < Fork::Cancun { return Err(VMError::TxValidation(TxValidationError::Type3TxPreFork)); } @@ -1149,7 +1148,7 @@ impl VM { ) -> Result<(StorageSlot, bool), VMError> { // [EIP-2929] - Introduced conditional tracking of accessed storage slots for Berlin and later specs. let mut storage_slot_was_cold = false; - if self.env.spec_id >= Fork::Berlin { + if self.env.fork >= Fork::Berlin { storage_slot_was_cold = self .accrued_substate .touched_storage_slots diff --git a/crates/vm/vm.rs b/crates/vm/vm.rs index c21f806c0d..e56df80843 100644 --- a/crates/vm/vm.rs +++ b/crates/vm/vm.rs @@ -94,7 +94,7 @@ cfg_if::cfg_if! { pub fn beacon_root_contract_call_levm( store_wrapper: Arc, block_header: &BlockHeader, - spec_id: Fork, + fork: Fork, ) -> Result { lazy_static! { static ref SYSTEM_ADDRESS: Address = @@ -125,7 +125,7 @@ cfg_if::cfg_if! { block_blob_gas_used: block_header.blob_gas_used.map(U256::from), block_gas_limit: 30_000_000, transient_storage: HashMap::new(), - spec_id, + fork, ..Default::default() }; @@ -292,7 +292,7 @@ cfg_if::cfg_if! { block_header: &BlockHeader, db: Arc, block_cache: CacheDB, - spec_id: Fork + fork: Fork ) -> Result { let gas_price : U256 = tx.effective_gas_price(block_header.base_fee_per_gas).ok_or(VMError::InvalidTransaction)?.into(); @@ -300,7 +300,7 @@ cfg_if::cfg_if! { origin: tx.sender(), refunded_gas: 0, gas_limit: tx.gas_limit(), - spec_id, + fork, block_number: block_header.number.into(), coinbase: block_header.coinbase, timestamp: block_header.timestamp.into(), @@ -981,27 +981,7 @@ fn access_list_inspector( /// Returns the spec id according to the block timestamp and the stored chain config /// WARNING: Assumes at least Merge fork is active pub fn spec_id(chain_config: &ChainConfig, block_timestamp: u64) -> SpecId { - match chain_config.get_fork(block_timestamp) { - Fork::Cancun => SpecId::CANCUN, - Fork::Shanghai => SpecId::SHANGHAI, - Fork::Paris => SpecId::MERGE, - Fork::Istanbul => SpecId::ISTANBUL, - Fork::Berlin => SpecId::BERLIN, - Fork::Prague => SpecId::PRAGUE, - Fork::Frontier => todo!(), - Fork::FrontierThawing => todo!(), - Fork::Homestead => todo!(), - Fork::DaoFork => todo!(), - Fork::Tangerine => todo!(), - Fork::SpuriousDragon => todo!(), - Fork::Byzantium => todo!(), - Fork::Constantinople => todo!(), - Fork::Petersburg => todo!(), - Fork::MuirGlacier => todo!(), - Fork::London => todo!(), - Fork::ArrowGlacier => todo!(), - Fork::GrayGlacier => todo!(), - } + fork_to_spec_id(chain_config.get_fork(block_timestamp)) } pub fn fork_to_spec_id(fork: Fork) -> SpecId {