mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 15:21:08 +00:00
migrations: prevent accidentally using unversioned migrations instead of VersionedMigration (#3835)
closes #1324 #### Problem Currently, it is possible to accidentally use inner unversioned migration instead of `VersionedMigration` since both implement `OnRuntimeUpgrade`. #### Solution With this change, we make it clear that value of `Inner` is not intended to be used directly. It is achieved by bounding `Inner` to new trait `UncheckedOnRuntimeUpgrade`, which has the same interface (except `unchecked_` prefix) as `OnRuntimeUpgrade`. #### `try-runtime` functions Since developers can implement `try-runtime` for `Inner` value in `VersionedMigration` and have custom logic for it, I added the same `try-runtime` functions to `UncheckedOnRuntimeUpgrade`. I looked for a ways to not duplicate functions, but couldn't find anything that doesn't significantly change the codebase. So I would appreciate If you have any suggestions to improve this cc @liamaharon @xlc polkadot address: 16FqwPZ8GRC5U5D4Fu7W33nA55ZXzXGWHwmbnE1eT6pxuqcT --------- Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
@@ -20,7 +20,7 @@ use crate::{Config, OverweightIndex, Pallet, QueueConfig, QueueConfigData, DEFAU
|
||||
use cumulus_primitives_core::XcmpMessageFormat;
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
traits::{EnqueueMessage, OnRuntimeUpgrade, StorageVersion},
|
||||
traits::{EnqueueMessage, StorageVersion, UncheckedOnRuntimeUpgrade},
|
||||
weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, Weight},
|
||||
};
|
||||
|
||||
@@ -96,7 +96,7 @@ pub mod v2 {
|
||||
/// 2D weights).
|
||||
pub struct UncheckedMigrationToV2<T: Config>(PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrationToV2<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV2<T> {
|
||||
#[allow(deprecated)]
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let translate = |pre: v1::QueueConfigData| -> v2::QueueConfigData {
|
||||
@@ -187,7 +187,7 @@ pub mod v3 {
|
||||
/// Migrates the pallet storage to v3.
|
||||
pub struct UncheckedMigrationToV3<T: Config>(PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrationToV3<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV3<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
#[frame_support::storage_alias]
|
||||
type Overweight<T: Config> =
|
||||
@@ -266,7 +266,7 @@ pub mod v4 {
|
||||
/// thresholds to at least the default values.
|
||||
pub struct UncheckedMigrationToV4<T: Config>(PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrationToV4<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV4<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let translate = |pre: v2::QueueConfigData| -> QueueConfigData {
|
||||
let pre_default = v2::QueueConfigData::default();
|
||||
@@ -315,6 +315,7 @@ pub mod v4 {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Test};
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{Config, MaxPermanentSlots, MaxTemporarySlots, Pallet, LOG_TARGET};
|
||||
use frame_support::traits::{Get, GetStorageVersion, OnRuntimeUpgrade};
|
||||
use frame_support::traits::{Get, GetStorageVersion, UncheckedOnRuntimeUpgrade};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
@@ -23,10 +23,9 @@ use frame_support::ensure;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
pub mod v1 {
|
||||
|
||||
use super::*;
|
||||
pub struct VersionUncheckedMigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
let on_chain_version = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use frame_support::traits::{Contains, OnRuntimeUpgrade};
|
||||
use frame_support::traits::{Contains, UncheckedOnRuntimeUpgrade};
|
||||
|
||||
#[derive(Encode, Decode)]
|
||||
pub struct ParaInfoV1<Account, Balance> {
|
||||
@@ -27,7 +27,7 @@ pub struct ParaInfoV1<Account, Balance> {
|
||||
pub struct VersionUncheckedMigrateToV1<T, UnlockParaIds>(
|
||||
sp_std::marker::PhantomData<(T, UnlockParaIds)>,
|
||||
);
|
||||
impl<T: Config, UnlockParaIds: Contains<ParaId>> OnRuntimeUpgrade
|
||||
impl<T: Config, UnlockParaIds: Contains<ParaId>> UncheckedOnRuntimeUpgrade
|
||||
for VersionUncheckedMigrateToV1<T, UnlockParaIds>
|
||||
{
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
migrations::VersionedMigration, pallet_prelude::ValueQuery, storage_alias,
|
||||
traits::OnRuntimeUpgrade, weights::Weight,
|
||||
traits::UncheckedOnRuntimeUpgrade, weights::Weight,
|
||||
};
|
||||
|
||||
mod v0 {
|
||||
@@ -51,7 +51,7 @@ mod v1 {
|
||||
|
||||
/// Migration to V1
|
||||
pub struct UncheckedMigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrateToV1<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrateToV1<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight: Weight = Weight::zero();
|
||||
|
||||
@@ -141,7 +141,7 @@ pub type MigrateV0ToV1<T> = VersionedMigration<
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{v0, v1, OnRuntimeUpgrade, Weight};
|
||||
use super::{v0, v1, UncheckedOnRuntimeUpgrade, Weight};
|
||||
use crate::mock::{new_test_ext, MockGenesisConfig, OnDemandAssigner, Test};
|
||||
use primitives::Id as ParaId;
|
||||
|
||||
@@ -163,7 +163,7 @@ mod tests {
|
||||
|
||||
// For tests, db weight is zero.
|
||||
assert_eq!(
|
||||
<v1::UncheckedMigrateToV1<Test> as OnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
<v1::UncheckedMigrateToV1<Test> as UncheckedOnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
Weight::zero()
|
||||
);
|
||||
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
//! A module that is responsible for migration of storage.
|
||||
|
||||
use crate::configuration::{Config, Pallet};
|
||||
use frame_support::{pallet_prelude::*, traits::Defensive, weights::Weight};
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, UncheckedOnRuntimeUpgrade},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use primitives::{
|
||||
AsyncBackingParams, Balance, ExecutorParams, NodeFeatures, SessionIndex,
|
||||
@@ -26,8 +30,6 @@ use primitives::{
|
||||
use sp_runtime::Perbill;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
|
||||
use super::v9::V9HostConfiguration;
|
||||
// All configuration of the runtime with respect to paras.
|
||||
#[derive(Clone, Encode, PartialEq, Decode, Debug)]
|
||||
@@ -163,7 +165,7 @@ mod v10 {
|
||||
}
|
||||
|
||||
pub struct VersionUncheckedMigrateToV10<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateToV10<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateToV10<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade() for HostConfiguration MigrateToV10");
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
|
||||
use crate::configuration::{self, Config, Pallet};
|
||||
use frame_support::{
|
||||
migrations::VersionedMigration, pallet_prelude::*, traits::Defensive, weights::Weight,
|
||||
migrations::VersionedMigration,
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, UncheckedOnRuntimeUpgrade},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use primitives::{
|
||||
@@ -27,7 +30,6 @@ use primitives::{
|
||||
};
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
use polkadot_core_primitives::Balance;
|
||||
use sp_arithmetic::Perbill;
|
||||
|
||||
@@ -176,7 +178,7 @@ pub type MigrateToV11<T> = VersionedMigration<
|
||||
>;
|
||||
|
||||
pub struct UncheckedMigrateToV11<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrateToV11<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrateToV11<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade() for HostConfiguration MigrateToV11");
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::configuration::{self, migration::v11::V11HostConfiguration, Config, P
|
||||
use frame_support::{
|
||||
migrations::VersionedMigration,
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, OnRuntimeUpgrade},
|
||||
traits::{Defensive, UncheckedOnRuntimeUpgrade},
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use primitives::vstaging::SchedulerParams;
|
||||
@@ -70,7 +70,7 @@ pub type MigrateToV12<T> = VersionedMigration<
|
||||
|
||||
pub struct UncheckedMigrateToV12<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrateToV12<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrateToV12<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade() for HostConfiguration MigrateToV12");
|
||||
|
||||
@@ -73,7 +73,7 @@ mod v1 {
|
||||
CandidatePendingAvailability as V1CandidatePendingAvailability, Config, Pallet,
|
||||
PendingAvailability as V1PendingAvailability,
|
||||
};
|
||||
use frame_support::{traits::OnRuntimeUpgrade, weights::Weight};
|
||||
use frame_support::{traits::UncheckedOnRuntimeUpgrade, weights::Weight};
|
||||
use sp_core::Get;
|
||||
use sp_std::{collections::vec_deque::VecDeque, vec::Vec};
|
||||
|
||||
@@ -87,7 +87,7 @@ mod v1 {
|
||||
|
||||
pub struct VersionUncheckedMigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
log::trace!(target: crate::inclusion::LOG_TARGET, "Running pre_upgrade() for inclusion MigrateToV1");
|
||||
@@ -216,7 +216,7 @@ mod tests {
|
||||
},
|
||||
mock::{new_test_ext, MockGenesisConfig, Test},
|
||||
};
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
use frame_support::traits::UncheckedOnRuntimeUpgrade;
|
||||
use primitives::{AvailabilityBitfield, Id as ParaId};
|
||||
use test_helpers::{dummy_candidate_commitments, dummy_candidate_descriptor, dummy_hash};
|
||||
|
||||
@@ -225,7 +225,7 @@ mod tests {
|
||||
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
|
||||
// No data to migrate.
|
||||
assert_eq!(
|
||||
<VersionUncheckedMigrateToV1<Test> as OnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
<VersionUncheckedMigrateToV1<Test> as UncheckedOnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
Weight::zero()
|
||||
);
|
||||
assert!(V1PendingAvailability::<Test>::iter().next().is_none());
|
||||
@@ -299,7 +299,7 @@ mod tests {
|
||||
|
||||
// For tests, db weight is zero.
|
||||
assert_eq!(
|
||||
<VersionUncheckedMigrateToV1<Test> as OnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
<VersionUncheckedMigrateToV1<Test> as UncheckedOnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
Weight::zero()
|
||||
);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
migrations::VersionedMigration, pallet_prelude::ValueQuery, storage_alias,
|
||||
traits::OnRuntimeUpgrade, weights::Weight,
|
||||
traits::UncheckedOnRuntimeUpgrade, weights::Weight,
|
||||
};
|
||||
|
||||
/// Old/legacy assignment representation (v0).
|
||||
@@ -105,7 +105,8 @@ mod v0 {
|
||||
// - Assignments only consist of `ParaId`, `Assignment` is a concrete type (Same as V0Assignment).
|
||||
mod v1 {
|
||||
use frame_support::{
|
||||
pallet_prelude::ValueQuery, storage_alias, traits::OnRuntimeUpgrade, weights::Weight,
|
||||
pallet_prelude::ValueQuery, storage_alias, traits::UncheckedOnRuntimeUpgrade,
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
|
||||
@@ -164,7 +165,7 @@ mod v1 {
|
||||
|
||||
/// Migration to V1
|
||||
pub struct UncheckedMigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrateToV1<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrateToV1<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight: Weight = Weight::zero();
|
||||
|
||||
@@ -302,7 +303,7 @@ mod v2 {
|
||||
/// Migration to V2
|
||||
pub struct UncheckedMigrateToV2<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for UncheckedMigrateToV2<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrateToV2<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight: Weight = Weight::zero();
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::{
|
||||
};
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
traits::{OnRuntimeUpgrade, StorageVersion},
|
||||
traits::{OnRuntimeUpgrade, StorageVersion, UncheckedOnRuntimeUpgrade},
|
||||
weights::Weight,
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ pub mod v1 {
|
||||
///
|
||||
/// Use experimental [`MigrateToV1`] instead.
|
||||
pub struct VersionUncheckedMigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight = T::DbWeight::get().reads(1);
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
|
||||
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
|
||||
|
||||
title: "migrations: prevent accidentally using inner unversioned migration instead of `VersionedMigration`"
|
||||
|
||||
doc:
|
||||
- audience: Runtime Dev
|
||||
description: |
|
||||
Currently, it is possible to accidentally use inner unversioned migration instead of `VersionedMigration`
|
||||
since both implement `OnRuntimeUpgrade`. With this change, we make it clear that `Inner` is not intended
|
||||
to be used directly. It is achieved by bounding `Inner` to new trait `UncheckedOnRuntimeUpgrade`, which
|
||||
has the same interface as `OnRuntimeUpgrade`, but can not be used directly for runtime upgrade migrations.
|
||||
|
||||
This change will break all existing migrations passed to `VersionedMigration`. Developers should simply change
|
||||
those migrations to implement `UncheckedOnRuntimeUpgrade` instead of `OnRuntimeUpgrade`.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
--- a/path/to/migration.rs
|
||||
+++ b/path/to/migration.rs
|
||||
@@ -1,7 +1,7 @@
|
||||
-impl<T: Config> OnRuntimeUpgrade for MigrateVNToVM<T> {
|
||||
+impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateVNToVM<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
// Migration logic here
|
||||
// Adjust the migration logic if necessary to align with the expectations
|
||||
// of new `UncheckedOnRuntimeUpgrade` trait.
|
||||
0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
crates:
|
||||
- name: "pallet-example-single-block-migrations"
|
||||
bump: "major"
|
||||
- name: "pallet-xcm"
|
||||
bump: "major"
|
||||
- name: "pallet-grandpa"
|
||||
bump: "major"
|
||||
- name: "pallet-identity"
|
||||
bump: "major"
|
||||
- name: "pallet-nomination-pools"
|
||||
bump: "major"
|
||||
- name: "pallet-society"
|
||||
bump: "major"
|
||||
- name: "frame-support"
|
||||
bump: "major"
|
||||
- name: "pallet-uniques"
|
||||
bump: "major"
|
||||
- name: "polkadot-runtime-parachains"
|
||||
bump: "major"
|
||||
- name: "polkadot-runtime-common"
|
||||
bump: "major"
|
||||
@@ -89,7 +89,7 @@
|
||||
//!
|
||||
//! See the migration source code for detailed comments.
|
||||
//!
|
||||
//! To keep the migration logic organised, it is split across additional modules:
|
||||
//! Here's a brief overview of modules and types defined in `v1.rs`:
|
||||
//!
|
||||
//! ### `mod v0`
|
||||
//!
|
||||
@@ -98,28 +98,29 @@
|
||||
//!
|
||||
//! This allows reading the old v0 value from storage during the migration.
|
||||
//!
|
||||
//! ### `mod version_unchecked`
|
||||
//! ### `InnerMigrateV0ToV1`
|
||||
//!
|
||||
//! Here we define our raw migration logic,
|
||||
//! `version_unchecked::MigrateV0ToV1` which implements the [`OnRuntimeUpgrade`] trait.
|
||||
//! `InnerMigrateV0ToV1` which implements the [`UncheckedOnRuntimeUpgrade`] trait.
|
||||
//!
|
||||
//! Importantly, it is kept in a private module so that it cannot be accidentally used in a runtime.
|
||||
//! #### Why [`UncheckedOnRuntimeUpgrade`]?
|
||||
//!
|
||||
//! Private modules cannot be referenced in docs, so please read the code directly.
|
||||
//! Otherwise, we would have two implementations of [`OnRuntimeUpgrade`] which could be confusing,
|
||||
//! and may lead to accidentally using the wrong one.
|
||||
//!
|
||||
//! #### Standalone Struct or Pallet Hook?
|
||||
//!
|
||||
//! Note that the storage migration logic is attached to a standalone struct implementing
|
||||
//! [`OnRuntimeUpgrade`], rather than implementing the
|
||||
//! [`UncheckedOnRuntimeUpgrade`], rather than implementing the
|
||||
//! [`Hooks::on_runtime_upgrade`](frame_support::traits::Hooks::on_runtime_upgrade) hook directly on
|
||||
//! the pallet. The pallet hook is better suited for special types of logic that need to execute on
|
||||
//! every runtime upgrade, but not so much for one-off storage migrations.
|
||||
//!
|
||||
//! ### `pub mod versioned`
|
||||
//! ### `MigrateV0ToV1`
|
||||
//!
|
||||
//! Here, `version_unchecked::MigrateV0ToV1` is wrapped in a
|
||||
//! Here, `InnerMigrateV0ToV1` is wrapped in a
|
||||
//! [`VersionedMigration`] to define
|
||||
//! [`versioned::MigrateV0ToV1`](crate::migrations::v1::versioned::MigrateV0ToV1), which may be used
|
||||
//! [`MigrateV0ToV1`](crate::migrations::v1::MigrateV0ToV1), which may be used
|
||||
//! in runtimes.
|
||||
//!
|
||||
//! Using [`VersionedMigration`] ensures that
|
||||
@@ -128,8 +129,6 @@
|
||||
//! - Reads and writes from checking and setting the on-chain storage version are accounted for in
|
||||
//! the final [`Weight`](frame_support::weights::Weight)
|
||||
//!
|
||||
//! This is the only public module exported from `v1`.
|
||||
//!
|
||||
//! ### `mod test`
|
||||
//!
|
||||
//! Here basic unit tests are defined for the migration.
|
||||
@@ -142,7 +141,8 @@
|
||||
//! [`VersionedMigration`]: frame_support::migrations::VersionedMigration
|
||||
//! [`GetStorageVersion`]: frame_support::traits::GetStorageVersion
|
||||
//! [`OnRuntimeUpgrade`]: frame_support::traits::OnRuntimeUpgrade
|
||||
//! [`MigrateV0ToV1`]: crate::migrations::v1::versioned::MigrationV0ToV1
|
||||
//! [`UncheckedOnRuntimeUpgrade`]: frame_support::traits::UncheckedOnRuntimeUpgrade
|
||||
//! [`MigrateV0ToV1`]: crate::migrations::v1::MigrateV0ToV1
|
||||
|
||||
// We make sure this pallet uses `no_std` for compiling to Wasm.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
use frame_support::{
|
||||
storage_alias,
|
||||
traits::{Get, OnRuntimeUpgrade},
|
||||
traits::{Get, UncheckedOnRuntimeUpgrade},
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
@@ -34,118 +34,92 @@ mod v0 {
|
||||
pub type Value<T: crate::Config> = StorageValue<crate::Pallet<T>, u32>;
|
||||
}
|
||||
|
||||
/// Private module containing *version unchecked* migration logic.
|
||||
/// Implements [`UncheckedOnRuntimeUpgrade`], migrating the state of this pallet from V0 to V1.
|
||||
///
|
||||
/// Should only be used by the [`VersionedMigration`](frame_support::migrations::VersionedMigration)
|
||||
/// type in this module to create something to export.
|
||||
/// In V0 of the template [`crate::Value`] is just a `u32`. In V1, it has been upgraded to
|
||||
/// contain the struct [`crate::CurrentAndPreviousValue`].
|
||||
///
|
||||
/// The unversioned migration should be kept private so the unversioned migration cannot
|
||||
/// accidentally be used in any runtimes.
|
||||
///
|
||||
/// For more about this pattern of keeping items private, see
|
||||
/// - <https://github.com/rust-lang/rust/issues/30905>
|
||||
/// - <https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40>
|
||||
mod version_unchecked {
|
||||
use super::*;
|
||||
/// In this migration, update the on-chain storage for the pallet to reflect the new storage
|
||||
/// layout.
|
||||
pub struct InnerMigrateV0ToV1<T: crate::Config>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
/// Implements [`OnRuntimeUpgrade`], migrating the state of this pallet from V0 to V1.
|
||||
impl<T: crate::Config> UncheckedOnRuntimeUpgrade for InnerMigrateV0ToV1<T> {
|
||||
/// Return the existing [`crate::Value`] so we can check that it was correctly set in
|
||||
/// `InnerMigrateV0ToV1::post_upgrade`.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
use codec::Encode;
|
||||
|
||||
// Access the old value using the `storage_alias` type
|
||||
let old_value = v0::Value::<T>::get();
|
||||
// Return it as an encoded `Vec<u8>`
|
||||
Ok(old_value.encode())
|
||||
}
|
||||
|
||||
/// Migrate the storage from V0 to V1.
|
||||
///
|
||||
/// In V0 of the template [`crate::Value`] is just a `u32`. In V1, it has been upgraded to
|
||||
/// contain the struct [`crate::CurrentAndPreviousValue`].
|
||||
/// - If the value doesn't exist, there is nothing to do.
|
||||
/// - If the value exists, it is read and then written back to storage inside a
|
||||
/// [`crate::CurrentAndPreviousValue`].
|
||||
fn on_runtime_upgrade() -> frame_support::weights::Weight {
|
||||
// Read the old value from storage
|
||||
if let Some(old_value) = v0::Value::<T>::take() {
|
||||
// Write the new value to storage
|
||||
let new = crate::CurrentAndPreviousValue { current: old_value, previous: None };
|
||||
crate::Value::<T>::put(new);
|
||||
// One read for the old value, one write for the new value
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
} else {
|
||||
// One read for trying to access the old value
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the storage was migrated correctly.
|
||||
///
|
||||
/// In this migration, update the on-chain storage for the pallet to reflect the new storage
|
||||
/// layout.
|
||||
pub struct MigrateV0ToV1<T: crate::Config>(sp_std::marker::PhantomData<T>);
|
||||
/// - If there was no old value, the new value should not be set.
|
||||
/// - If there was an old value, the new value should be a [`crate::CurrentAndPreviousValue`].
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
use codec::Decode;
|
||||
use frame_support::ensure;
|
||||
|
||||
impl<T: crate::Config> OnRuntimeUpgrade for MigrateV0ToV1<T> {
|
||||
/// Return the existing [`crate::Value`] so we can check that it was correctly set in
|
||||
/// `version_unchecked::MigrateV0ToV1::post_upgrade`.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
use codec::Encode;
|
||||
let maybe_old_value = Option::<u32>::decode(&mut &state[..]).map_err(|_| {
|
||||
sp_runtime::TryRuntimeError::Other("Failed to decode old value from storage")
|
||||
})?;
|
||||
|
||||
// Access the old value using the `storage_alias` type
|
||||
let old_value = v0::Value::<T>::get();
|
||||
// Return it as an encoded `Vec<u8>`
|
||||
Ok(old_value.encode())
|
||||
}
|
||||
match maybe_old_value {
|
||||
Some(old_value) => {
|
||||
let expected_new_value =
|
||||
crate::CurrentAndPreviousValue { current: old_value, previous: None };
|
||||
let actual_new_value = crate::Value::<T>::get();
|
||||
|
||||
/// Migrate the storage from V0 to V1.
|
||||
///
|
||||
/// - If the value doesn't exist, there is nothing to do.
|
||||
/// - If the value exists, it is read and then written back to storage inside a
|
||||
/// [`crate::CurrentAndPreviousValue`].
|
||||
fn on_runtime_upgrade() -> frame_support::weights::Weight {
|
||||
// Read the old value from storage
|
||||
if let Some(old_value) = v0::Value::<T>::take() {
|
||||
// Write the new value to storage
|
||||
let new = crate::CurrentAndPreviousValue { current: old_value, previous: None };
|
||||
crate::Value::<T>::put(new);
|
||||
// One read for the old value, one write for the new value
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
} else {
|
||||
// One read for trying to access the old value
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the storage was migrated correctly.
|
||||
///
|
||||
/// - If there was no old value, the new value should not be set.
|
||||
/// - If there was an old value, the new value should be a
|
||||
/// [`crate::CurrentAndPreviousValue`].
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
use codec::Decode;
|
||||
use frame_support::ensure;
|
||||
|
||||
let maybe_old_value = Option::<u32>::decode(&mut &state[..]).map_err(|_| {
|
||||
sp_runtime::TryRuntimeError::Other("Failed to decode old value from storage")
|
||||
})?;
|
||||
|
||||
match maybe_old_value {
|
||||
Some(old_value) => {
|
||||
let expected_new_value =
|
||||
crate::CurrentAndPreviousValue { current: old_value, previous: None };
|
||||
let actual_new_value = crate::Value::<T>::get();
|
||||
|
||||
ensure!(actual_new_value.is_some(), "New value not set");
|
||||
ensure!(
|
||||
actual_new_value == Some(expected_new_value),
|
||||
"New value not set correctly"
|
||||
);
|
||||
},
|
||||
None => {
|
||||
ensure!(crate::Value::<T>::get().is_none(), "New value unexpectedly set");
|
||||
},
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
ensure!(actual_new_value.is_some(), "New value not set");
|
||||
ensure!(
|
||||
actual_new_value == Some(expected_new_value),
|
||||
"New value not set correctly"
|
||||
);
|
||||
},
|
||||
None => {
|
||||
ensure!(crate::Value::<T>::get().is_none(), "New value unexpectedly set");
|
||||
},
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Public module containing *version checked* migration logic.
|
||||
///
|
||||
/// This is the only module that should be exported from this module.
|
||||
///
|
||||
/// See [`VersionedMigration`](frame_support::migrations::VersionedMigration) docs for more about
|
||||
/// how it works.
|
||||
pub mod versioned {
|
||||
use super::*;
|
||||
|
||||
/// `version_unchecked::MigrateV0ToV1` wrapped in a
|
||||
/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that:
|
||||
/// - The migration only runs once when the on-chain storage version is 0
|
||||
/// - The on-chain storage version is updated to `1` after the migration executes
|
||||
/// - Reads/Writes from checking/settings the on-chain storage version are accounted for
|
||||
pub type MigrateV0ToV1<T> = frame_support::migrations::VersionedMigration<
|
||||
0, // The migration will only execute when the on-chain storage version is 0
|
||||
1, // The on-chain storage version will be set to 1 after the migration is complete
|
||||
version_unchecked::MigrateV0ToV1<T>,
|
||||
crate::pallet::Pallet<T>,
|
||||
<T as frame_system::Config>::DbWeight,
|
||||
>;
|
||||
}
|
||||
/// [`UncheckedOnRuntimeUpgrade`] implementation [`InnerMigrateV0ToV1`] wrapped in a
|
||||
/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that:
|
||||
/// - The migration only runs once when the on-chain storage version is 0
|
||||
/// - The on-chain storage version is updated to `1` after the migration executes
|
||||
/// - Reads/Writes from checking/settings the on-chain storage version are accounted for
|
||||
pub type MigrateV0ToV1<T> = frame_support::migrations::VersionedMigration<
|
||||
0, // The migration will only execute when the on-chain storage version is 0
|
||||
1, // The on-chain storage version will be set to 1 after the migration is complete
|
||||
InnerMigrateV0ToV1<T>,
|
||||
crate::pallet::Pallet<T>,
|
||||
<T as frame_system::Config>::DbWeight,
|
||||
>;
|
||||
|
||||
/// Tests for our migration.
|
||||
///
|
||||
@@ -155,10 +129,10 @@ pub mod versioned {
|
||||
/// 3. The storage is in the expected state after the migration
|
||||
#[cfg(any(all(feature = "try-runtime", test), doc))]
|
||||
mod test {
|
||||
use self::InnerMigrateV0ToV1;
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, MockRuntime};
|
||||
use frame_support::assert_ok;
|
||||
use version_unchecked::MigrateV0ToV1;
|
||||
|
||||
#[test]
|
||||
fn handles_no_existing_value() {
|
||||
@@ -168,16 +142,16 @@ mod test {
|
||||
assert!(v0::Value::<MockRuntime>::get().is_none());
|
||||
|
||||
// Get the pre_upgrade bytes
|
||||
let bytes = match MigrateV0ToV1::<MockRuntime>::pre_upgrade() {
|
||||
let bytes = match InnerMigrateV0ToV1::<MockRuntime>::pre_upgrade() {
|
||||
Ok(bytes) => bytes,
|
||||
Err(e) => panic!("pre_upgrade failed: {:?}", e),
|
||||
};
|
||||
|
||||
// Execute the migration
|
||||
let weight = MigrateV0ToV1::<MockRuntime>::on_runtime_upgrade();
|
||||
let weight = InnerMigrateV0ToV1::<MockRuntime>::on_runtime_upgrade();
|
||||
|
||||
// Verify post_upgrade succeeds
|
||||
assert_ok!(MigrateV0ToV1::<MockRuntime>::post_upgrade(bytes));
|
||||
assert_ok!(InnerMigrateV0ToV1::<MockRuntime>::post_upgrade(bytes));
|
||||
|
||||
// The weight should be just 1 read for trying to access the old value.
|
||||
assert_eq!(weight, <MockRuntime as frame_system::Config>::DbWeight::get().reads(1));
|
||||
@@ -195,16 +169,16 @@ mod test {
|
||||
v0::Value::<MockRuntime>::put(initial_value);
|
||||
|
||||
// Get the pre_upgrade bytes
|
||||
let bytes = match MigrateV0ToV1::<MockRuntime>::pre_upgrade() {
|
||||
let bytes = match InnerMigrateV0ToV1::<MockRuntime>::pre_upgrade() {
|
||||
Ok(bytes) => bytes,
|
||||
Err(e) => panic!("pre_upgrade failed: {:?}", e),
|
||||
};
|
||||
|
||||
// Execute the migration
|
||||
let weight = MigrateV0ToV1::<MockRuntime>::on_runtime_upgrade();
|
||||
let weight = InnerMigrateV0ToV1::<MockRuntime>::on_runtime_upgrade();
|
||||
|
||||
// Verify post_upgrade succeeds
|
||||
assert_ok!(MigrateV0ToV1::<MockRuntime>::post_upgrade(bytes));
|
||||
assert_ok!(InnerMigrateV0ToV1::<MockRuntime>::post_upgrade(bytes));
|
||||
|
||||
// The weight used should be 1 read for the old value, and 1 write for the new
|
||||
// value.
|
||||
|
||||
@@ -20,7 +20,7 @@ use codec::Decode;
|
||||
use frame_support::{
|
||||
migrations::VersionedMigration,
|
||||
storage,
|
||||
traits::{Get, OnRuntimeUpgrade},
|
||||
traits::{Get, UncheckedOnRuntimeUpgrade},
|
||||
weights::Weight,
|
||||
};
|
||||
use sp_consensus_grandpa::AuthorityList;
|
||||
@@ -36,9 +36,9 @@ fn load_authority_list() -> AuthorityList {
|
||||
}
|
||||
|
||||
/// Actual implementation of [`MigrateV4ToV5`].
|
||||
pub struct MigrateImpl<T>(PhantomData<T>);
|
||||
pub struct UncheckedMigrateImpl<T>(PhantomData<T>);
|
||||
|
||||
impl<T: crate::Config> OnRuntimeUpgrade for MigrateImpl<T> {
|
||||
impl<T: crate::Config> UncheckedOnRuntimeUpgrade for UncheckedMigrateImpl<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
use codec::Encode;
|
||||
@@ -92,5 +92,10 @@ impl<T: crate::Config> OnRuntimeUpgrade for MigrateImpl<T> {
|
||||
/// Migrate the storage from V4 to V5.
|
||||
///
|
||||
/// Switches from `GRANDPA_AUTHORITIES_KEY` to a normal FRAME storage item.
|
||||
pub type MigrateV4ToV5<T> =
|
||||
VersionedMigration<4, 5, MigrateImpl<T>, Pallet<T>, <T as frame_system::Config>::DbWeight>;
|
||||
pub type MigrateV4ToV5<T> = VersionedMigration<
|
||||
4,
|
||||
5,
|
||||
UncheckedMigrateImpl<T>,
|
||||
Pallet<T>,
|
||||
<T as frame_system::Config>::DbWeight,
|
||||
>;
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
//! Storage migrations for the Identity pallet.
|
||||
|
||||
use super::*;
|
||||
use frame_support::{migrations::VersionedMigration, pallet_prelude::*, traits::OnRuntimeUpgrade};
|
||||
use frame_support::{
|
||||
migrations::VersionedMigration, pallet_prelude::*, traits::UncheckedOnRuntimeUpgrade,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use codec::{Decode, Encode};
|
||||
@@ -66,7 +68,7 @@ pub mod v1 {
|
||||
/// prevent stalling a parachain by accumulating too much weight in the migration. To have an
|
||||
/// unlimited migration (e.g. in a chain without PoV limits), set this to `u64::MAX`.
|
||||
pub struct VersionUncheckedMigrateV0ToV1<T, const KL: u64>(PhantomData<T>);
|
||||
impl<T: Config, const KL: u64> OnRuntimeUpgrade for VersionUncheckedMigrateV0ToV1<T, KL> {
|
||||
impl<T: Config, const KL: u64> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV0ToV1<T, KL> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
let identities = v0::IdentityOf::<T>::iter().count();
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
use super::*;
|
||||
use crate::log;
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
use frame_support::traits::{OnRuntimeUpgrade, UncheckedOnRuntimeUpgrade};
|
||||
use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
@@ -132,7 +132,7 @@ pub mod v8 {
|
||||
}
|
||||
|
||||
pub struct VersionUncheckedMigrateV7ToV8<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateV7ToV8<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV7ToV8<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
Ok(Vec::new())
|
||||
@@ -211,7 +211,7 @@ pub(crate) mod v7 {
|
||||
CountedStorageMap<Pallet<T>, Twox64Concat, PoolId, V7BondedPoolInner<T>>;
|
||||
|
||||
pub struct VersionUncheckedMigrateV6ToV7<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateV6ToV7<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV6ToV7<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let migrated = BondedPools::<T>::count();
|
||||
// The TVL should be the sum of all the funds that are actively staked and in the
|
||||
@@ -282,7 +282,7 @@ mod v6 {
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV6<T> {
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV6<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut success = 0u64;
|
||||
let mut fail = 0u64;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
use super::*;
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::traits::{Defensive, DefensiveOption, Instance, OnRuntimeUpgrade};
|
||||
use frame_support::traits::{Defensive, DefensiveOption, Instance, UncheckedOnRuntimeUpgrade};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
@@ -36,7 +36,7 @@ impl<
|
||||
T: Config<I>,
|
||||
I: Instance + 'static,
|
||||
PastPayouts: Get<Vec<(<T as frame_system::Config>::AccountId, BalanceOf<T, I>)>>,
|
||||
> OnRuntimeUpgrade for VersionUncheckedMigrateToV2<T, I, PastPayouts>
|
||||
> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateToV2<T, I, PastPayouts>
|
||||
{
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
|
||||
@@ -41,19 +41,19 @@ use sp_std::{marker::PhantomData, vec::Vec};
|
||||
/// It takes 5 type parameters:
|
||||
/// - `From`: The version being upgraded from.
|
||||
/// - `To`: The version being upgraded to.
|
||||
/// - `Inner`: An implementation of `OnRuntimeUpgrade`.
|
||||
/// - `Inner`: An implementation of `UncheckedOnRuntimeUpgrade`.
|
||||
/// - `Pallet`: The Pallet being upgraded.
|
||||
/// - `Weight`: The runtime's RuntimeDbWeight implementation.
|
||||
///
|
||||
/// When a [`VersionedMigration`] `on_runtime_upgrade`, `pre_upgrade`, or `post_upgrade` method is
|
||||
/// called, the on-chain version of the pallet is compared to `From`. If they match, the `Inner`
|
||||
/// equivalent is called and the pallets on-chain version is set to `To` after the migration.
|
||||
/// Otherwise, a warning is logged notifying the developer that the upgrade was a noop and should
|
||||
/// probably be removed.
|
||||
/// `UncheckedOnRuntimeUpgrade` is called and the pallets on-chain version is set to `To`
|
||||
/// after the migration. Otherwise, a warning is logged notifying the developer that the upgrade was
|
||||
/// a noop and should probably be removed.
|
||||
///
|
||||
/// It is STRONGLY RECOMMENDED to write the unversioned migration logic in a private module and
|
||||
/// only export the versioned migration logic to prevent accidentally using the unversioned
|
||||
/// migration in any runtimes.
|
||||
/// By not bounding `Inner` with `OnRuntimeUpgrade`, we prevent developers from
|
||||
/// accidentally using the unchecked version of the migration in a runtime upgrade instead of
|
||||
/// [`VersionedMigration`].
|
||||
///
|
||||
/// ### Examples
|
||||
/// ```ignore
|
||||
@@ -71,9 +71,9 @@ use sp_std::{marker::PhantomData, vec::Vec};
|
||||
/// /// - https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40
|
||||
/// mod version_unchecked {
|
||||
/// use super::*;
|
||||
/// pub struct MigrateV5ToV6<T>(sp_std::marker::PhantomData<T>);
|
||||
/// impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateV5ToV6<T> {
|
||||
/// // OnRuntimeUpgrade implementation...
|
||||
/// pub struct VersionUncheckedMigrateV5ToV6<T>(sp_std::marker::PhantomData<T>);
|
||||
/// impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV5ToV6<T> {
|
||||
/// // `UncheckedOnRuntimeUpgrade` implementation...
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
@@ -116,7 +116,7 @@ pub enum VersionedPostUpgradeData {
|
||||
impl<
|
||||
const FROM: u16,
|
||||
const TO: u16,
|
||||
Inner: crate::traits::OnRuntimeUpgrade,
|
||||
Inner: crate::traits::UncheckedOnRuntimeUpgrade,
|
||||
Pallet: GetStorageVersion<InCodeStorageVersion = StorageVersion> + PalletInfoAccess,
|
||||
DbWeight: Get<RuntimeDbWeight>,
|
||||
> crate::traits::OnRuntimeUpgrade for VersionedMigration<FROM, TO, Inner, Pallet, DbWeight>
|
||||
|
||||
@@ -87,7 +87,7 @@ pub use hooks::GenesisBuild;
|
||||
pub use hooks::{
|
||||
BeforeAllRuntimeMigrations, BuildGenesisConfig, Hooks, IntegrityTest, OnFinalize, OnGenesis,
|
||||
OnIdle, OnInitialize, OnPoll, OnRuntimeUpgrade, OnTimestampSet, PostInherents,
|
||||
PostTransactions, PreInherents,
|
||||
PostTransactions, PreInherents, UncheckedOnRuntimeUpgrade,
|
||||
};
|
||||
|
||||
pub mod schedule;
|
||||
|
||||
@@ -227,6 +227,30 @@ pub trait OnRuntimeUpgrade {
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is intended for use within `VersionedMigration` to execute storage migrations without
|
||||
/// automatic version checks. Implementations should ensure migration logic is safe and idempotent.
|
||||
pub trait UncheckedOnRuntimeUpgrade {
|
||||
/// Called within `VersionedMigration` to execute the actual migration. It is also
|
||||
/// expected that no version checks are performed within this function.
|
||||
///
|
||||
/// See also [`Hooks::on_runtime_upgrade`].
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
|
||||
/// See [`Hooks::pre_upgrade`].
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
/// See [`Hooks::post_upgrade`].
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
|
||||
#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
|
||||
#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
|
||||
@@ -459,7 +483,9 @@ pub trait Hooks<BlockNumber> {
|
||||
/// ## Implementation Note: Standalone Migrations
|
||||
///
|
||||
/// Additional migrations can be created by directly implementing [`OnRuntimeUpgrade`] on
|
||||
/// structs and passing them to `Executive`.
|
||||
/// structs and passing them to `Executive`. Or alternatively, by implementing
|
||||
/// [`UncheckedOnRuntimeUpgrade`], passing it to [`crate::migrations::VersionedMigration`],
|
||||
/// which already implements [`OnRuntimeUpgrade`].
|
||||
///
|
||||
/// ## Implementation Note: Pallet Versioning
|
||||
///
|
||||
|
||||
@@ -23,7 +23,7 @@ use frame_support::{
|
||||
construct_runtime, derive_impl,
|
||||
migrations::VersionedMigration,
|
||||
parameter_types,
|
||||
traits::{GetStorageVersion, OnRuntimeUpgrade, StorageVersion},
|
||||
traits::{GetStorageVersion, OnRuntimeUpgrade, StorageVersion, UncheckedOnRuntimeUpgrade},
|
||||
weights::constants::RocksDbWeight,
|
||||
};
|
||||
use frame_system::Config;
|
||||
@@ -103,9 +103,11 @@ parameter_types! {
|
||||
static PostUpgradeCalledWith: Vec<u8> = Vec::new();
|
||||
}
|
||||
|
||||
/// Implement `OnRuntimeUpgrade` for `SomeUnversionedMigration`.
|
||||
/// Implement `UncheckedOnRuntimeUpgrade` for `SomeUnversionedMigration`.
|
||||
/// It sets SomeStorage to S, and returns a weight derived from UpgradeReads and UpgradeWrites.
|
||||
impl<T: dummy_pallet::Config, const S: u32> OnRuntimeUpgrade for SomeUnversionedMigration<T, S> {
|
||||
impl<T: dummy_pallet::Config, const S: u32> UncheckedOnRuntimeUpgrade
|
||||
for SomeUnversionedMigration<T, S>
|
||||
{
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
PreUpgradeCalled::set(true);
|
||||
Ok(PreUpgradeReturnBytes::get().to_vec())
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
//! Various pieces of common functionality.
|
||||
use super::*;
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::traits::{Get, OnRuntimeUpgrade};
|
||||
use frame_support::traits::{Get, UncheckedOnRuntimeUpgrade};
|
||||
|
||||
mod v1 {
|
||||
use super::*;
|
||||
|
||||
/// Actual implementation of the storage migration.
|
||||
pub struct MigrateToV1Impl<T, I>(PhantomData<(T, I)>);
|
||||
pub struct UncheckedMigrateToV1Impl<T, I>(PhantomData<(T, I)>);
|
||||
|
||||
impl<T: Config<I>, I: 'static> OnRuntimeUpgrade for MigrateToV1Impl<T, I> {
|
||||
impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for UncheckedMigrateToV1Impl<T, I> {
|
||||
fn on_runtime_upgrade() -> frame_support::weights::Weight {
|
||||
let mut count = 0;
|
||||
for (collection, detail) in Collection::<T, I>::iter() {
|
||||
@@ -49,7 +49,7 @@ mod v1 {
|
||||
pub type MigrateV0ToV1<T, I> = frame_support::migrations::VersionedMigration<
|
||||
0,
|
||||
1,
|
||||
v1::MigrateToV1Impl<T, I>,
|
||||
v1::UncheckedMigrateToV1Impl<T, I>,
|
||||
Pallet<T, I>,
|
||||
<T as frame_system::Config>::DbWeight,
|
||||
>;
|
||||
|
||||
Reference in New Issue
Block a user