Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Use #[pallet::storage_version] for pallet staking #12728

Merged
merged 15 commits into from
Jan 3, 2023
Merged
25 changes: 0 additions & 25 deletions frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,31 +877,6 @@ impl Default for Forcing {
}
}

// A value placed in storage that represents the current version of the Staking storage. This value
// is used by the `on_runtime_upgrade` logic to determine whether we run storage migration logic.
// This should match directly with the semantic versions of the Rust crate.
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
enum Releases {
V1_0_0Ancient,
V2_0_0,
V3_0_0,
V4_0_0,
V5_0_0, // blockable validators.
V6_0_0, // removal of all storage associated with offchain phragmen.
V7_0_0, // keep track of number of nominators / validators in map
V8_0_0, // populate `VoterList`.
V9_0_0, // inject validators into `VoterList` as well.
V10_0_0, // remove `EarliestUnappliedSlash`.
V11_0_0, // Move pallet storage prefix, e.g. BagsList -> VoterBagsList
V12_0_0, // remove `HistoryDepth`.
}

impl Default for Releases {
fn default() -> Self {
Releases::V11_0_0
}
}

/// A `Convert` implementation that finds the stash of the given controller account,
/// if any.
pub struct StashOf<T>(sp_std::marker::PhantomData<T>);
Expand Down
133 changes: 105 additions & 28 deletions frame/staking/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,65 @@
use super::*;
use frame_election_provider_support::SortedListProvider;
use frame_support::traits::OnRuntimeUpgrade;
use frame_support::dispatch::GetStorageVersion;

pub mod v13 {
use super::*;
use frame_support::{pallet_prelude::ValueQuery, storage_alias};

#[storage_alias]
type StorageVersion<T: Config> = StorageValue<Pallet<T>, Releases, ValueQuery>;

#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
enum Releases {
Ank4n marked this conversation as resolved.
Show resolved Hide resolved
V12_0_0,
Ank4n marked this conversation as resolved.
Show resolved Hide resolved
}
pub struct MigrateToV13<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for MigrateToV13<T> {
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == Releases::V12_0_0,
"Required v12 before upgrading to v13"
);

Ok(Default::default())
}

fn on_runtime_upgrade() -> frame_support::weights::Weight {
let current = Pallet::<T>::current_storage_version();
let onchain = StorageVersion::<T>::get();

if current == 13 && onchain == Releases::V12_0_0 {
StorageVersion::<T>::kill();
current.put::<Pallet<T>>();

log!(info, "v13 applied successfully");
T::DbWeight::get().reads_writes(1, 2)
} else {
log!(warn, "Skipping v13, should be removed");
melekes marked this conversation as resolved.
Show resolved Hide resolved
T::DbWeight::get().reads(1)
}
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
frame_support::ensure!(
Pallet::<T>::on_chain_storage_version() == 13,
"v13 not applied"
);

frame_support::ensure!(
!StorageVersion::<T>::exists(),
"Storage version not migrated correctly"
);

Ok(())
}

}

}

