From f88f4edbc42b76053404f9ba45d641dafb147ab7 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 16 Jun 2021 05:57:14 +0100 Subject: [PATCH] Add Control to Growth of the Staking Pallet (#8920) * start count * track count * add max limit * min bonds for participating * respect min bond when unbonding * revert a bit of u32 * fix merge * more merge fixes * update to `Current*` * add helper functions * Update frame/staking/src/lib.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * fix * minbond as storage * checkpoint * chill_other * better bond tracking * MinBond to MinNominatorBond * better doc * use helper function * oops * simple hard limits to validators / nominators. * better doc * update storage version * fix tests * enable migrations * min bond tests * chill other tests * tests for max cap * check `None` on cap too * benchmarks * Update frame/staking/src/lib.rs * Update frame/staking/src/lib.rs Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com> * Update frame/staking/src/lib.rs Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com> * Update frame/staking/src/tests.rs Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com> * fix benchmark * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * nits * fix reap_stash benchmark * remove lower bound to min bond Co-authored-by: kianenigma Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Parity Bot Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com> --- frame/staking/src/benchmarking.rs | 53 +++- frame/staking/src/lib.rs | 295 ++++++++++++++++++--- frame/staking/src/mock.rs | 25 +- frame/staking/src/testing_utils.rs | 2 + frame/staking/src/tests.rs | 397 +++++++++++++++++++---------- frame/staking/src/weights.rs | 284 +++++++++++---------- 6 files changed, 750 insertions(+), 306 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 2ad939e5b166c..8adf797abe9e9 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -30,6 +30,7 @@ pub use frame_benchmarking::{ const SEED: u32 = 0; const MAX_SPANS: u32 = 100; const MAX_VALIDATORS: u32 = 1000; +const MAX_NOMINATORS: u32 = 1000; const MAX_SLASHES: u32 = 1000; // Add slashing spans to a user account. Not relevant for actual use, only to benchmark @@ -463,12 +464,18 @@ benchmarks! { reap_stash { let s in 1 .. MAX_SPANS; let (stash, controller) = create_stash_controller::(0, 100, Default::default())?; + Staking::::validate(RawOrigin::Signed(controller.clone()).into(), ValidatorPrefs::default())?; add_slashing_spans::(&stash, s); T::Currency::make_free_balance_be(&stash, T::Currency::minimum_balance()); whitelist_account!(controller); + + assert!(Bonded::::contains_key(&stash)); + assert!(Validators::::contains_key(&stash)); + }: _(RawOrigin::Signed(controller), stash.clone(), s) verify { assert!(!Bonded::::contains_key(&stash)); + assert!(!Validators::::contains_key(&stash)); } new_era { @@ -563,9 +570,9 @@ benchmarks! { get_npos_voters { // number of validator intention. - let v in 200 .. 400; + let v in (MAX_VALIDATORS / 2) .. MAX_VALIDATORS; // number of nominator intention. - let n in 200 .. 400; + let n in (MAX_NOMINATORS / 2) .. MAX_NOMINATORS; // total number of slashing spans. Assigned to validators randomly. let s in 1 .. 20; @@ -584,15 +591,42 @@ benchmarks! { get_npos_targets { // number of validator intention. - let v in 200 .. 400; + let v in (MAX_VALIDATORS / 2) .. MAX_VALIDATORS; // number of nominator intention. - let n = 500; + let n = MAX_NOMINATORS; let _ = create_validators_with_nominators_for_era::(v, n, T::MAX_NOMINATIONS as usize, false, None)?; }: { let targets = >::get_npos_targets(); assert_eq!(targets.len() as u32, v); } + + update_staking_limits { + // This function always does the same thing... just write to 4 storage items. + }: _( + RawOrigin::Root, + BalanceOf::::max_value(), + BalanceOf::::max_value(), + Some(u32::max_value()), + Some(u32::max_value()) + ) verify { + assert_eq!(MinNominatorBond::::get(), BalanceOf::::max_value()); + assert_eq!(MinValidatorBond::::get(), BalanceOf::::max_value()); + assert_eq!(MaxNominatorsCount::::get(), Some(u32::max_value())); + assert_eq!(MaxValidatorsCount::::get(), Some(u32::max_value())); + } + + chill_other { + let (_, controller) = create_stash_controller::(USER_SEED, 100, Default::default())?; + Staking::::validate(RawOrigin::Signed(controller.clone()).into(), ValidatorPrefs::default())?; + Staking::::update_staking_limits( + RawOrigin::Root.into(), BalanceOf::::max_value(), BalanceOf::::max_value(), None, None, + )?; + let caller = whitelisted_caller(); + }: _(RawOrigin::Signed(caller), controller.clone()) + verify { + assert!(!Validators::::contains_key(controller)); + } } #[cfg(test)] @@ -603,7 +637,7 @@ mod tests { #[test] fn create_validators_with_nominators_for_era_works() { - ExtBuilder::default().has_stakers(true).build().execute_with(|| { + ExtBuilder::default().has_stakers(true).build_and_execute(|| { let v = 10; let n = 100; @@ -625,7 +659,7 @@ mod tests { #[test] fn create_validator_with_nominators_works() { - ExtBuilder::default().has_stakers(true).build().execute_with(|| { + ExtBuilder::default().has_stakers(true).build_and_execute(|| { let n = 10; let (validator_stash, nominators) = create_validator_with_nominators::( @@ -649,7 +683,7 @@ mod tests { #[test] fn add_slashing_spans_works() { - ExtBuilder::default().has_stakers(true).build().execute_with(|| { + ExtBuilder::default().has_stakers(true).build_and_execute(|| { let n = 10; let (validator_stash, _nominators) = create_validator_with_nominators::( @@ -680,7 +714,7 @@ mod tests { #[test] fn test_payout_all() { - ExtBuilder::default().has_stakers(true).build().execute_with(|| { + ExtBuilder::default().has_stakers(true).build_and_execute(|| { let v = 10; let n = 100; @@ -700,6 +734,7 @@ mod tests { impl_benchmark_test_suite!( Staking, - crate::mock::ExtBuilder::default().has_stakers(true).build(), + crate::mock::ExtBuilder::default().has_stakers(true), crate::mock::Test, + exec_name = build_and_execute ); diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ff7a1ae8a8820..b6d02fa2fd30d 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -745,17 +745,46 @@ enum Releases { V4_0_0, V5_0_0, // blockable validators. V6_0_0, // removal of all storage associated with offchain phragmen. + V7_0_0, // keep track of number of nominators / validators in map } impl Default for Releases { fn default() -> Self { - Releases::V6_0_0 + Releases::V7_0_0 } } pub mod migrations { use super::*; + pub mod v7 { + use super::*; + + pub fn pre_migrate() -> Result<(), &'static str> { + assert!(CurrentValidatorsCount::::get().is_zero(), "CurrentValidatorsCount already set."); + assert!(CurrentNominatorsCount::::get().is_zero(), "CurrentNominatorsCount already set."); + assert!(StorageVersion::::get() == Releases::V6_0_0); + Ok(()) + } + + pub fn migrate() -> Weight { + log!(info, "Migrating staking to Releases::V7_0_0"); + let validator_count = Validators::::iter().count() as u32; + let nominator_count = Nominators::::iter().count() as u32; + + CurrentValidatorsCount::::put(validator_count); + CurrentNominatorsCount::::put(nominator_count); + + StorageVersion::::put(Releases::V7_0_0); + log!(info, "Completed staking migration to Releases::V7_0_0"); + + T::DbWeight::get().reads_writes( + validator_count.saturating_add(nominator_count).into(), + 2, + ) + } + } + pub mod v6 { use super::*; use frame_support::{traits::Get, weights::Weight, generate_storage_alias}; @@ -940,6 +969,14 @@ pub mod pallet { #[pallet::getter(fn bonded)] pub type Bonded = StorageMap<_, Twox64Concat, T::AccountId, T::AccountId>; + /// The minimum active bond to become and maintain the role of a nominator. + #[pallet::storage] + pub type MinNominatorBond = StorageValue<_, BalanceOf, ValueQuery>; + + /// The minimum active bond to become and maintain the role of a validator. + #[pallet::storage] + pub type MinValidatorBond = StorageValue<_, BalanceOf, ValueQuery>; + /// Map from all (unlocked) "controller" accounts to the info regarding the staking. #[pallet::storage] #[pallet::getter(fn ledger)] @@ -960,15 +997,39 @@ pub mod pallet { >; /// The map from (wannabe) validator stash key to the preferences of that validator. + /// + /// When updating this storage item, you must also update the `CurrentValidatorsCount`. #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = StorageMap<_, Twox64Concat, T::AccountId, ValidatorPrefs, ValueQuery>; + /// A tracker to keep count of the number of items in the `Validators` map. + #[pallet::storage] + pub type CurrentValidatorsCount = StorageValue<_, u32, ValueQuery>; + + /// The maximum validator count before we stop allowing new validators to join. + /// + /// When this value is not set, no limits are enforced. + #[pallet::storage] + pub type MaxValidatorsCount = StorageValue<_, u32, OptionQuery>; + /// The map from nominator stash key to the set of stash keys of all validators to nominate. + /// + /// When updating this storage item, you must also update the `CurrentNominatorsCount`. #[pallet::storage] #[pallet::getter(fn nominators)] pub type Nominators = StorageMap<_, Twox64Concat, T::AccountId, Nominations>; + /// A tracker to keep count of the number of items in the `Nominators` map. + #[pallet::storage] + pub type CurrentNominatorsCount = StorageValue<_, u32, ValueQuery>; + + /// The maximum nominator count before we stop allowing new validators to join. + /// + /// When this value is not set, no limits are enforced. + #[pallet::storage] + pub type MaxNominatorsCount = StorageValue<_, u32, OptionQuery>; + /// The current era index. /// /// This is the latest planned era, depending on how the Session pallet queues the validator @@ -1165,6 +1226,8 @@ pub mod pallet { pub slash_reward_fraction: Perbill, pub canceled_payout: BalanceOf, pub stakers: Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>, + pub min_nominator_bond: BalanceOf, + pub min_validator_bond: BalanceOf, } #[cfg(feature = "std")] @@ -1179,6 +1242,8 @@ pub mod pallet { slash_reward_fraction: Default::default(), canceled_payout: Default::default(), stakers: Default::default(), + min_nominator_bond: Default::default(), + min_validator_bond: Default::default(), } } } @@ -1194,6 +1259,8 @@ pub mod pallet { CanceledSlashPayout::::put(self.canceled_payout); SlashRewardFraction::::put(self.slash_reward_fraction); StorageVersion::::put(Releases::V6_0_0); + MinNominatorBond::::put(self.min_nominator_bond); + MinValidatorBond::::put(self.min_validator_bond); for &(ref stash, ref controller, balance, ref status) in &self.stakers { assert!( @@ -1274,8 +1341,8 @@ pub mod pallet { DuplicateIndex, /// Slash record index out of bounds. InvalidSlashIndex, - /// Can not bond with value less than minimum balance. - InsufficientValue, + /// Can not bond with value less than minimum required. + InsufficientBond, /// Can not schedule more unlock chunks. NoMoreChunks, /// Can not rebond without unlocking chunks. @@ -1300,18 +1367,35 @@ pub mod pallet { TooManyTargets, /// A nomination target was supplied that was blocked or otherwise not a validator. BadTarget, + /// The user has enough bond and thus cannot be chilled forcefully by an external person. + CannotChillOther, + /// There are too many nominators in the system. Governance needs to adjust the staking settings + /// to keep things safe for the runtime. + TooManyNominators, + /// There are too many validators in the system. Governance needs to adjust the staking settings + /// to keep things safe for the runtime. + TooManyValidators, } #[pallet::hooks] impl Hooks> for Pallet { fn on_runtime_upgrade() -> Weight { - if StorageVersion::::get() == Releases::V5_0_0 { - migrations::v6::migrate::() + if StorageVersion::::get() == Releases::V6_0_0 { + migrations::v7::migrate::() } else { T::DbWeight::get().reads(1) } } + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + if StorageVersion::::get() == Releases::V6_0_0 { + migrations::v7::pre_migrate::() + } else { + Ok(()) + } + } + fn on_initialize(_now: BlockNumberFor) -> Weight { // just return the weight of the on_finalize. T::DbWeight::get().reads(1) @@ -1389,7 +1473,7 @@ pub mod pallet { // Reject a bond which is considered to be _dust_. if value < T::Currency::minimum_balance() { - Err(Error::::InsufficientValue)? + Err(Error::::InsufficientBond)? } frame_system::Pallet::::inc_consumers(&stash).map_err(|_| Error::::BadState)?; @@ -1454,7 +1538,7 @@ pub mod pallet { ledger.total += extra; ledger.active += extra; // Last check: the new active amount of ledger must be more than ED. - ensure!(ledger.active >= T::Currency::minimum_balance(), Error::::InsufficientValue); + ensure!(ledger.active >= T::Currency::minimum_balance(), Error::::InsufficientBond); Self::deposit_event(Event::::Bonded(stash, extra)); Self::update_ledger(&controller, &ledger); @@ -1473,6 +1557,9 @@ pub mod pallet { /// can co-exists at the same time. In that case, [`Call::withdraw_unbonded`] need /// to be called first to remove some of the chunks (if possible). /// + /// If a user encounters the `InsufficientBond` error when calling this extrinsic, + /// they should call `chill` first in order to free up their bonded funds. + /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// @@ -1514,6 +1601,18 @@ pub mod pallet { ledger.active = Zero::zero(); } + let min_active_bond = if Nominators::::contains_key(&ledger.stash) { + MinNominatorBond::::get() + } else if Validators::::contains_key(&ledger.stash) { + MinValidatorBond::::get() + } else { + Zero::zero() + }; + + // Make sure that the user maintains enough active bond for their role. + // If a user runs into this error, they should chill first. + ensure!(ledger.active >= min_active_bond, Error::::InsufficientBond); + // Note: in case there is no current era it is fine to bond one era more. let era = Self::current_era().unwrap_or(0) + T::BondingDuration::get(); ledger.unlocking.push(UnlockChunk { value, era }); @@ -1614,10 +1713,19 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::validate())] pub fn validate(origin: OriginFor, prefs: ValidatorPrefs) -> DispatchResult { let controller = ensure_signed(origin)?; + + // If this error is reached, we need to adjust the `MinValidatorBond` and start calling `chill_other`. + // Until then, we explicitly block new validators to protect the runtime. + if let Some(max_validators) = MaxValidatorsCount::::get() { + ensure!(CurrentValidatorsCount::::get() < max_validators, Error::::TooManyValidators); + } + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + ensure!(ledger.active >= MinValidatorBond::::get(), Error::::InsufficientBond); + let stash = &ledger.stash; - >::remove(stash); - >::insert(stash, prefs); + Self::do_remove_nominator(stash); + Self::do_add_validator(stash, prefs); Ok(()) } @@ -1646,7 +1754,16 @@ pub mod pallet { targets: Vec<::Source>, ) -> DispatchResult { let controller = ensure_signed(origin)?; + + // If this error is reached, we need to adjust the `MinNominatorBond` and start calling `chill_other`. + // Until then, we explicitly block new nominators to protect the runtime. + if let Some(max_nominators) = MaxNominatorsCount::::get() { + ensure!(CurrentNominatorsCount::::get() < max_nominators, Error::::TooManyNominators); + } + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + ensure!(ledger.active >= MinNominatorBond::::get(), Error::::InsufficientBond); + let stash = &ledger.stash; ensure!(!targets.is_empty(), Error::::EmptyTargets); ensure!(targets.len() <= T::MAX_NOMINATIONS as usize, Error::::TooManyTargets); @@ -1669,8 +1786,8 @@ pub mod pallet { suppressed: false, }; - >::remove(stash); - >::insert(stash, &nominations); + Self::do_remove_validator(stash); + Self::do_add_nominator(stash, nominations); Ok(()) } @@ -2022,7 +2139,7 @@ pub mod pallet { let ledger = ledger.rebond(value); // Last check: the new active amount of ledger must be more than ED. - ensure!(ledger.active >= T::Currency::minimum_balance(), Error::::InsufficientValue); + ensure!(ledger.active >= T::Currency::minimum_balance(), Error::::InsufficientBond); Self::deposit_event(Event::::Bonded(ledger.stash.clone(), value)); Self::update_ledger(&controller, &ledger); @@ -2135,6 +2252,80 @@ pub mod pallet { Ok(()) } + + /// Update the various staking limits this pallet. + /// + /// * `min_nominator_bond`: The minimum active bond needed to be a nominator. + /// * `min_validator_bond`: The minimum active bond needed to be a validator. + /// * `max_nominator_count`: The max number of users who can be a nominator at once. + /// When set to `None`, no limit is enforced. + /// * `max_validator_count`: The max number of users who can be a validator at once. + /// When set to `None`, no limit is enforced. + /// + /// Origin must be Root to call this function. + /// + /// NOTE: Existing nominators and validators will not be affected by this update. + /// to kick people under the new limits, `chill_other` should be called. + #[pallet::weight(T::WeightInfo::update_staking_limits())] + pub fn update_staking_limits( + origin: OriginFor, + min_nominator_bond: BalanceOf, + min_validator_bond: BalanceOf, + max_nominator_count: Option, + max_validator_count: Option, + ) -> DispatchResult { + ensure_root(origin)?; + MinNominatorBond::::set(min_nominator_bond); + MinValidatorBond::::set(min_validator_bond); + MaxNominatorsCount::::set(max_nominator_count); + MaxValidatorsCount::::set(max_validator_count); + Ok(()) + } + + /// Declare a `controller` as having no desire to either validator or nominate. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// The dispatch origin for this call must be _Signed_, but can be called by anyone. + /// + /// If the caller is the same as the controller being targeted, then no further checks + /// are enforced. However, this call can also be made by an third party user who witnesses + /// that this controller does not satisfy the minimum bond requirements to be in their role. + /// + /// This can be helpful if bond requirements are updated, and we need to remove old users + /// who do not satisfy these requirements. + /// + // TODO: Maybe we can deprecate `chill` in the future. + // https://github.com/paritytech/substrate/issues/9111 + #[pallet::weight(T::WeightInfo::chill_other())] + pub fn chill_other( + origin: OriginFor, + controller: T::AccountId, + ) -> DispatchResult { + // Anyone can call this function. + let caller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + let stash = ledger.stash; + + // If the caller is not the controller, we want to check that the minimum bond + // requirements are not satisfied, and thus we have reason to chill this user. + // + // Otherwise, if caller is the same as the controller, this is just like `chill`. + if caller != controller { + let min_active_bond = if Nominators::::contains_key(&stash) { + MinNominatorBond::::get() + } else if Validators::::contains_key(&stash) { + MinValidatorBond::::get() + } else { + Zero::zero() + }; + + ensure!(ledger.active < min_active_bond, Error::::CannotChillOther); + } + + Self::chill_stash(&stash); + Ok(()) + } } } @@ -2296,8 +2487,8 @@ impl Pallet { /// Chill a stash account. fn chill_stash(stash: &T::AccountId) { - >::remove(stash); - >::remove(stash); + Self::do_remove_validator(stash); + Self::do_remove_nominator(stash); } /// Actually make a payment to a staker. This uses the currency's reward function @@ -2645,8 +2836,8 @@ impl Pallet { >::remove(&controller); >::remove(stash); - >::remove(stash); - >::remove(stash); + Self::do_remove_validator(stash); + Self::do_remove_nominator(stash); frame_system::Pallet::::dec_consumers(stash); @@ -2749,7 +2940,7 @@ impl Pallet { // Collect all slashing spans into a BTreeMap for further queries. let slashing_spans = >::iter().collect::>(); - for (nominator, nominations) in >::iter() { + for (nominator, nominations) in Nominators::::iter() { let Nominations { submitted_in, mut targets, suppressed: _ } = nominations; // Filter out nomination targets which were nominated before the most recent @@ -2769,8 +2960,49 @@ impl Pallet { all_voters } + /// This is a very expensive function and result should be cached versus being called multiple times. pub fn get_npos_targets() -> Vec { - >::iter().map(|(v, _)| v).collect::>() + Validators::::iter().map(|(v, _)| v).collect::>() + } + + /// This function will add a nominator to the `Nominators` storage map, + /// and keep track of the `CurrentNominatorsCount`. + /// + /// If the nominator already exists, their nominations will be updated. + pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { + if !Nominators::::contains_key(who) { + CurrentNominatorsCount::::mutate(|x| x.saturating_inc()) + } + Nominators::::insert(who, nominations); + } + + /// This function will remove a nominator from the `Nominators` storage map, + /// and keep track of the `CurrentNominatorsCount`. + pub fn do_remove_nominator(who: &T::AccountId) { + if Nominators::::contains_key(who) { + Nominators::::remove(who); + CurrentNominatorsCount::::mutate(|x| x.saturating_dec()); + } + } + + /// This function will add a validator to the `Validators` storage map, + /// and keep track of the `CurrentValidatorsCount`. + /// + /// If the validator already exists, their preferences will be updated. + pub fn do_add_validator(who: &T::AccountId, prefs: ValidatorPrefs) { + if !Validators::::contains_key(who) { + CurrentValidatorsCount::::mutate(|x| x.saturating_inc()) + } + Validators::::insert(who, prefs); + } + + /// This function will remove a validator from the `Validators` storage map, + /// and keep track of the `CurrentValidatorsCount`. + pub fn do_remove_validator(who: &T::AccountId) { + if Validators::::contains_key(who) { + Validators::::remove(who); + CurrentValidatorsCount::::mutate(|x| x.saturating_dec()); + } } } @@ -2785,12 +3017,11 @@ impl frame_election_provider_support::ElectionDataProvider, ) -> data_provider::Result<(Vec<(T::AccountId, VoteWeight, Vec)>, Weight)> { - // NOTE: reading these counts already needs to iterate a lot of storage keys, but they get - // cached. This is okay for the case of `Ok(_)`, but bad for `Err(_)`, as the trait does not - // report weight in failures. - let nominator_count = >::iter().count(); - let validator_count = >::iter().count(); - let voter_count = nominator_count.saturating_add(validator_count); + let nominator_count = CurrentNominatorsCount::::get(); + let validator_count = CurrentValidatorsCount::::get(); + let voter_count = nominator_count.saturating_add(validator_count) as usize; + debug_assert!(>::iter().count() as u32 == CurrentNominatorsCount::::get()); + debug_assert!(>::iter().count() as u32 == CurrentValidatorsCount::::get()); if maybe_max_len.map_or(false, |max_len| voter_count > max_len) { return Err("Voter snapshot too big"); @@ -2798,15 +3029,15 @@ impl frame_election_provider_support::ElectionDataProvider>::iter().count(); let weight = T::WeightInfo::get_npos_voters( - validator_count as u32, - nominator_count as u32, + nominator_count, + validator_count, slashing_span_count as u32, ); Ok((Self::get_npos_voters(), weight)) } fn targets(maybe_max_len: Option) -> data_provider::Result<(Vec, Weight)> { - let target_count = >::iter().count(); + let target_count = CurrentValidatorsCount::::get() as usize; if maybe_max_len.map_or(false, |max_len| target_count > max_len) { return Err("Target snapshot too big"); @@ -2859,7 +3090,7 @@ impl frame_election_provider_support::ElectionDataProvider = target_stake .and_then(|w| >::try_from(w).ok()) - .unwrap_or(T::Currency::minimum_balance() * 100u32.into()); + .unwrap_or(MinNominatorBond::::get() * 100u32.into()); >::insert(v.clone(), v.clone()); >::insert( v.clone(), @@ -2871,8 +3102,8 @@ impl frame_election_provider_support::ElectionDataProvider>::insert( - v, + Self::do_add_validator( + &v, ValidatorPrefs { commission: Perbill::zero(), blocked: false }, ); }); @@ -2892,8 +3123,8 @@ impl frame_election_provider_support::ElectionDataProvider>::insert( - v, + Self::do_add_nominator( + &v, Nominations { targets: t, submitted_in: 0, suppressed: false }, ); }); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index f58cdf0d2350f..35a1fa45284da 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -242,6 +242,7 @@ impl onchain::Config for Test { type Accuracy = Perbill; type DataProvider = Staking; } + impl Config for Test { const MAX_NOMINATIONS: u32 = 16; type Currency = Balances; @@ -286,6 +287,8 @@ pub struct ExtBuilder { invulnerables: Vec, has_stakers: bool, initialize_first_session: bool, + min_nominator_bond: Balance, + min_validator_bond: Balance, } impl Default for ExtBuilder { @@ -300,6 +303,8 @@ impl Default for ExtBuilder { invulnerables: vec![], has_stakers: true, initialize_first_session: true, + min_nominator_bond: ExistentialDeposit::get(), + min_validator_bond: ExistentialDeposit::get(), } } } @@ -361,7 +366,15 @@ impl ExtBuilder { OFFSET.with(|v| *v.borrow_mut() = offset); self } - pub fn build(self) -> sp_io::TestExternalities { + pub fn min_nominator_bond(mut self, amount: Balance) -> Self { + self.min_nominator_bond = amount; + self + } + pub fn min_validator_bond(mut self, amount: Balance) -> Self { + self.min_validator_bond = amount; + self + } + fn build(self) -> sp_io::TestExternalities { sp_tracing::try_init_simple(); let mut storage = frame_system::GenesisConfig::default() .build_storage::() @@ -434,6 +447,8 @@ impl ExtBuilder { minimum_validator_count: self.minimum_validator_count, invulnerables: self.invulnerables, slash_reward_fraction: Perbill::from_percent(10), + min_nominator_bond: self.min_nominator_bond, + min_validator_bond: self.min_validator_bond, ..Default::default() } .assimilate_storage(&mut storage); @@ -477,6 +492,14 @@ fn post_conditions() { check_nominators(); check_exposures(); check_ledgers(); + check_count(); +} + +fn check_count() { + let nominator_count = Nominators::::iter().count() as u32; + let validator_count = Validators::::iter().count() as u32; + assert_eq!(nominator_count, CurrentNominatorsCount::::get()); + assert_eq!(validator_count, CurrentValidatorsCount::::get()); } fn check_ledgers() { diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index f3af4ac0920d1..8a4392edfed25 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -30,7 +30,9 @@ const SEED: u32 = 0; /// This function removes all validators and nominators from storage. pub fn clear_validators_and_nominators() { Validators::::remove_all(None); + CurrentValidatorsCount::::kill(); Nominators::::remove_all(None); + CurrentNominatorsCount::::kill(); } /// Grab a funded user. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index ee8f78769e70a..976ee34d9b8eb 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -297,8 +297,7 @@ fn staking_should_work() { ExtBuilder::default() .nominate(false) .fair(false) // to give 20 more staked value - .build() - .execute_with(|| { + .build_and_execute(|| { // remember + compare this along with the test. assert_eq_uvec!(validator_controllers(), vec![20, 10]); @@ -374,8 +373,7 @@ fn blocking_and_kicking_works() { .validator_count(4) .nominate(true) .num_validators(3) - .build() - .execute_with(|| { + .build_and_execute(|| { // block validator 10/11 assert_ok!(Staking::validate(Origin::signed(10), ValidatorPrefs { blocked: true, .. Default::default() })); // attempt to nominate from 100/101... @@ -398,8 +396,7 @@ fn less_than_needed_candidates_works() { .validator_count(4) .nominate(false) .num_validators(3) - .build() - .execute_with(|| { + .build_and_execute(|| { assert_eq!(Staking::validator_count(), 4); assert_eq!(Staking::minimum_validator_count(), 1); assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); @@ -426,8 +423,7 @@ fn no_candidate_emergency_condition() { .num_validators(4) .validator_pool(true) .nominate(false) - .build() - .execute_with(|| { + .build_and_execute(|| { // initial validators assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); let prefs = ValidatorPrefs { commission: Perbill::one(), .. Default::default() }; @@ -468,8 +464,7 @@ fn nominating_and_rewards_should_work() { ExtBuilder::default() .nominate(false) .validator_pool(true) - .build() - .execute_with(|| { + .build_and_execute(|| { // initial validators -- everyone is actually even. assert_eq_uvec!(validator_controllers(), vec![40, 30]); @@ -1254,8 +1249,7 @@ fn rebond_works() { // * it can re-bond a portion of the funds scheduled to unlock. ExtBuilder::default() .nominate(false) - .build() - .execute_with(|| { + .build_and_execute(|| { // Set payee to controller. avoids confusion assert_ok!(Staking::set_payee( Origin::signed(10), @@ -1399,8 +1393,7 @@ fn rebond_is_fifo() { // Rebond should proceed by reversing the most recent bond operations. ExtBuilder::default() .nominate(false) - .build() - .execute_with(|| { + .build_and_execute(|| { // Set payee to controller. avoids confusion assert_ok!(Staking::set_payee( Origin::signed(10), @@ -1547,109 +1540,117 @@ fn reward_to_stake_works() { fn on_free_balance_zero_stash_removes_validator() { // Tests that validator storage items are cleaned up when stash is empty // Tests that storage items are untouched when controller is empty - ExtBuilder::default().existential_deposit(10).build_and_execute(|| { - // Check the balance of the validator account - assert_eq!(Balances::free_balance(10), 256); - // Check the balance of the stash account - assert_eq!(Balances::free_balance(11), 256000); - // Check these two accounts are bonded - assert_eq!(Staking::bonded(&11), Some(10)); - - // Set some storage items which we expect to be cleaned up - // Set payee information - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); - - // Check storage items that should be cleaned up - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - - // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, Balance::max_value()); - - // Check the balance of the stash account has not been touched - assert_eq!(Balances::free_balance(11), 256000); - // Check these two accounts are still bonded - assert_eq!(Staking::bonded(&11), Some(10)); - - // Check storage items have not changed - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - - // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, Balance::max_value()); - // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 10); - - // Reap the stash - assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); - - // Check storage items do not exist - assert!(!>::contains_key(&10)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - }); + ExtBuilder::default() + .existential_deposit(10) + .min_nominator_bond(10) + .min_validator_bond(10) + .build_and_execute(|| { + // Check the balance of the validator account + assert_eq!(Balances::free_balance(10), 256); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(11), 256000); + // Check these two accounts are bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Set some storage items which we expect to be cleaned up + // Set payee information + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); + + // Check storage items that should be cleaned up + assert!(>::contains_key(&10)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + + // Reduce free_balance of controller to 0 + let _ = Balances::slash(&10, Balance::max_value()); + + // Check the balance of the stash account has not been touched + assert_eq!(Balances::free_balance(11), 256000); + // Check these two accounts are still bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Check storage items have not changed + assert!(>::contains_key(&10)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + + // Reduce free_balance of stash to 0 + let _ = Balances::slash(&11, Balance::max_value()); + // Check total balance of stash + assert_eq!(Balances::total_balance(&11), 10); + + // Reap the stash + assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); + + // Check storage items do not exist + assert!(!>::contains_key(&10)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + }); } #[test] fn on_free_balance_zero_stash_removes_nominator() { // Tests that nominator storage items are cleaned up when stash is empty // Tests that storage items are untouched when controller is empty - ExtBuilder::default().existential_deposit(10).build_and_execute(|| { - // Make 10 a nominator - assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); - // Check that account 10 is a nominator - assert!(>::contains_key(11)); - // Check the balance of the nominator account - assert_eq!(Balances::free_balance(10), 256); - // Check the balance of the stash account - assert_eq!(Balances::free_balance(11), 256000); - - // Set payee information - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); - - // Check storage items that should be cleaned up - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - - // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, Balance::max_value()); - // Check total balance of account 10 - assert_eq!(Balances::total_balance(&10), 0); - - // Check the balance of the stash account has not been touched - assert_eq!(Balances::free_balance(11), 256000); - // Check these two accounts are still bonded - assert_eq!(Staking::bonded(&11), Some(10)); - - // Check storage items have not changed - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - - // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, Balance::max_value()); - // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 10); - - // Reap the stash - assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); - - // Check storage items do not exist - assert!(!>::contains_key(&10)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - }); + ExtBuilder::default() + .existential_deposit(10) + .min_nominator_bond(10) + .min_validator_bond(10) + .build_and_execute(|| { + // Make 10 a nominator + assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); + // Check that account 10 is a nominator + assert!(>::contains_key(11)); + // Check the balance of the nominator account + assert_eq!(Balances::free_balance(10), 256); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(11), 256000); + + // Set payee information + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); + + // Check storage items that should be cleaned up + assert!(>::contains_key(&10)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + + // Reduce free_balance of controller to 0 + let _ = Balances::slash(&10, Balance::max_value()); + // Check total balance of account 10 + assert_eq!(Balances::total_balance(&10), 0); + + // Check the balance of the stash account has not been touched + assert_eq!(Balances::free_balance(11), 256000); + // Check these two accounts are still bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Check storage items have not changed + assert!(>::contains_key(&10)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + + // Reduce free_balance of stash to 0 + let _ = Balances::slash(&11, Balance::max_value()); + // Check total balance of stash + assert_eq!(Balances::total_balance(&11), 10); + + // Reap the stash + assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); + + // Check storage items do not exist + assert!(!>::contains_key(&10)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + }); } @@ -1725,14 +1726,15 @@ fn bond_with_no_staked_value() { ExtBuilder::default() .validator_count(3) .existential_deposit(5) + .min_nominator_bond(5) + .min_validator_bond(5) .nominate(false) .minimum_validator_count(1) - .build() - .execute_with(|| { + .build_and_execute(|| { // Can't bond with 1 assert_noop!( Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller), - Error::::InsufficientValue, + Error::::InsufficientBond, ); // bonded with absolute minimum value possible. assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::Controller)); @@ -1774,8 +1776,7 @@ fn bond_with_little_staked_value_bounded() { .validator_count(3) .nominate(false) .minimum_validator_count(1) - .build() - .execute_with(|| { + .build_and_execute(|| { // setup assert_ok!(Staking::chill(Origin::signed(30))); assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); @@ -1828,8 +1829,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_election_provider() { .validator_count(2) .nominate(false) .minimum_validator_count(1) - .build() - .execute_with(|| { + .build_and_execute(|| { // disable the nominator assert_ok!(Staking::chill(Origin::signed(100))); // make stakes equal. @@ -1876,8 +1876,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_election_provider_elected() { .validator_count(2) .nominate(false) .minimum_validator_count(1) - .build() - .execute_with(|| { + .build_and_execute(|| { // disable the nominator assert_ok!(Staking::chill(Origin::signed(100))); // 31/30 will have less stake @@ -1923,8 +1922,7 @@ fn new_era_elects_correct_number_of_validators() { .validator_pool(true) .fair(true) .validator_count(1) - .build() - .execute_with(|| { + .build_and_execute(|| { assert_eq!(Staking::validator_count(), 1); assert_eq!(validator_controllers().len(), 1); @@ -2466,7 +2464,11 @@ fn only_slash_for_max_in_era() { #[test] fn garbage_collection_after_slashing() { // ensures that `SlashingSpans` and `SpanSlash` of an account is removed after reaping. - ExtBuilder::default().existential_deposit(2).build_and_execute(|| { + ExtBuilder::default() + .existential_deposit(2) + .min_nominator_bond(2) + .min_validator_bond(2) + .build_and_execute(|| { assert_eq!(Balances::free_balance(11), 256_000); on_offence_now( @@ -3723,6 +3725,8 @@ fn session_buffering_no_offset() { fn cannot_rebond_to_lower_than_ed() { ExtBuilder::default() .existential_deposit(10) + .min_nominator_bond(10) + .min_validator_bond(10) .build_and_execute(|| { // stash must have more balance than bonded for this to work. assert_eq!(Balances::free_balance(&21), 512_000); @@ -3739,7 +3743,8 @@ fn cannot_rebond_to_lower_than_ed() { } ); - // unbond all of it. + // unbond all of it. must be chilled first. + assert_ok!(Staking::chill(Origin::signed(20))); assert_ok!(Staking::unbond(Origin::signed(20), 1000)); assert_eq!( Staking::ledger(&20).unwrap(), @@ -3755,7 +3760,7 @@ fn cannot_rebond_to_lower_than_ed() { // now bond a wee bit more assert_noop!( Staking::rebond(Origin::signed(20), 5), - Error::::InsufficientValue, + Error::::InsufficientBond, ); }) } @@ -3764,6 +3769,8 @@ fn cannot_rebond_to_lower_than_ed() { fn cannot_bond_extra_to_lower_than_ed() { ExtBuilder::default() .existential_deposit(10) + .min_nominator_bond(10) + .min_validator_bond(10) .build_and_execute(|| { // stash must have more balance than bonded for this to work. assert_eq!(Balances::free_balance(&21), 512_000); @@ -3780,7 +3787,8 @@ fn cannot_bond_extra_to_lower_than_ed() { } ); - // unbond all of it. + // unbond all of it. must be chilled first. + assert_ok!(Staking::chill(Origin::signed(20))); assert_ok!(Staking::unbond(Origin::signed(20), 1000)); assert_eq!( Staking::ledger(&20).unwrap(), @@ -3799,7 +3807,7 @@ fn cannot_bond_extra_to_lower_than_ed() { // now bond a wee bit more assert_noop!( Staking::bond_extra(Origin::signed(21), 5), - Error::::InsufficientValue, + Error::::InsufficientBond, ); }) } @@ -3809,6 +3817,8 @@ fn do_not_die_when_active_is_ed() { let ed = 10; ExtBuilder::default() .existential_deposit(ed) + .min_nominator_bond(ed) + .min_validator_bond(ed) .build_and_execute(|| { // initial stuff. assert_eq!( @@ -3888,7 +3898,7 @@ mod election_data_provider { #[test] fn voters_include_self_vote() { - ExtBuilder::default().nominate(false).build().execute_with(|| { + ExtBuilder::default().nominate(false).build_and_execute(|| { assert!(>::iter().map(|(x, _)| x).all(|v| Staking::voters(None) .unwrap() .0 @@ -3900,7 +3910,7 @@ mod election_data_provider { #[test] fn voters_exclude_slashed() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( >::voters(None) @@ -3946,7 +3956,7 @@ mod election_data_provider { #[test] fn respects_len_limits() { - ExtBuilder::default().build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::voters(Some(1)).unwrap_err(), "Voter snapshot too big"); assert_eq!(Staking::targets(Some(1)).unwrap_err(), "Target snapshot too big"); }); @@ -3954,7 +3964,7 @@ mod election_data_provider { #[test] fn estimate_next_election_works() { - ExtBuilder::default().session_per_era(5).period(5).build().execute_with(|| { + ExtBuilder::default().session_per_era(5).period(5).build_and_execute(|| { // first session is always length 0. for b in 1..20 { run_to_block(b); @@ -4013,4 +4023,129 @@ mod election_data_provider { assert_eq!(ForceEra::::get(), Forcing::NotForcing); }) } + + #[test] + #[should_panic] + fn count_check_works() { + ExtBuilder::default().build_and_execute(|| { + // We should never insert into the validators or nominators map directly as this will + // not keep track of the count. This test should panic as we verify the count is accurate + // after every test using the `post_checks` in `mock`. + Validators::::insert(987654321, ValidatorPrefs::default()); + Nominators::::insert(987654321, Nominations { + targets: vec![], + submitted_in: Default::default(), + suppressed: false, + }); + }) + } + + #[test] + fn min_bond_checks_work() { + ExtBuilder::default() + .existential_deposit(100) + .min_nominator_bond(1_000) + .min_validator_bond(1_500) + .build_and_execute(|| { + // 500 is not enough for any role + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller)); + assert_noop!(Staking::nominate(Origin::signed(4), vec![1]), Error::::InsufficientBond); + assert_noop!(Staking::validate(Origin::signed(4), ValidatorPrefs::default()), Error::::InsufficientBond); + + // 1000 is enough for nominator + assert_ok!(Staking::bond_extra(Origin::signed(3), 500)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![1])); + assert_noop!(Staking::validate(Origin::signed(4), ValidatorPrefs::default()), Error::::InsufficientBond); + + // 1500 is enough for validator + assert_ok!(Staking::bond_extra(Origin::signed(3), 500)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![1])); + assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + + // Can't unbond anything as validator + assert_noop!(Staking::unbond(Origin::signed(4), 500), Error::::InsufficientBond); + + // Once they are a nominator, they can unbond 500 + assert_ok!(Staking::nominate(Origin::signed(4), vec![1])); + assert_ok!(Staking::unbond(Origin::signed(4), 500)); + assert_noop!(Staking::unbond(Origin::signed(4), 500), Error::::InsufficientBond); + + // Once they are chilled they can unbond everything + assert_ok!(Staking::chill(Origin::signed(4))); + assert_ok!(Staking::unbond(Origin::signed(4), 1000)); + }) + } + + #[test] + fn chill_other_works() { + ExtBuilder::default() + .existential_deposit(100) + .min_nominator_bond(1_000) + .min_validator_bond(1_500) + .build_and_execute(|| { + // Nominator + assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); + + // Validator + assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + + // Can't chill these users + assert_noop!(Staking::chill_other(Origin::signed(1), 2), Error::::CannotChillOther); + assert_noop!(Staking::chill_other(Origin::signed(1), 4), Error::::CannotChillOther); + + // Change the minimum bond + assert_ok!(Staking::update_staking_limits(Origin::root(), 1_500, 2_000, None, None)); + + // Users can now be chilled + assert_ok!(Staking::chill_other(Origin::signed(1), 2)); + assert_ok!(Staking::chill_other(Origin::signed(1), 4)); + }) + } + + #[test] + fn capped_stakers_works() { + ExtBuilder::default().build_and_execute(|| { + let validator_count = CurrentValidatorsCount::::get(); + assert_eq!(validator_count, 3); + let nominator_count = CurrentNominatorsCount::::get(); + assert_eq!(nominator_count, 1); + + // Change the maximums + let max = 10; + assert_ok!(Staking::update_staking_limits(Origin::root(), 10, 10, Some(max), Some(max))); + + // can create `max - validator_count` validators + assert_ok!(testing_utils::create_validators::(max - validator_count, 100)); + + // but no more + let (_, last_validator) = testing_utils::create_stash_controller::( + 1337, 100, RewardDestination::Controller, + ).unwrap(); + assert_noop!( + Staking::validate(Origin::signed(last_validator), ValidatorPrefs::default()), + Error::::TooManyValidators, + ); + + // same with nominators + for i in 0 .. max - nominator_count { + let (_, controller) = testing_utils::create_stash_controller::( + i + 10_000_000, 100, RewardDestination::Controller, + ).unwrap(); + assert_ok!(Staking::nominate(Origin::signed(controller), vec![1])); + } + + // one more is too many + let (_, last_nominator) = testing_utils::create_stash_controller::( + 20_000_000, 100, RewardDestination::Controller, + ).unwrap(); + assert_noop!(Staking::nominate(Origin::signed(last_nominator), vec![1]), Error::::TooManyNominators); + + // No problem when we set to `None` again + assert_ok!(Staking::update_staking_limits(Origin::root(), 10, 10, None, None)); + assert_ok!(Staking::nominate(Origin::signed(last_nominator), vec![1])); + assert_ok!(Staking::validate(Origin::signed(last_validator), ValidatorPrefs::default())); + }) + } } diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 5960d6612566e..980b0855fbd81 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-07, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-06-15, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -70,365 +70,383 @@ pub trait WeightInfo { fn new_era(v: u32, n: u32, ) -> Weight; fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight; fn get_npos_targets(v: u32, ) -> Weight; + fn update_staking_limits() -> Weight; + fn chill_other() -> Weight; } /// Weights for pallet_staking using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn bond() -> Weight { - (91_959_000 as Weight) + (91_278_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn bond_extra() -> Weight { - (69_291_000 as Weight) + (69_833_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn unbond() -> Weight { - (63_513_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (75_020_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn withdraw_unbonded_update(s: u32, ) -> Weight { - (64_747_000 as Weight) - // Standard Error: 0 - .saturating_add((77_000 as Weight).saturating_mul(s as Weight)) + (63_898_000 as Weight) + // Standard Error: 1_000 + .saturating_add((50_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn withdraw_unbonded_kill(s: u32, ) -> Weight { - (100_375_000 as Weight) + (103_717_000 as Weight) // Standard Error: 1_000 - .saturating_add((3_067_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add((2_942_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } fn validate() -> Weight { - (17_849_000 as Weight) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) + (40_702_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn kick(k: u32, ) -> Weight { - (27_939_000 as Weight) - // Standard Error: 16_000 - .saturating_add((21_431_000 as Weight).saturating_mul(k as Weight)) + (33_572_000 as Weight) + // Standard Error: 18_000 + .saturating_add((20_771_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } fn nominate(n: u32, ) -> Weight { - (32_791_000 as Weight) - // Standard Error: 33_000 - .saturating_add((7_006_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (53_561_000 as Weight) + // Standard Error: 34_000 + .saturating_add((6_652_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn chill() -> Weight { - (17_014_000 as Weight) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + (21_489_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) } fn set_payee() -> Weight { - (14_816_000 as Weight) + (14_514_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn set_controller() -> Weight { - (33_600_000 as Weight) + (32_598_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn set_validator_count() -> Weight { - (2_706_000 as Weight) + (2_477_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn force_no_eras() -> Weight { - (2_973_000 as Weight) + (2_743_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn force_new_era() -> Weight { - (2_949_000 as Weight) + (2_784_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn force_new_era_always() -> Weight { - (3_011_000 as Weight) + (2_749_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn set_invulnerables(v: u32, ) -> Weight { - (3_078_000 as Weight) + (2_798_000 as Weight) // Standard Error: 0 .saturating_add((5_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn force_unstake(s: u32, ) -> Weight { - (69_220_000 as Weight) - // Standard Error: 1_000 - .saturating_add((3_070_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + (70_372_000 as Weight) + // Standard Error: 13_000 + .saturating_add((3_029_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } fn cancel_deferred_slash(s: u32, ) -> Weight { - (3_460_399_000 as Weight) - // Standard Error: 222_000 - .saturating_add((19_782_000 as Weight).saturating_mul(s as Weight)) + (3_436_822_000 as Weight) + // Standard Error: 221_000 + .saturating_add((19_799_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (120_436_000 as Weight) + (132_018_000 as Weight) // Standard Error: 27_000 - .saturating_add((63_092_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((61_340_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(n as Weight))) } fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (181_424_000 as Weight) - // Standard Error: 51_000 - .saturating_add((78_631_000 as Weight).saturating_mul(n as Weight)) + (158_346_000 as Weight) + // Standard Error: 61_000 + .saturating_add((77_147_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(n as Weight))) } fn rebond(l: u32, ) -> Weight { - (59_349_000 as Weight) + (57_756_000 as Weight) // Standard Error: 2_000 - .saturating_add((64_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((79_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 97_000 - .saturating_add((44_609_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 100_000 + .saturating_add((44_873_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) } fn reap_stash(s: u32, ) -> Weight { - (72_356_000 as Weight) - // Standard Error: 2_000 - .saturating_add((3_066_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + (75_073_000 as Weight) + // Standard Error: 4_000 + .saturating_add((2_988_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_462_000 - .saturating_add((393_007_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 73_000 - .saturating_add((72_014_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_146_000 + .saturating_add((362_986_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 57_000 + .saturating_add((60_216_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) - .saturating_add(T::DbWeight::get().writes(9 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) } fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 235_000 - .saturating_add((35_212_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 235_000 - .saturating_add((38_391_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 3_200_000 - .saturating_add((31_130_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 230_000 + .saturating_add((35_891_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 230_000 + .saturating_add((37_854_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 7_842_000 + .saturating_add((32_492_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) } fn get_npos_targets(v: u32, ) -> Weight { - (52_314_000 as Weight) - // Standard Error: 71_000 - .saturating_add((15_195_000 as Weight).saturating_mul(v as Weight)) + (0 as Weight) + // Standard Error: 74_000 + .saturating_add((16_370_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } + fn update_staking_limits() -> Weight { + (6_398_000 as Weight) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + fn chill_other() -> Weight { + (44_694_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } } // For backwards compatibility and tests impl WeightInfo for () { fn bond() -> Weight { - (91_959_000 as Weight) + (91_278_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn bond_extra() -> Weight { - (69_291_000 as Weight) + (69_833_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn unbond() -> Weight { - (63_513_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (75_020_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn withdraw_unbonded_update(s: u32, ) -> Weight { - (64_747_000 as Weight) - // Standard Error: 0 - .saturating_add((77_000 as Weight).saturating_mul(s as Weight)) + (63_898_000 as Weight) + // Standard Error: 1_000 + .saturating_add((50_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn withdraw_unbonded_kill(s: u32, ) -> Weight { - (100_375_000 as Weight) + (103_717_000 as Weight) // Standard Error: 1_000 - .saturating_add((3_067_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + .saturating_add((2_942_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } fn validate() -> Weight { - (17_849_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + (40_702_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn kick(k: u32, ) -> Weight { - (27_939_000 as Weight) - // Standard Error: 16_000 - .saturating_add((21_431_000 as Weight).saturating_mul(k as Weight)) + (33_572_000 as Weight) + // Standard Error: 18_000 + .saturating_add((20_771_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } fn nominate(n: u32, ) -> Weight { - (32_791_000 as Weight) - // Standard Error: 33_000 - .saturating_add((7_006_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + (53_561_000 as Weight) + // Standard Error: 34_000 + .saturating_add((6_652_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn chill() -> Weight { - (17_014_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + (21_489_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) } fn set_payee() -> Weight { - (14_816_000 as Weight) + (14_514_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn set_controller() -> Weight { - (33_600_000 as Weight) + (32_598_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn set_validator_count() -> Weight { - (2_706_000 as Weight) + (2_477_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn force_no_eras() -> Weight { - (2_973_000 as Weight) + (2_743_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn force_new_era() -> Weight { - (2_949_000 as Weight) + (2_784_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn force_new_era_always() -> Weight { - (3_011_000 as Weight) + (2_749_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn set_invulnerables(v: u32, ) -> Weight { - (3_078_000 as Weight) + (2_798_000 as Weight) // Standard Error: 0 .saturating_add((5_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn force_unstake(s: u32, ) -> Weight { - (69_220_000 as Weight) - // Standard Error: 1_000 - .saturating_add((3_070_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + (70_372_000 as Weight) + // Standard Error: 13_000 + .saturating_add((3_029_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } fn cancel_deferred_slash(s: u32, ) -> Weight { - (3_460_399_000 as Weight) - // Standard Error: 222_000 - .saturating_add((19_782_000 as Weight).saturating_mul(s as Weight)) + (3_436_822_000 as Weight) + // Standard Error: 221_000 + .saturating_add((19_799_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (120_436_000 as Weight) + (132_018_000 as Weight) // Standard Error: 27_000 - .saturating_add((63_092_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((61_340_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(n as Weight))) } fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (181_424_000 as Weight) - // Standard Error: 51_000 - .saturating_add((78_631_000 as Weight).saturating_mul(n as Weight)) + (158_346_000 as Weight) + // Standard Error: 61_000 + .saturating_add((77_147_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(n as Weight))) } fn rebond(l: u32, ) -> Weight { - (59_349_000 as Weight) + (57_756_000 as Weight) // Standard Error: 2_000 - .saturating_add((64_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((79_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 97_000 - .saturating_add((44_609_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 100_000 + .saturating_add((44_873_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) } fn reap_stash(s: u32, ) -> Weight { - (72_356_000 as Weight) - // Standard Error: 2_000 - .saturating_add((3_066_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + (75_073_000 as Weight) + // Standard Error: 4_000 + .saturating_add((2_988_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_462_000 - .saturating_add((393_007_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 73_000 - .saturating_add((72_014_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_146_000 + .saturating_add((362_986_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 57_000 + .saturating_add((60_216_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) - .saturating_add(RocksDbWeight::get().writes(9 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) } fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 235_000 - .saturating_add((35_212_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 235_000 - .saturating_add((38_391_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 3_200_000 - .saturating_add((31_130_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 230_000 + .saturating_add((35_891_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 230_000 + .saturating_add((37_854_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 7_842_000 + .saturating_add((32_492_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) } fn get_npos_targets(v: u32, ) -> Weight { - (52_314_000 as Weight) - // Standard Error: 71_000 - .saturating_add((15_195_000 as Weight).saturating_mul(v as Weight)) + (0 as Weight) + // Standard Error: 74_000 + .saturating_add((16_370_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } + fn update_staking_limits() -> Weight { + (6_398_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + fn chill_other() -> Weight { + (44_694_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } }