Skip to content

Commit cc1f422

Browse files
Ank4nkianenigma
authored andcommitted
Bound staking storage items (paritytech#12230)
* replace pallet level unboundedness to individual storage items * bound structs * bounding history depth * defensive error * use the era history depth from config * clean up history depth from storage in v11 * keep the name HistoryDepth for the new configuration value * use u32 for history depth in node runtime * improve doc comments * add HistoryDepth to mock runtimes with pallet-staking * rustfmt * refactor and doc improve * apply re-benchmarked weight for staking * pr feedback improvements * test for claimed rewards following the expected bounds * refactor test to calculate first and last reward era programmatically * verify previous eras cannot be claimed * add migration v12 * ".git/.scripts/bench-bot.sh" pallet dev pallet_staking * fix compiler error * corrupting history depth does not lead to catastrophic issue * fix new line * remove unused import * fmt * add test to document scenario where history depth is reduced without migration * fmt * Update frame/staking/src/lib.rs Co-authored-by: Kian Paimani <[email protected]> * Update frame/staking/src/migrations.rs Co-authored-by: Kian Paimani <[email protected]> * doc for all storage items bounded by HistoryDepth * Update frame/staking/src/pallet/mod.rs Co-authored-by: Kian Paimani <[email protected]> * Update frame/staking/src/tests.rs Co-authored-by: Kian Paimani <[email protected]> * pr feedback fixes * Update frame/staking/src/tests.rs Co-authored-by: Kian Paimani <[email protected]> * remove extra checks * fix merge * fmt Co-authored-by: command-bot <> Co-authored-by: Kian Paimani <[email protected]> Co-authored-by: kianenigma <[email protected]>
1 parent 7703f7b commit cc1f422

File tree

16 files changed

+669
-483
lines changed

16 files changed

+669
-483
lines changed

bin/node/runtime/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ parameter_types! {
535535
pub const MaxNominatorRewardedPerValidator: u32 = 256;
536536
pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17);
537537
pub OffchainRepeat: BlockNumber = 5;
538+
pub HistoryDepth: u32 = 84;
538539
}
539540

