Skip to content

Commit

Permalink
[doc] Example MBM pallet (#2119)
Browse files Browse the repository at this point in the history
## Basic example showcasing a migration using the MBM framework

This PR has been built on top of
#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 <[email protected]>
Co-authored-by: Oliver Tale-Yazdi <[email protected]>
Co-authored-by: Liam Aharon <[email protected]>
  • Loading branch information
3 people authored and Ank4n committed Apr 9, 2024
1 parent 63064e6 commit 2f49bf6
Show file tree
Hide file tree
Showing 17 changed files with 686 additions and 11 deletions.
15 changes: 15 additions & 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ members = [
"substrate/frame/examples/dev-mode",
"substrate/frame/examples/frame-crate",
"substrate/frame/examples/kitchensink",
"substrate/frame/examples/multi-block-migrations",
"substrate/frame/examples/offchain-worker",
"substrate/frame/examples/single-block-migrations",
"substrate/frame/examples/split",
Expand Down
16 changes: 16 additions & 0 deletions prdoc/pr_2119.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title: "Add example pallet for Multi-Block-Migrations"

doc:
- audience: Runtime Dev
description: |
- Add an example pallet to demonstrate Multi-Block-Migrations.
- Add a `MigrationId` to frame-support for more convenient identification or migrations.
- Add default config prelude for testing in pallet-migrations.

crates:
- name: frame-support
bump: minor
- name: pallet-migrations
bump: minor
- name: kitchensink-runtime
bump: patch
4 changes: 4 additions & 0 deletions substrate/bin/node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", defaul
pallet-example-tasks = { path = "../../../frame/examples/tasks", default-features = false }
pallet-fast-unstake = { path = "../../../frame/fast-unstake", default-features = false }
pallet-migrations = { path = "../../../frame/migrations", default-features = false }
pallet-example-mbm = { path = "../../../frame/examples/multi-block-migrations", default-features = false }
pallet-nis = { path = "../../../frame/nis", default-features = false }
pallet-grandpa = { path = "../../../frame/grandpa", default-features = false }
pallet-im-online = { path = "../../../frame/im-online", default-features = false }
Expand Down Expand Up @@ -188,6 +189,7 @@ std = [
"pallet-election-provider-multi-phase/std",
"pallet-election-provider-support-benchmarking?/std",
"pallet-elections-phragmen/std",
"pallet-example-mbm/std",
"pallet-example-tasks/std",
"pallet-fast-unstake/std",
"pallet-glutton/std",
Expand Down Expand Up @@ -294,6 +296,7 @@ runtime-benchmarks = [
"pallet-election-provider-multi-phase/runtime-benchmarks",
"pallet-election-provider-support-benchmarking/runtime-benchmarks",
"pallet-elections-phragmen/runtime-benchmarks",
"pallet-example-mbm/runtime-benchmarks",
"pallet-example-tasks/runtime-benchmarks",
"pallet-fast-unstake/runtime-benchmarks",
"pallet-glutton/runtime-benchmarks",
Expand Down Expand Up @@ -373,6 +376,7 @@ try-runtime = [
"pallet-democracy/try-runtime",
"pallet-election-provider-multi-phase/try-runtime",
"pallet-elections-phragmen/try-runtime",
"pallet-example-mbm/try-runtime",
"pallet-example-tasks/try-runtime",
"pallet-fast-unstake/try-runtime",
"pallet-glutton/try-runtime",
Expand Down
6 changes: 6 additions & 0 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ impl pallet_example_tasks::Config for Runtime {
type WeightInfo = pallet_example_tasks::weights::SubstrateWeight<Runtime>;
}

impl pallet_example_mbm::Config for Runtime {}

impl pallet_utility::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
Expand Down Expand Up @@ -2439,6 +2441,9 @@ mod runtime {

#[runtime::pallet_index(77)]
pub type SkipFeelessPayment = pallet_skip_feeless_payment;

#[runtime::pallet_index(78)]
pub type PalletExampleMbms = pallet_example_mbm;
}

/// The address format for describing accounts.
Expand Down Expand Up @@ -2597,6 +2602,7 @@ mod benches {
[pallet_whitelist, Whitelist]
[pallet_tx_pause, TxPause]
[pallet_safe_mode, SafeMode]
[pallet_example_mbm, PalletExampleMbms]
);
}

Expand Down
47 changes: 47 additions & 0 deletions substrate/frame/examples/multi-block-migrations/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[package]
name = "pallet-example-mbm"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage = "https://substrate.io"
repository.workspace = true
description = "Example FRAME pallet for multi-block migrations"
publish = false

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.5", default-features = false }
pallet-migrations = { path = "../../migrations", default-features = false }
frame-support = { path = "../../support", default-features = false }
frame-system = { path = "../../system", default-features = false }
frame-benchmarking = { path = "../../benchmarking", default-features = false, optional = true }
log = { version = "0.4.20", default-features = false }
scale-info = { version = "2.10.0", default-features = false }
sp-io = { path = "../../../primitives/io", default-features = false }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-migrations/std",
"scale-info/std",
"sp-io/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-migrations/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-migrations/try-runtime",
]
87 changes: 87 additions & 0 deletions substrate/frame/examples/multi-block-migrations/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(not(feature = "std"), no_std)]

//! # Multi-Block Migrations Example Pallet
//!
//! This pallet serves as a minimal example of a pallet that uses the [Multi-Block Migrations
//! Framework](frame_support::migrations). You can observe how to configure it in a runtime in the
//! `kitchensink-runtime` crate.
//!
//! ## Introduction and Purpose
//!
//! The primary purpose of this pallet is to demonstrate the concept of Multi-Block Migrations in
//! Substrate. It showcases the migration of values from in the
//! [`MyMap`](`pallet::MyMap`) storage map a `u32` to a `u64` data type using the
//! [`SteppedMigration`](`frame_support::migrations::SteppedMigration`) implementation from the
//! [`migrations::v1`] module.
//!
//! The [`MyMap`](`pallet::MyMap`) storage item is defined in this `pallet`, and is
//! aliased to [`v0::MyMap`](`migrations::v1::v0::MyMap`) in the [`migrations::v1`]
//! module.
//!
//! ## How to Read the Documentation
//!
//! To access and navigate this documentation in your browser, use the following command:
//!
//! - `cargo doc --package pallet-example-mbm --open`
//!
//! This documentation is organized to help you understand the pallet's components, features, and
//! migration process.
//!
//! ## Example Usage
//!
//! To use this pallet and understand multi-block migrations, you can refer to the
//! [`migrations::v1`] module, which contains a step-by-step migration example.
//!
//! ## Pallet Structure
//!
//! The pallet is structured as follows:
//!
//! - [`migrations`]: Contains migration-related modules and migration logic.
//! - [`v1`](`migrations::v1`): Demonstrates the migration process for changing the data type in
//! the storage map.
//! - [`pallet`]: Defines the pallet configuration and storage items.
//!
//! ## Migration Safety
//!
//! When working with migrations, it's crucial to ensure the safety of your migrations. The
//! preferred tool to test migrations is
//! [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli). Support will be added to
//! dry-run MBMs once they are stable
//! (tracked: <https://github.com/paritytech/try-runtime-cli/issues/17>).

pub mod migrations;
mod mock;

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use frame_support::{pallet_prelude::StorageMap, Blake2_128Concat};

#[pallet::pallet]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config {}

/// Define a storage item to illustrate multi-block migrations.
#[pallet::storage]
pub type MyMap<T: Config> = StorageMap<_, Blake2_128Concat, u32, u64>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// # Multi-Block Migrations Module
///
/// This module showcases a simple use of the multi-block migrations framework.
pub mod v1;

/// A unique identifier across all pallets.
///
/// This constant represents a unique identifier for the migrations of this pallet.
/// It helps differentiate migrations for this pallet from those of others. Note that we don't
/// directly pull the crate name from the environment, since that would change if the crate were
/// ever to be renamed and could cause historic migrations to run again.
pub const PALLET_MIGRATIONS_ID: &[u8; 18] = b"pallet-example-mbm";
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Benchmark the multi-block-migration.

#![cfg(feature = "runtime-benchmarks")]

use crate::{
migrations::{
v1,
v1::{weights, weights::WeightInfo},
},
Config, Pallet,
};
use frame_benchmarking::v2::*;
use frame_support::{migrations::SteppedMigration, weights::WeightMeter};

#[benchmarks]
mod benches {
use super::*;

/// Benchmark a single step of the `v1::LazyMigrationV1` migration.
#[benchmark]
fn step() {
v1::v0::MyMap::<T>::insert(0, 0);
let mut meter = WeightMeter::new();

#[block]
{
v1::LazyMigrationV1::<T, weights::SubstrateWeight<T>>::step(None, &mut meter).unwrap();
}

// Check that the new storage is decodable:
assert_eq!(crate::MyMap::<T>::get(0), Some(0));
// uses twice the weight once for migration and then for checking if there is another key.
assert_eq!(meter.consumed(), weights::SubstrateWeight::<T>::step() * 2);
}

impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime);
}
Loading

0 comments on commit 2f49bf6

Please sign in to comment.