Skip to content

Multi-Block-Migrations, poll hook and new System callbacks#1781

Merged
ggwpez merged 136 commits intomasterfrom
oty-after-inherents
Feb 28, 2024
Merged

Multi-Block-Migrations, poll hook and new System callbacks#1781
ggwpez merged 136 commits intomasterfrom
oty-after-inherents

Conversation

@ggwpez
Copy link
Copy Markdown
Member

@ggwpez ggwpez commented Oct 3, 2023

🚨 BUG alert: Please ensure to apply this patch when you want to integrate this feature: #5695 🚨


This MR is the merge of paritytech/substrate#14414 and paritytech/substrate#14275. It implements RFC#13, closes #198.

It introduces three major topicals:

  1. Multi-Block-Migrations
  2. New pallet poll hook for periodic service work
  3. Replacement hooks for on_initialize and on_finalize in cases where poll cannot be used

and some more general changes to FRAME.
The changes for each topical span over multiple crates. They are listed in topical order below.

1.) Multi-Block-Migrations

Multi-Block-Migrations are facilitated by creating pallet_migrations and configuring System::Config::MultiBlockMigrator to point to it. Executive picks this up and triggers one step of the migrations pallet per block.
The chain is in lockdown mode for as long as an MBM is ongoing. Executive does this by polling MultiBlockMigrator::ongoing and not allowing any transaction in a block, if true.

A MBM is defined through trait SteppedMigration. A condensed version looks like this:

/// A migration that can proceed in multiple steps.
pub trait SteppedMigration {
	type Cursor: FullCodec + MaxEncodedLen;
	type Identifier: FullCodec + MaxEncodedLen;

	fn id() -> Self::Identifier;

	fn max_steps() -> Option<u32>;

	fn step(
		cursor: Option<Self::Cursor>,
		meter: &mut WeightMeter,
	) -> Result<Option<Self::Cursor>, SteppedMigrationError>;
}

pallet_migrations can be configured with an aggregated tuple of these migrations. It then starts to migrate them one-by-one on the next runtime upgrade.
Two things are important here:

    1. Doing another runtime upgrade while MBMs are ongoing is not a good idea and can lead to messed up state.
    1. Pallet Migrations MUST BE CONFIGURED IN System::Config, otherwise it is not used.

The pallet supports an UpgradeStatusHandler that can be used to notify external logic of upgrade start/finish (for example to pause XCM dispatch).

Error recovery is very limited in the case that a migration errors or times out (exceeds its max_steps). Currently the runtime dev can decide in FailedMigrationHandler::failed how to handle this. One follow-up would be to pair this with the SafeMode pallet and enact safe mode when an upgrade fails, to allow governance to rescue the chain. This is currently not possible, since governance is not Mandatory.

Runtime API

  • Core: initialize_block now returns ExtrinsicInclusionMode to inform the Block Author whether they can push transactions.

Integration

Add it to your runtime implementation of Core and BlockBuilder:

diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
@@ impl_runtime_apis! {
	impl sp_block_builder::Core<Block> for Runtime {
-		fn initialize_block(header: &<Block as BlockT>::Header) {
+		fn initialize_block(header: &<Block as BlockT>::Header) -> ExtrinsicInclusionMode {
			Executive::initialize_block(header)
		}

		...
	}

2.) poll hook

A new pallet hook is introduced: poll. Poll is intended to replace mostly all usage of on_initialize.
The reason for this is that any code that can be called from on_initialize cannot be migrated through an MBM. Currently there is no way to statically check this; the implication is to use on_initialize as rarely as possible.
Failing to do so can result in broken storage invariants.

The implementation of the poll hook depends on the Runtime API changes that are explained above.

3.) Hard-Deadline callbacks

Three new callbacks are introduced and configured on System::Config: PreInherents, PostInherents and PostTransactions.
These hooks are meant as replacement for on_initialize and on_finalize in cases where the code that runs cannot be moved to poll.
The reason for this is to make the usage of HD-code (hard deadline) more explicit - again to prevent broken invariants by MBMs.

4.) FRAME (general changes)

frame_system pallet

A new memorize storage item InherentsApplied is added. It is used by executive to track whether inherents have already been applied. Executive and can then execute the MBMs directly between inherents and transactions.

