From ca15fe7e3d22e61b90d591a2fb806481ecc11bd5 Mon Sep 17 00:00:00 2001 From: Ankan <10196091+Ank4n@users.noreply.github.com> Date: Mon, 17 Oct 2022 18:44:42 +0200 Subject: [PATCH] Execute try-state at end of each test to ensure pallet data integrity (#12453) * execute try-state at end of tests * run post condition only with try runtime * Revert "run post condition only with try runtime" This reverts commit 7db0ecf7eaa2ee5afa5a995487b73d023ba3bcd9. * voterlist contains validators as well * fmt * simplify * fmt Co-authored-by: parity-processbot <> --- substrate/frame/staking/src/mock.rs | 108 +------------------- substrate/frame/staking/src/pallet/impls.rs | 5 +- 2 files changed, 7 insertions(+), 106 deletions(-) diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs index 3a9351ef4a..24e5aa9716 100644 --- a/substrate/frame/staking/src/mock.rs +++ b/substrate/frame/staking/src/mock.rs @@ -18,9 +18,7 @@ //! Test utilities use crate::{self as pallet_staking, *}; -use frame_election_provider_support::{ - onchain, SequentialPhragmen, SortedListProvider, VoteWeight, -}; +use frame_election_provider_support::{onchain, SequentialPhragmen, VoteWeight}; use frame_support::{ assert_ok, parameter_types, traits::{ @@ -548,108 +546,10 @@ impl ExtBuilder { sp_tracing::try_init_simple(); let mut ext = self.build(); ext.execute_with(test); - ext.execute_with(post_conditions); - } -} - -fn post_conditions() { - check_nominators(); - check_exposures(); - check_ledgers(); - check_count(); -} - -fn check_count() { - let nominator_count = Nominators::::iter_keys().count() as u32; - let validator_count = Validators::::iter().count() as u32; - assert_eq!(nominator_count, Nominators::::count()); - assert_eq!(validator_count, Validators::::count()); - - // the voters that the `VoterList` list is storing for us. - let external_voters = ::VoterList::count(); - assert_eq!(external_voters, nominator_count + validator_count); -} - -fn check_ledgers() { - // check the ledger of all stakers. - Bonded::::iter().for_each(|(_, ctrl)| assert_ledger_consistent(ctrl)) -} - -fn check_exposures() { - // a check per validator to ensure the exposure struct is always sane. - let era = active_era(); - ErasStakers::::iter_prefix_values(era).for_each(|expo| { - assert_eq!( - expo.total as u128, - expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), - "wrong total exposure.", - ); - }) -} - -fn check_nominators() { - // 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 = active_era(); - >::iter() - .filter_map( - |(nominator, nomination)| { - if nomination.submitted_in > era { - Some(nominator) - } else { - None - } - }, - ) - .for_each(|nominator| { - // must be bonded. - assert_is_stash(nominator); - let mut sum = 0; - Session::validators() - .iter() - .map(|v| Staking::eras_stakers(era, v)) - .for_each(|e| { - let individual = - e.others.iter().filter(|e| e.who == nominator).collect::>(); - let len = individual.len(); - match len { - 0 => { /* not supporting this validator at all. */ }, - 1 => sum += individual[0].value, - _ => panic!("nominator cannot back a validator more than once."), - }; - }); - - let nominator_stake = Staking::slashable_balance_of(&nominator); - // a nominator cannot over-spend. - assert!( - nominator_stake >= sum, - "failed: Nominator({}) stake({}) >= sum divided({})", - nominator, - nominator_stake, - sum, - ); - - let diff = nominator_stake - sum; - assert!(diff < 100); + ext.execute_with(|| { + Staking::do_try_state(System::block_number()).unwrap(); }); -} - -fn assert_is_stash(acc: AccountId) { - assert!(Staking::bonded(&acc).is_some(), "Not a stash."); -} - -fn assert_ledger_consistent(ctrl: AccountId) { - // ensures ledger.total == ledger.active + sum(ledger.unlocking). - let ledger = Staking::ledger(ctrl).expect("Not a controller."); - let real_total: Balance = ledger.unlocking.iter().fold(ledger.active, |a, c| a + c.value); - assert_eq!(real_total, ledger.total); - assert!( - ledger.active >= Balances::minimum_balance() || ledger.active == 0, - "{}: active ledger amount ({}) must be greater than ED {}", - ctrl, - ledger.active, - Balances::minimum_balance() - ); + } } pub(crate) fn active_era() -> EraIndex { diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 6da27da362..4ef0642296 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -1552,11 +1552,12 @@ impl StakingInterface for Pallet { } } -#[cfg(feature = "try-runtime")] +#[cfg(any(test, feature = "try-runtime"))] impl Pallet { pub(crate) fn do_try_state(_: BlockNumberFor) -> Result<(), &'static str> { ensure!( - T::VoterList::iter().all(|x| >::contains_key(&x)), + T::VoterList::iter() + .all(|x| >::contains_key(&x) || >::contains_key(&x)), "VoterList contains non-nominators" ); T::VoterList::try_state()?;