mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 05:38:00 +00:00
Used CountedStorageMap in pallet-staking (#10233)
* Removed counters and used CountedStorageMap instead. * Little refactoring * Update frame/staking/src/migrations.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Removed redundant code to update counter for validator & nominator. * Removed redundant code to update counter for validator & nominator. * Removed unreachable code to inject the hashed prefix for nominator & validator. * Removed redundant check for nominator & validator count. * Generated `fn prefix_hash` for `CountedStorageMap`. * Applied changes from `cargo fmt` * Possible correct implementation of migration code * Implemented fn module_prefix, storage_prefix and prefix_hash. * Removed counted_map.rs * Renamed `fn storage_prefix` to `storage_counter_prefix`. * Update frame/support/src/storage/types/counted_map.rs * Update frame/bags-list/remote-tests/src/snapshot.rs * Update frame/support/src/storage/types/counted_map.rs * Fixed errors. Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
@@ -665,8 +665,8 @@ impl<T: Config> Pallet<T> {
|
||||
maybe_max_len: Option<usize>,
|
||||
) -> Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> {
|
||||
let max_allowed_len = {
|
||||
let nominator_count = CounterForNominators::<T>::get() as usize;
|
||||
let validator_count = CounterForValidators::<T>::get() as usize;
|
||||
let nominator_count = Nominators::<T>::count() as usize;
|
||||
let validator_count = Validators::<T>::count() as usize;
|
||||
let all_voter_count = validator_count.saturating_add(nominator_count);
|
||||
maybe_max_len.unwrap_or(all_voter_count).min(all_voter_count)
|
||||
};
|
||||
@@ -765,18 +765,15 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// This function will add a nominator to the `Nominators` storage map,
|
||||
/// [`SortedListProvider`] and keep track of the `CounterForNominators`.
|
||||
/// and [`SortedListProvider`].
|
||||
///
|
||||
/// If the nominator already exists, their nominations will be updated.
|
||||
///
|
||||
/// NOTE: you must ALWAYS use this function to add nominator or update their targets. Any access
|
||||
/// to `Nominators`, its counter, or `VoterList` outside of this function is almost certainly
|
||||
/// to `Nominators` or `VoterList` outside of this function is almost certainly
|
||||
/// wrong.
|
||||
pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations<T::AccountId>) {
|
||||
if !Nominators::<T>::contains_key(who) {
|
||||
// maybe update the counter.
|
||||
CounterForNominators::<T>::mutate(|x| x.saturating_inc());
|
||||
|
||||
// maybe update sorted list. Error checking is defensive-only - this should never fail.
|
||||
if T::SortedListProvider::on_insert(who.clone(), Self::weight_of(who)).is_err() {
|
||||
log!(warn, "attempt to insert duplicate nominator ({:#?})", who);
|
||||
@@ -790,53 +787,46 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// This function will remove a nominator from the `Nominators` storage map,
|
||||
/// [`SortedListProvider`] and keep track of the `CounterForNominators`.
|
||||
/// and [`SortedListProvider`].
|
||||
///
|
||||
/// Returns true if `who` was removed from `Nominators`, otherwise false.
|
||||
///
|
||||
/// NOTE: you must ALWAYS use this function to remove a nominator from the system. Any access to
|
||||
/// `Nominators`, its counter, or `VoterList` outside of this function is almost certainly
|
||||
/// `Nominators` or `VoterList` outside of this function is almost certainly
|
||||
/// wrong.
|
||||
pub fn do_remove_nominator(who: &T::AccountId) -> bool {
|
||||
if Nominators::<T>::contains_key(who) {
|
||||
Nominators::<T>::remove(who);
|
||||
CounterForNominators::<T>::mutate(|x| x.saturating_dec());
|
||||
T::SortedListProvider::on_remove(who);
|
||||
debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(()));
|
||||
debug_assert_eq!(CounterForNominators::<T>::get(), T::SortedListProvider::count());
|
||||
debug_assert_eq!(Nominators::<T>::count(), T::SortedListProvider::count());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// This function will add a validator to the `Validators` storage map, and keep track of the
|
||||
/// `CounterForValidators`.
|
||||
/// This function will add a validator to the `Validators` storage map.
|
||||
///
|
||||
/// If the validator already exists, their preferences will be updated.
|
||||
///
|
||||
/// NOTE: you must ALWAYS use this function to add a validator to the system. Any access to
|
||||
/// `Validators`, its counter, or `VoterList` outside of this function is almost certainly
|
||||
/// `Validators` or `VoterList` outside of this function is almost certainly
|
||||
/// wrong.
|
||||
pub fn do_add_validator(who: &T::AccountId, prefs: ValidatorPrefs) {
|
||||
if !Validators::<T>::contains_key(who) {
|
||||
CounterForValidators::<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 `CounterForValidators`.
|
||||
/// This function will remove a validator from the `Validators` storage map.
|
||||
///
|
||||
/// Returns true if `who` was removed from `Validators`, otherwise false.
|
||||
///
|
||||
/// NOTE: you must ALWAYS use this function to remove a validator from the system. Any access to
|
||||
/// `Validators`, its counter, or `VoterList` outside of this function is almost certainly
|
||||
/// `Validators` or `VoterList` outside of this function is almost certainly
|
||||
/// wrong.
|
||||
pub fn do_remove_validator(who: &T::AccountId) -> bool {
|
||||
if Validators::<T>::contains_key(who) {
|
||||
Validators::<T>::remove(who);
|
||||
CounterForValidators::<T>::mutate(|x| x.saturating_dec());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -865,14 +855,6 @@ impl<T: Config> ElectionDataProvider<T::AccountId, BlockNumberFor<T>> for Pallet
|
||||
fn voters(
|
||||
maybe_max_len: Option<usize>,
|
||||
) -> data_provider::Result<Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>> {
|
||||
debug_assert!(<Nominators<T>>::iter().count() as u32 == CounterForNominators::<T>::get());
|
||||
debug_assert!(<Validators<T>>::iter().count() as u32 == CounterForValidators::<T>::get());
|
||||
debug_assert_eq!(
|
||||
CounterForNominators::<T>::get(),
|
||||
T::SortedListProvider::count(),
|
||||
"voter_count must be accurate",
|
||||
);
|
||||
|
||||
// This can never fail -- if `maybe_max_len` is `Some(_)` we handle it.
|
||||
let voters = Self::get_npos_voters(maybe_max_len);
|
||||
debug_assert!(maybe_max_len.map_or(true, |max| voters.len() <= max));
|
||||
@@ -881,7 +863,7 @@ impl<T: Config> ElectionDataProvider<T::AccountId, BlockNumberFor<T>> for Pallet
|
||||
}
|
||||
|
||||
fn targets(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<T::AccountId>> {
|
||||
let target_count = CounterForValidators::<T>::get();
|
||||
let target_count = Validators::<T>::count();
|
||||
|
||||
// We can't handle this case yet -- return an error.
|
||||
if maybe_max_len.map_or(false, |max_len| target_count > max_len as u32) {
|
||||
@@ -967,10 +949,9 @@ impl<T: Config> ElectionDataProvider<T::AccountId, BlockNumberFor<T>> for Pallet
|
||||
fn clear() {
|
||||
<Bonded<T>>::remove_all(None);
|
||||
<Ledger<T>>::remove_all(None);
|
||||
<Validators<T>>::remove_all(None);
|
||||
<Nominators<T>>::remove_all(None);
|
||||
<CounterForNominators<T>>::kill();
|
||||
<CounterForValidators<T>>::kill();
|
||||
<Validators<T>>::remove_all();
|
||||
<Nominators<T>>::remove_all();
|
||||
|
||||
T::SortedListProvider::unsafe_clear();
|
||||
}
|
||||
|
||||
@@ -1284,7 +1265,7 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsMap<T> {
|
||||
Box::new(Nominators::<T>::iter().map(|(n, _)| n))
|
||||
}
|
||||
fn count() -> u32 {
|
||||
CounterForNominators::<T>::get()
|
||||
Nominators::<T>::count()
|
||||
}
|
||||
fn contains(id: &T::AccountId) -> bool {
|
||||
Nominators::<T>::contains_key(id)
|
||||
@@ -1309,10 +1290,10 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsMap<T> {
|
||||
fn sanity_check() -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unsafe_clear() {
|
||||
// NOTE: Caller must ensure this doesn't lead to too many storage accesses. This is a
|
||||
// condition of SortedListProvider::unsafe_clear.
|
||||
Nominators::<T>::remove_all(None);
|
||||
CounterForNominators::<T>::take();
|
||||
Nominators::<T>::remove_all();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,16 +234,10 @@ pub mod pallet {
|
||||
StorageMap<_, Twox64Concat, T::AccountId, RewardDestination<T::AccountId>, ValueQuery>;
|
||||
|
||||
/// The map from (wannabe) validator stash key to the preferences of that validator.
|
||||
///
|
||||
/// When updating this storage item, you must also update the `CounterForValidators`.
|
||||
#[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 CounterForValidators<T> = StorageValue<_, u32, ValueQuery>;
|
||||
CountedStorageMap<_, Twox64Concat, T::AccountId, ValidatorPrefs, ValueQuery>;
|
||||
|
||||
/// The maximum validator count before we stop allowing new validators to join.
|
||||
///
|
||||
@@ -252,16 +246,10 @@ pub mod pallet {
|
||||
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 `CounterForNominators`.
|
||||
#[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 CounterForNominators<T> = StorageValue<_, u32, ValueQuery>;
|
||||
CountedStorageMap<_, Twox64Concat, T::AccountId, Nominations<T::AccountId>>;
|
||||
|
||||
/// The maximum nominator count before we stop allowing new validators to join.
|
||||
///
|
||||
@@ -570,7 +558,7 @@ pub mod pallet {
|
||||
// all voters are reported to the `SortedListProvider`.
|
||||
assert_eq!(
|
||||
T::SortedListProvider::count(),
|
||||
CounterForNominators::<T>::get(),
|
||||
Nominators::<T>::count(),
|
||||
"not all genesis stakers were inserted into sorted list provider, something is wrong."
|
||||
);
|
||||
}
|
||||
@@ -987,7 +975,7 @@ pub mod pallet {
|
||||
// the runtime.
|
||||
if let Some(max_validators) = MaxValidatorsCount::<T>::get() {
|
||||
ensure!(
|
||||
CounterForValidators::<T>::get() < max_validators,
|
||||
Validators::<T>::count() < max_validators,
|
||||
Error::<T>::TooManyValidators
|
||||
);
|
||||
}
|
||||
@@ -1027,7 +1015,7 @@ pub mod pallet {
|
||||
// the runtime.
|
||||
if let Some(max_nominators) = MaxNominatorsCount::<T>::get() {
|
||||
ensure!(
|
||||
CounterForNominators::<T>::get() < max_nominators,
|
||||
Nominators::<T>::count() < max_nominators,
|
||||
Error::<T>::TooManyNominators
|
||||
);
|
||||
}
|
||||
@@ -1610,7 +1598,7 @@ pub mod pallet {
|
||||
let min_active_bond = if Nominators::<T>::contains_key(&stash) {
|
||||
let max_nominator_count =
|
||||
MaxNominatorsCount::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
|
||||
let current_nominator_count = CounterForNominators::<T>::get();
|
||||
let current_nominator_count = Nominators::<T>::count();
|
||||
ensure!(
|
||||
threshold * max_nominator_count < current_nominator_count,
|
||||
Error::<T>::CannotChillOther
|
||||
@@ -1619,7 +1607,7 @@ pub mod pallet {
|
||||
} else if Validators::<T>::contains_key(&stash) {
|
||||
let max_validator_count =
|
||||
MaxValidatorsCount::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
|
||||
let current_validator_count = CounterForValidators::<T>::get();
|
||||
let current_validator_count = Validators::<T>::count();
|
||||
ensure!(
|
||||
threshold * max_validator_count < current_validator_count,
|
||||
Error::<T>::CannotChillOther
|
||||
|
||||
Reference in New Issue
Block a user