mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 03:01:07 +00:00
Runtime State Test + Integration with try-runtime (#10174)
* add missing version to dependencies * Huh * add features more * more fixing * last touches * it all finally works * remove some feature gates * remove unused * fix old macro * make it work again * fmt * remove unused import * ".git/.scripts/fmt.sh" 1 * Cleanup more * fix and rename everything * a few clippy fixes * Add try-runtime feature Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * small fixes * fmt * Update bin/node-template/runtime/src/lib.rs * fix build * Update utils/frame/try-runtime/cli/src/lib.rs Co-authored-by: David <dvdplm@gmail.com> * Update utils/frame/try-runtime/cli/src/commands/execute_block.rs Co-authored-by: David <dvdplm@gmail.com> * address all review comments * fix typos * revert spec change * last touches * update docs * fmt * remove some debug_assertions * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: command-bot <> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: David <dvdplm@gmail.com>
This commit is contained in:
@@ -153,7 +153,7 @@ pub mod v8 {
|
||||
Nominators::<T>::iter().map(|(id, _)| id),
|
||||
Pallet::<T>::weight_of_fn(),
|
||||
);
|
||||
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
|
||||
debug_assert_eq!(T::VoterList::try_state(), Ok(()));
|
||||
|
||||
StorageVersion::<T>::put(crate::Releases::V8_0_0);
|
||||
crate::log!(
|
||||
@@ -170,7 +170,7 @@ pub mod v8 {
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub fn post_migrate<T: Config>() -> Result<(), &'static str> {
|
||||
T::VoterList::sanity_check().map_err(|_| "VoterList is not in a sane state.")?;
|
||||
T::VoterList::try_state().map_err(|_| "VoterList is not in a sane state.")?;
|
||||
crate::log!(info, "👜 staking bags-list migration passes POST migrate checks ✅",);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -789,7 +789,6 @@ impl<T: Config> Pallet<T> {
|
||||
Nominators::<T>::count() + Validators::<T>::count(),
|
||||
T::VoterList::count()
|
||||
);
|
||||
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
|
||||
}
|
||||
|
||||
/// This function will remove a nominator from the `Nominators` storage map,
|
||||
@@ -809,7 +808,6 @@ impl<T: Config> Pallet<T> {
|
||||
false
|
||||
};
|
||||
|
||||
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
|
||||
debug_assert_eq!(
|
||||
Nominators::<T>::count() + Validators::<T>::count(),
|
||||
T::VoterList::count()
|
||||
@@ -837,7 +835,6 @@ impl<T: Config> Pallet<T> {
|
||||
Nominators::<T>::count() + Validators::<T>::count(),
|
||||
T::VoterList::count()
|
||||
);
|
||||
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
|
||||
}
|
||||
|
||||
/// This function will remove a validator from the `Validators` storage map.
|
||||
@@ -856,7 +853,6 @@ impl<T: Config> Pallet<T> {
|
||||
false
|
||||
};
|
||||
|
||||
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
|
||||
debug_assert_eq!(
|
||||
Nominators::<T>::count() + Validators::<T>::count(),
|
||||
T::VoterList::count()
|
||||
@@ -1369,7 +1365,7 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsAndValidatorsM
|
||||
// nothing to do upon regenerate.
|
||||
0
|
||||
}
|
||||
fn sanity_check() -> Result<(), &'static str> {
|
||||
fn try_state() -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1452,3 +1448,104 @@ impl<T: Config> StakingInterface for Pallet<T> {
|
||||
Nominators::<T>::get(who).map(|n| n.targets.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
impl<T: Config> Pallet<T> {
|
||||
pub(crate) fn do_try_state(_: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
T::VoterList::try_state()?;
|
||||
Self::check_nominators()?;
|
||||
Self::check_exposures()?;
|
||||
Self::check_ledgers()?;
|
||||
Self::check_count()
|
||||
}
|
||||
|
||||
fn check_count() -> Result<(), &'static str> {
|
||||
ensure!(
|
||||
<T as Config>::VoterList::count() ==
|
||||
Nominators::<T>::count() + Validators::<T>::count(),
|
||||
"wrong external count"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_ledgers() -> Result<(), &'static str> {
|
||||
Bonded::<T>::iter()
|
||||
.map(|(_, ctrl)| Self::ensure_ledger_consistent(ctrl))
|
||||
.collect::<Result<_, _>>()
|
||||
}
|
||||
|
||||
fn check_exposures() -> Result<(), &'static str> {
|
||||
// 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)
|
||||
.map(|expo| {
|
||||
ensure!(
|
||||
expo.total ==
|
||||
expo.own +
|
||||
expo.others
|
||||
.iter()
|
||||
.map(|e| e.value)
|
||||
.fold(Zero::zero(), |acc, x| acc + x),
|
||||
"wrong total exposure.",
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
}
|
||||
|
||||
fn check_nominators() -> Result<(), &'static str> {
|
||||
// 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;
|
||||
<Nominators<T>>::iter()
|
||||
.filter_map(
|
||||
|(nominator, nomination)| {
|
||||
if nomination.submitted_in > era {
|
||||
Some(nominator)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|nominator| {
|
||||
// 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| {
|
||||
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."),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
})
|
||||
.collect::<Result<_, _>>()
|
||||
}
|
||||
|
||||
fn ensure_is_stash(who: &T::AccountId) -> Result<(), &'static str> {
|
||||
ensure!(Self::bonded(who).is_some(), "Not a stash.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_ledger_consistent(ctrl: T::AccountId) -> Result<(), &'static str> {
|
||||
// ensures ledger.total == ledger.active + sum(ledger.unlocking).
|
||||
let ledger = Self::ledger(ctrl.clone()).ok_or("Not a controller.")?;
|
||||
let real_total: BalanceOf<T> =
|
||||
ledger.unlocking.iter().fold(ledger.active, |a, c| a + c.value);
|
||||
ensure!(real_total == ledger.total, "ledger.total corrupt");
|
||||
|
||||
if !(ledger.active >= T::Currency::minimum_balance() || ledger.active.is_zero()) {
|
||||
log!(warn, "ledger.active less than ED: {:?}, {:?}", ctrl, ledger)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -744,6 +744,11 @@ pub mod pallet {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(n: BlockNumberFor<T>) -> Result<(), &'static str> {
|
||||
Self::do_try_state(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
@@ -856,7 +861,6 @@ pub mod pallet {
|
||||
if T::VoterList::contains(&stash) {
|
||||
let _ =
|
||||
T::VoterList::on_update(&stash, Self::weight_of(&ledger.stash)).defensive();
|
||||
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
|
||||
}
|
||||
|
||||
Self::deposit_event(Event::<T>::Bonded(stash, extra));
|
||||
|
||||
Reference in New Issue
Block a user