Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[doc] Example MBM pallet #2119

Merged
merged 24 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -331,6 +331,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`
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
//!
//! 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
Loading