Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bound some storage items for pallet staking and clean up deprecated exposures #7483

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
use sp_core::storage::Storage;
use sp_runtime::Perbill;
use sp_runtime::{BoundedVec, Perbill};

// Polkadot
use polkadot_primitives::{AssignmentId, ValidatorId};
Expand Down Expand Up @@ -87,7 +87,13 @@ pub fn genesis() -> Storage {
.iter()
.map(|x| (x.0.clone(), x.1.clone(), STASH, pallet_staking::StakerStatus::Validator))
.collect(),
invulnerables: validators::initial_authorities().iter().map(|x| x.0.clone()).collect(),
invulnerables: BoundedVec::try_from(
validators::initial_authorities()
.iter()
.map(|x| x.0.clone())
.collect::<Vec<_>>(),
)
.expect("Limit for staking invulnerables must be less than initial authorities."),
force_era: pallet_staking::Forcing::ForceNone,
slash_reward_fraction: Perbill::from_percent(10),
..Default::default()
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/common/src/try_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ where

let all_stakers = Ledger::<T>::iter().map(|(ctrl, l)| (ctrl, l.stash)).collect::<BTreeSet<_>>();
let mut all_exposed = BTreeSet::new();
ErasStakers::<T>::iter().for_each(|(_, val, expo)| {
ErasStakersPaged::<T>::iter().for_each(|((_era, val, _page), expo)| {
all_exposed.insert(val);
all_exposed.extend(expo.others.iter().map(|ie| ie.who.clone()))
});
Expand Down
2 changes: 2 additions & 0 deletions polkadot/runtime/test-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ impl pallet_staking::Config for Runtime {
type WeightInfo = ();
type DisablingStrategy = pallet_staking::UpToLimitWithReEnablingDisablingStrategy;
type MaxValidatorSet = MaxAuthorities;
type MaxInvulnerables = ConstU32<20>;
type MaxDisabledValidators = ConstU32<100>;
}

parameter_types! {
Expand Down
12 changes: 9 additions & 3 deletions polkadot/runtime/westend/src/genesis_config_presets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use sp_consensus_grandpa::AuthorityId as GrandpaId;
use sp_core::{crypto::get_public_from_string_or_panic, sr25519};
use sp_genesis_builder::PresetId;
use sp_keyring::Sr25519Keyring;
use sp_runtime::Perbill;
use sp_runtime::{BoundedVec, Perbill};
use westend_runtime_constants::currency::UNITS as WND;

/// Helper function to generate stash, controller and session key from seed
Expand Down Expand Up @@ -202,7 +202,10 @@ fn westend_testnet_genesis(
.iter()
.map(|x| (x.0.clone(), x.0.clone(), STASH, StakerStatus::<AccountId>::Validator))
.collect::<Vec<_>>(),
invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect::<Vec<_>>(),
invulnerables: BoundedVec::try_from(
initial_authorities.iter().map(|x| x.0.clone()).collect::<Vec<_>>()
)
.expect("Too many invulnerable validators: upper limit is MaxInvulnerables from pallet staking config"),
force_era: Forcing::NotForcing,
slash_reward_fraction: Perbill::from_percent(10),
},
Expand Down Expand Up @@ -373,7 +376,10 @@ fn westend_staging_testnet_config_genesis() -> serde_json::Value {
.iter()
.map(|x| (x.0.clone(), x.0.clone(), STASH, StakerStatus::<AccountId>::Validator))
.collect::<Vec<_>>(),
invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect::<Vec<_>>(),
invulnerables: BoundedVec::try_from(
initial_authorities.iter().map(|x| x.0.clone()).collect::<Vec<_>>()
)
.expect("Too many invulnerable validators: upper limit is MaxInvulnerables from pallet staking config"),
force_era: Forcing::ForceNone,
slash_reward_fraction: Perbill::from_percent(10),
},
Expand Down
5 changes: 4 additions & 1 deletion polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,8 @@ impl pallet_staking::Config for Runtime {
type EventListeners = (NominationPools, DelegatedStaking);
type WeightInfo = weights::pallet_staking::WeightInfo<Runtime>;
type DisablingStrategy = pallet_staking::UpToLimitWithReEnablingDisablingStrategy;
type MaxInvulnerables = frame_support::traits::ConstU32<20>;
type MaxDisabledValidators = ConstU32<100>;
}

impl pallet_fast_unstake::Config for Runtime {
Expand Down Expand Up @@ -1156,7 +1158,8 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
matches!(
c,
RuntimeCall::Staking(..) |
RuntimeCall::Session(..) | RuntimeCall::Utility(..) |
RuntimeCall::Session(..) |
RuntimeCall::Utility(..) |
RuntimeCall::FastUnstake(..) |
RuntimeCall::VoterList(..) |
RuntimeCall::NominationPools(..)
Expand Down
2 changes: 0 additions & 2 deletions polkadot/runtime/westend/src/weights/pallet_fast_unstake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ impl<T: frame_system::Config> pallet_fast_unstake::WeightInfo for WeightInfo<T>
/// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Staking CurrentEra (r:1 w:0)
/// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: Staking ErasStakers (r:257 w:0)
/// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured)
/// The range of component `v` is `[1, 256]`.
/// The range of component `b` is `[1, 64]`.
fn on_idle_check(v: u32, b: u32, ) -> Weight {
Expand Down
2 changes: 0 additions & 2 deletions polkadot/runtime/westend/src/weights/pallet_staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,8 +500,6 @@ impl<T: frame_system::Config> pallet_staking::WeightInfo for WeightInfo<T> {
/// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
/// Storage: `Staking::Ledger` (r:65 w:65)
/// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakersClipped` (r:1 w:0)
/// Proof: `Staking::ErasStakersClipped` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
/// Storage: `Staking::ClaimedRewards` (r:1 w:1)
Expand Down
2 changes: 2 additions & 0 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,8 @@ impl pallet_staking::Config for Runtime {
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
type BenchmarkingConfig = StakingBenchmarkingConfig;
type DisablingStrategy = pallet_staking::UpToLimitWithReEnablingDisablingStrategy;
type MaxInvulnerables = ConstU32<20>;
type MaxDisabledValidators = ConstU32<100>;
}

impl pallet_fast_unstake::Config for Runtime {
Expand Down
5 changes: 3 additions & 2 deletions substrate/bin/node/testing/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use kitchensink_runtime::{
RuntimeGenesisConfig, SessionConfig, SocietyConfig, StakerStatus, StakingConfig,
};
use sp_keyring::Ed25519Keyring;
use sp_runtime::Perbill;
use sp_runtime::{BoundedVec, Perbill};

/// Create genesis runtime configuration for tests.
pub fn config() -> RuntimeGenesisConfig {
Expand Down Expand Up @@ -65,7 +65,8 @@ pub fn config_endowed(extra_endowed: Vec<AccountId>) -> RuntimeGenesisConfig {
validator_count: 3,
minimum_validator_count: 0,
slash_reward_fraction: Perbill::from_percent(10),
invulnerables: vec![alice(), bob(), charlie()],
invulnerables: BoundedVec::try_from(vec![alice(), bob(), charlie()])
.expect("Too many invulnerable validators: upper limit is MaxInvulnerables from pallet staking config"),
..Default::default()
},
society: SocietyConfig { pot: 0 },
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use sp_runtime::{
impl_opaque_keys,
testing::{Digest, DigestItem, Header, TestXt},
traits::{Header as _, OpaqueKeys},
BuildStorage, Perbill,
BoundedVec, BuildStorage, Perbill,
};
use sp_staking::{EraIndex, SessionIndex};

Expand Down Expand Up @@ -345,7 +345,7 @@ pub fn new_test_ext_raw_authorities(authorities: Vec<AuthorityId>) -> sp_io::Tes
validator_count: 8,
force_era: pallet_staking::Forcing::ForceNew,
minimum_validator_count: 0,
invulnerables: vec![],
invulnerables: BoundedVec::new(),
..Default::default()
};

Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/beefy/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use sp_runtime::{
impl_opaque_keys,
testing::TestXt,
traits::{Header as HeaderT, OpaqueKeys},
BuildStorage, Perbill,
BoundedVec, BuildStorage, Perbill,
};
use sp_staking::{EraIndex, SessionIndex};
use sp_state_machine::BasicExternalities;
Expand Down Expand Up @@ -315,7 +315,7 @@ impl ExtBuilder {
validator_count: 2,
force_era: pallet_staking::Forcing::ForceNew,
minimum_validator_count: 0,
invulnerables: vec![],
invulnerables: BoundedVec::new(),
..Default::default()
};

Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/delegated-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use frame_support::{
PalletId,
};

use sp_runtime::{traits::IdentityLookup, BuildStorage, Perbill};
use sp_runtime::{traits::IdentityLookup, BoundedVec, BuildStorage, Perbill};

use frame_election_provider_support::{
bounds::{ElectionBounds, ElectionBoundsBuilder},
Expand Down Expand Up @@ -221,7 +221,7 @@ impl ExtBuilder {
// ideal validator count
validator_count: 2,
minimum_validator_count: 1,
invulnerables: vec![],
invulnerables: BoundedVec::new(),
slash_reward_fraction: Perbill::from_percent(10),
min_nominator_bond: ExistentialDeposit::get(),
min_validator_bond: ExistentialDeposit::get(),
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use sp_runtime::{
impl_opaque_keys,
testing::{TestXt, UintAuthorityId},
traits::OpaqueKeys,
BuildStorage, DigestItem, Perbill,
BoundedVec, BuildStorage, DigestItem, Perbill,
};
use sp_staking::{EraIndex, SessionIndex};

Expand Down Expand Up @@ -261,7 +261,7 @@ pub fn new_test_ext_raw_authorities(authorities: AuthorityList) -> sp_io::TestEx
validator_count: 8,
force_era: pallet_staking::Forcing::ForceNew,
minimum_validator_count: 0,
invulnerables: vec![],
invulnerables: BoundedVec::new(),
..Default::default()
};

Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/root-offences/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl Config for Test {
pub struct ExtBuilder {
validator_count: u32,
minimum_validator_count: u32,
invulnerables: Vec<AccountId>,
invulnerables: BoundedVec<AccountId, <Test as pallet_staking::Config>::MaxInvulnerables>,
balance_factor: Balance,
}

Expand All @@ -192,7 +192,7 @@ impl Default for ExtBuilder {
Self {
validator_count: 2,
minimum_validator_count: 0,
invulnerables: vec![],
invulnerables: BoundedVec::new(),
balance_factor: 1,
}
}
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/staking/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ mod benchmarks {

#[benchmark]
// Worst case scenario, the list of invulnerables is very long.
fn set_invulnerables(v: Linear<0, { BenchMaxValidators::<T>::get() }>) {
fn set_invulnerables(v: Linear<0, { T::MaxInvulnerables::get() }>) {
let mut invulnerables = Vec::new();
for i in 0..v {
invulnerables.push(account("invulnerable", i, SEED));
Expand Down
87 changes: 10 additions & 77 deletions substrate/frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,44 +1109,12 @@ where
pub struct EraInfo<T>(core::marker::PhantomData<T>);
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 <ErasStakers<T>>::contains_key(era, validator) {
// this means non paged exposure, and we treat them as single paged.
1
} 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.
Expand All @@ -1167,20 +1135,7 @@ impl<T: Config> EraInfo<T> {
validator: &T::AccountId,
page: Page,
) -> Option<PagedExposure<T::AccountId, BalanceOf<T>>> {
let overview = <ErasStakersOverview<T>>::get(&era, validator);

// return clipped exposure if page zero and paged exposure does not exist
// exists for backward compatibility and can be removed as part of #13034
if overview.is_none() && page == 0 {
return Some(PagedExposure::from_clipped(<ErasStakersClipped<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 @@ -1201,13 +1156,9 @@ impl<T: Config> EraInfo<T> {
era: EraIndex,
validator: &T::AccountId,
) -> Exposure<T::AccountId, BalanceOf<T>> {
let overview = <ErasStakersOverview<T>>::get(&era, validator);

if overview.is_none() {
return ErasStakers::<T>::get(era, validator)
}

let overview = overview.expect("checked above; qed");
let Some(overview) = <ErasStakersOverview<T>>::get(&era, validator) else {
return Exposure::default();
};

let mut others = Vec::with_capacity(overview.nominator_count as usize);
for page in 0..overview.page_count {
Expand Down Expand Up @@ -1238,20 +1189,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> {
if Self::is_non_paged_exposure(era, validator) {
return match ledger.legacy_claimed_rewards.binary_search(&era) {
// already claimed
Ok(_) => None,
// Non-paged exposure is considered as a single page
Err(_) => Some(0),
}
}

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 All @@ -1260,11 +1198,6 @@ impl<T: Config> EraInfo<T> {
all_claimable_pages.into_iter().find(|p| !claimed_pages.contains(p))
}

/// Checks if exposure is paged or not.
fn is_non_paged_exposure(era: EraIndex, validator: &T::AccountId) -> bool {
<ErasStakersClipped<T>>::contains_key(&era, validator)
}

/// Returns validator commission for this era and page.
pub(crate) fn get_validator_commission(
era: EraIndex,
Expand Down
Loading
Loading