The Config gets five new items:

  • SingleBlockMigrations this is the new way of configuring migrations that run in a single block. Previously they were defined as last generic argument of Executive. This shift is brings all central configuration about migrations closer into view of the developer (migrations that are configured in Executive will still work for now but is deprecated).
  • MultiBlockMigrator this can be configured to an engine that drives MBMs. One example would be the pallet_migrations. Note that this is only the engine; the exact MBMs are injected into the engine.
  • PreInherents a callback that executes after on_initialize but before inherents.
  • PostInherents a callback that executes after all inherents ran (including MBMs and poll).
  • PostTransactions in symmetry to PreInherents, this one is called before on_finalize but after all transactions.

A sane default is to set all of these to (). Example diff suitable for any chain:

@@ impl frame_system::Config for Test {
 	type MaxConsumers = ConstU32<16>;
+	type SingleBlockMigrations = ();
+	type MultiBlockMigrator = ();
+	type PreInherents = ();
+	type PostInherents = ();
+	type PostTransactions = ();
 }

An overview of how the block execution now looks like is here. The same graph is also in the rust doc.

Screenshot 2023-12-04 at 19 11 29

Inherent Order

Moved to #2154


TODO

  • Check that try-runtime still works
  • Ensure backwards compatibility with old Runtime APIs
  • Consume weight correctly
  • Cleanup

ggwpez added 5 commits October 3, 2023 12:11
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
@ggwpez ggwpez changed the title Add after_inherents hook Simple Multi-Block-Migrations Oct 4, 2023
@ggwpez ggwpez added the T1-FRAME This PR/Issue is related to core FRAME, the framework. label Oct 4, 2023
ggwpez added 5 commits October 4, 2023 15:45
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
@ggwpez ggwpez marked this pull request as ready for review October 5, 2023 20:46
@ggwpez ggwpez requested review from a team October 5, 2023 20:46
@paritytech-ci paritytech-ci requested review from a team October 5, 2023 20:48
Copy link
Copy Markdown
Contributor

@liamaharon liamaharon left a comment

Choose a reason for hiding this comment

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

Really great pallet docs 👌

Just a few small comments

Comment thread substrate/bin/node/runtime/Cargo.toml Outdated
Comment thread substrate/bin/node/runtime/Cargo.toml Outdated
Comment thread substrate/bin/node/runtime/src/lib.rs
Comment thread substrate/frame/executive/src/lib.rs Outdated
Comment thread substrate/frame/executive/src/tests.rs Outdated
Comment thread substrate/frame/migrations/src/tests.rs Outdated
Comment thread substrate/frame/migrations/src/tests.rs Outdated
Comment thread substrate/frame/support/src/migrations.rs Outdated
Comment thread substrate/frame/support/src/migrations.rs Outdated
Comment thread substrate/frame/support/src/migrations.rs Outdated
@liamaharon
Copy link
Copy Markdown
Contributor

Executive now additionally takes an MultiStepMigrator trait that defaults to ().
IT IS PARAMOUNT TO SET THIS TO THE MIGRATIONS PALLET WHEN YOU DEPLOY IT.

Can we enforce this somehow?

@ggwpez
Copy link
Copy Markdown
Member Author

ggwpez commented Oct 6, 2023

Executive now additionally takes an MultiStepMigrator trait that defaults to ().
IT IS PARAMOUNT TO SET THIS TO THE MIGRATIONS PALLET WHEN YOU DEPLOY IT.

Can we enforce this somehow?

I think so. I will try to add a check into the integrity_test, otherwise this is a huge footgun.

@ggwpez ggwpez changed the title Simple Multi-Block-Migrations Multi-Block-Migrations, poll hook and new System callbacks Oct 24, 2023
@ggwpez ggwpez marked this pull request as draft October 24, 2023 15:59
Comment thread substrate/frame/migrations/src/weights.rs
Comment thread substrate/frame/migrations/src/lib.rs Outdated
Comment thread substrate/frame/migrations/src/lib.rs Outdated
Comment thread substrate/frame/migrations/src/lib.rs Outdated
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
enddynayn added a commit to frequency-chain/frequency that referenced this pull request Jul 26, 2024
- Upgrade Polkadot-sdk to v.1.8.0.
- Update weights to reflect the new version.

