diff --git a/etherlink/kernel_evm/kernel/src/block.rs b/etherlink/kernel_evm/kernel/src/block.rs index 36b60e409572d3ef4b28776469bf5d1db040bca9..aee0b7b4c91e723639bcc130fcf7b8b7099ee56d 100644 --- a/etherlink/kernel_evm/kernel/src/block.rs +++ b/etherlink/kernel_evm/kernel/src/block.rs @@ -471,11 +471,11 @@ fn promote_block( pub fn produce( host: &mut Host, - chain_id: U256, config: &mut Configuration, sequencer_pool_address: Option, tracer_input: Option, ) -> Result { + let chain_id = config.chain_config.chain_id; let minimum_base_fee_per_gas = crate::retrieve_minimum_base_fee_per_gas(host)?; let da_fee_per_byte = crate::retrieve_da_fee(host)?; @@ -606,6 +606,7 @@ mod tests { use crate::blueprint_storage::read_next_blueprint; use crate::blueprint_storage::store_inbox_blueprint; use crate::blueprint_storage::store_inbox_blueprint_by_number; + use crate::configuration::ChainConfig; use crate::fees::DA_FEE_PER_BYTE; use crate::fees::MINIMUM_BASE_FEE_PER_GAS; use crate::inbox::Transaction; @@ -679,6 +680,13 @@ mod tests { const DUMMY_BASE_FEE_PER_GAS: u64 = MINIMUM_BASE_FEE_PER_GAS; const DUMMY_DA_FEE: u64 = DA_FEE_PER_BYTE; + fn dummy_configuration() -> Configuration { + Configuration { + chain_config: ChainConfig::new_evm_config(DUMMY_CHAIN_ID), + ..Configuration::default() + } + } + fn dummy_block_fees() -> BlockFees { BlockFees::new( U256::from(DUMMY_BASE_FEE_PER_GAS), @@ -847,14 +855,8 @@ mod tests { ); store_block_fees(host, &dummy_block_fees()).unwrap(); - produce( - host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); } fn assert_current_block_reading_validity(host: &mut Host) { @@ -895,14 +897,8 @@ mod tests { U256::from(30000u64), ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); assert!( read_transaction_receipt_status(&mut host, &tx_hash).is_err(), @@ -940,14 +936,8 @@ mod tests { ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let status = read_transaction_receipt_status(&mut host, &tx_hash) .expect("Should have found receipt"); @@ -983,14 +973,8 @@ mod tests { ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let receipt = read_transaction_receipt(&mut host, &tx_hash) .expect("should have found receipt"); assert_eq!(TransactionStatus::Success, receipt.status); @@ -1065,23 +1049,11 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); // Produce block for blueprint containing transaction_0 - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); // Produce block for blueprint containing transaction_1 - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let dest_address = H160::from_str("423163e58aabec5daa3dd1130b759d24bef0f6ea").unwrap(); @@ -1132,14 +1104,8 @@ mod tests { ); store_block_fees(&mut host, &dummy_block_fees).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let receipt0 = read_transaction_receipt(&mut host, &tx_hash_0) .expect("should have found receipt"); let receipt1 = read_transaction_receipt(&mut host, &tx_hash_1) @@ -1192,14 +1158,8 @@ mod tests { ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let dest_address = H160::from_str("423163e58aabec5daa3dd1130b759d24bef0f6ea").unwrap(); @@ -1242,14 +1202,8 @@ mod tests { U256::from(10000000000000000000u64), ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let new_number_of_blocks_indexed = blocks_index.length(&host).unwrap(); @@ -1401,14 +1355,8 @@ mod tests { // Apply the transaction store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); assert!( read_transaction_receipt(&mut host, &tx_hash).is_err(), "Transaction is invalid, so should not have a receipt" @@ -1448,40 +1396,22 @@ mod tests { let blueprint = almost_empty_blueprint(); store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("Empty block should have been produced"); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("Empty block should have been produced"); check_current_block_number(&mut host, 0); // second block let blueprint = almost_empty_blueprint(); store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("Empty block should have been produced"); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("Empty block should have been produced"); check_current_block_number(&mut host, 1); // third block let blueprint = almost_empty_blueprint(); store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("Empty block should have been produced"); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("Empty block should have been produced"); check_current_block_number(&mut host, 2); } @@ -1613,13 +1543,12 @@ mod tests { let mut configuration = Configuration { limits, - ..Configuration::default() + ..dummy_configuration() }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - let computation_result = - produce(&mut host, DUMMY_CHAIN_ID, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = produce(&mut host, &mut configuration, None, None) + .expect("Should have produced"); // test no new block assert!( @@ -1694,18 +1623,16 @@ mod tests { let mut configuration = Configuration { limits, - ..Configuration::default() + ..dummy_configuration() }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - let computation_result = - produce(&mut host, DUMMY_CHAIN_ID, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = produce(&mut host, &mut configuration, None, None) + .expect("Should have produced"); // test reboot is set matches!(computation_result, ComputationResult::RebootNeeded); - let computation_result = - produce(&mut host, DUMMY_CHAIN_ID, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = produce(&mut host, &mut configuration, None, None) + .expect("Should have produced"); // test no new block assert_eq!( @@ -1786,14 +1713,8 @@ mod tests { U256::from(1_000_000_000_000_000_000u64), ); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); // See address at https://www.multicall3.com/ on in the github repository linked above let expected_created_contract = @@ -1854,7 +1775,7 @@ mod tests { let mut configuration = Configuration { limits, - ..Configuration::default() + ..dummy_configuration() }; // sanity check: no current block assert!( @@ -1862,8 +1783,7 @@ mod tests { "Should not have found current block number" ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce(&mut host, DUMMY_CHAIN_ID, &mut configuration, None, None) - .expect("Should have produced"); + produce(&mut host, &mut configuration, None, None).expect("Should have produced"); assert!( block_storage::read_current_number(&host).is_ok(), @@ -1877,8 +1797,7 @@ mod tests { store_inbox_blueprint(&mut host, blueprint(proposals_second_reboot)).unwrap(); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce(&mut host, DUMMY_CHAIN_ID, &mut configuration, None, None) - .expect("Should have produced"); + produce(&mut host, &mut configuration, None, None).expect("Should have produced"); let block = block_storage::read_current(&mut host).expect("Should have found a block"); @@ -1959,14 +1878,8 @@ mod tests { ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce( - &mut host, - DUMMY_CHAIN_ID, - &mut Configuration::default(), - None, - None, - ) - .expect("The block production failed."); + produce(&mut host, &mut dummy_configuration(), None, None) + .expect("The block production failed."); let receipt = read_transaction_receipt(&mut host, &tx_hash) .expect("Should have found receipt"); diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index 21cbea8ac1e12be4421a8059907c89a5d337b081..71b469061a2fabb77f5c9b776647ab08b0612be0 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -640,7 +640,7 @@ mod tests { use super::*; use crate::block::GENESIS_PARENT_HASH; - use crate::configuration::{DalConfiguration, Limits, TezosContracts}; + use crate::configuration::{ChainConfig, DalConfiguration, Limits, TezosContracts}; use crate::delayed_inbox::Hash; use crate::sequencer_blueprint::rlp_roundtrip; use crate::storage::store_last_info_per_level_timestamp; @@ -681,6 +681,7 @@ mod tests { }, limits: Limits::default(), enable_fa_bridge: false, + chain_config: ChainConfig::default(), garbage_collect_blocks: false, }; diff --git a/etherlink/kernel_evm/kernel/src/chains.rs b/etherlink/kernel_evm/kernel/src/chains.rs new file mode 100644 index 0000000000000000000000000000000000000000..54ee5fa7d40675479d21731d6edc511b4a8203bf --- /dev/null +++ b/etherlink/kernel_evm/kernel/src/chains.rs @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2025 Functori +// +// SPDX-License-Identifier: MIT + +#[derive(Clone, Copy, Debug)] +pub enum ChainFamily { + Evm, + Michelson, +} + +impl std::fmt::Display for ChainFamily { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Evm => write!(f, "EVM"), + Self::Michelson => write!(f, "Michelson"), + } + } +} diff --git a/etherlink/kernel_evm/kernel/src/configuration.rs b/etherlink/kernel_evm/kernel/src/configuration.rs index 7bca9d7f5a41671a31cb31f0f5b96af24156a393..b3b3639f83093fe8128479dcabacc3180d6d3336 100644 --- a/etherlink/kernel_evm/kernel/src/configuration.rs +++ b/etherlink/kernel_evm/kernel/src/configuration.rs @@ -1,5 +1,6 @@ use crate::{ blueprint_storage::DEFAULT_MAX_BLUEPRINT_LOOKAHEAD_IN_SECONDS, + chains::ChainFamily, delayed_inbox::DelayedInbox, storage::{ dal_slots, enable_dal, evm_node_flag, is_enable_fa_bridge, @@ -11,11 +12,16 @@ use crate::{ tick_model::constants::{MAXIMUM_GAS_LIMIT, MAX_ALLOWED_TICKS}, }; use evm_execution::read_ticketer; +use primitive_types::U256; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_evm_logging::{log, Level::*}; use tezos_evm_runtime::runtime::Runtime; use tezos_smart_rollup_encoding::public_key::PublicKey; +/// The chain id will need to be unique when the EVM rollup is deployed in +/// production. +pub const CHAIN_ID: u32 = 1337; + #[derive(Debug, Clone, Default)] pub struct DalConfiguration { pub slot_indices: Vec, @@ -53,6 +59,39 @@ impl std::fmt::Display for ConfigurationMode { } } +pub struct ChainConfig { + pub chain_id: U256, + pub chain_family: ChainFamily, +} + +impl Default for ChainConfig { + fn default() -> Self { + Self { + chain_id: U256::from(CHAIN_ID), + chain_family: ChainFamily::Evm, + } + } +} + +impl std::fmt::Display for ChainConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{{Chain id: {}, Chain informations: {}}}", + self.chain_id, self.chain_family + ) + } +} + +impl ChainConfig { + pub fn new_evm_config(chain_id: U256) -> Self { + ChainConfig { + chain_id, + chain_family: ChainFamily::Evm, + } + } +} + pub struct Limits { pub maximum_allowed_ticks: u64, pub maximum_gas_limit: u64, @@ -72,6 +111,7 @@ pub struct Configuration { pub mode: ConfigurationMode, pub limits: Limits, pub enable_fa_bridge: bool, + pub chain_config: ChainConfig, pub garbage_collect_blocks: bool, } @@ -82,6 +122,7 @@ impl Default for Configuration { mode: ConfigurationMode::Proxy, limits: Limits::default(), enable_fa_bridge: false, + chain_config: ChainConfig::default(), garbage_collect_blocks: false, } } @@ -91,8 +132,8 @@ impl std::fmt::Display for Configuration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "Tezos Contracts: {}, Mode: {}, Enable FA Bridge: {}, Garbage collect blocks: {}", - &self.tezos_contracts, &self.mode, &self.enable_fa_bridge, &self.garbage_collect_blocks + "Tezos Contracts: {}, Mode: {}, Enable FA Bridge: {}, Chain Config: {}, Garbage collect blocks: {}", + &self.tezos_contracts, &self.mode, &self.enable_fa_bridge, &self.chain_config, &self.garbage_collect_blocks ) } } @@ -194,13 +235,17 @@ fn fetch_dal_configuration(host: &mut Host) -> Option(host: &mut Host) -> Configuration { +pub fn fetch_configuration( + host: &mut Host, + chain_id: U256, +) -> Configuration { let tezos_contracts = fetch_tezos_contracts(host); let limits = fetch_limits(host); let sequencer = sequencer(host).unwrap_or_default(); let enable_fa_bridge = is_enable_fa_bridge(host).unwrap_or_default(); let dal: Option = fetch_dal_configuration(host); let evm_node_flag = evm_node_flag(host).unwrap_or(false); + let chain_config = ChainConfig::new_evm_config(chain_id); match sequencer { Some(sequencer) => { let delayed_bridge = read_delayed_transaction_bridge(host) @@ -229,6 +274,7 @@ pub fn fetch_configuration(host: &mut Host) -> Configuration { }, limits, enable_fa_bridge, + chain_config, garbage_collect_blocks: !evm_node_flag, }, Err(err) => { @@ -245,6 +291,7 @@ pub fn fetch_configuration(host: &mut Host) -> Configuration { mode: ConfigurationMode::Proxy, limits, enable_fa_bridge, + chain_config, garbage_collect_blocks: false, }, } diff --git a/etherlink/kernel_evm/kernel/src/lib.rs b/etherlink/kernel_evm/kernel/src/lib.rs index 9c66c77ef9d6cc99fbc6b0b93dba4c9ca31bdb2c..dd8511d510f633cf6dbc357a7824f6e868ffc341 100644 --- a/etherlink/kernel_evm/kernel/src/lib.rs +++ b/etherlink/kernel_evm/kernel/src/lib.rs @@ -5,7 +5,7 @@ // // SPDX-License-Identifier: MIT -use crate::configuration::{fetch_configuration, Configuration}; +use crate::configuration::{fetch_configuration, Configuration, CHAIN_ID}; use crate::error::Error; use crate::error::UpgradeProcessError::Fallback; use crate::migration::storage_migration; @@ -44,6 +44,7 @@ mod block_storage; mod blueprint; mod blueprint_storage; mod bridge; +mod chains; mod configuration; mod dal; mod dal_slot_import_signal; @@ -68,10 +69,6 @@ mod upgrade; extern crate alloc; -/// The chain id will need to be unique when the EVM rollup is deployed in -/// production. -pub const CHAIN_ID: u32 = 1337; - /// The configuration for the EVM execution. const CONFIG: Config = Config { // The current implementation doesn't support Cancun call stack limit of 256. @@ -241,7 +238,7 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { // in the storage. set_kernel_version(host)?; host.mark_for_reboot()?; - let configuration = fetch_configuration(host); + let configuration = fetch_configuration(host, chain_id); log!( host, Info, @@ -275,7 +272,7 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { let smart_rollup_address = host.reveal_metadata().raw_rollup_address; // 2. Fetch the per mode configuration of the kernel. Returns the default // configuration if it fails. - let mut configuration = fetch_configuration(host); + let mut configuration = fetch_configuration(host, chain_id); let sequencer_pool_address = read_sequencer_pool_address(host); // Run the stage one, this is a no-op if the inbox was already consumed @@ -298,7 +295,6 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { log!(host, Debug, "Entering stage two."); if let block::ComputationResult::RebootNeeded = block::produce( host, - chain_id, &mut configuration, sequencer_pool_address, trace_input, @@ -380,7 +376,7 @@ mod tests { use crate::block_storage; use crate::blueprint_storage::store_inbox_blueprint_by_number; - use crate::configuration::{Configuration, Limits}; + use crate::configuration::{ChainConfig, Configuration, Limits}; use crate::fees; use crate::main; use crate::parsing::RollupType; @@ -434,6 +430,13 @@ mod tests { const DUMMY_BASE_FEE_PER_GAS: u64 = 12345u64; const DUMMY_DA_FEE: u64 = 2_000_000_000_000u64; + fn dummy_configuration() -> Configuration { + Configuration { + chain_config: ChainConfig::new_evm_config(DUMMY_CHAIN_ID), + ..Configuration::default() + } + } + fn dummy_block_fees() -> BlockFees { BlockFees::new( DUMMY_BASE_FEE_PER_GAS.into(), @@ -605,7 +608,7 @@ mod tests { let mut configuration = Configuration { limits, - ..Configuration::default() + ..dummy_configuration() }; crate::storage::store_minimum_base_fee_per_gas( @@ -616,14 +619,9 @@ mod tests { crate::storage::store_da_fee(&mut host, block_fees.da_fee_per_byte()).unwrap(); // If the upgrade is started, it should raise an error - let computation_result = crate::block::produce( - &mut host, - DUMMY_CHAIN_ID, - &mut configuration, - None, - None, - ) - .expect("Should have produced"); + let computation_result = + crate::block::produce(&mut host, &mut configuration, None, None) + .expect("Should have produced"); // test there is a new block assert_eq!( diff --git a/etherlink/kernel_evm/kernel/src/reveal_storage.rs b/etherlink/kernel_evm/kernel/src/reveal_storage.rs index e0a57867aac162ee1bc81218b30547d1133b10d4..49a0db13293de3b96436331229b934d4c6934e52 100644 --- a/etherlink/kernel_evm/kernel/src/reveal_storage.rs +++ b/etherlink/kernel_evm/kernel/src/reveal_storage.rs @@ -6,8 +6,9 @@ //! chain into a new deployment. It is not tick-safe, and should obviously not be used in a //! production setup. -use crate::configuration::fetch_configuration; -use crate::storage::{ADMIN, SEQUENCER}; +use crate::configuration::{fetch_configuration, CHAIN_ID}; +use crate::storage::{read_chain_id, ADMIN, SEQUENCER}; +use primitive_types::U256; use rlp::{Decodable, DecoderError, Rlp}; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_ethereum::rlp_helpers::{decode_field, next, FromRlpBytes}; @@ -105,6 +106,7 @@ pub fn reveal_storage( log!(host, Info, "Done revealing"); - let configuration = fetch_configuration(host); + let chain_id = read_chain_id(host).unwrap_or(U256::from(CHAIN_ID)); + let configuration = fetch_configuration(host, chain_id); log!(host, Info, "Configuration {}", configuration); } diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index d86514d4999247dcd532510fce9e6ec766773ef8..7b060ba0c48dde588205e46d363302de37b5837d 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -190,7 +190,7 @@ pub fn fetch_blueprints( #[cfg(test)] mod tests { use crate::{ - configuration::Limits, + configuration::{ChainConfig, Limits}, dal_slot_import_signal::{ DalSlotImportSignals, DalSlotIndicesList, DalSlotIndicesOfLevel, UnsignedDalSlotSignals, @@ -268,6 +268,7 @@ mod tests { }, limits: Limits::default(), enable_fa_bridge: false, + chain_config: ChainConfig::default(), garbage_collect_blocks: false, } } @@ -282,6 +283,7 @@ mod tests { mode: ConfigurationMode::Proxy, limits: Limits::default(), enable_fa_bridge: false, + chain_config: ChainConfig::default(), garbage_collect_blocks: false, } }