From be5cb4e9354fe75bbd3c581ab77d2a1570af04d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 12 Feb 2025 18:13:26 +0100 Subject: [PATCH 1/4] Etherlink/Kernel/Migration: add legacy module --- etherlink/kernel_evm/kernel/src/migration.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/etherlink/kernel_evm/kernel/src/migration.rs b/etherlink/kernel_evm/kernel/src/migration.rs index e566c57a1a7f..6c559e5c256d 100644 --- a/etherlink/kernel_evm/kernel/src/migration.rs +++ b/etherlink/kernel_evm/kernel/src/migration.rs @@ -70,6 +70,13 @@ pub fn allow_path_not_found(res: Result<(), RuntimeError>) -> Result<(), Runtime const TMP_NEXT_BLUEPRINT_PATH: RefPath = RefPath::assert_from(b"/__tmp_next_blueprint_path"); +mod legacy { + // This module contains copies of old implementations of some + // functions. The legacy semantics of these functions is needed in + // some migration step to access the storage using the fields + // which were present at the time. +} + fn migrate_to( host: &mut Host, version: StorageVersion, -- GitLab From 0ac56bdb126e88993b14e87cbbb141393efebc3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 12 Feb 2025 18:16:45 +0100 Subject: [PATCH 2/4] Etherlink/Kernel/Migration: snapshot read_next_blueprint_number --- etherlink/kernel_evm/kernel/src/migration.rs | 22 +++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/migration.rs b/etherlink/kernel_evm/kernel/src/migration.rs index 6c559e5c256d..c34dd0782bf9 100644 --- a/etherlink/kernel_evm/kernel/src/migration.rs +++ b/etherlink/kernel_evm/kernel/src/migration.rs @@ -6,8 +6,7 @@ use crate::block_storage; use crate::blueprint_storage::{ - blueprint_path, clear_all_blueprints, read_next_blueprint_number, - store_current_block_header, + blueprint_path, clear_all_blueprints, store_current_block_header, }; use crate::error::Error; use crate::error::StorageError; @@ -75,6 +74,23 @@ mod legacy { // functions. The legacy semantics of these functions is needed in // some migration step to access the storage using the fields // which were present at the time. + + use super::*; + use tezos_storage::error::Error as GenStorageError; + + pub fn read_next_blueprint_number( + host: &Host, + ) -> anyhow::Result { + match block_storage::read_current_number(host) { + Err(err) => match err.downcast_ref() { + Some(GenStorageError::Runtime(RuntimeError::PathNotFound)) => { + Ok(U256::zero()) + } + _ => Err(err), + }, + Ok(block_number) => Ok(block_number.saturating_add(U256::one())), + } + } } fn migrate_to( @@ -208,7 +224,7 @@ fn migrate_to( // However we need to keep the next blueprint as it // trigerred the upgrade. - let next_blueprint_number = read_next_blueprint_number(host)?; + let next_blueprint_number = legacy::read_next_blueprint_number(host)?; let blueprint_path = blueprint_path(next_blueprint_number)?; allow_path_not_found( host.store_move(&blueprint_path, &TMP_NEXT_BLUEPRINT_PATH), -- GitLab From 81af0e7d7820eb7660cba6110bf2f0be672bc712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Tue, 18 Feb 2025 18:09:46 +0100 Subject: [PATCH 3/4] Etherlink/Kernel: read_next_blueprint_number does not read a block This commit changes the definition of read_next_blueprint_number to use the /evm/current_block_header field. In particular, we don't access the world state and the amount of data fetched is bounded. --- .../kernel/src/blueprint_storage.rs | 28 ++++++++++--------- etherlink/kernel_evm/kernel/src/inbox.rs | 20 +++++++++++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index 5a2dc0879a48..c43ae539e780 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -3,7 +3,6 @@ // // SPDX-License-Identifier: MIT -use crate::block_storage; use crate::blueprint::Blueprint; use crate::configuration::{Configuration, ConfigurationMode}; use crate::error::{Error, StorageError}; @@ -28,9 +27,7 @@ use tezos_smart_rollup::types::Timestamp; use tezos_smart_rollup_core::MAX_INPUT_MESSAGE_SIZE; use tezos_smart_rollup_host::path::*; use tezos_smart_rollup_host::runtime::RuntimeError; -use tezos_storage::{ - error::Error as GenStorageError, read_rlp, store_read_slice, store_rlp, -}; +use tezos_storage::{read_rlp, store_read_slice, store_rlp}; pub const EVM_BLUEPRINTS: RefPath = RefPath::assert_from(b"/evm/blueprints"); @@ -210,15 +207,13 @@ pub fn store_inbox_blueprint( } #[inline(always)] -pub fn read_next_blueprint_number(host: &Host) -> anyhow::Result { - match block_storage::read_current_number(host) { - Err(err) => match err.downcast_ref() { - Some(GenStorageError::Runtime(RuntimeError::PathNotFound)) => { - Ok(U256::zero()) - } - _ => Err(err), - }, - Ok(block_number) => Ok(block_number.saturating_add(U256::one())), +pub fn read_next_blueprint_number(host: &Host) -> Result { + match read_current_block_header(host) { + Ok(block_header) => Ok(block_header.blueprint_header.number + 1), + Err(Error::Storage(StorageError::Runtime(RuntimeError::PathNotFound))) => { + Ok(U256::zero()) + } + Err(err) => Err(err), } } @@ -306,6 +301,12 @@ pub fn store_current_block_header( store_rlp(current_block_header, host, &EVM_CURRENT_BLOCK_HEADER).map_err(Error::from) } +pub fn read_current_block_header( + host: &Host, +) -> Result { + Ok(read_rlp(host, &EVM_CURRENT_BLOCK_HEADER)?) +} + /// For the tick model we only accept blueprints where cumulative size of chunks /// less or equal than 512kB. A chunk weights 4kB, then (512 * 1024) / 4096 = /// 128. @@ -600,6 +601,7 @@ pub fn read_next_blueprint( host: &mut Host, config: &mut Configuration, ) -> anyhow::Result<(Option, usize)> { + use crate::block_storage; let (number, parent_hash, previous_timestamp) = match block_storage::read_current(host) { Ok(block) => (block.number + 1, block.hash, block.timestamp), diff --git a/etherlink/kernel_evm/kernel/src/inbox.rs b/etherlink/kernel_evm/kernel/src/inbox.rs index 74fa96b7747f..5b2b034395c3 100644 --- a/etherlink/kernel_evm/kernel/src/inbox.rs +++ b/etherlink/kernel_evm/kernel/src/inbox.rs @@ -761,7 +761,10 @@ pub fn read_sequencer_inbox( #[cfg(test)] mod tests { use super::*; - use crate::blueprint_storage::blueprint_path; + use crate::blueprint_storage::{ + blueprint_path, store_current_block_header, BlockHeader, BlueprintHeader, + EVMBlockHeader, + }; use crate::configuration::TezosContracts; use crate::dal_slot_import_signal::{ DalSlotIndicesList, DalSlotIndicesOfLevel, UnsignedDalSlotSignals, @@ -1374,8 +1377,19 @@ mod tests { // Prepare the host. let mut host = MockKernelHost::default(); let address = smart_rollup_address(); - crate::block_storage::internal_for_tests::store_current_number( - &mut host, head_level, + store_current_block_header( + &mut host, + &BlockHeader { + blueprint_header: BlueprintHeader { + number: head_level, + timestamp: 0.into(), + }, + evm_block_header: EVMBlockHeader { + hash: crate::block::GENESIS_PARENT_HASH, + receipts_root: vec![], + transactions_root: vec![], + }, + }, ) .unwrap(); -- GitLab From 2a559fcc5ec0288549a06179c34a0fcb0709f95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Tue, 18 Feb 2025 18:21:48 +0100 Subject: [PATCH 4/4] Etherlink/Kernel: use timestamp from block header In this commit, when computing at stage 1 the timestamp of a flushed blueprint in the future of the current block, we read the block header instead of the block. --- etherlink/kernel_evm/kernel/src/stage_one.rs | 32 ++++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index eba15df16691..cf02693849ce 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -5,7 +5,8 @@ use crate::blueprint::Blueprint; use crate::blueprint_storage::{ - clear_all_blueprints, store_forced_blueprint, store_inbox_blueprint, + clear_all_blueprints, read_current_block_header, store_forced_blueprint, + store_inbox_blueprint, BlockHeader, }; use crate::configuration::{ Configuration, ConfigurationMode, DalConfiguration, TezosContracts, @@ -18,7 +19,6 @@ use crate::storage::read_last_info_per_level_timestamp; use anyhow::Ok; use std::ops::Add; use tezos_crypto_rs::hash::ContractKt1Hash; -use tezos_ethereum::block::L2Block; use tezos_evm_logging::{log, Level::*}; use tezos_evm_runtime::runtime::Runtime; use tezos_smart_rollup_encoding::public_key::PublicKey; @@ -58,8 +58,13 @@ fn fetch_delayed_transactions( delayed_inbox: &mut DelayedInbox, ) -> anyhow::Result<()> { let timestamp = read_last_info_per_level_timestamp(host)?; - // Number for the first forced blueprint - let base = crate::blueprint_storage::read_next_blueprint_number(host)?; + // Number and minimal timestamp for the first forced blueprint + let (base, minimal_timestamp) = match read_current_block_header(host) { + Result::Ok(BlockHeader { + blueprint_header, .. + }) => (blueprint_header.number + 1, blueprint_header.timestamp), + Err(_) => (0.into(), 0.into()), + }; // Accumulator of how many blueprints we fetched let mut offset: u32 = 0; @@ -71,22 +76,9 @@ fn fetch_delayed_transactions( timed_out.len() ); - let timestamp = match crate::block_storage::read_current(host) { - Result::Ok(L2Block { - timestamp: head_timestamp, - .. - }) => { - // Timestamp has to be at least equal or greater than previous timestamp. - // If it's not the case, we fallback and take the previous block timestamp. - std::cmp::max(timestamp, head_timestamp) - } - Err(_) => { - // If there's no current block, there's no previous - // timestamp. So we take whatever is the current - // timestamp. - timestamp - } - }; + // Timestamp has to be at least equal or greater than previous timestamp. + // If it's not the case, we fallback and take the previous block timestamp. + let timestamp = std::cmp::max(timestamp, minimal_timestamp); let level = base.add(offset); Event::FlushDelayedInbox { -- GitLab