From 2c7264027215444c31ee60178698d459f904c713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 26 Mar 2025 11:43:17 +0100 Subject: [PATCH 1/7] Etherlink/Kernel: extract chain config from the config record We want to allow having 3 possible types for the chain config (EvmChainConfig, MichelsonChainConfig, and an enum wrapping both cases simply named ChainConfig). Updating a field in a record to change its type is syntactically too heavy compared to simply passing the chain config alongside the config when we need both. --- etherlink/kernel_latest/kernel/src/block.rs | 142 +++++++++++------- .../kernel/src/blueprint_storage.rs | 4 +- .../kernel_latest/kernel/src/configuration.rs | 15 +- etherlink/kernel_latest/kernel/src/lib.rs | 54 ++++--- .../kernel/src/reveal_storage.rs | 6 +- .../kernel_latest/kernel/src/stage_one.rs | 83 +++++++--- 6 files changed, 190 insertions(+), 114 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index 1baa7fd9147d..ea4649fb59fd 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -274,10 +274,11 @@ enum BlueprintParsing { fn next_bip_from_blueprints( host: &mut Host, tick_counter: &TickCounter, + chain_config: &ChainConfig, config: &mut Configuration, kernel_upgrade: &Option, ) -> Result { - let chain_family = config.chain_config.get_chain_family(); + let chain_family = chain_config.get_chain_family(); let (next_bip_number, timestamp, chain_header) = match read_current_block_header_for_family(host, &chain_family) { Err(_) => ( @@ -307,7 +308,7 @@ fn next_bip_from_blueprints( return Ok(BlueprintParsing::None); } } - match (&config.chain_config, chain_header) { + match (&chain_config, chain_header) { (ChainConfig::Evm(chain_config), ChainHeader::Eth(header)) => { let gas_price = crate::gas_price::base_fee_per_gas( host, @@ -498,11 +499,12 @@ fn promote_block( pub fn produce( host: &mut Host, + chain_config: &ChainConfig, config: &mut Configuration, sequencer_pool_address: Option, tracer_input: Option, ) -> Result { - let chain_id = config.chain_config.get_chain_id(); + let chain_id = chain_config.get_chain_id(); let da_fee_per_byte = crate::retrieve_da_fee(host)?; let kernel_upgrade = upgrade::read_kernel_upgrade(host)?; @@ -537,6 +539,7 @@ pub fn produce( let block_in_progress = match next_bip_from_blueprints( safe_host.host, &tick_counter, + chain_config, config, &kernel_upgrade, )? { @@ -559,7 +562,7 @@ pub fn produce( }; let processed_blueprint = block_in_progress.number(); - let computation_result = match (&config.chain_config, block_in_progress) { + let computation_result = match (&chain_config, block_in_progress) { ( ChainConfig::Evm(chain_config), BlockInProgress::Etherlink(block_in_progress), @@ -765,24 +768,16 @@ 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(evm_configuration: Config) -> Configuration { - Configuration { - chain_config: ChainConfig::new_evm_config( - DUMMY_CHAIN_ID, - EvmLimits::default(), - evm_configuration, - ), - ..Configuration::default() - } + fn dummy_configuration(evm_configuration: Config) -> ChainConfig { + ChainConfig::new_evm_config( + DUMMY_CHAIN_ID, + EvmLimits::default(), + evm_configuration, + ) } - fn dummy_tez_configuration() -> Configuration { - Configuration { - chain_config: ChainConfig::Michelson(MichelsonChainConfig::create_config( - DUMMY_CHAIN_ID, - )), - ..Configuration::default() - } + fn dummy_tez_configuration() -> ChainConfig { + ChainConfig::Michelson(MichelsonChainConfig::create_config(DUMMY_CHAIN_ID)) } fn dummy_block_fees() -> BlockFees { @@ -955,7 +950,8 @@ mod tests { produce( host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut Configuration::default(), None, None, ) @@ -976,7 +972,8 @@ mod tests { fn test_produce_tezlink_block() { let mut host = MockKernelHost::default(); - let mut config = dummy_tez_configuration(); + let chain_config = dummy_tez_configuration(); + let mut config = Configuration::default(); store_blueprints( &mut host, @@ -987,13 +984,13 @@ mod tests { ], ); - produce(&mut host, &mut config, None, None) + produce(&mut host, &chain_config, &mut config, None, None) .expect("The block production should have succeeded."); - produce(&mut host, &mut config, None, None) + produce(&mut host, &chain_config, &mut config, None, None) .expect("The block production should have succeeded."); - produce(&mut host, &mut config, None, None) + produce(&mut host, &chain_config, &mut config, None, None) .expect("The block production should have succeeded."); - let computation = produce(&mut host, &mut config, None, None) + let computation = produce(&mut host, &chain_config, &mut config, None, None) .expect("The block production should have succeeded."); assert_eq!(ComputationResult::Finished, computation); assert_eq!(U256::from(2), read_current_number(&host).unwrap()); @@ -1008,6 +1005,7 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); + let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; @@ -1030,7 +1028,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1051,6 +1050,7 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); + let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; @@ -1074,7 +1074,8 @@ mod tests { produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1089,6 +1090,7 @@ mod tests { // Test if a valid transaction is producing a receipt with a contract address fn test_valid_transactions_receipt_contract_address() { let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; let tx = dummy_eth_transaction_deploy(); @@ -1116,7 +1118,8 @@ mod tests { produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1165,6 +1168,7 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); + let mut config = Configuration::default(); let tx_hash_0 = [0; TRANSACTION_HASH_SIZE]; let tx_hash_1 = [1; TRANSACTION_HASH_SIZE]; @@ -1197,7 +1201,8 @@ mod tests { // Produce block for blueprint containing transaction_0 produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1205,7 +1210,8 @@ mod tests { // Produce block for blueprint containing transaction_1 produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1223,6 +1229,7 @@ mod tests { // Test transfers gas consumption consistency fn test_cumulative_transfers_gas_consumption() { let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); let base_gas = U256::from(21000); let dummy_block_fees = dummy_block_fees(); @@ -1262,7 +1269,8 @@ mod tests { produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1296,6 +1304,7 @@ mod tests { // Test that the same transaction can not be replayed twice fn test_replay_attack() { let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); let tx = Transaction { tx_hash: [0; TRANSACTION_HASH_SIZE], @@ -1321,7 +1330,8 @@ mod tests { produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1352,6 +1362,7 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); + let mut config = Configuration::default(); let blocks_index = block_storage::internal_for_tests::init_blocks_index().unwrap(); @@ -1370,7 +1381,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1498,6 +1510,7 @@ mod tests { #[test] fn invalid_transaction_should_bump_nonce() { let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -1530,7 +1543,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1569,6 +1583,7 @@ mod tests { #[test] fn test_first_blocks() { let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); // first block should be 0 let blueprint = almost_empty_blueprint(); @@ -1576,7 +1591,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1588,7 +1604,8 @@ mod tests { store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1600,7 +1617,8 @@ mod tests { store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1731,12 +1749,18 @@ mod tests { // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..dummy_configuration(EVMVersion::current_test_config()) + ..Configuration::default() }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - let computation_result = produce(&mut host, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = produce( + &mut host, + &dummy_configuration(EVMVersion::current_test_config()), + &mut configuration, + None, + None, + ) + .expect("Should have produced"); // test no new block assert!( @@ -1752,6 +1776,7 @@ mod tests { fn test_reboot_many_tx_many_proposal() { // init host let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); crate::storage::store_minimum_base_fee_per_gas( &mut host, @@ -1804,18 +1829,21 @@ mod tests { store_blueprints(&mut host, proposals); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. + let chain_config = dummy_configuration(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..dummy_configuration(EVMVersion::current_test_config()) + ..Configuration::default() }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - let computation_result = produce(&mut host, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = + produce(&mut host, &chain_config, &mut configuration, None, None) + .expect("Should have produced"); // test reboot is set matches!(computation_result, ComputationResult::RebootNeeded); - let computation_result = produce(&mut host, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = + produce(&mut host, &chain_config, &mut configuration, None, None) + .expect("Should have produced"); // test no new block assert_eq!( @@ -1839,9 +1867,8 @@ mod tests { "There should be some transactions left" ); - let _next_blueprint = - read_next_blueprint(&mut host, &mut Configuration::default()) - .expect("The next blueprint should be available"); + let _next_blueprint = read_next_blueprint(&mut host, &mut config) + .expect("The next blueprint should be available"); } #[test] @@ -1858,6 +1885,7 @@ mod tests { // init host let mut host = MockKernelHost::default(); + let mut config = Configuration::default(); // see // https://basescan.org/tx/0x07471adfe8f4ec553c1199f495be97fc8be8e0626ae307281c22534460184ed1 @@ -1898,7 +1926,8 @@ mod tests { produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) @@ -1956,9 +1985,10 @@ mod tests { store_inbox_blueprint(&mut host, blueprint(proposals_first_reboot)).unwrap(); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. + let chain_config = dummy_configuration(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..dummy_configuration(EVMVersion::current_test_config()) + ..Configuration::default() }; // sanity check: no current block assert!( @@ -1966,7 +1996,8 @@ mod tests { "Should not have found current block number" ); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce(&mut host, &mut configuration, None, None).expect("Should have produced"); + produce(&mut host, &chain_config, &mut configuration, None, None) + .expect("Should have produced"); assert!( block_storage::read_current_number(&host).is_ok(), @@ -1980,7 +2011,8 @@ mod tests { store_inbox_blueprint(&mut host, blueprint(proposals_second_reboot)).unwrap(); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - produce(&mut host, &mut configuration, None, None).expect("Should have produced"); + produce(&mut host, &chain_config, &mut configuration, None, None) + .expect("Should have produced"); let block = block_storage::read_current(&mut host, &ChainFamily::Evm) .expect("Should have found a block"); @@ -2025,6 +2057,7 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); + let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; let tx_hash_eip1559 = [1; TRANSACTION_HASH_SIZE]; @@ -2061,7 +2094,8 @@ mod tests { produce( &mut host, - &mut dummy_configuration(EVMVersion::current_test_config()), + &dummy_configuration(EVMVersion::current_test_config()), + &mut config, None, None, ) diff --git a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs index 1760b5998516..e8788e1e2c93 100644 --- a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs @@ -734,7 +734,7 @@ pub fn read_next_blueprint( host: &mut Host, config: &mut Configuration, ) -> anyhow::Result<(Option, usize)> { - let chain_family = config.chain_config.get_chain_family(); + let chain_family = ChainFamily::Evm; let (number, previous_timestamp, block_header) = match read_current_block_header_for_family(host, &chain_family) { Ok(BlockHeader { @@ -772,7 +772,6 @@ mod tests { use super::*; use crate::block::GENESIS_PARENT_HASH; - use crate::chains::ChainConfig; use crate::configuration::{DalConfiguration, TezosContracts}; use crate::delayed_inbox::Hash; use crate::sequencer_blueprint::{rlp_roundtrip, rlp_roundtrip_f}; @@ -815,7 +814,6 @@ mod tests { }, maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, - chain_config: ChainConfig::default(), garbage_collect_blocks: false, }; diff --git a/etherlink/kernel_latest/kernel/src/configuration.rs b/etherlink/kernel_latest/kernel/src/configuration.rs index 1719fabf2237..d73739d6c624 100644 --- a/etherlink/kernel_latest/kernel/src/configuration.rs +++ b/etherlink/kernel_latest/kernel/src/configuration.rs @@ -70,7 +70,6 @@ pub struct Configuration { pub mode: ConfigurationMode, pub maximum_allowed_ticks: u64, pub enable_fa_bridge: bool, - pub chain_config: ChainConfig, pub garbage_collect_blocks: bool, } @@ -81,7 +80,6 @@ impl Default for Configuration { mode: ConfigurationMode::Proxy, maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, - chain_config: ChainConfig::default(), garbage_collect_blocks: false, } } @@ -91,8 +89,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: {}, Chain Config: {}, Garbage collect blocks: {}", - &self.tezos_contracts, &self.mode, &self.enable_fa_bridge, &self.chain_config, &self.garbage_collect_blocks + "Tezos Contracts: {}, Mode: {}, Enable FA Bridge: {}, Garbage collect blocks: {}", + &self.tezos_contracts, &self.mode, &self.enable_fa_bridge, &self.garbage_collect_blocks ) } } @@ -209,10 +207,7 @@ pub fn fetch_chain_configuration( } } -pub fn fetch_configuration( - host: &mut Host, - chain_id: U256, -) -> Configuration { +pub fn fetch_configuration(host: &mut Host) -> Configuration { let tezos_contracts = fetch_tezos_contracts(host); let maximum_allowed_ticks = read_maximum_allowed_ticks(host).unwrap_or(MAX_ALLOWED_TICKS); @@ -220,7 +215,6 @@ pub fn fetch_configuration( 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 = fetch_chain_configuration(host, chain_id); match sequencer { Some(sequencer) => { let delayed_bridge = read_delayed_transaction_bridge(host) @@ -249,13 +243,11 @@ pub fn fetch_configuration( }, maximum_allowed_ticks, enable_fa_bridge, - chain_config, garbage_collect_blocks: !evm_node_flag, }, Err(err) => { log!(host, Fatal, "The kernel failed to created the delayed inbox, reverting configuration to proxy ({:?})", err); Configuration { - chain_config, ..Configuration::default() } } @@ -266,7 +258,6 @@ pub fn fetch_configuration( mode: ConfigurationMode::Proxy, maximum_allowed_ticks, enable_fa_bridge, - chain_config, garbage_collect_blocks: false, }, } diff --git a/etherlink/kernel_latest/kernel/src/lib.rs b/etherlink/kernel_latest/kernel/src/lib.rs index 37462d3effa5..75a83dd50eac 100644 --- a/etherlink/kernel_latest/kernel/src/lib.rs +++ b/etherlink/kernel_latest/kernel/src/lib.rs @@ -5,7 +5,10 @@ // // SPDX-License-Identifier: MIT -use crate::configuration::{fetch_configuration, Configuration, CHAIN_ID}; +use crate::chains::ChainConfig; +use crate::configuration::{ + fetch_chain_configuration, fetch_configuration, Configuration, CHAIN_ID, +}; use crate::error::Error; use crate::error::UpgradeProcessError::Fallback; use crate::migration::storage_migration; @@ -106,12 +109,14 @@ pub fn stage_zero(host: &mut Host) -> Result( host: &mut Host, smart_rollup_address: [u8; 20], + chain_config: &ChainConfig, configuration: &mut Configuration, ) -> Result { log!(host, Debug, "Entering stage one."); + log!(host, Debug, "Chain Configuration: {}", chain_config); log!(host, Debug, "Configuration: {}", configuration); - fetch_blueprints(host, smart_rollup_address, configuration) + fetch_blueprints(host, smart_rollup_address, chain_config, configuration) } fn set_kernel_version(host: &mut Host) -> Result<(), Error> { @@ -235,7 +240,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, chain_id); + let configuration = fetch_configuration(host); log!( host, Info, @@ -269,16 +274,21 @@ 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, chain_id); + let chain_configuration = fetch_chain_configuration(host, chain_id); + let mut configuration = fetch_configuration(host); let sequencer_pool_address = read_sequencer_pool_address(host); // Run the stage one, this is a no-op if the inbox was already consumed // by another kernel run. This ensures that if the migration does not // consume all reboots. At least one reboot will be used to consume the // inbox. - if let StageOneStatus::Reboot = - stage_one(host, smart_rollup_address, &mut configuration) - .context("Failed during stage 1")? + if let StageOneStatus::Reboot = stage_one( + host, + smart_rollup_address, + &chain_configuration, + &mut configuration, + ) + .context("Failed during stage 1")? { host.mark_for_reboot()?; return Ok(()); @@ -292,6 +302,7 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { log!(host, Debug, "Entering stage two."); if let block::ComputationResult::RebootNeeded = block::produce( host, + &chain_configuration, &mut configuration, sequencer_pool_address, trace_input, @@ -430,15 +441,12 @@ mod tests { const DUMMY_BASE_FEE_PER_GAS: u64 = 12345u64; const DUMMY_DA_FEE: u64 = 2_000_000_000_000u64; - fn dummy_configuration(evm_configuration: Config) -> Configuration { - Configuration { - chain_config: ChainConfig::new_evm_config( - DUMMY_CHAIN_ID, - EvmLimits::default(), - evm_configuration, - ), - ..Configuration::default() - } + fn dummy_configuration(evm_configuration: Config) -> ChainConfig { + ChainConfig::new_evm_config( + DUMMY_CHAIN_ID, + EvmLimits::default(), + evm_configuration, + ) } fn dummy_block_fees() -> BlockFees { @@ -605,9 +613,10 @@ mod tests { let block_fees = dummy_block_fees(); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. + let chain_config = dummy_configuration(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..dummy_configuration(EVMVersion::current_test_config()) + ..Configuration::default() }; crate::storage::store_minimum_base_fee_per_gas( @@ -618,9 +627,14 @@ 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, &mut configuration, None, None) - .expect("Should have produced"); + let computation_result = crate::block::produce( + &mut host, + &chain_config, + &mut configuration, + None, + None, + ) + .expect("Should have produced"); // test there is a new block assert_eq!( diff --git a/etherlink/kernel_latest/kernel/src/reveal_storage.rs b/etherlink/kernel_latest/kernel/src/reveal_storage.rs index 49a0db13293d..6eeb7e9aa78b 100644 --- a/etherlink/kernel_latest/kernel/src/reveal_storage.rs +++ b/etherlink/kernel_latest/kernel/src/reveal_storage.rs @@ -6,7 +6,7 @@ //! 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, CHAIN_ID}; +use crate::configuration::{fetch_chain_configuration, fetch_configuration, CHAIN_ID}; use crate::storage::{read_chain_id, ADMIN, SEQUENCER}; use primitive_types::U256; use rlp::{Decodable, DecoderError, Rlp}; @@ -107,6 +107,8 @@ pub fn reveal_storage( log!(host, Info, "Done revealing"); let chain_id = read_chain_id(host).unwrap_or(U256::from(CHAIN_ID)); - let configuration = fetch_configuration(host, chain_id); + let chain_config = fetch_chain_configuration(host, chain_id); + let configuration = fetch_configuration(host); + log!(host, Info, "Chain Configuration {}", chain_config); log!(host, Info, "Configuration {}", configuration); } diff --git a/etherlink/kernel_latest/kernel/src/stage_one.rs b/etherlink/kernel_latest/kernel/src/stage_one.rs index ff7bd59edc8b..399a834b1ff2 100644 --- a/etherlink/kernel_latest/kernel/src/stage_one.rs +++ b/etherlink/kernel_latest/kernel/src/stage_one.rs @@ -164,6 +164,7 @@ fn fetch_sequencer_blueprints( pub fn fetch_blueprints( host: &mut Host, smart_rollup_address: [u8; RAW_ROLLUP_ADDRESS_SIZE], + chain_config: &ChainConfig, config: &mut Configuration, ) -> Result { match &mut config.mode { @@ -185,7 +186,7 @@ pub fn fetch_blueprints( config.maximum_allowed_ticks, config.enable_fa_bridge, config.garbage_collect_blocks, - &config.chain_config, + chain_config, ), ConfigurationMode::Proxy => fetch_proxy_blueprints( host, @@ -193,7 +194,7 @@ pub fn fetch_blueprints( &config.tezos_contracts, config.enable_fa_bridge, config.garbage_collect_blocks, - &config.chain_config, + chain_config, ), } } @@ -281,7 +282,6 @@ mod tests { }, maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, - chain_config: test_chain_config(), garbage_collect_blocks: false, } } @@ -296,7 +296,6 @@ mod tests { mode: ConfigurationMode::Proxy, maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, - chain_config: test_chain_config(), garbage_collect_blocks: false, } } @@ -406,8 +405,10 @@ mod tests { let mut host = MockKernelHost::default(); host.host .add_external(Bytes::from(hex::decode(DUMMY_TRANSACTION).unwrap())); + let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -429,8 +430,10 @@ mod tests { .add_external(Bytes::from(hex::decode(DUMMY_CHUNK1).unwrap())); host.host .add_external(Bytes::from(hex::decode(DUMMY_CHUNK2).unwrap())); + let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -447,8 +450,10 @@ mod tests { let mut host = MockKernelHost::default(); host.host .add_external(Bytes::from(hex::decode(DUMMY_TRANSACTION).unwrap())); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -477,8 +482,10 @@ mod tests { .add_external(Bytes::from(hex::decode(DUMMY_CHUNK1).unwrap())); host.host .add_external(Bytes::from(hex::decode(DUMMY_CHUNK2).unwrap())); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -504,8 +511,10 @@ mod tests { host.host.add_external(Bytes::from( hex::decode(DUMMY_BLUEPRINT_CHUNK_NUMBER_10).unwrap(), )); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); // The dummy chunk in the inbox is registered at block 10 if read_blueprint( @@ -538,8 +547,10 @@ mod tests { host.host.add_external(Bytes::from( hex::decode(DUMMY_BLUEPRINT_CHUNK_UNPARSABLE).unwrap(), )); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -565,6 +576,7 @@ mod tests { host.host.add_external(Bytes::from( hex::decode(DUMMY_BLUEPRINT_CHUNK_NUMBER_10).unwrap(), )); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); match read_proxy_inbox( @@ -573,7 +585,7 @@ mod tests { &conf.tezos_contracts, false, false, - &conf.chain_config, + &chain_config, ) .unwrap() { @@ -608,6 +620,7 @@ mod tests { fn test_parsing_delayed_inbox(enable_dal: bool) { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); let metadata = TransferMetadata::new( delayed_bridge(&conf), @@ -616,7 +629,8 @@ mod tests { for message in dummy_delayed_transaction() { host.host.add_transfer(message, &metadata); } - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -643,6 +657,7 @@ mod tests { fn test_parsing_l1_contract_inbox(enable_dal: bool) { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); let metadata = TransferMetadata::new( ContractKt1Hash::from_b58check(DUMMY_INVALID_TICKETER).unwrap(), @@ -651,7 +666,8 @@ mod tests { for message in dummy_delayed_transaction() { host.host.add_transfer(message, &metadata); } - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -679,6 +695,7 @@ mod tests { #[test] fn test_parsing_delayed_inbox_rejected_in_proxy() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); let metadata = TransferMetadata::new( ContractKt1Hash::from_b58check(DUMMY_INVALID_TICKETER).unwrap(), @@ -687,7 +704,8 @@ mod tests { for message in dummy_delayed_transaction() { host.host.add_transfer(message, &metadata) } - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail").0 @@ -702,6 +720,7 @@ mod tests { #[test] fn test_deposit_in_proxy_mode() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); let metadata = TransferMetadata::new( conf.tezos_contracts.ticketer.clone().unwrap(), @@ -711,7 +730,8 @@ mod tests { dummy_deposit(conf.tezos_contracts.ticketer.clone().unwrap()), &metadata, ); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -729,6 +749,7 @@ mod tests { #[test] fn test_deposit_with_invalid_ticketer() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); let metadata = TransferMetadata::new( ContractKt1Hash::from_b58check(DUMMY_INVALID_TICKETER).unwrap(), @@ -740,7 +761,8 @@ mod tests { ), &metadata, ); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -757,6 +779,7 @@ mod tests { fn test_deposit_in_sequencer_mode(enable_dal: bool) { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); let metadata = TransferMetadata::new( conf.tezos_contracts.ticketer.clone().unwrap(), @@ -766,7 +789,8 @@ mod tests { dummy_deposit(conf.tezos_contracts.ticketer.clone().unwrap()), &metadata, ); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &mut conf).expect("fetch failed"); + fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -824,6 +848,7 @@ mod tests { fn setup_dal_signal( host: &mut MockKernelHost, + chain_config: &ChainConfig, conf: &mut Configuration, signal_slots: Option>, filled_slots: Option>, @@ -842,15 +867,17 @@ mod tests { let filled_slots = filled_slots.unwrap_or(dal_slots); fill_slots(host, filled_slots); - fetch_blueprints(host, DEFAULT_SR_ADDRESS, conf).expect("fetch failed"); + fetch_blueprints(host, DEFAULT_SR_ADDRESS, chain_config, conf) + .expect("fetch failed"); } #[test] fn test_dal_signal() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(true, None); - setup_dal_signal(&mut host, &mut conf, None, None); + setup_dal_signal(&mut host, &chain_config, &mut conf, None, None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -864,9 +891,16 @@ mod tests { #[test] fn test_dal_signal_empty_slot() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(false, Some(vec![8])); - setup_dal_signal(&mut host, &mut conf, Some(vec![21]), Some(vec![])); + setup_dal_signal( + &mut host, + &chain_config, + &mut conf, + Some(vec![21]), + Some(vec![]), + ); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -880,9 +914,10 @@ mod tests { #[test] fn test_dal_signal_with_multiple_slots_filled() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(true, Some(vec![6, 8])); - setup_dal_signal(&mut host, &mut conf, None, None); + setup_dal_signal(&mut host, &chain_config, &mut conf, None, None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -896,9 +931,10 @@ mod tests { #[test] fn test_parsable_dal_signal_without_dal() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(false, None); - setup_dal_signal(&mut host, &mut conf, Some(vec![6]), None); + setup_dal_signal(&mut host, &chain_config, &mut conf, Some(vec![6]), None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -912,9 +948,10 @@ mod tests { #[test] fn test_invalid_dal_signal() { let mut host = MockKernelHost::default(); + let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(true, Some(vec![8])); - setup_dal_signal(&mut host, &mut conf, Some(vec![21]), None); + setup_dal_signal(&mut host, &chain_config, &mut conf, Some(vec![21]), None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") -- GitLab From 4e4534fd0a1f6833808b0b185c1ba7111fd5c786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 26 Mar 2025 12:02:40 +0100 Subject: [PATCH 2/7] Etherlink/Kernel: extract Bluprint->BIP conversion in the Eth case This is to prepare abstracting this in a trait. --- etherlink/kernel_latest/kernel/src/block.rs | 58 +++++++++++++-------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index ea4649fb59fd..4aac52b75354 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -8,11 +8,12 @@ use crate::apply::{ apply_transaction, ExecutionInfo, ExecutionResult, Validity, WITHDRAWAL_OUTBOX_QUEUE, }; +use crate::blueprint::Blueprint; use crate::blueprint_storage::{ drop_blueprint, read_blueprint, read_current_block_header_for_family, - store_current_block_header, BlockHeader, ChainHeader, + store_current_block_header, BlockHeader, ChainHeader, EVMBlockHeader, }; -use crate::chains::{ChainConfig, EvmLimits}; +use crate::chains::{ChainConfig, EvmChainConfig, EvmLimits}; use crate::configuration::ConfigurationMode; use crate::delayed_inbox::DelayedInbox; use crate::error::Error; @@ -49,7 +50,7 @@ pub const GAS_LIMIT: u64 = 1 << 50; /// Struct used to allow the compiler to check that the tick counter value is /// correctly moved and updated. Copy and Clone should NOT be derived. -struct TickCounter { +pub struct TickCounter { c: u64, } @@ -270,6 +271,34 @@ enum BlueprintParsing { None, } +pub fn eth_bip_from_blueprint( + host: &Host, + chain_config: &EvmChainConfig, + tick_counter: &TickCounter, + next_bip_number: U256, + header: EVMBlockHeader, + blueprint: Blueprint, +) -> EthBlockInProgress { + let gas_price = crate::gas_price::base_fee_per_gas( + host, + blueprint.timestamp, + chain_config.limits.minimum_base_fee_per_gas, + ); + + let bip = EthBlockInProgress::from_blueprint( + blueprint, + next_bip_number, + header.hash, + tick_counter.c, + gas_price, + header.receipts_root, + header.transactions_root, + ); + + tezos_evm_logging::log!(host, tezos_evm_logging::Level::Debug, "bip: {bip:?}"); + bip +} + #[cfg_attr(feature = "benchmark", inline(never))] fn next_bip_from_blueprints( host: &mut Host, @@ -310,26 +339,13 @@ fn next_bip_from_blueprints( } match (&chain_config, chain_header) { (ChainConfig::Evm(chain_config), ChainHeader::Eth(header)) => { - let gas_price = crate::gas_price::base_fee_per_gas( + let bip = eth_bip_from_blueprint( host, - blueprint.timestamp, - chain_config.limits.minimum_base_fee_per_gas, - ); - - let bip = block_in_progress::EthBlockInProgress::from_blueprint( - blueprint, + chain_config, + tick_counter, next_bip_number, - header.hash, - tick_counter.c, - gas_price, - header.receipts_root, - header.transactions_root, - ); - - tezos_evm_logging::log!( - host, - tezos_evm_logging::Level::Debug, - "bip: {bip:?}" + header, + blueprint, ); Ok(BlueprintParsing::Next(Box::new( BlockInProgress::Etherlink(bip), -- GitLab From 75cf965de048bb8272941c80e25937faf5e53e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 26 Mar 2025 12:28:02 +0100 Subject: [PATCH 3/7] Etherlink/Kernel: split blueprint_storage::fetch_delayed_txs This is also to prepare abstracting these functions in a trait. --- .../kernel/src/blueprint_storage.rs | 64 ++++++++++++++++--- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs index e8788e1e2c93..ac60dc569dbb 100644 --- a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs @@ -464,33 +464,52 @@ pub enum BlueprintValidity { BlueprintTooLarge, } -fn fetch_delayed_txs( +pub enum DelayedTransactionFetchingResult { + Ok(Transactions), + BlueprintTooLarge, + DelayedHashMissing(delayed_inbox::Hash), +} + +fn fetch_hashes_from_delayed_inbox( host: &mut Host, - blueprint_with_hashes: BlueprintWithDelayedHashes, + delayed_hashes: Vec, delayed_inbox: &mut DelayedInbox, current_blueprint_size: usize, -) -> anyhow::Result<(BlueprintValidity, usize)> { +) -> anyhow::Result<(DelayedTransactionFetchingResult>, usize)> { let mut delayed_txs = vec![]; let mut total_size = current_blueprint_size; - for tx_hash in blueprint_with_hashes.delayed_hashes { + for tx_hash in delayed_hashes { let tx = delayed_inbox.find_transaction(host, tx_hash)?; // This is overestimated, as the transactions cannot be chunked in the // delayed bridge. total_size += MAXIMUM_SIZE_OF_DELAYED_TRANSACTION; // If the size would overflow the 512KB, reject the blueprint if MAXIMUM_SIZE_OF_BLUEPRINT < total_size { - return Ok((BlueprintValidity::BlueprintTooLarge, total_size)); + return Ok(( + DelayedTransactionFetchingResult::BlueprintTooLarge, + total_size, + )); } match tx { Some(tx) => delayed_txs.push(tx.0), None => { - return Ok((BlueprintValidity::DelayedHashMissing(tx_hash), total_size)) + return Ok(( + DelayedTransactionFetchingResult::DelayedHashMissing(tx_hash), + total_size, + )) } } } + Ok(( + DelayedTransactionFetchingResult::Ok(delayed_txs), + total_size, + )) +} - let transactions_with_hashes = blueprint_with_hashes - .transactions +fn transactions_from_bytes( + transactions: Vec>, +) -> anyhow::Result> { + transactions .into_iter() .map(|tx_common| { let tx_hash = Keccak256::digest(&tx_common).into(); @@ -501,7 +520,34 @@ fn fetch_delayed_txs( content: TransactionContent::Ethereum(tx_common), }) }) - .collect::>>()?; + .collect::>>() +} + +fn fetch_delayed_txs( + host: &mut Host, + blueprint_with_hashes: BlueprintWithDelayedHashes, + delayed_inbox: &mut DelayedInbox, + current_blueprint_size: usize, +) -> anyhow::Result<(BlueprintValidity, usize)> { + let (mut delayed_txs, total_size) = match fetch_hashes_from_delayed_inbox( + host, + blueprint_with_hashes.delayed_hashes, + delayed_inbox, + current_blueprint_size, + )? { + (DelayedTransactionFetchingResult::Ok(delayed_txs), total_size) => { + (delayed_txs, total_size) + } + (DelayedTransactionFetchingResult::BlueprintTooLarge, total_size) => { + return Ok((BlueprintValidity::BlueprintTooLarge, total_size)); + } + (DelayedTransactionFetchingResult::DelayedHashMissing(hash), total_size) => { + return Ok((BlueprintValidity::DelayedHashMissing(hash), total_size)); + } + }; + + let transactions_with_hashes = + transactions_from_bytes(blueprint_with_hashes.transactions)?; delayed_txs.extend(transactions_with_hashes); Ok(( -- GitLab From 6448aff9c16751432927e2bdc37e85590a61faf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 26 Mar 2025 17:29:53 +0100 Subject: [PATCH 4/7] Etherlink/Kernel: make Blueprint and StoreBlueprint polymorphic We parametrize them by the type of transactions, for now it is always instanciated with the transaction::Transactions enum but soon it will have Eth-specific and Tezos-specific instances --- etherlink/kernel_latest/kernel/src/block.rs | 15 +++-- .../kernel/src/block_in_progress.rs | 6 +- .../kernel_latest/kernel/src/blueprint.rs | 9 ++- .../kernel/src/blueprint_storage.rs | 55 ++++++++++--------- etherlink/kernel_latest/kernel/src/lib.rs | 4 +- 5 files changed, 49 insertions(+), 40 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index 4aac52b75354..8e37f1c8f031 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -19,7 +19,7 @@ use crate::delayed_inbox::DelayedInbox; use crate::error::Error; use crate::event::Event; use crate::l2block::L2Block; -use crate::transaction::Transaction; +use crate::transaction::{Transaction, Transactions}; use crate::upgrade; use crate::upgrade::KernelUpgrade; use crate::Configuration; @@ -277,7 +277,7 @@ pub fn eth_bip_from_blueprint( tick_counter: &TickCounter, next_bip_number: U256, header: EVMBlockHeader, - blueprint: Blueprint, + blueprint: Blueprint, ) -> EthBlockInProgress { let gas_price = crate::gas_price::base_fee_per_gas( host, @@ -729,14 +729,14 @@ mod tests { use tezos_smart_rollup_encoding::timestamp::Timestamp; use tezos_smart_rollup_host::runtime::Runtime as SdkRuntime; - fn blueprint(transactions: Vec) -> Blueprint { + fn blueprint(transactions: Vec) -> Blueprint { Blueprint { transactions: Transactions::EthTxs(transactions), timestamp: Timestamp::from(0i64), } } - fn tezlink_blueprint() -> Blueprint { + fn tezlink_blueprint() -> Blueprint { Blueprint { transactions: Transactions::TezTxs, timestamp: Timestamp::from(0i64), @@ -916,7 +916,10 @@ mod tests { ) } - fn store_blueprints(host: &mut Host, blueprints: Vec) { + fn store_blueprints( + host: &mut Host, + blueprints: Vec>, + ) { for (i, blueprint) in blueprints.into_iter().enumerate() { store_inbox_blueprint_by_number(host, blueprint, U256::from(i)) .expect("Should have stored blueprint"); @@ -1576,7 +1579,7 @@ mod tests { } /// A blueprint that should produce 1 block with an invalid transaction - fn almost_empty_blueprint() -> Blueprint { + fn almost_empty_blueprint() -> Blueprint { let tx_hash = [0; TRANSACTION_HASH_SIZE]; // transaction should be invalid diff --git a/etherlink/kernel_latest/kernel/src/block_in_progress.rs b/etherlink/kernel_latest/kernel/src/block_in_progress.rs index 7bb71fa27489..e22fa0feca51 100644 --- a/etherlink/kernel_latest/kernel/src/block_in_progress.rs +++ b/etherlink/kernel_latest/kernel/src/block_in_progress.rs @@ -13,7 +13,9 @@ use crate::gas_price::base_fee_per_gas; use crate::l2block::L2Block; use crate::storage::{self, object_path, receipt_path}; use crate::tick_model; -use crate::transaction::{Transaction, Transactions::EthTxs, Transactions::TezTxs}; +use crate::transaction::{ + Transaction, Transactions, Transactions::EthTxs, Transactions::TezTxs, +}; use anyhow::Context; use evm_execution::account_storage::EVM_ACCOUNTS_PATH; use primitive_types::{H160, H256, U256}; @@ -277,7 +279,7 @@ impl EthBlockInProgress { } pub fn from_blueprint( - blueprint: crate::blueprint::Blueprint, + blueprint: crate::blueprint::Blueprint, number: U256, parent_hash: H256, tick_counter: u64, diff --git a/etherlink/kernel_latest/kernel/src/blueprint.rs b/etherlink/kernel_latest/kernel/src/blueprint.rs index 9f17143847a0..a585acb070a7 100644 --- a/etherlink/kernel_latest/kernel/src/blueprint.rs +++ b/etherlink/kernel_latest/kernel/src/blueprint.rs @@ -5,7 +5,6 @@ // // SPDX-License-Identifier: MIT -use crate::transaction::Transactions; use rlp::{Decodable, DecoderError, Encodable}; use tezos_ethereum::rlp_helpers::{ self, append_timestamp, decode_field, decode_timestamp, @@ -15,12 +14,12 @@ use tezos_smart_rollup_encoding::timestamp::Timestamp; /// The blueprint of a block is a list of transactions. #[derive(PartialEq, Debug, Clone)] -pub struct Blueprint { - pub transactions: Transactions, +pub struct Blueprint { + pub transactions: Txs, pub timestamp: Timestamp, } -impl Encodable for Blueprint { +impl Encodable for Blueprint { fn rlp_append(&self, stream: &mut rlp::RlpStream) { stream.begin_list(2); stream.append(&self.transactions); @@ -28,7 +27,7 @@ impl Encodable for Blueprint { } } -impl Decodable for Blueprint { +impl Decodable for Blueprint { fn decode(decoder: &rlp::Rlp) -> Result { if !decoder.is_list() { return Err(DecoderError::RlpExpectedToBeList); diff --git a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs index ac60dc569dbb..e0ec54ec5f65 100644 --- a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs @@ -13,7 +13,9 @@ use crate::sequencer_blueprint::{ BlueprintWithDelayedHashes, UnsignedSequencerBlueprint, }; use crate::storage::read_last_info_per_level_timestamp; -use crate::transaction::{Transaction, TransactionContent, Transactions::EthTxs}; +use crate::transaction::{ + Transaction, TransactionContent, Transactions, Transactions::EthTxs, +}; use crate::{delayed_inbox, DelayedInbox}; use primitive_types::{H256, U256}; use rlp::{Decodable, DecoderError, Encodable}; @@ -48,15 +50,15 @@ const EVM_CURRENT_BLOCK_HEADER: RefPath = /// inbox messages. Note that the latter are only to be /// used when the kernel isn't running with a sequencer. #[derive(PartialEq, Debug, Clone)] -enum StoreBlueprint { +enum StoreBlueprint { SequencerChunk(Vec), - InboxBlueprint(Blueprint), + InboxBlueprint(Blueprint), } const SEQUENCER_CHUNK_TAG: u8 = 0; const INBOX_BLUEPRINT_TAG: u8 = 1; -impl Encodable for StoreBlueprint { +impl Encodable for StoreBlueprint { fn rlp_append(&self, stream: &mut rlp::RlpStream) { stream.begin_list(2); match &self { @@ -72,7 +74,7 @@ impl Encodable for StoreBlueprint { } } -impl Decodable for StoreBlueprint { +impl Decodable for StoreBlueprint { fn decode(decoder: &rlp::Rlp) -> Result { if !decoder.is_list() { return Err(DecoderError::RlpExpectedToBeList); @@ -251,13 +253,16 @@ pub fn store_sequencer_blueprint( store_blueprint_nb_chunks(host, &blueprint_path, blueprint.nb_chunks)?; let blueprint_chunk_path = blueprint_chunk_path(&blueprint_path, blueprint.chunk_index)?; - let store_blueprint = StoreBlueprint::SequencerChunk(blueprint.chunk); + // The `Transactions` type parameter of `StoreBlueprint` is not + // used in the `SequencerChunk` case so it is irrelevant here, we could pass + // any type implementing the `Encodable` trait. + let store_blueprint = StoreBlueprint::>::SequencerChunk(blueprint.chunk); store_rlp(&store_blueprint, host, &blueprint_chunk_path).map_err(Error::from) } -pub fn store_inbox_blueprint_by_number( +pub fn store_inbox_blueprint_by_number( host: &mut Host, - blueprint: Blueprint, + blueprint: Blueprint, number: U256, ) -> Result<(), Error> { let blueprint_path = blueprint_path(number)?; @@ -267,9 +272,9 @@ pub fn store_inbox_blueprint_by_number( store_rlp(&store_blueprint, host, &chunk_path).map_err(Error::from) } -pub fn store_inbox_blueprint( +pub fn store_inbox_blueprint( host: &mut Host, - blueprint: Blueprint, + blueprint: Blueprint, ) -> anyhow::Result<()> { let number = read_next_blueprint_number(host)?; Ok(store_inbox_blueprint_by_number(host, blueprint, number)?) @@ -287,9 +292,9 @@ pub fn read_next_blueprint_number(host: &Host) -> Result( +pub fn store_forced_blueprint( host: &mut Host, - blueprint: Blueprint, + blueprint: Blueprint, number: U256, ) -> Result<(), Error> { let blueprint_path = blueprint_path(number)?; @@ -454,8 +459,8 @@ const MAXIMUM_SIZE_OF_DELAYED_TRANSACTION: usize = MAX_INPUT_MESSAGE_SIZE; /// Only used for test, as all errors are handled in the same way #[cfg_attr(feature = "benchmark", allow(dead_code))] #[derive(Debug, PartialEq)] -pub enum BlueprintValidity { - Valid(Blueprint), +pub enum BlueprintValidity { + Valid(Blueprint), InvalidParentHash, TimestampFromPast, TimestampFromFuture, @@ -464,8 +469,8 @@ pub enum BlueprintValidity { BlueprintTooLarge, } -pub enum DelayedTransactionFetchingResult { - Ok(Transactions), +pub enum DelayedTransactionFetchingResult { + Ok(Txs), BlueprintTooLarge, DelayedHashMissing(delayed_inbox::Hash), } @@ -528,7 +533,7 @@ fn fetch_delayed_txs( blueprint_with_hashes: BlueprintWithDelayedHashes, delayed_inbox: &mut DelayedInbox, current_blueprint_size: usize, -) -> anyhow::Result<(BlueprintValidity, usize)> { +) -> anyhow::Result<(BlueprintValidity, usize)> { let (mut delayed_txs, total_size) = match fetch_hashes_from_delayed_inbox( host, blueprint_with_hashes.delayed_hashes, @@ -576,7 +581,7 @@ fn parse_and_validate_blueprint( max_blueprint_lookahead_in_seconds: i64, parent_chain_header: &ChainHeader, head_timestamp: Timestamp, -) -> anyhow::Result<(BlueprintValidity, usize)> { +) -> anyhow::Result<(BlueprintValidity, usize)> { // Decode match rlp::decode::(bytes) { Err(e) => Ok((BlueprintValidity::DecoderError(e), bytes.len())), @@ -638,10 +643,10 @@ fn parse_and_validate_blueprint( } } -fn invalidate_blueprint( +fn invalidate_blueprint( host: &mut Host, blueprint_path: &OwnedPath, - error: &BlueprintValidity, + error: &BlueprintValidity, ) -> Result<(), RuntimeError> { log!( host, @@ -661,20 +666,20 @@ fn read_all_chunks_and_validate( config: &mut Configuration, previous_chain_header: &ChainHeader, previous_timestamp: Timestamp, -) -> anyhow::Result<(Option, usize)> { +) -> anyhow::Result<(Option>, usize)> { let mut chunks = vec![]; let mut size = 0; if nb_chunks > MAXIMUM_NUMBER_OF_CHUNKS { invalidate_blueprint( host, blueprint_path, - &BlueprintValidity::BlueprintTooLarge, + &BlueprintValidity::::BlueprintTooLarge, )?; return Ok((None, 0)); }; for i in 0..nb_chunks { let path = blueprint_chunk_path(blueprint_path, i)?; - let stored_chunk = read_rlp(host, &path)?; + let stored_chunk = read_rlp::>(host, &path)?; // The tick model is based on the size of the chunk, we overapproximate it. size += MAX_INPUT_MESSAGE_SIZE; match stored_chunk { @@ -728,7 +733,7 @@ pub fn read_blueprint( number: U256, previous_timestamp: Timestamp, previous_chain_header: &ChainHeader, -) -> anyhow::Result<(Option, usize)> { +) -> anyhow::Result<(Option>, usize)> { let blueprint_path = blueprint_path(number)?; let exists = host.store_has(&blueprint_path)?.is_some(); if exists { @@ -779,7 +784,7 @@ pub fn read_blueprint( pub fn read_next_blueprint( host: &mut Host, config: &mut Configuration, -) -> anyhow::Result<(Option, usize)> { +) -> anyhow::Result<(Option>, usize)> { let chain_family = ChainFamily::Evm; let (number, previous_timestamp, block_header) = match read_current_block_header_for_family(host, &chain_family) { diff --git a/etherlink/kernel_latest/kernel/src/lib.rs b/etherlink/kernel_latest/kernel/src/lib.rs index 75a83dd50eac..2d2b9893ee73 100644 --- a/etherlink/kernel_latest/kernel/src/lib.rs +++ b/etherlink/kernel_latest/kernel/src/lib.rs @@ -394,7 +394,7 @@ mod tests { }; use crate::{ blueprint::Blueprint, - transaction::{Transaction, TransactionContent}, + transaction::{Transaction, TransactionContent, Transactions}, upgrade::KernelUpgrade, }; use evm::Config; @@ -492,7 +492,7 @@ mod tests { } } - fn blueprint(transactions: Vec) -> Blueprint { + fn blueprint(transactions: Vec) -> Blueprint { Blueprint { transactions: EthTxs(transactions), timestamp: Timestamp::from(0i64), -- GitLab From 0d5c0aa5405def962c6d70ff60730de83dad172f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 26 Mar 2025 17:36:13 +0100 Subject: [PATCH 5/7] Etherlink/Kernel: make BlueprintParsing polymorphic --- etherlink/kernel_latest/kernel/src/block.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index 8e37f1c8f031..84a6b886ac50 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -266,8 +266,8 @@ impl BlockInProgress { } } -enum BlueprintParsing { - Next(Box), +enum BlueprintParsing { + Next(Box), None, } @@ -306,7 +306,7 @@ fn next_bip_from_blueprints( chain_config: &ChainConfig, config: &mut Configuration, kernel_upgrade: &Option, -) -> Result { +) -> Result, anyhow::Error> { let chain_family = chain_config.get_chain_family(); let (next_bip_number, timestamp, chain_header) = match read_current_block_header_for_family(host, &chain_family) { -- GitLab From 3bd745a3590a9047543f2f68f56d39b2cb164677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Sat, 1 Mar 2025 13:12:03 +0100 Subject: [PATCH 6/7] Etherlink/Kernel: introduce ChainConfigTrait --- etherlink/kernel_latest/kernel/src/block.rs | 6 +- etherlink/kernel_latest/kernel/src/chains.rs | 104 ++++++++++++------- etherlink/kernel_latest/kernel/src/inbox.rs | 2 +- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index 84a6b886ac50..e40d1426bac3 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -282,7 +282,7 @@ pub fn eth_bip_from_blueprint( let gas_price = crate::gas_price::base_fee_per_gas( host, blueprint.timestamp, - chain_config.limits.minimum_base_fee_per_gas, + chain_config.get_limits().minimum_base_fee_per_gas, ); let bip = EthBlockInProgress::from_blueprint( @@ -595,13 +595,13 @@ pub fn produce( &precompiles, &mut tick_counter, sequencer_pool_address, - &chain_config.limits, + chain_config.get_limits(), config.maximum_allowed_ticks, tracer_input, chain_id, da_fee_per_byte, coinbase, - &chain_config.evm_config, + chain_config.get_evm_config(), ) } ( diff --git a/etherlink/kernel_latest/kernel/src/chains.rs b/etherlink/kernel_latest/kernel/src/chains.rs index 7f82548251e7..872e3b035063 100644 --- a/etherlink/kernel_latest/kernel/src/chains.rs +++ b/etherlink/kernel_latest/kernel/src/chains.rs @@ -2,13 +2,11 @@ // // SPDX-License-Identifier: MIT -use evm_execution::configuration::EVMVersion; -use primitive_types::U256; - use crate::{ - configuration::CHAIN_ID, fees::MINIMUM_BASE_FEE_PER_GAS, - tick_model::constants::MAXIMUM_GAS_LIMIT, + fees::MINIMUM_BASE_FEE_PER_GAS, tick_model::constants::MAXIMUM_GAS_LIMIT, CHAIN_ID, }; +use evm_execution::configuration::EVMVersion; +use primitive_types::U256; #[derive(Clone, Copy, Debug)] pub enum ChainFamily { @@ -32,14 +30,43 @@ impl From for ChainFamily { } } +#[derive(Debug)] pub struct EvmChainConfig { - pub chain_id: U256, - pub limits: EvmLimits, - pub evm_config: evm_execution::Config, + chain_id: U256, + limits: EvmLimits, + evm_config: evm_execution::Config, +} + +#[derive(Debug)] +pub struct MichelsonChainConfig { + chain_id: U256, +} + +pub enum ChainConfig { + Evm(Box), + Michelson(MichelsonChainConfig), +} + +pub trait ChainConfigTrait: std::fmt::Debug { + fn get_chain_id(&self) -> U256; + + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + chain_family: ChainFamily, + ) -> std::fmt::Result { + write!(f, "{{Chain family: {}, {:?}}}", chain_family, self) + } +} + +impl ChainConfigTrait for EvmChainConfig { + fn get_chain_id(&self) -> U256 { + self.chain_id + } } impl EvmChainConfig { - pub fn create_config( + fn create_config( chain_id: U256, limits: EvmLimits, evm_config: evm_execution::Config, @@ -50,10 +77,20 @@ impl EvmChainConfig { evm_config, } } + + pub fn get_limits(&self) -> &EvmLimits { + &self.limits + } + + pub fn get_evm_config(&self) -> &evm_execution::Config { + &self.evm_config + } } -pub struct MichelsonChainConfig { - pub chain_id: U256, +impl ChainConfigTrait for MichelsonChainConfig { + fn get_chain_id(&self) -> U256 { + self.chain_id + } } impl MichelsonChainConfig { @@ -62,19 +99,15 @@ impl MichelsonChainConfig { } } -#[allow(clippy::large_enum_variant)] -pub enum ChainConfig { - Evm(EvmChainConfig), - Michelson(MichelsonChainConfig), -} - impl ChainConfig { pub fn new_evm_config( chain_id: U256, limits: EvmLimits, evm_config: evm_execution::Config, ) -> Self { - ChainConfig::Evm(EvmChainConfig::create_config(chain_id, limits, evm_config)) + ChainConfig::Evm(Box::new(EvmChainConfig::create_config( + chain_id, limits, evm_config, + ))) } pub fn new_michelson_config(chain_id: U256) -> Self { @@ -90,9 +123,9 @@ impl ChainConfig { pub fn get_chain_id(&self) -> U256 { match self { - ChainConfig::Evm(evm_chain_config) => evm_chain_config.chain_id, + ChainConfig::Evm(evm_chain_config) => evm_chain_config.get_chain_id(), ChainConfig::Michelson(michelson_chain_config) => { - michelson_chain_config.chain_id + michelson_chain_config.get_chain_id() } } } @@ -122,36 +155,31 @@ impl Default for EvmLimits { } } +impl Default for ChainConfig { + fn default() -> Self { + ChainConfig::Evm(Box::default()) + } +} + impl std::fmt::Display for ChainConfig { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let chain_family = self.get_chain_family(); match self { - ChainConfig::Evm(chain_config) => write!( - f, - "{{Chain id: {}, Chain family: {}, Limits: {:?}, VMConfig: {:?}}}", - chain_config.chain_id, - ChainFamily::Evm, - chain_config.limits, - chain_config.evm_config - ), - ChainConfig::Michelson(chain_config) => { - write!( - f, - "{{Chain id: {}, Chain family: {}}}", - chain_config.chain_id, - ChainFamily::Michelson - ) + ChainConfig::Evm(evm_chain_config) => evm_chain_config.fmt(f, chain_family), + ChainConfig::Michelson(michelson_chain_config) => { + michelson_chain_config.fmt(f, chain_family) } } } } -impl Default for ChainConfig { +impl Default for EvmChainConfig { fn default() -> Self { - Self::Evm(EvmChainConfig::create_config( + Self::create_config( U256::from(CHAIN_ID), EvmLimits::default(), EVMVersion::to_config(&EVMVersion::default()), - )) + ) } } diff --git a/etherlink/kernel_latest/kernel/src/inbox.rs b/etherlink/kernel_latest/kernel/src/inbox.rs index ebc6e3daf197..a36c0efae067 100644 --- a/etherlink/kernel_latest/kernel/src/inbox.rs +++ b/etherlink/kernel_latest/kernel/src/inbox.rs @@ -457,7 +457,7 @@ fn read_and_dispatch_input( ChainConfig::Evm(evm) => simulation::start_simulation_mode( host, enable_fa_bridge, - &evm.evm_config, + evm.get_evm_config(), ), ChainConfig::Michelson(_) => Ok(()), }?; -- GitLab From 49b96713876d979be09a00ab752d12140f6355dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Fri, 21 Mar 2025 02:35:49 +0100 Subject: [PATCH 7/7] Etherlink/Kernel: abstract all chain-specific aspects in the trait This statically ensures that the mixed Eth-Tez branches in stage 2 are dead code. --- etherlink/kernel_latest/kernel/src/block.rs | 353 ++++++---------- .../kernel/src/block_in_progress.rs | 9 +- .../kernel/src/blueprint_storage.rs | 191 ++++----- etherlink/kernel_latest/kernel/src/chains.rs | 391 +++++++++++++++++- .../kernel_latest/kernel/src/configuration.rs | 4 +- etherlink/kernel_latest/kernel/src/inbox.rs | 66 ++- etherlink/kernel_latest/kernel/src/lib.rs | 41 +- .../kernel_latest/kernel/src/stage_one.rs | 219 ++++++---- .../kernel_latest/kernel/src/transaction.rs | 12 - 9 files changed, 766 insertions(+), 520 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index e40d1426bac3..d61a6ed68c78 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -10,21 +10,23 @@ use crate::apply::{ }; use crate::blueprint::Blueprint; use crate::blueprint_storage::{ - drop_blueprint, read_blueprint, read_current_block_header_for_family, + drop_blueprint, read_blueprint, read_current_block_header, store_current_block_header, BlockHeader, ChainHeader, EVMBlockHeader, }; -use crate::chains::{ChainConfig, EvmChainConfig, EvmLimits}; +use crate::chains::{ + BlockInProgressTrait, ChainConfigTrait, ChainHeaderTrait, EvmChainConfig, EvmLimits, +}; use crate::configuration::ConfigurationMode; use crate::delayed_inbox::DelayedInbox; use crate::error::Error; use crate::event::Event; use crate::l2block::L2Block; +use crate::storage; use crate::transaction::{Transaction, Transactions}; use crate::upgrade; use crate::upgrade::KernelUpgrade; use crate::Configuration; use crate::{block_in_progress, tick_model}; -use crate::{block_storage, storage}; use anyhow::Context; use block_in_progress::EthBlockInProgress; use evm::Config; @@ -41,7 +43,6 @@ use tezos_evm_runtime::safe_storage::SafeStorage; use tezos_smart_rollup::outbox::OutboxQueue; use tezos_smart_rollup::types::Timestamp; use tezos_smart_rollup_host::path::Path; -use tezos_tezlink::block::TezBlock; use tick_model::estimate_remaining_ticks_for_transaction_execution; pub const GENESIS_PARENT_HASH: H256 = H256([0xff; 32]); @@ -51,7 +52,7 @@ pub const GAS_LIMIT: u64 = 1 << 50; /// Struct used to allow the compiler to check that the tick counter value is /// correctly moved and updated. Copy and Clone should NOT be derived. pub struct TickCounter { - c: u64, + pub c: u64, } impl TickCounter { @@ -247,25 +248,6 @@ fn compute( }) } -#[allow(clippy::large_enum_variant)] -pub enum BlockInProgress { - Etherlink(EthBlockInProgress), - Tezlink { - number: U256, - timestamp: Timestamp, - previous_hash: H256, - }, -} - -impl BlockInProgress { - pub fn number(&self) -> U256 { - match self { - Self::Etherlink(bip) => bip.number, - Self::Tezlink { number, .. } => *number, - } - } -} - enum BlueprintParsing { Next(Box), None, @@ -300,32 +282,36 @@ pub fn eth_bip_from_blueprint( } #[cfg_attr(feature = "benchmark", inline(never))] -fn next_bip_from_blueprints( +fn next_bip_from_blueprints( host: &mut Host, tick_counter: &TickCounter, chain_config: &ChainConfig, config: &mut Configuration, kernel_upgrade: &Option, -) -> Result, anyhow::Error> { - let chain_family = chain_config.get_chain_family(); - let (next_bip_number, timestamp, chain_header) = - match read_current_block_header_for_family(host, &chain_family) { - Err(_) => ( - U256::zero(), - Timestamp::from(0), - ChainHeader::genesis_header(chain_family), - ), - Ok(BlockHeader { - blueprint_header, - chain_header, - }) => ( - blueprint_header.number + 1, - blueprint_header.timestamp, - chain_header, - ), - }; - let (blueprint, size) = - read_blueprint(host, config, next_bip_number, timestamp, &chain_header)?; +) -> Result, anyhow::Error> { + let (next_bip_number, timestamp, chain_header) = match read_current_block_header(host) + { + Err(_) => ( + U256::zero(), + Timestamp::from(0), + ChainConfig::ChainHeader::genesis_header(), + ), + Ok(BlockHeader { + blueprint_header, + chain_header, + }) => ( + blueprint_header.number + 1, + blueprint_header.timestamp, + chain_header, + ), + }; + let (blueprint, size) = read_blueprint::<_, ChainConfig>( + host, + config, + next_bip_number, + timestamp, + &chain_header, + )?; log!(host, Benchmarking, "Size of blueprint: {}", size); match blueprint { Some(blueprint) => { @@ -337,43 +323,22 @@ fn next_bip_from_blueprints( return Ok(BlueprintParsing::None); } } - match (&chain_config, chain_header) { - (ChainConfig::Evm(chain_config), ChainHeader::Eth(header)) => { - let bip = eth_bip_from_blueprint( - host, - chain_config, - tick_counter, - next_bip_number, - header, - blueprint, - ); - Ok(BlueprintParsing::Next(Box::new( - BlockInProgress::Etherlink(bip), - ))) - } - (ChainConfig::Michelson(_), ChainHeader::Tez(header)) => { - Ok(BlueprintParsing::Next(Box::new(BlockInProgress::Tezlink { - number: next_bip_number, - timestamp: blueprint.timestamp, - previous_hash: header.hash, - }))) - } - (_, _) => { - log!( - host, - Fatal, - "Incoherent state between the configuration and the header read in the durable storage" - ); - Ok(BlueprintParsing::None) - } - } + let bip: ChainConfig::BlockInProgress = chain_config + .block_in_progress_from_blueprint( + host, + tick_counter, + next_bip_number, + chain_header, + blueprint, + ); + Ok(BlueprintParsing::Next(Box::new(bip))) } None => Ok(BlueprintParsing::None), } } #[allow(clippy::too_many_arguments)] -fn compute_bip( +pub fn compute_bip( host: &mut Host, outbox_queue: &OutboxQueue<'_, impl Path>, mut block_in_progress: EthBlockInProgress, @@ -513,14 +478,13 @@ fn promote_block( Ok(()) } -pub fn produce( +pub fn produce( host: &mut Host, chain_config: &ChainConfig, config: &mut Configuration, sequencer_pool_address: Option, tracer_input: Option, ) -> Result { - let chain_id = chain_config.get_chain_id(); let da_fee_per_byte = crate::retrieve_da_fee(host)?; let kernel_upgrade = upgrade::read_kernel_upgrade(host)?; @@ -538,13 +502,9 @@ pub fn produce( // Check if there's a BIP in storage to resume its execution let (block_in_progress_provenance, block_in_progress) = - match storage::read_block_in_progress(&safe_host)? { + match ChainConfig::read_block_in_progress(&safe_host)? { Some(block_in_progress) => { - // We don't yet support saving Tez block in progress in the durable storage and restoring them. - ( - BlockInProgressProvenance::Storage, - BlockInProgress::Etherlink(block_in_progress), - ) + (BlockInProgressProvenance::Storage, block_in_progress) } None => { // Using `safe_host.host` allows to escape from the failsafe storage, which is necessary @@ -578,66 +538,18 @@ pub fn produce( }; let processed_blueprint = block_in_progress.number(); - let computation_result = match (&chain_config, block_in_progress) { - ( - ChainConfig::Evm(chain_config), - BlockInProgress::Etherlink(block_in_progress), - ) => { - log!( - safe_host, - Debug, - "Computing the BlockInProgress for Etherlink" - ); - compute_bip( - &mut safe_host, - &outbox_queue, - block_in_progress, - &precompiles, - &mut tick_counter, - sequencer_pool_address, - chain_config.get_limits(), - config.maximum_allowed_ticks, - tracer_input, - chain_id, - da_fee_per_byte, - coinbase, - chain_config.get_evm_config(), - ) - } - ( - ChainConfig::Michelson(_), - BlockInProgress::Tezlink { - number, - timestamp, - previous_hash, - }, - ) => { - log!( - safe_host, - Debug, - "Computing the BlockInProgress for Tezlink at level {}", - number - ); - - let tezblock = TezBlock::new(number, timestamp, previous_hash); - let new_block = L2Block::Tezlink(tezblock); - block_storage::store_current(&mut safe_host, &new_block) - .context("Failed to store the current block")?; - Ok(BlockComputationResult::Finished { - included_delayed_transactions: vec![], - block: new_block, - }) - } - (_, _) => { - // This case should be correctly handled by this MR https://gitlab.com/tezos/tezos/-/merge_requests/17259 - log!( - safe_host, - Fatal, - "Incoherent BlockInProgress found with the Chain running in the kernel" - ); - return Ok(ComputationResult::Finished); - } - }; + let computation_result = chain_config.compute_bip( + &mut safe_host, + &outbox_queue, + block_in_progress, + &precompiles, + &mut tick_counter, + sequencer_pool_address, + config.maximum_allowed_ticks, + tracer_input, + da_fee_per_byte, + coinbase, + ); match computation_result { Ok(BlockComputationResult::Finished { included_delayed_transactions, @@ -699,8 +611,9 @@ 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::chains::ChainFamily; - use crate::chains::MichelsonChainConfig; + use crate::chains::{ + ChainFamily, EvmChainConfig, MichelsonChainConfig, TezTransactions, + }; use crate::fees::DA_FEE_PER_BYTE; use crate::fees::MINIMUM_BASE_FEE_PER_GAS; use crate::storage::read_block_in_progress; @@ -736,9 +649,9 @@ mod tests { } } - fn tezlink_blueprint() -> Blueprint { + fn tezlink_blueprint() -> Blueprint { Blueprint { - transactions: Transactions::TezTxs, + transactions: TezTransactions {}, timestamp: Timestamp::from(0i64), } } @@ -784,16 +697,20 @@ 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(evm_configuration: Config) -> ChainConfig { - ChainConfig::new_evm_config( + fn dummy_evm_config(evm_configuration: Config) -> EvmChainConfig { + EvmChainConfig::create_config( DUMMY_CHAIN_ID, EvmLimits::default(), evm_configuration, ) } - fn dummy_tez_configuration() -> ChainConfig { - ChainConfig::Michelson(MichelsonChainConfig::create_config(DUMMY_CHAIN_ID)) + fn dummy_tez_config() -> MichelsonChainConfig { + MichelsonChainConfig::create_config(DUMMY_CHAIN_ID) + } + + fn dummy_configuration() -> Configuration { + Configuration::default() } fn dummy_block_fees() -> BlockFees { @@ -916,9 +833,9 @@ mod tests { ) } - fn store_blueprints( + fn store_blueprints( host: &mut Host, - blueprints: Vec>, + blueprints: Vec>, ) { for (i, blueprint) in blueprints.into_iter().enumerate() { store_inbox_blueprint_by_number(host, blueprint, U256::from(i)) @@ -956,7 +873,7 @@ mod tests { }, ]; - store_blueprints(host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(host, vec![blueprint(transactions)]); let sender = dummy_eth_caller(); set_balance( @@ -969,8 +886,8 @@ mod tests { produce( host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut Configuration::default(), + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -991,10 +908,10 @@ mod tests { fn test_produce_tezlink_block() { let mut host = MockKernelHost::default(); - let chain_config = dummy_tez_configuration(); - let mut config = Configuration::default(); + let chain_config = dummy_tez_config(); + let mut config = dummy_configuration(); - store_blueprints( + store_blueprints::<_, MichelsonChainConfig>( &mut host, vec![ tezlink_blueprint(), @@ -1024,7 +941,6 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); - let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; @@ -1034,7 +950,7 @@ mod tests { }; let transactions: Vec = vec![invalid_tx]; - store_blueprints(&mut host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(transactions)]); let mut evm_account_storage = init_account_storage().unwrap(); let sender = dummy_eth_caller(); @@ -1047,8 +963,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1069,7 +985,6 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); - let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; @@ -1079,7 +994,7 @@ mod tests { }; let transactions: Vec = vec![valid_tx]; - store_blueprints(&mut host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(transactions)]); let sender = dummy_eth_caller(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -1093,8 +1008,8 @@ mod tests { produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1109,7 +1024,6 @@ mod tests { // Test if a valid transaction is producing a receipt with a contract address fn test_valid_transactions_receipt_contract_address() { let mut host = MockKernelHost::default(); - let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; let tx = dummy_eth_transaction_deploy(); @@ -1123,7 +1037,7 @@ mod tests { }; let transactions: Vec = vec![valid_tx]; - store_blueprints(&mut host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(transactions)]); let sender = H160::from_str("af1276cbb260bb13deddb4209ae99ae6e497f446").unwrap(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -1137,8 +1051,8 @@ mod tests { produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1187,7 +1101,6 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); - let mut config = Configuration::default(); let tx_hash_0 = [0; TRANSACTION_HASH_SIZE]; let tx_hash_1 = [1; TRANSACTION_HASH_SIZE]; @@ -1202,7 +1115,7 @@ mod tests { content: Ethereum(dummy_eth_transaction_one()), }]; - store_blueprints( + store_blueprints::<_, EvmChainConfig>( &mut host, vec![blueprint(transaction_0), blueprint(transaction_1)], ); @@ -1220,8 +1133,8 @@ mod tests { // Produce block for blueprint containing transaction_0 produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1229,8 +1142,8 @@ mod tests { // Produce block for blueprint containing transaction_1 produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1248,7 +1161,6 @@ mod tests { // Test transfers gas consumption consistency fn test_cumulative_transfers_gas_consumption() { let mut host = MockKernelHost::default(); - let mut config = Configuration::default(); let base_gas = U256::from(21000); let dummy_block_fees = dummy_block_fees(); @@ -1274,7 +1186,7 @@ mod tests { }, ]; - store_blueprints(&mut host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(transactions)]); let sender = dummy_eth_caller(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -1288,8 +1200,8 @@ mod tests { produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1323,7 +1235,6 @@ mod tests { // Test that the same transaction can not be replayed twice fn test_replay_attack() { let mut host = MockKernelHost::default(); - let mut config = Configuration::default(); let tx = Transaction { tx_hash: [0; TRANSACTION_HASH_SIZE], @@ -1331,7 +1242,7 @@ mod tests { }; let transactions = vec![tx.clone(), tx]; - store_blueprints( + store_blueprints::<_, EvmChainConfig>( &mut host, vec![blueprint(transactions.clone()), blueprint(transactions)], ); @@ -1349,8 +1260,8 @@ mod tests { produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1381,12 +1292,11 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); - let mut config = Configuration::default(); let blocks_index = block_storage::internal_for_tests::init_blocks_index().unwrap(); - store_blueprints(&mut host, vec![blueprint(vec![])]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(vec![])]); let number_of_blocks_indexed = blocks_index.length(&host).unwrap(); let sender = dummy_eth_caller(); @@ -1400,8 +1310,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1529,7 +1439,6 @@ mod tests { #[test] fn invalid_transaction_should_bump_nonce() { let mut host = MockKernelHost::default(); - let mut config = Configuration::default(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -1556,14 +1465,17 @@ mod tests { tx_hash, content: Ethereum(tx), }; - store_blueprints(&mut host, vec![blueprint(vec![transaction])]); + store_blueprints::<_, EvmChainConfig>( + &mut host, + vec![blueprint(vec![transaction])], + ); // Apply the transaction store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1602,7 +1514,6 @@ mod tests { #[test] fn test_first_blocks() { let mut host = MockKernelHost::default(); - let mut config = Configuration::default(); // first block should be 0 let blueprint = almost_empty_blueprint(); @@ -1610,8 +1521,8 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1623,8 +1534,8 @@ mod tests { store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1636,8 +1547,8 @@ mod tests { store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -1761,25 +1672,21 @@ mod tests { wrap_transaction(2, loop_4600_tx), ]; - store_blueprints(&mut host, vec![blueprint(proposals)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(proposals)]); host.reboot_left().expect("should be some reboot left"); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. + let chain_config = dummy_evm_config(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..Configuration::default() + ..dummy_configuration() }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); - let computation_result = produce( - &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut configuration, - None, - None, - ) - .expect("Should have produced"); + let computation_result = + produce(&mut host, &chain_config, &mut configuration, None, None) + .expect("Should have produced"); // test no new block assert!( @@ -1845,13 +1752,13 @@ mod tests { ]), ]; - store_blueprints(&mut host, proposals); + store_blueprints::<_, EvmChainConfig>(&mut host, proposals); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. - let chain_config = dummy_configuration(EVMVersion::current_test_config()); + let chain_config = dummy_evm_config(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..Configuration::default() + ..dummy_configuration() }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); let computation_result = @@ -1904,7 +1811,6 @@ mod tests { // init host let mut host = MockKernelHost::default(); - let mut config = Configuration::default(); // see // https://basescan.org/tx/0x07471adfe8f4ec553c1199f495be97fc8be8e0626ae307281c22534460184ed1 @@ -1932,7 +1838,7 @@ mod tests { let transactions: Vec = vec![tx]; - store_blueprints(&mut host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(transactions)]); let sender = H160::from_str("05f32b3cc3888453ff71b01135b34ff8e41263f2").unwrap(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -1945,8 +1851,8 @@ mod tests { produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) @@ -2004,10 +1910,10 @@ mod tests { store_inbox_blueprint(&mut host, blueprint(proposals_first_reboot)).unwrap(); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. - let chain_config = dummy_configuration(EVMVersion::current_test_config()); + let chain_config = dummy_evm_config(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, - ..Configuration::default() + ..dummy_configuration() }; // sanity check: no current block assert!( @@ -2076,7 +1982,6 @@ mod tests { DUMMY_BASE_FEE_PER_GAS.into(), ) .unwrap(); - let mut config = Configuration::default(); let tx_hash = [0; TRANSACTION_HASH_SIZE]; let tx_hash_eip1559 = [1; TRANSACTION_HASH_SIZE]; @@ -2099,7 +2004,7 @@ mod tests { let transactions: Vec = vec![valid_tx, valid_tx_eip1559, valid_tx_eip2930]; - store_blueprints(&mut host, vec![blueprint(transactions)]); + store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(transactions)]); let sender = dummy_eth_caller(); let mut evm_account_storage = init_account_storage().unwrap(); @@ -2113,8 +2018,8 @@ mod tests { produce( &mut host, - &dummy_configuration(EVMVersion::current_test_config()), - &mut config, + &dummy_evm_config(EVMVersion::current_test_config()), + &mut dummy_configuration(), None, None, ) diff --git a/etherlink/kernel_latest/kernel/src/block_in_progress.rs b/etherlink/kernel_latest/kernel/src/block_in_progress.rs index e22fa0feca51..cd075b025a89 100644 --- a/etherlink/kernel_latest/kernel/src/block_in_progress.rs +++ b/etherlink/kernel_latest/kernel/src/block_in_progress.rs @@ -13,9 +13,7 @@ use crate::gas_price::base_fee_per_gas; use crate::l2block::L2Block; use crate::storage::{self, object_path, receipt_path}; use crate::tick_model; -use crate::transaction::{ - Transaction, Transactions, Transactions::EthTxs, Transactions::TezTxs, -}; +use crate::transaction::{Transaction, Transactions, Transactions::EthTxs}; use anyhow::Context; use evm_execution::account_storage::EVM_ACCOUNTS_PATH; use primitive_types::{H160, H256, U256}; @@ -290,11 +288,6 @@ impl EthBlockInProgress { // blueprint is turn into a ring to allow popping from the front let ring = match blueprint.transactions { EthTxs(transactions) => transactions.into(), - TezTxs => - // This should never happen as we are in an Ethereum block in progress - { - VecDeque::new() - } }; EthBlockInProgress::new_with_ticks( number, diff --git a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs index e0ec54ec5f65..34d713a1338f 100644 --- a/etherlink/kernel_latest/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_latest/kernel/src/blueprint_storage.rs @@ -3,9 +3,8 @@ // // SPDX-License-Identifier: MIT -use crate::block::GENESIS_PARENT_HASH; use crate::blueprint::Blueprint; -use crate::chains::ChainFamily; +use crate::chains::{ChainConfigTrait, ChainHeaderTrait, TransactionsTrait}; use crate::configuration::{Configuration, ConfigurationMode}; use crate::error::{Error, StorageError}; use crate::l2block::L2Block; @@ -13,9 +12,7 @@ use crate::sequencer_blueprint::{ BlueprintWithDelayedHashes, UnsignedSequencerBlueprint, }; use crate::storage::read_last_info_per_level_timestamp; -use crate::transaction::{ - Transaction, TransactionContent, Transactions, Transactions::EthTxs, -}; +use crate::transaction::{Transaction, TransactionContent, Transactions}; use crate::{delayed_inbox, DelayedInbox}; use primitive_types::{H256, U256}; use rlp::{Decodable, DecoderError, Encodable}; @@ -135,36 +132,6 @@ pub enum ChainHeader { Eth(EVMBlockHeader), } -impl ChainHeader { - fn evm_genesis() -> Self { - Self::Eth(EVMBlockHeader { - hash: GENESIS_PARENT_HASH, - receipts_root: vec![0; 32], - transactions_root: vec![0; 32], - }) - } - - fn tez_genesis() -> Self { - Self::Tez(TezBlockHeader { - hash: TezBlock::genesis_block_hash(), - }) - } - - pub fn genesis_header(chain_family: ChainFamily) -> ChainHeader { - match chain_family { - ChainFamily::Evm => Self::evm_genesis(), - ChainFamily::Michelson => Self::tez_genesis(), - } - } - - pub fn hash(&self) -> H256 { - match self { - Self::Eth(header) => header.hash, - Self::Tez(header) => header.hash, - } - } -} - impl From for BlockHeader { fn from(block: EthBlock) -> Self { Self { @@ -417,34 +384,6 @@ pub fn read_current_blueprint_header( Ok(block_header.blueprint_header) } -pub fn read_current_block_header_for_family( - host: &Host, - chain_family: &ChainFamily, -) -> Result, Error> { - match chain_family { - ChainFamily::Evm => { - let BlockHeader { - blueprint_header, - chain_header, - } = read_current_block_header::(host)?; - Ok(BlockHeader { - blueprint_header, - chain_header: ChainHeader::Eth(chain_header), - }) - } - ChainFamily::Michelson => { - let BlockHeader { - blueprint_header, - chain_header, - } = read_current_block_header::(host)?; - Ok(BlockHeader { - blueprint_header, - chain_header: ChainHeader::Tez(chain_header), - }) - } - } -} - /// For the tick model we only accept blueprints where cumulative size of chunks /// less or equal than 512kB. A chunk weights 4kB, then (512 * 1024) / 4096 = /// 128. @@ -475,12 +414,12 @@ pub enum DelayedTransactionFetchingResult { DelayedHashMissing(delayed_inbox::Hash), } -fn fetch_hashes_from_delayed_inbox( +pub fn fetch_hashes_from_delayed_inbox( host: &mut Host, delayed_hashes: Vec, delayed_inbox: &mut DelayedInbox, current_blueprint_size: usize, -) -> anyhow::Result<(DelayedTransactionFetchingResult>, usize)> { +) -> anyhow::Result<(DelayedTransactionFetchingResult, usize)> { let mut delayed_txs = vec![]; let mut total_size = current_blueprint_size; for tx_hash in delayed_hashes { @@ -506,12 +445,12 @@ fn fetch_hashes_from_delayed_inbox( } } Ok(( - DelayedTransactionFetchingResult::Ok(delayed_txs), + DelayedTransactionFetchingResult::Ok(Transactions::EthTxs(delayed_txs)), total_size, )) } -fn transactions_from_bytes( +pub fn transactions_from_bytes( transactions: Vec>, ) -> anyhow::Result> { transactions @@ -528,36 +467,37 @@ fn transactions_from_bytes( .collect::>>() } -fn fetch_delayed_txs( +pub fn fetch_delayed_txs( host: &mut Host, blueprint_with_hashes: BlueprintWithDelayedHashes, delayed_inbox: &mut DelayedInbox, current_blueprint_size: usize, -) -> anyhow::Result<(BlueprintValidity, usize)> { - let (mut delayed_txs, total_size) = match fetch_hashes_from_delayed_inbox( - host, - blueprint_with_hashes.delayed_hashes, - delayed_inbox, - current_blueprint_size, - )? { - (DelayedTransactionFetchingResult::Ok(delayed_txs), total_size) => { - (delayed_txs, total_size) - } - (DelayedTransactionFetchingResult::BlueprintTooLarge, total_size) => { - return Ok((BlueprintValidity::BlueprintTooLarge, total_size)); - } - (DelayedTransactionFetchingResult::DelayedHashMissing(hash), total_size) => { - return Ok((BlueprintValidity::DelayedHashMissing(hash), total_size)); - } - }; +) -> anyhow::Result<(BlueprintValidity, usize)> { + let (mut delayed_txs, total_size) = + match ChainConfig::fetch_hashes_from_delayed_inbox( + host, + blueprint_with_hashes.delayed_hashes, + delayed_inbox, + current_blueprint_size, + )? { + (DelayedTransactionFetchingResult::Ok(delayed_txs), total_size) => { + (delayed_txs, total_size) + } + (DelayedTransactionFetchingResult::BlueprintTooLarge, total_size) => { + return Ok((BlueprintValidity::BlueprintTooLarge, total_size)); + } + (DelayedTransactionFetchingResult::DelayedHashMissing(hash), total_size) => { + return Ok((BlueprintValidity::DelayedHashMissing(hash), total_size)); + } + }; let transactions_with_hashes = - transactions_from_bytes(blueprint_with_hashes.transactions)?; + ChainConfig::transactions_from_bytes(blueprint_with_hashes.transactions)?; delayed_txs.extend(transactions_with_hashes); Ok(( BlueprintValidity::Valid(Blueprint { - transactions: EthTxs(delayed_txs), + transactions: delayed_txs, timestamp: blueprint_with_hashes.timestamp, }), total_size, @@ -572,16 +512,16 @@ fn fetch_delayed_txs( pub const DEFAULT_MAX_BLUEPRINT_LOOKAHEAD_IN_SECONDS: i64 = 300i64; #[allow(clippy::too_many_arguments)] -fn parse_and_validate_blueprint( +fn parse_and_validate_blueprint( host: &mut Host, bytes: &[u8], delayed_inbox: &mut DelayedInbox, current_blueprint_size: usize, evm_node_flag: bool, max_blueprint_lookahead_in_seconds: i64, - parent_chain_header: &ChainHeader, + parent_chain_header: &ChainConfig::ChainHeader, head_timestamp: Timestamp, -) -> anyhow::Result<(BlueprintValidity, usize)> { +) -> anyhow::Result<(BlueprintValidity, usize)> { // Decode match rlp::decode::(bytes) { Err(e) => Ok((BlueprintValidity::DecoderError(e), bytes.len())), @@ -633,7 +573,7 @@ fn parse_and_validate_blueprint( } // Fetch delayed transactions - fetch_delayed_txs( + fetch_delayed_txs::<_, ChainConfig>( host, blueprint_with_hashes, delayed_inbox, @@ -659,27 +599,27 @@ fn invalidate_blueprint( host.store_delete(blueprint_path) } -fn read_all_chunks_and_validate( +fn read_all_chunks_and_validate( host: &mut Host, blueprint_path: &OwnedPath, nb_chunks: u16, config: &mut Configuration, - previous_chain_header: &ChainHeader, + previous_chain_header: &ChainConfig::ChainHeader, previous_timestamp: Timestamp, -) -> anyhow::Result<(Option>, usize)> { +) -> anyhow::Result<(Option>, usize)> { let mut chunks = vec![]; let mut size = 0; if nb_chunks > MAXIMUM_NUMBER_OF_CHUNKS { - invalidate_blueprint( + invalidate_blueprint::<_, ChainConfig::Transactions>( host, blueprint_path, - &BlueprintValidity::::BlueprintTooLarge, + &BlueprintValidity::BlueprintTooLarge, )?; return Ok((None, 0)); }; for i in 0..nb_chunks { let path = blueprint_chunk_path(blueprint_path, i)?; - let stored_chunk = read_rlp::>(host, &path)?; + let stored_chunk = read_rlp(host, &path)?; // The tick model is based on the size of the chunk, we overapproximate it. size += MAX_INPUT_MESSAGE_SIZE; match stored_chunk { @@ -699,16 +639,17 @@ fn read_all_chunks_and_validate( max_blueprint_lookahead_in_seconds, .. } => { - let validity = parse_and_validate_blueprint( - host, - chunks.concat().as_slice(), - delayed_inbox, - size, - *evm_node_flag, - *max_blueprint_lookahead_in_seconds, - previous_chain_header, - previous_timestamp, - )?; + let validity: (BlueprintValidity, usize) = + parse_and_validate_blueprint::<_, ChainConfig>( + host, + chunks.concat().as_slice(), + delayed_inbox, + size, + *evm_node_flag, + *max_blueprint_lookahead_in_seconds, + previous_chain_header, + previous_timestamp, + )?; if let (BlueprintValidity::Valid(blueprint), size_with_delayed_transactions) = validity { @@ -727,13 +668,13 @@ fn read_all_chunks_and_validate( } } -pub fn read_blueprint( +pub fn read_blueprint( host: &mut Host, config: &mut Configuration, number: U256, previous_timestamp: Timestamp, - previous_chain_header: &ChainHeader, -) -> anyhow::Result<(Option>, usize)> { + previous_chain_header: &ChainConfig::ChainHeader, +) -> anyhow::Result<(Option>, usize)> { let blueprint_path = blueprint_path(number)?; let exists = host.store_has(&blueprint_path)?.is_some(); if exists { @@ -748,7 +689,7 @@ pub fn read_blueprint( let available_chunks = n_subkeys as u16 - 1; if available_chunks == nb_chunks { // All chunks are available - let (blueprint, size) = read_all_chunks_and_validate( + let (blueprint, size) = read_all_chunks_and_validate::<_, ChainConfig>( host, &blueprint_path, nb_chunks, @@ -784,10 +725,9 @@ pub fn read_blueprint( pub fn read_next_blueprint( host: &mut Host, config: &mut Configuration, -) -> anyhow::Result<(Option>, usize)> { - let chain_family = ChainFamily::Evm; +) -> anyhow::Result<(Option>, usize)> { let (number, previous_timestamp, block_header) = - match read_current_block_header_for_family(host, &chain_family) { + match read_current_block_header::<_, EVMBlockHeader>(host) { Ok(BlockHeader { blueprint_header, chain_header, @@ -799,10 +739,16 @@ pub fn read_next_blueprint( Err(_) => ( U256::zero(), Timestamp::from(0), - ChainHeader::genesis_header(chain_family), + EVMBlockHeader::genesis_header(), ), }; - read_blueprint(host, config, number, previous_timestamp, &block_header) + read_blueprint::<_, crate::chains::EvmChainConfig>( + host, + config, + number, + previous_timestamp, + &block_header, + ) } pub fn drop_blueprint(host: &mut Host, number: U256) -> Result<(), Error> { @@ -823,6 +769,7 @@ mod tests { use super::*; use crate::block::GENESIS_PARENT_HASH; + use crate::chains::EvmChainConfig; use crate::configuration::{DalConfiguration, TezosContracts}; use crate::delayed_inbox::Hash; use crate::sequencer_blueprint::{rlp_roundtrip, rlp_roundtrip_f}; @@ -899,18 +846,18 @@ mod tests { let mut delayed_inbox = DelayedInbox::new(&mut host).expect("Delayed inbox should be created"); // Blueprint should have invalid parent hash - let validity = parse_and_validate_blueprint( + let validity = parse_and_validate_blueprint::<_, EvmChainConfig>( &mut host, blueprint_with_hashes_bytes.as_ref(), &mut delayed_inbox, 0, false, 500, - &ChainHeader::Eth(EVMBlockHeader { + &EVMBlockHeader { hash: GENESIS_PARENT_HASH, receipts_root: vec![0; 32], transactions_root: vec![0; 32], - }), + }, Timestamp::from(0), ) .expect("Should be able to parse blueprint"); @@ -965,18 +912,18 @@ mod tests { let mut delayed_inbox = DelayedInbox::new(&mut host).expect("Delayed inbox should be created"); // Blueprint should have invalid parent hash - let validity = parse_and_validate_blueprint( + let validity = parse_and_validate_blueprint::<_, EvmChainConfig>( &mut host, blueprint_with_hashes_bytes.as_ref(), &mut delayed_inbox, 0, false, 500, - &ChainHeader::Eth(EVMBlockHeader { + &EVMBlockHeader { hash: GENESIS_PARENT_HASH, receipts_root: vec![0; 32], transactions_root: vec![0; 32], - }), + }, Timestamp::from(0), ) .expect("Should be able to parse blueprint"); diff --git a/etherlink/kernel_latest/kernel/src/chains.rs b/etherlink/kernel_latest/kernel/src/chains.rs index 872e3b035063..40bce1e399b5 100644 --- a/etherlink/kernel_latest/kernel/src/chains.rs +++ b/etherlink/kernel_latest/kernel/src/chains.rs @@ -3,10 +3,32 @@ // SPDX-License-Identifier: MIT use crate::{ - fees::MINIMUM_BASE_FEE_PER_GAS, tick_model::constants::MAXIMUM_GAS_LIMIT, CHAIN_ID, + block::{eth_bip_from_blueprint, BlockComputationResult, TickCounter}, + block_in_progress::EthBlockInProgress, + blueprint::Blueprint, + blueprint_storage::{ + DelayedTransactionFetchingResult, EVMBlockHeader, TezBlockHeader, + }, + delayed_inbox::DelayedInbox, + fees::MINIMUM_BASE_FEE_PER_GAS, + l2block::L2Block, + simulation::start_simulation_mode, + tick_model::constants::MAXIMUM_GAS_LIMIT, + transaction::Transactions::EthTxs, + CHAIN_ID, }; -use evm_execution::configuration::EVMVersion; -use primitive_types::U256; +use anyhow::Context; +use evm_execution::{ + configuration::EVMVersion, precompiles::PrecompileBTreeMap, trace::TracerInput, +}; +use primitive_types::{H160, H256, U256}; +use rlp::{Decodable, Encodable}; +use std::fmt::{Debug, Display}; +use tezos_evm_logging::{log, Level::*}; +use tezos_evm_runtime::runtime::Runtime; +use tezos_smart_rollup::{outbox::OutboxQueue, types::Timestamp}; +use tezos_smart_rollup_host::path::Path; +use tezos_tezlink::block::TezBlock; #[derive(Clone, Copy, Debug)] pub enum ChainFamily { @@ -42,31 +64,271 @@ pub struct MichelsonChainConfig { chain_id: U256, } +pub trait BlockInProgressTrait { + fn number(&self) -> U256; +} + +impl BlockInProgressTrait for EthBlockInProgress { + fn number(&self) -> U256 { + self.number + } +} + +pub struct TezBlockInProgress { + number: U256, + timestamp: Timestamp, + previous_hash: H256, +} + +impl BlockInProgressTrait for TezBlockInProgress { + fn number(&self) -> U256 { + self.number + } +} + pub enum ChainConfig { Evm(Box), Michelson(MichelsonChainConfig), } -pub trait ChainConfigTrait: std::fmt::Debug { +pub trait TransactionsTrait { + fn extend(&mut self, other: Self); + fn number_of_txs(&self) -> usize; +} + +impl TransactionsTrait for crate::transaction::Transactions { + fn extend(&mut self, other: Self) { + let EthTxs(ref mut txs) = self; + let EthTxs(other) = other; + txs.extend(other) + } + fn number_of_txs(&self) -> usize { + let EthTxs(txs) = self; + txs.len() + } +} + +#[derive(Debug)] +pub struct TezTransactions {} + +impl TransactionsTrait for TezTransactions { + fn extend(&mut self, _: Self) {} + + fn number_of_txs(&self) -> usize { + 0 + } +} + +impl Encodable for TezTransactions { + fn rlp_append(&self, stream: &mut rlp::RlpStream) { + let Self {} = self; + stream.begin_list(0); + } +} + +impl Decodable for TezTransactions { + fn decode(_decoder: &rlp::Rlp) -> Result { + Ok(Self {}) + } +} + +pub trait ChainHeaderTrait { + fn hash(&self) -> H256; + + fn genesis_header() -> Self; +} + +impl ChainHeaderTrait for crate::blueprint_storage::EVMBlockHeader { + fn hash(&self) -> H256 { + self.hash + } + fn genesis_header() -> Self { + EVMBlockHeader { + hash: crate::block::GENESIS_PARENT_HASH, + receipts_root: vec![0; 32], + transactions_root: vec![0; 32], + } + } +} + +impl ChainHeaderTrait for crate::blueprint_storage::TezBlockHeader { + fn hash(&self) -> H256 { + self.hash + } + + fn genesis_header() -> Self { + Self { + hash: TezBlock::genesis_block_hash(), + } + } +} + +pub trait ChainConfigTrait: Debug { + type Transactions: TransactionsTrait + Encodable + Decodable + Debug; + + type BlockInProgress: BlockInProgressTrait; + + type ChainHeader: ChainHeaderTrait + Decodable; + fn get_chain_id(&self) -> U256; - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - chain_family: ChainFamily, - ) -> std::fmt::Result { + fn get_chain_family(&self) -> ChainFamily; + + fn fmt_with_family(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let chain_family = self.get_chain_family(); write!(f, "{{Chain family: {}, {:?}}}", chain_family, self) } + + fn fetch_hashes_from_delayed_inbox( + host: &mut impl Runtime, + delayed_hashes: Vec, + delayed_inbox: &mut DelayedInbox, + current_blueprint_size: usize, + ) -> anyhow::Result<(DelayedTransactionFetchingResult, usize)>; + + fn transactions_from_bytes(bytes: Vec>) + -> anyhow::Result; + + fn block_in_progress_from_blueprint( + &self, + host: &impl Runtime, + tick_counter: &crate::block::TickCounter, + current_block_number: U256, + previous_chain_header: Self::ChainHeader, + blueprint: Blueprint, + ) -> Self::BlockInProgress; + + fn read_block_in_progress( + host: &impl Runtime, + ) -> anyhow::Result>; + + #[allow(clippy::too_many_arguments)] + fn compute_bip( + &self, + host: &mut Host, + outbox_queue: &OutboxQueue<'_, impl Path>, + block_in_progress: Self::BlockInProgress, + precompiles: &PrecompileBTreeMap, + tick_counter: &mut TickCounter, + sequencer_pool_address: Option, + maximum_allowed_ticks: u64, + tracer_input: Option, + da_fee_per_byte: U256, + coinbase: H160, + ) -> anyhow::Result; + + fn start_simulation_mode( + &self, + host: &mut impl Runtime, + enable_fa_bridge: bool, + ) -> anyhow::Result<()>; } impl ChainConfigTrait for EvmChainConfig { + type Transactions = crate::transaction::Transactions; + + type BlockInProgress = crate::block_in_progress::EthBlockInProgress; + + type ChainHeader = crate::blueprint_storage::EVMBlockHeader; + fn get_chain_id(&self) -> U256 { self.chain_id } + + fn get_chain_family(&self) -> ChainFamily { + ChainFamily::Evm + } + + fn block_in_progress_from_blueprint( + &self, + host: &impl Runtime, + tick_counter: &crate::block::TickCounter, + current_block_number: U256, + header: Self::ChainHeader, + blueprint: Blueprint, + ) -> Self::BlockInProgress { + eth_bip_from_blueprint( + host, + self, + tick_counter, + current_block_number, + header, + blueprint, + ) + } + + fn transactions_from_bytes( + bytes: Vec>, + ) -> anyhow::Result { + Ok(EthTxs(crate::blueprint_storage::transactions_from_bytes( + bytes, + )?)) + } + + fn fetch_hashes_from_delayed_inbox( + host: &mut impl Runtime, + delayed_hashes: Vec, + delayed_inbox: &mut DelayedInbox, + current_blueprint_size: usize, + ) -> anyhow::Result<(DelayedTransactionFetchingResult, usize)> + { + crate::blueprint_storage::fetch_hashes_from_delayed_inbox( + host, + delayed_hashes, + delayed_inbox, + current_blueprint_size, + ) + } + + fn read_block_in_progress( + host: &impl Runtime, + ) -> anyhow::Result> { + crate::storage::read_block_in_progress(host) + } + + fn compute_bip( + &self, + host: &mut Host, + outbox_queue: &OutboxQueue<'_, impl Path>, + block_in_progress: Self::BlockInProgress, + precompiles: &PrecompileBTreeMap, + tick_counter: &mut TickCounter, + sequencer_pool_address: Option, + maximum_allowed_ticks: u64, + tracer_input: Option, + da_fee_per_byte: U256, + coinbase: H160, + ) -> anyhow::Result { + log!(host, Debug, "Computing the BlockInProgress for Etherlink"); + + crate::block::compute_bip( + host, + outbox_queue, + block_in_progress, + precompiles, + tick_counter, + sequencer_pool_address, + &self.limits, + maximum_allowed_ticks, + tracer_input, + self.chain_id, + da_fee_per_byte, + coinbase, + &self.evm_config, + ) + } + + fn start_simulation_mode( + &self, + host: &mut impl Runtime, + enable_fa_bridge: bool, + ) -> anyhow::Result<()> { + start_simulation_mode(host, enable_fa_bridge, &self.evm_config) + } } impl EvmChainConfig { - fn create_config( + pub fn create_config( chain_id: U256, limits: EvmLimits, evm_config: evm_execution::Config, @@ -88,9 +350,100 @@ impl EvmChainConfig { } impl ChainConfigTrait for MichelsonChainConfig { + type Transactions = TezTransactions; + type BlockInProgress = TezBlockInProgress; + type ChainHeader = TezBlockHeader; + fn get_chain_id(&self) -> U256 { self.chain_id } + + fn get_chain_family(&self) -> ChainFamily { + ChainFamily::Michelson + } + + fn block_in_progress_from_blueprint( + &self, + _host: &impl Runtime, + _tick_counter: &crate::block::TickCounter, + current_block_number: U256, + header: Self::ChainHeader, + blueprint: Blueprint, + ) -> Self::BlockInProgress { + TezBlockInProgress { + number: current_block_number, + timestamp: blueprint.timestamp, + previous_hash: header.hash, + } + } + + fn fetch_hashes_from_delayed_inbox( + _host: &mut impl Runtime, + _delayed_hashes: Vec, + _delayed_inbox: &mut DelayedInbox, + current_blueprint_size: usize, + ) -> anyhow::Result<(DelayedTransactionFetchingResult, usize)> + { + Ok(( + DelayedTransactionFetchingResult::Ok(TezTransactions {}), + current_blueprint_size, + )) + } + + fn transactions_from_bytes( + _bytes: Vec>, + ) -> anyhow::Result { + Ok(TezTransactions {}) + } + + fn read_block_in_progress( + _host: &impl Runtime, + ) -> anyhow::Result> { + Ok(None) + } + + fn compute_bip( + &self, + host: &mut Host, + _outbox_queue: &OutboxQueue<'_, impl Path>, + block_in_progress: Self::BlockInProgress, + _precompiles: &PrecompileBTreeMap, + _tick_counter: &mut TickCounter, + _sequencer_pool_address: Option, + _maximum_allowed_ticks: u64, + _tracer_input: Option, + _da_fee_per_byte: U256, + _coinbase: H160, + ) -> anyhow::Result { + let TezBlockInProgress { + number, + timestamp, + previous_hash, + } = block_in_progress; + log!( + host, + Debug, + "Computing the BlockInProgress for Tezlink at level {}", + number + ); + + let tezblock = TezBlock::new(number, timestamp, previous_hash); + let new_block = L2Block::Tezlink(tezblock); + crate::block_storage::store_current(host, &new_block) + .context("Failed to store the current block")?; + Ok(BlockComputationResult::Finished { + included_delayed_transactions: vec![], + block: new_block, + }) + } + + fn start_simulation_mode( + &self, + _host: &mut impl Runtime, + _enable_fa_bridge: bool, + ) -> anyhow::Result<()> { + Ok(()) + } } impl MichelsonChainConfig { @@ -131,7 +484,7 @@ impl ChainConfig { } } -impl std::fmt::Display for ChainFamily { +impl Display for ChainFamily { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Evm => write!(f, "EVM"), @@ -161,13 +514,12 @@ impl Default for ChainConfig { } } -impl std::fmt::Display for ChainConfig { +impl Display for ChainConfig { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let chain_family = self.get_chain_family(); match self { - ChainConfig::Evm(evm_chain_config) => evm_chain_config.fmt(f, chain_family), + ChainConfig::Evm(evm_chain_config) => evm_chain_config.fmt_with_family(f), ChainConfig::Michelson(michelson_chain_config) => { - michelson_chain_config.fmt(f, chain_family) + michelson_chain_config.fmt_with_family(f) } } } @@ -184,10 +536,15 @@ impl Default for EvmChainConfig { } #[cfg(test)] -pub fn test_chain_config() -> ChainConfig { - ChainConfig::new_evm_config( +pub fn test_evm_chain_config() -> EvmChainConfig { + EvmChainConfig::create_config( U256::from(CHAIN_ID), EvmLimits::default(), EVMVersion::current_test_config(), ) } + +#[cfg(test)] +pub fn test_chain_config() -> ChainConfig { + ChainConfig::Evm(Box::new(test_evm_chain_config())) +} diff --git a/etherlink/kernel_latest/kernel/src/configuration.rs b/etherlink/kernel_latest/kernel/src/configuration.rs index d73739d6c624..63c13837e2eb 100644 --- a/etherlink/kernel_latest/kernel/src/configuration.rs +++ b/etherlink/kernel_latest/kernel/src/configuration.rs @@ -247,9 +247,7 @@ pub fn fetch_configuration(host: &mut Host) -> Configuration { }, Err(err) => { log!(host, Fatal, "The kernel failed to created the delayed inbox, reverting configuration to proxy ({:?})", err); - Configuration { - ..Configuration::default() - } + Configuration::default() } } } diff --git a/etherlink/kernel_latest/kernel/src/inbox.rs b/etherlink/kernel_latest/kernel/src/inbox.rs index a36c0efae067..6ec24efe5532 100644 --- a/etherlink/kernel_latest/kernel/src/inbox.rs +++ b/etherlink/kernel_latest/kernel/src/inbox.rs @@ -7,7 +7,7 @@ use crate::blueprint_storage::store_sequencer_blueprint; use crate::bridge::Deposit; -use crate::chains::{ChainConfig, ChainFamily}; +use crate::chains::{ChainConfigTrait, ChainFamily, EvmChainConfig}; use crate::configuration::{DalConfiguration, TezosContracts}; use crate::dal::fetch_and_parse_sequencer_blueprint_from_dal; use crate::dal_slot_import_signal::DalSlotImportSignals; @@ -26,13 +26,10 @@ use crate::storage::{ }; use crate::tick_model::constants::TICKS_FOR_BLUEPRINT_INTERCEPT; use crate::tick_model::maximum_ticks_for_sequencer_chunk; -use crate::transaction::{ - Transaction, TransactionContent, Transactions, - Transactions::{EthTxs, TezTxs}, -}; +use crate::transaction::{Transaction, TransactionContent, Transactions}; +use crate::upgrade; use crate::upgrade::*; use crate::Error; -use crate::{simulation, upgrade}; use evm_execution::fa_bridge::deposit::FaDeposit; use primitive_types::U256; use sha3::{Digest, Keccak256}; @@ -416,7 +413,11 @@ enum ReadStatus { } #[allow(clippy::too_many_arguments)] -fn read_and_dispatch_input( +fn read_and_dispatch_input< + Host: Runtime, + Mode: Parsable + InputHandler, + ChainConfig: ChainConfigTrait, +>( host: &mut Host, smart_rollup_address: [u8; 20], tezos_contracts: &TezosContracts, @@ -453,14 +454,7 @@ fn read_and_dispatch_input( // kernel enters in simulation mode, reading will be done by the // simulation and all the previous and next transactions are // discarded. - match chain_configuration { - ChainConfig::Evm(evm) => simulation::start_simulation_mode( - host, - enable_fa_bridge, - evm.get_evm_config(), - ), - ChainConfig::Michelson(_) => Ok(()), - }?; + chain_configuration.start_simulation_mode(host, enable_fa_bridge)?; Ok(ReadStatus::FinishedIgnore) } InputResult::Input(input) => { @@ -482,20 +476,18 @@ pub fn read_proxy_inbox( tezos_contracts: &TezosContracts, enable_fa_bridge: bool, garbage_collect_blocks: bool, - chain_configuration: &ChainConfig, + chain_configuration: &EvmChainConfig, ) -> Result, anyhow::Error> { - let transactions = match ChainConfig::get_chain_family(chain_configuration) { - ChainFamily::Evm => EthTxs(vec![]), - ChainFamily::Michelson => TezTxs, + let mut res = ProxyInboxContent { + transactions: Transactions::EthTxs(vec![]), }; - let mut res = ProxyInboxContent { transactions }; // The mutable variable is used to retrieve the information of whether the // inbox was empty or not. As we consume all the inbox in one go, if the // variable remains true, that means that the inbox was already consumed // during this kernel run. let mut inbox_is_empty = true; loop { - match read_and_dispatch_input::( + match read_and_dispatch_input::( host, smart_rollup_address, tezos_contracts, @@ -546,7 +538,7 @@ pub enum StageOneStatus { } #[allow(clippy::too_many_arguments)] -pub fn read_sequencer_inbox( +pub fn read_sequencer_inbox( host: &mut Host, smart_rollup_address: [u8; 20], tezos_contracts: &TezosContracts, @@ -587,7 +579,7 @@ pub fn read_sequencer_inbox( ); return Ok(StageOneStatus::Reboot); }; - match read_and_dispatch_input::( + match read_and_dispatch_input::( host, smart_rollup_address, tezos_contracts, @@ -633,7 +625,7 @@ mod tests { blueprint_path, store_current_block_header, BlockHeader, BlueprintHeader, ChainHeader, EVMBlockHeader, }; - use crate::chains::test_chain_config; + use crate::chains::test_evm_chain_config; use crate::configuration::TezosContracts; use crate::dal_slot_import_signal::{ DalSlotIndicesList, DalSlotIndicesOfLevel, UnsignedDalSlotSignals, @@ -641,7 +633,7 @@ mod tests { use crate::parsing::RollupType; use crate::storage::*; use crate::tick_model::constants::MAX_ALLOWED_TICKS; - use crate::transaction::TransactionContent::Ethereum; + use crate::transaction::{TransactionContent::Ethereum, Transactions::EthTxs}; use primitive_types::U256; use rlp::Encodable; use std::fmt::Write; @@ -789,7 +781,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap() .unwrap(); @@ -821,7 +813,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap() .unwrap(); @@ -878,7 +870,7 @@ mod tests { }, false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap() .unwrap(); @@ -925,7 +917,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap(); @@ -977,7 +969,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap(); @@ -1017,7 +1009,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap(); @@ -1074,7 +1066,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap() .unwrap(); @@ -1096,7 +1088,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap() .unwrap(); @@ -1159,7 +1151,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap() .unwrap(); @@ -1184,7 +1176,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap(); assert!(inbox_content.is_some()); @@ -1196,7 +1188,7 @@ mod tests { &TezosContracts::default(), false, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap(); assert!(inbox_content.is_none()); @@ -1303,7 +1295,7 @@ mod tests { MAX_ALLOWED_TICKS, None, false, - &test_chain_config(), + &test_evm_chain_config(), ) .unwrap(); diff --git a/etherlink/kernel_latest/kernel/src/lib.rs b/etherlink/kernel_latest/kernel/src/lib.rs index 2d2b9893ee73..2d9b6c0634d2 100644 --- a/etherlink/kernel_latest/kernel/src/lib.rs +++ b/etherlink/kernel_latest/kernel/src/lib.rs @@ -5,7 +5,6 @@ // // SPDX-License-Identifier: MIT -use crate::chains::ChainConfig; use crate::configuration::{ fetch_chain_configuration, fetch_configuration, Configuration, CHAIN_ID, }; @@ -109,7 +108,7 @@ pub fn stage_zero(host: &mut Host) -> Result( host: &mut Host, smart_rollup_address: [u8; 20], - chain_config: &ChainConfig, + chain_config: &chains::ChainConfig, configuration: &mut Configuration, ) -> Result { log!(host, Debug, "Entering stage one."); @@ -300,13 +299,22 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { #[cfg(not(feature = "benchmark-bypass-stage2"))] { log!(host, Debug, "Entering stage two."); - if let block::ComputationResult::RebootNeeded = block::produce( - host, - &chain_configuration, - &mut configuration, - sequencer_pool_address, - trace_input, - ) + if let block::ComputationResult::RebootNeeded = match chain_configuration { + chains::ChainConfig::Evm(chain_configuration) => block::produce( + host, + &*chain_configuration, + &mut configuration, + sequencer_pool_address, + trace_input, + ), + chains::ChainConfig::Michelson(chain_configuration) => block::produce( + host, + &chain_configuration, + &mut configuration, + sequencer_pool_address, + trace_input, + ), + } .context("Failed during stage 2")? { host.mark_for_reboot()?; @@ -384,7 +392,7 @@ mod tests { use crate::block_storage; use crate::blueprint_storage::store_inbox_blueprint_by_number; - use crate::chains::{ChainConfig, EvmLimits}; + use crate::chains::test_evm_chain_config; use crate::configuration::Configuration; use crate::fees; use crate::main; @@ -397,9 +405,7 @@ mod tests { transaction::{Transaction, TransactionContent, Transactions}, upgrade::KernelUpgrade, }; - use evm::Config; use evm_execution::account_storage::{self, EthereumAccountStorage}; - use evm_execution::configuration::EVMVersion; use evm_execution::fa_bridge::deposit::{ticket_hash, FaDeposit}; use evm_execution::fa_bridge::test_utils::{ convert_h160, convert_u256, dummy_ticket, kernel_wrapper, ticket_balance_add, @@ -441,14 +447,6 @@ mod tests { const DUMMY_BASE_FEE_PER_GAS: u64 = 12345u64; const DUMMY_DA_FEE: u64 = 2_000_000_000_000u64; - fn dummy_configuration(evm_configuration: Config) -> ChainConfig { - ChainConfig::new_evm_config( - DUMMY_CHAIN_ID, - EvmLimits::default(), - evm_configuration, - ) - } - fn dummy_block_fees() -> BlockFees { BlockFees::new( DUMMY_BASE_FEE_PER_GAS.into(), @@ -613,7 +611,6 @@ mod tests { let block_fees = dummy_block_fees(); // Set the tick limit to 11bn ticks - 2bn, which is the old limit minus the safety margin. - let chain_config = dummy_configuration(EVMVersion::current_test_config()); let mut configuration = Configuration { maximum_allowed_ticks: 9_000_000_000, ..Configuration::default() @@ -629,7 +626,7 @@ mod tests { // If the upgrade is started, it should raise an error let computation_result = crate::block::produce( &mut host, - &chain_config, + &test_evm_chain_config(), &mut configuration, None, None, diff --git a/etherlink/kernel_latest/kernel/src/stage_one.rs b/etherlink/kernel_latest/kernel/src/stage_one.rs index 399a834b1ff2..780aa81d45e5 100644 --- a/etherlink/kernel_latest/kernel/src/stage_one.rs +++ b/etherlink/kernel_latest/kernel/src/stage_one.rs @@ -8,7 +8,7 @@ use crate::blueprint_storage::{ clear_all_blueprints, read_current_blueprint_header, store_forced_blueprint, store_inbox_blueprint, }; -use crate::chains::ChainConfig; +use crate::chains::{ChainConfig, ChainConfigTrait, EvmChainConfig}; use crate::configuration::{ Configuration, ConfigurationMode, DalConfiguration, TezosContracts, }; @@ -33,7 +33,7 @@ pub fn fetch_proxy_blueprints( tezos_contracts: &TezosContracts, enable_fa_bridge: bool, garbage_collect_blocks: bool, - chain_configuration: &ChainConfig, + chain_configuration: &EvmChainConfig, ) -> Result { if let Some(ProxyInboxContent { transactions }) = read_proxy_inbox( host, @@ -117,7 +117,7 @@ fn fetch_delayed_transactions( } #[allow(clippy::too_many_arguments)] -fn fetch_sequencer_blueprints( +fn fetch_sequencer_blueprints( host: &mut Host, smart_rollup_address: [u8; RAW_ROLLUP_ADDRESS_SIZE], tezos_contracts: &TezosContracts, @@ -164,18 +164,21 @@ fn fetch_sequencer_blueprints( pub fn fetch_blueprints( host: &mut Host, smart_rollup_address: [u8; RAW_ROLLUP_ADDRESS_SIZE], - chain_config: &ChainConfig, + chain_config: &crate::chains::ChainConfig, config: &mut Configuration, ) -> Result { - match &mut config.mode { - ConfigurationMode::Sequencer { - delayed_bridge, - delayed_inbox, - sequencer, - dal, - evm_node_flag: _, - max_blueprint_lookahead_in_seconds: _, - } => fetch_sequencer_blueprints( + match (chain_config, &mut config.mode) { + ( + ChainConfig::Evm(chain_config), + ConfigurationMode::Sequencer { + delayed_bridge, + delayed_inbox, + sequencer, + dal, + evm_node_flag: _, + max_blueprint_lookahead_in_seconds: _, + }, + ) => fetch_sequencer_blueprints( host, smart_rollup_address, &config.tezos_contracts, @@ -186,24 +189,55 @@ pub fn fetch_blueprints( config.maximum_allowed_ticks, config.enable_fa_bridge, config.garbage_collect_blocks, - chain_config, + &**chain_config, ), - ConfigurationMode::Proxy => fetch_proxy_blueprints( + ( + ChainConfig::Michelson(chain_config), + ConfigurationMode::Sequencer { + delayed_bridge, + delayed_inbox, + sequencer, + dal, + evm_node_flag: _, + max_blueprint_lookahead_in_seconds: _, + }, + ) => fetch_sequencer_blueprints( host, smart_rollup_address, &config.tezos_contracts, + delayed_bridge.clone(), + delayed_inbox, + sequencer.clone(), + dal.clone(), + config.maximum_allowed_ticks, config.enable_fa_bridge, config.garbage_collect_blocks, chain_config, ), + (ChainConfig::Evm(chain_config), ConfigurationMode::Proxy) => { + fetch_proxy_blueprints( + host, + smart_rollup_address, + &config.tezos_contracts, + config.enable_fa_bridge, + config.garbage_collect_blocks, + chain_config, + ) + } + (ChainConfig::Michelson(_), ConfigurationMode::Proxy) => { + // Proxy mode is only available for the EVM chain. + Ok(StageOneStatus::Done) + } } } #[cfg(test)] mod tests { use crate::{ - blueprint_storage::ChainHeader, - chains::{test_chain_config, ChainFamily}, + blueprint_storage::EVMBlockHeader, + chains::{ + test_chain_config, test_evm_chain_config, ChainHeaderTrait, TransactionsTrait, + }, dal_slot_import_signal::{ DalSlotImportSignals, DalSlotIndicesList, DalSlotIndicesOfLevel, UnsignedDalSlotSignals, @@ -405,10 +439,14 @@ mod tests { let mut host = MockKernelHost::default(); host.host .add_external(Bytes::from(hex::decode(DUMMY_TRANSACTION).unwrap())); - let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -430,10 +468,14 @@ mod tests { .add_external(Bytes::from(hex::decode(DUMMY_CHUNK1).unwrap())); host.host .add_external(Bytes::from(hex::decode(DUMMY_CHUNK2).unwrap())); - let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -450,10 +492,14 @@ mod tests { let mut host = MockKernelHost::default(); host.host .add_external(Bytes::from(hex::decode(DUMMY_TRANSACTION).unwrap())); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -482,10 +528,14 @@ mod tests { .add_external(Bytes::from(hex::decode(DUMMY_CHUNK1).unwrap())); host.host .add_external(Bytes::from(hex::decode(DUMMY_CHUNK2).unwrap())); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -511,18 +561,22 @@ mod tests { host.host.add_external(Bytes::from( hex::decode(DUMMY_BLUEPRINT_CHUNK_NUMBER_10).unwrap(), )); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); // The dummy chunk in the inbox is registered at block 10 - if read_blueprint( + if read_blueprint::<_, EvmChainConfig>( &mut host, &mut conf, U256::from(10), Timestamp::from(0), - &ChainHeader::genesis_header(ChainFamily::Evm), + &EVMBlockHeader::genesis_header(), ) .expect("Blueprint reading shouldn't fail") .0 @@ -547,10 +601,14 @@ mod tests { host.host.add_external(Bytes::from( hex::decode(DUMMY_BLUEPRINT_CHUNK_UNPARSABLE).unwrap(), )); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -576,7 +634,6 @@ mod tests { host.host.add_external(Bytes::from( hex::decode(DUMMY_BLUEPRINT_CHUNK_NUMBER_10).unwrap(), )); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); match read_proxy_inbox( @@ -585,7 +642,7 @@ mod tests { &conf.tezos_contracts, false, false, - &chain_config, + &test_evm_chain_config(), ) .unwrap() { @@ -620,7 +677,6 @@ mod tests { fn test_parsing_delayed_inbox(enable_dal: bool) { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); let metadata = TransferMetadata::new( delayed_bridge(&conf), @@ -629,8 +685,13 @@ mod tests { for message in dummy_delayed_transaction() { host.host.add_transfer(message, &metadata); } - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -657,7 +718,6 @@ mod tests { fn test_parsing_l1_contract_inbox(enable_dal: bool) { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); let metadata = TransferMetadata::new( ContractKt1Hash::from_b58check(DUMMY_INVALID_TICKETER).unwrap(), @@ -666,8 +726,13 @@ mod tests { for message in dummy_delayed_transaction() { host.host.add_transfer(message, &metadata); } - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -695,7 +760,6 @@ mod tests { #[test] fn test_parsing_delayed_inbox_rejected_in_proxy() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); let metadata = TransferMetadata::new( ContractKt1Hash::from_b58check(DUMMY_INVALID_TICKETER).unwrap(), @@ -704,8 +768,13 @@ mod tests { for message in dummy_delayed_transaction() { host.host.add_transfer(message, &metadata) } - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail").0 @@ -720,7 +789,6 @@ mod tests { #[test] fn test_deposit_in_proxy_mode() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); let metadata = TransferMetadata::new( conf.tezos_contracts.ticketer.clone().unwrap(), @@ -730,8 +798,13 @@ mod tests { dummy_deposit(conf.tezos_contracts.ticketer.clone().unwrap()), &metadata, ); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -749,7 +822,6 @@ mod tests { #[test] fn test_deposit_with_invalid_ticketer() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_proxy_configuration(); let metadata = TransferMetadata::new( ContractKt1Hash::from_b58check(DUMMY_INVALID_TICKETER).unwrap(), @@ -761,8 +833,13 @@ mod tests { ), &metadata, ); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); match read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -779,7 +856,6 @@ mod tests { fn test_deposit_in_sequencer_mode(enable_dal: bool) { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(enable_dal, None); let metadata = TransferMetadata::new( conf.tezos_contracts.ticketer.clone().unwrap(), @@ -789,8 +865,13 @@ mod tests { dummy_deposit(conf.tezos_contracts.ticketer.clone().unwrap()), &metadata, ); - fetch_blueprints(&mut host, DEFAULT_SR_ADDRESS, &chain_config, &mut conf) - .expect("fetch failed"); + fetch_blueprints( + &mut host, + DEFAULT_SR_ADDRESS, + &test_chain_config(), + &mut conf, + ) + .expect("fetch failed"); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -848,7 +929,6 @@ mod tests { fn setup_dal_signal( host: &mut MockKernelHost, - chain_config: &ChainConfig, conf: &mut Configuration, signal_slots: Option>, filled_slots: Option>, @@ -867,17 +947,16 @@ mod tests { let filled_slots = filled_slots.unwrap_or(dal_slots); fill_slots(host, filled_slots); - fetch_blueprints(host, DEFAULT_SR_ADDRESS, chain_config, conf) + fetch_blueprints(host, DEFAULT_SR_ADDRESS, &test_chain_config(), conf) .expect("fetch failed"); } #[test] fn test_dal_signal() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(true, None); - setup_dal_signal(&mut host, &chain_config, &mut conf, None, None); + setup_dal_signal(&mut host, &mut conf, None, None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -891,16 +970,9 @@ mod tests { #[test] fn test_dal_signal_empty_slot() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(false, Some(vec![8])); - setup_dal_signal( - &mut host, - &chain_config, - &mut conf, - Some(vec![21]), - Some(vec![]), - ); + setup_dal_signal(&mut host, &mut conf, Some(vec![21]), Some(vec![])); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -914,10 +986,9 @@ mod tests { #[test] fn test_dal_signal_with_multiple_slots_filled() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(true, Some(vec![6, 8])); - setup_dal_signal(&mut host, &chain_config, &mut conf, None, None); + setup_dal_signal(&mut host, &mut conf, None, None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -931,10 +1002,9 @@ mod tests { #[test] fn test_parsable_dal_signal_without_dal() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(false, None); - setup_dal_signal(&mut host, &chain_config, &mut conf, Some(vec![6]), None); + setup_dal_signal(&mut host, &mut conf, Some(vec![6]), None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") @@ -948,10 +1018,9 @@ mod tests { #[test] fn test_invalid_dal_signal() { let mut host = MockKernelHost::default(); - let chain_config = test_chain_config(); let mut conf = dummy_sequencer_config(true, Some(vec![8])); - setup_dal_signal(&mut host, &chain_config, &mut conf, Some(vec![21]), None); + setup_dal_signal(&mut host, &mut conf, Some(vec![21]), None); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") diff --git a/etherlink/kernel_latest/kernel/src/transaction.rs b/etherlink/kernel_latest/kernel/src/transaction.rs index de228d038fd1..f05e746fd75d 100644 --- a/etherlink/kernel_latest/kernel/src/transaction.rs +++ b/etherlink/kernel_latest/kernel/src/transaction.rs @@ -90,21 +90,12 @@ impl Decodable for TransactionContent { #[derive(PartialEq, Debug, Clone)] pub enum Transactions { EthTxs(Vec), - TezTxs, } impl Transactions { - pub fn number_of_txs(&self) -> usize { - match self { - Self::EthTxs(transactions) => transactions.len(), - Self::TezTxs => 0, - } - } - pub fn push(&mut self, tx: Transaction) { match self { Self::EthTxs(transactions) => transactions.push(tx), - Self::TezTxs => (), } } } @@ -115,9 +106,6 @@ impl Encodable for Transactions { Self::EthTxs(transactions) => { s.append_list(transactions); } - Self::TezTxs => { - s.append_list::(&[]); - } } } } -- GitLab