mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 19:17: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:
@@ -19,9 +19,10 @@ use frame_support::{
|
||||
dispatch::{Parameter, UnfilteredDispatchable},
|
||||
storage::unhashed,
|
||||
traits::{
|
||||
GetCallName, GetPalletVersion, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade,
|
||||
GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade,
|
||||
PalletInfoAccess, StorageVersion,
|
||||
},
|
||||
weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays},
|
||||
weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays, RuntimeDbWeight},
|
||||
};
|
||||
use sp_io::{
|
||||
hashing::{blake2_128, twox_128, twox_64},
|
||||
@@ -96,13 +97,15 @@ impl SomeAssociation2 for u64 {
|
||||
pub mod pallet {
|
||||
use super::{
|
||||
SomeAssociation1, SomeAssociation2, SomeType1, SomeType2, SomeType3, SomeType4, SomeType5,
|
||||
SomeType6, SomeType7,
|
||||
SomeType6, SomeType7, StorageVersion,
|
||||
};
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
type BalanceOf<T> = <T as Config>::Balance;
|
||||
|
||||
pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(10);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config
|
||||
where
|
||||
@@ -146,6 +149,7 @@ pub mod pallet {
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(crate) trait Store)]
|
||||
#[pallet::generate_storage_info]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::hooks]
|
||||
@@ -896,12 +900,7 @@ fn pallet_hooks_expand() {
|
||||
assert_eq!(AllPallets::on_initialize(1), 10);
|
||||
AllPallets::on_finalize(1);
|
||||
|
||||
assert_eq!(pallet::Pallet::<Runtime>::storage_version(), None);
|
||||
assert_eq!(AllPallets::on_runtime_upgrade(), 30);
|
||||
assert_eq!(
|
||||
pallet::Pallet::<Runtime>::storage_version(),
|
||||
Some(pallet::Pallet::<Runtime>::current_version()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
frame_system::Pallet::<Runtime>::events()[0].event,
|
||||
@@ -921,15 +920,60 @@ fn pallet_hooks_expand() {
|
||||
#[test]
|
||||
fn pallet_on_genesis() {
|
||||
TestExternalities::default().execute_with(|| {
|
||||
assert_eq!(pallet::Pallet::<Runtime>::storage_version(), None);
|
||||
assert_eq!(pallet::Pallet::<Runtime>::on_chain_storage_version(), StorageVersion::new(0));
|
||||
pallet::Pallet::<Runtime>::on_genesis();
|
||||
assert_eq!(
|
||||
pallet::Pallet::<Runtime>::storage_version(),
|
||||
Some(pallet::Pallet::<Runtime>::current_version()),
|
||||
pallet::Pallet::<Runtime>::current_storage_version(),
|
||||
pallet::Pallet::<Runtime>::on_chain_storage_version(),
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn migrate_from_pallet_version_to_storage_version() {
|
||||
const PALLET_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__PALLET_VERSION__:";
|
||||
|
||||
fn pallet_version_key(name: &str) -> [u8; 32] {
|
||||
let pallet_name = sp_io::hashing::twox_128(name.as_bytes());
|
||||
let postfix = sp_io::hashing::twox_128(PALLET_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);
|
||||
|
||||
final_key
|
||||
}
|
||||
|
||||
TestExternalities::default().execute_with(|| {
|
||||
// Insert some fake pallet versions
|
||||
sp_io::storage::set(&pallet_version_key(Example::name()), &[1, 2, 3]);
|
||||
sp_io::storage::set(&pallet_version_key(Example2::name()), &[1, 2, 3]);
|
||||
sp_io::storage::set(&pallet_version_key(System::name()), &[1, 2, 3]);
|
||||
|
||||
// Check that everyone currently is at version 0
|
||||
assert_eq!(Example::on_chain_storage_version(), StorageVersion::new(0));
|
||||
assert_eq!(Example2::on_chain_storage_version(), StorageVersion::new(0));
|
||||
assert_eq!(System::on_chain_storage_version(), StorageVersion::new(0));
|
||||
|
||||
let db_weight = RuntimeDbWeight { read: 0, write: 5 };
|
||||
let weight = frame_support::migrations::migrate_from_pallet_version_to_storage_version::<
|
||||
AllPalletsWithSystem,
|
||||
>(&db_weight);
|
||||
|
||||
// 3 pallets, 2 writes and every write costs 5 weight.
|
||||
assert_eq!(3 * 2 * 5, weight);
|
||||
|
||||
// All pallet versions should be removed
|
||||
assert!(sp_io::storage::get(&pallet_version_key(Example::name())).is_none());
|
||||
assert!(sp_io::storage::get(&pallet_version_key(Example2::name())).is_none());
|
||||
assert!(sp_io::storage::get(&pallet_version_key(System::name())).is_none());
|
||||
|
||||
assert_eq!(Example::on_chain_storage_version(), pallet::STORAGE_VERSION);
|
||||
assert_eq!(Example2::on_chain_storage_version(), StorageVersion::new(0));
|
||||
assert_eq!(System::on_chain_storage_version(), StorageVersion::new(0));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn metadata() {
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
use frame_support::{
|
||||
dispatch::UnfilteredDispatchable,
|
||||
storage::unhashed,
|
||||
traits::{
|
||||
GetCallName, GetPalletVersion, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade,
|
||||
},
|
||||
traits::{GetCallName, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade},
|
||||
weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays},
|
||||
};
|
||||
use sp_io::{
|
||||
@@ -505,17 +503,7 @@ fn pallet_hooks_expand() {
|
||||
assert_eq!(AllPallets::on_initialize(1), 21);
|
||||
AllPallets::on_finalize(1);
|
||||
|
||||
assert_eq!(pallet::Pallet::<Runtime>::storage_version(), None);
|
||||
assert_eq!(pallet::Pallet::<Runtime, pallet::Instance1>::storage_version(), None);
|
||||
assert_eq!(AllPallets::on_runtime_upgrade(), 61);
|
||||
assert_eq!(
|
||||
pallet::Pallet::<Runtime>::storage_version(),
|
||||
Some(pallet::Pallet::<Runtime>::current_version()),
|
||||
);
|
||||
assert_eq!(
|
||||
pallet::Pallet::<Runtime, pallet::Instance1>::storage_version(),
|
||||
Some(pallet::Pallet::<Runtime, pallet::Instance1>::current_version()),
|
||||
);
|
||||
|
||||
// The order is indeed reversed due to https://github.com/paritytech/substrate/issues/6280
|
||||
assert_eq!(
|
||||
@@ -548,19 +536,9 @@ fn pallet_hooks_expand() {
|
||||
#[test]
|
||||
fn pallet_on_genesis() {
|
||||
TestExternalities::default().execute_with(|| {
|
||||
assert_eq!(pallet::Pallet::<Runtime>::storage_version(), None);
|
||||
pallet::Pallet::<Runtime>::on_genesis();
|
||||
assert_eq!(
|
||||
pallet::Pallet::<Runtime>::storage_version(),
|
||||
Some(pallet::Pallet::<Runtime>::current_version()),
|
||||
);
|
||||
|
||||
assert_eq!(pallet::Pallet::<Runtime, pallet::Instance1>::storage_version(), None);
|
||||
pallet::Pallet::<Runtime, pallet::Instance1>::on_genesis();
|
||||
assert_eq!(
|
||||
pallet::Pallet::<Runtime, pallet::Instance1>::storage_version(),
|
||||
Some(pallet::Pallet::<Runtime, pallet::Instance1>::current_version()),
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Tests related to the pallet version.
|
||||
|
||||
#![recursion_limit = "128"]
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
crate_to_pallet_version,
|
||||
traits::{
|
||||
GetPalletVersion, OnRuntimeUpgrade, PalletVersion, PALLET_VERSION_STORAGE_KEY_POSTFIX,
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
use sp_core::{sr25519, H256};
|
||||
use sp_runtime::{
|
||||
generic,
|
||||
traits::{BlakeTwo256, Verify},
|
||||
BuildStorage,
|
||||
};
|
||||
|
||||
/// A version that we will check for in the tests
|
||||
const SOME_TEST_VERSION: PalletVersion = PalletVersion { major: 3000, minor: 30, patch: 13 };
|
||||
|
||||
/// Checks that `on_runtime_upgrade` sets the latest pallet version when being called without
|
||||
/// being provided by the user.
|
||||
mod module1 {
|
||||
pub trait Config: frame_system::Config {}
|
||||
|
||||
frame_support::decl_module! {
|
||||
pub struct Module<T: Config> for enum Call where
|
||||
origin: <T as frame_system::Config>::Origin,
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that `on_runtime_upgrade` sets the latest pallet version when being called and also
|
||||
/// being provided by the user.
|
||||
mod module2 {
|
||||
use super::*;
|
||||
|
||||
pub trait Config<I = DefaultInstance>: frame_system::Config {}
|
||||
|
||||
frame_support::decl_module! {
|
||||
pub struct Module<T: Config<I>, I: Instance=DefaultInstance> for enum Call where
|
||||
origin: <T as frame_system::Config>::Origin,
|
||||
{
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
assert_eq!(crate_to_pallet_version!(), Self::current_version());
|
||||
|
||||
let version_key = PalletVersion::storage_key::<T::PalletInfo, Self>().unwrap();
|
||||
let version_value = sp_io::storage::get(&version_key);
|
||||
|
||||
if version_value.is_some() {
|
||||
assert_eq!(SOME_TEST_VERSION, Self::storage_version().unwrap());
|
||||
} else {
|
||||
// As the storage version does not exist yet, it should be `None`.
|
||||
assert!(Self::storage_version().is_none());
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::decl_storage! {
|
||||
trait Store for Module<T: Config<I>, I: Instance=DefaultInstance> as Module2 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
mod pallet3 {
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {}
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
mod pallet4 {
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config<I: 'static = ()>: frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {}
|
||||
}
|
||||
|
||||
impl module1::Config for Runtime {}
|
||||
impl module2::Config for Runtime {}
|
||||
impl module2::Config<module2::Instance1> for Runtime {}
|
||||
impl module2::Config<module2::Instance2> for Runtime {}
|
||||
|
||||
impl pallet3::Config for Runtime {}
|
||||
impl pallet4::Config for Runtime {}
|
||||
impl pallet4::Config<pallet4::Instance1> for Runtime {}
|
||||
impl pallet4::Config<pallet4::Instance2> for Runtime {}
|
||||
|
||||
pub type Signature = sr25519::Signature;
|
||||
pub type AccountId = <Signature as Verify>::Signer;
|
||||
pub type BlockNumber = u64;
|
||||
pub type Index = u64;
|
||||
|
||||
frame_support::parameter_types!(
|
||||
pub const BlockHashCount: u32 = 250;
|
||||
);
|
||||
|
||||
impl frame_system::Config for Runtime {
|
||||
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Call = Call;
|
||||
type Hash = H256;
|
||||
type Hashing = sp_runtime::traits::BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = sp_runtime::traits::IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = Event;
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = ();
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
}
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Event<T>},
|
||||
Module1: module1::{Pallet, Call},
|
||||
Module2: module2::{Pallet, Call},
|
||||
Module2_1: module2::<Instance1>::{Pallet, Call},
|
||||
Module2_2: module2::<Instance2>::{Pallet, Call},
|
||||
Pallet3: pallet3::{Pallet, Call},
|
||||
Pallet4: pallet4::{Pallet, Call},
|
||||
Pallet4_1: pallet4::<Instance1>::{Pallet, Call},
|
||||
Pallet4_2: pallet4::<Instance2>::{Pallet, Call},
|
||||
}
|
||||
);
|
||||
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
|
||||
|
||||
/// Returns the storage key for `PalletVersion` for the given `pallet`.
|
||||
fn get_pallet_version_storage_key_for_pallet(pallet: &str) -> [u8; 32] {
|
||||
let pallet_name = sp_io::hashing::twox_128(pallet.as_bytes());
|
||||
let postfix = sp_io::hashing::twox_128(PALLET_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);
|
||||
|
||||
final_key
|
||||
}
|
||||
|
||||
/// Checks the version of the given `pallet`.
|
||||
///
|
||||
/// It is expected that the pallet version can be found in the storage and equals the
|
||||
/// current crate version.
|
||||
fn check_pallet_version(pallet: &str) {
|
||||
let key = get_pallet_version_storage_key_for_pallet(pallet);
|
||||
let value = sp_io::storage::get(&key).expect("Pallet version exists");
|
||||
let version =
|
||||
PalletVersion::decode(&mut &value[..]).expect("Pallet version is encoded correctly");
|
||||
|
||||
assert_eq!(crate_to_pallet_version!(), version);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn on_runtime_upgrade_sets_the_pallet_versions_in_storage() {
|
||||
sp_io::TestExternalities::new_empty().execute_with(|| {
|
||||
AllPallets::on_runtime_upgrade();
|
||||
|
||||
check_pallet_version("Module1");
|
||||
check_pallet_version("Module2");
|
||||
check_pallet_version("Module2_1");
|
||||
check_pallet_version("Module2_2");
|
||||
check_pallet_version("Pallet3");
|
||||
check_pallet_version("Pallet4");
|
||||
check_pallet_version("Pallet4_1");
|
||||
check_pallet_version("Pallet4_2");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn on_runtime_upgrade_overwrites_old_version() {
|
||||
sp_io::TestExternalities::new_empty().execute_with(|| {
|
||||
let key = get_pallet_version_storage_key_for_pallet("Module2");
|
||||
sp_io::storage::set(&key, &SOME_TEST_VERSION.encode());
|
||||
|
||||
AllPallets::on_runtime_upgrade();
|
||||
|
||||
check_pallet_version("Module1");
|
||||
check_pallet_version("Module2");
|
||||
check_pallet_version("Module2_1");
|
||||
check_pallet_version("Module2_2");
|
||||
check_pallet_version("Pallet3");
|
||||
check_pallet_version("Pallet4");
|
||||
check_pallet_version("Pallet4_1");
|
||||
check_pallet_version("Pallet4_2");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn genesis_init_puts_pallet_version_into_storage() {
|
||||
let storage = GenesisConfig::default().build_storage().expect("Builds genesis storage");
|
||||
|
||||
sp_io::TestExternalities::new(storage).execute_with(|| {
|
||||
check_pallet_version("Module1");
|
||||
check_pallet_version("Module2");
|
||||
check_pallet_version("Module2_1");
|
||||
check_pallet_version("Module2_2");
|
||||
check_pallet_version("Pallet3");
|
||||
check_pallet_version("Pallet4");
|
||||
check_pallet_version("Pallet4_1");
|
||||
check_pallet_version("Pallet4_2");
|
||||
|
||||
let system_version = System::storage_version().expect("System version should be set");
|
||||
assert_eq!(System::current_version(), system_version);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user