Skip to content

Commit

Permalink
Fixes from #5986
Browse files Browse the repository at this point in the history
  • Loading branch information
re-gius committed Nov 25, 2024
1 parent 9a25fbc commit 98daabc
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 251 deletions.
36 changes: 34 additions & 2 deletions polkadot/runtime/common/src/try_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@

//! Common try-runtime only tests for runtimes.
use frame_support::traits::{Get, Hooks};
use alloc::{collections::btree_set::BTreeSet, vec::Vec};
use frame_support::{
dispatch::RawOrigin,
traits::{Get, Hooks},
};
use pallet_fast_unstake::{Pallet as FastUnstake, *};
use pallet_staking::*;

/// progress until the inactive nominators have all beenprocessed.
/// register all inactive nominators for fast-unstake, and progress until they have all been
/// processed.
pub fn migrate_all_inactive_nominators<T: pallet_fast_unstake::Config + pallet_staking::Config>()
where
<T as frame_system::Config>::RuntimeEvent: TryInto<pallet_fast_unstake::Event<T>>,
Expand All @@ -28,6 +34,32 @@ where
let mut unstaked_err = 0;
let mut unstaked_slashed = 0;

let all_stakers = Ledger::<T>::iter().map(|(ctrl, l)| (ctrl, l.stash)).collect::<BTreeSet<_>>();
let mut all_exposed = BTreeSet::new();
ErasStakersPaged::<T>::iter().for_each(|((_era, val, _page), expo)| {
all_exposed.insert(val);
all_exposed.extend(expo.others.iter().map(|ie| ie.who.clone()))
});

let eligible = all_stakers
.iter()
.filter_map(|(ctrl, stash)| all_exposed.contains(stash).then_some(ctrl))
.collect::<Vec<_>>();

log::info!(
target: "runtime::test",
"registering {} out of {} stakers for fast-unstake",
eligible.len(),
all_stakers.len()
);
for ctrl in eligible {
if let Err(why) =
FastUnstake::<T>::register_fast_unstake(RawOrigin::Signed(ctrl.clone()).into())
{
log::warn!(target: "runtime::test", "failed to register {:?} due to {:?}", ctrl, why);
}
}