Notable Changes:
- [System Callabacks](paritytech/polkadot-sdk#1781)
- [Remove of pallet pallet::getter](paritytech/polkadot-sdk#3456)
- [Add storage_proof_size host function](paritytech/polkadot-sdk#3002)

For more details, please refer to:

[Release
Notes](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.9.0)
enddynayn added a commit to frequency-chain/frequency that referenced this pull request Jul 26, 2024
- Upgrade Polkadot-sdk to v.1.8.0.
- Update weights to reflect the new version.

Notable Changes:
- [System Callabacks](paritytech/polkadot-sdk#1781)
- [Remove of pallet pallet::getter](paritytech/polkadot-sdk#3456)
- [Add storage_proof_size host function](paritytech/polkadot-sdk#3002)
- [Rename of storage version function](https://github.com/paritytech/polkadot-sdk/pull/1554/files#diff-01dc4f43df9baa537f30c6b369525715d596a3068944f38458e9f160d5412d58R306)

For more details, please refer to:

[Release
Notes](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.9.0)
enddynayn added a commit to frequency-chain/frequency that referenced this pull request Jul 26, 2024
- Upgrade Polkadot-sdk to v.1.9.0.
- Update weights to reflect the new version.

Notable Changes:
- [System Callabacks](paritytech/polkadot-sdk#1781)
- [Remove of pallet pallet::getter](paritytech/polkadot-sdk#3456)
- [Add storage_proof_size host function](paritytech/polkadot-sdk#3002)
- [Rename of storage version function](https://github.com/paritytech/polkadot-sdk/pull/1554/files#diff-01dc4f43df9baa537f30c6b369525715d596a3068944f38458e9f160d5412d58R306)

For more details, please refer to:

[Release
Notes](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.9.0)
enddynayn added a commit to frequency-chain/frequency that referenced this pull request Jul 26, 2024
- Upgrade Polkadot-sdk to v.1.9.0.
- Update weights to reflect the new version.

Notable Changes:
- [System
Callbacks](paritytech/polkadot-sdk#1781)
- [Remove of pallet
pallet::getter](paritytech/polkadot-sdk#3456)
- [Add storage_proof_size host
function](paritytech/polkadot-sdk#3002)
- [Rename of storage version
function](https://github.com/paritytech/polkadot-sdk/pull/1554/files#diff-01dc4f43df9baa537f30c6b369525715d596a3068944f38458e9f160d5412d58R306)

For more details, please refer to:

[Release
Notes](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.9.0)
enddynayn added a commit to frequency-chain/frequency that referenced this pull request Jul 26, 2024
- Update weights to reflect the new version.

Notable Changes:
- [System Callbacks](paritytech/polkadot-sdk#1781)

For more details, please refer to:

[Release Notes](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.10.0)

issue-1922
enddynayn added a commit to frequency-chain/frequency that referenced this pull request Jul 30, 2024
rustadot pushed a commit to rustadot/recurrency that referenced this pull request Sep 5, 2024
- Upgrade Polkadot-sdk to v.1.9.0.
- Update weights to reflect the new version.

Notable Changes:
- [System
Callbacks](paritytech/polkadot-sdk#1781)
- [Remove of pallet
pallet::getter](paritytech/polkadot-sdk#3456)
- [Add storage_proof_size host
function](paritytech/polkadot-sdk#3002)
- [Rename of storage version
function](https://github.com/paritytech/polkadot-sdk/pull/1554/files#diff-01dc4f43df9baa537f30c6b369525715d596a3068944f38458e9f160d5412d58R306)

For more details, please refer to:

[Release
Notes](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.9.0)
@ggwpez
Copy link
Copy Markdown
Member Author

ggwpez commented Sep 24, 2024

There was a bug found and fixed in the original version of this: #5695

aurexav added a commit to darwinia-network/darwinia that referenced this pull request Dec 18, 2024
github-merge-queue bot pushed a commit that referenced this pull request Sep 2, 2025
…e_upgrade (#9451)

Recently, when moving the single block migrations from
`frame_executive::Executive` to `SingleBlockMigrations` in
`frame_system::Config`, I noticed that `try_runtime_upgrade` was
ignoring the `SingleBlockMigrations` defined in frame_system. More
context at polkadot-fellows/runtimes#844

Based on PR #1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but from what I
understood is or will be deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

## Follow-up Changes
Will try to open a pull request tomorrow for deprecating the use of
`OnRuntimeUpgrade` in `frame_executive::Executive`.
paritytech-release-backport-bot bot pushed a commit that referenced this pull request Sep 2, 2025
…e_upgrade (#9451)

Recently, when moving the single block migrations from
`frame_executive::Executive` to `SingleBlockMigrations` in
`frame_system::Config`, I noticed that `try_runtime_upgrade` was
ignoring the `SingleBlockMigrations` defined in frame_system. More
context at polkadot-fellows/runtimes#844

Based on PR #1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but from what I
understood is or will be deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

## Follow-up Changes
Will try to open a pull request tomorrow for deprecating the use of
`OnRuntimeUpgrade` in `frame_executive::Executive`.

(cherry picked from commit 7753112)
paritytech-release-backport-bot bot pushed a commit that referenced this pull request Sep 2, 2025
…e_upgrade (#9451)

Recently, when moving the single block migrations from
`frame_executive::Executive` to `SingleBlockMigrations` in
`frame_system::Config`, I noticed that `try_runtime_upgrade` was
ignoring the `SingleBlockMigrations` defined in frame_system. More
context at polkadot-fellows/runtimes#844

Based on PR #1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but from what I
understood is or will be deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

## Follow-up Changes
Will try to open a pull request tomorrow for deprecating the use of
`OnRuntimeUpgrade` in `frame_executive::Executive`.

(cherry picked from commit 7753112)
github-merge-queue bot pushed a commit that referenced this pull request Sep 12, 2025
#9638)

Follow-up of #9451

Based on PR #1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but is deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

`Executive` docs will look like:

<img width="800" alt="image"
src="https://github.com/user-attachments/assets/6f285c26-5c61-4350-a41b-aebc6b856601"
/>

Companion PR in polkadot-fellows/runtimes#844
bkchr pushed a commit to polkadot-fellows/runtimes that referenced this pull request Oct 12, 2025
…nfig (#844)

**Depends on** paritytech/polkadot-sdk#9451
---

Based on PR paritytech/polkadot-sdk#1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but from what I
understood is or will be deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

Will also open a PR on polkadot-sdk side, adding a deprecation warning.
alvicsam pushed a commit that referenced this pull request Oct 17, 2025
…e_upgrade (#9451)

Recently, when moving the single block migrations from
`frame_executive::Executive` to `SingleBlockMigrations` in
`frame_system::Config`, I noticed that `try_runtime_upgrade` was
ignoring the `SingleBlockMigrations` defined in frame_system. More
context at polkadot-fellows/runtimes#844

Based on PR #1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but from what I
understood is or will be deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

## Follow-up Changes
Will try to open a pull request tomorrow for deprecating the use of
`OnRuntimeUpgrade` in `frame_executive::Executive`.
alvicsam pushed a commit that referenced this pull request Oct 17, 2025
#9638)

Follow-up of #9451

Based on PR #1781 and
[PRDoc](https://github.com/paritytech/polkadot-sdk/blob/beb9030b249cc078b3955232074a8495e7e0302a/prdoc/1.9.0/pr_1781.prdoc#L29),
the new way for providing the single block migrations should be through
`SingleBlockMigrations` in `frame_system::Config`. Providing them from
`frame_executive::Executive` is still supported, but is deprecated.

> `SingleBlockMigrations` this is the new way of configuring migrations
that run in a single block. Previously they were defined as last generic
argument of Executive. This shift is brings all central configuration
about migrations closer into view of the developer (migrations that are
configured in Executive will still work for now but is deprecated).

`Executive` docs will look like:

<img width="800" alt="image"
src="https://github.com/user-attachments/assets/6f285c26-5c61-4350-a41b-aebc6b856601"
/>

Companion PR in polkadot-fellows/runtimes#844
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T1-FRAME This PR/Issue is related to core FRAME, the framework.

Projects

Status: Audited

Development

Successfully merging this pull request may close these issues.

[FRAME Core] Simple Multi-block Migrations