Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

[FRAME] Simple multi block migrations #14275

Draft
wants to merge 66 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
dc35acf
Add stepped migrations and pallet
ggwpez May 30, 2023
283d51c
Cleanup
ggwpez May 30, 2023
7c53a74
Comment
ggwpez May 30, 2023
edb005c
Suspension and benches
ggwpez May 31, 2023
8331fbe
Add generic to Executive
ggwpez May 31, 2023
c23259f
Cleanup
ggwpez May 31, 2023
9ffd3d7
Merge remote-tracking branch 'origin/master' into oty-multi-step-migr…
ggwpez May 31, 2023
3afdf0a
Add Executed
ggwpez May 31, 2023
104fd6d
Add events
ggwpez May 31, 2023
1e18cae
Fixes
ggwpez May 31, 2023
7ab621a
Make cursor generic
ggwpez Jun 1, 2023
acd99bb
Fix kitchensink
ggwpez Jun 1, 2023
d217589
Add testing
ggwpez Jun 1, 2023
3351a54
Tests
ggwpez Jun 1, 2023
4eeb47e
Use default configs for System
ggwpez Jun 1, 2023
80922c9
Tests
ggwpez Jun 1, 2023
4ae8fbf
Fixes
ggwpez Jun 1, 2023
e6beda5
Add status handling
ggwpez Jun 2, 2023
fa20468
Refactor
ggwpez Jun 2, 2023
ad98b43
Fixes
ggwpez Jun 2, 2023
5c3a90d
Clippy
ggwpez Jun 2, 2023
357fa47
Update frame/support/src/migrations.rs
ggwpez Jun 2, 2023
da04876
Update frame/migrations/src/mock.rs
ggwpez Jun 2, 2023
2e86915
Update frame/migrations/src/tests.rs
ggwpez Jun 2, 2023
99691a3
fmt
ggwpez Jun 2, 2023
e44c902
Add timeout checking
ggwpez Jun 3, 2023
5f512e6
Fix stuff
ggwpez Jun 5, 2023
c72c7b7
Add docs
ggwpez Jun 5, 2023
790914d
Fix docs and kitchensink
ggwpez Jun 5, 2023
642d65a
Format Cargo.toml
ggwpez Jun 5, 2023
a2b3194
Docs
ggwpez Jun 5, 2023
60c1322
Now it sounds like English 😂
ggwpez Jun 11, 2023
17be927
Fix test
ggwpez Jun 11, 2023
741c476
fmt
ggwpez Jun 11, 2023
6a1438e
Benches still WIP
ggwpez Jun 11, 2023
0e4f8a6
Move code
ggwpez Jun 13, 2023
97b58e1
Docs review fixes
ggwpez Jun 13, 2023
87ac850
Add tests
ggwpez Jun 13, 2023
b8c8559
Rename to OnMigrationUpdate
ggwpez Jun 13, 2023
3b27c4f
Fix bugs
ggwpez Jun 14, 2023
07f6889
More fixes
ggwpez Jun 14, 2023
f202a80
Fixes
ggwpez Jun 14, 2023
1249955
Undo changes to frame-executive
ggwpez Jun 14, 2023
717b30e
Fix executive
ggwpez Jun 14, 2023
c7e8384
Fix
ggwpez Jun 14, 2023
a1589a3
Fix docs
ggwpez Jun 15, 2023
4fd5d93
Add log target to sc-basic-authorship
ggwpez Jun 15, 2023
e75d0c1
Merge remote-tracking branch 'origin/master' into oty-multi-step-migr…
ggwpez Jun 15, 2023
37cf9b8
Add mock_helpers
ggwpez Jun 15, 2023
69fddc3
Add progress_mbms to BlockBuilder
ggwpez Jun 15, 2023
7435788
Add log target
ggwpez Jun 16, 2023
6b1d6b1
Factor out apply_inherents
ggwpez Jun 16, 2023
0b7dddc
Factor out apply_extrinsics
ggwpez Jun 16, 2023
648e005
Factor out print_summary
ggwpez Jun 16, 2023
24c8bf6
Pimp print_summary
ggwpez Jun 16, 2023
4b99c6e
Cleanup
ggwpez Jun 16, 2023
93f0d32
Fixes
ggwpez Jun 16, 2023
c57bbf5
Backup
ggwpez Jun 16, 2023
30c302e
Merge branch 'oty-refactor-block-builder' into oty-multi-step-migration
ggwpez Jun 16, 2023
4101e82
Fix stuff
ggwpez Jun 16, 2023
8f7bda1
Works
ggwpez Jun 16, 2023
e430d57
Fix template
ggwpez Jun 17, 2023
89313b3
Fix test
ggwpez Jun 18, 2023
999b0f0
WIP
ggwpez Jun 27, 2023
f87a8e4
Use impl trait for tuples
bkchr Jun 29, 2023
f3f76b6
Simplify
bkchr Jun 29, 2023
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
27 changes: 22 additions & 5 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 @@ -119,6 +119,7 @@ members = [
"frame/lottery",
"frame/membership",
"frame/merkle-mountain-range",
"frame/migrations",
"frame/multisig",
"frame/nicks",
"frame/node-authorization",
Expand Down
4 changes: 4 additions & 0 deletions bin/node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pallet-identity = { version = "4.0.0-dev", default-features = false, path = "../
pallet-lottery = { version = "4.0.0-dev", default-features = false, path = "../../../frame/lottery" }
pallet-membership = { version = "4.0.0-dev", default-features = false, path = "../../../frame/membership" }
pallet-message-queue = { version = "7.0.0-dev", default-features = false, path = "../../../frame/message-queue" }
pallet-migrations = { version = "1.0.0", default-features = false, path = "../../../frame/migrations" }
pallet-mmr = { version = "4.0.0-dev", default-features = false, path = "../../../frame/merkle-mountain-range" }
pallet-multisig = { version = "4.0.0-dev", default-features = false, path = "../../../frame/multisig" }
pallet-nfts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/nfts" }
Expand Down Expand Up @@ -171,6 +172,7 @@ std = [
"pallet-lottery/std",
"pallet-membership/std",
"pallet-message-queue/std",
"pallet-migrations/std",
"pallet-mmr/std",
"pallet-multisig/std",
"pallet-nomination-pools/std",
Expand Down Expand Up @@ -265,6 +267,7 @@ runtime-benchmarks = [
"pallet-lottery/runtime-benchmarks",
"pallet-membership/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"pallet-migrations/runtime-benchmarks",
"pallet-mmr/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-nomination-pools-benchmarking/runtime-benchmarks",
Expand Down Expand Up @@ -328,6 +331,7 @@ try-runtime = [
"pallet-lottery/try-runtime",
"pallet-membership/try-runtime",
"pallet-message-queue/try-runtime",
"pallet-migrations/try-runtime",
"pallet-mmr/try-runtime",
"pallet-multisig/try-runtime",
"pallet-nomination-pools/try-runtime",
Expand Down
15 changes: 15 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use frame_support::{
construct_runtime,
dispatch::DispatchClass,
instances::{Instance1, Instance2},
migrations::SteppedMigration,
ord_parameter_types,
pallet_prelude::Get,
parameter_types,
Expand Down Expand Up @@ -1855,6 +1856,18 @@ impl pallet_statement::Config for Runtime {
type MaxAllowedBytes = MaxAllowedBytes;
}

parameter_types! {
pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block;
pub const MbmMigrations: Vec<Box<dyn SteppedMigration>> = vec![];
}

impl pallet_migrations::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Migrations = MbmMigrations; // same as ()
type ServiceWeight = MbmServiceWeight;
type WeightInfo = pallet_migrations::weights::SubstrateWeight<Runtime>;
}

construct_runtime!(
pub struct Runtime where
Block = Block,
Expand Down Expand Up @@ -1930,6 +1943,7 @@ construct_runtime!(
MessageQueue: pallet_message_queue,
Pov: frame_benchmarking_pallet_pov,
Statement: pallet_statement,
MultiBlockMigrations: pallet_migrations,
}
);

Expand Down Expand Up @@ -2029,6 +2043,7 @@ mod benches {
[pallet_lottery, Lottery]
[pallet_membership, TechnicalMembership]
[pallet_message_queue, MessageQueue]
[pallet_migrations, MultiBlockMigrations]
[pallet_mmr, Mmr]
[pallet_multisig, Multisig]
[pallet_nomination_pools, NominationPoolsBench::<Runtime>]
Expand Down
2 changes: 2 additions & 0 deletions frame/executive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ sp-core = { version = "21.0.0", default-features = false, path = "../../primitiv
sp-io = { version = "23.0.0", default-features = false, path = "../../primitives/io" }
sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" }
sp-storage = { version = "13.0.0", default-features = false, path = "../../primitives/storage" }
sp-tracing = { version = "10.0.0", default-features = false, path = "../../primitives/tracing" }

[dev-dependencies]
Expand All @@ -47,6 +48,7 @@ std = [
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
"sp-storage/std",
"sp-tracing/std",
]
try-runtime = ["frame-support/try-runtime", "frame-try-runtime/try-runtime", "sp-runtime/try-runtime"]
44 changes: 37 additions & 7 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@

use codec::{Codec, Encode};
use frame_support::{
dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo},
dispatch::{
DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo, WithPostDispatchInfo,
},
pallet_prelude::InvalidTransaction,
traits::{
EnsureInherentsAreFirst, ExecuteBlock, OffchainWorker, OnFinalize, OnIdle, OnInitialize,
Expand All @@ -133,7 +135,7 @@ use sp_runtime::{
ValidateUnsigned, Zero,
},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
ApplyExtrinsicResult, DispatchError,
};
use sp_std::{marker::PhantomData, prelude::*};

Expand Down Expand Up @@ -165,6 +167,7 @@ pub struct Executive<
UnsignedValidator,
AllPalletsWithSystem,
OnRuntimeUpgrade = (),
ExtrinsicSuspender = (),
>(
PhantomData<(
System,
Expand All @@ -173,6 +176,7 @@ pub struct Executive<
UnsignedValidator,
AllPalletsWithSystem,
OnRuntimeUpgrade,
ExtrinsicSuspender,
)>,
);

Expand All @@ -187,9 +191,17 @@ impl<
+ OnFinalize<System::BlockNumber>
+ OffchainWorker<System::BlockNumber>,
COnRuntimeUpgrade: OnRuntimeUpgrade,
ExtrinsicSuspender: frame_support::migrations::ExtrinsicSuspenderQuery,
> ExecuteBlock<Block>
for Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
where
for Executive<
System,
Block,
Context,
UnsignedValidator,
AllPalletsWithSystem,
COnRuntimeUpgrade,
ExtrinsicSuspender,
> where
Block::Extrinsic: Checkable<Context> + Codec,
CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
CallOf<Block::Extrinsic, Context>:
Expand All @@ -205,6 +217,7 @@ where
UnsignedValidator,
AllPalletsWithSystem,
COnRuntimeUpgrade,
ExtrinsicSuspender,
>::execute_block(block);
}
}
Expand Down Expand Up @@ -378,8 +391,17 @@ impl<
+ OnFinalize<System::BlockNumber>
+ OffchainWorker<System::BlockNumber>,
COnRuntimeUpgrade: OnRuntimeUpgrade,
> Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
where
ExtrinsicSuspender: frame_support::migrations::ExtrinsicSuspenderQuery,
>
Executive<
System,
Block,
Context,
UnsignedValidator,
AllPalletsWithSystem,
COnRuntimeUpgrade,
ExtrinsicSuspender,
> where
Block::Extrinsic: Checkable<Context> + Codec,
CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
CallOf<Block::Extrinsic, Context>:
Expand Down Expand Up @@ -564,7 +586,15 @@ where

// Decode parameters and dispatch
let dispatch_info = xt.get_dispatch_info();
let r = Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?;
// Check whether we need to error because extrinsics are paused.
let r = if dispatch_info.class != DispatchClass::Mandatory &&
ExtrinsicSuspender::is_suspended()
{
// no refunds
Err(DispatchError::Suspended.with_weight(dispatch_info.weight))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orthogonal to my other comment but I feel this is wrong: For a non mandatory suspended extrinsic, the extrinsic is not applied but it is noted applied with note_applied_extrinsic and the apply extrinsic is a success.

Instead what we want is to not apply suspended extrinsics.
So I think here it should do an early return of Err(InvalidTransaction::Suspended) then in client basic-authorship in the proposer we should end the proposing when we find a suspended transaction. (because runtime only accept inherents when it is suspending transactions)
Or we do an early return of Err(Exhausted) and the proposer will try MAX_SKIPPED_TRANSACTIONS=8 other transaction and then end the proposing. ( if I read the code correctly )

(Or we go with making the block full in on_initialize or on_post_inherent)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead what we want is to not apply suspended extrinsics.

Yes. This is what i meant above with:

Other discussions yielded that we want a runtime API that polls the MBM state and only include non-mandatory transactions into a block when there is no MBM ongoing. But that is more complicated to implement obviously.

This could also be returned as bool from initialize_block. So the block builder will then know to not include any extrinsics.
Do you think that could work? I think it is better than the approach to first include the extrinsic and then reject it from inside the runtime.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to panic now. The block builder should not be able to include non-mandatory transactions while a MBM is ongoing. And a block will not be importable if it does not respect that.

} else {
Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?
};
ggwpez marked this conversation as resolved.
Show resolved Hide resolved

// Mandatory(inherents) are not allowed to fail.
//
Expand Down
46 changes: 46 additions & 0 deletions frame/migrations/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[package]
name = "pallet-migrations"
version = "1.0.0"
description = "FRAME pallet to execute multi-block migrations."
authors = ["Parity Technologies <admin@parity.io>"]
homepage = "https://substrate.io"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/paritytech/substrate"

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

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }

frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
impl-trait-for-tuples = "0.2.2"
log = "0.4.18"
sp-std = { version = "8.0.0", path = "../../primitives/std", default-features = false }
sp-runtime = { version = "24.0.0", path = "../../primitives/runtime", default-features = false }

[dev-dependencies]
sp-tracing = { version = "10.0.0", path = "../../primitives/tracing", features = [ "std" ] }
sp-core = { version = "21.0.0", path = "../../primitives/core", features = [ "std" ] }
sp-io = { version = "23.0.0", path = "../../primitives/io", features = [ "std" ] }

[features]
default = ["std"]

std = [
"codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"sp-std/std",
"sp-runtime/std",
]

runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks",]

try-runtime = ["frame-support/try-runtime", "sp-runtime/try-runtime",]
82 changes: 82 additions & 0 deletions frame/migrations/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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(feature = "runtime-benchmarks")]

use super::*;

use frame_benchmarking::v2::*;
use frame_support::migrations::STEPPED_MIGRATION_CURSOR_LEN as CURSOR_LEN;
use frame_system::{Pallet as System, RawOrigin};

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

#[benchmark]
fn on_runtime_upgrade() {
assert!(!Cursor::<T>::exists());

#[block]
{
Pallet::<T>::on_runtime_upgrade();
}
}

#[benchmark]
fn on_init_base() {
assert!(!Cursor::<T>::exists());
System::<T>::set_block_number(1u32.into());

#[block]
{
Pallet::<T>::on_initialize(1u32.into());
}
}

#[benchmark]
fn on_init_loop_base() {
System::<T>::set_block_number(1u32.into());
Pallet::<T>::on_runtime_upgrade();

#[block]
{
Pallet::<T>::on_initialize(1u32.into());
}
}

/// Benchmarks the slowest path of `change_value`.
#[benchmark]
fn force_set_cursor() {
Cursor::<T>::set(Some(cursor(0)));

#[extrinsic_call]
_(RawOrigin::Root, Some(cursor(1)));
}

fn cursor(i: u32) -> MigrationCursor {
MigrationCursor::Active(
u32::MAX - i,
Some(vec![1u8; CURSOR_LEN as usize].try_into().expect("Static length is good")),
)
}

// Implements a test for each benchmark. Execute with:
// `cargo test -p pallet-migrations --features runtime-benchmarks`.
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
}
Loading