pub mod v12 {
use super::*;
Expand All @@ -36,7 +95,7 @@ pub mod v12 {
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == Releases::V11_0_0,
Pallet::<T>::on_chain_storage_version() == 11,
"Expected v11 before upgrading to v12"
);

Expand All @@ -53,9 +112,12 @@ pub mod v12 {
}

fn on_runtime_upgrade() -> frame_support::weights::Weight {
if StorageVersion::<T>::get() == Releases::V11_0_0 {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

if current == 12 && onchain == 11 {
HistoryDepth::<T>::kill();
StorageVersion::<T>::put(Releases::V12_0_0);
current.put::<Pallet<T>>();

log!(info, "v12 applied successfully");
T::DbWeight::get().reads_writes(1, 2)
Expand All @@ -68,7 +130,7 @@ pub mod v12 {
#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == crate::Releases::V12_0_0,
Pallet::<T>::on_chain_storage_version() == 12,
"v12 not applied"
);
Ok(())
Expand All @@ -92,7 +154,7 @@ pub mod v11 {
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == crate::Releases::V10_0_0,
Pallet::<T>::on_chain_storage_version() == 10,
"must upgrade linearly"
);
let old_pallet_prefix = twox_128(N::get().as_bytes());
Expand All @@ -114,12 +176,15 @@ pub mod v11 {
/// The migration will look into the storage version in order to avoid triggering a
/// migration on an up to date storage.
fn on_runtime_upgrade() -> Weight {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

let old_pallet_name = N::get();
let new_pallet_name = <P as PalletInfoAccess>::name();

if StorageVersion::<T>::get() == Releases::V10_0_0 {
if current == 11 && onchain == 10 {
// bump version anyway, even if we don't need to move the prefix
StorageVersion::<T>::put(Releases::V11_0_0);
current.put::<Pallet<T>>();
if new_pallet_name == old_pallet_name {
log!(
warn,
Expand All @@ -139,7 +204,7 @@ pub mod v11 {
#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == crate::Releases::V11_0_0,
Pallet::<T>::on_chain_storage_version() == 11,
"wrong version after the upgrade"
);

Expand Down Expand Up @@ -184,7 +249,10 @@ pub mod v10 {
pub struct MigrateToV10<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for MigrateToV10<T> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
if StorageVersion::<T>::get() == Releases::V9_0_0 {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

if current == 10 && onchain == 9 {
let pending_slashes = <Pallet<T> as Store>::UnappliedSlashes::iter().take(512);
for (era, slashes) in pending_slashes {
for slash in slashes {
Expand All @@ -196,7 +264,7 @@ pub mod v10 {
}

EarliestUnappliedSlash::<T>::kill();
StorageVersion::<T>::put(Releases::V10_0_0);
current.put::<Pallet<T>>();

log!(info, "MigrateToV10 executed successfully");
T::DbWeight::get().reads_writes(1, 1)
Expand All @@ -221,7 +289,10 @@ pub mod v9 {
pub struct InjectValidatorsIntoVoterList<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for InjectValidatorsIntoVoterList<T> {
fn on_runtime_upgrade() -> Weight {
if StorageVersion::<T>::get() == Releases::V8_0_0 {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

if current == 9 && onchain == 8 {
let prev_count = T::VoterList::count();
let weight_of_cached = Pallet::<T>::weight_of_fn();
for (v, _) in Validators::<T>::iter() {
Expand All @@ -239,13 +310,13 @@ pub mod v9 {
T::VoterList::count(),
);

StorageVersion::<T>::put(crate::Releases::V9_0_0);
current.put::<Pallet<T>>();
T::BlockWeights::get().max_block
} else {
log!(
warn,
"InjectValidatorsIntoVoterList being executed on the wrong storage \
version, expected Releases::V8_0_0"
version, expected 8"
);
T::DbWeight::get().reads(1)
}
Expand All @@ -254,7 +325,7 @@ pub mod v9 {
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == crate::Releases::V8_0_0,
Pallet::<T>::on_chain_storage_version() == 8,
"must upgrade linearly"
);

Expand All @@ -272,7 +343,7 @@ pub mod v9 {
assert!(post_count == prev_count + validators);

frame_support::ensure!(
StorageVersion::<T>::get() == crate::Releases::V9_0_0,
Pallet::<T>::on_chain_storage_version() == 9,
"must upgrade "
);
Ok(())
Expand All @@ -281,14 +352,15 @@ pub mod v9 {
}

pub mod v8 {
use crate::{Config, Nominators, Pallet, StorageVersion, Weight};
use super::*;
use crate::{Config, Nominators, Pallet, Weight};
use frame_election_provider_support::SortedListProvider;
use frame_support::traits::Get;
use frame_support::traits::{Get};

#[cfg(feature = "try-runtime")]
pub fn pre_migrate<T: Config>() -> Result<(), &'static str> {
frame_support::ensure!(
StorageVersion::<T>::get() == crate::Releases::V7_0_0,
Pallet::<T>::on_chain_storage_version() == 7
"must upgrade linearly"
);

Expand All @@ -298,19 +370,22 @@ pub mod v8 {

/// Migration to sorted `VoterList`.
pub fn migrate<T: Config>() -> Weight {
if StorageVersion::<T>::get() == crate::Releases::V7_0_0 {
crate::log!(info, "migrating staking to Releases::V8_0_0");
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

if current == 8 && onchain == 7 {
crate::log!(info, "migrating staking to 8");

let migrated = T::VoterList::unsafe_regenerate(
Nominators::<T>::iter().map(|(id, _)| id),
Pallet::<T>::weight_of_fn(),
);
debug_assert_eq!(T::VoterList::try_state(), Ok(()));

StorageVersion::<T>::put(crate::Releases::V8_0_0);
current.put::<Pallet<T>>();
crate::log!(
info,
"👜 completed staking migration to Releases::V8_0_0 with {} voters migrated",
"👜 completed staking migration to 8_with {} voters migrated",
migrated,
);

Expand Down Expand Up @@ -348,20 +423,21 @@ pub mod v7 {
);
assert!(Validators::<T>::count().is_zero(), "Validators already set.");
assert!(Nominators::<T>::count().is_zero(), "Nominators already set.");
assert!(StorageVersion::<T>::get() == Releases::V6_0_0);
assert!(Pallet::<T>::on_chain_storage_version() == 6);
Ok(())
}

pub fn migrate<T: Config>() -> Weight {
log!(info, "Migrating staking to Releases::V7_0_0");
log!(info, "Migrating staking to 7");
let validator_count = Validators::<T>::iter().count() as u32;
let nominator_count = Nominators::<T>::iter().count() as u32;

CounterForValidators::<T>::put(validator_count);
CounterForNominators::<T>::put(nominator_count);

StorageVersion::<T>::put(Releases::V7_0_0);
log!(info, "Completed staking migration to Releases::V7_0_0");
Pallet::<T>::current_storage_version().put::<Pallet<T>>();

log!(info, "Completed staking migration to 7");

T::DbWeight::get().reads_writes(validator_count.saturating_add(nominator_count).into(), 2)
}
Expand Down Expand Up @@ -403,7 +479,7 @@ pub mod v6 {

/// Migrate storage to v6.
pub fn migrate<T: Config>() -> Weight {
log!(info, "Migrating staking to Releases::V6_0_0");
log!(info, "Migrating staking to 6");

SnapshotValidators::<T>::kill();
SnapshotNominators::<T>::kill();
Expand All @@ -412,7 +488,8 @@ pub mod v6 {
EraElectionStatus::<T>::kill();
IsCurrentSessionFinal::<T>::kill();

StorageVersion::<T>::put(Releases::V6_0_0);
Pallet::<T>::current_storage_version().put::<Pallet<T>>();

log!(info, "Done.");
T::DbWeight::get().writes(6 + 1)
}
Expand Down
14 changes: 5 additions & 9 deletions frame/staking/src/pallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub use impls::*;
use crate::{
slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout,
EraRewardPoints, Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf,
Releases, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk,
RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk,
ValidatorPrefs,
};

Expand All @@ -58,8 +58,12 @@ pub mod pallet {

use super::*;

/// The current storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(12);
Ank4n marked this conversation as resolved.
Show resolved Hide resolved

#[pallet::pallet]
#[pallet::generate_store(pub(crate) trait Store)]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);

/// Possible operations on the configuration values of this pallet.
Expand Down Expand Up @@ -550,13 +554,6 @@ pub mod pallet {
#[pallet::getter(fn offending_validators)]
pub type OffendingValidators<T: Config> = StorageValue<_, Vec<(u32, bool)>, ValueQuery>;

/// True if network has been upgraded to this version.
/// Storage version of the pallet.
///
/// This is set to v7.0.0 for new networks.
#[pallet::storage]
pub(crate) type StorageVersion<T: Config> = StorageValue<_, Releases, ValueQuery>;

/// The threshold for when users can start calling `chill_other` for other validators /
/// nominators. The threshold is compared to the actual number of validators / nominators
/// (`CountFor*`) in the system compared to the configured max (`Max*Count`).
Expand Down Expand Up @@ -607,7 +604,6 @@ pub mod pallet {
ForceEra::<T>::put(self.force_era);
CanceledSlashPayout::<T>::put(self.canceled_payout);
SlashRewardFraction::<T>::put(self.slash_reward_fraction);
StorageVersion::<T>::put(Releases::V7_0_0);
MinNominatorBond::<T>::put(self.min_nominator_bond);
MinValidatorBond::<T>::put(self.min_validator_bond);
if let Some(x) = self.max_validator_count {
Expand Down