diff --git a/etherlink/CHANGES_KERNEL.md b/etherlink/CHANGES_KERNEL.md index 30e0e45ba3e65c38fc67a4995d4e9c241409ac1a..8fb8caf79dfb1a59caaa9668a481741957e86dfb 100644 --- a/etherlink/CHANGES_KERNEL.md +++ b/etherlink/CHANGES_KERNEL.md @@ -14,6 +14,8 @@ IO. (!16661 !16684 !16685 !16618) - Add a storage field containing the number of the next blueprint to apply at path ``/evm/blueprints/next``. (!16569) +- Add a storage field containing the timestamp of the previous block + at path ``/evm/blueprints/last_block_timestamp``. (!16686) ## Next proposal diff --git a/etherlink/kernel_evm/kernel/src/block.rs b/etherlink/kernel_evm/kernel/src/block.rs index 0ab4e23414e11d2e0e8ad5ddd85dadc1bb98079c..fd9bfa653984d6819d9c672a46d8ac2bd6d50832 100644 --- a/etherlink/kernel_evm/kernel/src/block.rs +++ b/etherlink/kernel_evm/kernel/src/block.rs @@ -10,7 +10,8 @@ use crate::apply::{ }; use crate::block_storage; use crate::blueprint_storage::{ - drop_blueprint, read_blueprint, store_next_blueprint_number, + drop_blueprint, read_blueprint, store_last_block_timestamp, + store_next_blueprint_number, }; use crate::configuration::ConfigurationMode; use crate::configuration::Limits; @@ -418,6 +419,7 @@ fn promote_block( safe_host.host, block.number.saturating_add(U256::one()), )?; + store_last_block_timestamp(safe_host.host, &block.timestamp)?; Event::BlueprintApplied { number: block.number, diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index 9f972833553ba9c2a8ed4ac706a7e5015dfde0f2..fae09280a479491bef5e6904927f04c702784da5 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -12,7 +12,9 @@ use crate::inbox::{Transaction, TransactionContent}; use crate::sequencer_blueprint::{ BlueprintWithDelayedHashes, UnsignedSequencerBlueprint, }; -use crate::storage::read_last_info_per_level_timestamp; +use crate::storage::{ + read_last_info_per_level_timestamp, read_timestamp_path, store_timestamp_path, +}; use crate::{delayed_inbox, DelayedInbox}; use primitive_types::U256; use rlp::{Decodable, DecoderError, Encodable}; @@ -36,6 +38,9 @@ const EVM_BLUEPRINT_NB_CHUNKS: RefPath = RefPath::assert_from(b"/nb_chunks"); const NEXT_BLUEPRINT_NUMBER: RefPath = RefPath::assert_from(b"/evm/blueprints/next"); +const LAST_BLOCK_TIMESTAMP: RefPath = + RefPath::assert_from(b"/evm/blueprints/last_block_timestamp"); + /// The store representation of a blueprint. /// It's designed to support storing sequencer blueprints, /// which can be chunked, and blueprints constructed from @@ -166,7 +171,7 @@ pub fn store_inbox_blueprint( } #[inline(always)] -pub fn read_next_blueprint_number(host: &Host) -> anyhow::Result { +pub fn read_next_blueprint_number(host: &Host) -> Result { match read_u256_le(host, &NEXT_BLUEPRINT_NUMBER) { Err(GenStorageError::Runtime(RuntimeError::PathNotFound)) => Ok(U256::zero()), res => Ok(res?), @@ -176,10 +181,23 @@ pub fn read_next_blueprint_number(host: &Host) -> anyhow::Result< pub fn store_next_blueprint_number( host: &mut Host, number: U256, -) -> anyhow::Result<()> { +) -> Result<(), Error> { Ok(write_u256_le(host, &NEXT_BLUEPRINT_NUMBER, number)?) } +pub fn read_last_block_timestamp( + host: &Host, +) -> anyhow::Result { + Ok(read_timestamp_path(host, &LAST_BLOCK_TIMESTAMP)?) +} + +pub fn store_last_block_timestamp( + host: &mut Host, + timestamp: &Timestamp, +) -> Result<(), Error> { + store_timestamp_path(host, &LAST_BLOCK_TIMESTAMP, timestamp) +} + // Used to store a blueprint made out of forced delayed transactions. pub fn store_forced_blueprint( host: &mut Host, @@ -489,7 +507,14 @@ pub fn drop_blueprint(host: &mut Host, number: U256) -> Result<() pub fn clear_all_blueprints(host: &mut Host) -> Result<(), Error> { if host.store_has(&EVM_BLUEPRINTS)?.is_some() { - Ok(host.store_delete(&EVM_BLUEPRINTS)?) + let next_blueprint_number = read_next_blueprint_number(host)?; + let last_block_timestamp = read_last_block_timestamp(host).ok(); + host.store_delete(&EVM_BLUEPRINTS)?; + store_next_blueprint_number(host, next_blueprint_number)?; + if let Some(last_block_timestamp) = last_block_timestamp { + store_last_block_timestamp(host, &last_block_timestamp)? + } + Ok(()) } else { Ok(()) } diff --git a/etherlink/kernel_evm/kernel/src/migration.rs b/etherlink/kernel_evm/kernel/src/migration.rs index 40b15c95d8a43cc50fae16cf3a0ebbf32493d903..549c0ec83062a4c464871a9bc565cc738a0ef3e7 100644 --- a/etherlink/kernel_evm/kernel/src/migration.rs +++ b/etherlink/kernel_evm/kernel/src/migration.rs @@ -6,7 +6,8 @@ use crate::block_storage; use crate::blueprint_storage::{ - blueprint_path, clear_all_blueprints, store_next_blueprint_number, + blueprint_path, clear_all_blueprints, store_last_block_timestamp, + store_next_blueprint_number, }; use crate::error::Error; use crate::error::StorageError; @@ -271,6 +272,21 @@ fn migrate_to( store_next_blueprint_number(host, legacy::read_next_blueprint_number(host)?)?; Ok(MigrationStatus::Done) } + StorageVersion::V28 => { + // Initialize the last_block_timestamp field + match block_storage::read_current(host) { + Ok(block) => { + store_last_block_timestamp(host, &block.timestamp)?; + Ok(MigrationStatus::Done) + } + Err(err) => match err.downcast_ref() { + Some(tezos_storage::error::Error::Runtime( + RuntimeError::PathNotFound, + )) => Ok(MigrationStatus::Done), + _ => Err(err), + }, + } + } } } diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index 21c7d86fc8a48d6bc7a2a0ee89c519b64fdc3eee..5de87e05844e49acb34f3bb8bbd4739c4f285321 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -18,7 +18,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; @@ -71,11 +70,8 @@ fn fetch_delayed_transactions( timed_out.len() ); - let timestamp = match crate::block_storage::read_current(host) { - Result::Ok(L2Block { - timestamp: head_timestamp, - .. - }) => { + let timestamp = match crate::blueprint_storage::read_last_block_timestamp(host) { + Result::Ok(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) diff --git a/etherlink/kernel_evm/kernel/src/storage.rs b/etherlink/kernel_evm/kernel/src/storage.rs index d0fa9b9b54164b05caf4198ebe8b1b94f3c0f662..cf997235d0bc417c7ba24a12ed9cd226946b94d0 100644 --- a/etherlink/kernel_evm/kernel/src/storage.rs +++ b/etherlink/kernel_evm/kernel/src/storage.rs @@ -60,6 +60,7 @@ pub enum StorageVersion { V25, V26, V27, + V28, } impl From for u64 { @@ -74,7 +75,7 @@ impl StorageVersion { } } -pub const STORAGE_VERSION: StorageVersion = StorageVersion::V27; +pub const STORAGE_VERSION: StorageVersion = StorageVersion::V28; pub const PRIVATE_FLAG_PATH: RefPath = RefPath::assert_from(b"/evm/remove_whitelist"); @@ -534,7 +535,7 @@ pub fn store_sequencer_pool_address( pub fn store_timestamp_path( host: &mut Host, - path: &OwnedPath, + path: &impl Path, timestamp: &Timestamp, ) -> Result<(), Error> { host.store_write(path, ×tamp.i64().to_le_bytes(), 0)?; @@ -590,13 +591,13 @@ pub fn store_last_info_per_level_timestamp( host: &mut Host, timestamp: Timestamp, ) -> Result<(), Error> { - store_timestamp_path(host, &EVM_INFO_PER_LEVEL_TIMESTAMP.into(), ×tamp)?; + store_timestamp_path(host, &EVM_INFO_PER_LEVEL_TIMESTAMP, ×tamp)?; store_info_per_level_stats(host, timestamp) } pub fn read_timestamp_path( host: &Host, - path: &OwnedPath, + path: &impl Path, ) -> Result { let mut buffer = [0u8; 8]; store_read_slice(host, path, &mut buffer, 8)?; @@ -607,7 +608,7 @@ pub fn read_timestamp_path( pub fn read_last_info_per_level_timestamp( host: &Host, ) -> Result { - read_timestamp_path(host, &EVM_INFO_PER_LEVEL_TIMESTAMP.into()) + read_timestamp_path(host, &EVM_INFO_PER_LEVEL_TIMESTAMP) } pub fn read_admin(host: &mut Host) -> Option { diff --git a/etherlink/kernel_evm/kernel/tests/resources/failed_migration.wasm b/etherlink/kernel_evm/kernel/tests/resources/failed_migration.wasm index c4efa61843a4df05175fc16f45a5157593e20af4..8bd849627ca16a1f3d587e27c5b0745a70cc022c 100755 Binary files a/etherlink/kernel_evm/kernel/tests/resources/failed_migration.wasm and b/etherlink/kernel_evm/kernel/tests/resources/failed_migration.wasm differ