540541
pub struct StakingBenchmarkingConfig;
@@ -572,6 +573,7 @@ impl pallet_staking::Config for Runtime {
572573
// This a placeholder, to be introduced in the next PR as an instance of bags-list
573574
type TargetList = pallet_staking::UseValidatorsMap<Self>;
574575
type MaxUnlockingChunks = ConstU32<32>;
576+
type HistoryDepth = HistoryDepth;
575577
type OnStakerSlash = NominationPools;
576578
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
577579
type BenchmarkingConfig = StakingBenchmarkingConfig;

frame/babe/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ impl pallet_staking::Config for Test {
204204
type VoterList = pallet_staking::UseNominatorsAndValidatorsMap<Self>;
205205
type TargetList = pallet_staking::UseValidatorsMap<Self>;
206206
type MaxUnlockingChunks = ConstU32<32>;
207+
type HistoryDepth = ConstU32<84>;
207208
type OnStakerSlash = ();
208209
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
209210
type WeightInfo = ();

frame/grandpa/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ impl pallet_staking::Config for Test {
208208
type VoterList = pallet_staking::UseNominatorsAndValidatorsMap<Self>;
209209
type TargetList = pallet_staking::UseValidatorsMap<Self>;
210210
type MaxUnlockingChunks = ConstU32<32>;
211+
type HistoryDepth = ConstU32<84>;
211212
type OnStakerSlash = ();
212213
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
213214
type WeightInfo = ();

frame/nomination-pools/benchmarking/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl pallet_staking::Config for Runtime {
115115
type VoterList = VoterList;
116116
type TargetList = pallet_staking::UseValidatorsMap<Self>;
117117
type MaxUnlockingChunks = ConstU32<32>;
118+
type HistoryDepth = ConstU32<84>;
118119
type OnStakerSlash = Pools;
119120
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
120121
type WeightInfo = ();

frame/nomination-pools/test-staking/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ impl pallet_staking::Config for Runtime {
129129
type VoterList = VoterList;
130130
type TargetList = pallet_staking::UseValidatorsMap<Self>;
131131
type MaxUnlockingChunks = ConstU32<32>;
132+
type HistoryDepth = ConstU32<84>;
132133
type OnStakerSlash = Pools;
133134
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
134135
type WeightInfo = ();

frame/offences/benchmarking/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ impl pallet_staking::Config for Test {
182182
type VoterList = pallet_staking::UseNominatorsAndValidatorsMap<Self>;
183183
type TargetList = pallet_staking::UseValidatorsMap<Self>;
184184
type MaxUnlockingChunks = ConstU32<32>;
185+
type HistoryDepth = ConstU32<84>;
185186
type OnStakerSlash = ();
186187
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
187188
type WeightInfo = ();

frame/session/benchmarking/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl pallet_staking::Config for Test {
174174
type ElectionProvider = onchain::UnboundedExecution<OnChainSeqPhragmen>;
175175
type GenesisElectionProvider = Self::ElectionProvider;
176176
type MaxUnlockingChunks = ConstU32<32>;
177+
type HistoryDepth = ConstU32<84>;
177178
type VoterList = pallet_staking::UseNominatorsAndValidatorsMap<Self>;
178179
type TargetList = pallet_staking::UseValidatorsMap<Self>;
179180
type OnStakerSlash = ();

frame/staking/src/benchmarking.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -660,25 +660,6 @@ benchmarks! {
660660
assert!(original_bonded < new_bonded);
661661
}
662662

663-
set_history_depth {
664-
let e in 1 .. 100;
665-
HistoryDepth::<T>::put(e);
666-
CurrentEra::<T>::put(e);
667-
let dummy = || -> T::AccountId { codec::Decode::decode(&mut TrailingZeroInput::zeroes()).unwrap() };
668-
for i in 0 .. e {
669-
<ErasStakers<T>>::insert(i, dummy(), Exposure::<T::AccountId, BalanceOf<T>>::default());
670-
<ErasStakersClipped<T>>::insert(i, dummy(), Exposure::<T::AccountId, BalanceOf<T>>::default());
671-
<ErasValidatorPrefs<T>>::insert(i, dummy(), ValidatorPrefs::default());
672-
<ErasValidatorReward<T>>::insert(i, BalanceOf::<T>::one());
673-
<ErasRewardPoints<T>>::insert(i, EraRewardPoints::<T::AccountId>::default());
674-
<ErasTotalStake<T>>::insert(i, BalanceOf::<T>::one());
675-
ErasStartSessionIndex::<T>::insert(i, i);
676-
}
677-
}: _(RawOrigin::Root, EraIndex::zero(), u32::MAX)
678-
verify {
679-
assert_eq!(HistoryDepth::<T>::get(), 0);
680-
}
681-
682663
reap_stash {
683664
let s in 1 .. MAX_SPANS;
684665
// clean up any existing state.
@@ -698,7 +679,7 @@ benchmarks! {
698679
active: T::Currency::minimum_balance() - One::one(),
699680
total: T::Currency::minimum_balance() - One::one(),
700681
unlocking: Default::default(),
701-
claimed_rewards: vec![],
682+
claimed_rewards: Default::default(),
702683
};
703684
Ledger::<T>::insert(&controller, l);
704685

frame/staking/src/lib.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,12 @@ pub mod weights;
299299

300300
mod pallet;
301301

302-
use codec::{Decode, Encode, HasCompact};
302+
use codec::{Decode, Encode, HasCompact, MaxEncodedLen};
303303
use frame_support::{
304304
parameter_types,
305305
traits::{Currency, Defensive, Get},
306306
weights::Weight,
307-
BoundedVec, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
307+
BoundedVec, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
308308
};
309309
use scale_info::TypeInfo;
310310
use sp_runtime::{
@@ -354,7 +354,7 @@ parameter_types! {
354354
}
355355

356356
/// Information regarding the active era (era in used in session).
357-
#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
357+
#[derive(Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
358358
pub struct ActiveEraInfo {
359359
/// Index of era.
360360
pub index: EraIndex,
@@ -395,7 +395,7 @@ pub enum StakerStatus<AccountId> {
395395
}
396396

397397
/// A destination account for payment.
398-
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
398+
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
399399
pub enum RewardDestination<AccountId> {
400400
/// Pay into the stash account, increasing the amount at stake accordingly.
401401
Staked,
@@ -416,7 +416,7 @@ impl<AccountId> Default for RewardDestination<AccountId> {
416416
}
417417

418418
/// Preference of what happens regarding validation.
419-
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default)]
419+
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default, MaxEncodedLen)]
420420
pub struct ValidatorPrefs {
421421
/// Reward that validator takes up-front; only the rest is split between themselves and
422422
/// nominators.
@@ -429,8 +429,8 @@ pub struct ValidatorPrefs {
429429
}
430430

431431
/// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked.
432-
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
433-
pub struct UnlockChunk<Balance: HasCompact> {
432+
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
433+
pub struct UnlockChunk<Balance: HasCompact + MaxEncodedLen> {
434434
/// Amount of funds to be unlocked.
435435
#[codec(compact)]
436436
value: Balance,
@@ -440,7 +440,16 @@ pub struct UnlockChunk<Balance: HasCompact> {
440440
}
441441

442442
/// The ledger of a (bonded) stash.
443-
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebugNoBound, TypeInfo)]
443+
#[derive(
444+
PartialEqNoBound,
445+
EqNoBound,
446+
CloneNoBound,
447+
Encode,
448+
Decode,
449+
RuntimeDebugNoBound,
450+
TypeInfo,
451+
MaxEncodedLen,
452+
)]
444453
#[scale_info(skip_type_params(T))]
445454
pub struct StakingLedger<T: Config> {
446455
/// The stash account whose balance is actually locked and at stake.
@@ -459,7 +468,7 @@ pub struct StakingLedger<T: Config> {
459468
pub unlocking: BoundedVec<UnlockChunk<BalanceOf<T>>, MaxUnlockingChunks>,
460469
/// List of eras for which the stakers behind a validator have claimed rewards. Only updated
461470
/// for validators.
462-
pub claimed_rewards: Vec<EraIndex>,
471+
pub claimed_rewards: BoundedVec<EraIndex, T::HistoryDepth>,
463472
}
464473

465474
impl<T: Config> StakingLedger<T> {
@@ -470,7 +479,7 @@ impl<T: Config> StakingLedger<T> {
470479
total: Zero::zero(),
471480
active: Zero::zero(),
472481
unlocking: Default::default(),
473-
claimed_rewards: vec![],
482+
claimed_rewards: Default::default(),
474483
}
475484
}
476485

@@ -676,7 +685,9 @@ impl<T: Config> StakingLedger<T> {
676685
}
677686

678687
/// A record of the nominations made by a specific account.
679-
#[derive(PartialEqNoBound, EqNoBound, Clone, Encode, Decode, RuntimeDebugNoBound, TypeInfo)]
688+
#[derive(
689+
PartialEqNoBound, EqNoBound, Clone, Encode, Decode, RuntimeDebugNoBound, TypeInfo, MaxEncodedLen,
690+
)]
680691
#[codec(mel_bound())]
681692
#[scale_info(skip_type_params(T))]
682693
pub struct Nominations<T: Config> {
@@ -850,7 +861,7 @@ impl<Balance: AtLeast32BitUnsigned + Clone, T: Get<&'static PiecewiseLinear<'sta
850861
}
851862

852863
/// Mode of era-forcing.
853-
#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
864+
#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
854865
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
855866
pub enum Forcing {
856867
/// Not forcing anything - just let whatever happen.
@@ -874,7 +885,7 @@ impl Default for Forcing {
874885
// A value placed in storage that represents the current version of the Staking storage. This value
875886
// is used by the `on_runtime_upgrade` logic to determine whether we run storage migration logic.
876887
// This should match directly with the semantic versions of the Rust crate.
877-
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
888+
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
878889
enum Releases {
879890
V1_0_0Ancient,
880891
V2_0_0,
@@ -887,6 +898,7 @@ enum Releases {
887898
V9_0_0, // inject validators into `VoterList` as well.
888899
V10_0_0, // remove `EarliestUnappliedSlash`.
889900
V11_0_0, // Move pallet storage prefix, e.g. BagsList -> VoterBagsList
901+
V12_0_0, // remove `HistoryDepth`.
890902
}
891903

892904
impl Default for Releases {

frame/staking/src/migrations.rs

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,53 @@ use super::*;
2020
use frame_election_provider_support::SortedListProvider;
2121
use frame_support::traits::OnRuntimeUpgrade;
2222

23+
pub mod v12 {
24+
use super::*;
25+
use frame_support::{pallet_prelude::ValueQuery, storage_alias};
26+
27+
#[storage_alias]
28+
type HistoryDepth<T: Config> = StorageValue<Pallet<T>, u32, ValueQuery>;
29+
30+
/// Clean up `HistoryDepth` from storage.
31+
///
32+
/// We will be depending on the configurable value of `HistoryDepth` post
33+
/// this release.
34+
pub struct MigrateToV12<T>(sp_std::marker::PhantomData<T>);
35+
impl<T: Config> OnRuntimeUpgrade for MigrateToV12<T> {
36+
#[cfg(feature = "try-runtime")]
37+
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
38+
frame_support::ensure!(
39+
T::HistoryDepth::get() == HistoryDepth::<T>::get(),
40+
"Provided value of HistoryDepth should be same as the existing storage value"
41+
);
42+
43+
Ok(Default::default())
44+
}
45+
46+
fn on_runtime_upgrade() -> frame_support::weights::Weight {
47+
if StorageVersion::<T>::get() == Releases::V11_0_0 {
48+
HistoryDepth::<T>::kill();
49+
StorageVersion::<T>::put(Releases::V12_0_0);
50+
51+
log!(info, "v12 applied successfully");
52+
T::DbWeight::get().reads_writes(1, 2)
53+
} else {
54+
log!(warn, "Skipping v12, should be removed");
55+
T::DbWeight::get().reads(1)
56+
}
57+
}
58+
59+
#[cfg(feature = "try-runtime")]
60+
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
61+
frame_support::ensure!(
62+
StorageVersion::<T>::get() == crate::Releases::V12_0_0,
63+
"v12 not applied"
64+
);
65+
Ok(())
66+
}
67+
}
68+
}
69+
2370
pub mod v11 {
2471
use super::*;
2572
use frame_support::{
@@ -82,11 +129,6 @@ pub mod v11 {
82129

83130
#[cfg(feature = "try-runtime")]
84131
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
85-
frame_support::ensure!(
86-
StorageVersion::<T>::get() == crate::Releases::V11_0_0,
87-
"wrong version after the upgrade"
88-
);
89-
90132
let old_pallet_name = N::get();
91133
let new_pallet_name = <P as PalletInfoAccess>::name();
92134

0 commit comments

Comments
 (0)