diff --git a/etherlink/kernel_evm/ethereum/src/block.rs b/etherlink/kernel_evm/ethereum/src/block.rs index fa5f117e032fb8957bd2d99925729d5442b44ba9..9831cef6f294f1c4d75971b85cd8cfbd8065e315 100644 --- a/etherlink/kernel_evm/ethereum/src/block.rs +++ b/etherlink/kernel_evm/ethereum/src/block.rs @@ -128,7 +128,7 @@ impl BlockConstants { } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct L2Block { +pub struct EthBlock { // This choice of a L2 block representation is totally // arbitrarily based on what is an Ethereum block and is // subject to change. @@ -153,7 +153,7 @@ pub struct L2Block { pub mix_hash: H256, } -impl L2Block { +impl EthBlock { #[allow(clippy::too_many_arguments)] pub fn new( number: U256, @@ -181,7 +181,7 @@ impl L2Block { timestamp, &None, ); - L2Block { + EthBlock { number, hash, parent_hash, @@ -231,7 +231,7 @@ impl L2Block { H256(Keccak256::digest(bytes).into()) } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> Result { let first = *bytes.first().ok_or(DecoderError::Custom("Empty bytes"))?; if first == 0x01 { let decoder = Rlp::new(&bytes[1..]); @@ -242,7 +242,7 @@ impl L2Block { } } - fn rlp_decode_v0(decoder: &Rlp) -> Result { + fn rlp_decode_v0(decoder: &Rlp) -> Result { if decoder.is_list() { if Ok(13) == decoder.item_count() { let mut it = decoder.iter(); @@ -264,7 +264,7 @@ impl L2Block { decode_transaction_hash_list(&next(&mut it)?, "transactions")?; let gas_used: U256 = decode_field_u256_le(&next(&mut it)?, "gas_used")?; let timestamp = decode_timestamp(&next(&mut it)?)?; - Ok(L2Block { + Ok(EthBlock { number, hash, parent_hash, @@ -289,7 +289,7 @@ impl L2Block { } } - fn rlp_decode_v1(decoder: &Rlp) -> Result { + fn rlp_decode_v1(decoder: &Rlp) -> Result { if decoder.is_list() { if Ok(15) == decoder.item_count() { let mut it = decoder.iter(); @@ -314,7 +314,7 @@ impl L2Block { let base_fee_per_gas: U256 = decode_field_u256_le(&next(&mut it)?, "base_fee_per_gas")?; let mix_hash: H256 = decode_field(&next(&mut it)?, "mix_hash")?; - Ok(L2Block { + Ok(EthBlock { number, hash, parent_hash, @@ -339,7 +339,7 @@ impl L2Block { } } - fn rlp_encode(self: &L2Block, s: &mut RlpStream) { + fn rlp_encode(self: &EthBlock, s: &mut RlpStream) { s.begin_list(15); append_u256_le(s, &self.number); s.append(&self.hash); @@ -361,7 +361,7 @@ impl L2Block { } } -impl VersionedEncoding for L2Block { +impl VersionedEncoding for EthBlock { const VERSION: u8 = 1; fn unversionned_encode(&self) -> bytes::BytesMut { @@ -378,7 +378,7 @@ impl VersionedEncoding for L2Block { #[cfg(test)] mod tests { - use super::L2Block; + use super::EthBlock; use crate::eth_gen::OwnedHash; use crate::rlp_helpers::VersionedEncoding; use crate::transaction::TRANSACTION_HASH_SIZE; @@ -386,9 +386,9 @@ mod tests { use primitive_types::{H256, U256}; use tezos_smart_rollup_encoding::timestamp::Timestamp; - fn block_encoding_roundtrip(v: L2Block) { + fn block_encoding_roundtrip(v: EthBlock) { let bytes = v.to_bytes(); - let v2 = L2Block::from_bytes(&bytes).expect("L2Block should be decodable"); + let v2 = EthBlock::from_bytes(&bytes).expect("EthBlock should be decodable"); assert_eq!(v, v2, "Roundtrip failed on {:?}", v) } @@ -397,8 +397,8 @@ mod tests { pub fn dummy_hash() -> OwnedHash { DUMMY_HASH.into() } - fn dummy_block(tx_length: usize) -> L2Block { - L2Block { + fn dummy_block(tx_length: usize) -> EthBlock { + EthBlock { number: U256::from(42), hash: H256::from([3u8; 32]), parent_hash: H256::from([2u8; 32]), @@ -420,7 +420,7 @@ mod tests { #[test] fn roundtrip_rlp() { for tx_length in 0..3 { - let v: L2Block = dummy_block(tx_length); + let v: EthBlock = dummy_block(tx_length); block_encoding_roundtrip(v); } } diff --git a/etherlink/kernel_evm/kernel/src/block.rs b/etherlink/kernel_evm/kernel/src/block.rs index a0b4a4e7b90110379a7e9ed4466bd375597d9500..1555f0bad9792dd578ca6a2e7b046547d4531eae 100644 --- a/etherlink/kernel_evm/kernel/src/block.rs +++ b/etherlink/kernel_evm/kernel/src/block.rs @@ -12,8 +12,8 @@ use crate::blueprint_storage::{ drop_blueprint, read_blueprint, read_current_block_header, store_current_block_header, BlockHeader, BlueprintHeader, EVMBlockHeader, }; +use crate::chains::{ChainConfig, EvmLimits}; use crate::configuration::ConfigurationMode; -use crate::configuration::Limits; use crate::delayed_inbox::DelayedInbox; use crate::error::Error; use crate::event::Event; @@ -32,7 +32,7 @@ use evm_execution::precompiles::PrecompileBTreeMap; use evm_execution::trace::TracerInput; use primitive_types::{H160, H256, U256}; use tezos_ethereum::block::BlockConstants; -use tezos_ethereum::block::L2Block; +use tezos_ethereum::block::EthBlock; use tezos_ethereum::transaction::TransactionHash; use tezos_evm_logging::{log, Level::*, Verbosity}; use tezos_evm_runtime::runtime::Runtime; @@ -76,7 +76,7 @@ pub enum BlockComputationResult { RebootNeeded, Finished { included_delayed_transactions: Vec, - block: Box, + block: Box, }, } @@ -120,7 +120,8 @@ fn compute( precompiles: &PrecompileBTreeMap, evm_account_storage: &mut EthereumAccountStorage, sequencer_pool_address: Option, - limits: &Limits, + maximum_allowed_ticks: u64, + limits: &EvmLimits, tracer_input: Option, evm_configuration: &Config, ) -> Result { @@ -139,7 +140,7 @@ fn compute( log!(host, Benchmarking, "Transaction data size: {}", data_size); // The current number of ticks remaining for the current `kernel_run` is allocated for the transaction. let allocated_ticks = estimate_remaining_ticks_for_transaction_execution( - limits.maximum_allowed_ticks, + maximum_allowed_ticks, block_in_progress.estimated_ticks_in_run, data_size, ); @@ -255,7 +256,6 @@ fn next_bip_from_blueprints( tick_counter: &TickCounter, config: &mut Configuration, kernel_upgrade: &Option, - minimum_base_fee_per_gas: U256, ) -> Result { let ( current_block_number, @@ -305,28 +305,33 @@ fn next_bip_from_blueprints( return Ok(BlueprintParsing::None); } } - let gas_price = crate::gas_price::base_fee_per_gas( - host, - blueprint.timestamp, - minimum_base_fee_per_gas, - ); - - let bip = block_in_progress::BlockInProgress::from_blueprint( - blueprint, - current_block_number, - current_block_parent_hash, - tick_counter.c, - gas_price, - receipts_root, - transactions_root, - ); - - tezos_evm_logging::log!( - host, - tezos_evm_logging::Level::Debug, - "bip: {bip:?}" - ); - Ok(BlueprintParsing::Next(Box::new(bip))) + match &config.chain_config { + ChainConfig::Evm(chain_config) => { + let gas_price = crate::gas_price::base_fee_per_gas( + host, + blueprint.timestamp, + chain_config.limits.minimum_base_fee_per_gas, + ); + + let bip = block_in_progress::BlockInProgress::from_blueprint( + blueprint, + current_block_number, + current_block_parent_hash, + tick_counter.c, + gas_price, + receipts_root, + transactions_root, + ); + + tezos_evm_logging::log!( + host, + tezos_evm_logging::Level::Debug, + "bip: {bip:?}" + ); + Ok(BlueprintParsing::Next(Box::new(bip))) + } + ChainConfig::Michelson(_) => panic!("Implement Tezlink"), + } } None => Ok(BlueprintParsing::None), } @@ -338,20 +343,21 @@ fn compute_bip( outbox_queue: &OutboxQueue<'_, impl Path>, mut block_in_progress: BlockInProgress, precompiles: &PrecompileBTreeMap, - evm_account_storage: &mut EthereumAccountStorage, tick_counter: &mut TickCounter, sequencer_pool_address: Option, - limits: &Limits, + limits: &EvmLimits, + maximum_allowed_ticks: u64, tracer_input: Option, chain_id: U256, - minimum_base_fee_per_gas: U256, da_fee_per_byte: U256, coinbase: H160, evm_configuration: &Config, ) -> anyhow::Result { + let mut evm_account_storage = + init_account_storage().context("Failed to initialize EVM account storage")?; let constants: BlockConstants = block_in_progress.constants( chain_id, - minimum_base_fee_per_gas, + limits.minimum_base_fee_per_gas, da_fee_per_byte, GAS_LIMIT, coinbase, @@ -362,8 +368,9 @@ fn compute_bip( &mut block_in_progress, &constants, precompiles, - evm_account_storage, + &mut evm_account_storage, sequencer_pool_address, + maximum_allowed_ticks, limits, tracer_input, evm_configuration, @@ -438,7 +445,7 @@ fn promote_block( safe_host: &mut SafeStorage<&mut Host>, outbox_queue: &OutboxQueue<'_, impl Path>, block_in_progress_provenance: &BlockInProgressProvenance, - block: L2Block, + block: EthBlock, config: &mut Configuration, delayed_txs: Vec, ) -> anyhow::Result<()> { @@ -480,8 +487,7 @@ pub fn produce( sequencer_pool_address: Option, tracer_input: Option, ) -> Result { - let chain_id = config.chain_config.chain_id; - let minimum_base_fee_per_gas = crate::retrieve_minimum_base_fee_per_gas(host)?; + let chain_id = config.chain_config.get_chain_id(); let da_fee_per_byte = crate::retrieve_da_fee(host)?; let kernel_upgrade = upgrade::read_kernel_upgrade(host)?; @@ -490,8 +496,6 @@ pub fn produce( // in blocks is set to the pool address. let coinbase = sequencer_pool_address.unwrap_or_default(); - let mut evm_account_storage = - init_account_storage().context("Failed to initialize EVM account storage")?; let mut tick_counter = TickCounter::new(0u64); let mut safe_host = SafeStorage { host }; @@ -516,7 +520,6 @@ pub fn produce( &tick_counter, config, &kernel_upgrade, - minimum_base_fee_per_gas, )? { BlueprintParsing::Next(bip) => bip, BlueprintParsing::None => { @@ -537,22 +540,25 @@ pub fn produce( }; let processed_blueprint = block_in_progress.number; - match compute_bip( - &mut safe_host, - &outbox_queue, - block_in_progress, - &precompiles, - &mut evm_account_storage, - &mut tick_counter, - sequencer_pool_address, - &config.limits, - tracer_input, - chain_id, - minimum_base_fee_per_gas, - da_fee_per_byte, - coinbase, - &config.chain_config.evm_configuration, - ) { + let computation_result = match &config.chain_config { + ChainConfig::Evm(chain_config) => compute_bip( + &mut safe_host, + &outbox_queue, + block_in_progress, + &precompiles, + &mut tick_counter, + sequencer_pool_address, + &chain_config.limits, + config.maximum_allowed_ticks, + tracer_input, + chain_id, + da_fee_per_byte, + coinbase, + &chain_config.evm_config, + ), + ChainConfig::Michelson(_) => panic!("Implement Tezlink"), + }; + match computation_result { Ok(BlockComputationResult::Finished { included_delayed_transactions, block, @@ -612,7 +618,6 @@ mod tests { use crate::blueprint_storage::read_next_blueprint; use crate::blueprint_storage::store_inbox_blueprint; use crate::blueprint_storage::store_inbox_blueprint_by_number; - use crate::configuration::ChainConfig; use crate::fees::DA_FEE_PER_BYTE; use crate::fees::MINIMUM_BASE_FEE_PER_GAS; use crate::inbox::Transaction; @@ -622,6 +627,7 @@ mod tests { use crate::storage::read_block_in_progress; use crate::storage::read_last_info_per_level_timestamp; use crate::storage::{read_transaction_receipt, read_transaction_receipt_status}; + use crate::tick_model::constants::MAX_ALLOWED_TICKS; use crate::{retrieve_block_fees, retrieve_chain_id}; use evm_execution::account_storage::{ account_path, init_account_storage, EthereumAccountStorage, @@ -689,7 +695,11 @@ mod tests { fn dummy_configuration(evm_configuration: Config) -> Configuration { Configuration { - chain_config: ChainConfig::new_evm_config(DUMMY_CHAIN_ID, evm_configuration), + chain_config: ChainConfig::new_evm_config( + DUMMY_CHAIN_ID, + EvmLimits::default(), + evm_configuration, + ), ..Configuration::default() } } @@ -1324,8 +1334,7 @@ mod tests { vec![0; 32], ); // run is almost full wrt ticks - let limits = Limits::default(); - block_in_progress.estimated_ticks_in_run = limits.maximum_allowed_ticks - 1000; + block_in_progress.estimated_ticks_in_run = MAX_ALLOWED_TICKS - 1000; // act let result = compute( @@ -1336,7 +1345,8 @@ mod tests { &precompiles, &mut evm_account_storage, None, - &limits, + MAX_ALLOWED_TICKS, + &EvmLimits::default(), None, &EVMVersion::current_test_config(), ) @@ -1609,13 +1619,8 @@ mod tests { 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 limits = Limits { - maximum_allowed_ticks: 9_000_000_000, - ..Limits::default() - }; - let mut configuration = Configuration { - limits, + maximum_allowed_ticks: 9_000_000_000, ..dummy_configuration(EVMVersion::current_test_config()) }; @@ -1689,13 +1694,8 @@ 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 limits = Limits { - maximum_allowed_ticks: 9_000_000_000, - ..Limits::default() - }; - let mut configuration = Configuration { - limits, + maximum_allowed_ticks: 9_000_000_000, ..dummy_configuration(EVMVersion::current_test_config()) }; store_block_fees(&mut host, &dummy_block_fees()).unwrap(); @@ -1846,13 +1846,8 @@ 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 limits = Limits { - maximum_allowed_ticks: 9_000_000_000, - ..Limits::default() - }; - let mut configuration = Configuration { - limits, + maximum_allowed_ticks: 9_000_000_000, ..dummy_configuration(EVMVersion::current_test_config()) }; // sanity check: no current block diff --git a/etherlink/kernel_evm/kernel/src/block_in_progress.rs b/etherlink/kernel_evm/kernel/src/block_in_progress.rs index 0726000fa5d1c96714edbcbdecf869ca1de2edd7..12a0e3ff898c3d87e71d2c112ca3cfe99db4be1b 100644 --- a/etherlink/kernel_evm/kernel/src/block_in_progress.rs +++ b/etherlink/kernel_evm/kernel/src/block_in_progress.rs @@ -18,7 +18,7 @@ use evm_execution::account_storage::EVM_ACCOUNTS_PATH; use primitive_types::{H160, H256, U256}; use rlp::{Decodable, DecoderError, Encodable}; use std::collections::VecDeque; -use tezos_ethereum::block::{BlockConstants, BlockFees, L2Block}; +use tezos_ethereum::block::{BlockConstants, BlockFees, EthBlock}; use tezos_ethereum::eth_gen::OwnedHash; use tezos_ethereum::rlp_helpers::*; use tezos_ethereum::transaction::{ @@ -442,7 +442,7 @@ impl BlockInProgress { self, host: &mut Host, block_constants: &BlockConstants, - ) -> Result { + ) -> Result { let state_root = Self::safe_store_get_hash(host, &EVM_ACCOUNTS_PATH)?; let receipts_root = self.receipts_root(host, &self.previous_receipts_root)?; let transactions_root = @@ -452,7 +452,7 @@ impl BlockInProgress { self.timestamp, block_constants.block_fees.minimum_base_fee_per_gas(), ); - let new_block = L2Block::new( + let new_block = EthBlock::new( self.number, self.valid_txs, self.timestamp, diff --git a/etherlink/kernel_evm/kernel/src/block_storage.rs b/etherlink/kernel_evm/kernel/src/block_storage.rs index f090c86b40f9adf14a8aa490cca2fa460350b4bb..22586cbdd07dc05ec9954498029d11d4e32b6530 100644 --- a/etherlink/kernel_evm/kernel/src/block_storage.rs +++ b/etherlink/kernel_evm/kernel/src/block_storage.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use primitive_types::{H256, U256}; -use tezos_ethereum::block::L2Block; +use tezos_ethereum::block::EthBlock; use tezos_ethereum::rlp_helpers::VersionedEncoding; use tezos_evm_logging::{ log, @@ -52,7 +52,7 @@ fn store_current_hash(host: &mut impl Runtime, hash: H256) -> anyhow::Result<()> fn store_block( host: &mut impl Runtime, - block: &L2Block, + block: &EthBlock, index_block: bool, ) -> anyhow::Result<()> { if index_block { @@ -68,7 +68,7 @@ fn store_block( fn store_current_index_or_not( host: &mut impl Runtime, - block: &L2Block, + block: &EthBlock, index_block: bool, ) -> anyhow::Result<()> { store_current_number(host, block.number)?; @@ -86,11 +86,11 @@ fn store_current_index_or_not( Ok(()) } -pub fn store_current(host: &mut impl Runtime, block: &L2Block) -> anyhow::Result<()> { +pub fn store_current(host: &mut impl Runtime, block: &EthBlock) -> anyhow::Result<()> { store_current_index_or_not(host, block, true) } -pub fn restore_current(host: &mut impl Runtime, block: &L2Block) -> anyhow::Result<()> { +pub fn restore_current(host: &mut impl Runtime, block: &EthBlock) -> anyhow::Result<()> { store_current_index_or_not(host, block, false) } @@ -102,11 +102,11 @@ pub fn read_current_hash(host: &impl Runtime) -> anyhow::Result { read_h256_be(host, &path::CURRENT_HASH) } -pub fn read_current(host: &mut impl Runtime) -> anyhow::Result { +pub fn read_current(host: &mut impl Runtime) -> anyhow::Result { let hash = read_current_hash(host)?; let block_path = path::path(hash)?; let bytes = &host.store_read_all(&block_path)?; - let block_from_bytes = L2Block::from_bytes(bytes)?; + let block_from_bytes = EthBlock::from_bytes(bytes)?; Ok(block_from_bytes) } diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index 71b469061a2fabb77f5c9b776647ab08b0612be0..1df6f8bef9c025eca6bc787da29ce80f9d447293 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -16,7 +16,7 @@ use primitive_types::{H256, U256}; use rlp::{Decodable, DecoderError, Encodable}; use sha3::{Digest, Keccak256}; use std::fmt::Debug; -use tezos_ethereum::block::L2Block; +use tezos_ethereum::block::EthBlock; use tezos_ethereum::eth_gen::OwnedHash; use tezos_ethereum::rlp_helpers::{ self, append_timestamp, append_u256_le, decode_field_u256_le, decode_timestamp, @@ -116,8 +116,8 @@ pub struct BlockHeader { pub evm_block_header: H, } -impl From for BlockHeader { - fn from(block: L2Block) -> Self { +impl From for BlockHeader { + fn from(block: EthBlock) -> Self { Self { blueprint_header: BlueprintHeader { number: block.number, @@ -640,10 +640,12 @@ mod tests { use super::*; use crate::block::GENESIS_PARENT_HASH; - use crate::configuration::{ChainConfig, DalConfiguration, Limits, TezosContracts}; + use crate::chains::ChainConfig; + use crate::configuration::{DalConfiguration, TezosContracts}; use crate::delayed_inbox::Hash; use crate::sequencer_blueprint::rlp_roundtrip; use crate::storage::store_last_info_per_level_timestamp; + use crate::tick_model::constants::MAX_ALLOWED_TICKS; use primitive_types::H256; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_ethereum::transaction::TRANSACTION_HASH_SIZE; @@ -679,7 +681,7 @@ mod tests { evm_node_flag: false, max_blueprint_lookahead_in_seconds: 100_000i64, }, - limits: Limits::default(), + maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, chain_config: ChainConfig::default(), garbage_collect_blocks: false, diff --git a/etherlink/kernel_evm/kernel/src/chains.rs b/etherlink/kernel_evm/kernel/src/chains.rs index 54ee5fa7d40675479d21731d6edc511b4a8203bf..7906077b59387c37e361d48bb18b6ea6b67d0ae4 100644 --- a/etherlink/kernel_evm/kernel/src/chains.rs +++ b/etherlink/kernel_evm/kernel/src/chains.rs @@ -2,12 +2,76 @@ // // 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, +}; + #[derive(Clone, Copy, Debug)] pub enum ChainFamily { Evm, Michelson, } +pub struct EvmChainConfig { + pub chain_id: U256, + pub limits: EvmLimits, + pub evm_config: evm_execution::Config, +} + +impl EvmChainConfig { + pub fn create_config( + chain_id: U256, + limits: EvmLimits, + evm_config: evm_execution::Config, + ) -> Self { + Self { + chain_id, + limits, + evm_config, + } + } +} + +pub struct MichelsonChainConfig { + pub chain_id: U256, +} + +#[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)) + } + + pub fn get_chain_family(&self) -> ChainFamily { + match self { + ChainConfig::Evm(_) => ChainFamily::Evm, + ChainConfig::Michelson(_) => ChainFamily::Michelson, + } + } + + pub fn get_chain_id(&self) -> U256 { + match self { + ChainConfig::Evm(evm_chain_config) => evm_chain_config.chain_id, + ChainConfig::Michelson(michelson_chain_config) => { + michelson_chain_config.chain_id + } + } + } +} + impl std::fmt::Display for ChainFamily { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -16,3 +80,60 @@ impl std::fmt::Display for ChainFamily { } } } + +#[derive(Clone, Copy, Debug)] +pub struct EvmLimits { + pub maximum_gas_limit: u64, + pub minimum_base_fee_per_gas: U256, +} + +impl Default for EvmLimits { + fn default() -> Self { + Self { + maximum_gas_limit: MAXIMUM_GAS_LIMIT, + minimum_base_fee_per_gas: MINIMUM_BASE_FEE_PER_GAS.into(), + } + } +} + +impl std::fmt::Display for ChainConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + 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 + ) + } + } + } +} + +impl Default for ChainConfig { + fn default() -> Self { + Self::Evm(EvmChainConfig::create_config( + U256::from(CHAIN_ID), + EvmLimits::default(), + EVMVersion::to_config(&EVMVersion::default()), + )) + } +} + +#[cfg(test)] +pub fn test_chain_config() -> ChainConfig { + ChainConfig::new_evm_config( + U256::from(CHAIN_ID), + EvmLimits::default(), + EVMVersion::current_test_config(), + ) +} diff --git a/etherlink/kernel_evm/kernel/src/configuration.rs b/etherlink/kernel_evm/kernel/src/configuration.rs index a44e1b2f7f5ce26941bff8e627ef304031822f48..f2d0ac9192d66ced8bf81521920d6c4bd185d90e 100644 --- a/etherlink/kernel_evm/kernel/src/configuration.rs +++ b/etherlink/kernel_evm/kernel/src/configuration.rs @@ -5,8 +5,9 @@ use crate::{ blueprint_storage::DEFAULT_MAX_BLUEPRINT_LOOKAHEAD_IN_SECONDS, - chains::ChainFamily, + chains::{ChainConfig, EvmLimits}, delayed_inbox::DelayedInbox, + retrieve_minimum_base_fee_per_gas, storage::{ dal_slots, enable_dal, evm_node_flag, is_enable_fa_bridge, max_blueprint_lookahead_in_seconds, read_admin, read_delayed_transaction_bridge, @@ -16,11 +17,7 @@ use crate::{ }, tick_model::constants::{MAXIMUM_GAS_LIMIT, MAX_ALLOWED_TICKS}, }; -use evm::Config; -use evm_execution::{ - configuration::{fetch_evm_configuration, EVMVersion}, - read_ticketer, -}; +use evm_execution::{configuration::fetch_evm_configuration, read_ticketer}; use primitive_types::U256; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_evm_logging::{log, Level::*}; @@ -68,60 +65,10 @@ impl std::fmt::Display for ConfigurationMode { } } -pub struct ChainConfig { - pub chain_id: U256, - pub chain_family: ChainFamily, - pub evm_configuration: Config, -} - -impl Default for ChainConfig { - fn default() -> Self { - Self { - chain_id: U256::from(CHAIN_ID), - chain_family: ChainFamily::Evm, - evm_configuration: EVMVersion::to_config(&EVMVersion::default()), - } - } -} - -impl std::fmt::Display for ChainConfig { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{{Chain id: {}, Chain informations: {}}}", - self.chain_id, self.chain_family - ) - } -} - -impl ChainConfig { - pub fn new_evm_config(chain_id: U256, evm_configuration: Config) -> Self { - ChainConfig { - chain_id, - chain_family: ChainFamily::Evm, - evm_configuration, - } - } -} - -pub struct Limits { - pub maximum_allowed_ticks: u64, - pub maximum_gas_limit: u64, -} - -impl Default for Limits { - fn default() -> Self { - Self { - maximum_allowed_ticks: MAX_ALLOWED_TICKS, - maximum_gas_limit: MAXIMUM_GAS_LIMIT, - } - } -} - pub struct Configuration { pub tezos_contracts: TezosContracts, pub mode: ConfigurationMode, - pub limits: Limits, + pub maximum_allowed_ticks: u64, pub enable_fa_bridge: bool, pub chain_config: ChainConfig, pub garbage_collect_blocks: bool, @@ -132,7 +79,7 @@ impl Default for Configuration { Self { tezos_contracts: TezosContracts::default(), mode: ConfigurationMode::Proxy, - limits: Limits::default(), + maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, chain_config: ChainConfig::default(), garbage_collect_blocks: false, @@ -224,16 +171,15 @@ fn fetch_tezos_contracts(host: &mut impl Runtime) -> TezosContracts { } } -pub fn fetch_limits(host: &mut impl Runtime) -> Limits { - let maximum_allowed_ticks = - read_maximum_allowed_ticks(host).unwrap_or(MAX_ALLOWED_TICKS); - +pub fn fetch_evm_limits(host: &mut impl Runtime) -> EvmLimits { let maximum_gas_limit = read_or_set_maximum_gas_per_transaction(host).unwrap_or(MAXIMUM_GAS_LIMIT); - Limits { - maximum_allowed_ticks, + let minimum_base_fee_per_gas = retrieve_minimum_base_fee_per_gas(host); + + EvmLimits { maximum_gas_limit, + minimum_base_fee_per_gas, } } @@ -252,13 +198,16 @@ pub fn fetch_configuration( chain_id: U256, ) -> Configuration { let tezos_contracts = fetch_tezos_contracts(host); - let limits = fetch_limits(host); + let maximum_allowed_ticks = + read_maximum_allowed_ticks(host).unwrap_or(MAX_ALLOWED_TICKS); + let evm_limits = fetch_evm_limits(host); let sequencer = sequencer(host).unwrap_or_default(); let enable_fa_bridge = is_enable_fa_bridge(host).unwrap_or_default(); let evm_configuration = fetch_evm_configuration(host); let dal: Option = fetch_dal_configuration(host); let evm_node_flag = evm_node_flag(host).unwrap_or(false); - let chain_config = ChainConfig::new_evm_config(chain_id, evm_configuration); + let chain_config = + ChainConfig::new_evm_config(chain_id, evm_limits, evm_configuration); match sequencer { Some(sequencer) => { let delayed_bridge = read_delayed_transaction_bridge(host) @@ -285,7 +234,7 @@ pub fn fetch_configuration( evm_node_flag, max_blueprint_lookahead_in_seconds, }, - limits, + maximum_allowed_ticks, enable_fa_bridge, chain_config, garbage_collect_blocks: !evm_node_flag, @@ -293,7 +242,7 @@ pub fn fetch_configuration( Err(err) => { log!(host, Fatal, "The kernel failed to created the delayed inbox, reverting configuration to proxy ({:?})", err); Configuration { - limits, + chain_config, ..Configuration::default() } } @@ -302,7 +251,7 @@ pub fn fetch_configuration( None => Configuration { tezos_contracts, mode: ConfigurationMode::Proxy, - limits, + maximum_allowed_ticks, enable_fa_bridge, chain_config, garbage_collect_blocks: false, diff --git a/etherlink/kernel_evm/kernel/src/inbox.rs b/etherlink/kernel_evm/kernel/src/inbox.rs index 7c80f4a37cd758aadfd5db14d2a0173b20f52fad..608add59a3d480ea8ababeb93d07f80e8d12fc62 100644 --- a/etherlink/kernel_evm/kernel/src/inbox.rs +++ b/etherlink/kernel_evm/kernel/src/inbox.rs @@ -7,7 +7,8 @@ use crate::blueprint_storage::store_sequencer_blueprint; use crate::bridge::Deposit; -use crate::configuration::{fetch_limits, DalConfiguration, TezosContracts}; +use crate::chains::ChainConfig; +use crate::configuration::{DalConfiguration, TezosContracts}; use crate::dal::fetch_and_parse_sequencer_blueprint_from_dal; use crate::dal_slot_import_signal::DalSlotImportSignals; use crate::delayed_inbox::DelayedInbox; @@ -29,7 +30,6 @@ use crate::tick_model::maximum_ticks_for_sequencer_chunk; use crate::upgrade::*; use crate::Error; use crate::{simulation, upgrade}; -use evm::Config; use evm_execution::fa_bridge::{deposit::FaDeposit, FA_DEPOSIT_PROXY_GAS_LIMIT}; use evm_execution::EthereumError; use primitive_types::U256; @@ -573,7 +573,7 @@ fn read_and_dispatch_input( res: &mut Mode::Inbox, enable_fa_bridge: bool, garbage_collect_blocks: bool, - evm_configuration: &Config, + chain_configuration: &ChainConfig, ) -> anyhow::Result { let input: InputResult = read_input( host, @@ -601,7 +601,14 @@ 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. - simulation::start_simulation_mode(host, enable_fa_bridge, evm_configuration)?; + match chain_configuration { + ChainConfig::Evm(evm) => simulation::start_simulation_mode( + host, + enable_fa_bridge, + &evm.evm_config, + ), + ChainConfig::Michelson(_) => Ok(()), + }?; Ok(ReadStatus::FinishedIgnore) } InputResult::Input(input) => { @@ -617,7 +624,7 @@ pub fn read_proxy_inbox( tezos_contracts: &TezosContracts, enable_fa_bridge: bool, garbage_collect_blocks: bool, - evm_configuration: &Config, + chain_configuration: &ChainConfig, ) -> Result, anyhow::Error> { let mut res = ProxyInboxContent { transactions: vec![], @@ -637,7 +644,7 @@ pub fn read_proxy_inbox( &mut res, enable_fa_bridge, garbage_collect_blocks, - evm_configuration, + chain_configuration, ) { Err(err) => // If we failed to read or dispatch the input. @@ -687,23 +694,22 @@ pub fn read_sequencer_inbox( sequencer: PublicKey, delayed_inbox: &mut DelayedInbox, enable_fa_bridge: bool, + maximum_allowed_ticks: u64, dal: Option, garbage_collect_blocks: bool, - evm_configuration: &Config, + chain_configuration: &ChainConfig, ) -> Result { // 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; - let limits = fetch_limits(host); let next_blueprint_number: U256 = crate::blueprint_storage::read_next_blueprint_number(host)?; let mut parsing_context = SequencerParsingContext { sequencer, delayed_bridge, - allocated_ticks: limits - .maximum_allowed_ticks + allocated_ticks: maximum_allowed_ticks .saturating_sub(TICKS_FOR_BLUEPRINT_INTERCEPT), dal_configuration: dal, buffer_transaction_chunks: None, @@ -717,9 +723,7 @@ pub fn read_sequencer_inbox( host, Benchmarking, "Estimated ticks: {}", - limits - .maximum_allowed_ticks - .saturating_sub(parsing_context.allocated_ticks) + maximum_allowed_ticks.saturating_sub(parsing_context.allocated_ticks) ); return Ok(StageOneStatus::Reboot); }; @@ -732,7 +736,7 @@ pub fn read_sequencer_inbox( delayed_inbox, enable_fa_bridge, garbage_collect_blocks, - evm_configuration, + chain_configuration, ) { Err(err) => // If we failed to read or dispatch the input. @@ -753,9 +757,7 @@ pub fn read_sequencer_inbox( host, Benchmarking, "Estimated ticks: {}", - limits - .maximum_allowed_ticks - .saturating_sub(parsing_context.allocated_ticks) + maximum_allowed_ticks.saturating_sub(parsing_context.allocated_ticks) ); return Ok(StageOneStatus::Done); } @@ -771,6 +773,7 @@ mod tests { blueprint_path, store_current_block_header, BlockHeader, BlueprintHeader, EVMBlockHeader, }; + use crate::chains::test_chain_config; use crate::configuration::TezosContracts; use crate::dal_slot_import_signal::{ DalSlotIndicesList, DalSlotIndicesOfLevel, UnsignedDalSlotSignals, @@ -778,7 +781,7 @@ mod tests { use crate::inbox::TransactionContent::Ethereum; use crate::parsing::RollupType; use crate::storage::*; - use evm_execution::configuration::EVMVersion; + use crate::tick_model::constants::MAX_ALLOWED_TICKS; use primitive_types::U256; use std::fmt::Write; use tezos_crypto_rs::hash::SmartRollupHash; @@ -925,7 +928,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap() .unwrap(); @@ -957,7 +960,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap() .unwrap(); @@ -1014,7 +1017,7 @@ mod tests { }, false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap() .unwrap(); @@ -1061,7 +1064,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap(); @@ -1113,7 +1116,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap(); @@ -1153,7 +1156,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap(); @@ -1210,7 +1213,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap() .unwrap(); @@ -1232,7 +1235,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap() .unwrap(); @@ -1295,7 +1298,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap() .unwrap(); @@ -1320,7 +1323,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap(); assert!(inbox_content.is_some()); @@ -1332,7 +1335,7 @@ mod tests { &TezosContracts::default(), false, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap(); assert!(inbox_content.is_none()); @@ -1435,9 +1438,10 @@ mod tests { pk.clone(), &mut delayed_inbox, false, + MAX_ALLOWED_TICKS, None, false, - &EVMVersion::current_test_config(), + &test_chain_config(), ) .unwrap(); diff --git a/etherlink/kernel_evm/kernel/src/lib.rs b/etherlink/kernel_evm/kernel/src/lib.rs index 436caee611fc1849d838a25dd866d2b35a1d27aa..6eefbba8977a335b48bc71194956dfb8524d1681 100644 --- a/etherlink/kernel_evm/kernel/src/lib.rs +++ b/etherlink/kernel_evm/kernel/src/lib.rs @@ -142,15 +142,22 @@ fn retrieve_chain_id(host: &mut Host) -> Result { } } -fn retrieve_minimum_base_fee_per_gas( - host: &mut Host, -) -> Result { +fn retrieve_minimum_base_fee_per_gas(host: &mut Host) -> U256 { match read_minimum_base_fee_per_gas(host) { - Ok(minimum_base_fee_per_gas) => Ok(minimum_base_fee_per_gas), + Ok(minimum_base_fee_per_gas) => minimum_base_fee_per_gas, Err(_) => { let minimum_base_fee_per_gas = crate::fees::MINIMUM_BASE_FEE_PER_GAS.into(); - store_minimum_base_fee_per_gas(host, minimum_base_fee_per_gas)?; - Ok(minimum_base_fee_per_gas) + if let Err(err) = + store_minimum_base_fee_per_gas(host, minimum_base_fee_per_gas) + { + log!( + host, + Error, + "Can't store the default minimum_base_fee: {:?}", + err + ); + } + minimum_base_fee_per_gas } } } @@ -188,7 +195,7 @@ fn retrieve_da_fee(host: &mut Host) -> Result { fn retrieve_block_fees( host: &mut Host, ) -> Result { - let minimum_base_fee_per_gas = retrieve_minimum_base_fee_per_gas(host)?; + let minimum_base_fee_per_gas = retrieve_minimum_base_fee_per_gas(host); let base_fee_per_gas = retrieve_base_fee_per_gas(host, minimum_base_fee_per_gas); let da_fee = retrieve_da_fee(host)?; let block_fees = tezos_ethereum::block::BlockFees::new( @@ -362,7 +369,8 @@ mod tests { use crate::block_storage; use crate::blueprint_storage::store_inbox_blueprint_by_number; - use crate::configuration::{ChainConfig, Configuration, Limits}; + use crate::chains::{ChainConfig, EvmLimits}; + use crate::configuration::Configuration; use crate::fees; use crate::main; use crate::parsing::RollupType; @@ -419,7 +427,11 @@ mod tests { fn dummy_configuration(evm_configuration: Config) -> Configuration { Configuration { - chain_config: ChainConfig::new_evm_config(DUMMY_CHAIN_ID, evm_configuration), + chain_config: ChainConfig::new_evm_config( + DUMMY_CHAIN_ID, + EvmLimits::default(), + evm_configuration, + ), ..Configuration::default() } } @@ -588,13 +600,8 @@ 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 limits = Limits { - maximum_allowed_ticks: 9_000_000_000, - ..Limits::default() - }; - let mut configuration = Configuration { - limits, + maximum_allowed_ticks: 9_000_000_000, ..dummy_configuration(EVMVersion::current_test_config()) }; diff --git a/etherlink/kernel_evm/kernel/src/simulation.rs b/etherlink/kernel_evm/kernel/src/simulation.rs index 8e0f4af3e277785a6fa4b1bae45ae25e919ca8ae..af6dc6b30e516630bf9e787ba4c49ed75500c498 100644 --- a/etherlink/kernel_evm/kernel/src/simulation.rs +++ b/etherlink/kernel_evm/kernel/src/simulation.rs @@ -9,12 +9,12 @@ // when the proxy node simulates directly use crate::block_storage; -use crate::configuration::fetch_limits; use crate::fees::simulation_add_gas_for_fees; use crate::storage::{ - read_last_info_per_level_timestamp, read_sequencer_pool_address, read_tracer_input, + read_last_info_per_level_timestamp, read_maximum_allowed_ticks, + read_sequencer_pool_address, read_tracer_input, }; -use crate::tick_model::constants::MAXIMUM_GAS_LIMIT; +use crate::tick_model::constants::{MAXIMUM_GAS_LIMIT, MAX_ALLOWED_TICKS}; use crate::{error::Error, error::StorageError, storage}; use crate::{parsable, parsing, retrieve_chain_id, tick_model}; @@ -373,7 +373,7 @@ impl Evaluation { evm_configuration: &Config, ) -> Result, Error> { let chain_id = retrieve_chain_id(host)?; - let minimum_base_fee_per_gas = crate::retrieve_minimum_base_fee_per_gas(host)?; + let minimum_base_fee_per_gas = crate::retrieve_minimum_base_fee_per_gas(host); let da_fee = crate::retrieve_da_fee(host)?; let coinbase = read_sequencer_pool_address(host).unwrap_or_default(); let mut evm_account_storage = account_storage::init_account_storage() @@ -450,10 +450,11 @@ impl Evaluation { let precompiles = precompiles::precompile_set::(enable_fa_withdrawals); let tx_data_size = self.data.len() as u64; - let limits = fetch_limits(host); + let maximum_allowed_ticks = + read_maximum_allowed_ticks(host).unwrap_or(MAX_ALLOWED_TICKS); let allocated_ticks = tick_model::estimate_remaining_ticks_for_transaction_execution( - limits.maximum_allowed_ticks, + maximum_allowed_ticks, 0, tx_data_size, ); diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index 4d5c4b4333961e14f6261a17a25591608a14e3a3..86f89e6a803321d9a55174dc2aea362cff8b81e3 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -8,6 +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::configuration::{ Configuration, ConfigurationMode, DalConfiguration, TezosContracts, }; @@ -17,7 +18,6 @@ use crate::inbox::{read_proxy_inbox, read_sequencer_inbox}; use crate::inbox::{ProxyInboxContent, StageOneStatus}; use crate::storage::read_last_info_per_level_timestamp; use anyhow::Ok; -use evm::Config; use std::ops::Add; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_evm_logging::{log, Level::*}; @@ -32,7 +32,7 @@ pub fn fetch_proxy_blueprints( tezos_contracts: &TezosContracts, enable_fa_bridge: bool, garbage_collect_blocks: bool, - evm_configuration: &Config, + chain_configuration: &ChainConfig, ) -> Result { if let Some(ProxyInboxContent { transactions }) = read_proxy_inbox( host, @@ -40,7 +40,7 @@ pub fn fetch_proxy_blueprints( tezos_contracts, enable_fa_bridge, garbage_collect_blocks, - evm_configuration, + chain_configuration, )? { let timestamp = read_last_info_per_level_timestamp(host).unwrap_or(Timestamp::from(0)); @@ -124,9 +124,10 @@ fn fetch_sequencer_blueprints( delayed_inbox: &mut DelayedInbox, sequencer: PublicKey, dal: Option, + maximum_allowed_ticks: u64, enable_fa_bridge: bool, garbage_collect_blocks: bool, - evm_configuration: &Config, + chain_configuration: &ChainConfig, ) -> Result { match read_sequencer_inbox( host, @@ -136,9 +137,10 @@ fn fetch_sequencer_blueprints( sequencer, delayed_inbox, enable_fa_bridge, + maximum_allowed_ticks, dal, garbage_collect_blocks, - evm_configuration, + chain_configuration, )? { StageOneStatus::Done => { // Check if there are timed-out transactions in the delayed inbox @@ -179,9 +181,10 @@ pub fn fetch_blueprints( delayed_inbox, sequencer.clone(), dal.clone(), + config.maximum_allowed_ticks, config.enable_fa_bridge, config.garbage_collect_blocks, - &config.chain_config.evm_configuration, + &config.chain_config, ), ConfigurationMode::Proxy => fetch_proxy_blueprints( host, @@ -189,7 +192,7 @@ pub fn fetch_blueprints( &config.tezos_contracts, config.enable_fa_bridge, config.garbage_collect_blocks, - &config.chain_config.evm_configuration, + &config.chain_config, ), } } @@ -197,14 +200,14 @@ pub fn fetch_blueprints( #[cfg(test)] mod tests { use crate::{ - configuration::{ChainConfig, Limits}, + chains::test_chain_config, dal_slot_import_signal::{ DalSlotImportSignals, DalSlotIndicesList, DalSlotIndicesOfLevel, UnsignedDalSlotSignals, }, parsing::DAL_SLOT_IMPORT_SIGNAL_TAG, + tick_model::constants::MAX_ALLOWED_TICKS, }; - use evm_execution::configuration::EVMVersion; use primitive_types::U256; use rlp::Encodable; use tezos_crypto_rs::hash::{HashTrait, SecretKeyEd25519, UnknownSignature}; @@ -274,9 +277,9 @@ mod tests { evm_node_flag: false, max_blueprint_lookahead_in_seconds: 100_000i64, }, - limits: Limits::default(), + maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, - chain_config: ChainConfig::default(), + chain_config: test_chain_config(), garbage_collect_blocks: false, } } @@ -289,9 +292,9 @@ mod tests { ..contracts }, mode: ConfigurationMode::Proxy, - limits: Limits::default(), + maximum_allowed_ticks: MAX_ALLOWED_TICKS, enable_fa_bridge: false, - chain_config: ChainConfig::default(), + chain_config: test_chain_config(), garbage_collect_blocks: false, } } @@ -564,7 +567,7 @@ mod tests { &conf.tezos_contracts, false, false, - &EVMVersion::current_test_config(), + &conf.chain_config, ) .unwrap() {