mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 15:11:02 +00:00
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 <>
This commit is contained in:
@@ -18,9 +18,7 @@
|
|||||||
//! Test utilities
|
//! Test utilities
|
||||||
|
|
||||||
use crate::{self as pallet_staking, *};
|
use crate::{self as pallet_staking, *};
|
||||||
use frame_election_provider_support::{
|
use frame_election_provider_support::{onchain, SequentialPhragmen, VoteWeight};
|
||||||
onchain, SequentialPhragmen, SortedListProvider, VoteWeight,
|
|
||||||
};
|
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
assert_ok, parameter_types,
|
assert_ok, parameter_types,
|
||||||
traits::{
|
traits::{
|
||||||
@@ -548,108 +546,10 @@ impl ExtBuilder {
|
|||||||
sp_tracing::try_init_simple();
|
sp_tracing::try_init_simple();
|
||||||
let mut ext = self.build();
|
let mut ext = self.build();
|
||||||
ext.execute_with(test);
|
ext.execute_with(test);
|
||||||
ext.execute_with(post_conditions);
|
ext.execute_with(|| {
|
||||||
}
|
Staking::do_try_state(System::block_number()).unwrap();
|
||||||
}
|
|
||||||
|
|
||||||
fn post_conditions() {
|
|
||||||
check_nominators();
|
|
||||||
check_exposures();
|
|
||||||
check_ledgers();
|
|
||||||
check_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_count() {
|
|
||||||
let nominator_count = Nominators::<Test>::iter_keys().count() as u32;
|
|
||||||
let validator_count = Validators::<Test>::iter().count() as u32;
|
|
||||||
assert_eq!(nominator_count, Nominators::<Test>::count());
|
|
||||||
assert_eq!(validator_count, Validators::<Test>::count());
|
|
||||||
|
|
||||||
// the voters that the `VoterList` list is storing for us.
|
|
||||||
let external_voters = <Test as Config>::VoterList::count();
|
|
||||||
assert_eq!(external_voters, nominator_count + validator_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_ledgers() {
|
|
||||||
// check the ledger of all stakers.
|
|
||||||
Bonded::<Test>::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::<Test>::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::<u128>(),
|
|
||||||
"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();
|
|
||||||
<Nominators<Test>>::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::<Vec<_>>();
|
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
pub(crate) fn active_era() -> EraIndex {
|
||||||
|
|||||||
@@ -1552,11 +1552,12 @@ impl<T: Config> StakingInterface for Pallet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "try-runtime")]
|
#[cfg(any(test, feature = "try-runtime"))]
|
||||||
impl<T: Config> Pallet<T> {
|
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<(), &'static str> {
|
||||||
ensure!(
|
ensure!(
|
||||||
T::VoterList::iter().all(|x| <Nominators<T>>::contains_key(&x)),
|
T::VoterList::iter()
|
||||||
|
.all(|x| <Nominators<T>>::contains_key(&x) || <Validators<T>>::contains_key(&x)),
|
||||||
"VoterList contains non-nominators"
|
"VoterList contains non-nominators"
|
||||||
);
|
);
|
||||||
T::VoterList::try_state()?;
|
T::VoterList::try_state()?;
|
||||||
|
|||||||
Reference in New Issue
Block a user