Skip to content

Commit

Permalink
[NPoS] Use EraInfo to manipulate exposure in fast-unstake tests (#2459)
Browse files Browse the repository at this point in the history
The FastUnstake pallet tests were previously directly modifying storage
items in the pallet-staking to alter exposure. However, due to the
introduction of the [new paged exposure
feature](#1189) these
tests were not testing against correct storage items. This issue
resulted in a bug that I didn't catch, which has been addressed in [this
fix](#2369).

This PR introduces a modification to how the pallet-fast-unstake handles
exposure. It now utilizes `pallet-staking::EraInfo` to set or mutate
Exposures.
  • Loading branch information
Ank4n authored Nov 24, 2023
1 parent 90488ff commit 8af61d0
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 13 deletions.
11 changes: 6 additions & 5 deletions substrate/frame/fast-unstake/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl ExtBuilder {
(v, Exposure { total: 0, own: 0, others })
})
.for_each(|(validator, exposure)| {
pallet_staking::ErasStakers::<T>::insert(era, validator, exposure);
pallet_staking::EraInfo::<T>::set_exposure(era, &validator, exposure);
});
}

Expand Down Expand Up @@ -342,10 +342,11 @@ pub fn assert_unstaked(stash: &AccountId) {
}

pub fn create_exposed_nominator(exposed: AccountId, era: u32) {
// create an exposed nominator in era 1
pallet_staking::ErasStakers::<T>::mutate(era, VALIDATORS_PER_ERA, |expo| {
expo.others.push(IndividualExposure { who: exposed, value: 0 as Balance });
});
// create an exposed nominator in passed era
let mut exposure = pallet_staking::EraInfo::<T>::get_full_exposure(era, &VALIDATORS_PER_ERA);
exposure.others.push(IndividualExposure { who: exposed, value: 0 as Balance });
pallet_staking::EraInfo::<T>::set_exposure(era, &VALIDATORS_PER_ERA, exposure);

Balances::make_free_balance_be(&exposed, 100);
assert_ok!(Staking::bond(
RuntimeOrigin::signed(exposed),
Expand Down
8 changes: 5 additions & 3 deletions substrate/frame/fast-unstake/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,10 +788,12 @@ mod on_idle {
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(VALIDATOR_PREFIX)));

// but they indeed are exposed!
assert!(pallet_staking::ErasStakers::<T>::contains_key(
assert!(pallet_staking::EraInfo::<T>::get_paged_exposure(
BondingDuration::get() - 1,
VALIDATOR_PREFIX
));
&VALIDATOR_PREFIX,
0
)
.is_some());

// process a block, this validator is exposed and has been slashed.
next_block(true);
Expand Down
10 changes: 5 additions & 5 deletions substrate/frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ pub struct Nominations<T: Config> {
/// This is useful where we need to take into account the validator's own stake and total exposure
/// in consideration, in addition to the individual nominators backing them.
#[derive(Encode, Decode, RuntimeDebug, TypeInfo, PartialEq, Eq)]
struct PagedExposure<AccountId, Balance: HasCompact + codec::MaxEncodedLen> {
pub struct PagedExposure<AccountId, Balance: HasCompact + codec::MaxEncodedLen> {
exposure_metadata: PagedExposureMetadata<Balance>,
exposure_page: ExposurePage<AccountId, Balance>,
}
Expand Down Expand Up @@ -1017,7 +1017,7 @@ where
/// Wrapper struct for Era related information. It is not a pure encapsulation as these storage
/// items can be accessed directly but nevertheless, its recommended to use `EraInfo` where we
/// can and add more functions to it as needed.
pub(crate) struct EraInfo<T>(sp_std::marker::PhantomData<T>);
pub struct EraInfo<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> EraInfo<T> {
/// 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
Expand Down Expand Up @@ -1047,7 +1047,7 @@ impl<T: Config> EraInfo<T> {
///
/// This builds a paged exposure from `PagedExposureMetadata` and `ExposurePage` of the
/// validator. For older non-paged exposure, it returns the clipped exposure directly.
pub(crate) fn get_paged_exposure(
pub fn get_paged_exposure(
era: EraIndex,
validator: &T::AccountId,
page: Page,
Expand Down Expand Up @@ -1082,7 +1082,7 @@ impl<T: Config> EraInfo<T> {
}

/// Get full exposure of the validator at a given era.
pub(crate) fn get_full_exposure(
pub fn get_full_exposure(
era: EraIndex,
validator: &T::AccountId,
) -> Exposure<T::AccountId, BalanceOf<T>> {
Expand Down Expand Up @@ -1176,7 +1176,7 @@ impl<T: Config> EraInfo<T> {
}

/// Store exposure for elected validators at start of an era.
pub(crate) fn set_exposure(
pub fn set_exposure(
era: EraIndex,
validator: &T::AccountId,
exposure: Exposure<T::AccountId, BalanceOf<T>>,
Expand Down

0 comments on commit 8af61d0

Please sign in to comment.