mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 02:57:57 +00:00
Initialise on-chain StorageVersion for pallets added after genesis (#1297)
Original PR https://github.com/paritytech/substrate/pull/14641 --- Closes https://github.com/paritytech/polkadot-sdk/issues/109 ### Problem Quoting from the above issue: > When adding a pallet to chain after genesis we currently don't set the StorageVersion. So, when calling on_chain_storage_version it returns 0 while the pallet is maybe already at storage version 9 when it was added to the chain. This could lead to issues when running migrations. ### Solution - Create a new trait `BeforeAllRuntimeMigrations` with a single method `fn before_all_runtime_migrations() -> Weight` trait with a noop default implementation - Modify `Executive` to call `BeforeAllRuntimeMigrations::before_all_runtime_migrations` for all pallets before running any other hooks - Implement `BeforeAllRuntimeMigrations` in the pallet proc macro to initialize the on-chain version to the current pallet version if the pallet has no storage set (indicating it has been recently added to the runtime and needs to have its version initialised). ### Other changes in this PR - Abstracted repeated boilerplate to access the `pallet_name` in the pallet expand proc macro. ### FAQ #### Why create a new hook instead of adding this logic to the pallet `pre_upgrade`? `Executive` currently runs `COnRuntimeUpgrade` (custom migrations) before `AllPalletsWithSystem` migrations. We need versions to be initialized before the `COnRuntimeUpgrade` migrations are run, because `COnRuntimeUpgrade` migrations may use the on-chain version for critical logic. e.g. `VersionedRuntimeUpgrade` uses it to decide whether or not to execute. We cannot reorder `COnRuntimeUpgrade` and `AllPalletsWithSystem` so `AllPalletsWithSystem` runs first, because `AllPalletsWithSystem` have some logic in their `post_upgrade` hooks to verify that the on-chain version and current pallet version match. A common use case of `COnRuntimeUpgrade` migrations is to perform a migration which will result in the versions matching, so if they were reordered these `post_upgrade` checks would fail. #### Why init the on-chain version for pallets without a current storage version? We must init the on-chain version for pallets even if they don't have a defined storage version so if there is a future version bump, the on-chain version is not automatically set to that new version without a proper migration. e.g. bad scenario: 1. A pallet with no 'current version' is added to the runtime 2. Later, the pallet is upgraded with the 'current version' getting set to 1 and a migration is added to Executive Migrations to migrate the storage from 0 to 1 a. Runtime upgrade occurs b. `before_all` hook initializes the on-chain version to 1 c. `on_runtime_upgrade` of the migration executes, and sees the on-chain version is already 1 therefore think storage is already migrated and does not execute the storage migration Now, on-chain version is 1 but storage is still at version 0. By always initializing the on-chain version when the pallet is added to the runtime we avoid that scenario. --------- Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
@@ -121,8 +121,8 @@ use frame_support::{
|
||||
dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo},
|
||||
pallet_prelude::InvalidTransaction,
|
||||
traits::{
|
||||
EnsureInherentsAreFirst, ExecuteBlock, OffchainWorker, OnFinalize, OnIdle, OnInitialize,
|
||||
OnRuntimeUpgrade,
|
||||
BeforeAllRuntimeMigrations, EnsureInherentsAreFirst, ExecuteBlock, OffchainWorker,
|
||||
OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade,
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
@@ -194,6 +194,7 @@ impl<
|
||||
Context: Default,
|
||||
UnsignedValidator,
|
||||
AllPalletsWithSystem: OnRuntimeUpgrade
|
||||
+ BeforeAllRuntimeMigrations
|
||||
+ OnInitialize<BlockNumberFor<System>>
|
||||
+ OnIdle<BlockNumberFor<System>>
|
||||
+ OnFinalize<BlockNumberFor<System>>
|
||||
@@ -231,6 +232,7 @@ impl<
|
||||
Context: Default,
|
||||
UnsignedValidator,
|
||||
AllPalletsWithSystem: OnRuntimeUpgrade
|
||||
+ BeforeAllRuntimeMigrations
|
||||
+ OnInitialize<BlockNumberFor<System>>
|
||||
+ OnIdle<BlockNumberFor<System>>
|
||||
+ OnFinalize<BlockNumberFor<System>>
|
||||
@@ -364,7 +366,9 @@ where
|
||||
///
|
||||
/// The `checks` param determines whether to execute `pre/post_upgrade` and `try_state` hooks.
|
||||
pub fn try_runtime_upgrade(checks: UpgradeCheckSelect) -> Result<Weight, TryRuntimeError> {
|
||||
let weight =
|
||||
let before_all_weight =
|
||||
<AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
|
||||
let try_on_runtime_upgrade_weight =
|
||||
<(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::try_on_runtime_upgrade(
|
||||
checks.pre_and_post(),
|
||||
)?;
|
||||
@@ -385,7 +389,7 @@ where
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(weight)
|
||||
Ok(before_all_weight.saturating_add(try_on_runtime_upgrade_weight))
|
||||
}
|
||||
|
||||
/// Logs the result of trying to decode the entire state.
|
||||
@@ -429,6 +433,7 @@ impl<
|
||||
Context: Default,
|
||||
UnsignedValidator,
|
||||
AllPalletsWithSystem: OnRuntimeUpgrade
|
||||
+ BeforeAllRuntimeMigrations
|
||||
+ OnInitialize<BlockNumberFor<System>>
|
||||
+ OnIdle<BlockNumberFor<System>>
|
||||
+ OnFinalize<BlockNumberFor<System>>
|
||||
@@ -445,7 +450,10 @@ where
|
||||
{
|
||||
/// Execute all `OnRuntimeUpgrade` of this runtime, and return the aggregate weight.
|
||||
pub fn execute_on_runtime_upgrade() -> Weight {
|
||||
let before_all_weight =
|
||||
<AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
|
||||
<(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::on_runtime_upgrade()
|
||||
.saturating_add(before_all_weight)
|
||||
}
|
||||
|
||||
/// Start the execution of a particular block.
|
||||
|
||||
Reference in New Issue
Block a user