log::info!(
target: "runtime::test",
"registered {} successfully, starting at {:?}.",
Expand Down
57 changes: 12 additions & 45 deletions substrate/frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,45 +1054,19 @@ impl<T: Config> EraInfo<T> {
/// Returns true if validator has one or more page of era rewards not claimed yet.
// Also looks at legacy storage that can be cleaned up after #433.
pub fn pending_rewards(era: EraIndex, validator: &T::AccountId) -> bool {
let page_count = if let Some(overview) = <ErasStakersOverview<T>>::get(&era, validator) {
overview.page_count
} else {
// if no exposure, then no rewards to claim.
return false
};

// check if era is marked claimed in legacy storage.
if <Ledger<T>>::get(validator)
.map(|l| l.legacy_claimed_rewards.contains(&era))
.unwrap_or_default()
{
return false
}

ClaimedRewards::<T>::get(era, validator).len() < page_count as usize
}

/// Temporary function which looks at both (1) passed param `T::StakingLedger` for legacy
/// non-paged rewards, and (2) `T::ClaimedRewards` for paged rewards. This function can be
/// removed once `T::HistoryDepth` eras have passed and none of the older non-paged rewards
/// are relevant/claimable.
// Refer tracker issue for cleanup: https://github.com/paritytech/polkadot-sdk/issues/433
pub(crate) fn is_rewards_claimed_with_legacy_fallback(
era: EraIndex,
ledger: &StakingLedger<T>,
validator: &T::AccountId,
page: Page,
) -> bool {
ledger.legacy_claimed_rewards.binary_search(&era).is_ok() ||
Self::is_rewards_claimed(era, validator, page)
<ErasStakersOverview<T>>::get(&era, validator)
.map(|overview| {
ClaimedRewards::<T>::get(era, validator).len() < overview.page_count as usize
})
.unwrap_or(false)
}

/// Check if the rewards for the given era and page index have been claimed.
///
/// This is only used for paged rewards. Once older non-paged rewards are no longer
/// relevant, `is_rewards_claimed_with_legacy_fallback` can be removed and this function can
/// be made public.
fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: Page) -> bool {
pub(crate) fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: Page) -> bool {
ClaimedRewards::<T>::get(era, validator).contains(&page)
}

Expand All @@ -1105,14 +1079,7 @@ impl<T: Config> EraInfo<T> {
validator: &T::AccountId,
page: Page,
) -> Option<PagedExposure<T::AccountId, BalanceOf<T>>> {
let overview = <ErasStakersOverview<T>>::get(&era, validator);

// no exposure for this validator
if overview.is_none() {
return None
}

let overview = overview.expect("checked above; qed");
let overview = <ErasStakersOverview<T>>::get(&era, validator)?;

// validator stake is added only in page zero
let validator_stake = if page == 0 { overview.own } else { Zero::zero() };
Expand All @@ -1135,6 +1102,10 @@ impl<T: Config> EraInfo<T> {
) -> Exposure<T::AccountId, BalanceOf<T>> {
let overview = <ErasStakersOverview<T>>::get(&era, validator);

if overview.is_none() {
return Exposure::default()
}

let overview = overview.expect("checked above; qed");

let mut others = Vec::with_capacity(overview.nominator_count as usize);
Expand Down Expand Up @@ -1166,11 +1137,7 @@ impl<T: Config> EraInfo<T> {
}

/// Returns the next page that can be claimed or `None` if nothing to claim.
pub(crate) fn get_next_claimable_page(
era: EraIndex,
validator: &T::AccountId,
ledger: &StakingLedger<T>,
) -> Option<Page> {
pub(crate) fn get_next_claimable_page(era: EraIndex, validator: &T::AccountId) -> Option<Page> {
// Find next claimable page of paged exposure.
let page_count = Self::get_page_count(era, validator);
let all_claimable_pages: Vec<Page> = (0..page_count).collect();
Expand Down
19 changes: 7 additions & 12 deletions substrate/frame/staking/src/pallet/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,8 @@ impl<T: Config> Pallet<T> {
validator_stash: T::AccountId,
era: EraIndex,
) -> DispatchResultWithPostInfo {
let controller = Self::bonded(&validator_stash).ok_or_else(|| {
Error::<T>::NotStash.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
})?;

let ledger = Self::ledger(StakingAccount::Controller(controller))?;
let page = EraInfo::<T>::get_next_claimable_page(era, &validator_stash, &ledger)
.ok_or_else(|| {
let page =
EraInfo::<T>::get_next_claimable_page(era, &validator_stash).ok_or_else(|| {
Error::<T>::AlreadyClaimed
.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
})?;
Expand Down Expand Up @@ -294,13 +289,13 @@ impl<T: Config> Pallet<T> {

let stash = ledger.stash.clone();

if EraInfo::<T>::is_rewards_claimed_with_legacy_fallback(era, &ledger, &stash, page) {
if EraInfo::<T>::is_rewards_claimed(era, &stash, page) {
return Err(Error::<T>::AlreadyClaimed
.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)))
} else {
EraInfo::<T>::set_rewards_as_claimed(era, &stash, page);
}

EraInfo::<T>::set_rewards_as_claimed(era, &stash, page);

let exposure = EraInfo::<T>::get_paged_exposure(era, &stash, page).ok_or_else(|| {
Error::<T>::InvalidEraToReward
.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
Expand Down Expand Up @@ -350,7 +345,7 @@ impl<T: Config> Pallet<T> {
era_index: era,
validator_stash: stash.clone(),
page,
next: EraInfo::<T>::get_next_claimable_page(era, &stash, &ledger),
next: EraInfo::<T>::get_next_claimable_page(era, &stash),
});

let mut total_imbalance = PositiveImbalanceOf::<T>::zero();
Expand Down Expand Up @@ -1163,7 +1158,7 @@ impl<T: Config> Pallet<T> {

/// Returns full exposure of a validator for a given era.
///
/// History note: This used to be a getter for old storage item `ErasStakers` deprecated in v14
/// History note: This used to be a getter for the storage item `ErasStakers` deprecated in v14
/// and deleted in v17. Since this function is used in the codebase at various places, we kept
/// it as a custom getter that takes care of getting the full exposure of the validator in a
/// backward compatible way.
Expand Down
Loading

0 comments on commit 98daabc

Please sign in to comment.