mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 10:17:57 +00:00
BREAKING - Try-runtime: Use proper error types (#13993)
* Try-state: DispatchResult as return type * try_state for the rest of the pallets * pre_upgrade * post_upgrade * try_runtime_upgrade * fixes * bags-list fix * fix * update test * warning fix * ... * final fixes 🤞 * warning.. * frame-support * warnings * Update frame/staking/src/migrations.rs Co-authored-by: Liam Aharon <liam.aharon@hotmail.com> * fix * fix warning * nit fix * merge fixes * small fix * should be good now * missed these ones * introduce TryRuntimeError and TryRuntimeResult * fixes * fix * removed TryRuntimeResult & made some fixes * fix testsg * tests passing * unnecessary imports * Update frame/assets/src/migration.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> --------- Co-authored-by: Liam Aharon <liam.aharon@hotmail.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
This commit is contained in:
@@ -18,6 +18,9 @@
|
||||
use super::*;
|
||||
use frame_support::{log, traits::OnRuntimeUpgrade};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
pub mod v1 {
|
||||
use frame_support::{pallet_prelude::*, weights::Weight};
|
||||
|
||||
@@ -92,7 +95,7 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() == 0,
|
||||
"must upgrade linearly"
|
||||
@@ -102,13 +105,13 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(prev_count: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(prev_count: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect(
|
||||
"the state parameter should be something that was generated by pre_upgrade",
|
||||
);
|
||||
let post_count = Asset::<T>::iter().count() as u32;
|
||||
assert_eq!(
|
||||
prev_count, post_count,
|
||||
ensure!(
|
||||
prev_count == post_count,
|
||||
"the asset count before and after the migration should be the same"
|
||||
);
|
||||
|
||||
@@ -116,17 +119,18 @@ pub mod v1 {
|
||||
let onchain_version = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
frame_support::ensure!(current_version == 1, "must_upgrade");
|
||||
assert_eq!(
|
||||
current_version, onchain_version,
|
||||
ensure!(
|
||||
current_version == onchain_version,
|
||||
"after migration, the current_version and onchain_version should be the same"
|
||||
);
|
||||
|
||||
Asset::<T>::iter().for_each(|(_id, asset)| {
|
||||
assert!(
|
||||
Asset::<T>::iter().try_for_each(|(_id, asset)| -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
asset.status == AssetStatus::Live || asset.status == AssetStatus::Frozen,
|
||||
"assets should only be live or frozen. None should be in destroying status, or undefined state"
|
||||
)
|
||||
});
|
||||
"assets should only be live or frozen. None should be in destroying status, or undefined state"
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ use frame_system::ensure_signed;
|
||||
use sp_runtime::traits::{AtLeast32BitUnsigned, Bounded, StaticLookup};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[cfg(any(feature = "runtime-benchmarks", test))]
|
||||
mod benchmarks;
|
||||
|
||||
@@ -267,7 +270,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
fn try_state(_: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
|
||||
<Self as SortedListProvider<T::AccountId>>::try_state()
|
||||
}
|
||||
}
|
||||
@@ -275,7 +278,7 @@ pub mod pallet {
|
||||
|
||||
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
pub fn do_try_state() -> Result<(), &'static str> {
|
||||
pub fn do_try_state() -> Result<(), TryRuntimeError> {
|
||||
List::<T, I>::do_try_state()
|
||||
}
|
||||
}
|
||||
@@ -355,7 +358,7 @@ impl<T: Config<I>, I: 'static> SortedListProvider<T::AccountId> for Pallet<T, I>
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state() -> Result<(), &'static str> {
|
||||
fn try_state() -> Result<(), TryRuntimeError> {
|
||||
Self::do_try_state()
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@ use sp_std::{
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo, PalletError)]
|
||||
pub enum ListError {
|
||||
/// A duplicate id has been detected.
|
||||
@@ -512,11 +515,11 @@ impl<T: Config<I>, I: 'static> List<T, I> {
|
||||
/// * and sanity-checks all bags and nodes. This will cascade down all the checks and makes sure
|
||||
/// all bags and nodes are checked per *any* update to `List`.
|
||||
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
|
||||
pub(crate) fn do_try_state() -> Result<(), &'static str> {
|
||||
pub(crate) fn do_try_state() -> Result<(), TryRuntimeError> {
|
||||
let mut seen_in_list = BTreeSet::new();
|
||||
ensure!(
|
||||
Self::iter().map(|node| node.id).all(|id| seen_in_list.insert(id)),
|
||||
"duplicate identified",
|
||||
"duplicate identified"
|
||||
);
|
||||
|
||||
let iter_count = Self::iter().count() as u32;
|
||||
@@ -750,7 +753,7 @@ impl<T: Config<I>, I: 'static> Bag<T, I> {
|
||||
/// * Ensures tail has no next.
|
||||
/// * Ensures there are no loops, traversal from head to tail is correct.
|
||||
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
|
||||
fn do_try_state(&self) -> Result<(), &'static str> {
|
||||
fn do_try_state(&self) -> Result<(), TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
self.head()
|
||||
.map(|head| head.prev().is_none())
|
||||
@@ -895,15 +898,12 @@ impl<T: Config<I>, I: 'static> Node<T, I> {
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
|
||||
fn do_try_state(&self) -> Result<(), &'static str> {
|
||||
fn do_try_state(&self) -> Result<(), TryRuntimeError> {
|
||||
let expected_bag = Bag::<T, I>::get(self.bag_upper).ok_or("bag not found for node")?;
|
||||
|
||||
let id = self.id();
|
||||
|
||||
frame_support::ensure!(
|
||||
expected_bag.contains(id),
|
||||
"node does not exist in the expected bag"
|
||||
);
|
||||
frame_support::ensure!(expected_bag.contains(id), "node does not exist in the bag");
|
||||
|
||||
let non_terminal_check = !self.is_terminal() &&
|
||||
expected_bag.head.as_ref() != Some(id) &&
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::{
|
||||
};
|
||||
use frame_election_provider_support::{SortedListProvider, VoteWeight};
|
||||
use frame_support::{assert_ok, assert_storage_noop};
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
fn node(
|
||||
id: AccountId,
|
||||
@@ -359,7 +360,10 @@ mod list {
|
||||
// make sure there are no duplicates.
|
||||
ExtBuilder::default().build_and_execute_no_post_check(|| {
|
||||
Bag::<Runtime>::get(10).unwrap().insert_unchecked(2, 10);
|
||||
assert_eq!(List::<Runtime>::do_try_state(), Err("duplicate identified"));
|
||||
assert_eq!(
|
||||
List::<Runtime>::do_try_state(),
|
||||
TryRuntimeError::Other("duplicate identified").into()
|
||||
);
|
||||
});
|
||||
|
||||
// ensure count is in sync with `ListNodes::count()`.
|
||||
@@ -373,7 +377,10 @@ mod list {
|
||||
CounterForListNodes::<Runtime>::mutate(|counter| *counter += 1);
|
||||
assert_eq!(crate::ListNodes::<Runtime>::count(), 5);
|
||||
|
||||
assert_eq!(List::<Runtime>::do_try_state(), Err("iter_count != stored_count"));
|
||||
assert_eq!(
|
||||
List::<Runtime>::do_try_state(),
|
||||
TryRuntimeError::Other("iter_count != stored_count").into()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ use frame_support::traits::OnRuntimeUpgrade;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
@@ -35,7 +38,7 @@ impl<T: crate::Config<I>, I: 'static> OnRuntimeUpgrade for CheckCounterPrefix<T,
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
// The old explicit storage item.
|
||||
#[frame_support::storage_alias]
|
||||
type CounterForListNodes<T: crate::Config<I>, I: 'static> =
|
||||
@@ -88,7 +91,7 @@ mod old {
|
||||
pub struct AddScore<T: crate::Config<I>, I: 'static = ()>(sp_std::marker::PhantomData<(T, I)>);
|
||||
impl<T: crate::Config<I>, I: 'static> OnRuntimeUpgrade for AddScore<T, I> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
// The list node data should be corrupt at this point, so this is zero.
|
||||
ensure!(crate::ListNodes::<T, I>::iter().count() == 0, "list node data is not corrupt");
|
||||
// We can use the helper `old::ListNode` to get the existing data.
|
||||
@@ -119,7 +122,7 @@ impl<T: crate::Config<I>, I: 'static> OnRuntimeUpgrade for AddScore<T, I> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(node_count_before: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(node_count_before: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let node_count_before: u32 = Decode::decode(&mut node_count_before.as_slice())
|
||||
.expect("the state parameter should be something that was generated by pre_upgrade");
|
||||
// Now the list node data is not corrupt anymore.
|
||||
|
||||
@@ -60,6 +60,9 @@ use frame_support::{
|
||||
weights::Weight,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "try-runtime", test))]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -346,9 +349,8 @@ pub mod pallet {
|
||||
#[pallet::hooks]
|
||||
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_n: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
Self::do_try_state()?;
|
||||
Ok(())
|
||||
fn try_state(_n: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
|
||||
Self::do_try_state()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,77 +969,78 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Looking at prime account:
|
||||
/// * The prime account must be a member of the collective.
|
||||
#[cfg(any(feature = "try-runtime", test))]
|
||||
fn do_try_state() -> DispatchResult {
|
||||
Self::proposals().into_iter().try_for_each(|proposal| -> DispatchResult {
|
||||
ensure!(
|
||||
Self::proposal_of(proposal).is_some(),
|
||||
DispatchError::Other(
|
||||
fn do_try_state() -> Result<(), TryRuntimeError> {
|
||||
Self::proposals()
|
||||
.into_iter()
|
||||
.try_for_each(|proposal| -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
Self::proposal_of(proposal).is_some(),
|
||||
"Proposal hash from `Proposals` is not found inside the `ProposalOf` mapping."
|
||||
)
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
ensure!(
|
||||
Self::proposals().into_iter().count() <= Self::proposal_count() as usize,
|
||||
DispatchError::Other("The actual number of proposals is greater than `ProposalCount`")
|
||||
"The actual number of proposals is greater than `ProposalCount`"
|
||||
);
|
||||
ensure!(
|
||||
Self::proposals().into_iter().count() == <ProposalOf<T, I>>::iter_keys().count(),
|
||||
DispatchError::Other("Proposal count inside `Proposals` is not equal to the proposal count in `ProposalOf`")
|
||||
"Proposal count inside `Proposals` is not equal to the proposal count in `ProposalOf`"
|
||||
);
|
||||
|
||||
Self::proposals().into_iter().try_for_each(|proposal| -> DispatchResult {
|
||||
if let Some(votes) = Self::voting(proposal) {
|
||||
let ayes = votes.ayes.len();
|
||||
let nays = votes.nays.len();
|
||||
Self::proposals()
|
||||
.into_iter()
|
||||
.try_for_each(|proposal| -> Result<(), TryRuntimeError> {
|
||||
if let Some(votes) = Self::voting(proposal) {
|
||||
let ayes = votes.ayes.len();
|
||||
let nays = votes.nays.len();
|
||||
|
||||
ensure!(
|
||||
ayes.saturating_add(nays) <= T::MaxMembers::get() as usize,
|
||||
DispatchError::Other("The sum of ayes and nays is greater than `MaxMembers`")
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
ensure!(
|
||||
ayes.saturating_add(nays) <= T::MaxMembers::get() as usize,
|
||||
"The sum of ayes and nays is greater than `MaxMembers`"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let mut proposal_indices = vec![];
|
||||
Self::proposals().into_iter().try_for_each(|proposal| -> DispatchResult {
|
||||
if let Some(votes) = Self::voting(proposal) {
|
||||
let proposal_index = votes.index;
|
||||
ensure!(
|
||||
!proposal_indices.contains(&proposal_index),
|
||||
DispatchError::Other("The proposal index is not unique.")
|
||||
);
|
||||
proposal_indices.push(proposal_index);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
Self::proposals()
|
||||
.into_iter()
|
||||
.try_for_each(|proposal| -> Result<(), TryRuntimeError> {
|
||||
if let Some(votes) = Self::voting(proposal) {
|
||||
let proposal_index = votes.index;
|
||||
ensure!(
|
||||
!proposal_indices.contains(&proposal_index),
|
||||
"The proposal index is not unique."
|
||||
);
|
||||
proposal_indices.push(proposal_index);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
<Voting<T, I>>::iter_keys().try_for_each(|proposal_hash| -> DispatchResult {
|
||||
ensure!(
|
||||
Self::proposals().contains(&proposal_hash),
|
||||
DispatchError::Other(
|
||||
<Voting<T, I>>::iter_keys().try_for_each(
|
||||
|proposal_hash| -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
Self::proposals().contains(&proposal_hash),
|
||||
"`Proposals` doesn't contain the proposal hash from the `Voting` storage map."
|
||||
)
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
ensure!(
|
||||
Self::members().len() <= T::MaxMembers::get() as usize,
|
||||
DispatchError::Other("The member count is greater than `MaxMembers`.")
|
||||
"The member count is greater than `MaxMembers`."
|
||||
);
|
||||
|
||||
ensure!(
|
||||
Self::members().windows(2).all(|members| members[0] <= members[1]),
|
||||
DispatchError::Other("The members are not sorted by value.")
|
||||
"The members are not sorted by value."
|
||||
);
|
||||
|
||||
if let Some(prime) = Self::prime() {
|
||||
ensure!(
|
||||
Self::members().contains(&prime),
|
||||
DispatchError::Other("Prime account is not a member.")
|
||||
);
|
||||
ensure!(Self::members().contains(&prime), "Prime account is not a member.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -28,6 +28,9 @@ use frame_support::{
|
||||
use sp_runtime::traits::Saturating;
|
||||
use sp_std::{marker::PhantomData, prelude::*};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// Performs all necessary migrations based on `StorageVersion`.
|
||||
pub struct Migration<T: Config>(PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
@@ -66,7 +69,7 @@ impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
let version = <Pallet<T>>::on_chain_storage_version();
|
||||
|
||||
if version == 7 {
|
||||
@@ -77,7 +80,7 @@ impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let version = Decode::decode(&mut state.as_ref()).map_err(|_| "Cannot decode version")?;
|
||||
post_checks::post_upgrade::<T>(version)
|
||||
}
|
||||
@@ -355,7 +358,7 @@ mod v8 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub fn pre_upgrade<T: Config>() -> Result<(), &'static str> {
|
||||
pub fn pre_upgrade<T: Config>() -> Result<(), TryRuntimeError> {
|
||||
use frame_support::traits::ReservableCurrency;
|
||||
for (key, value) in ContractInfoOf::<T, OldContractInfo<T>>::iter() {
|
||||
let reserved = T::Currency::reserved_balance(&key);
|
||||
@@ -418,7 +421,7 @@ mod post_checks {
|
||||
type ContractInfoOf<T: Config, V> =
|
||||
StorageMap<Pallet<T>, Twox64Concat, <T as frame_system::Config>::AccountId, V>;
|
||||
|
||||
pub fn post_upgrade<T: Config>(old_version: StorageVersion) -> Result<(), &'static str> {
|
||||
pub fn post_upgrade<T: Config>(old_version: StorageVersion) -> Result<(), TryRuntimeError> {
|
||||
if old_version < 7 {
|
||||
return Ok(())
|
||||
}
|
||||
@@ -434,7 +437,7 @@ mod post_checks {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn v8<T: Config>() -> Result<(), &'static str> {
|
||||
fn v8<T: Config>() -> Result<(), TryRuntimeError> {
|
||||
use frame_support::traits::ReservableCurrency;
|
||||
for (key, value) in ContractInfoOf::<T, ContractInfo<T>>::iter() {
|
||||
let reserved = T::Currency::reserved_balance(&key);
|
||||
@@ -455,13 +458,13 @@ mod post_checks {
|
||||
storage_bytes.saturating_accrue(len);
|
||||
storage_items.saturating_accrue(1);
|
||||
}
|
||||
ensure!(storage_bytes == value.storage_bytes, "Storage bytes do not match.",);
|
||||
ensure!(storage_items == value.storage_items, "Storage items do not match.",);
|
||||
ensure!(storage_bytes == value.storage_bytes, "Storage bytes do not match.");
|
||||
ensure!(storage_items == value.storage_items, "Storage items do not match.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn v9<T: Config>() -> Result<(), &'static str> {
|
||||
fn v9<T: Config>() -> Result<(), TryRuntimeError> {
|
||||
for value in CodeStorage::<T>::iter_values() {
|
||||
ensure!(
|
||||
value.determinism == Determinism::Enforced,
|
||||
|
||||
@@ -61,12 +61,12 @@ pub mod v1 {
|
||||
|
||||
impl<T: Config + frame_system::Config<Hash = H256>> OnRuntimeUpgrade for Migration<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 0, "can only upgrade from version 0");
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 0, "can only upgrade from version 0");
|
||||
|
||||
let props_count = v0::PublicProps::<T>::get().len();
|
||||
log::info!(target: TARGET, "{} public proposals will be migrated.", props_count,);
|
||||
ensure!(props_count <= T::MaxProposals::get() as usize, "too many proposals");
|
||||
ensure!(props_count <= T::MaxProposals::get() as usize, Error::<T>::TooMany);
|
||||
|
||||
let referenda_count = v0::ReferendumInfoOf::<T>::iter().count();
|
||||
log::info!(target: TARGET, "{} referenda will be migrated.", referenda_count);
|
||||
@@ -133,15 +133,15 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 1, "must upgrade");
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 1, "must upgrade");
|
||||
|
||||
let (old_props_count, old_ref_count): (u32, u32) =
|
||||
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
|
||||
let new_props_count = crate::PublicProps::<T>::get().len() as u32;
|
||||
assert_eq!(new_props_count, old_props_count, "must migrate all public proposals");
|
||||
ensure!(new_props_count == old_props_count, "must migrate all public proposals");
|
||||
let new_ref_count = crate::ReferendumInfoOf::<T>::iter().count() as u32;
|
||||
assert_eq!(new_ref_count, old_ref_count, "must migrate all referenda");
|
||||
ensure!(new_ref_count == old_ref_count, "must migrate all referenda");
|
||||
|
||||
log::info!(
|
||||
target: TARGET,
|
||||
|
||||
@@ -257,6 +257,9 @@ use sp_runtime::{
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
#[cfg(test)]
|
||||
@@ -883,7 +886,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_n: T::BlockNumber) -> Result<(), &'static str> {
|
||||
fn try_state(_n: T::BlockNumber) -> Result<(), TryRuntimeError> {
|
||||
Self::do_try_state()
|
||||
}
|
||||
}
|
||||
@@ -1579,7 +1582,7 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
impl<T: Config> Pallet<T> {
|
||||
fn do_try_state() -> Result<(), &'static str> {
|
||||
fn do_try_state() -> Result<(), TryRuntimeError> {
|
||||
Self::try_state_snapshot()?;
|
||||
Self::try_state_signed_submissions_map()?;
|
||||
Self::try_state_phase_off()
|
||||
@@ -1588,7 +1591,7 @@ impl<T: Config> Pallet<T> {
|
||||
// [`Snapshot`] state check. Invariants:
|
||||
// - [`DesiredTargets`] exists if and only if [`Snapshot`] is present.
|
||||
// - [`SnapshotMetadata`] exist if and only if [`Snapshot`] is present.
|
||||
fn try_state_snapshot() -> Result<(), &'static str> {
|
||||
fn try_state_snapshot() -> Result<(), TryRuntimeError> {
|
||||
if <Snapshot<T>>::exists() &&
|
||||
<SnapshotMetadata<T>>::exists() &&
|
||||
<DesiredTargets<T>>::exists()
|
||||
@@ -1600,7 +1603,7 @@ impl<T: Config> Pallet<T> {
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err("If snapshot exists, metadata and desired targets should be set too. Otherwise, none should be set.")
|
||||
Err("If snapshot exists, metadata and desired targets should be set too. Otherwise, none should be set.".into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1608,28 +1611,34 @@ impl<T: Config> Pallet<T> {
|
||||
// - All [`SignedSubmissionIndices`] are present in [`SignedSubmissionsMap`], and no more;
|
||||
// - [`SignedSubmissionNextIndex`] is not present in [`SignedSubmissionsMap`];
|
||||
// - [`SignedSubmissionIndices`] is sorted by election score.
|
||||
fn try_state_signed_submissions_map() -> Result<(), &'static str> {
|
||||
fn try_state_signed_submissions_map() -> Result<(), TryRuntimeError> {
|
||||
let mut last_score: ElectionScore = Default::default();
|
||||
let indices = <SignedSubmissionIndices<T>>::get();
|
||||
|
||||
for (i, indice) in indices.iter().enumerate() {
|
||||
let submission = <SignedSubmissionsMap<T>>::get(indice.2);
|
||||
if submission.is_none() {
|
||||
return Err("All signed submissions indices must be part of the submissions map")
|
||||
return Err(
|
||||
"All signed submissions indices must be part of the submissions map".into()
|
||||
)
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
last_score = indice.0
|
||||
} else {
|
||||
if last_score.strict_threshold_better(indice.0, Perbill::zero()) {
|
||||
return Err("Signed submission indices vector must be ordered by election score")
|
||||
return Err(
|
||||
"Signed submission indices vector must be ordered by election score".into()
|
||||
)
|
||||
}
|
||||
last_score = indice.0;
|
||||
}
|
||||
}
|
||||
|
||||
if <SignedSubmissionsMap<T>>::iter().nth(indices.len()).is_some() {
|
||||
return Err("Signed submissions map length should be the same as the indices vec length")
|
||||
return Err(
|
||||
"Signed submissions map length should be the same as the indices vec length".into()
|
||||
)
|
||||
}
|
||||
|
||||
match <SignedSubmissionNextIndex<T>>::get() {
|
||||
@@ -1637,7 +1646,8 @@ impl<T: Config> Pallet<T> {
|
||||
next =>
|
||||
if <SignedSubmissionsMap<T>>::get(next).is_some() {
|
||||
return Err(
|
||||
"The next submissions index should not be in the submissions maps already",
|
||||
"The next submissions index should not be in the submissions maps already"
|
||||
.into(),
|
||||
)
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -1647,12 +1657,12 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
// [`Phase::Off`] state check. Invariants:
|
||||
// - If phase is `Phase::Off`, [`Snapshot`] must be none.
|
||||
fn try_state_phase_off() -> Result<(), &'static str> {
|
||||
fn try_state_phase_off() -> Result<(), TryRuntimeError> {
|
||||
match Self::current_phase().is_off() {
|
||||
false => Ok(()),
|
||||
true =>
|
||||
if <Snapshot<T>>::get().is_some() {
|
||||
Err("Snapshot must be none when in Phase::Off")
|
||||
Err("Snapshot must be none when in Phase::Off".into())
|
||||
} else {
|
||||
Ok(())
|
||||
},
|
||||
|
||||
@@ -189,6 +189,9 @@ pub use sp_npos_elections::{
|
||||
};
|
||||
pub use traits::NposSolution;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
// re-export for the solution macro, with the dependencies of the macro.
|
||||
#[doc(hidden)]
|
||||
pub use codec;
|
||||
@@ -564,7 +567,7 @@ pub trait SortedListProvider<AccountId> {
|
||||
|
||||
/// Check internal state of the list. Only meant for debugging.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state() -> Result<(), &'static str>;
|
||||
fn try_state() -> Result<(), TryRuntimeError>;
|
||||
|
||||
/// If `who` changes by the returned amount they are guaranteed to have a worst case change
|
||||
/// in their list position.
|
||||
|
||||
@@ -115,6 +115,9 @@ use sp_runtime::{
|
||||
};
|
||||
use sp_std::{cmp::Ordering, prelude::*};
|
||||
|
||||
#[cfg(any(feature = "try-runtime", test))]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
mod benchmarking;
|
||||
pub mod weights;
|
||||
pub use weights::WeightInfo;
|
||||
@@ -327,7 +330,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_n: T::BlockNumber) -> Result<(), &'static str> {
|
||||
fn try_state(_n: T::BlockNumber) -> Result<(), TryRuntimeError> {
|
||||
Self::do_try_state()
|
||||
}
|
||||
}
|
||||
@@ -1193,7 +1196,7 @@ impl<T: Config> ContainsLengthBound for Pallet<T> {
|
||||
|
||||
#[cfg(any(feature = "try-runtime", test))]
|
||||
impl<T: Config> Pallet<T> {
|
||||
fn do_try_state() -> Result<(), &'static str> {
|
||||
fn do_try_state() -> Result<(), TryRuntimeError> {
|
||||
Self::try_state_members()?;
|
||||
Self::try_state_runners_up()?;
|
||||
Self::try_state_candidates()?;
|
||||
@@ -1204,20 +1207,20 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// [`Members`] state checks. Invariants:
|
||||
/// - Members are always sorted based on account ID.
|
||||
fn try_state_members() -> Result<(), &'static str> {
|
||||
fn try_state_members() -> Result<(), TryRuntimeError> {
|
||||
let mut members = Members::<T>::get().clone();
|
||||
members.sort_by_key(|m| m.who.clone());
|
||||
|
||||
if Members::<T>::get() == members {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("try_state checks: Members must be always sorted by account ID")
|
||||
Err("try_state checks: Members must be always sorted by account ID".into())
|
||||
}
|
||||
}
|
||||
|
||||
// [`RunnersUp`] state checks. Invariants:
|
||||
// - Elements are sorted based on weight (worst to best).
|
||||
fn try_state_runners_up() -> Result<(), &'static str> {
|
||||
fn try_state_runners_up() -> Result<(), TryRuntimeError> {
|
||||
let mut sorted = RunnersUp::<T>::get();
|
||||
// worst stake first
|
||||
sorted.sort_by(|a, b| a.stake.cmp(&b.stake));
|
||||
@@ -1225,27 +1228,28 @@ impl<T: Config> Pallet<T> {
|
||||
if RunnersUp::<T>::get() == sorted {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("try_state checks: Runners Up must always be sorted by stake (worst to best)")
|
||||
Err("try_state checks: Runners Up must always be sorted by stake (worst to best)"
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
// [`Candidates`] state checks. Invariants:
|
||||
// - Always sorted based on account ID.
|
||||
fn try_state_candidates() -> Result<(), &'static str> {
|
||||
fn try_state_candidates() -> Result<(), TryRuntimeError> {
|
||||
let mut candidates = Candidates::<T>::get().clone();
|
||||
candidates.sort_by_key(|(c, _)| c.clone());
|
||||
|
||||
if Candidates::<T>::get() == candidates {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("try_state checks: Candidates must be always sorted by account ID")
|
||||
Err("try_state checks: Candidates must be always sorted by account ID".into())
|
||||
}
|
||||
}
|
||||
// [`Candidates`] and [`RunnersUp`] state checks. Invariants:
|
||||
// - Candidates and runners-ups sets are disjoint.
|
||||
fn try_state_candidates_runners_up_disjoint() -> Result<(), &'static str> {
|
||||
fn try_state_candidates_runners_up_disjoint() -> Result<(), TryRuntimeError> {
|
||||
match Self::intersects(&Self::candidates_ids(), &Self::runners_up_ids()) {
|
||||
true => Err("Candidates and runners up sets should always be disjoint"),
|
||||
true => Err("Candidates and runners up sets should always be disjoint".into()),
|
||||
false => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -1253,11 +1257,12 @@ impl<T: Config> Pallet<T> {
|
||||
// [`Members`], [`Candidates`] and [`RunnersUp`] state checks. Invariants:
|
||||
// - Members and candidates sets are disjoint;
|
||||
// - Members and runners-ups sets are disjoint.
|
||||
fn try_state_members_disjoint() -> Result<(), &'static str> {
|
||||
fn try_state_members_disjoint() -> Result<(), TryRuntimeError> {
|
||||
match Self::intersects(&Pallet::<T>::members_ids(), &Self::candidates_ids()) &&
|
||||
Self::intersects(&Pallet::<T>::members_ids(), &Self::runners_up_ids())
|
||||
{
|
||||
true => Err("Members set should be disjoint from candidates and runners-up sets"),
|
||||
true =>
|
||||
Err("Members set should be disjoint from candidates and runners-up sets".into()),
|
||||
false => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -1265,14 +1270,14 @@ impl<T: Config> Pallet<T> {
|
||||
// [`Members`], [`RunnersUp`] and approval stake state checks. Invariants:
|
||||
// - Selected members should have approval stake;
|
||||
// - Selected RunnersUp should have approval stake.
|
||||
fn try_state_members_approval_stake() -> Result<(), &'static str> {
|
||||
fn try_state_members_approval_stake() -> Result<(), TryRuntimeError> {
|
||||
match Members::<T>::get()
|
||||
.iter()
|
||||
.chain(RunnersUp::<T>::get().iter())
|
||||
.all(|s| s.stake != BalanceOf::<T>::zero())
|
||||
{
|
||||
true => Ok(()),
|
||||
false => Err("Members and RunnersUp must have approval stake"),
|
||||
false => Err("Members and RunnersUp must have approval stake".into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +137,9 @@ use sp_runtime::{
|
||||
};
|
||||
use sp_std::{marker::PhantomData, prelude::*};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[allow(dead_code)]
|
||||
const LOG_TARGET: &str = "runtime::executive";
|
||||
|
||||
@@ -338,7 +341,7 @@ where
|
||||
/// `true`. Also, if set to `true`, it runs the `pre_upgrade` and `post_upgrade` hooks.
|
||||
pub fn try_runtime_upgrade(
|
||||
checks: frame_try_runtime::UpgradeCheckSelect,
|
||||
) -> Result<Weight, &'static str> {
|
||||
) -> Result<Weight, TryRuntimeError> {
|
||||
if checks.try_state() {
|
||||
let _guard = frame_support::StorageNoopGuard::default();
|
||||
<AllPalletsWithSystem as frame_support::traits::TryState<System::BlockNumber>>::try_state(
|
||||
|
||||
@@ -91,6 +91,9 @@ pub mod pallet {
|
||||
use sp_std::{prelude::*, vec::Vec};
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
#[derive(scale_info::TypeInfo, codec::Encode, codec::Decode, codec::MaxEncodedLen)]
|
||||
#[codec(mel_bound(T: Config))]
|
||||
#[scale_info(skip_type_params(T))]
|
||||
@@ -228,10 +231,10 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_n: T::BlockNumber) -> Result<(), &'static str> {
|
||||
fn try_state(_n: T::BlockNumber) -> Result<(), TryRuntimeError> {
|
||||
// ensure that the value of `ErasToCheckPerBlock` is less than
|
||||
// `T::MaxErasToCheckPerBlock`.
|
||||
assert!(
|
||||
ensure!(
|
||||
ErasToCheckPerBlock::<T>::get() <= T::MaxErasToCheckPerBlock::get(),
|
||||
"the value of `ErasToCheckPerBlock` is greater than `T::MaxErasToCheckPerBlock`",
|
||||
);
|
||||
|
||||
@@ -25,6 +25,11 @@ pub mod v1 {
|
||||
use sp_staking::EraIndex;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
@@ -65,14 +70,20 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(Pallet::<T>::on_chain_storage_version(), 0);
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() == 0,
|
||||
"The onchain storage version must be zero for the migration to execute."
|
||||
);
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
|
||||
assert_eq!(Pallet::<T>::on_chain_storage_version(), 1);
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() == 1,
|
||||
"The onchain version must be updated after the migration."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ pub mod v1 {
|
||||
pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
ensure!(onchain < 1, "this migration can be deleted");
|
||||
@@ -72,7 +72,7 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain < 2, "this migration needs to be removed");
|
||||
ensure!(onchain == 1, "this migration needs to be run");
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
use super::*;
|
||||
use frame_support::{log, traits::OnRuntimeUpgrade};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
pub mod v1 {
|
||||
use frame_support::{pallet_prelude::*, weights::Weight};
|
||||
|
||||
@@ -90,7 +93,7 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
let current_version = Pallet::<T>::current_storage_version();
|
||||
let onchain_version = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain_version == 0 && current_version == 1, "migration from version 0 to 1.");
|
||||
@@ -99,13 +102,13 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(prev_count: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(prev_count: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect(
|
||||
"the state parameter should be something that was generated by pre_upgrade",
|
||||
);
|
||||
let post_count = Collection::<T>::iter().count() as u32;
|
||||
assert_eq!(
|
||||
prev_count, post_count,
|
||||
ensure!(
|
||||
prev_count == post_count,
|
||||
"the records count before and after the migration should be the same"
|
||||
);
|
||||
|
||||
|
||||
@@ -378,6 +378,9 @@ use sp_runtime::{
|
||||
use sp_staking::{EraIndex, OnStakerSlash, StakingInterface};
|
||||
use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, ops::Div, vec::Vec};
|
||||
|
||||
#[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// The log target of this pallet.
|
||||
pub const LOG_TARGET: &str = "runtime::nomination-pools";
|
||||
|
||||
@@ -2626,7 +2629,7 @@ pub mod pallet {
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_n: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
fn try_state(_n: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
|
||||
Self::do_try_state(u8::MAX)
|
||||
}
|
||||
|
||||
@@ -3055,7 +3058,7 @@ impl<T: Config> Pallet<T> {
|
||||
/// multiple `level`s, where the higher the level, the more checks we performs. So,
|
||||
/// `try_state(255)` is the strongest sanity check, and `0` performs no checks.
|
||||
#[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))]
|
||||
pub fn do_try_state(level: u8) -> Result<(), &'static str> {
|
||||
pub fn do_try_state(level: u8) -> Result<(), TryRuntimeError> {
|
||||
if level.is_zero() {
|
||||
return Ok(())
|
||||
}
|
||||
@@ -3063,12 +3066,24 @@ impl<T: Config> Pallet<T> {
|
||||
// result in the same set of keys, in the same order.
|
||||
let bonded_pools = BondedPools::<T>::iter_keys().collect::<Vec<_>>();
|
||||
let reward_pools = RewardPools::<T>::iter_keys().collect::<Vec<_>>();
|
||||
assert_eq!(bonded_pools, reward_pools);
|
||||
ensure!(
|
||||
bonded_pools == reward_pools,
|
||||
"`BondedPools` and `RewardPools` must all have the EXACT SAME key-set."
|
||||
);
|
||||
|
||||
assert!(Metadata::<T>::iter_keys().all(|k| bonded_pools.contains(&k)));
|
||||
assert!(SubPoolsStorage::<T>::iter_keys().all(|k| bonded_pools.contains(&k)));
|
||||
ensure!(
|
||||
SubPoolsStorage::<T>::iter_keys().all(|k| bonded_pools.contains(&k)),
|
||||
"`SubPoolsStorage` must be a subset of the above superset."
|
||||
);
|
||||
ensure!(
|
||||
Metadata::<T>::iter_keys().all(|k| bonded_pools.contains(&k)),
|
||||
"`Metadata` keys must be a subset of the above superset."
|
||||
);
|
||||
|
||||
assert!(MaxPools::<T>::get().map_or(true, |max| bonded_pools.len() <= (max as usize)));
|
||||
ensure!(
|
||||
MaxPools::<T>::get().map_or(true, |max| bonded_pools.len() <= (max as usize)),
|
||||
Error::<T>::MaxPools
|
||||
);
|
||||
|
||||
for id in reward_pools {
|
||||
let account = Self::create_reward_account(id);
|
||||
@@ -3088,9 +3103,9 @@ impl<T: Config> Pallet<T> {
|
||||
let mut pools_members = BTreeMap::<PoolId, u32>::new();
|
||||
let mut pools_members_pending_rewards = BTreeMap::<PoolId, BalanceOf<T>>::new();
|
||||
let mut all_members = 0u32;
|
||||
PoolMembers::<T>::iter().for_each(|(_, d)| {
|
||||
PoolMembers::<T>::iter().try_for_each(|(_, d)| -> Result<(), TryRuntimeError> {
|
||||
let bonded_pool = BondedPools::<T>::get(d.pool_id).unwrap();
|
||||
assert!(!d.total_points().is_zero(), "no member should have zero points: {d:?}");
|
||||
ensure!(!d.total_points().is_zero(), "No member should have zero points");
|
||||
*pools_members.entry(d.pool_id).or_default() += 1;
|
||||
all_members += 1;
|
||||
|
||||
@@ -3103,9 +3118,11 @@ impl<T: Config> Pallet<T> {
|
||||
let pending_rewards = d.pending_rewards(current_rc).unwrap();
|
||||
*pools_members_pending_rewards.entry(d.pool_id).or_default() += pending_rewards;
|
||||
} // else this pool has been heavily slashed and cannot have any rewards anymore.
|
||||
});
|
||||
|
||||
RewardPools::<T>::iter_keys().for_each(|id| {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
RewardPools::<T>::iter_keys().try_for_each(|id| -> Result<(), TryRuntimeError> {
|
||||
// the sum of the pending rewards must be less than the leftover balance. Since the
|
||||
// reward math rounds down, we might accumulate some dust here.
|
||||
log!(
|
||||
@@ -3115,30 +3132,40 @@ impl<T: Config> Pallet<T> {
|
||||
pools_members_pending_rewards.get(&id),
|
||||
RewardPool::<T>::current_balance(id)
|
||||
);
|
||||
assert!(
|
||||
ensure!(
|
||||
RewardPool::<T>::current_balance(id) >=
|
||||
pools_members_pending_rewards.get(&id).copied().unwrap_or_default()
|
||||
)
|
||||
});
|
||||
|
||||
BondedPools::<T>::iter().for_each(|(id, inner)| {
|
||||
let bonded_pool = BondedPool { id, inner };
|
||||
assert_eq!(
|
||||
pools_members.get(&id).copied().unwrap_or_default(),
|
||||
bonded_pool.member_counter
|
||||
pools_members_pending_rewards.get(&id).copied().unwrap_or_default(),
|
||||
"The sum of the pending rewards must be less than the leftover balance."
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
BondedPools::<T>::iter().try_for_each(|(id, inner)| -> Result<(), TryRuntimeError> {
|
||||
let bonded_pool = BondedPool { id, inner };
|
||||
ensure!(
|
||||
pools_members.get(&id).copied().unwrap_or_default() ==
|
||||
bonded_pool.member_counter,
|
||||
"Each `BondedPool.member_counter` must be equal to the actual count of members of this pool"
|
||||
);
|
||||
ensure!(
|
||||
MaxPoolMembersPerPool::<T>::get()
|
||||
.map_or(true, |max| bonded_pool.member_counter <= max),
|
||||
Error::<T>::MaxPoolMembers
|
||||
);
|
||||
assert!(MaxPoolMembersPerPool::<T>::get()
|
||||
.map_or(true, |max| bonded_pool.member_counter <= max));
|
||||
|
||||
let depositor = PoolMembers::<T>::get(&bonded_pool.roles.depositor).unwrap();
|
||||
assert!(
|
||||
ensure!(
|
||||
bonded_pool.is_destroying_and_only_depositor(depositor.active_points()) ||
|
||||
depositor.active_points() >= MinCreateBond::<T>::get(),
|
||||
"depositor must always have MinCreateBond stake in the pool, except for when the \
|
||||
pool is being destroyed and the depositor is the last member",
|
||||
);
|
||||
});
|
||||
assert!(MaxPoolMembers::<T>::get().map_or(true, |max| all_members <= max));
|
||||
Ok(())
|
||||
})?;
|
||||
ensure!(
|
||||
MaxPoolMembers::<T>::get().map_or(true, |max| all_members <= max),
|
||||
Error::<T>::MaxPoolMembers
|
||||
);
|
||||
|
||||
if level <= 1 {
|
||||
return Ok(())
|
||||
|
||||
@@ -20,6 +20,9 @@ use crate::log;
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
@@ -100,9 +103,12 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
// new version must be set.
|
||||
assert_eq!(Pallet::<T>::on_chain_storage_version(), 1);
|
||||
ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() == 1,
|
||||
"The onchain version must be updated after the migration."
|
||||
);
|
||||
Pallet::<T>::try_state(frame_system::Pallet::<T>::block_number())?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -352,38 +358,47 @@ pub mod v2 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
// all reward accounts must have more than ED.
|
||||
RewardPools::<T>::iter().for_each(|(id, _)| {
|
||||
assert!(
|
||||
RewardPools::<T>::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
T::Currency::free_balance(&Pallet::<T>::create_reward_account(id)) >=
|
||||
T::Currency::minimum_balance()
|
||||
)
|
||||
});
|
||||
T::Currency::minimum_balance(),
|
||||
"Reward accounts must have greater balance than ED."
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
// new version must be set.
|
||||
assert_eq!(Pallet::<T>::on_chain_storage_version(), 2);
|
||||
ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() == 2,
|
||||
"The onchain version must be updated after the migration."
|
||||
);
|
||||
|
||||
// no reward or bonded pool has been skipped.
|
||||
assert_eq!(RewardPools::<T>::iter().count() as u32, RewardPools::<T>::count());
|
||||
assert_eq!(BondedPools::<T>::iter().count() as u32, BondedPools::<T>::count());
|
||||
ensure!(
|
||||
RewardPools::<T>::iter().count() as u32 == RewardPools::<T>::count(),
|
||||
"The count of reward pools must remain the same after the migration."
|
||||
);
|
||||
ensure!(
|
||||
BondedPools::<T>::iter().count() as u32 == BondedPools::<T>::count(),
|
||||
"The count of reward pools must remain the same after the migration."
|
||||
);
|
||||
|
||||
// all reward pools must have exactly ED in them. This means no reward can be claimed,
|
||||
// and that setting reward counters all over the board to zero will work henceforth.
|
||||
RewardPools::<T>::iter().for_each(|(id, _)| {
|
||||
assert_eq!(
|
||||
RewardPool::<T>::current_balance(id),
|
||||
Zero::zero(),
|
||||
"reward pool({}) balance is {:?}",
|
||||
id,
|
||||
RewardPool::<T>::current_balance(id)
|
||||
RewardPools::<T>::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
RewardPool::<T>::current_balance(id) == Zero::zero(),
|
||||
"Reward pool balance must be zero.",
|
||||
);
|
||||
});
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
log!(info, "post upgrade hook for MigrateToV2 executed.");
|
||||
Ok(())
|
||||
@@ -435,7 +450,7 @@ pub mod v3 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(
|
||||
Pallet::<T>::current_storage_version() > Pallet::<T>::on_chain_storage_version(),
|
||||
"the on_chain version is equal or more than the current one"
|
||||
@@ -444,7 +459,7 @@ pub mod v3 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
Metadata::<T>::iter_keys().all(|id| BondedPools::<T>::contains_key(&id)),
|
||||
"not all of the stale metadata has been removed"
|
||||
@@ -535,7 +550,7 @@ pub mod v4 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(
|
||||
Pallet::<T>::current_storage_version() > Pallet::<T>::on_chain_storage_version(),
|
||||
"the on_chain version is equal or more than the current one"
|
||||
@@ -544,7 +559,7 @@ pub mod v4 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
// ensure all BondedPools items now contain an `inner.commission: Commission` field.
|
||||
ensure!(
|
||||
BondedPools::<T>::iter().all(|(_, inner)| inner.commission.current.is_none() &&
|
||||
@@ -620,7 +635,7 @@ pub mod v5 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(
|
||||
Pallet::<T>::current_storage_version() > Pallet::<T>::on_chain_storage_version(),
|
||||
"the on_chain version is equal or more than the current one"
|
||||
@@ -654,7 +669,7 @@ pub mod v5 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(data: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(data: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let old_rpool_values: u64 = Decode::decode(&mut &data[..]).unwrap();
|
||||
let rpool_keys = RewardPools::<T>::iter_keys().count() as u64;
|
||||
let rpool_values = RewardPools::<T>::iter_values().count() as u64;
|
||||
|
||||
@@ -4269,10 +4269,7 @@ mod create {
|
||||
assert!(!BondedPools::<Runtime>::contains_key(2));
|
||||
assert!(!RewardPools::<Runtime>::contains_key(2));
|
||||
assert!(!PoolMembers::<Runtime>::contains_key(11));
|
||||
assert_err!(
|
||||
StakingMock::active_stake(&next_pool_stash),
|
||||
DispatchError::Other("balance not found")
|
||||
);
|
||||
assert_err!(StakingMock::active_stake(&next_pool_stash), "balance not found");
|
||||
|
||||
Balances::make_free_balance_be(&11, StakingMock::minimum_nominator_bond() + ed);
|
||||
assert_ok!(Pools::create(
|
||||
|
||||
@@ -29,6 +29,8 @@ use sp_std::vec::Vec;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
mod v0 {
|
||||
use super::*;
|
||||
@@ -51,7 +53,7 @@ pub mod v1 {
|
||||
pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain < 1, "pallet_offences::MigrateToV1 migration can be deleted");
|
||||
|
||||
@@ -81,7 +83,7 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain == 1, "pallet_offences::MigrateToV1 needs to be run");
|
||||
ensure!(
|
||||
|
||||
@@ -24,6 +24,11 @@ use frame_support::{
|
||||
};
|
||||
use sp_std::collections::btree_map::BTreeMap;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// The log target.
|
||||
const TARGET: &'static str = "runtime::preimage::migration::v1";
|
||||
|
||||
@@ -78,8 +83,8 @@ pub mod v1 {
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 0, "can only upgrade from version 0");
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 0, "can only upgrade from version 0");
|
||||
|
||||
let images = v0::image_count::<T>().expect("v0 storage corrupted");
|
||||
log::info!(target: TARGET, "Migrating {} images", &images);
|
||||
@@ -148,7 +153,7 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(state: Vec<u8>) -> DispatchResult {
|
||||
let old_images: u32 =
|
||||
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
|
||||
let new_images = image_count::<T>().expect("V1 storage corrupted");
|
||||
@@ -161,7 +166,7 @@ pub mod v1 {
|
||||
old_images
|
||||
);
|
||||
}
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 1, "must upgrade");
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 1, "must upgrade");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||
use frame_support::{pallet_prelude::*, storage_alias, traits::OnRuntimeUpgrade};
|
||||
use log;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// Initial version of storage types.
|
||||
pub mod v0 {
|
||||
use super::*;
|
||||
@@ -95,9 +98,9 @@ pub mod v1 {
|
||||
pub struct MigrateV0ToV1<T, I = ()>(PhantomData<(T, I)>);
|
||||
impl<T: Config<I>, I: 'static> OnRuntimeUpgrade for MigrateV0ToV1<T, I> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
let onchain_version = Pallet::<T, I>::on_chain_storage_version();
|
||||
assert_eq!(onchain_version, 0, "migration from version 0 to 1.");
|
||||
ensure!(onchain_version == 0, "migration from version 0 to 1.");
|
||||
let referendum_count = v0::ReferendumInfoFor::<T, I>::iter().count();
|
||||
log::info!(
|
||||
target: TARGET,
|
||||
@@ -147,16 +150,13 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let onchain_version = Pallet::<T, I>::on_chain_storage_version();
|
||||
assert_eq!(onchain_version, 1, "must upgrade from version 0 to 1.");
|
||||
ensure!(onchain_version == 1, "must upgrade from version 0 to 1.");
|
||||
let pre_referendum_count: u32 = Decode::decode(&mut &state[..])
|
||||
.expect("failed to decode the state from pre-upgrade.");
|
||||
let post_referendum_count = ReferendumInfoFor::<T, I>::iter().count() as u32;
|
||||
assert_eq!(
|
||||
post_referendum_count, pre_referendum_count,
|
||||
"must migrate all referendums."
|
||||
);
|
||||
ensure!(post_referendum_count == pre_referendum_count, "must migrate all referendums.");
|
||||
log::info!(target: TARGET, "migrated all referendums.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
use super::*;
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// The log target.
|
||||
const TARGET: &'static str = "runtime::scheduler::migration";
|
||||
|
||||
@@ -97,8 +100,8 @@ pub mod v3 {
|
||||
|
||||
impl<T: Config<Hash = PreimageHash>> OnRuntimeUpgrade for MigrateToV4<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 3, "Can only upgrade from version 3");
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 3, "Can only upgrade from version 3");
|
||||
|
||||
let agendas = Agenda::<T>::iter_keys().count() as u32;
|
||||
let decodable_agendas = Agenda::<T>::iter_values().count() as u32;
|
||||
@@ -125,7 +128,7 @@ pub mod v3 {
|
||||
agenda.len(),
|
||||
max_scheduled_per_block,
|
||||
);
|
||||
return Err("Agenda would overflow `MaxScheduledPerBlock`.")
|
||||
return Err("Agenda would overflow `MaxScheduledPerBlock`.".into())
|
||||
}
|
||||
}
|
||||
// Check that bounding the calls will not overflow `MAX_LENGTH`.
|
||||
@@ -142,7 +145,7 @@ pub mod v3 {
|
||||
block_number,
|
||||
l,
|
||||
);
|
||||
return Err("Call is too large.")
|
||||
return Err("Call is too large.".into())
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
@@ -169,12 +172,12 @@ pub mod v3 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 4, "Must upgrade");
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 4, "Must upgrade");
|
||||
|
||||
// Check that everything decoded fine.
|
||||
for k in crate::Agenda::<T>::iter_keys() {
|
||||
assert!(crate::Agenda::<T>::try_get(k).is_ok(), "Cannot decode V4 Agenda");
|
||||
ensure!(crate::Agenda::<T>::try_get(k).is_ok(), "Cannot decode V4 Agenda");
|
||||
}
|
||||
|
||||
let old_agendas: u32 =
|
||||
@@ -210,7 +213,7 @@ pub mod v4 {
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for CleanupAgendas<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
assert_eq!(
|
||||
StorageVersion::get::<Pallet<T>>(),
|
||||
4,
|
||||
@@ -285,8 +288,8 @@ pub mod v4 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 4, "Version must not change");
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 4, "Version must not change");
|
||||
|
||||
let (old_agendas, non_empty_agendas): (u32, u32) =
|
||||
Decode::decode(&mut state.as_ref()).expect("Must decode pre_upgrade state");
|
||||
@@ -305,7 +308,7 @@ pub mod v4 {
|
||||
old_agendas, new_agendas
|
||||
),
|
||||
}
|
||||
assert_eq!(new_agendas, non_empty_agendas, "Expected to keep all non-empty agendas");
|
||||
ensure!(new_agendas == non_empty_agendas, "Expected to keep all non-empty agendas");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -496,7 +499,7 @@ mod test {
|
||||
|
||||
// The pre_upgrade hook fails:
|
||||
let err = v3::MigrateToV4::<Test>::pre_upgrade().unwrap_err();
|
||||
assert!(err.contains("Call is too large"));
|
||||
assert!(err == "Call is too large".into());
|
||||
// But the migration itself works:
|
||||
let _w = v3::MigrateToV4::<Test>::on_runtime_upgrade();
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@ use frame_support::{
|
||||
traits::OnRuntimeUpgrade,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// Used for release versioning upto v12.
|
||||
///
|
||||
/// Obsolete from v13. Keeping around to make encoding/decoding of old migration code easier.
|
||||
@@ -58,7 +63,7 @@ pub mod v13 {
|
||||
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> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V12_0_0,
|
||||
"Required v12 before upgrading to v13"
|
||||
@@ -84,7 +89,7 @@ pub mod v13 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() == 13,
|
||||
"v13 not applied"
|
||||
@@ -114,7 +119,7 @@ pub mod v12 {
|
||||
pub struct MigrateToV12<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV12<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V11_0_0,
|
||||
"Expected v11 before upgrading to v12"
|
||||
@@ -146,7 +151,7 @@ pub mod v12 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V12_0_0,
|
||||
"v12 not applied"
|
||||
@@ -170,7 +175,7 @@ pub mod v11 {
|
||||
for MigrateToV11<T, P, N>
|
||||
{
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V10_0_0,
|
||||
"must upgrade linearly"
|
||||
@@ -217,7 +222,7 @@ pub mod v11 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V11_0_0,
|
||||
"wrong version after the upgrade"
|
||||
@@ -332,7 +337,7 @@ pub mod v9 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V8_0_0,
|
||||
"must upgrade linearly"
|
||||
@@ -343,17 +348,21 @@ pub mod v9 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(prev_count: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(prev_count: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect(
|
||||
"the state parameter should be something that was generated by pre_upgrade",
|
||||
);
|
||||
let post_count = T::VoterList::count();
|
||||
let validators = Validators::<T>::count();
|
||||
assert!(post_count == prev_count + validators);
|
||||
ensure!(
|
||||
post_count == prev_count + validators,
|
||||
"`VoterList` count after the migration must equal to the sum of \
|
||||
previous count and the current number of validators"
|
||||
);
|
||||
|
||||
frame_support::ensure!(
|
||||
StorageVersion::<T>::get() == ObsoleteReleases::V9_0_0,
|
||||
"must upgrade "
|
||||
"must upgrade"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ use crate::{
|
||||
|
||||
use super::{pallet::*, STAKING_ID};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
#[cfg(any(test, feature = "try-runtime"))]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// The maximum number of iterations that we do whilst iterating over `T::VoterList` in
|
||||
/// `get_npos_voters`.
|
||||
///
|
||||
@@ -1467,7 +1472,7 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseValidatorsMap<T> {
|
||||
0
|
||||
}
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state() -> Result<(), &'static str> {
|
||||
fn try_state() -> Result<(), TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1544,7 +1549,7 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsAndValidatorsM
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state() -> Result<(), &'static str> {
|
||||
fn try_state() -> Result<(), TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1713,7 +1718,7 @@ impl<T: Config> StakingInterface for Pallet<T> {
|
||||
|
||||
#[cfg(any(test, feature = "try-runtime"))]
|
||||
impl<T: Config> Pallet<T> {
|
||||
pub(crate) fn do_try_state(_: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
pub(crate) fn do_try_state(_: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
T::VoterList::iter()
|
||||
.all(|x| <Nominators<T>>::contains_key(&x) || <Validators<T>>::contains_key(&x)),
|
||||
@@ -1726,7 +1731,7 @@ impl<T: Config> Pallet<T> {
|
||||
Self::check_count()
|
||||
}
|
||||
|
||||
fn check_count() -> Result<(), &'static str> {
|
||||
fn check_count() -> Result<(), TryRuntimeError> {
|
||||
ensure!(
|
||||
<T as Config>::VoterList::count() ==
|
||||
Nominators::<T>::count() + Validators::<T>::count(),
|
||||
@@ -1739,18 +1744,19 @@ impl<T: Config> Pallet<T> {
|
||||
ensure!(
|
||||
ValidatorCount::<T>::get() <=
|
||||
<T::ElectionProvider as frame_election_provider_support::ElectionProviderBase>::MaxWinners::get(),
|
||||
"validator count exceeded election max winners"
|
||||
Error::<T>::TooManyValidators
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_ledgers() -> Result<(), &'static str> {
|
||||
fn check_ledgers() -> Result<(), TryRuntimeError> {
|
||||
Bonded::<T>::iter()
|
||||
.map(|(_, ctrl)| Self::ensure_ledger_consistent(ctrl))
|
||||
.collect::<Result<_, _>>()
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_exposures() -> Result<(), &'static str> {
|
||||
fn check_exposures() -> Result<(), TryRuntimeError> {
|
||||
// a check per validator to ensure the exposure struct is always sane.
|
||||
let era = Self::active_era().unwrap().index;
|
||||
ErasStakers::<T>::iter_prefix_values(era)
|
||||
@@ -1766,10 +1772,10 @@ impl<T: Config> Pallet<T> {
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
.collect::<Result<(), TryRuntimeError>>()
|
||||
}
|
||||
|
||||
fn check_nominators() -> Result<(), &'static str> {
|
||||
fn check_nominators() -> Result<(), TryRuntimeError> {
|
||||
// a check per nominator to ensure their entire stake is correctly distributed. Will only
|
||||
// kick-in if the nomination was submitted before the current era.
|
||||
let era = Self::active_era().unwrap().index;
|
||||
@@ -1783,27 +1789,33 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|nominator| {
|
||||
.map(|nominator| -> Result<(), TryRuntimeError> {
|
||||
// must be bonded.
|
||||
Self::ensure_is_stash(&nominator)?;
|
||||
let mut sum = BalanceOf::<T>::zero();
|
||||
T::SessionInterface::validators()
|
||||
.iter()
|
||||
.map(|v| Self::eras_stakers(era, v))
|
||||
.map(|e| {
|
||||
.map(|e| -> Result<(), TryRuntimeError> {
|
||||
let individual =
|
||||
e.others.iter().filter(|e| e.who == nominator).collect::<Vec<_>>();
|
||||
let len = individual.len();
|
||||
match len {
|
||||
0 => { /* not supporting this validator at all. */ },
|
||||
1 => sum += individual[0].value,
|
||||
_ => return Err("nominator cannot back a validator more than once."),
|
||||
_ =>
|
||||
return Err(
|
||||
"nominator cannot back a validator more than once.".into()
|
||||
),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(())
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_is_stash(who: &T::AccountId) -> Result<(), &'static str> {
|
||||
@@ -1811,7 +1823,7 @@ impl<T: Config> Pallet<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_ledger_consistent(ctrl: T::AccountId) -> Result<(), &'static str> {
|
||||
fn ensure_ledger_consistent(ctrl: T::AccountId) -> Result<(), TryRuntimeError> {
|
||||
// ensures ledger.total == ledger.active + sum(ledger.unlocking).
|
||||
let ledger = Self::ledger(ctrl.clone()).ok_or("Not a controller.")?;
|
||||
let real_total: BalanceOf<T> =
|
||||
|
||||
@@ -805,7 +805,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(n: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
fn try_state(n: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
Self::do_try_state(n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
current_version,
|
||||
);
|
||||
|
||||
return Err("On chain and current storage version do not match. Missing runtime upgrade?");
|
||||
return Err("On chain and current storage version do not match. Missing runtime upgrade?".into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -128,7 +128,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
);
|
||||
|
||||
return Err("On chain storage version set, while the pallet doesn't \
|
||||
have the `#[pallet::storage_version(VERSION)]` attribute.");
|
||||
have the `#[pallet::storage_version(VERSION)]` attribute.".into());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -211,7 +211,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<#frame_support::sp_std::vec::Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<#frame_support::sp_std::vec::Vec<u8>, #frame_support::sp_runtime::TryRuntimeError> {
|
||||
<
|
||||
Self
|
||||
as
|
||||
@@ -220,7 +220,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: #frame_support::sp_std::vec::Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(state: #frame_support::sp_std::vec::Vec<u8>) -> Result<(), #frame_support::sp_runtime::TryRuntimeError> {
|
||||
#post_storage_version_check
|
||||
|
||||
<
|
||||
@@ -268,7 +268,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
fn try_state(
|
||||
n: <T as #frame_system::Config>::BlockNumber,
|
||||
_s: #frame_support::traits::TryStateSelect
|
||||
) -> Result<(), &'static str> {
|
||||
) -> Result<(), #frame_support::sp_runtime::TryRuntimeError> {
|
||||
#log_try_state
|
||||
<
|
||||
Self as #frame_support::traits::Hooks<
|
||||
|
||||
@@ -2097,7 +2097,7 @@ macro_rules! decl_module {
|
||||
fn try_state(
|
||||
_: <$trait_instance as $system::Config>::BlockNumber,
|
||||
_: $crate::traits::TryStateSelect,
|
||||
) -> Result<(), &'static str> {
|
||||
) -> Result<(), $crate::sp_runtime::TryRuntimeError> {
|
||||
let pallet_name = <<
|
||||
$trait_instance
|
||||
as
|
||||
@@ -2144,12 +2144,12 @@ macro_rules! decl_module {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<$crate::sp_std::vec::Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<$crate::sp_std::vec::Vec<u8>, $crate::sp_runtime::TryRuntimeError> {
|
||||
Ok($crate::sp_std::vec::Vec::new())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: $crate::sp_std::vec::Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: $crate::sp_std::vec::Vec<u8>) -> Result<(), $crate::sp_runtime::TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -2182,12 +2182,12 @@ macro_rules! decl_module {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<$crate::sp_std::vec::Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<$crate::sp_std::vec::Vec<u8>, $crate::sp_runtime::TryRuntimeError> {
|
||||
Ok($crate::sp_std::vec::Vec::new())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: $crate::sp_std::vec::Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: $crate::sp_std::vec::Vec<u8>) -> Result<(), $crate::sp_runtime::TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ impl<P: Get<&'static str>, DbWeight: Get<RuntimeDbWeight>> frame_support::traits
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
let hashed_prefix = twox_128(P::get().as_bytes());
|
||||
match contains_prefixed_key(&hashed_prefix) {
|
||||
true => log::info!("Found {} keys pre-removal 👀", P::get()),
|
||||
@@ -197,12 +197,12 @@ impl<P: Get<&'static str>, DbWeight: Get<RuntimeDbWeight>> frame_support::traits
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
let hashed_prefix = twox_128(P::get().as_bytes());
|
||||
match contains_prefixed_key(&hashed_prefix) {
|
||||
true => {
|
||||
log::error!("{} has keys remaining post-removal ❗", P::get());
|
||||
return Err("Keys remaining post-removal, this should never happen 🚨")
|
||||
return Err("Keys remaining post-removal, this should never happen 🚨".into())
|
||||
},
|
||||
false => log::info!("No {} keys found post-removal 🎉", P::get()),
|
||||
};
|
||||
|
||||
@@ -22,6 +22,9 @@ use impl_trait_for_tuples::impl_for_tuples;
|
||||
use sp_runtime::traits::AtLeast32BitUnsigned;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_runtime::TryRuntimeError;
|
||||
|
||||
/// The block initialization trait.
|
||||
///
|
||||
/// Implementing this lets you express what should happen for your pallet when the block is
|
||||
@@ -136,7 +139,7 @@ pub trait OnRuntimeUpgrade {
|
||||
/// Same as `on_runtime_upgrade`, but perform the optional `pre_upgrade` and `post_upgrade` as
|
||||
/// well.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, &'static str> {
|
||||
fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, TryRuntimeError> {
|
||||
let maybe_state = if checks {
|
||||
let _guard = frame_support::StorageNoopGuard::default();
|
||||
let state = Self::pre_upgrade()?;
|
||||
@@ -167,7 +170,7 @@ pub trait OnRuntimeUpgrade {
|
||||
/// This hook must not write to any state, as it would make the main `on_runtime_upgrade` path
|
||||
/// inaccurate.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
@@ -182,7 +185,7 @@ pub trait OnRuntimeUpgrade {
|
||||
/// This hook must not write to any state, as it would make the main `on_runtime_upgrade` path
|
||||
/// inaccurate.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -201,7 +204,7 @@ impl OnRuntimeUpgrade for Tuple {
|
||||
/// consecutive migrations for the same pallet without errors. Therefore pre and post upgrade
|
||||
/// hooks for tuples are a noop.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, &'static str> {
|
||||
fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, TryRuntimeError> {
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
let mut errors = Vec::new();
|
||||
@@ -224,12 +227,12 @@ impl OnRuntimeUpgrade for Tuple {
|
||||
errors.iter().for_each(|err| {
|
||||
log::error!(
|
||||
target: "try-runtime",
|
||||
"{}",
|
||||
"{:?}",
|
||||
err
|
||||
);
|
||||
});
|
||||
|
||||
return Err("Detected multiple errors while executing `try_on_runtime_upgrade`, check the logs!")
|
||||
return Err("Detected multiple errors while executing `try_on_runtime_upgrade`, check the logs!".into())
|
||||
}
|
||||
|
||||
Ok(weight)
|
||||
@@ -305,7 +308,7 @@ pub trait Hooks<BlockNumber> {
|
||||
///
|
||||
/// This hook should not alter any storage.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_n: BlockNumber) -> Result<(), &'static str> {
|
||||
fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -317,7 +320,7 @@ pub trait Hooks<BlockNumber> {
|
||||
///
|
||||
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
@@ -329,7 +332,7 @@ pub trait Hooks<BlockNumber> {
|
||||
///
|
||||
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -411,13 +414,13 @@ mod tests {
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
Pre::mutate(|s| s.push(stringify!($name)));
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
Post::mutate(|s| s.push(stringify!($name)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
use impl_trait_for_tuples::impl_for_tuples;
|
||||
use sp_arithmetic::traits::AtLeast32BitUnsigned;
|
||||
use sp_runtime::TryRuntimeError;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
/// Which state tests to execute.
|
||||
@@ -129,7 +130,7 @@ impl core::str::FromStr for UpgradeCheckSelect {
|
||||
/// This hook should not alter any storage.
|
||||
pub trait TryState<BlockNumber> {
|
||||
/// Execute the state checks.
|
||||
fn try_state(_: BlockNumber, _: Select) -> Result<(), &'static str>;
|
||||
fn try_state(_: BlockNumber, _: Select) -> Result<(), TryRuntimeError>;
|
||||
}
|
||||
|
||||
#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
|
||||
@@ -139,7 +140,7 @@ impl<BlockNumber: Clone + sp_std::fmt::Debug + AtLeast32BitUnsigned> TryState<Bl
|
||||
for Tuple
|
||||
{
|
||||
for_tuples!( where #( Tuple: crate::traits::PalletInfoAccess )* );
|
||||
fn try_state(n: BlockNumber, targets: Select) -> Result<(), &'static str> {
|
||||
fn try_state(n: BlockNumber, targets: Select) -> Result<(), TryRuntimeError> {
|
||||
match targets {
|
||||
Select::None => Ok(()),
|
||||
Select::All => {
|
||||
@@ -148,7 +149,7 @@ impl<BlockNumber: Clone + sp_std::fmt::Debug + AtLeast32BitUnsigned> TryState<Bl
|
||||
result
|
||||
},
|
||||
Select::RoundRobin(len) => {
|
||||
let functions: &[fn(BlockNumber, Select) -> Result<(), &'static str>] =
|
||||
let functions: &[fn(BlockNumber, Select) -> Result<(), TryRuntimeError>] =
|
||||
&[for_tuples!(#( Tuple::try_state ),*)];
|
||||
let skip = n.clone() % (functions.len() as u32).into();
|
||||
let skip: u32 =
|
||||
@@ -163,7 +164,7 @@ impl<BlockNumber: Clone + sp_std::fmt::Debug + AtLeast32BitUnsigned> TryState<Bl
|
||||
Select::Only(ref pallet_names) => {
|
||||
let try_state_fns: &[(
|
||||
&'static str,
|
||||
fn(BlockNumber, Select) -> Result<(), &'static str>,
|
||||
fn(BlockNumber, Select) -> Result<(), TryRuntimeError>,
|
||||
)] = &[for_tuples!(
|
||||
#( (<Tuple as crate::traits::PalletInfoAccess>::name(), Tuple::try_state) ),*
|
||||
)];
|
||||
|
||||
@@ -2110,9 +2110,11 @@ fn post_runtime_upgrade_detects_storage_version_issues() {
|
||||
// Call `on_genesis` to put the storage version of `Example` into the storage.
|
||||
Example::on_genesis();
|
||||
// The version isn't changed, we should detect it.
|
||||
assert!(Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost)
|
||||
.unwrap_err()
|
||||
.contains("On chain and current storage version do not match"));
|
||||
assert!(
|
||||
Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap_err() ==
|
||||
"On chain and current storage version do not match. Missing runtime upgrade?"
|
||||
.into()
|
||||
);
|
||||
});
|
||||
|
||||
TestExternalities::default().execute_with(|| {
|
||||
@@ -2138,9 +2140,12 @@ fn post_runtime_upgrade_detects_storage_version_issues() {
|
||||
|
||||
// `CustomUpgradePallet4` will set a storage version for `Example4` while this doesn't has
|
||||
// any storage version "enabled".
|
||||
assert!(ExecutiveWithUpgradePallet4::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost)
|
||||
.unwrap_err()
|
||||
.contains("On chain storage version set, while the pallet doesn't"));
|
||||
assert!(
|
||||
ExecutiveWithUpgradePallet4::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost)
|
||||
.unwrap_err() == "On chain storage version set, while the pallet \
|
||||
doesn't have the `#[pallet::storage_version(VERSION)]` attribute."
|
||||
.into()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -784,6 +784,9 @@ pub type ApplyExtrinsicResult =
|
||||
pub type ApplyExtrinsicResultWithInfo<T> =
|
||||
Result<DispatchResultWithInfo<T>, transaction_validity::TransactionValidityError>;
|
||||
|
||||
/// The error type used as return type in try runtime hooks.
|
||||
pub type TryRuntimeError = DispatchError;
|
||||
|
||||
/// Verify a signature on an encoded value in a lazy manner. This can be
|
||||
/// an optimization if the signature scheme has an "unsigned" escape hash.
|
||||
pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
|
||||
|
||||
@@ -122,10 +122,10 @@
|
||||
//!
|
||||
//! ```ignore
|
||||
//! #[cfg(feature = "try-runtime")]
|
||||
//! fn pre_upgrade() -> Result<Vec<u8>, &'static str> {}
|
||||
//! fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {}
|
||||
//!
|
||||
//! #[cfg(feature = "try-runtime")]
|
||||
//! fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {}
|
||||
//! fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {}
|
||||
//! ```
|
||||
//!
|
||||
//! (The pallet macro syntax will support this simply as a part of `#[pallet::hooks]`).
|
||||
@@ -141,7 +141,7 @@
|
||||
//!
|
||||
//! ```ignore
|
||||
//! #[cfg(feature = "try-runtime")]
|
||||
//! fn try_state(_: BlockNumber) -> Result<(), &'static str> {}
|
||||
//! fn try_state(_: BlockNumber) -> Result<(), TryRuntimeError> {}
|
||||
//! ```
|
||||
//!
|
||||
//! which is called on numerous code paths in the try-runtime tool. These checks should ensure that
|
||||
|
||||
Reference in New Issue
Block a user