mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 03:27:58 +00:00
Move PalletVersion away from the crate version (#9165)
* Move `PalletVersion` away from the crate version Before this pr, `PalletVersion` was referring to the crate version that hosted the pallet. This pr introduces a custom `package.metadata.frame` section in the `Cargo.toml` that can contain a `pallet-version` key value pair. While the value is expected to be a valid u16. If this key/value pair isn't given, the version is set to 1. It also changes the `PalletVersion` declaration. We now only have one `u16` that represents the version. Not a major/minor/patch version. As the old `PalletVersion` was starting with the `u16` major, decoding the old values will work. * Overhaul the entire implementation - Drop PalletVersion - Introduce StorageVersion - StorageVersion needs to be set in the crate and set for the macros - Added migration * Fix migrations * Review feedback * Remove unneeded dep * remove pub consts * Brings back logging and implements `GetStorageVersion` * Return weight from migration * Fmt and remove unused import * Update frame/support/src/dispatch.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Update frame/support/src/traits/metadata.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
@@ -323,7 +323,6 @@ pub trait OnTimestampSet<Moment> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::traits::metadata::PalletVersion;
|
||||
|
||||
#[test]
|
||||
fn on_initialize_and_on_runtime_upgrade_weight_merge_works() {
|
||||
@@ -342,18 +341,4 @@ mod tests {
|
||||
assert_eq!(<(Test, Test)>::on_initialize(0), 20);
|
||||
assert_eq!(<(Test, Test)>::on_runtime_upgrade(), 40);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_pallet_version_ordering() {
|
||||
let version = PalletVersion::new(1, 0, 0);
|
||||
assert!(version > PalletVersion::new(0, 1, 2));
|
||||
assert!(version == PalletVersion::new(1, 0, 0));
|
||||
assert!(version < PalletVersion::new(1, 0, 1));
|
||||
assert!(version < PalletVersion::new(1, 1, 0));
|
||||
|
||||
let version = PalletVersion::new(2, 50, 50);
|
||||
assert!(version < PalletVersion::new(2, 50, 51));
|
||||
assert!(version > PalletVersion::new(2, 49, 51));
|
||||
assert!(version < PalletVersion::new(3, 49, 51));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,52 +68,42 @@ pub trait GetCallMetadata {
|
||||
fn get_call_metadata(&self) -> CallMetadata;
|
||||
}
|
||||
|
||||
/// The storage key postfix that is used to store the [`PalletVersion`] per pallet.
|
||||
/// The storage key postfix that is used to store the [`StorageVersion`] per pallet.
|
||||
///
|
||||
/// The full storage key is built by using:
|
||||
/// Twox128([`PalletInfo::name`]) ++ Twox128([`PALLET_VERSION_STORAGE_KEY_POSTFIX`])
|
||||
pub const PALLET_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__PALLET_VERSION__:";
|
||||
/// Twox128([`PalletInfo::name`]) ++ Twox128([`STORAGE_VERSION_STORAGE_KEY_POSTFIX`])
|
||||
pub const STORAGE_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__STORAGE_VERSION__:";
|
||||
|
||||
/// The version of a pallet.
|
||||
/// The storage version of a pallet.
|
||||
///
|
||||
/// Each pallet version is stored in the state under a fixed key. See
|
||||
/// [`PALLET_VERSION_STORAGE_KEY_POSTFIX`] for how this key is built.
|
||||
#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Ord, Clone, Copy)]
|
||||
pub struct PalletVersion {
|
||||
/// The major version of the pallet.
|
||||
pub major: u16,
|
||||
/// The minor version of the pallet.
|
||||
pub minor: u8,
|
||||
/// The patch version of the pallet.
|
||||
pub patch: u8,
|
||||
}
|
||||
/// Each storage version of a pallet is stored in the state under a fixed key. See
|
||||
/// [`STORAGE_VERSION_STORAGE_KEY_POSTFIX`] for how this key is built.
|
||||
#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Ord, Clone, Copy, PartialOrd, Default)]
|
||||
pub struct StorageVersion(u16);
|
||||
|
||||
impl PalletVersion {
|
||||
impl StorageVersion {
|
||||
/// Creates a new instance of `Self`.
|
||||
pub fn new(major: u16, minor: u8, patch: u8) -> Self {
|
||||
Self { major, minor, patch }
|
||||
pub const fn new(version: u16) -> Self {
|
||||
Self(version)
|
||||
}
|
||||
|
||||
/// Returns the storage key for a pallet version.
|
||||
/// Returns the storage key for a storage version.
|
||||
///
|
||||
/// See [`PALLET_VERSION_STORAGE_KEY_POSTFIX`] on how this key is built.
|
||||
///
|
||||
/// Returns `None` if the given `PI` returned a `None` as name for the given
|
||||
/// `Pallet`.
|
||||
pub fn storage_key<PI: PalletInfo, Pallet: 'static>() -> Option<[u8; 32]> {
|
||||
let pallet_name = PI::name::<Pallet>()?;
|
||||
/// See [`STORAGE_VERSION_STORAGE_KEY_POSTFIX`] on how this key is built.
|
||||
pub fn storage_key<P: PalletInfoAccess>() -> [u8; 32] {
|
||||
let pallet_name = P::name();
|
||||
|
||||
let pallet_name = sp_io::hashing::twox_128(pallet_name.as_bytes());
|
||||
let postfix = sp_io::hashing::twox_128(PALLET_VERSION_STORAGE_KEY_POSTFIX);
|
||||
let postfix = sp_io::hashing::twox_128(STORAGE_VERSION_STORAGE_KEY_POSTFIX);
|
||||
|
||||
let mut final_key = [0u8; 32];
|
||||
final_key[..16].copy_from_slice(&pallet_name);
|
||||
final_key[16..].copy_from_slice(&postfix);
|
||||
|
||||
Some(final_key)
|
||||
final_key
|
||||
}
|
||||
|
||||
/// Put this pallet version into the storage.
|
||||
/// Put this storage version for the given pallet into the storage.
|
||||
///
|
||||
/// It will use the storage key that is associated with the given `Pallet`.
|
||||
///
|
||||
@@ -125,47 +115,75 @@ impl PalletVersion {
|
||||
///
|
||||
/// It will also panic if this function isn't executed in an externalities
|
||||
/// provided environment.
|
||||
pub fn put_into_storage<PI: PalletInfo, Pallet: 'static>(&self) {
|
||||
let key = Self::storage_key::<PI, Pallet>()
|
||||
.expect("Every active pallet has a name in the runtime; qed");
|
||||
pub fn put<P: PalletInfoAccess>(&self) {
|
||||
let key = Self::storage_key::<P>();
|
||||
|
||||
crate::storage::unhashed::put(&key, self);
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_std::cmp::PartialOrd for PalletVersion {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<sp_std::cmp::Ordering> {
|
||||
let res = self
|
||||
.major
|
||||
.cmp(&other.major)
|
||||
.then_with(|| self.minor.cmp(&other.minor).then_with(|| self.patch.cmp(&other.patch)));
|
||||
/// Get the storage version of the given pallet from the storage.
|
||||
///
|
||||
/// It will use the storage key that is associated with the given `Pallet`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic iff `Pallet` can not be found by `PalletInfo`.
|
||||
/// In a runtime that is put together using
|
||||
/// [`construct_runtime!`](crate::construct_runtime) this should never happen.
|
||||
///
|
||||
/// It will also panic if this function isn't executed in an externalities
|
||||
/// provided environment.
|
||||
pub fn get<P: PalletInfoAccess>() -> Self {
|
||||
let key = Self::storage_key::<P>();
|
||||
|
||||
Some(res)
|
||||
crate::storage::unhashed::get_or_default(&key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides version information about a pallet.
|
||||
///
|
||||
/// This trait provides two functions for returning the version of a
|
||||
/// pallet. There is a state where both functions can return distinct versions.
|
||||
/// See [`GetPalletVersion::storage_version`] for more information about this.
|
||||
pub trait GetPalletVersion {
|
||||
/// Returns the current version of the pallet.
|
||||
fn current_version() -> PalletVersion;
|
||||
|
||||
/// Returns the version of the pallet that is stored in storage.
|
||||
///
|
||||
/// Most of the time this will return the exact same version as
|
||||
/// [`GetPalletVersion::current_version`]. Only when being in
|
||||
/// a state after a runtime upgrade happened and the pallet did
|
||||
/// not yet updated its version in storage, this will return a
|
||||
/// different(the previous, seen from the time of calling) version.
|
||||
///
|
||||
/// See [`PalletVersion`] for more information.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If there was no previous version of the pallet stored in the state,
|
||||
/// this function returns `None`.
|
||||
fn storage_version() -> Option<PalletVersion>;
|
||||
impl PartialEq<u16> for StorageVersion {
|
||||
fn eq(&self, other: &u16) -> bool {
|
||||
self.0 == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<u16> for StorageVersion {
|
||||
fn partial_cmp(&self, other: &u16) -> Option<sp_std::cmp::Ordering> {
|
||||
Some(self.0.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides information about the storage version of a pallet.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// It is required to update the on-chain storage version manually when a migration was applied.
|
||||
pub trait GetStorageVersion {
|
||||
/// Returns the current storage version as supported by the pallet.
|
||||
fn current_storage_version() -> StorageVersion;
|
||||
/// Returns the on-chain storage version of the pallet as stored in the storage.
|
||||
fn on_chain_storage_version() -> StorageVersion;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn check_storage_version_ordering() {
|
||||
let version = StorageVersion::new(1);
|
||||
assert!(version == StorageVersion::new(1));
|
||||
assert!(version < StorageVersion::new(2));
|
||||
assert!(version < StorageVersion::new(3));
|
||||
|
||||
let version = StorageVersion::new(2);
|
||||
assert!(version < StorageVersion::new(3));
|
||||
assert!(version > StorageVersion::new(1));
|
||||
assert!(version < StorageVersion::new(5));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user