From 729def7618864efe7aae3476f2ba6b27aac59fce Mon Sep 17 00:00:00 2001 From: Rodi-Can Bozman Date: Tue, 24 Jun 2025 14:12:49 +0200 Subject: [PATCH 1/3] Etherlink/Revm: avoid unecessary write access --- etherlink/kernel_latest/revm/src/world_state_handler.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/etherlink/kernel_latest/revm/src/world_state_handler.rs b/etherlink/kernel_latest/revm/src/world_state_handler.rs index 280fc2379c3f..cd338e4ef0aa 100644 --- a/etherlink/kernel_latest/revm/src/world_state_handler.rs +++ b/etherlink/kernel_latest/revm/src/world_state_handler.rs @@ -154,7 +154,14 @@ impl StorageAccount { Ok(()) } else { let code_hash = match code { - None => KECCAK_EMPTY, + // There is nothing to store if there's no code or if the legacy analyzed + // bytecode is just the STOP instruction (0x00). + None => return Ok(()), + Some(Bytecode::LegacyAnalyzed(bytecode)) + if bytecode.bytecode() == &Bytes::from_static(&[0]) => + { + return Ok(()) + } Some(code) => CodeStorage::add(host, code.original_byte_slice())?, }; let code_hash_bytes: [u8; 32] = code_hash.into(); -- GitLab From c2b3948ea8da4fd1319385d8410670ad483f9cb8 Mon Sep 17 00:00:00 2001 From: Rodi-Can Bozman Date: Tue, 24 Jun 2025 14:13:40 +0200 Subject: [PATCH 2/3] Etherlink/Revm: remove irrelavant check at validation --- etherlink/kernel_latest/kernel/src/apply.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/apply.rs b/etherlink/kernel_latest/kernel/src/apply.rs index 0c86df2ede52..e5344a661628 100644 --- a/etherlink/kernel_latest/kernel/src/apply.rs +++ b/etherlink/kernel_latest/kernel/src/apply.rs @@ -267,14 +267,10 @@ fn is_valid_ethereum_transaction_common( return Ok(Validity::InvalidPrePay); } - // TODO: Whenever the configuration/spec id of our EVM - // is properly propagated to REVM, re-adjust this condition. - if let Ok(false) = is_revm_enabled(host) { - // The sender does not have code, see EIP3607. - if code_exists { - log!(host, Benchmarking, "Transaction status: ERROR_CODE."); - return Ok(Validity::InvalidCode); - } + // The sender does not have code, see EIP3607. + if code_exists { + log!(host, Benchmarking, "Transaction status: ERROR_CODE."); + return Ok(Validity::InvalidCode); } // check that enough gas is provided to cover fees -- GitLab From a98c4c5a09aefd582b8258a633569b0ba606ba3f Mon Sep 17 00:00:00 2001 From: Rodi-Can Bozman Date: Tue, 24 Jun 2025 14:45:10 +0200 Subject: [PATCH 3/3] Etherlink/Revm: modular specid instead of hardcoded configuration The specid is properly propagated from our setted evm version. --- etherlink/kernel_latest/kernel/src/apply.rs | 15 ++++++++++ .../kernel_latest/kernel/src/simulation.rs | 1 + etherlink/kernel_latest/revm/src/lib.rs | 30 ++++++++++++++----- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/apply.rs b/etherlink/kernel_latest/kernel/src/apply.rs index e5344a661628..5a25cfffaf40 100644 --- a/etherlink/kernel_latest/kernel/src/apply.rs +++ b/etherlink/kernel_latest/kernel/src/apply.rs @@ -24,6 +24,7 @@ use evm_execution::trace::{ get_tracer_configuration, CallTrace, CallTracerConfig, CallTracerInput, TracerInput, }; use primitive_types::{H160, H256, U256}; +use revm::primitives::hardfork::SpecId; use std::borrow::Cow; use tezos_ethereum::access_list::{AccessList, AccessListItem}; use tezos_ethereum::block::BlockConstants; @@ -304,6 +305,17 @@ fn log_transaction_type(host: &Host, to: Option, data: &[u8 } } +fn config_to_revm_specid(config: &Config) -> revm::primitives::hardfork::SpecId { + // This is a hack-ish way to derive the spec id from Sputnik's + // configuration. The last case is the very first EVM version + // that we supported (:= Shanghai). + if config.selfdestruct_deprecated { + SpecId::CANCUN + } else { + SpecId::SHANGHAI + } +} + #[allow(clippy::too_many_arguments)] pub fn revm_run_transaction( host: &mut Host, @@ -315,6 +327,7 @@ pub fn revm_run_transaction( call_data: Vec, effective_gas_price: U256, access_list: AccessList, + config: &Config, ) -> Result, anyhow::Error> { // Disclaimer: // The following code is over-complicated because we maintain @@ -344,6 +357,7 @@ pub fn revm_run_transaction( }; match revm_etherlink::run_transaction( host, + config_to_revm_specid(config), block_constants, &mut world_state_handler, revm_etherlink::precompile_provider::EtherlinkPrecompiles::new(), @@ -554,6 +568,7 @@ fn apply_ethereum_transaction_common( call_data, effective_gas_price, transaction.access_list.clone(), + evm_configuration, ) { Ok(outcome) => outcome, Err(err) => { diff --git a/etherlink/kernel_latest/kernel/src/simulation.rs b/etherlink/kernel_latest/kernel/src/simulation.rs index e3ae25e7e784..0152ffca6ee2 100644 --- a/etherlink/kernel_latest/kernel/src/simulation.rs +++ b/etherlink/kernel_latest/kernel/src/simulation.rs @@ -489,6 +489,7 @@ impl Evaluation { gas_price, // TODO: Replace this by the decoded access lists if any. empty_access_list(), + evm_configuration, ) { Ok(Some(outcome)) if !self.with_da_fees => { let result: SimulationResult = diff --git a/etherlink/kernel_latest/revm/src/lib.rs b/etherlink/kernel_latest/revm/src/lib.rs index 656b32e14741..2e249d2c9876 100644 --- a/etherlink/kernel_latest/revm/src/lib.rs +++ b/etherlink/kernel_latest/revm/src/lib.rs @@ -34,8 +34,6 @@ mod code_storage; mod database; mod storage_helpers; -const DEFAULT_SPEC_ID: SpecId = SpecId::PRAGUE; - #[derive(Error, Debug)] pub enum Error { #[error("Runtime error: {0}")] @@ -145,10 +143,9 @@ fn evm<'a, Host: Runtime>( tx: &'a TxEnv, precompiles: EtherlinkPrecompiles, chain_id: u64, + spec_id: SpecId, ) -> EvmContext<'a, Host> { - let cfg = CfgEnv::new() - .with_chain_id(chain_id) - .with_spec(DEFAULT_SPEC_ID); + let cfg = CfgEnv::new().with_chain_id(chain_id).with_spec(spec_id); let context: Context< BlockEnv, @@ -158,7 +155,7 @@ fn evm<'a, Host: Runtime>( Journal>, (), LocalContext, - > = Context::new(db, DEFAULT_SPEC_ID); + > = Context::new(db, spec_id); let evm = context .with_block(block) @@ -172,6 +169,7 @@ fn evm<'a, Host: Runtime>( #[allow(clippy::too_many_arguments)] pub fn run_transaction<'a, Host: Runtime>( host: &'a mut Host, + spec_id: SpecId, block_constants: &'a BlockConstants, world_state_handler: &'a mut WorldStateHandler, precompiles: EtherlinkPrecompiles, @@ -211,6 +209,7 @@ pub fn run_transaction<'a, Host: Runtime>( &tx, precompiles, block_constants.chain_id.as_u64(), + spec_id, ); evm.db_mut().initialize_storage()?; @@ -249,7 +248,9 @@ mod test { }; use serde_json::Value; use tezos_evm_runtime::runtime::MockKernelHost; - use utilities::{block_constants_with_fees, block_constants_with_no_fees}; + use utilities::{ + block_constants_with_fees, block_constants_with_no_fees, DEFAULT_SPEC_ID, + }; use crate::world_state_handler::new_world_state_handler; use crate::{ @@ -259,7 +260,15 @@ mod test { mod utilities { use primitive_types::{H160 as PH160, U256 as PU256}; + use revm::primitives::hardfork::SpecId; use tezos_ethereum::block::{BlockConstants, BlockFees}; + + // The default SpecId is set to Cancun. + // It isn't modular like it was in the previous evm execution. + // This value was normally retrived from the old execution storage. Once we fully + // make the switch to REVM this part will become modular again. + // For now we keep it at Cancun which is the latest EVM version Etherlink supports. + pub(crate) const DEFAULT_SPEC_ID: SpecId = SpecId::CANCUN; const ETHERLINK_CHAIN_ID: u64 = 42793; pub(crate) fn block_constants_with_fees() -> BlockConstants { @@ -320,6 +329,7 @@ mod test { let execution_result = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, precompiles, @@ -399,6 +409,7 @@ mod test { let execution_result = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, precompiles, @@ -453,6 +464,7 @@ mod test { let result = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, precompiles, @@ -536,6 +548,7 @@ mod test { // Deploy XTZWithdrawal let ExecutionOutcome { result, .. } = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, EtherlinkPrecompiles::new(), @@ -567,6 +580,7 @@ mod test { withdrawals, } = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, EtherlinkPrecompiles::new(), @@ -624,6 +638,7 @@ mod test { let result_create = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, EtherlinkPrecompiles::new(), @@ -651,6 +666,7 @@ mod test { let result_call = run_transaction( &mut host, + DEFAULT_SPEC_ID, &block_constants, &mut world_state_handler, EtherlinkPrecompiles::new(), -- GitLab