[doc] Example MBM pallet (#2119)

## Basic example showcasing a migration using the MBM framework

This PR has been built on top of
https://github.com/paritytech/polkadot-sdk/pull/1781 and adds two new
example crates to the `examples` pallet

### Changes Made:

Added the `pallet-example-mbm` crate: This crate provides a minimal
example of a pallet that uses MBM. It showcases a storage migration
where values are migrated from a `u32` to a `u64`.

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
Juan Girini
2024-04-04 13:47:24 +02:00
committed by GitHub
parent 0ef37c7540
commit bcb4d137c9
17 changed files with 686 additions and 11 deletions
+46 -4
View File
@@ -276,9 +276,10 @@ pub mod pallet {
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pallet::config]
#[pallet::config(with_default)]
pub trait Config: frame_system::Config {
/// The overarching event type of the runtime.
#[pallet::no_default_bounds]
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// All the multi-block migrations to run.
@@ -286,12 +287,14 @@ pub mod pallet {
/// Should only be updated in a runtime-upgrade once all the old migrations have completed.
/// (Check that [`Cursor`] is `None`).
#[cfg(not(feature = "runtime-benchmarks"))]
#[pallet::no_default]
type Migrations: SteppedMigrations;
/// Mocked migrations for benchmarking only.
///
/// Should be configured to [`crate::mock_helpers::MockedMigrations`] in benchmarks.
#[cfg(feature = "runtime-benchmarks")]
#[pallet::no_default]
type Migrations: MockedMigrations;
/// The maximal length of an encoded cursor.
@@ -323,6 +326,45 @@ pub mod pallet {
type WeightInfo: WeightInfo;
}
/// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`].
pub mod config_preludes {
use super::{inject_runtime_type, DefaultConfig};
use frame_support::{
derive_impl,
migrations::FreezeChainOnFailedMigration,
pallet_prelude::{ConstU32, *},
};
use frame_system::limits::BlockWeights;
/// Provides a viable default config that can be used with
/// [`derive_impl`](`frame_support::derive_impl`) to derive a testing pallet config
/// based on this one.
///
/// See `Test` in the `default-config` example pallet's `test.rs` for an example of
/// a downstream user of this particular `TestDefaultConfig`
pub struct TestDefaultConfig;
frame_support::parameter_types! {
/// Maximal weight per block that can be spent on migrations in tests.
pub TestMaxServiceWeight: Weight = <<TestDefaultConfig as frame_system::DefaultConfig>::BlockWeights as Get<BlockWeights>>::get().max_block.div(2);
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
impl frame_system::DefaultConfig for TestDefaultConfig {}
#[frame_support::register_default_impl(TestDefaultConfig)]
impl DefaultConfig for TestDefaultConfig {
#[inject_runtime_type]
type RuntimeEvent = ();
type CursorMaxLen = ConstU32<{ 1 << 16 }>;
type IdentifierMaxLen = ConstU32<{ 256 }>;
type MigrationStatusHandler = ();
type FailedMigrationHandler = FreezeChainOnFailedMigration;
type MaxServiceWeight = TestMaxServiceWeight;
type WeightInfo = ();
}
}
/// The currently active migration to run and its cursor.
///
/// `None` indicates that no migration is running.
@@ -421,12 +463,11 @@ pub mod pallet {
}
// The per-block service weight is sane.
#[cfg(not(test))]
{
let want = T::MaxServiceWeight::get();
let max = <T as frame_system::Config>::BlockWeights::get().max_block;
assert!(want.all_lte(max), "Service weight is larger than a block: {want} > {max}",);
assert!(want.all_lte(max), "Service weight is larger than a block: {want} > {max}");
}
// Cursor MEL
@@ -726,7 +767,8 @@ impl<T: Config> Pallet<T> {
}
}
fn exec_migration_max_weight() -> Weight {
/// The maximal weight of calling the private `Self::exec_migration` function.
pub fn exec_migration_max_weight() -> Weight {
T::WeightInfo::exec_migration_complete()
.max(T::WeightInfo::exec_migration_completed())
.max(T::WeightInfo::exec_migration_skipped_historic())
+5 -6
View File
@@ -28,7 +28,7 @@ use frame_support::{
weights::Weight,
};
use frame_system::EventRecord;
use sp_core::{ConstU32, H256};
use sp_core::H256;
type Block = frame_system::mocking::MockBlock<Test>;
@@ -51,15 +51,14 @@ frame_support::parameter_types! {
pub const MaxServiceWeight: Weight = Weight::MAX.div(10);
}
#[derive_impl(crate::config_preludes::TestDefaultConfig)]
impl crate::Config for Test {
type RuntimeEvent = RuntimeEvent;
#[cfg(feature = "runtime-benchmarks")]
type Migrations = crate::mock_helpers::MockedMigrations;
#[cfg(not(feature = "runtime-benchmarks"))]
type Migrations = MockedMigrations;
type CursorMaxLen = ConstU32<65_536>;
type IdentifierMaxLen = ConstU32<256>;
type MigrationStatusHandler = MockedMigrationStatusHandler;
type FailedMigrationHandler = MockedFailedMigrationHandler;
type MaxServiceWeight = MaxServiceWeight;
type WeightInfo = ();
}
frame_support::parameter_types! {
@@ -79,7 +79,7 @@ impl SteppedMigrations for MockedMigrations {
let mut count: u32 =
cursor.as_ref().and_then(|c| Decode::decode(&mut &c[..]).ok()).unwrap_or(0);
log::debug!("MockedMigration: Step {}", count);
log::debug!("MockedMigration: Step {count} vs max {steps}");
if count != steps || matches!(kind, TimeoutAfter) {
count += 1;
return Some(Ok(Some(count.encode())))