From 5e25a91b55461894ab2bae6489f10dc79713cab7 Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 10 Apr 2025 18:04:24 +0200 Subject: [PATCH 1/8] Kernel: Add storage_root_path path in chain configuration Use root path defined in chains.rs for Tezlink and Etherlink --- etherlink/kernel_latest/kernel/src/chains.rs | 13 +++++++++++ .../tezos_execution/src/context.rs | 23 +++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/chains.rs b/etherlink/kernel_latest/kernel/src/chains.rs index 7182493d59d6..f6f8b548efc5 100644 --- a/etherlink/kernel_latest/kernel/src/chains.rs +++ b/etherlink/kernel_latest/kernel/src/chains.rs @@ -32,6 +32,9 @@ use tezos_smart_rollup::{outbox::OutboxQueue, types::Timestamp}; use tezos_smart_rollup_host::path::{Path, RefPath}; use tezos_tezlink::block::TezBlock; +pub const ETHERLINK_SAFE_STORAGE_ROOT_PATH: RefPath = + RefPath::assert_from(b"/evm/world_state"); + pub const TEZLINK_SAFE_STORAGE_ROOT_PATH: RefPath = RefPath::assert_from(b"/tezlink"); #[derive(Clone, Copy, Debug)] @@ -178,6 +181,8 @@ pub trait ChainConfigTrait: Debug { fn get_chain_family(&self) -> ChainFamily; + fn _storage_root_path(&self) -> RefPath; + 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) @@ -340,6 +345,10 @@ impl ChainConfigTrait for EvmChainConfig { ) -> PrecompileBTreeMap { precompile_set::(enable_fa_bridge) } + + fn _storage_root_path(&self) -> RefPath { + ETHERLINK_SAFE_STORAGE_ROOT_PATH + } } impl EvmChainConfig { @@ -470,6 +479,10 @@ impl ChainConfigTrait for MichelsonChainConfig { ) -> PrecompileBTreeMap { PrecompileBTreeMap::new() } + + fn _storage_root_path(&self) -> RefPath { + TEZLINK_SAFE_STORAGE_ROOT_PATH + } } impl MichelsonChainConfig { diff --git a/etherlink/kernel_latest/tezos_execution/src/context.rs b/etherlink/kernel_latest/tezos_execution/src/context.rs index 60003315b033..f27e0aaeb2a4 100644 --- a/etherlink/kernel_latest/tezos_execution/src/context.rs +++ b/etherlink/kernel_latest/tezos_execution/src/context.rs @@ -2,13 +2,10 @@ // // SPDX-License-Identifier: MIT -use tezos_smart_rollup_host::path::{OwnedPath, RefPath}; +use tezos_smart_rollup_host::path::{concat, OwnedPath, Path, PathError, RefPath}; // TODO: https://gitlab.com/tezos/tezos/-/issues/7867: add the missing paths -// This path should be the only one to refers to '/tezlink/context' -const CONTEXT_PATH: RefPath = RefPath::assert_from(b"/tezlink/context"); - // Instead of using directly the paths, we construct a Context object that holds the // path to the context and does the concatenations. // This will prevent '/tezlink/context' to appear at multiple place like '/evm/world_state' @@ -17,10 +14,17 @@ pub struct Context { } impl Context { - #[allow(dead_code)] + pub fn from(root: &impl Path) -> Result { + let context = RefPath::assert_from(b"/context"); + let path = concat(root, &context)?; + Ok(Self { path }) + } + + #[cfg(test)] pub fn init_context() -> Self { - Context { - path: CONTEXT_PATH.into(), + let path = RefPath::assert_from(b"/tezlink/context"); + Self { + path: OwnedPath::from(path), } } } @@ -30,25 +34,20 @@ pub mod contracts { use super::Context; - #[allow(dead_code)] const ROOT: RefPath = RefPath::assert_from(b"/contracts"); - #[allow(dead_code)] const INDEX: RefPath = RefPath::assert_from(b"/index"); - #[allow(dead_code)] const GLOBAL_COUNTER: RefPath = RefPath::assert_from(b"/global_counter"); pub fn root(context: &Context) -> Result { concat(&context.path, &ROOT) } - #[allow(dead_code)] pub fn index(context: &Context) -> Result { concat(&root(context)?, &INDEX) } - #[allow(dead_code)] pub fn global_counter(context: &Context) -> Result { concat(&root(context)?, &GLOBAL_COUNTER) } -- GitLab From e42c7316e3311fe6faa5cd4d2a57876e2f27b2c2 Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 10 Apr 2025 18:00:17 +0200 Subject: [PATCH 2/8] Kernel: Make safe storage parametrable (to be reused by Tezlink) --- etherlink/kernel_latest/kernel/src/block.rs | 17 +++++++++++++---- etherlink/kernel_latest/kernel/src/chains.rs | 6 +++--- etherlink/kernel_latest/kernel/src/lib.rs | 10 +++++++--- .../kernel_latest/runtime/src/safe_storage.rs | 10 +++++----- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index e13383e64dbb..990eaa782108 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -41,7 +41,7 @@ use tezos_evm_runtime::runtime::Runtime; 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_smart_rollup_host::path::{OwnedPath, Path}; pub const GENESIS_PARENT_HASH: H256 = H256([0xff; 32]); @@ -478,7 +478,10 @@ pub fn produce( let mut tick_counter = TickCounter::new(0u64); - let mut safe_host = SafeStorage { host }; + let mut safe_host = SafeStorage { + host, + world_state: OwnedPath::from(&chain_config.storage_root_path()), + }; let outbox_queue = OutboxQueue::new(&WITHDRAWAL_OUTBOX_QUEUE, u32::MAX)?; let precompiles = chain_config.precompiles_set(config.enable_fa_bridge); @@ -1669,7 +1672,10 @@ mod tests { matches!(computation_result, ComputationResult::RebootNeeded); // The block is in progress, therefore it is in the safe storage. - let safe_host = SafeStorage { host: &mut host }; + let safe_host = SafeStorage { + host: &mut host, + world_state: OwnedPath::from(&chain_config.storage_root_path()), + }; let bip = read_block_in_progress(&safe_host) .expect("Should be able to read the block in progress") .expect("The reboot context should have a block in progress"); @@ -1767,7 +1773,10 @@ mod tests { matches!(computation_result, ComputationResult::RebootNeeded); // The block is in progress, therefore it is in the safe storage. - let safe_host = SafeStorage { host: &mut host }; + let safe_host = SafeStorage { + host: &mut host, + world_state: OwnedPath::from(&chain_config.storage_root_path()), + }; let bip = read_block_in_progress(&safe_host) .expect("Should be able to read the block in progress") .expect("The reboot context should have a block in progress"); diff --git a/etherlink/kernel_latest/kernel/src/chains.rs b/etherlink/kernel_latest/kernel/src/chains.rs index f6f8b548efc5..62bb412346ea 100644 --- a/etherlink/kernel_latest/kernel/src/chains.rs +++ b/etherlink/kernel_latest/kernel/src/chains.rs @@ -181,7 +181,7 @@ pub trait ChainConfigTrait: Debug { fn get_chain_family(&self) -> ChainFamily; - fn _storage_root_path(&self) -> RefPath; + fn storage_root_path(&self) -> RefPath; fn fmt_with_family(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let chain_family = self.get_chain_family(); @@ -346,7 +346,7 @@ impl ChainConfigTrait for EvmChainConfig { precompile_set::(enable_fa_bridge) } - fn _storage_root_path(&self) -> RefPath { + fn storage_root_path(&self) -> RefPath { ETHERLINK_SAFE_STORAGE_ROOT_PATH } } @@ -480,7 +480,7 @@ impl ChainConfigTrait for MichelsonChainConfig { PrecompileBTreeMap::new() } - fn _storage_root_path(&self) -> RefPath { + fn storage_root_path(&self) -> RefPath { TEZLINK_SAFE_STORAGE_ROOT_PATH } } diff --git a/etherlink/kernel_latest/kernel/src/lib.rs b/etherlink/kernel_latest/kernel/src/lib.rs index e168fd981efa..c92a6415d7be 100644 --- a/etherlink/kernel_latest/kernel/src/lib.rs +++ b/etherlink/kernel_latest/kernel/src/lib.rs @@ -14,6 +14,7 @@ use crate::migration::storage_migration; use crate::stage_one::fetch_blueprints; use crate::storage::{read_sequencer_pool_address, PRIVATE_FLAG_PATH}; use anyhow::Context; +use chains::ETHERLINK_SAFE_STORAGE_ROOT_PATH; use delayed_inbox::DelayedInbox; use fallback_upgrade::fallback_backup_kernel; use inbox::StageOneStatus; @@ -29,7 +30,6 @@ use storage::{ use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_evm_logging::{log, Level::*, Verbosity}; use tezos_evm_runtime::runtime::{KernelHost, Runtime}; -use tezos_evm_runtime::safe_storage::WORLD_STATE_PATH; use tezos_smart_rollup::entrypoint; use tezos_smart_rollup::michelson::MichelsonUnit; use tezos_smart_rollup::outbox::{ @@ -359,12 +359,16 @@ pub fn kernel_loop(host: &mut H let world_state_subkeys = host .host - .store_count_subkeys(&WORLD_STATE_PATH) + .store_count_subkeys(ÐERLINK_SAFE_STORAGE_ROOT_PATH) .expect("The kernel failed to read the number of /evm/world_state subkeys"); if world_state_subkeys == 0 { host.host - .store_write(&WORLD_STATE_PATH, "Un festival de GADT".as_bytes(), 0) + .store_write( + ÐERLINK_SAFE_STORAGE_ROOT_PATH, + "Un festival de GADT".as_bytes(), + 0, + ) .unwrap(); } diff --git a/etherlink/kernel_latest/runtime/src/safe_storage.rs b/etherlink/kernel_latest/runtime/src/safe_storage.rs index 3147795e3edf..3dadd8584876 100644 --- a/etherlink/kernel_latest/runtime/src/safe_storage.rs +++ b/etherlink/kernel_latest/runtime/src/safe_storage.rs @@ -19,7 +19,6 @@ use tezos_smart_rollup_host::{ }; pub const TMP_PATH: RefPath = RefPath::assert_from(b"/tmp"); -pub const WORLD_STATE_PATH: RefPath = RefPath::assert_from(b"/evm/world_state"); pub const TRACE_PATH: RefPath = RefPath::assert_from(b"/evm/trace"); pub fn safe_path(path: &T) -> Result { @@ -28,6 +27,7 @@ pub fn safe_path(path: &T) -> Result { pub struct SafeStorage { pub host: Runtime, + pub world_state: OwnedPath, } impl InternalRuntime for SafeStorage<&mut Host> { @@ -234,13 +234,13 @@ impl Verbosity for SafeStorage<&mut Host> { impl SafeStorage<&mut Host> { pub fn start(&mut self) -> Result<(), RuntimeError> { - let tmp_path = safe_path(&WORLD_STATE_PATH)?; - self.host.store_copy(&WORLD_STATE_PATH, &tmp_path) + let tmp_path = safe_path(&self.world_state)?; + self.host.store_copy(&self.world_state, &tmp_path) } pub fn promote(&mut self) -> Result<(), RuntimeError> { - let tmp_path = safe_path(&WORLD_STATE_PATH)?; - self.host.store_move(&tmp_path, &WORLD_STATE_PATH) + let tmp_path = safe_path(&self.world_state)?; + self.host.store_move(&tmp_path, &self.world_state) } // Only used in tracing mode, so that the trace doesn't polute the world -- GitLab From 3b67a7b5517bc8817831e2df6ab5cca4c83ee06d Mon Sep 17 00:00:00 2001 From: arnaud Date: Wed, 16 Apr 2025 17:55:10 +0200 Subject: [PATCH 3/8] Kernel/Block storage: Parametrize block storage functions Instead of having paths as constant we concat PATH Kernel/Block Storage: Remove PATH and use path coming from chain config instead --- etherlink/kernel_latest/kernel/src/block.rs | 81 ++++++++---- .../kernel/src/block_in_progress.rs | 3 +- .../kernel_latest/kernel/src/block_storage.rs | 115 ++++++++++++------ etherlink/kernel_latest/kernel/src/chains.rs | 3 +- etherlink/kernel_latest/kernel/src/inbox.rs | 5 +- etherlink/kernel_latest/kernel/src/lib.rs | 9 +- .../kernel_latest/kernel/src/migration.rs | 15 ++- .../kernel_latest/kernel/src/simulation.rs | 8 +- .../kernel_latest/kernel/src/stage_one.rs | 6 +- 9 files changed, 173 insertions(+), 72 deletions(-) diff --git a/etherlink/kernel_latest/kernel/src/block.rs b/etherlink/kernel_latest/kernel/src/block.rs index 990eaa782108..078f480a3ef9 100644 --- a/etherlink/kernel_latest/kernel/src/block.rs +++ b/etherlink/kernel_latest/kernel/src/block.rs @@ -598,13 +598,10 @@ pub fn produce( mod tests { use super::*; use crate::block_storage; - use crate::block_storage::read_current_number; use crate::blueprint::Blueprint; use crate::blueprint_storage::store_inbox_blueprint; use crate::blueprint_storage::store_inbox_blueprint_by_number; - use crate::chains::{ - ChainFamily, EvmChainConfig, MichelsonChainConfig, TezTransactions, - }; + use crate::chains::{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; @@ -632,6 +629,13 @@ mod tests { use tezos_evm_runtime::runtime::MockKernelHost; use tezos_evm_runtime::runtime::Runtime; use tezos_smart_rollup_encoding::timestamp::Timestamp; + use tezos_smart_rollup_host::path::concat; + use tezos_smart_rollup_host::path::RefPath; + + fn read_current_number(host: &impl Runtime) -> anyhow::Result { + Ok(crate::blueprint_storage::read_current_blueprint_header(host)?.number) + } + use tezos_smart_rollup_host::runtime::Runtime as SdkRuntime; fn blueprint(transactions: Vec) -> Blueprint { @@ -886,8 +890,15 @@ mod tests { .expect("The block production failed."); } - fn assert_current_block_reading_validity(host: &mut Host) { - match block_storage::read_current(host, &ChainFamily::Evm) { + fn assert_current_block_reading_validity( + host: &mut Host, + chain_config: &impl ChainConfigTrait, + ) { + match block_storage::read_current( + host, + &chain_config.storage_root_path(), + &chain_config.get_chain_family(), + ) { Ok(_) => (), Err(e) => { panic!("Block reading failed: {:?}\n", e) @@ -903,6 +914,16 @@ mod tests { let chain_config = dummy_tez_config(); let mut config = dummy_configuration(); + // We need to store something at the tezlink root path, + // otherwise the copy of the root done by the safe storage will fail + let path = concat( + &chain_config.storage_root_path(), + &RefPath::assert_from(b"/fee"), + ) + .expect("Path concatenation should have succeeded"); + host.store_write_all(&path, &[4; 32]) + .expect("Write in durable storage should have succeeded"); + store_blueprints::<_, MichelsonChainConfig>( &mut host, vec![ @@ -1216,11 +1237,13 @@ mod tests { fn test_read_storage_current_block_after_block_production_with_filled_queue() { let mut host = MockKernelHost::default(); + let chain_config = dummy_evm_config(EVMVersion::current_test_config()); + let mut evm_account_storage = init_account_storage().unwrap(); produce_block_with_several_valid_txs(&mut host, &mut evm_account_storage); - assert_current_block_reading_validity(&mut host); + assert_current_block_reading_validity(&mut host, &chain_config); } #[test] @@ -1285,8 +1308,11 @@ mod tests { ) .unwrap(); - let blocks_index = - block_storage::internal_for_tests::init_blocks_index().unwrap(); + let chain_config = dummy_evm_config(EVMVersion::current_test_config()); + let blocks_index = block_storage::internal_for_tests::init_blocks_index( + &chain_config.storage_root_path(), + ) + .unwrap(); store_blueprints::<_, EvmChainConfig>(&mut host, vec![blueprint(vec![])]); @@ -1302,7 +1328,7 @@ mod tests { store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &dummy_evm_config(EVMVersion::current_test_config()), + &chain_config, &mut dummy_configuration(), None, None, @@ -1311,12 +1337,15 @@ mod tests { let new_number_of_blocks_indexed = blocks_index.length(&host).unwrap(); - let current_block_hash = - block_storage::read_current(&mut host, &ChainFamily::Evm) - .unwrap() - .hash() - .as_bytes() - .to_vec(); + let current_block_hash = block_storage::read_current( + &mut host, + &chain_config.storage_root_path(), + &chain_config.get_chain_family(), + ) + .unwrap() + .hash() + .as_bytes() + .to_vec(); assert_eq!(number_of_blocks_indexed + 1, new_number_of_blocks_indexed); @@ -1499,8 +1528,8 @@ mod tests { } fn check_current_block_number(host: &mut Host, nb: usize) { - let current_nb = block_storage::read_current_number(host) - .expect("Should have manage to check block number"); + let current_nb = + read_current_number(host).expect("Should have manage to check block number"); assert_eq!(current_nb, U256::from(nb), "Incorrect block number"); } @@ -1508,13 +1537,14 @@ mod tests { fn test_first_blocks() { let mut host = MockKernelHost::default(); + let chain_config = dummy_evm_config(EVMVersion::current_test_config()); // first block should be 0 let blueprint = almost_empty_blueprint(); store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); store_block_fees(&mut host, &dummy_block_fees()).unwrap(); produce( &mut host, - &dummy_evm_config(EVMVersion::current_test_config()), + &chain_config, &mut dummy_configuration(), None, None, @@ -1527,7 +1557,7 @@ mod tests { store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); produce( &mut host, - &dummy_evm_config(EVMVersion::current_test_config()), + &chain_config, &mut dummy_configuration(), None, None, @@ -1540,7 +1570,7 @@ mod tests { store_inbox_blueprint(&mut host, blueprint).expect("Should store a blueprint"); produce( &mut host, - &dummy_evm_config(EVMVersion::current_test_config()), + &chain_config, &mut dummy_configuration(), None, None, @@ -1615,7 +1645,7 @@ mod tests { // sanity check: no current block assert!( - block_storage::read_current_number(&host).is_err(), + read_current_number(&host).is_err(), "Should not have found current block number" ); @@ -1664,7 +1694,7 @@ mod tests { // test no new block assert!( - block_storage::read_current_number(&host).is_err(), + read_current_number(&host).is_err(), "Should not have found current block number" ); @@ -1708,7 +1738,7 @@ mod tests { // sanity check: no current block assert!( - block_storage::read_current_number(&host).is_err(), + read_current_number(&host).is_err(), "Should not have found current block number" ); //provision sender account @@ -1763,8 +1793,7 @@ mod tests { // test no new block assert_eq!( - block_storage::read_current_number(&host) - .expect("should have found a block number"), + read_current_number(&host).expect("should have found a block number"), U256::zero(), "There should have been one block registered" ); diff --git a/etherlink/kernel_latest/kernel/src/block_in_progress.rs b/etherlink/kernel_latest/kernel/src/block_in_progress.rs index 44416d29203f..21552bef7064 100644 --- a/etherlink/kernel_latest/kernel/src/block_in_progress.rs +++ b/etherlink/kernel_latest/kernel/src/block_in_progress.rs @@ -7,6 +7,7 @@ use crate::apply::{TransactionObjectInfo, TransactionReceiptInfo}; use crate::block_storage; +use crate::chains::ETHERLINK_SAFE_STORAGE_ROOT_PATH; use crate::error::Error; use crate::error::TransferError::CumulativeGasUsedOverflow; use crate::gas_price::base_fee_per_gas; @@ -481,7 +482,7 @@ impl EthBlockInProgress { base_fee_per_gas, ); let new_block = L2Block::Etherlink(Box::new(new_block)); - block_storage::store_current(host, &new_block) + block_storage::store_current(host, ÐERLINK_SAFE_STORAGE_ROOT_PATH, &new_block) .context("Failed to store the current block")?; Ok(new_block) } diff --git a/etherlink/kernel_latest/kernel/src/block_storage.rs b/etherlink/kernel_latest/kernel/src/block_storage.rs index 88f560398a8b..1544192cb693 100644 --- a/etherlink/kernel_latest/kernel/src/block_storage.rs +++ b/etherlink/kernel_latest/kernel/src/block_storage.rs @@ -9,9 +9,9 @@ use tezos_evm_logging::{ }; use tezos_evm_runtime::runtime::Runtime; use tezos_indexable_storage::IndexableStorage; -use tezos_smart_rollup_host::path::concat; use tezos_smart_rollup_host::path::OwnedPath; use tezos_smart_rollup_host::path::RefPath; +use tezos_smart_rollup_host::path::{concat, Path}; use tezos_storage::{read_h256_be, read_u256_le, write_h256_be, write_u256_le}; use crate::storage::EVM_TRANSACTIONS_OBJECTS; @@ -19,59 +19,92 @@ use crate::storage::EVM_TRANSACTIONS_RECEIPTS; use crate::{chains::ChainFamily, l2block::L2Block, migration::allow_path_not_found}; mod path { + use tezos_smart_rollup_host::path::Path; + use super::*; - pub const PATH: RefPath = RefPath::assert_from(b"/evm/world_state/blocks"); + const CURRENT_NUMBER: RefPath = RefPath::assert_from(b"/blocks/current/number"); + + pub fn current_number( + root: &impl Path, + ) -> Result { + concat(root, &CURRENT_NUMBER) + } + + const CURRENT_HASH: RefPath = RefPath::assert_from(b"/blocks/current/hash"); + + pub fn current_hash( + root: &impl Path, + ) -> Result { + concat(root, &CURRENT_HASH) + } - pub const CURRENT_NUMBER: RefPath = - RefPath::assert_from(b"/evm/world_state/blocks/current/number"); - pub const CURRENT_HASH: RefPath = - RefPath::assert_from(b"/evm/world_state/blocks/current/hash"); + pub fn blocks( + root: &impl Path, + ) -> Result { + concat(root, &RefPath::assert_from(b"/blocks")) + } - pub const INDEXES: RefPath = RefPath::assert_from(b"/evm/world_state/indexes/blocks"); + const INDEXES: RefPath = RefPath::assert_from(b"/indexes/blocks"); + + pub fn indexes( + root: &impl Path, + ) -> Result { + concat(root, &INDEXES) + } /// Path to the block in the storage. The path to the block is /// indexed by its hash. - pub fn path(hash: H256) -> anyhow::Result { + pub fn path(root: &impl Path, hash: H256) -> anyhow::Result { let hash = hex::encode(hash); let raw_hash_path: Vec = format!("/{}", &hash).into(); let hash_path = OwnedPath::try_from(raw_hash_path)?; - Ok(concat(&PATH, &hash_path)?) + Ok(concat(&blocks(root)?, &hash_path)?) } } -fn store_current_number(host: &mut impl Runtime, number: U256) -> anyhow::Result<()> { - Ok(write_u256_le(host, &path::CURRENT_NUMBER, number)?) +fn store_current_number( + host: &mut impl Runtime, + root: &impl Path, + number: U256, +) -> anyhow::Result<()> { + Ok(write_u256_le(host, &path::current_number(root)?, number)?) } -fn store_current_hash(host: &mut impl Runtime, hash: H256) -> anyhow::Result<()> { - write_h256_be(host, &path::CURRENT_HASH, hash) +fn store_current_hash( + host: &mut impl Runtime, + root: &impl Path, + hash: H256, +) -> anyhow::Result<()> { + write_h256_be(host, &path::current_hash(root)?, hash) } fn store_block( host: &mut impl Runtime, + root: &impl Path, block: &L2Block, index_block: bool, ) -> anyhow::Result<()> { if index_block { // Index the block, /evm/world_state/indexes/blocks/ points to // the block hash. - let index = IndexableStorage::new(&path::INDEXES)?; + let index = IndexableStorage::new_owned_path(path::indexes(root)?); index.push_value(host, block.hash().as_bytes())?; } - let path = path::path(block.hash())?; + let path = path::path(root, block.hash())?; let bytes = block.to_bytes(); Ok(host.store_write_all(&path, &bytes)?) } fn store_current_index_or_not( host: &mut impl Runtime, + root: &impl Path, block: &L2Block, index_block: bool, ) -> anyhow::Result<()> { - store_current_number(host, block.number())?; - store_current_hash(host, block.hash())?; - store_block(host, block, index_block)?; + store_current_number(host, root, block.number())?; + store_current_hash(host, root, block.hash())?; + store_block(host, root, block, index_block)?; log!( host, Info, @@ -84,28 +117,40 @@ fn store_current_index_or_not( Ok(()) } -pub fn store_current(host: &mut impl Runtime, block: &L2Block) -> anyhow::Result<()> { - store_current_index_or_not(host, block, true) +pub fn store_current( + host: &mut impl Runtime, + root: &impl Path, + block: &L2Block, +) -> anyhow::Result<()> { + store_current_index_or_not(host, root, block, true) } -pub fn restore_current(host: &mut impl Runtime, block: &L2Block) -> anyhow::Result<()> { - store_current_index_or_not(host, block, false) +pub fn restore_current( + host: &mut impl Runtime, + root: &impl Path, + block: &L2Block, +) -> anyhow::Result<()> { + store_current_index_or_not(host, root, block, false) } -pub fn read_current_number(host: &impl Runtime) -> anyhow::Result { - Ok(read_u256_le(host, &path::CURRENT_NUMBER)?) +pub fn read_current_number( + host: &impl Runtime, + root: &impl Path, +) -> anyhow::Result { + Ok(read_u256_le(host, &path::current_number(root)?)?) } -pub fn read_current_hash(host: &impl Runtime) -> anyhow::Result { - read_h256_be(host, &path::CURRENT_HASH) +pub fn read_current_hash(host: &impl Runtime, root: &impl Path) -> anyhow::Result { + read_h256_be(host, &path::current_hash(root)?) } pub fn read_current( host: &mut impl Runtime, + root: &impl Path, chain_family: &ChainFamily, ) -> anyhow::Result { - let hash = read_current_hash(host)?; - let block_path = path::path(hash)?; + let hash = read_current_hash(host, root)?; + let block_path = path::path(root, hash)?; let bytes = &host.store_read_all(&block_path)?; let block_from_bytes = L2Block::try_from_bytes(chain_family, bytes)?; Ok(block_from_bytes) @@ -113,14 +158,15 @@ pub fn read_current( pub fn garbage_collect_blocks( host: &mut impl Runtime, + root: &impl Path, chain_family: &ChainFamily, ) -> anyhow::Result<()> { log!(host, Debug, "Garbage collecting blocks."); - if let Ok(block) = read_current(host, chain_family) { + if let Ok(block) = read_current(host, root, chain_family) { // The kernel needs the current block to process the next one. Therefore // we garbage collect everything but the current block. - host.store_delete(&path::PATH)?; - restore_current(host, &block)?; + host.store_delete(&path::blocks(root)?)?; + restore_current(host, root, &block)?; // Clean all transactions, they are unused by the kernel. allow_path_not_found(host.store_delete(&EVM_TRANSACTIONS_OBJECTS))?; allow_path_not_found(host.store_delete(&EVM_TRANSACTIONS_RECEIPTS))?; @@ -132,14 +178,15 @@ pub fn garbage_collect_blocks( pub mod internal_for_tests { use super::*; - pub fn init_blocks_index() -> anyhow::Result { - Ok(IndexableStorage::new(&path::INDEXES)?) + pub fn init_blocks_index(root: &impl Path) -> anyhow::Result { + Ok(IndexableStorage::new_owned_path(path::indexes(root)?)) } pub fn store_current_number( host: &mut impl Runtime, + root: &impl Path, number: U256, ) -> anyhow::Result<()> { - super::store_current_number(host, number) + super::store_current_number(host, root, number) } } diff --git a/etherlink/kernel_latest/kernel/src/chains.rs b/etherlink/kernel_latest/kernel/src/chains.rs index 62bb412346ea..b143e55d0011 100644 --- a/etherlink/kernel_latest/kernel/src/chains.rs +++ b/etherlink/kernel_latest/kernel/src/chains.rs @@ -457,7 +457,8 @@ impl ChainConfigTrait for MichelsonChainConfig { let tezblock = TezBlock::new(number, timestamp, previous_hash); let new_block = L2Block::Tezlink(tezblock); - crate::block_storage::store_current(host, &new_block) + let root = self.storage_root_path(); + crate::block_storage::store_current(host, &root, &new_block) .context("Failed to store the current block")?; Ok(BlockComputationResult::Finished { included_delayed_transactions: vec![], diff --git a/etherlink/kernel_latest/kernel/src/inbox.rs b/etherlink/kernel_latest/kernel/src/inbox.rs index 13577392575f..f755123f15f8 100644 --- a/etherlink/kernel_latest/kernel/src/inbox.rs +++ b/etherlink/kernel_latest/kernel/src/inbox.rs @@ -39,6 +39,7 @@ use tezos_ethereum::tx_common::EthereumTransactionCommon; use tezos_evm_logging::{log, Level::*}; use tezos_evm_runtime::runtime::Runtime; use tezos_smart_rollup_encoding::public_key::PublicKey; +use tezos_smart_rollup_host::path::Path; #[derive(Debug, PartialEq)] pub struct ProxyInboxContent { @@ -377,6 +378,7 @@ pub fn handle_input( host: &mut impl Runtime, input: Input, inbox_content: &mut Mode::Inbox, + root: &impl Path, chain_family: &ChainFamily, garbage_collect_blocks: bool, ) -> anyhow::Result<()> { @@ -392,7 +394,7 @@ pub fn handle_input( clear_events(host)?; if garbage_collect_blocks { log!(host, Debug, "Garbage collection of old blocks"); - crate::block_storage::garbage_collect_blocks(host, chain_family)?; + crate::block_storage::garbage_collect_blocks(host, root, chain_family)?; } store_last_info_per_level_timestamp(host, info.info.predecessor_timestamp)?; store_l1_level(host, info.level)? @@ -466,6 +468,7 @@ fn read_and_dispatch_input< host, input, res, + &chain_configuration.storage_root_path(), &chain_configuration.get_chain_family(), garbage_collect_blocks, )?; diff --git a/etherlink/kernel_latest/kernel/src/lib.rs b/etherlink/kernel_latest/kernel/src/lib.rs index c92a6415d7be..261e65a350bd 100644 --- a/etherlink/kernel_latest/kernel/src/lib.rs +++ b/etherlink/kernel_latest/kernel/src/lib.rs @@ -173,9 +173,14 @@ fn retrieve_base_fee_per_gas( host: &mut Host, minimum_base_fee_per_gas: U256, ) -> U256 { - use chains::ChainFamily; + use chains::{ChainConfigTrait, EvmChainConfig}; - match block_storage::read_current(host, &ChainFamily::Evm) { + let chain_config = EvmChainConfig::default(); + match block_storage::read_current( + host, + &chain_config.storage_root_path(), + &chain_config.get_chain_family(), + ) { Ok(current_block) => { let current_base_fee_per_gas = current_block.base_fee_per_gas(); if current_base_fee_per_gas < minimum_base_fee_per_gas { diff --git a/etherlink/kernel_latest/kernel/src/migration.rs b/etherlink/kernel_latest/kernel/src/migration.rs index ffea81c17be1..57237dfcf973 100644 --- a/etherlink/kernel_latest/kernel/src/migration.rs +++ b/etherlink/kernel_latest/kernel/src/migration.rs @@ -8,6 +8,7 @@ use crate::block_storage; use crate::blueprint_storage::{ blueprint_path, clear_all_blueprints, store_current_block_header, }; +use crate::chains::ETHERLINK_SAFE_STORAGE_ROOT_PATH; use crate::error::Error; use crate::error::StorageError; use crate::error::UpgradeProcessError; @@ -86,7 +87,8 @@ mod legacy { pub fn read_next_blueprint_number( host: &Host, ) -> anyhow::Result { - match block_storage::read_current_number(host) { + match block_storage::read_current_number(host, ÐERLINK_SAFE_STORAGE_ROOT_PATH) + { Err(err) => match err.downcast_ref() { Some(GenStorageError::Runtime(RuntimeError::PathNotFound)) => { Ok(U256::zero()) @@ -157,7 +159,10 @@ fn migrate_to( // // We need only the former. - let current_number = block_storage::read_current_number(host)?; + let current_number = block_storage::read_current_number( + host, + ÐERLINK_SAFE_STORAGE_ROOT_PATH, + )?; let to_clean = U256::min( current_number + 1, evm_execution::storage::blocks::BLOCKS_STORED.into(), @@ -273,7 +278,11 @@ fn migrate_to( } StorageVersion::V27 => { // Initialize the next_blueprint_info field - match block_storage::read_current(host, &crate::chains::ChainFamily::Evm) { + match block_storage::read_current( + host, + ÐERLINK_SAFE_STORAGE_ROOT_PATH, + &crate::chains::ChainFamily::Evm, + ) { Ok(block) => { store_current_block_header(host, &block.into())?; Ok(MigrationStatus::Done) diff --git a/etherlink/kernel_latest/kernel/src/simulation.rs b/etherlink/kernel_latest/kernel/src/simulation.rs index 0bfea78cb651..eb1bbccc488b 100644 --- a/etherlink/kernel_latest/kernel/src/simulation.rs +++ b/etherlink/kernel_latest/kernel/src/simulation.rs @@ -11,7 +11,7 @@ use std::borrow::Cow; use crate::block_storage; -use crate::chains::ChainFamily; +use crate::chains::{ChainFamily, ETHERLINK_SAFE_STORAGE_ROOT_PATH}; use crate::fees::simulation_add_gas_for_fees; use crate::l2block::L2Block; use crate::storage::{ @@ -399,7 +399,11 @@ impl Evaluation { } } - let constants = match block_storage::read_current(host, &ChainFamily::Evm) { + let constants = match block_storage::read_current( + host, + ÐERLINK_SAFE_STORAGE_ROOT_PATH, + &ChainFamily::Evm, + ) { Ok(L2Block::Etherlink(block)) => { // Timestamp is taken from the simulation caller if provided. // If the timestamp is missing, because of an older evm-node, diff --git a/etherlink/kernel_latest/kernel/src/stage_one.rs b/etherlink/kernel_latest/kernel/src/stage_one.rs index 983e2011fde0..588f65499876 100644 --- a/etherlink/kernel_latest/kernel/src/stage_one.rs +++ b/etherlink/kernel_latest/kernel/src/stage_one.rs @@ -636,6 +636,7 @@ mod tests { hex::decode(DUMMY_BLUEPRINT_CHUNK_NUMBER_10).unwrap(), )); let mut conf = dummy_sequencer_config(enable_dal, None); + let chain_config = test_evm_chain_config(); match read_proxy_inbox( &mut host, @@ -643,7 +644,7 @@ mod tests { &conf.tezos_contracts, false, false, - &test_evm_chain_config(), + &chain_config, ) .unwrap() { @@ -656,7 +657,8 @@ mod tests { }; // The dummy chunk in the inbox is registered at block 10 - store_current_number(&mut host, U256::from(9)).unwrap(); + store_current_number(&mut host, &chain_config.storage_root_path(), U256::from(9)) + .unwrap(); if read_next_blueprint(&mut host, &mut conf) .expect("Blueprint reading shouldn't fail") .0 -- GitLab From 8daf877d855deedd224f3df46ab6bb6998667ea9 Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 18 Apr 2025 15:34:14 +0200 Subject: [PATCH 4/8] L2/Node: Add Etherlink and Tezlink root and parametrize durable_storage_path --- .../bin_node/lib_dev/blueprints_publisher.ml | 7 ++++- etherlink/bin_node/lib_dev/durable_storage.ml | 4 +-- .../bin_node/lib_dev/durable_storage_path.ml | 28 ++++++++++++++----- .../bin_node/lib_dev/durable_storage_path.mli | 14 +++++++--- .../lib_dev/etherlink_durable_storage.ml | 14 ++++++---- etherlink/bin_node/lib_dev/evm_context.ml | 27 ++++++++++++++++-- etherlink/bin_node/lib_dev/evm_ro_context.ml | 9 ++++-- etherlink/bin_node/lib_dev/evm_state.ml | 20 ++++++++++--- etherlink/bin_node/lib_dev/rollup_node.ml | 13 +++++++-- .../lib_dev/tezlink_durable_storage.ml | 12 +++++--- 10 files changed, 114 insertions(+), 34 deletions(-) diff --git a/etherlink/bin_node/lib_dev/blueprints_publisher.ml b/etherlink/bin_node/lib_dev/blueprints_publisher.ml index a5eabc415649..0ca4d2c32755 100644 --- a/etherlink/bin_node/lib_dev/blueprints_publisher.ml +++ b/etherlink/bin_node/lib_dev/blueprints_publisher.ml @@ -224,7 +224,12 @@ module Worker = struct ~base:(rollup_node_endpoint self) durable_state_value ((), Block_id.Level rollup_block_lvl) - {key = Durable_storage_path.Block.current_number} + { + key = + Durable_storage_path.Block.current_number + (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root; + } () in match finalized_current_number with diff --git a/etherlink/bin_node/lib_dev/durable_storage.ml b/etherlink/bin_node/lib_dev/durable_storage.ml index f00662d12a78..d2a7c6508000 100644 --- a/etherlink/bin_node/lib_dev/durable_storage.ml +++ b/etherlink/bin_node/lib_dev/durable_storage.ml @@ -106,14 +106,14 @@ let is_multichain_enabled read = let* bytes_opt = read Durable_storage_path.Feature_flags.multichain in return (Option.is_some bytes_opt) -let block_number read n = +let block_number ~root read n = let open Lwt_result_syntax in match n with (* This avoids an unecessary service call in case we ask a block's number with an already expected/known block number [n]. *) | Durable_storage_path.Block.Nth i -> return @@ Ethereum_types.Qty i | Durable_storage_path.Block.Current -> ( - let+ answer = read Durable_storage_path.Block.current_number in + let+ answer = read (Durable_storage_path.Block.current_number ~root) in match answer with | Some bytes -> Ethereum_types.Qty (Bytes.to_string bytes |> Z.of_bits) | None -> diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.ml b/etherlink/bin_node/lib_dev/durable_storage_path.ml index f4515d622aaa..0169894b0d5a 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.ml +++ b/etherlink/bin_node/lib_dev/durable_storage_path.ml @@ -16,6 +16,12 @@ let reboot_counter = "/readonly/kernel/env/reboot_counter" let evm_node_flag = "/__evm_node" +module Tezlink = struct + let root = "/tezlink" +end + +let tezlink_root = Tezlink.root + module EVM = struct let root = "/evm" @@ -28,6 +34,13 @@ module World_state = struct let make s = EVM.make (root ^ s) end +let etherlink_root = World_state.make "" + +let root_of_chain_family chain_family = + match chain_family with + | L2_types.EVM -> etherlink_root + | L2_types.Michelson -> tezlink_root + let chain_id = EVM.make "/chain_id" let minimum_base_fee_per_gas = World_state.make "/fees/minimum_base_fee_per_gas" @@ -142,29 +155,30 @@ end module Block = struct type number = Current | Nth of Z.t - let blocks = World_state.make "/blocks" + let blocks ~root = root ^ "/blocks" let number = "/number" - let by_hash (Block_hash (Hex hash)) = blocks ^ "/" ^ hash + let by_hash ~root (Block_hash (Hex hash)) = blocks ~root ^ "/" ^ hash - let current_number = blocks ^ "/current" ^ number + let current_number ~root = blocks ~root ^ "/current" ^ number - let current_hash = blocks ^ "/current/hash" + let current_hash ~root = blocks ~root ^ "/current/hash" end module Indexes = struct - let indexes = World_state.make "/indexes" + let indexes ~root = root ^ "/indexes" let blocks = "/blocks" - let blocks = indexes ^ blocks + let blocks ~root = indexes ~root ^ blocks let number_to_string = function | Block.Current -> "current" | Nth i -> Z.to_string i - let block_by_number number = blocks ^ "/" ^ number_to_string number + let block_by_number ~root number = + blocks ~root ^ "/" ^ number_to_string number end module Transaction_receipt = struct diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.mli b/etherlink/bin_node/lib_dev/durable_storage_path.mli index cbca43891b69..b1660f21ee4f 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.mli +++ b/etherlink/bin_node/lib_dev/durable_storage_path.mli @@ -12,6 +12,12 @@ open Ethereum_types type path = string +val tezlink_root : path + +val etherlink_root : path + +val root_of_chain_family : L2_types.chain_family -> path + val reboot_counter : string val evm_node_flag : path @@ -89,18 +95,18 @@ module Block : sig type number = Current | Nth of Z.t (** Path to the given block. *) - val by_hash : block_hash -> path + val by_hash : root:path -> block_hash -> path (** Path to the current block number. *) - val current_number : path + val current_number : root:path -> path (** Path to the current block hash. *) - val current_hash : path + val current_hash : root:path -> path end module Indexes : sig (** Make the path to the indexed block hash. *) - val block_by_number : Block.number -> path + val block_by_number : root:path -> Block.number -> path end module Transaction_receipt : sig diff --git a/etherlink/bin_node/lib_dev/etherlink_durable_storage.ml b/etherlink/bin_node/lib_dev/etherlink_durable_storage.ml index 0234210f5288..3fe0568ff13a 100644 --- a/etherlink/bin_node/lib_dev/etherlink_durable_storage.ml +++ b/etherlink/bin_node/lib_dev/etherlink_durable_storage.ml @@ -8,6 +8,8 @@ open Durable_storage open Ethereum_types +let root = Durable_storage_path.etherlink_root + let balance read address = inspect_durable_and_decode_default ~default:(Ethereum_types.Qty Z.zero) @@ -53,7 +55,7 @@ let code read address = decode) let current_block_number read = - Durable_storage.block_number read Durable_storage_path.Block.Current + Durable_storage.block_number ~root read Durable_storage_path.Block.Current let un_qty (Qty z) = z @@ -83,6 +85,7 @@ let transaction_receipt read ?block_hash tx_hash = inspect_durable_and_decode read (Durable_storage_path.Indexes.block_by_number + ~root (Nth (un_qty temp_receipt.blockNumber))) decode_block_hash in @@ -118,6 +121,7 @@ let transaction_object read tx_hash = inspect_durable_and_decode read (Durable_storage_path.Indexes.block_by_number + ~root (Nth (un_qty blockNumber))) decode_block_hash in @@ -154,11 +158,11 @@ let populate_tx_objects read ~full_transaction_object let blocks_by_number read ~full_transaction_object ~number = let open Lwt_result_syntax in - let* (Ethereum_types.Qty level) = block_number read number in + let* (Ethereum_types.Qty level) = block_number ~root read number in let* block_hash_opt = inspect_durable_and_decode_opt read - (Durable_storage_path.Indexes.block_by_number (Nth level)) + (Durable_storage_path.Indexes.block_by_number ~root (Nth level)) decode_block_hash in match block_hash_opt with @@ -167,7 +171,7 @@ let blocks_by_number read ~full_transaction_object ~number = let* block_opt = inspect_durable_and_decode_opt read - (Durable_storage_path.Block.by_hash block_hash) + (Durable_storage_path.Block.by_hash ~root block_hash) Ethereum_types.block_from_rlp in match block_opt with @@ -185,7 +189,7 @@ let block_by_hash read ~full_transaction_object block_hash = let* block_opt = inspect_durable_and_decode_opt read - (Durable_storage_path.Block.by_hash block_hash) + (Durable_storage_path.Block.by_hash ~root block_hash) Ethereum_types.block_from_rlp in match block_opt with diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 5e7464ad1c34..1a9b70084729 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -521,10 +521,15 @@ module State = struct if not ctxt.legacy_block_storage then Evm_store.Blocks.find_hash_of_number conn (Qty number) else + let chain_family = + Configuration.retrieve_chain_family + ~l2_chains:ctxt.configuration.experimental_features.l2_chains + in + let root = Durable_storage_path.root_of_chain_family chain_family in let*! bytes = Evm_state.inspect evm_state - (Durable_storage_path.Indexes.block_by_number (Nth number)) + (Durable_storage_path.Indexes.block_by_number ~root (Nth number)) in return (Option.map Ethereum_types.decode_block_hash bytes) in @@ -1699,10 +1704,18 @@ module State = struct if not ctxt.legacy_block_storage then Evm_store.Blocks.find_hash_of_number conn (Qty pred_number) else + let chain_family = + Configuration.retrieve_chain_family + ~l2_chains:ctxt.configuration.experimental_features.l2_chains + in + let root = + Durable_storage_path.root_of_chain_family chain_family + in let*! bytes = Evm_state.inspect ctxt.session.evm_state (Durable_storage_path.Indexes.block_by_number + ~root (Nth pred_number)) in return (Option.map Ethereum_types.decode_block_hash bytes) @@ -2055,7 +2068,11 @@ let init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context = (* Assert we can read the current blueprint number *) let* current_blueprint_number = let*! current_blueprint_number_opt = - Evm_state.inspect evm_state Durable_storage_path.Block.current_number + Evm_state.inspect + evm_state + (Durable_storage_path.Block.current_number + (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root) in match current_blueprint_number_opt with | Some bytes -> return (Bytes.to_string bytes |> Z.of_bits) @@ -2065,7 +2082,11 @@ let init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context = (* Assert we can read the current block hash *) let* () = let*! current_block_hash_opt = - Evm_state.inspect evm_state Durable_storage_path.Block.current_hash + Evm_state.inspect + evm_state + (Durable_storage_path.Block.current_hash + (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root) in match current_block_hash_opt with | Some _bytes -> return_unit diff --git a/etherlink/bin_node/lib_dev/evm_ro_context.ml b/etherlink/bin_node/lib_dev/evm_ro_context.ml index d2643b75030c..821581df25cc 100644 --- a/etherlink/bin_node/lib_dev/evm_ro_context.ml +++ b/etherlink/bin_node/lib_dev/evm_ro_context.ml @@ -161,8 +161,9 @@ let get_irmin_hash_from_block_hash ~chain_family ctxt hash = (* we use the latest state to read the contents of the block *) let* latest_hash = find_latest_hash ctxt in let* evm_tree = get_evm_state ctxt latest_hash in + let root = Durable_storage_path.root_of_chain_family chain_family in let*! res = - Evm_state.inspect evm_tree Durable_storage_path.Block.(by_hash hash) + Evm_state.inspect evm_tree Durable_storage_path.Block.(by_hash ~root hash) in match res with | Some block_bytes -> @@ -392,7 +393,11 @@ struct let* irmin_hash = find_irmin_hash Ctxt.ctxt block_param in let* evm_state = get_evm_state Ctxt.ctxt irmin_hash in let*! bytes = - Evm_state.inspect evm_state Durable_storage_path.(Block.by_hash hash) + Evm_state.inspect + evm_state + Durable_storage_path.( + (* We're expecting an etherlink block here so we can inline etherlink root *) + Block.by_hash ~root:Durable_storage_path.etherlink_root hash) in match bytes with | Some bytes -> diff --git a/etherlink/bin_node/lib_dev/evm_state.ml b/etherlink/bin_node/lib_dev/evm_state.ml index efa0232acc66..91ae7deee3a5 100644 --- a/etherlink/bin_node/lib_dev/evm_state.ml +++ b/etherlink/bin_node/lib_dev/evm_state.ml @@ -224,7 +224,11 @@ let kernel_version evm_state = let current_block_height evm_state = let open Lwt_syntax in let* current_block_number = - inspect evm_state Durable_storage_path.Block.current_number + inspect + evm_state + (Durable_storage_path.Block.current_number + (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root) in match current_block_number with | None -> @@ -239,8 +243,9 @@ let current_block_height evm_state = let current_block_hash ~chain_family evm_state = let open Lwt_result_syntax in + let root = Durable_storage_path.root_of_chain_family chain_family in let*! current_hash = - inspect evm_state Durable_storage_path.Block.current_hash + inspect evm_state (Durable_storage_path.Block.current_hash ~root) in match current_hash with | Some h -> return (decode_block_hash h) @@ -344,9 +349,10 @@ let apply_blueprint ?wasm_pvm_fallback ?log_file ?profile ~data_dir exec_inputs in let* block_hash = current_block_hash ~chain_family evm_state in + let root = Durable_storage_path.root_of_chain_family chain_family in let* block = let*! bytes = - inspect evm_state (Durable_storage_path.Block.by_hash block_hash) + inspect evm_state (Durable_storage_path.Block.by_hash ~root block_hash) in return (Option.map (L2_types.block_from_bytes ~chain_family) bytes) in @@ -437,7 +443,11 @@ let clear_block_storage block evm_state = (* Handles case (1.). *) let* evm_state = if number > Z.zero then - let pred_block_path = Durable_storage_path.Block.by_hash block_parent in + let pred_block_path = + Durable_storage_path.Block.by_hash (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root + block_parent + in delete ~kind:Value evm_state pred_block_path else return evm_state in @@ -451,6 +461,8 @@ let clear_block_storage block evm_state = if number >= to_keep then let index_path = Durable_storage_path.Indexes.block_by_number + (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root (Nth (Z.sub number to_keep)) in delete ~kind:Value evm_state index_path diff --git a/etherlink/bin_node/lib_dev/rollup_node.ml b/etherlink/bin_node/lib_dev/rollup_node.ml index d4ec4c1962ee..5ebeaecd4245 100644 --- a/etherlink/bin_node/lib_dev/rollup_node.ml +++ b/etherlink/bin_node/lib_dev/rollup_node.ml @@ -164,7 +164,11 @@ end) : Services_backend_sig.Backend = struct let read_from_block_parameter param = let* state = Reader.get_state ~block:(Block_parameter param) () in let* value = - Reader.read state Durable_storage_path.Block.current_number + Reader.read + state + (Durable_storage_path.Block.current_number + (* TODO: Remove etherlink root *) + ~root:Durable_storage_path.etherlink_root) in match value with | Some value -> @@ -176,7 +180,12 @@ end) : Services_backend_sig.Backend = struct | Block_hash {hash; _} -> ( let* state = Reader.get_state ~block:(Block_parameter Latest) () in let* value = - Reader.read state (Durable_storage_path.Block.by_hash hash) + Reader.read + state + (Durable_storage_path.Block.by_hash + (* We're expecting an etherlink block here so we can inline etherlink root *) + ~root:Durable_storage_path.etherlink_root + hash) in match value with | Some value -> diff --git a/etherlink/bin_node/lib_dev/tezlink_durable_storage.ml b/etherlink/bin_node/lib_dev/tezlink_durable_storage.ml index 7b51ac27b6be..af9fafc77176 100644 --- a/etherlink/bin_node/lib_dev/tezlink_durable_storage.ml +++ b/etherlink/bin_node/lib_dev/tezlink_durable_storage.ml @@ -7,6 +7,8 @@ (*****************************************************************************) open Tezos_types +let root = Durable_storage_path.tezlink_root + module Path = struct (** [to_path encoding value] uses [encoding] to encode [value] in hexadecimal *) @@ -50,11 +52,13 @@ let counter read c = let nth_block read n = let open Lwt_result_syntax in let number = Durable_storage_path.Block.(Nth n) in - let* (Ethereum_types.Qty level) = Durable_storage.block_number read number in + let* (Ethereum_types.Qty level) = + Durable_storage.block_number ~root read number + in let* block_hash_opt = Durable_storage.inspect_durable_and_decode_opt read - (Durable_storage_path.Indexes.block_by_number (Nth level)) + (Durable_storage_path.Indexes.block_by_number ~root (Nth level)) Ethereum_types.decode_block_hash in match block_hash_opt with @@ -63,7 +67,7 @@ let nth_block read n = let* block_opt = Durable_storage.inspect_durable_and_decode_opt read - (Durable_storage_path.Block.by_hash block_hash) + (Durable_storage_path.Block.by_hash ~root block_hash) L2_types.Tezos_block.block_from_binary in match block_opt with @@ -76,7 +80,7 @@ let nth_block_hash read n = let number = Durable_storage_path.Block.(Nth n) in Durable_storage.inspect_durable_and_decode_opt read - (Durable_storage_path.Indexes.block_by_number number) + (Durable_storage_path.Indexes.block_by_number ~root number) Ethereum_types.decode_block_hash module Make_block_storage (Reader : Durable_storage.READER) : -- GitLab From 23681cbc9f3c607e7abf3e0e60d3f64c8cab36c4 Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 18 Apr 2025 15:42:14 +0200 Subject: [PATCH 5/8] L2/Node: Add chain_family or root to functions to choose etherlink or tezlink --- .../bin_node/lib_dev/block_storage_setup.ml | 12 ++++++-- etherlink/bin_node/lib_dev/evm_context.ml | 28 +++++++++++++------ etherlink/bin_node/lib_dev/evm_state.ml | 21 ++++++-------- etherlink/bin_node/lib_dev/evm_state.mli | 16 ++++++----- 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/etherlink/bin_node/lib_dev/block_storage_setup.ml b/etherlink/bin_node/lib_dev/block_storage_setup.ml index 2d80798954ff..8ff71b919201 100644 --- a/etherlink/bin_node/lib_dev/block_storage_setup.ml +++ b/etherlink/bin_node/lib_dev/block_storage_setup.ml @@ -82,7 +82,11 @@ let enable ~keep_alive ?evm_node_endpoint store = if enable_fallback && key = tmp_world_state_path ^ "/transactions_receipts" then Lwt_preemptive.run_in_main @@ fun () -> - let* pred = Evm_state.current_block_height tree in + let* pred = + Evm_state.current_block_height + ~root:Durable_storage_path.etherlink_root + tree + in let n = Ethereum_types.Qty.next pred in let+ block = get_block_exn n in let s = Ethereum_types.hash_to_bytes block.receiptRoot in @@ -91,7 +95,11 @@ let enable ~keep_alive ?evm_node_endpoint store = enable_fallback && key = tmp_world_state_path ^ "/transactions_objects" then Lwt_preemptive.run_in_main @@ fun () -> - let* pred = Evm_state.current_block_height tree in + let* pred = + Evm_state.current_block_height + ~root:Durable_storage_path.etherlink_root + tree + in let n = Ethereum_types.Qty.next pred in let+ block = get_block_exn n in let s = Ethereum_types.hash_to_bytes block.transactionRoot in diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 1a9b70084729..56df800fca34 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -801,7 +801,9 @@ module State = struct | Eth block -> store_block_unsafe conn evm_state block | Tez block -> store_tez_block_unsafe conn block in - let*! evm_state = Evm_state.clear_block_storage block evm_state in + let*! evm_state = + Evm_state.clear_block_storage chain_family block evm_state + in return (evm_state, receipts) else let*! receipts = @@ -2053,8 +2055,10 @@ let init_context_from_rollup_node ~data_dir ~rollup_node_data_dir = let*! evm_state = Irmin_context.PVMState.get evm_node_context in return (evm_node_context, evm_state, final_l2_block.header.level) -let init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context = +let init_store_from_rollup_node ~chain_family ~data_dir ~evm_state + ~irmin_context = let open Lwt_result_syntax in + let root = Durable_storage_path.root_of_chain_family chain_family in (* Tell the kernel that it is executed by an EVM node *) let*! evm_state = Evm_state.flag_local_exec evm_state in (* We remove the delayed inbox from the EVM state. Its contents will be @@ -2070,9 +2074,7 @@ let init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context = let*! current_blueprint_number_opt = Evm_state.inspect evm_state - (Durable_storage_path.Block.current_number - (* TODO: Remove etherlink root *) - ~root:Durable_storage_path.etherlink_root) + (Durable_storage_path.Block.current_number ~root) in match current_blueprint_number_opt with | Some bytes -> return (Bytes.to_string bytes |> Z.of_bits) @@ -2084,9 +2086,7 @@ let init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context = let*! current_block_hash_opt = Evm_state.inspect evm_state - (Durable_storage_path.Block.current_hash - (* TODO: Remove etherlink root *) - ~root:Durable_storage_path.etherlink_root) + (Durable_storage_path.Block.current_hash ~root) in match current_block_hash_opt with | Some _bytes -> return_unit @@ -2153,7 +2153,17 @@ let init_from_rollup_node ~configuration ~omit_delayed_tx_events ~data_dir let* evm_events = get_evm_events_from_rollup_node_state ~omit_delayed_tx_events evm_state in - let* () = init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context in + let chain_family = + Configuration.retrieve_chain_family + ~l2_chains:configuration.Configuration.experimental_features.l2_chains + in + let* () = + init_store_from_rollup_node + ~chain_family + ~data_dir + ~evm_state + ~irmin_context + in let* smart_rollup_address, _genesis_level = rollup_node_metadata ~rollup_node_data_dir in diff --git a/etherlink/bin_node/lib_dev/evm_state.ml b/etherlink/bin_node/lib_dev/evm_state.ml index 91ae7deee3a5..e23fa9ef23df 100644 --- a/etherlink/bin_node/lib_dev/evm_state.ml +++ b/etherlink/bin_node/lib_dev/evm_state.ml @@ -221,14 +221,10 @@ let kernel_version evm_state = let+ version = inspect evm_state Durable_storage_path.kernel_version in match version with Some v -> Bytes.unsafe_to_string v | None -> "(unknown)" -let current_block_height evm_state = +let current_block_height ~root evm_state = let open Lwt_syntax in let* current_block_number = - inspect - evm_state - (Durable_storage_path.Block.current_number - (* TODO: Remove etherlink root *) - ~root:Durable_storage_path.etherlink_root) + inspect evm_state (Durable_storage_path.Block.current_number ~root) in match current_block_number with | None -> @@ -330,12 +326,13 @@ let apply_blueprint ?wasm_pvm_fallback ?log_file ?profile ~data_dir ~chain_family ~config ~native_execution_policy evm_state (blueprint : Blueprint_types.payload) = let open Lwt_result_syntax in + let root = Durable_storage_path.root_of_chain_family chain_family in let exec_inputs = List.map (function `External payload -> `Input ("\001" ^ payload)) blueprint in - let*! (Qty before_height) = current_block_height evm_state in + let*! (Qty before_height) = current_block_height ~root evm_state in let* evm_state = execute ~native_execution:(native_execution_policy = Configuration.Always) @@ -427,7 +424,7 @@ let get_delayed_inbox_item evm_state hash = return res | _ -> failwith "invalid delayed inbox item" -let clear_block_storage block evm_state = +let clear_block_storage chain_family block evm_state = let open Lwt_syntax in (* We have 2 path to clear related to block storage: 1. The predecessor block. @@ -437,6 +434,7 @@ let clear_block_storage block evm_state = necessary to produce the next block. Block production starts by reading the head to retrieve information such as parent block hash. *) + let root = Durable_storage_path.root_of_chain_family chain_family in let block_parent = L2_types.block_parent block in let block_number = L2_types.block_number block in let (Qty number) = block_number in @@ -444,9 +442,7 @@ let clear_block_storage block evm_state = let* evm_state = if number > Z.zero then let pred_block_path = - Durable_storage_path.Block.by_hash (* TODO: Remove etherlink root *) - ~root:Durable_storage_path.etherlink_root - block_parent + Durable_storage_path.Block.by_hash ~root block_parent in delete ~kind:Value evm_state pred_block_path else return evm_state @@ -461,8 +457,7 @@ let clear_block_storage block evm_state = if number >= to_keep then let index_path = Durable_storage_path.Indexes.block_by_number - (* TODO: Remove etherlink root *) - ~root:Durable_storage_path.etherlink_root + ~root (Nth (Z.sub number to_keep)) in delete ~kind:Value evm_state index_path diff --git a/etherlink/bin_node/lib_dev/evm_state.mli b/etherlink/bin_node/lib_dev/evm_state.mli index dc95edf0a381..6c0b2502b31f 100644 --- a/etherlink/bin_node/lib_dev/evm_state.mli +++ b/etherlink/bin_node/lib_dev/evm_state.mli @@ -72,9 +72,10 @@ val execute_and_inspect : t -> bytes option list tzresult Lwt.t -(** [current_block_height evm_state] returns the height of the latest block - produced by the kernel. *) -val current_block_height : t -> Ethereum_types.quantity Lwt.t +(** [current_block_height ~root evm_state] returns the height of the latest + block produced by the kernel at [root]. *) +val current_block_height : + root:Durable_storage_path.path -> t -> Ethereum_types.quantity Lwt.t (** Same as {!current_block_height} for the block hash. *) val current_block_hash : @@ -135,10 +136,11 @@ val preload_kernel : t -> unit Lwt.t val get_delayed_inbox_item : t -> Ethereum_types.hash -> Evm_events.Delayed_transaction.t tzresult Lwt.t -(**[clear_block_storage block state] removes the parent of [block], and all - durable storage information stored for [block], if this function is called - they need to be store elsewhere, mainly it consists in transactions. *) -val clear_block_storage : 'transaction_object L2_types.block -> t -> t Lwt.t +(** [clear_block_storage chain_family block state] removes the parent of [block], + and all durable storage information stored for [block], if this function is + called they need to be store elsewhere, mainly it consists in transactions. *) +val clear_block_storage : + L2_types.chain_family -> 'transaction_object L2_types.block -> t -> t Lwt.t (** [storage_version tree] returns the current storage version set by the kernel. This storage version is used by the EVM node to determine whether a -- GitLab From 27c57e627ad4f906f5ce9e3a79ea5fd40a465f39 Mon Sep 17 00:00:00 2001 From: arnaud Date: Wed, 21 May 2025 15:05:18 +0200 Subject: [PATCH 6/8] L2/Node: Make 'block_param_to_block_number' a generic function that takes a chain family --- etherlink/bin_node/lib_dev/evm_ro_context.ml | 18 ++++++++--------- etherlink/bin_node/lib_dev/filter_helpers.ml | 1 + etherlink/bin_node/lib_dev/rollup_node.ml | 20 ++++++------------- etherlink/bin_node/lib_dev/services.ml | 9 +++++++-- .../bin_node/lib_dev/services_backend_sig.ml | 5 ++++- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/etherlink/bin_node/lib_dev/evm_ro_context.ml b/etherlink/bin_node/lib_dev/evm_ro_context.ml index 821581df25cc..c4431fc8fc76 100644 --- a/etherlink/bin_node/lib_dev/evm_ro_context.ml +++ b/etherlink/bin_node/lib_dev/evm_ro_context.ml @@ -358,9 +358,10 @@ struct Evm_store.use Ctxt.ctxt.store @@ fun conn -> Evm_store.L1_l2_finalized_levels.find conn ~l1_level - let block_param_to_block_number + let block_param_to_block_number ~chain_family (block_param : Ethereum_types.Block_parameter.extended) = let open Lwt_result_syntax in + let root = Durable_storage_path.root_of_chain_family chain_family in match block_param with | Block_parameter (Number n) -> return n | Block_parameter (Latest | Pending) when Ctxt.ctxt.finalized_view -> ( @@ -395,14 +396,12 @@ struct let*! bytes = Evm_state.inspect evm_state - Durable_storage_path.( - (* We're expecting an etherlink block here so we can inline etherlink root *) - Block.by_hash ~root:Durable_storage_path.etherlink_root hash) + Durable_storage_path.(Block.by_hash ~root hash) in match bytes with | Some bytes -> - let block = Ethereum_types.block_from_rlp bytes in - return block.number + let block = L2_types.block_from_bytes ~chain_family bytes in + return (L2_types.block_number block) | None -> failwith "Missing block %a" Ethereum_types.pp_block_hash hash) end @@ -544,7 +543,7 @@ let ro_backend ?evm_node_endpoint ctxt config : (module Services_backend_sig.S) module Tracer_etherlink = Tracer_sig.Make (Executor) (Etherlink_block_storage) (Tracer) - let block_param_to_block_number + let block_param_to_block_number ~chain_family (block_param : Ethereum_types.Block_parameter.extended) = let open Lwt_result_syntax in match block_param with @@ -555,7 +554,7 @@ let ro_backend ?evm_node_endpoint ctxt config : (module Services_backend_sig.S) | Some number -> return number | None -> failwith "Missing block %a" Ethereum_types.pp_block_hash hash) - | param -> block_param_to_block_number param + | param -> block_param_to_block_number ~chain_family param module Tezlink_block_storage : Tezlink_block_storage_sig.S = struct let nth_block level = @@ -577,7 +576,8 @@ let ro_backend ?evm_node_endpoint ctxt config : (module Services_backend_sig.S) (struct include Backend.Reader - let block_param_to_block_number = block_param_to_block_number + let block_param_to_block_number = + block_param_to_block_number ~chain_family:L2_types.Michelson end) (Tezlink_block_storage) end) diff --git a/etherlink/bin_node/lib_dev/filter_helpers.ml b/etherlink/bin_node/lib_dev/filter_helpers.ml index b4d33609f297..6dffbb19ba24 100644 --- a/etherlink/bin_node/lib_dev/filter_helpers.ml +++ b/etherlink/bin_node/lib_dev/filter_helpers.ml @@ -91,6 +91,7 @@ let validate_range log_filter_config | {from_block; to_block; _} -> let get_block_number block_param = Rollup_node_rpc.block_param_to_block_number + ~chain_family:L2_types.EVM (Block_parameter (Option.value ~default:Block_parameter.Latest block_param)) in diff --git a/etherlink/bin_node/lib_dev/rollup_node.ml b/etherlink/bin_node/lib_dev/rollup_node.ml index 5ebeaecd4245..ae520f300a72 100644 --- a/etherlink/bin_node/lib_dev/rollup_node.ml +++ b/etherlink/bin_node/lib_dev/rollup_node.ml @@ -158,17 +158,14 @@ end) : Services_backend_sig.Backend = struct | _ -> failwith "Inconsistent simulation results" end - let block_param_to_block_number + let block_param_to_block_number ~chain_family (block_param : Ethereum_types.Block_parameter.extended) = let open Lwt_result_syntax in + let root = Durable_storage_path.root_of_chain_family chain_family in let read_from_block_parameter param = let* state = Reader.get_state ~block:(Block_parameter param) () in let* value = - Reader.read - state - (Durable_storage_path.Block.current_number - (* TODO: Remove etherlink root *) - ~root:Durable_storage_path.etherlink_root) + Reader.read state (Durable_storage_path.Block.current_number ~root) in match value with | Some value -> @@ -180,17 +177,12 @@ end) : Services_backend_sig.Backend = struct | Block_hash {hash; _} -> ( let* state = Reader.get_state ~block:(Block_parameter Latest) () in let* value = - Reader.read - state - (Durable_storage_path.Block.by_hash - (* We're expecting an etherlink block here so we can inline etherlink root *) - ~root:Durable_storage_path.etherlink_root - hash) + Reader.read state (Durable_storage_path.Block.by_hash ~root hash) in match value with | Some value -> - let block = Ethereum_types.block_from_rlp value in - return block.number + let block = L2_types.block_from_bytes ~chain_family value in + return (L2_types.block_number block) | None -> failwith "Missing state for block %a" diff --git a/etherlink/bin_node/lib_dev/services.ml b/etherlink/bin_node/lib_dev/services.ml index 6db4e109c1fd..942e18fcac7e 100644 --- a/etherlink/bin_node/lib_dev/services.ml +++ b/etherlink/bin_node/lib_dev/services.ml @@ -178,7 +178,9 @@ let get_block_by_number ~full_transaction_object block_param (module Rollup_node_rpc : Services_backend_sig.S) = let open Lwt_result_syntax in let* (Ethereum_types.Qty n) = - Rollup_node_rpc.block_param_to_block_number (Block_parameter block_param) + Rollup_node_rpc.block_param_to_block_number + ~chain_family:L2_types.EVM + (Block_parameter block_param) in Rollup_node_rpc.Etherlink_block_storage.nth_block ~full_transaction_object n @@ -186,7 +188,9 @@ let get_block_receipts block_param (module Rollup_node_rpc : Services_backend_sig.S) = let open Lwt_result_syntax in let* (Ethereum_types.Qty n) = - Rollup_node_rpc.block_param_to_block_number (Block_parameter block_param) + Rollup_node_rpc.block_param_to_block_number + ~chain_family:L2_types.EVM + (Block_parameter block_param) in Rollup_node_rpc.Etherlink_block_storage.block_receipts n @@ -915,6 +919,7 @@ let dispatch_request (rpc_server_family : Rpc_types.rpc_server_family) let f ((block_param, config) : Tracer_types.block_input) = let* (Ethereum_types.Qty block_number) = Backend_rpc.block_param_to_block_number + ~chain_family:L2_types.EVM (Block_parameter block_param) in let*! traces = diff --git a/etherlink/bin_node/lib_dev/services_backend_sig.ml b/etherlink/bin_node/lib_dev/services_backend_sig.ml index c6b181962b55..d9c53e2a8c06 100644 --- a/etherlink/bin_node/lib_dev/services_backend_sig.ml +++ b/etherlink/bin_node/lib_dev/services_backend_sig.ml @@ -16,6 +16,7 @@ module type S = sig module Tracer_etherlink : Tracer_sig.S val block_param_to_block_number : + chain_family:L2_types.chain_family -> Ethereum_types.Block_parameter.extended -> Ethereum_types.quantity tzresult Lwt.t @@ -84,6 +85,7 @@ module type Backend = sig (** [block_param_to_block_number block_param] returns the block number of the block identified by [block_param]. *) val block_param_to_block_number : + chain_family:L2_types.chain_family -> Ethereum_types.Block_parameter.extended -> Ethereum_types.quantity tzresult Lwt.t @@ -129,7 +131,8 @@ module Make (Backend : Backend) (Executor : Evm_execution.S) : S = struct (struct include Backend.Reader - let block_param_to_block_number = Backend.block_param_to_block_number + let block_param_to_block_number = + Backend.block_param_to_block_number ~chain_family:L2_types.Michelson end) (Tezlink_block_storage) -- GitLab From 9c1f99a3f715b737a21693b70096187bff4ff56f Mon Sep 17 00:00:00 2001 From: arnaud Date: Mon, 19 May 2025 11:34:35 +0200 Subject: [PATCH 7/8] L2/node: Extract current_block_number from etherink module to make it generic The goal is to use it in the next commit when introducing an rpc generic block number --- etherlink/bin_node/lib_dev/durable_storage.ml | 5 +++++ etherlink/bin_node/lib_dev/services_backend_sig.ml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/etherlink/bin_node/lib_dev/durable_storage.ml b/etherlink/bin_node/lib_dev/durable_storage.ml index d2a7c6508000..ffdeba5e37f9 100644 --- a/etherlink/bin_node/lib_dev/durable_storage.ml +++ b/etherlink/bin_node/lib_dev/durable_storage.ml @@ -176,4 +176,9 @@ module Make (Reader : READER) = struct let open Lwt_result_syntax in let* read = read_with_state () in kernel_root_hash read + + let current_block_number ~root = + let open Lwt_result_syntax in + let* read = read_with_state () in + block_number ~root read Durable_storage_path.Block.Current end diff --git a/etherlink/bin_node/lib_dev/services_backend_sig.ml b/etherlink/bin_node/lib_dev/services_backend_sig.ml index d9c53e2a8c06..7bf936c5e6d4 100644 --- a/etherlink/bin_node/lib_dev/services_backend_sig.ml +++ b/etherlink/bin_node/lib_dev/services_backend_sig.ml @@ -20,6 +20,11 @@ module type S = sig Ethereum_types.Block_parameter.extended -> Ethereum_types.quantity tzresult Lwt.t + (** [current_block_number ~root] returns the current block number of the L2 chain + prefixed by [root] (depending on the chain_family in the configuration) *) + val current_block_number : + root:string -> Ethereum_types.quantity tzresult Lwt.t + (** [chain_id ()] returns chain id defined by the rollup. *) val chain_id : unit -> L2_types.chain_id tzresult Lwt.t -- GitLab From 21feb1367f3031888874b6608767ece4ba1b6d5e Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 15 May 2025 17:12:09 +0200 Subject: [PATCH 8/8] L2/node: Introduce a generic block number rpc and use it in blueprint follower Blueprint follower was using `eth_blockNumber` to follow the chain. But in Tezlink mode `eth_blockNumber` is returning an error because searching in `/evm/world_state`. So we introduce a new rpc or the sequencer that will return the block number depending on the chain family. The tezt that verify that restricted rpcs worked was modified because it was disabling `tez_blockNumber` and make the node crash --- .../bin_node/lib_dev/blueprints_follower.ml | 6 ++++- etherlink/bin_node/lib_dev/rpc_encodings.ml | 27 ++++++++++++++++--- etherlink/bin_node/lib_dev/rpc_encodings.mli | 3 +++ etherlink/bin_node/lib_dev/services.ml | 13 +++++++++ etherlink/tezt/tests/evm_rollup.ml | 6 ++--- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/etherlink/bin_node/lib_dev/blueprints_follower.ml b/etherlink/bin_node/lib_dev/blueprints_follower.ml index 38d775ed83cc..637508c61df4 100644 --- a/etherlink/bin_node/lib_dev/blueprints_follower.ml +++ b/etherlink/bin_node/lib_dev/blueprints_follower.ml @@ -48,7 +48,11 @@ let local_head_too_old ?remote_head ~evm_node_endpoint return (Qty remote_head) | None | Some _ -> (* See {Note keep_alive} *) - Batch.call (module Block_number) ~keep_alive:true ~evm_node_endpoint () + Batch.call + (module Generic_block_number) + ~keep_alive:true + ~evm_node_endpoint + () in return ( is_too_old ~remote:remote_head_number ~next:next_blueprint_number, diff --git a/etherlink/bin_node/lib_dev/rpc_encodings.ml b/etherlink/bin_node/lib_dev/rpc_encodings.ml index 151805da56d2..6ffe10d318b3 100644 --- a/etherlink/bin_node/lib_dev/rpc_encodings.ml +++ b/etherlink/bin_node/lib_dev/rpc_encodings.ml @@ -217,6 +217,22 @@ module Kernel_root_hash = struct type ('input, 'output) method_ += Method : (input, output) method_ end +module Generic_block_number = struct + open Ethereum_types + + type input = unit + + type output = quantity + + let input_encoding = Data_encoding.unit + + let output_encoding = quantity_encoding + + let method_ = "tez_blockNumber" + + type ('input, 'output) method_ += Method : (input, output) method_ +end + module Network_id = struct type input = unit @@ -1025,11 +1041,17 @@ type map_result = let evm_supported_methods : (module METHOD) list = [ + (* Generic rpcs *) + (module Generic_block_number); (module Kernel_version); (module Kernel_root_hash); (module Network_id); (module Chain_id); (module Chain_family); + (module Durable_state_value); + (module Durable_state_subkeys); + (module Get_finalized_blocks_of_l1_level); + (* Etherlink rpcs *) (module Accounts); (module Get_balance); (module Get_storage_at); @@ -1060,8 +1082,6 @@ let evm_supported_methods : (module METHOD) list = (module Produce_block); (module Produce_proposal); (module Inject_transaction); - (module Durable_state_value); - (module Durable_state_subkeys); (module Eth_max_priority_fee_per_gas); (module Replay_block); (module Trace_transaction); @@ -1071,7 +1091,6 @@ let evm_supported_methods : (module METHOD) list = (module Subscribe); (module Unsubscribe); (module Trace_block); - (module Get_finalized_blocks_of_l1_level); ] let evm_unsupported_methods : string list = @@ -1126,7 +1145,7 @@ let michelson_supported_methods = evm_supported_methods let multichain_sequencer_supported_methods : (module METHOD) list = [ - (module Block_number); + (module Generic_block_number); (module Send_raw_transaction); (* Private RPCs *) (module Produce_block); diff --git a/etherlink/bin_node/lib_dev/rpc_encodings.mli b/etherlink/bin_node/lib_dev/rpc_encodings.mli index 362b8d60859a..ae6d35378e9b 100644 --- a/etherlink/bin_node/lib_dev/rpc_encodings.mli +++ b/etherlink/bin_node/lib_dev/rpc_encodings.mli @@ -161,6 +161,9 @@ module Get_storage_at : * Ethereum_types.Block_parameter.extended and type output = Ethereum_types.hex +module Generic_block_number : + METHOD with type input = unit and type output = Ethereum_types.quantity + module Block_number : METHOD with type input = unit and type output = Ethereum_types.quantity diff --git a/etherlink/bin_node/lib_dev/services.ml b/etherlink/bin_node/lib_dev/services.ml index 942e18fcac7e..3fd9c599ec62 100644 --- a/etherlink/bin_node/lib_dev/services.ml +++ b/etherlink/bin_node/lib_dev/services.ml @@ -549,6 +549,19 @@ let dispatch_request (rpc_server_family : Rpc_types.rpc_server_family) rpc_ok value in build_with_input ~f module_ parameters + | Generic_block_number.Method -> + let f (_ : unit option) = + let chain_family = + Configuration.retrieve_chain_family + ~l2_chains:config.experimental_features.l2_chains + in + let root = + Durable_storage_path.root_of_chain_family chain_family + in + let* block_number = Backend_rpc.current_block_number ~root in + rpc_ok block_number + in + build ~f module_ parameters | Block_number.Method -> let f (_ : unit option) = let* block_number = diff --git a/etherlink/tezt/tests/evm_rollup.ml b/etherlink/tezt/tests/evm_rollup.ml index 7bb198a86f01..3aab368bae7a 100644 --- a/etherlink/tezt/tests/evm_rollup.ml +++ b/etherlink/tezt/tests/evm_rollup.ml @@ -6426,11 +6426,11 @@ let test_rpcs_can_be_disabled = register_both ~tags:["evm"; "rpc"; "restricted"] ~title:"RPCs can be restricted" - ~restricted_rpcs:"tez_*" + ~restricted_rpcs:"tez_kernel*" @@ fun ~protocol:_ ~evm_setup -> let* kernel_version = Rpc.tez_kernelVersion evm_setup.evm_node in (match kernel_version with - | Ok _ -> Test.fail "tez_* methods should be unsupported" + | Ok _ -> Test.fail "tez_kernel* methods should be unsupported" | Error err -> Check.( (err.message = "Method disabled") @@ -6438,7 +6438,7 @@ let test_rpcs_can_be_disabled = ~error_msg:"Disabled method should return %R, but returned %L")) ; let* kernel_root_hash = Rpc.tez_kernelRootHash evm_setup.evm_node in (match kernel_root_hash with - | Ok _ -> Test.fail "tez_* methods should be unsupported" + | Ok _ -> Test.fail "tez_kernel* methods should be unsupported" | Error err -> Check.( (err.message = "Method disabled") -- GitLab