From fbf7da47a37a5dbe77075738db44e88b0a427749 Mon Sep 17 00:00:00 2001 From: tgmichel Date: Wed, 23 Feb 2022 19:16:35 +0100 Subject: [PATCH] Fix bug parent hash on `BlockV2` upgrade (#570) * Fix bug parent hash on `BlockV2` upgrade * BlockV0 -> BlockV2 migration utility functions --- frame/ethereum/Cargo.toml | 1 + frame/ethereum/src/lib.rs | 73 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/frame/ethereum/Cargo.toml b/frame/ethereum/Cargo.toml index c64a5447cf..fcdd50a468 100644 --- a/frame/ethereum/Cargo.toml +++ b/frame/ethereum/Cargo.toml @@ -67,3 +67,4 @@ std = [ "fp-storage/std", "pallet-evm/std", ] +try-runtime = [ "frame-support/try-runtime" ] diff --git a/frame/ethereum/src/lib.rs b/frame/ethereum/src/lib.rs index c9e611783d..dbd6b17d5b 100644 --- a/frame/ethereum/src/lib.rs +++ b/frame/ethereum/src/lib.rs @@ -33,11 +33,13 @@ use evm::ExitReason; use fp_consensus::{PostLog, PreLog, FRONTIER_ENGINE_ID}; use fp_evm::CallOrCreateInfo; use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; +#[cfg(feature = "try-runtime")] +use frame_support::traits::OnRuntimeUpgradeHelpersExt; use frame_support::{ codec::{Decode, Encode}, dispatch::DispatchResultWithPostInfo, scale_info::TypeInfo, - traits::{EnsureOrigin, Get}, + traits::{EnsureOrigin, Get, PalletInfoAccess}, weights::{Pays, PostDispatchInfo, Weight}, }; use frame_system::{pallet_prelude::OriginFor, WeightInfo}; @@ -427,7 +429,11 @@ impl Pallet { let receipts_root = ethereum::util::ordered_trie_root(receipts.iter().map(|r| rlp::encode(r))); let partial_header = ethereum::PartialHeader { - parent_hash: Self::current_block_hash().unwrap_or_default(), + parent_hash: if block_number > U256::zero() { + BlockHash::::get(block_number - 1) + } else { + H256::default() + }, beneficiary: pallet_evm::Pallet::::find_author(), state_root: T::StateRoot::get(), receipts_root, @@ -848,6 +854,69 @@ impl Pallet { Ok(()) } } + + pub fn migrate_block_v0_to_v2() -> Weight { + let db_weights = T::DbWeight::get(); + let mut weight: Weight = db_weights.read; + let item = b"CurrentBlock"; + let block_v0 = frame_support::storage::migration::get_storage_value::( + Self::name().as_bytes(), + item, + &[], + ); + if let Some(block_v0) = block_v0 { + weight = weight.saturating_add(db_weights.write); + let block_v2: ethereum::BlockV2 = block_v0.into(); + frame_support::storage::migration::put_storage_value::( + Self::name().as_bytes(), + item, + &[], + block_v2, + ); + } + weight + } + + #[cfg(feature = "try-runtime")] + pub fn pre_migrate_block_v2() -> Result<(), &'static str> { + let item = b"CurrentBlock"; + let block_v0 = frame_support::storage::migration::get_storage_value::( + Self::name().as_bytes(), + item, + &[], + ); + if let Some(block_v0) = block_v0 { + Self::set_temp_storage(block_v0.header.number, "number"); + Self::set_temp_storage(block_v0.header.parent_hash, "parent_hash"); + Self::set_temp_storage(block_v0.transactions.len() as u64, "transaction_len"); + } + Ok(()) + } + + #[cfg(feature = "try-runtime")] + pub fn post_migrate_block_v2() -> Result<(), &'static str> { + let v0_number = + Self::get_temp_storage("number").expect("We stored a number; it should be there; qed"); + let v0_parent_hash = Self::get_temp_storage("parent_hash") + .expect("We stored a parent hash; it should be there; qed"); + let v0_transaction_len: u64 = Self::get_temp_storage("transaction_len") + .expect("We stored a transaction count; it should be there; qed"); + + let item = b"CurrentBlock"; + let block_v2 = frame_support::storage::migration::get_storage_value::( + Self::name().as_bytes(), + item, + &[], + ); + + assert!(block_v2.is_some()); + + let block_v2 = block_v2.unwrap(); + assert_eq!(block_v2.header.number, v0_number); + assert_eq!(block_v2.header.parent_hash, v0_parent_hash); + assert_eq!(block_v2.transactions.len() as u64, v0_transaction_len); + Ok(()) + } } #[derive(Eq, PartialEq, Clone, RuntimeDebug)]