Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
start on migration work
Browse files Browse the repository at this point in the history
  • Loading branch information
claravanstaden committed May 30, 2024
1 parent 0b302ff commit 3b4980d
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bridges/snowbridge/pallets/ethereum-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
mod migration;

use frame_support::{
dispatch::DispatchResult, pallet_prelude::OptionQuery, traits::Get, transactional,
Expand Down
114 changes: 114 additions & 0 deletions bridges/snowbridge/pallets/ethereum-client/src/migration/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
use crate::pallet::Config;
use frame_support::{
migrations::{MigrationId, SteppedMigration, SteppedMigrationError},
pallet_prelude::PhantomData,
weights::WeightMeter,
};
use frame_support::migration::clear_storage_prefix;
use frame_support::storage::unhashed::clear_prefix;
use sp_core::Get;
use sp_runtime::Saturating;

mod weights;
pub const PALLET_MIGRATIONS_ID: &[u8; 26] = b"ethereum-execution-headers";

/// Module containing the old Ethereum execution headers that should be cleaned up.
mod v0 {
use super::Config;
use crate::pallet::Pallet;
use frame_support::{storage_alias, Blake2_128Concat, Identity};
use frame_support::pallet_prelude::{OptionQuery, ValueQuery};
use sp_core::H256;

#[storage_alias]
pub(super) type LatestExecutionState<T: Config> =
StorageValue<Pallet<T>, ExecutionHeaderState, ValueQuery>;

#[storage_alias]
pub type ExecutionHeaders<T: Config> =
StorageMap<Pallet<T>, Identity, H256, CompactExecutionHeader, OptionQuery>;

#[storage_alias]
pub type ExecutionHeaderIndex<T: Config> = StorageValue<Pallet<T>, u32, ValueQuery>;

#[storage_alias]
pub type ExecutionHeaderMapping<T: Config> = StorageMap<Pallet<T>, Identity, u32, H256, ValueQuery>;
}

#[derive(Copy, Clone, Default, Encode, Decode, TypeInfo, MaxEncodedLen)]
pub struct ExecutionHeaderState {
pub beacon_block_root: H256,
pub beacon_slot: u64,
pub block_hash: H256,
pub block_number: u64,
}

#[derive(
Default,
Encode,
Decode,
CloneNoBound,
PartialEqNoBound,
RuntimeDebugNoBound,
TypeInfo,
MaxEncodedLen,
)]
pub struct CompactExecutionHeader {
pub parent_hash: H256,
#[codec(compact)]
pub block_number: u64,
pub state_root: H256,
pub receipts_root: H256,
}

pub struct EthereumExecutionHeaderCleanup<T: Config, W: weights::WeightInfo, M: Get<u32>>(PhantomData<(T, W)>);
impl<T: Config, W: weights::WeightInfo, M:Get <u32>> SteppedMigration for EthereumExecutionHeaderCleanup<T, W, M> {
type Cursor = u32;
type Identifier = MigrationId<26>; // Length of the migration ID PALLET_MIGRATIONS_ID

fn id() -> Self::Identifier {
MigrationId { pallet_id: *PALLET_MIGRATIONS_ID, version_from: 0, version_to: 1 }
}

fn step(
mut cursor: Option<Self::Cursor>,
meter: &mut WeightMeter,
) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
let required = W::step();
// If there is not enough weight for a single step, return an error. This case can be
// problematic if it is the first migration that ran in this block. But there is nothing
// that we can do about it here.
if meter.remaining().any_lt(required) {
return Err(SteppedMigrationError::InsufficientWeight { required });
}

// We loop here to do as much progress as possible per step.
loop {
if meter.try_consume(required).is_err() {
break;
}

let mut index = if let Some(last_key) = cursor {
last_key.saturating_add(1)
} else {
// If no cursor is provided, start iterating from the beginning.
0
};

if index >= M::get() {
v0::LatestExecutionState::<T>::kill();
v0::ExecutionHeaderIndex::<T>::kill();
// We are at the end of the migration, signal complete.
cursor = None;
} else {
let execution_hash = v0::ExecutionHeaderMapping::<T>::get(index);
v0::ExecutionHeaders::<T>::delete(execution_hash);
v0::ExecutionHeaderMapping::<T>::delete(index);
cursor = Some(index)
}
}
Ok(cursor)
}
}
27 changes: 27 additions & 0 deletions bridges/snowbridge/pallets/ethereum-client/src/migration/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
#![cfg(all(test, not(feature = "runtime-benchmarks")))]

