Runtime Upgrade ref docs and Single Block Migration example pallet (#1554)

Closes https://github.com/paritytech/polkadot-sdk-docs/issues/55

- Changes 'current storage version' terminology to less ambiguous
'in-code storage version' (suggestion by @ggwpez)
- Adds a new example pallet `pallet-example-single-block-migrations`
- Adds a new reference doc to replace
https://docs.substrate.io/maintain/runtime-upgrades/ (temporarily living
in the pallet while we wait for developer hub PR to merge)
- Adds documentation for the `storage_alias` macro
- Improves `trait Hooks` docs 
- Improves `trait GetStorageVersion` docs
- Update the suggested patterns for using `VersionedMigration`, so that
version unchecked migrations are never exported
- Prevents accidental usage of version unchecked migrations in runtimes

https://github.com/paritytech/substrate/pull/14421#discussion_r1255467895
- Unversioned migration code is kept inside `mod version_unchecked`,
versioned code is kept in `pub mod versioned`
- It is necessary to use modules to limit visibility because the inner
migration must be `pub`. See
https://github.com/rust-lang/rust/issues/30905 and

https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40
for more.

### todo

- [x] move to reference docs to proper place within sdk-docs (now that
https://github.com/paritytech/polkadot-sdk/pull/2102 is merged)
- [x] prdoc

---------

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Juan <juangirini@gmail.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: command-bot <>
Co-authored-by: gupnik <nikhilgupta.iitk@gmail.com>
This commit is contained in:
Liam Aharon
2024-02-28 18:32:02 +11:00
committed by GitHub
parent 7ec0b8741b
commit 12ce4f7d04
87 changed files with 1222 additions and 369 deletions
+37 -1
View File
@@ -555,6 +555,42 @@ pub fn __create_tt_macro(input: TokenStream) -> TokenStream {
tt_macro::create_tt_return_macro(input)
}
/// Allows accessing on-chain pallet storage that is no longer accessible via the pallet.
///
/// This is especially useful when writing storage migrations, when types of storage items are
/// modified or outright removed, but the previous definition is required to perform the migration.
///
/// ## Example
///
/// Imagine a pallet with the following storage definition:
/// ```ignore
/// #[pallet::storage]
/// pub type Value<T: Config> = StorageValue<_, u32>;
/// ```
/// `Value` can be accessed by calling `Value::<T>::get()`.
///
/// Now imagine the definition of `Value` is updated to a `(u32, u32)`:
/// ```ignore
/// #[pallet::storage]
/// pub type Value<T: Config> = StorageValue<_, (u32, u32)>;
/// ```
/// The on-chain value of `Value` is `u32`, but `Value::<T>::get()` expects it to be `(u32, u32)`.
///
/// In this instance the developer must write a storage migration to reading the old value of
/// `Value` and writing it back to storage in the new format, so that the on-chain storage layout is
/// consistent with what is defined in the pallet.
///
/// We can read the old v0 value of `Value` in the migration by creating a `storage_alias`:
/// ```ignore
/// pub(crate) mod v0 {
/// use super::*;
///
/// #[storage_alias]
/// pub type Value<T: crate::Config> = StorageValue<crate::Pallet<T>, u32>;
/// }
/// ```
///
/// The developer can now access the old value of `Value` by calling `v0::Value::<T>::get()`.
#[proc_macro_attribute]
pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream {
storage_alias::storage_alias(attributes.into(), input.into())
@@ -1058,7 +1094,7 @@ pub fn generate_store(_: TokenStream, _: TokenStream) -> TokenStream {
/// pub struct Pallet<T>(_);
/// ```
///
/// If not present, the current storage version is set to the default value.
/// If not present, the in-code storage version is set to the default value.
#[proc_macro_attribute]
pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -42,7 +42,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
>::name::<Self>().unwrap_or("<unknown pallet name>")
};
let initialize_on_chain_storage_version = if let Some(current_version) =
let initialize_on_chain_storage_version = if let Some(in_code_version) =
&def.pallet_struct.storage_version
{
quote::quote! {
@@ -50,9 +50,9 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
target: #frame_support::LOG_TARGET,
"🐥 New pallet {:?} detected in the runtime. Initializing the on-chain storage version to match the storage version defined in the pallet: {:?}",
#pallet_name,
#current_version
#in_code_version
);
#current_version.put::<Self>();
#in_code_version.put::<Self>();
}
} else {
quote::quote! {
@@ -73,10 +73,10 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
#frame_support::__private::log::info!(
target: #frame_support::LOG_TARGET,
"⚠️ {} declares internal migrations (which *might* execute). \
On-chain `{:?}` vs current storage version `{:?}`",
On-chain `{:?}` vs in-code storage version `{:?}`",
#pallet_name,
<Self as #frame_support::traits::GetStorageVersion>::on_chain_storage_version(),
<Self as #frame_support::traits::GetStorageVersion>::current_storage_version(),
<Self as #frame_support::traits::GetStorageVersion>::in_code_storage_version(),
);
}
} else {
@@ -102,23 +102,23 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
};
// If a storage version is set, we should ensure that the storage version on chain matches the
// current storage version. This assumes that `Executive` is running custom migrations before
// in-code storage version. This assumes that `Executive` is running custom migrations before
// the pallets are called.
let post_storage_version_check = if def.pallet_struct.storage_version.is_some() {
quote::quote! {
let on_chain_version = <Self as #frame_support::traits::GetStorageVersion>::on_chain_storage_version();
let current_version = <Self as #frame_support::traits::GetStorageVersion>::current_storage_version();
let in_code_version = <Self as #frame_support::traits::GetStorageVersion>::in_code_storage_version();
if on_chain_version != current_version {
if on_chain_version != in_code_version {
#frame_support::__private::log::error!(
target: #frame_support::LOG_TARGET,
"{}: On chain storage version {:?} doesn't match current storage version {:?}.",
"{}: On chain storage version {:?} doesn't match in-code storage version {:?}.",
#pallet_name,
on_chain_version,
current_version,
in_code_version,
);
return Err("On chain and current storage version do not match. Missing runtime upgrade?".into());
return Err("On chain and in-code storage version do not match. Missing runtime upgrade?".into());
}
}
} else {
@@ -160,7 +160,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
}
);
let (storage_version, current_storage_version_ty) =
let (storage_version, in_code_storage_version_ty) =
if let Some(v) = def.pallet_struct.storage_version.as_ref() {
(quote::quote! { #v }, quote::quote! { #frame_support::traits::StorageVersion })
} else {
@@ -203,9 +203,9 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
for #pallet_ident<#type_use_gen>
#config_where_clause
{
type CurrentStorageVersion = #current_storage_version_ty;
type InCodeStorageVersion = #in_code_storage_version_ty;
fn current_storage_version() -> Self::CurrentStorageVersion {
fn in_code_storage_version() -> Self::InCodeStorageVersion {
#storage_version
}
@@ -44,7 +44,7 @@ pub struct PalletStructDef {
/// Whether to specify the storages max encoded len when implementing `StorageInfoTrait`.
/// Contains the span of the attribute.
pub without_storage_info: Option<proc_macro2::Span>,
/// The current storage version of the pallet.
/// The in-code storage version of the pallet.
pub storage_version: Option<syn::Path>,
}
+2 -2
View File
@@ -1178,7 +1178,7 @@ pub mod pallet_prelude {
/// # `pallet::storage_version`
///
/// Because the [`pallet::pallet`](#pallet-struct-placeholder-palletpallet-mandatory) macro
/// implements [`traits::GetStorageVersion`], the current storage version needs to be
/// implements [`traits::GetStorageVersion`], the in-code storage version needs to be
/// communicated to the macro. This can be done by using the `pallet::storage_version`
/// attribute:
///
@@ -1190,7 +1190,7 @@ pub mod pallet_prelude {
/// pub struct Pallet<T>(_);
/// ```
///
/// If not present, the current storage version is set to the default value.
/// If not present, the in-code storage version is set to the default value.
///
/// Also see [`pallet::storage_version`](`frame_support::pallet_macros::storage_version`)
///
+36 -19
View File
@@ -43,12 +43,30 @@ use sp_std::marker::PhantomData;
/// 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.
///
/// ### Examples
/// ```ignore
/// // In file defining migrations
/// pub struct VersionUncheckedMigrateV5ToV6<T>(sp_std::marker::PhantomData<T>);
/// impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateV5ToV6<T> {
/// // OnRuntimeUpgrade implementation...
///
/// /// Private module containing *version unchecked* migration logic.
/// ///
/// /// Should only be used by the [`VersionedMigration`] type in this module to create something to
/// /// export.
/// ///
/// /// We keep this 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::*;
/// pub struct MigrateV5ToV6<T>(sp_std::marker::PhantomData<T>);
/// impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateV5ToV6<T> {
/// // OnRuntimeUpgrade implementation...
/// }
/// }
///
/// pub type MigrateV5ToV6<T, I> =
@@ -91,7 +109,7 @@ impl<
const FROM: u16,
const TO: u16,
Inner: crate::traits::OnRuntimeUpgrade,
Pallet: GetStorageVersion<CurrentStorageVersion = StorageVersion> + PalletInfoAccess,
Pallet: GetStorageVersion<InCodeStorageVersion = StorageVersion> + PalletInfoAccess,
DbWeight: Get<RuntimeDbWeight>,
> crate::traits::OnRuntimeUpgrade for VersionedMigration<FROM, TO, Inner, Pallet, DbWeight>
{
@@ -163,25 +181,25 @@ impl<
}
}
/// Can store the current pallet version in storage.
pub trait StoreCurrentStorageVersion<T: GetStorageVersion + PalletInfoAccess> {
/// Write the current storage version to the storage.
fn store_current_storage_version();
/// Can store the in-code pallet version on-chain.
pub trait StoreInCodeStorageVersion<T: GetStorageVersion + PalletInfoAccess> {
/// Write the in-code storage version on-chain.
fn store_in_code_storage_version();
}
impl<T: GetStorageVersion<CurrentStorageVersion = StorageVersion> + PalletInfoAccess>
StoreCurrentStorageVersion<T> for StorageVersion
impl<T: GetStorageVersion<InCodeStorageVersion = StorageVersion> + PalletInfoAccess>
StoreInCodeStorageVersion<T> for StorageVersion
{
fn store_current_storage_version() {
let version = <T as GetStorageVersion>::current_storage_version();
fn store_in_code_storage_version() {
let version = <T as GetStorageVersion>::in_code_storage_version();
version.put::<T>();
}
}
impl<T: GetStorageVersion<CurrentStorageVersion = NoStorageVersionSet> + PalletInfoAccess>
StoreCurrentStorageVersion<T> for NoStorageVersionSet
impl<T: GetStorageVersion<InCodeStorageVersion = NoStorageVersionSet> + PalletInfoAccess>
StoreInCodeStorageVersion<T> for NoStorageVersionSet
{
fn store_current_storage_version() {
fn store_in_code_storage_version() {
StorageVersion::default().put::<T>();
}
}
@@ -193,7 +211,7 @@ pub trait PalletVersionToStorageVersionHelper {
impl<T: GetStorageVersion + PalletInfoAccess> PalletVersionToStorageVersionHelper for T
where
T::CurrentStorageVersion: StoreCurrentStorageVersion<T>,
T::InCodeStorageVersion: StoreInCodeStorageVersion<T>,
{
fn migrate(db_weight: &RuntimeDbWeight) -> Weight {
const PALLET_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__PALLET_VERSION__:";
@@ -204,8 +222,7 @@ where
sp_io::storage::clear(&pallet_version_key(<T as PalletInfoAccess>::name()));
<T::CurrentStorageVersion as StoreCurrentStorageVersion<T>>::store_current_storage_version(
);
<T::InCodeStorageVersion as StoreInCodeStorageVersion<T>>::store_in_code_storage_version();
db_weight.writes(2)
}
@@ -226,7 +243,7 @@ impl PalletVersionToStorageVersionHelper for T {
/// Migrate from the `PalletVersion` struct to the new [`StorageVersion`] struct.
///
/// This will remove all `PalletVersion's` from the state and insert the current storage version.
/// This will remove all `PalletVersion's` from the state and insert the in-code storage version.
pub fn migrate_from_pallet_version_to_storage_version<
Pallets: PalletVersionToStorageVersionHelper,
>(
+41 -29
View File
@@ -90,7 +90,7 @@ impl<BlockNumber: Copy + AtLeast32BitUnsigned> OnIdle<BlockNumber> for Tuple {
///
/// Implementing this trait for a pallet let's you express operations that should
/// happen at genesis. It will be called in an externalities provided environment and
/// will see the genesis state after all pallets have written their genesis state.
/// will set the genesis state after all pallets have written their genesis state.
#[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))]
@@ -306,19 +306,23 @@ pub trait IntegrityTest {
/// end
/// ```
///
/// * `OnRuntimeUpgrade` is only executed before everything else if a code
/// * `OnRuntimeUpgrade` is mandatorily at the beginning of the block body (extrinsics) being
/// processed. change is detected.
/// * Extrinsics start with inherents, and continue with other signed or unsigned extrinsics.
/// * `OnIdle` optionally comes after extrinsics.
/// `OnFinalize` mandatorily comes after `OnIdle`.
/// * [`OnRuntimeUpgrade`](Hooks::OnRuntimeUpgrade) hooks are only executed when a code change is
/// detected.
/// * [`OnRuntimeUpgrade`](Hooks::OnRuntimeUpgrade) hooks are mandatorily executed at the very
/// beginning of the block body, before any extrinsics are processed.
/// * [`Inherents`](sp_inherents) are always executed before any other other signed or unsigned
/// extrinsics.
/// * [`OnIdle`](Hooks::OnIdle) hooks are executed after extrinsics if there is weight remaining in
/// the block.
/// * [`OnFinalize`](Hooks::OnFinalize) hooks are mandatorily executed after
/// [`OnIdle`](Hooks::OnIdle).
///
/// > `OffchainWorker` is not part of this flow, as it is not really part of the consensus/main
/// > block import path, and is called optionally, and in other circumstances. See
/// > [`crate::traits::misc::OffchainWorker`] for more information.
/// > [`OffchainWorker`](crate::traits::misc::OffchainWorker) hooks are not part of this flow,
/// > because they are not part of the consensus/main block building logic. See
/// > [`OffchainWorker`](crate::traits::misc::OffchainWorker) for more information.
///
/// To learn more about the execution of hooks see `frame-executive` as this component is is charge
/// of dispatching extrinsics and placing the hooks in the correct order.
/// To learn more about the execution of hooks see the FRAME `Executive` pallet which is in charge
/// of dispatching extrinsics and calling hooks in the correct order.
pub trait Hooks<BlockNumber> {
/// Block initialization hook. This is called at the very beginning of block execution.
///
@@ -370,30 +374,38 @@ pub trait Hooks<BlockNumber> {
Weight::zero()
}
/// Hook executed when a code change (aka. a "runtime upgrade") is detected by FRAME.
/// Hook executed when a code change (aka. a "runtime upgrade") is detected by the FRAME
/// `Executive` pallet.
///
/// Be aware that this is called before [`Hooks::on_initialize`] of any pallet; therefore, a lot
/// of the critical storage items such as `block_number` in system pallet might have not been
/// set.
/// set yet.
///
/// Vert similar to [`Hooks::on_initialize`], any code in this block is mandatory and MUST
/// execute. Use with care.
/// Similar to [`Hooks::on_initialize`], any code in this block is mandatory and MUST execute.
/// It is strongly recommended to dry-run the execution of these hooks using
/// [try-runtime-cli](https://github.com/paritytech/try-runtime-cli) to ensure they will not
/// produce and overweight block which can brick your chain. Use with care!
///
/// ## Implementation Note: Versioning
/// ## Implementation Note: Standalone Migrations
///
/// 1. An implementation of this should typically follow a pattern where the version of the
/// pallet is checked against the onchain version, and a decision is made about what needs to be
/// done. This is helpful to prevent accidental repetitive execution of this hook, which can be
/// catastrophic.
/// Additional migrations can be created by directly implementing [`OnRuntimeUpgrade`] on
/// structs and passing them to `Executive`.
///
/// Alternatively, [`frame_support::migrations::VersionedMigration`] can be used to assist with
/// this.
/// ## Implementation Note: Pallet Versioning
///
/// ## Implementation Note: Runtime Level Migration
/// Implementations of this hook are typically wrapped in
/// [`crate::migrations::VersionedMigration`] to ensure the migration is executed exactly
/// once and only when it is supposed to.
///
/// Additional "upgrade hooks" can be created by pallets by a manual implementation of
/// [`Hooks::on_runtime_upgrade`] which can be passed on to `Executive` at the top level
/// runtime.
/// Alternatively, developers can manually implement version checks.
///
/// Failure to adequately check storage versions can result in accidental repetitive execution
/// of the hook, which can be catastrophic.
///
/// ## Implementation Note: Weight
///
/// Typically, implementations of this method are simple enough that weights can be calculated
/// manually. However, if required, a benchmark can also be used.
fn on_runtime_upgrade() -> Weight {
Weight::zero()
}
@@ -403,7 +415,7 @@ pub trait Hooks<BlockNumber> {
/// It should focus on certain checks to ensure that the state is sensible. This is never
/// executed in a consensus code-path, therefore it can consume as much weight as it needs.
///
/// This hook should not alter any storage.
/// This hook must not alter any storage.
#[cfg(feature = "try-runtime")]
fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError> {
Ok(())
@@ -415,7 +427,7 @@ pub trait Hooks<BlockNumber> {
/// which will be passed to `post_upgrade` after upgrading for post-check. An empty vector
/// should be returned if there is no such need.
///
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
/// This hook is never executed on-chain but instead used by testing tools.
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
Ok(Vec::new())
+46 -23
View File
@@ -261,41 +261,64 @@ impl Add<u16> for StorageVersion {
}
}
/// Special marker struct if no storage version is set for a pallet.
/// Special marker struct used when [`storage_version`](crate::pallet_macros::storage_version) is
/// not defined for a pallet.
///
/// If you (the reader) end up here, it probably means that you tried to compare
/// [`GetStorageVersion::on_chain_storage_version`] against
/// [`GetStorageVersion::current_storage_version`]. This basically means that the
/// [`storage_version`](crate::pallet_macros::storage_version) is missing in the pallet where the
/// mentioned functions are being called.
/// [`GetStorageVersion::in_code_storage_version`]. This basically means that the
/// [`storage_version`](crate::pallet_macros::storage_version) is missing from the pallet where the
/// mentioned functions are being called, and needs to be defined.
#[derive(Debug, Default)]
pub struct NoStorageVersionSet;
/// Provides information about the storage version of a pallet.
/// Provides information about a pallet's storage versions.
///
/// It differentiates between current and on-chain storage version. Both should be only out of sync
/// when a new runtime upgrade was applied and the runtime migrations did not yet executed.
/// Otherwise it means that the pallet works with an unsupported storage version and unforeseen
/// stuff can happen.
/// Every pallet has two storage versions:
/// 1. An in-code storage version
/// 2. An on-chain storage version
///
/// The current storage version is the version of the pallet as supported at runtime. The active
/// storage version is the version of the pallet in the storage.
/// The in-code storage version is the version of the pallet as defined in the runtime blob, and the
/// on-chain storage version is the version of the pallet stored on-chain.
///
/// It is required to update the on-chain storage version manually when a migration was applied.
/// Storage versions should be only ever be out of sync when a pallet has been updated to a new
/// version and the in-code version is incremented, but the migration has not yet been executed
/// on-chain as part of a runtime upgrade.
///
/// It is the responsibility of the developer to ensure that the on-chain storage version is set
/// correctly during a migration so that it matches the in-code storage version.
pub trait GetStorageVersion {
/// This will be filled out by the [`pallet`](crate::pallet) macro.
/// This type is generated by the [`pallet`](crate::pallet) macro.
///
/// If the [`storage_version`](crate::pallet_macros::storage_version) attribute isn't given
/// this is set to [`NoStorageVersionSet`] to inform the user that the attribute is missing.
/// This should prevent that the user forgets to set a storage version when required. However,
/// this will only work when the user actually tries to call [`Self::current_storage_version`]
/// to compare it against the [`Self::on_chain_storage_version`]. If the attribute is given,
/// this will be set to [`StorageVersion`].
type CurrentStorageVersion;
/// If the [`storage_version`](crate::pallet_macros::storage_version) attribute isn't specified,
/// this is set to [`NoStorageVersionSet`] to signify that it is missing.
///
/// If the [`storage_version`](crate::pallet_macros::storage_version) attribute is specified,
/// this is be set to a [`StorageVersion`] corresponding to the attribute.
///
/// The intention of using [`NoStorageVersionSet`] instead of defaulting to a [`StorageVersion`]
/// of zero is to prevent developers from forgetting to set
/// [`storage_version`](crate::pallet_macros::storage_version) when it is required, like in the
/// case that they wish to compare the in-code storage version to the on-chain storage version.
type InCodeStorageVersion;
/// Returns the current storage version as supported by the pallet.
fn current_storage_version() -> Self::CurrentStorageVersion;
/// Returns the on-chain storage version of the pallet as stored in the storage.
#[deprecated(
note = "This method has been renamed to `in_code_storage_version` and will be removed after March 2024."
)]
/// DEPRECATED: Use [`Self::current_storage_version`] instead.
///
/// Returns the in-code storage version as specified in the
/// [`storage_version`](crate::pallet_macros::storage_version) attribute, or
/// [`NoStorageVersionSet`] if the attribute is missing.
fn current_storage_version() -> Self::InCodeStorageVersion {
Self::in_code_storage_version()
}
/// Returns the in-code storage version as specified in the
/// [`storage_version`](crate::pallet_macros::storage_version) attribute, or
/// [`NoStorageVersionSet`] if the attribute is missing.
fn in_code_storage_version() -> Self::InCodeStorageVersion;
/// Returns the storage version of the pallet as last set in the actual on-chain storage.
fn on_chain_storage_version() -> StorageVersion;
}
@@ -683,7 +683,7 @@ fn test_metadata() {
name: "Version",
ty: meta_type::<RuntimeVersion>(),
value: RuntimeVersion::default().encode(),
docs: maybe_docs(vec![ " Get the chain's current version."]),
docs: maybe_docs(vec![ " Get the chain's in-code version."]),
},
PalletConstantMetadata {
name: "SS58Prefix",
+11 -11
View File
@@ -590,7 +590,7 @@ pub mod pallet2 {
Self::deposit_event(Event::Something(31));
if UpdateStorageVersion::get() {
Self::current_storage_version().put::<Self>();
Self::in_code_storage_version().put::<Self>();
}
Weight::zero()
@@ -1310,7 +1310,7 @@ fn pallet_on_genesis() {
assert_eq!(pallet::Pallet::<Runtime>::on_chain_storage_version(), StorageVersion::new(0));
pallet::Pallet::<Runtime>::on_genesis();
assert_eq!(
pallet::Pallet::<Runtime>::current_storage_version(),
pallet::Pallet::<Runtime>::in_code_storage_version(),
pallet::Pallet::<Runtime>::on_chain_storage_version(),
);
})
@@ -2257,10 +2257,10 @@ fn pallet_on_chain_storage_version_initializes_correctly() {
AllPalletsWithSystem,
>;
// Simple example of a pallet with current version 10 being added to the runtime for the first
// Simple example of a pallet with in-code version 10 being added to the runtime for the first
// time.
TestExternalities::default().execute_with(|| {
let current_version = Example::current_storage_version();
let in_code_version = Example::in_code_storage_version();
// Check the pallet has no storage items set.
let pallet_hashed_prefix = twox_128(Example::name().as_bytes());
@@ -2271,14 +2271,14 @@ fn pallet_on_chain_storage_version_initializes_correctly() {
// version.
Executive::execute_on_runtime_upgrade();
// Check that the storage version was initialized to the current version
// Check that the storage version was initialized to the in-code version
let on_chain_version_after = StorageVersion::get::<Example>();
assert_eq!(on_chain_version_after, current_version);
assert_eq!(on_chain_version_after, in_code_version);
});
// Pallet with no current storage version should have the on-chain version initialized to 0.
// Pallet with no in-code storage version should have the on-chain version initialized to 0.
TestExternalities::default().execute_with(|| {
// Example4 current_storage_version is NoStorageVersionSet.
// Example4 in_code_storage_version is NoStorageVersionSet.
// Check the pallet has no storage items set.
let pallet_hashed_prefix = twox_128(Example4::name().as_bytes());
@@ -2308,7 +2308,7 @@ fn post_runtime_upgrade_detects_storage_version_issues() {
impl OnRuntimeUpgrade for CustomUpgrade {
fn on_runtime_upgrade() -> Weight {
Example2::current_storage_version().put::<Example2>();
Example2::in_code_storage_version().put::<Example2>();
Default::default()
}
@@ -2351,14 +2351,14 @@ fn post_runtime_upgrade_detects_storage_version_issues() {
>;
TestExternalities::default().execute_with(|| {
// Set the on-chain version to one less than the current version for `Example`, simulating a
// Set the on-chain version to one less than the in-code version for `Example`, simulating a
// forgotten migration
StorageVersion::new(9).put::<Example2>();
// The version isn't changed, we should detect it.
assert!(
Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap_err() ==
"On chain and current storage version do not match. Missing runtime upgrade?"
"On chain and in-code storage version do not match. Missing runtime upgrade?"
.into()
);
});
@@ -29,7 +29,7 @@ mod pallet {
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_runtime_upgrade() -> Weight {
if Self::current_storage_version() != Self::on_chain_storage_version() {
if Self::in_code_storage_version() != Self::on_chain_storage_version() {
}
@@ -1,7 +1,7 @@
error[E0369]: binary operation `!=` cannot be applied to type `NoStorageVersionSet`
--> tests/pallet_ui/compare_unset_storage_version.rs:32:39
|
32 | if Self::current_storage_version() != Self::on_chain_storage_version() {
32 | if Self::in_code_storage_version() != Self::on_chain_storage_version() {
| ------------------------------- ^^ -------------------------------- StorageVersion
| |
| NoStorageVersionSet