mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 01:41:09 +00:00
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:
@@ -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 },
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user