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 <kian@parity.io>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Parity Bot <admin@parity.io>
Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>
This commit is contained in:
Shawn Tabrizi
2021-06-16 05:57:14 +01:00
committed by GitHub
parent 58e837fcd3
commit 36ac9111dd
6 changed files with 734 additions and 290 deletions
+44 -9
View File
@@ -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::<T>(0, 100, Default::default())?;
Staking::<T>::validate(RawOrigin::Signed(controller.clone()).into(), ValidatorPrefs::default())?;
add_slashing_spans::<T>(&stash, s);
T::Currency::make_free_balance_be(&stash, T::Currency::minimum_balance());
whitelist_account!(controller);
assert!(Bonded::<T>::contains_key(&stash));
assert!(Validators::<T>::contains_key(&stash));
}: _(RawOrigin::Signed(controller), stash.clone(), s)
verify {
assert!(!Bonded::<T>::contains_key(&stash));
assert!(!Validators::<T>::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::<T>(v, n, T::MAX_NOMINATIONS as usize, false, None)?;
}: {
let targets = <Staking<T>>::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::<T>::max_value(),
BalanceOf::<T>::max_value(),
Some(u32::max_value()),
Some(u32::max_value())
) verify {
assert_eq!(MinNominatorBond::<T>::get(), BalanceOf::<T>::max_value());
assert_eq!(MinValidatorBond::<T>::get(), BalanceOf::<T>::max_value());
assert_eq!(MaxNominatorsCount::<T>::get(), Some(u32::max_value()));
assert_eq!(MaxValidatorsCount::<T>::get(), Some(u32::max_value()));
}
chill_other {
let (_, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
Staking::<T>::validate(RawOrigin::Signed(controller.clone()).into(), ValidatorPrefs::default())?;
Staking::<T>::update_staking_limits(
RawOrigin::Root.into(), BalanceOf::<T>::max_value(), BalanceOf::<T>::max_value(), None, None,
)?;
let caller = whitelisted_caller();
}: _(RawOrigin::Signed(caller), controller.clone())
verify {
assert!(!Validators::<T>::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::<Test>(
@@ -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::<Test>(
@@ -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
);
+263 -32
View File
@@ -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<T: Config>() -> Result<(), &'static str> {
assert!(CurrentValidatorsCount::<T>::get().is_zero(), "CurrentValidatorsCount already set.");
assert!(CurrentNominatorsCount::<T>::get().is_zero(), "CurrentNominatorsCount already set.");
assert!(StorageVersion::<T>::get() == Releases::V6_0_0);
Ok(())
}
pub fn migrate<T: Config>() -> Weight {
log!(info, "Migrating staking to Releases::V7_0_0");
let validator_count = Validators::<T>::iter().count() as u32;
let nominator_count = Nominators::<T>::iter().count() as u32;
CurrentValidatorsCount::<T>::put(validator_count);
CurrentNominatorsCount::<T>::put(nominator_count);
StorageVersion::<T>::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<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, T::AccountId>;
/// The minimum active bond to become and maintain the role of a nominator.
#[pallet::storage]
pub type MinNominatorBond<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
/// The minimum active bond to become and maintain the role of a validator.
#[pallet::storage]
pub type MinValidatorBond<T: Config> = StorageValue<_, BalanceOf<T>, 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<T: Config> = 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<T> = 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<T> = 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<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, Nominations<T::AccountId>>;
/// A tracker to keep count of the number of items in the `Nominators` map.
#[pallet::storage]
pub type CurrentNominatorsCount<T> = 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<T> = 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<T>,
pub stakers: Vec<(T::AccountId, T::AccountId, BalanceOf<T>, StakerStatus<T::AccountId>)>,
pub min_nominator_bond: BalanceOf<T>,
pub min_validator_bond: BalanceOf<T>,
}
#[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::<T>::put(self.canceled_payout);
SlashRewardFraction::<T>::put(self.slash_reward_fraction);
StorageVersion::<T>::put(Releases::V6_0_0);
MinNominatorBond::<T>::put(self.min_nominator_bond);
MinValidatorBond::<T>::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<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_runtime_upgrade() -> Weight {
if StorageVersion::<T>::get() == Releases::V5_0_0 {
migrations::v6::migrate::<T>()
if StorageVersion::<T>::get() == Releases::V6_0_0 {
migrations::v7::migrate::<T>()
} else {
T::DbWeight::get().reads(1)
}
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<(), &'static str> {
if StorageVersion::<T>::get() == Releases::V6_0_0 {
migrations::v7::pre_migrate::<T>()
} else {
Ok(())
}
}
fn on_initialize(_now: BlockNumberFor<T>) -> 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::<T>::InsufficientValue)?
Err(Error::<T>::InsufficientBond)?
}
frame_system::Pallet::<T>::inc_consumers(&stash).map_err(|_| Error::<T>::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::<T>::InsufficientValue);
ensure!(ledger.active >= T::Currency::minimum_balance(), Error::<T>::InsufficientBond);
Self::deposit_event(Event::<T>::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::<T>::contains_key(&ledger.stash) {
MinNominatorBond::<T>::get()
} else if Validators::<T>::contains_key(&ledger.stash) {
MinValidatorBond::<T>::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::<T>::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<T>, 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::<T>::get() {
ensure!(CurrentValidatorsCount::<T>::get() < max_validators, Error::<T>::TooManyValidators);
}
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
ensure!(ledger.active >= MinValidatorBond::<T>::get(), Error::<T>::InsufficientBond);
let stash = &ledger.stash;
<Nominators<T>>::remove(stash);
<Validators<T>>::insert(stash, prefs);
Self::do_remove_nominator(stash);
Self::do_add_validator(stash, prefs);
Ok(())
}
@@ -1646,7 +1754,16 @@ pub mod pallet {
targets: Vec<<T::Lookup as StaticLookup>::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::<T>::get() {
ensure!(CurrentNominatorsCount::<T>::get() < max_nominators, Error::<T>::TooManyNominators);
}
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
ensure!(ledger.active >= MinNominatorBond::<T>::get(), Error::<T>::InsufficientBond);
let stash = &ledger.stash;
ensure!(!targets.is_empty(), Error::<T>::EmptyTargets);
ensure!(targets.len() <= T::MAX_NOMINATIONS as usize, Error::<T>::TooManyTargets);
@@ -1669,8 +1786,8 @@ pub mod pallet {
suppressed: false,
};
<Validators<T>>::remove(stash);
<Nominators<T>>::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::<T>::InsufficientValue);
ensure!(ledger.active >= T::Currency::minimum_balance(), Error::<T>::InsufficientBond);
Self::deposit_event(Event::<T>::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<T>,
min_nominator_bond: BalanceOf<T>,
min_validator_bond: BalanceOf<T>,
max_nominator_count: Option<u32>,
max_validator_count: Option<u32>,
) -> DispatchResult {
ensure_root(origin)?;
MinNominatorBond::<T>::set(min_nominator_bond);
MinValidatorBond::<T>::set(min_validator_bond);
MaxNominatorsCount::<T>::set(max_nominator_count);
MaxValidatorsCount::<T>::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<T>,
controller: T::AccountId,
) -> DispatchResult {
// Anyone can call this function.
let caller = ensure_signed(origin)?;
let ledger = Self::ledger(&controller).ok_or(Error::<T>::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::<T>::contains_key(&stash) {
MinNominatorBond::<T>::get()
} else if Validators::<T>::contains_key(&stash) {
MinValidatorBond::<T>::get()
} else {
Zero::zero()
};
ensure!(ledger.active < min_active_bond, Error::<T>::CannotChillOther);
}
Self::chill_stash(&stash);
Ok(())
}
}
}
@@ -2296,8 +2487,8 @@ impl<T: Config> Pallet<T> {
/// Chill a stash account.
fn chill_stash(stash: &T::AccountId) {
<Validators<T>>::remove(stash);
<Nominators<T>>::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<T: Config> Pallet<T> {
<Ledger<T>>::remove(&controller);
<Payee<T>>::remove(stash);
<Validators<T>>::remove(stash);
<Nominators<T>>::remove(stash);
Self::do_remove_validator(stash);
Self::do_remove_nominator(stash);
frame_system::Pallet::<T>::dec_consumers(stash);
@@ -2749,7 +2940,7 @@ impl<T: Config> Pallet<T> {
// Collect all slashing spans into a BTreeMap for further queries.
let slashing_spans = <SlashingSpans<T>>::iter().collect::<BTreeMap<_, _>>();
for (nominator, nominations) in <Nominators<T>>::iter() {
for (nominator, nominations) in Nominators::<T>::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<T: Config> Pallet<T> {
all_voters
}
/// This is a very expensive function and result should be cached versus being called multiple times.
pub fn get_npos_targets() -> Vec<T::AccountId> {
<Validators<T>>::iter().map(|(v, _)| v).collect::<Vec<_>>()
Validators::<T>::iter().map(|(v, _)| v).collect::<Vec<_>>()
}
/// 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<T::AccountId>) {
if !Nominators::<T>::contains_key(who) {
CurrentNominatorsCount::<T>::mutate(|x| x.saturating_inc())
}
Nominators::<T>::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::<T>::contains_key(who) {
Nominators::<T>::remove(who);
CurrentNominatorsCount::<T>::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::<T>::contains_key(who) {
CurrentValidatorsCount::<T>::mutate(|x| x.saturating_inc())
}
Validators::<T>::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::<T>::contains_key(who) {
Validators::<T>::remove(who);
CurrentValidatorsCount::<T>::mutate(|x| x.saturating_dec());
}
}
}
@@ -2785,12 +3017,11 @@ impl<T: Config> frame_election_provider_support::ElectionDataProvider<T::Account
fn voters(
maybe_max_len: Option<usize>,
) -> data_provider::Result<(Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>, 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 = <Nominators<T>>::iter().count();
let validator_count = <Validators<T>>::iter().count();
let voter_count = nominator_count.saturating_add(validator_count);
let nominator_count = CurrentNominatorsCount::<T>::get();
let validator_count = CurrentValidatorsCount::<T>::get();
let voter_count = nominator_count.saturating_add(validator_count) as usize;
debug_assert!(<Nominators<T>>::iter().count() as u32 == CurrentNominatorsCount::<T>::get());
debug_assert!(<Validators<T>>::iter().count() as u32 == CurrentValidatorsCount::<T>::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<T: Config> frame_election_provider_support::ElectionDataProvider<T::Account
let slashing_span_count = <SlashingSpans<T>>::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<usize>) -> data_provider::Result<(Vec<T::AccountId>, Weight)> {
let target_count = <Validators<T>>::iter().count();
let target_count = CurrentValidatorsCount::<T>::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<T: Config> frame_election_provider_support::ElectionDataProvider<T::Account
targets.into_iter().for_each(|v| {
let stake: BalanceOf<T> = target_stake
.and_then(|w| <BalanceOf<T>>::try_from(w).ok())
.unwrap_or(T::Currency::minimum_balance() * 100u32.into());
.unwrap_or(MinNominatorBond::<T>::get() * 100u32.into());
<Bonded<T>>::insert(v.clone(), v.clone());
<Ledger<T>>::insert(
v.clone(),
@@ -2871,8 +3102,8 @@ impl<T: Config> frame_election_provider_support::ElectionDataProvider<T::Account
claimed_rewards: vec![],
},
);
<Validators<T>>::insert(
v,
Self::do_add_validator(
&v,
ValidatorPrefs { commission: Perbill::zero(), blocked: false },
);
});
@@ -2892,8 +3123,8 @@ impl<T: Config> frame_election_provider_support::ElectionDataProvider<T::Account
claimed_rewards: vec![],
},
);
<Nominators<T>>::insert(
v,
Self::do_add_nominator(
&v,
Nominations { targets: t, submitted_in: 0, suppressed: false },
);
});
+24 -1
View File
@@ -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<AccountId>,
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::<Test>()
@@ -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::<Test>::iter().count() as u32;
let validator_count = Validators::<Test>::iter().count() as u32;
assert_eq!(nominator_count, CurrentNominatorsCount::<Test>::get());
assert_eq!(validator_count, CurrentValidatorsCount::<Test>::get());
}
fn check_ledgers() {
@@ -30,7 +30,9 @@ const SEED: u32 = 0;
/// This function removes all validators and nominators from storage.
pub fn clear_validators_and_nominators<T: Config>() {
Validators::<T>::remove_all(None);
CurrentValidatorsCount::<T>::kill();
Nominators::<T>::remove_all(None);
CurrentNominatorsCount::<T>::kill();
}
/// Grab a funded user.
+250 -115
View File
@@ -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));
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));
// 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!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Validators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::contains_key(&11));
// Check storage items that should be cleaned up
assert!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Validators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::contains_key(&11));
// Reduce free_balance of controller to 0
let _ = Balances::slash(&10, Balance::max_value());
// 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 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!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Validators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::contains_key(&11));
// Check storage items have not changed
assert!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Validators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::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);
// 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));
// Reap the stash
assert_ok!(Staking::reap_stash(Origin::none(), 11, 0));
// Check storage items do not exist
assert!(!<Ledger<Test>>::contains_key(&10));
assert!(!<Bonded<Test>>::contains_key(&11));
assert!(!<Validators<Test>>::contains_key(&11));
assert!(!<Nominators<Test>>::contains_key(&11));
assert!(!<Payee<Test>>::contains_key(&11));
});
// Check storage items do not exist
assert!(!<Ledger<Test>>::contains_key(&10));
assert!(!<Bonded<Test>>::contains_key(&11));
assert!(!<Validators<Test>>::contains_key(&11));
assert!(!<Nominators<Test>>::contains_key(&11));
assert!(!<Payee<Test>>::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!(<Nominators<Test>>::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);
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!(<Nominators<Test>>::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));
// Set payee information
assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash));
// Check storage items that should be cleaned up
assert!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Nominators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::contains_key(&11));
// Check storage items that should be cleaned up
assert!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Nominators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::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);
// 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 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!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Nominators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::contains_key(&11));
// Check storage items have not changed
assert!(<Ledger<Test>>::contains_key(&10));
assert!(<Bonded<Test>>::contains_key(&11));
assert!(<Nominators<Test>>::contains_key(&11));
assert!(<Payee<Test>>::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);
// 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));
// Reap the stash
assert_ok!(Staking::reap_stash(Origin::none(), 11, 0));
// Check storage items do not exist
assert!(!<Ledger<Test>>::contains_key(&10));
assert!(!<Bonded<Test>>::contains_key(&11));
assert!(!<Validators<Test>>::contains_key(&11));
assert!(!<Nominators<Test>>::contains_key(&11));
assert!(!<Payee<Test>>::contains_key(&11));
});
// Check storage items do not exist
assert!(!<Ledger<Test>>::contains_key(&10));
assert!(!<Bonded<Test>>::contains_key(&11));
assert!(!<Validators<Test>>::contains_key(&11));
assert!(!<Nominators<Test>>::contains_key(&11));
assert!(!<Payee<Test>>::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::<Test>::InsufficientValue,
Error::<Test>::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::<Test>::InsufficientValue,
Error::<Test>::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::<Test>::InsufficientValue,
Error::<Test>::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!(<Validators<Test>>::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!(
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::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::<Test>::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::<Test>::insert(987654321, ValidatorPrefs::default());
Nominators::<Test>::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::<Test>::InsufficientBond);
assert_noop!(Staking::validate(Origin::signed(4), ValidatorPrefs::default()), Error::<Test>::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::<Test>::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::<Test>::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::<Test>::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::<Test>::CannotChillOther);
assert_noop!(Staking::chill_other(Origin::signed(1), 4), Error::<Test>::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::<Test>::get();
assert_eq!(validator_count, 3);
let nominator_count = CurrentNominatorsCount::<Test>::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::<Test>(max - validator_count, 100));
// but no more
let (_, last_validator) = testing_utils::create_stash_controller::<Test>(
1337, 100, RewardDestination::Controller,
).unwrap();
assert_noop!(
Staking::validate(Origin::signed(last_validator), ValidatorPrefs::default()),
Error::<Test>::TooManyValidators,
);
// same with nominators
for i in 0 .. max - nominator_count {
let (_, controller) = testing_utils::create_stash_controller::<Test>(
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::<Test>(
20_000_000, 100, RewardDestination::Controller,
).unwrap();
assert_noop!(Staking::nominate(Origin::signed(last_nominator), vec![1]), Error::<Test>::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()));
})
}
}
+151 -133
View File
@@ -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<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
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))
}
}