use frame_support::traits::OnRuntimeUpgrade;
use pallet_migrations::WeightInfo as _;
use crate::mock::new_test_ext;

#[test]
fn ethereum_execution_header_migration_works() {
new_test_ext().execute_with(|| {
frame_support::__private::sp_tracing::try_init_simple();
// Insert some values into the old storage items.


// Give it enough weight to do exactly 16 iterations:
let limit = <T as pallet_migrations::Config>::WeightInfo::progress_mbms_none() +
pallet_migrations::Pallet::<T>::exec_migration_max_weight() +
weights::SubstrateWeight::<T>::step() * 16;
MigratorServiceWeight::set(&limit);

System::set_block_number(1);
AllPalletsWithSystem::on_runtime_upgrade(); // onboard MBMs

// Check everything is empty
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
//! Autogenerated weights for `pallet_example_mbm`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2024-03-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `Olivers-MBP`, CPU: `<UNKNOWN>`
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]

use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use core::marker::PhantomData;

/// Weight functions needed for `pallet_example_mbm`.
pub trait WeightInfo {
fn step() -> Weight;
}

/// Weights for `pallet_example_mbm` using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Storage: `PalletExampleMbms::MyMap` (r:2 w:1)
/// Proof: `PalletExampleMbms::MyMap` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
fn step() -> Weight {
// Proof Size summary in bytes:
// Measured: `28`
// Estimated: `5996`
// Minimum execution time: 6_000_000 picoseconds.
Weight::from_parts(8_000_000, 5996) // TODO update - add weights in rococo runtime
.saturating_add(T::DbWeight::get().reads(2_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
}

// For backwards compatibility and tests.
impl WeightInfo for () {
/// Storage: `PalletExampleMbms::MyMap` (r:2 w:1)
/// Proof: `PalletExampleMbms::MyMap` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
fn step() -> Weight {
// Proof Size summary in bytes:
// Measured: `28`
// Estimated: `5996`
// Minimum execution time: 6_000_000 picoseconds.
Weight::from_parts(8_000_000, 5996)
.saturating_add(RocksDbWeight::get().reads(2_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pallet-authorship = { path = "../../../../../substrate/frame/authorship", defaul
pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false }
pallet-session = { path = "../../../../../substrate/frame/session", default-features = false }
pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false }
pallet-migrations = { path = "../../../../../substrate/frame/migrations", default-features = false }
pallet-multisig = { path = "../../../../../substrate/frame/multisig", default-features = false }
pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false }
pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ impl frame_system::Config for Runtime {
/// The action to take on a Runtime Upgrade
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
type MaxConsumers = frame_support::traits::ConstU32<16>;
type MultiBlockMigrator = pallet_migrations::Pallet<Runtime>;
}

impl pallet_timestamp::Config for Runtime {
Expand Down Expand Up @@ -503,6 +504,21 @@ impl pallet_utility::Config for Runtime {
type WeightInfo = weights::pallet_utility::WeightInfo<Runtime>;
}

parameter_types! {
pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block;
}

impl pallet_migrations::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Migrations = ();
type CursorMaxLen = ConstU32<65_536>;
type IdentifierMaxLen = ConstU32<256>;
type MigrationStatusHandler = ();
type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration;
type MaxServiceWeight = MbmServiceWeight;
type WeightInfo = pallet_migrations::weights::SubstrateWeight<Runtime>;
}

// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime
Expand All @@ -512,6 +528,7 @@ construct_runtime!(
ParachainSystem: cumulus_pallet_parachain_system = 1,
Timestamp: pallet_timestamp = 2,
ParachainInfo: parachain_info = 3,
MultiBlockMigrations: pallet_migrations = 4,

// Monetary stuff.
Balances: pallet_balances = 10,
Expand Down

0 comments on commit 3b4980d

Please sign in to comment.