From 91abd30cd96b87aa7b30e3a718c169feb0495bfd Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 4 Jan 2023 03:52:48 +0100 Subject: [PATCH 001/131] paged exposure skeleton --- frame/staking/src/lib.rs | 5 +++-- frame/staking/src/pallet/impls.rs | 37 +++++++++++++++++++++++-------- frame/staking/src/pallet/mod.rs | 31 ++++++++++++++++++++++++-- primitives/staking/src/lib.rs | 3 +++ 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d6345c2161f73..17fb987ce913c 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -319,6 +319,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; pub use weights::WeightInfo; pub use pallet::{pallet::*, *}; +use sp_core::ConstU32; pub(crate) const LOG_TARGET: &str = "runtime::staking"; @@ -955,6 +956,6 @@ pub struct TestBenchmarkingConfig; #[cfg(feature = "std")] impl BenchmarkingConfig for TestBenchmarkingConfig { - type MaxValidators = frame_support::traits::ConstU32<100>; - type MaxNominators = frame_support::traits::ConstU32<100>; + type MaxValidators = ConstU32<100>; + type MaxNominators = ConstU32<100>; } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 99c2f6043ee2c..018ad1b244c14 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -561,20 +561,27 @@ impl Pallet { >, new_planned_era: EraIndex, ) -> BoundedVec> { - let elected_stashes: BoundedVec<_, MaxWinnersOf> = exposures - .iter() - .cloned() - .map(|(x, _)| x) - .collect::>() - .try_into() - .expect("since we only map through exposures, size of elected_stashes is always same as exposures; qed"); - - // Populate stakers, exposures, and the snapshot of validator prefs. + // Populate elected stash, stakers, exposures, and the snapshot of validator prefs. let mut total_stake: BalanceOf = Zero::zero(); + let mut elected_stashes = Vec::with_capacity(exposures.len()); exposures.into_iter().for_each(|(stash, exposure)| { + // build elected stash + elected_stashes.push(stash); + total_stake = total_stake.saturating_add(exposure.total); >::insert(new_planned_era, &stash, &exposure); + // split exposure into T::ExposurePageSize chunks + let paged_exposure: BoundedVec< + Exposure>, + T::ExposureMaxPages, + > = Self::get_paged_exposure(exposure); + + paged_exposure.iter().enumerate().for_each(|page, exposure| { + >::insert((new_planned_era, &stash, page), &exposure); + }); + + // fixme: get rid of clipped exposure someday let mut exposure_clipped = exposure; let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; if exposure_clipped.others.len() > clipped_max_len { @@ -584,6 +591,10 @@ impl Pallet { >::insert(&new_planned_era, &stash, exposure_clipped); }); + let elected_stashes: BoundedVec<_, MaxWinnersOf> = elected_stashes + .try_into() + .expect("elected_stashes.len() always equal to exposures.len(); qed"); + // Insert current era staking information >::insert(&new_planned_era, total_stake); @@ -605,6 +616,14 @@ impl Pallet { elected_stashes } + fn get_paged_exposure( + exposure: Exposure>, + ) -> BoundedVec>, T::ExposureMaxPages> { + let page_size = T::ExposurePageSize::get(); + let max_pages = T::ExposureMaxPages::get(); + + todo!() + } /// Consume a set of [`BoundedSupports`] from [`sp_npos_elections`] and collect them into a /// [`Exposure`]. fn collect_exposures( diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index a030538878241..2ec61558d334f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -36,7 +36,7 @@ use sp_runtime::{ traits::{CheckedSub, SaturatedConversion, StaticLookup, Zero}, ArithmeticError, Perbill, Percent, }; -use sp_staking::{EraIndex, SessionIndex}; +use sp_staking::{EraIndex, PageIndex, SessionIndex}; use sp_std::prelude::*; mod impls; @@ -210,6 +210,12 @@ pub mod pallet { #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; + #[pallet::constant] + type ExposurePageSize: Get; + + #[pallet::constant] + type ExposureMaxPages: Get; + /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. type OffendingValidatorsThreshold: Get; @@ -424,7 +430,7 @@ pub mod pallet { /// /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// - /// Is it removed after `HISTORY_DEPTH` eras. + /// It is removed after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. #[pallet::storage] #[pallet::unbounded] @@ -439,6 +445,27 @@ pub mod pallet { ValueQuery, >; + /// Paginated exposure of a validator at given era. + /// + /// This is keyed first by the era index to allow bulk deletion, then the stash account and + /// finally the page. + /// + /// It is removed after `HISTORY_DEPTH` eras. + /// If stakers hasn't been set or has been removed then empty exposure is returned. + #[pallet::storage] + #[pallet::getter(fn paged_eras_stakers)] + #[pallet::unbounded] + pub type PagedErasStakers = StorageNMap< + _, + ( + NMapKey, + NMapKey, + NMapKey, + ), + Exposure>, + ValueQuery, + >; + /// Similar to `ErasStakers`, this holds the preferences of validators. /// /// This is keyed first by the era index to allow bulk deletion and then the stash account. diff --git a/primitives/staking/src/lib.rs b/primitives/staking/src/lib.rs index a8d8e6a602c94..cadddbbc8f4a0 100644 --- a/primitives/staking/src/lib.rs +++ b/primitives/staking/src/lib.rs @@ -31,6 +31,9 @@ pub type SessionIndex = u32; /// Counter for the number of eras that have passed. pub type EraIndex = u32; +/// Counter for paged storage items. +pub type PageIndex = u32; + /// Trait describing something that implements a hook for any operations to perform when a staker is /// slashed. pub trait OnStakerSlash { From 7466cccf29c4e167d4009a663b5fe53a03c91b56 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 4 Jan 2023 05:23:44 +0100 Subject: [PATCH 002/131] insignificant changes --- frame/staking/src/pallet/impls.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 018ad1b244c14..a66a69cba7284 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -571,13 +571,8 @@ impl Pallet { total_stake = total_stake.saturating_add(exposure.total); >::insert(new_planned_era, &stash, &exposure); - // split exposure into T::ExposurePageSize chunks - let paged_exposure: BoundedVec< - Exposure>, - T::ExposureMaxPages, - > = Self::get_paged_exposure(exposure); - - paged_exposure.iter().enumerate().for_each(|page, exposure| { + // store paged exposure + Self::get_paged_exposure(exposure).iter().enumerate().for_each(|page, exposure| { >::insert((new_planned_era, &stash, page), &exposure); }); @@ -616,10 +611,12 @@ impl Pallet { elected_stashes } + fn get_paged_exposure( exposure: Exposure>, ) -> BoundedVec>, T::ExposureMaxPages> { let page_size = T::ExposurePageSize::get(); + // clip exposure if exceeds max_pages let max_pages = T::ExposureMaxPages::get(); todo!() From da60bf835c043a5fd638340f504382a7577b2732 Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 6 Jan 2023 18:51:27 +0100 Subject: [PATCH 003/131] impl paged exposure --- frame/staking/src/lib.rs | 2 +- frame/staking/src/pallet/impls.rs | 47 +++++++++++++++++++++++-------- frame/staking/src/pallet/mod.rs | 3 -- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 17fb987ce913c..d0416098d86f8 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -319,7 +319,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; pub use weights::WeightInfo; pub use pallet::{pallet::*, *}; -use sp_core::ConstU32; +use frame_support::traits::ConstU32; pub(crate) const LOG_TARGET: &str = "runtime::staking"; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a66a69cba7284..1d0fc15a5f041 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -30,6 +30,7 @@ use frame_support::{ }, weights::Weight, }; +use frame_support::traits::Len; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use pallet_session::historical; use sp_runtime::{ @@ -566,17 +567,22 @@ impl Pallet { let mut elected_stashes = Vec::with_capacity(exposures.len()); exposures.into_iter().for_each(|(stash, exposure)| { // build elected stash - elected_stashes.push(stash); + elected_stashes.push(stash.clone()); total_stake = total_stake.saturating_add(exposure.total); >::insert(new_planned_era, &stash, &exposure); // store paged exposure - Self::get_paged_exposure(exposure).iter().enumerate().for_each(|page, exposure| { - >::insert((new_planned_era, &stash, page), &exposure); - }); + Self::get_paged_exposure(&exposure, T::ExposurePageSize::get() as usize).iter().enumerate().for_each( + |(page, paged_exposure)| { + >::insert( + (new_planned_era, &stash, page as u32), + &paged_exposure, + ); + }, + ); - // fixme: get rid of clipped exposure someday + // fixme: get rid of clipped exposure let mut exposure_clipped = exposure; let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; if exposure_clipped.others.len() > clipped_max_len { @@ -611,16 +617,33 @@ impl Pallet { elected_stashes } + /// Takes a full set of exposure and splits it into `page_size` individual exposures. + fn get_paged_exposure( + exposure: &Exposure>, + page_size: usize, + ) -> Vec>> { + let individual_chunks = exposure.others.chunks(page_size); + let mut paged_exposure: Vec>> = Vec::with_capacity(Len::len(&individual_chunks)); - fn get_paged_exposure( - exposure: Exposure>, - ) -> BoundedVec>, T::ExposureMaxPages> { - let page_size = T::ExposurePageSize::get(); - // clip exposure if exceeds max_pages - let max_pages = T::ExposureMaxPages::get(); + // own balance that has not been accounted for in the paged exposure + let mut own_left = exposure.own; - todo!() + for chunk in individual_chunks { + let own = own_left; + let mut total: BalanceOf = own; + for individual in chunk.iter() { + total = total.saturating_add(individual.value); + } + + paged_exposure.push(Exposure { total, own, others: chunk.into() }); + + // subtract own that has been accounted + own_left = own_left.saturating_sub(own); + } + + paged_exposure } + /// Consume a set of [`BoundedSupports`] from [`sp_npos_elections`] and collect them into a /// [`Exposure`]. fn collect_exposures( diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 2ec61558d334f..592afa3745f18 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -213,9 +213,6 @@ pub mod pallet { #[pallet::constant] type ExposurePageSize: Get; - #[pallet::constant] - type ExposureMaxPages: Get; - /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. type OffendingValidatorsThreshold: Get; From 83815ad825e7956e055c95b64c8467fc03345bbb Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 6 Jan 2023 21:14:08 +0100 Subject: [PATCH 004/131] paged as exposure function --- frame/staking/src/lib.rs | 25 ++++++++++++ frame/staking/src/mock.rs | 1 + frame/staking/src/pallet/impls.rs | 67 ++++++++++++++++--------------- 3 files changed, 61 insertions(+), 32 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d0416098d86f8..44fbd74c6b116 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -733,6 +733,31 @@ impl Default for Exposure Exposure { + fn paged(&self, page_size: usize) -> Vec { + let individual_chunks = self.others.chunks(page_size); + let mut paged_exposure: Vec = Vec::with_capacity(individual_chunks.len()); + + // own balance that has not been accounted for in the paged exposure + let mut own_left = self.own; + + for chunk in individual_chunks { + let own = own_left; + let mut total = own; + for individual in chunk.iter() { + total = total.saturating_add(individual.value); + } + + paged_exposure.push(Exposure { total, own, others: chunk.iter().map(|c| IndividualExposure { who: c.who.clone(), value: c.value}).collect() }); + + // subtract own that has been accounted + own_left = own_left.saturating_sub(own); + } + + paged_exposure + } +} + /// A pending slash record. The value of the slash has been computed but not applied yet, /// rather deferred for several eras. #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index e876940cb92d3..2f1803fbf077c 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -293,6 +293,7 @@ impl crate::pallet::pallet::Config for Test { type EraPayout = ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = ConstU32<64>; + type ExposurePageSize = ConstU32<10>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 1d0fc15a5f041..251571fb3063b 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -26,11 +26,10 @@ use frame_support::{ pallet_prelude::*, traits::{ Currency, CurrencyToVote, Defensive, DefensiveResult, EstimateNextNewSession, Get, - Imbalance, LockableCurrency, OnUnbalanced, TryCollect, UnixTime, WithdrawReasons, + Imbalance, Len, LockableCurrency, OnUnbalanced, TryCollect, UnixTime, WithdrawReasons, }, weights::Weight, }; -use frame_support::traits::Len; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use pallet_session::historical; use sp_runtime::{ @@ -573,14 +572,16 @@ impl Pallet { >::insert(new_planned_era, &stash, &exposure); // store paged exposure - Self::get_paged_exposure(&exposure, T::ExposurePageSize::get() as usize).iter().enumerate().for_each( - |(page, paged_exposure)| { + exposure + .paged(T::ExposurePageSize::get() as usize) + .iter() + .enumerate() + .for_each(|(page, paged_exposure)| { >::insert( (new_planned_era, &stash, page as u32), &paged_exposure, ); - }, - ); + }); // fixme: get rid of clipped exposure let mut exposure_clipped = exposure; @@ -617,32 +618,34 @@ impl Pallet { elected_stashes } - /// Takes a full set of exposure and splits it into `page_size` individual exposures. - fn get_paged_exposure( - exposure: &Exposure>, - page_size: usize, - ) -> Vec>> { - let individual_chunks = exposure.others.chunks(page_size); - let mut paged_exposure: Vec>> = Vec::with_capacity(Len::len(&individual_chunks)); - - // own balance that has not been accounted for in the paged exposure - let mut own_left = exposure.own; - - for chunk in individual_chunks { - let own = own_left; - let mut total: BalanceOf = own; - for individual in chunk.iter() { - total = total.saturating_add(individual.value); - } - - paged_exposure.push(Exposure { total, own, others: chunk.into() }); - - // subtract own that has been accounted - own_left = own_left.saturating_sub(own); - } - - paged_exposure - } + // fixme : remove this + // /// Takes a full set of exposure and splits it into `page_size` individual exposures. + // fn get_paged_exposure( + // exposure: &Exposure>, + // page_size: usize, + // ) -> Vec>> { + // let individual_chunks = exposure.others.chunks(page_size); + // let mut paged_exposure: Vec>> = + // Vec::with_capacity(Len::len(&individual_chunks)); + // + // // own balance that has not been accounted for in the paged exposure + // let mut own_left = exposure.own; + // + // for chunk in individual_chunks { + // let own = own_left; + // let mut total: BalanceOf = own; + // for individual in chunk.iter() { + // total = total.saturating_add(individual.value); + // } + // + // paged_exposure.push(Exposure { total, own, others: chunk.into() }); + // + // // subtract own that has been accounted + // own_left = own_left.saturating_sub(own); + // } + // + // paged_exposure + // } /// Consume a set of [`BoundedSupports`] from [`sp_npos_elections`] and collect them into a /// [`Exposure`]. From 5289b5726c0e8b2ee68f72d2a85e17a80c882e57 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 7 Jan 2023 00:28:41 +0100 Subject: [PATCH 005/131] add test for paging exposure --- frame/staking/src/lib.rs | 2 +- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/tests.rs | 34 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 44fbd74c6b116..247a55c159584 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -734,7 +734,7 @@ impl Default for Exposure Exposure { - fn paged(&self, page_size: usize) -> Vec { + fn in_chunks_of(&self, page_size: usize) -> Vec { let individual_chunks = self.others.chunks(page_size); let mut paged_exposure: Vec = Vec::with_capacity(individual_chunks.len()); diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 251571fb3063b..1245826a6435a 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -573,7 +573,7 @@ impl Pallet { // store paged exposure exposure - .paged(T::ExposurePageSize::get() as usize) + .in_chunks_of(T::ExposurePageSize::get() as usize) .iter() .enumerate() .for_each(|(page, paged_exposure)| { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 16bafae01e3c3..9cad8ecf02eb3 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -5775,6 +5775,40 @@ fn set_min_commission_works_with_admin_origin() { }) } +#[test] +fn can_page_exposure() { + let mut others: Vec> = vec![]; + let mut total_stake: Balance = 0; + // 19 nominators + for i in 1..20 { + let individual_stake: Balance = 100 * i as Balance; + others.push(IndividualExposure { who: i, value: individual_stake }); + total_stake += individual_stake; + } + let own_stake: Balance = 500; + total_stake += own_stake; + assert_eq!(total_stake, 19_500); + // build full exposure set + let exposure: Exposure = + Exposure { total: total_stake, own: own_stake, others }; + + // when + let paged_exposures: Vec> = exposure.clone().in_chunks_of(3); + + // then + assert_eq!(paged_exposures.len(), (19 / 3) + 1); + // first page stake = 500 (own) + 100 + 200 + 300 + assert!(matches!(paged_exposures[0], Exposure { total: 1100, own: 500, .. })); + // second page stake = 0 + 400 + 500 + 600 + assert!(matches!(paged_exposures[1], Exposure { total: 1500, own: 0, .. })); + // verify total stake is same as in the original exposure. + assert_eq!(paged_exposures.iter().map(|a| a.total).reduce(|a, b| a + b).unwrap(), 19_500); + // verify own stake is same as in the original exposure. + assert_eq!(paged_exposures.iter().map(|a| a.own).reduce(|a, b| a + b).unwrap(), 500); + // verify number of nominators are same as in the original exposure. + assert_eq!(paged_exposures.iter().map(|a| a.others.len()).reduce(|a, b| a + b).unwrap(), 19); +} + mod staking_interface { use frame_support::storage::with_storage_layer; use sp_staking::StakingInterface; From d6ae0b793dee1ceba1501c060b5c4ef31522477e Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 7 Jan 2023 01:03:58 +0100 Subject: [PATCH 006/131] remove commented fn --- frame/staking/src/pallet/impls.rs | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 1245826a6435a..c0dbfef5484bb 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -617,36 +617,7 @@ impl Pallet { elected_stashes } - - // fixme : remove this - // /// Takes a full set of exposure and splits it into `page_size` individual exposures. - // fn get_paged_exposure( - // exposure: &Exposure>, - // page_size: usize, - // ) -> Vec>> { - // let individual_chunks = exposure.others.chunks(page_size); - // let mut paged_exposure: Vec>> = - // Vec::with_capacity(Len::len(&individual_chunks)); - // - // // own balance that has not been accounted for in the paged exposure - // let mut own_left = exposure.own; - // - // for chunk in individual_chunks { - // let own = own_left; - // let mut total: BalanceOf = own; - // for individual in chunk.iter() { - // total = total.saturating_add(individual.value); - // } - // - // paged_exposure.push(Exposure { total, own, others: chunk.into() }); - // - // // subtract own that has been accounted - // own_left = own_left.saturating_sub(own); - // } - // - // paged_exposure - // } - + /// Consume a set of [`BoundedSupports`] from [`sp_npos_elections`] and collect them into a /// [`Exposure`]. fn collect_exposures( From a30f442e810507d4436f47f1834f79de0a7dd267 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 7 Jan 2023 01:04:50 +0100 Subject: [PATCH 007/131] cargo fmt --- frame/staking/src/lib.rs | 17 ++++++++++++++--- frame/staking/src/pallet/impls.rs | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 247a55c159584..cec0b327f89f5 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -318,8 +318,8 @@ use sp_staking::{ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; pub use weights::WeightInfo; -pub use pallet::{pallet::*, *}; use frame_support::traits::ConstU32; +pub use pallet::{pallet::*, *}; pub(crate) const LOG_TARGET: &str = "runtime::staking"; @@ -733,7 +733,11 @@ impl Default for Exposure Exposure { +impl< + AccountId: Clone, + Balance: Default + HasCompact + sp_runtime::traits::AtLeast32BitUnsigned + Copy, + > Exposure +{ fn in_chunks_of(&self, page_size: usize) -> Vec { let individual_chunks = self.others.chunks(page_size); let mut paged_exposure: Vec = Vec::with_capacity(individual_chunks.len()); @@ -748,7 +752,14 @@ impl Pallet { elected_stashes } - + /// Consume a set of [`BoundedSupports`] from [`sp_npos_elections`] and collect them into a /// [`Exposure`]. fn collect_exposures( From d7b2ca51f43a21d0cd2f002bab80b1d1428701c6 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 7 Jan 2023 01:06:37 +0100 Subject: [PATCH 008/131] more fmt --- frame/staking/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index cec0b327f89f5..09f76d8ec272a 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -733,10 +733,8 @@ impl Default for Exposure Exposure +impl + Exposure { fn in_chunks_of(&self, page_size: usize) -> Vec { let individual_chunks = self.others.chunks(page_size); From 6962b18867874b21e23a441eb5339cf4079ab4f8 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 7 Jan 2023 01:08:46 +0100 Subject: [PATCH 009/131] remove unnecessary bound --- frame/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 09f76d8ec272a..379078fee2edf 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -733,7 +733,7 @@ impl Default for Exposure +impl Exposure { fn in_chunks_of(&self, page_size: usize) -> Vec { From 10a3b1d7190445f7a4c647e684bc931e6626c257 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 8 Jan 2023 21:09:04 +0100 Subject: [PATCH 010/131] add wrapper struct and refactor --- frame/staking/src/pallet/impls.rs | 31 +++---------- frame/staking/src/pallet/mod.rs | 76 ++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 27 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 90347178ac40c..1a3af19b89584 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -33,6 +33,7 @@ use frame_support::{ use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use pallet_session::historical; use sp_runtime::{ + generic::Era, traits::{Bounded, Convert, One, SaturatedConversion, Saturating, StaticLookup, Zero}, Perbill, }; @@ -564,41 +565,21 @@ impl Pallet { // Populate elected stash, stakers, exposures, and the snapshot of validator prefs. let mut total_stake: BalanceOf = Zero::zero(); let mut elected_stashes = Vec::with_capacity(exposures.len()); + exposures.into_iter().for_each(|(stash, exposure)| { // build elected stash elected_stashes.push(stash.clone()); - + // accumulate total stake total_stake = total_stake.saturating_add(exposure.total); - >::insert(new_planned_era, &stash, &exposure); - - // store paged exposure - exposure - .in_chunks_of(T::ExposurePageSize::get() as usize) - .iter() - .enumerate() - .for_each(|(page, paged_exposure)| { - >::insert( - (new_planned_era, &stash, page as u32), - &paged_exposure, - ); - }); - - // fixme: get rid of clipped exposure - let mut exposure_clipped = exposure; - let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; - if exposure_clipped.others.len() > clipped_max_len { - exposure_clipped.others.sort_by(|a, b| a.value.cmp(&b.value).reverse()); - exposure_clipped.others.truncate(clipped_max_len); - } - >::insert(&new_planned_era, &stash, exposure_clipped); + // store staker exposure for this era + EraInfo::::set_validator_exposure(new_planned_era, &stash, exposure); }); let elected_stashes: BoundedVec<_, MaxWinnersOf> = elected_stashes .try_into() .expect("elected_stashes.len() always equal to exposures.len(); qed"); - // Insert current era staking information - >::insert(&new_planned_era, total_stake); + EraInfo::::set_total_stake(new_planned_era, total_stake); // Collect the pref of all winners. for stash in &elected_stashes { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 592afa3745f18..179fc041a69de 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -450,9 +450,9 @@ pub mod pallet { /// It is removed after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. #[pallet::storage] - #[pallet::getter(fn paged_eras_stakers)] + #[pallet::getter(fn eras_stakers_paged)] #[pallet::unbounded] - pub type PagedErasStakers = StorageNMap< + pub type ErasStakersPaged = StorageNMap< _, ( NMapKey, @@ -463,6 +463,26 @@ pub mod pallet { ValueQuery, >; + /// History of rewards claimed by validator by era and page. + /// + /// This is keyed by era and validator stash which maps to the set of page indexes which have + /// been claimed. + /// + /// It is removed after `HISTORY_DEPTH` eras. + #[pallet::storage] + #[pallet::getter(fn claimed_rewards)] + #[pallet::unbounded] + pub type ClaimedRewards = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + // Validator stash + T::AccountId, + Vec, + ValueQuery, + >; + /// Similar to `ErasStakers`, this holds the preferences of validators. /// /// This is keyed first by the era index to allow bulk deletion and then the stash account. @@ -583,6 +603,58 @@ pub mod pallet { #[pallet::getter(fn current_planned_session)] pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; + /// Wrapper struct for `ErasRewards`, `ClaimedRewards`, `ErasRewardsClipped`, + /// `ErasRewardsPaged`, `ErasTotalStake`. + pub(crate) struct EraInfo(sp_std::marker::PhantomData); + impl EraInfo { + pub(crate) fn is_rewards_claimed( + era: EraIndex, + validator: T::AccountId, + page: PageIndex, + ) -> bool { + ClaimedRewards::::get(era, validator).iter().find(|&&p| page == p).is_some() + } + + pub(crate) fn set_rewards_as_claimed( + era: EraIndex, + validator: T::AccountId, + page: PageIndex, + ) { + ClaimedRewards::::mutate(era, validator, |pages| { + pages.push(page); + }) + } + + pub(crate) fn set_validator_exposure( + era: EraIndex, + validator: &T::AccountId, + exposure: Exposure>, + ) { + >::insert(era, &validator, &exposure); + + exposure + .in_chunks_of(T::ExposurePageSize::get() as usize) + .iter() + .enumerate() + .for_each(|(page, paged_exposure)| { + >::insert((era, &validator, page as u32), &paged_exposure); + }); + + // FIXME: get rid of clipped exposure + let mut exposure_clipped = exposure; + let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; + if exposure_clipped.others.len() > clipped_max_len { + exposure_clipped.others.sort_by(|a, b| a.value.cmp(&b.value).reverse()); + exposure_clipped.others.truncate(clipped_max_len); + } + >::insert(era, &validator, exposure_clipped); + } + + pub(crate) fn set_total_stake(era: EraIndex, total_stake: BalanceOf) { + >::insert(era, total_stake); + } + } + /// Indices of validators that have offended in the active era and whether they are currently /// disabled. /// From 3059b9ad2521b0710e6ac33f3510aa05c6ced728 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 8 Jan 2023 21:41:58 +0100 Subject: [PATCH 011/131] create temp fn that checks both ledger and new claimed_rewards --- frame/staking/src/pallet/impls.rs | 38 +++++++++++++++++++------------ frame/staking/src/pallet/mod.rs | 15 +++++++++--- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 1a3af19b89584..ebe93d092f4df 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -160,29 +160,35 @@ impl Pallet { })?; let mut ledger = >::get(&controller).ok_or(Error::::NotController)?; + // clean up older claimed rewards ledger .claimed_rewards .retain(|&x| x >= current_era.saturating_sub(history_depth)); + >::insert(&controller, &ledger); - match ledger.claimed_rewards.binary_search(&era) { - Ok(_) => - return Err(Error::::AlreadyClaimed - .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))), - Err(pos) => ledger - .claimed_rewards - .try_insert(pos, era) - // Since we retain era entries in `claimed_rewards` only upto - // `HistoryDepth`, following bound is always expected to be - // satisfied. - .defensive_map_err(|_| Error::::BoundNotMet)?, + // todo(ank4n): remove + // match ledger.claimed_rewards.binary_search(&era) { + // Ok(_) => + // return Err(Error::::AlreadyClaimed + // .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))), + // Err(pos) => ledger + // .claimed_rewards + // .try_insert(pos, era) + // // Since we retain era entries in `claimed_rewards` only upto + // // `HistoryDepth`, following bound is always expected to be + // // satisfied. + // .defensive_map_err(|_| Error::::BoundNotMet)?, + // } + + if EraInfo::::temp_is_rewards_claimed(era, &ledger, &ledger.stash, 0) { + return Err(Error::::AlreadyClaimed + .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))) + } else { + EraInfo::::set_rewards_as_claimed(era, &ledger.stash, 0); } - let exposure = >::get(&era, &ledger.stash); - // Input data seems good, no errors allowed after this point - >::insert(&controller, &ledger); - // Get Era reward points. It has TOTAL and INDIVIDUAL // Find the fraction of the era reward that belongs to the validator // Take that fraction of the eras rewards to split to nominator and validator @@ -190,6 +196,8 @@ impl Pallet { // Then look at the validator, figure out the proportion of their reward // which goes to them and each of their nominators. + let exposure = >::get(&era, &ledger.stash); + let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; let validator_reward_points = era_reward_points diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 179fc041a69de..10e0bc3980e45 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -607,17 +607,26 @@ pub mod pallet { /// `ErasRewardsPaged`, `ErasTotalStake`. pub(crate) struct EraInfo(sp_std::marker::PhantomData); impl EraInfo { - pub(crate) fn is_rewards_claimed( + + // TODO: Clean up in 84 eras + // looks at ledger for older non paged rewards, and `ClaimedRewards` for newer paged rewards. + pub(crate) fn temp_is_rewards_claimed( era: EraIndex, - validator: T::AccountId, + ledger: &StakingLedger, + validator: &T::AccountId, page: PageIndex, ) -> bool { + ledger.claimed_rewards.binary_search(&era).is_ok() && + Self::is_rewards_claimed(era, validator, page) + } + + fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: PageIndex) -> bool { ClaimedRewards::::get(era, validator).iter().find(|&&p| page == p).is_some() } pub(crate) fn set_rewards_as_claimed( era: EraIndex, - validator: T::AccountId, + validator: &T::AccountId, page: PageIndex, ) { ClaimedRewards::::mutate(era, validator, |pages| { From a06462c0fd20b502b91e3ce9ae39f38587609bf2 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 8 Jan 2023 22:24:00 +0100 Subject: [PATCH 012/131] incomplete, paged extrinisic to pay stakers --- frame/staking/src/pallet/impls.rs | 13 ++++++------- frame/staking/src/pallet/mod.rs | 27 +++++++++++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index ebe93d092f4df..a439285cb998e 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -37,10 +37,7 @@ use sp_runtime::{ traits::{Bounded, Convert, One, SaturatedConversion, Saturating, StaticLookup, Zero}, Perbill, }; -use sp_staking::{ - offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, - EraIndex, SessionIndex, Stake, StakingInterface, -}; +use sp_staking::{offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, EraIndex, SessionIndex, Stake, StakingInterface, PageIndex}; use sp_std::prelude::*; use crate::{ @@ -135,6 +132,7 @@ impl Pallet { pub(super) fn do_payout_stakers( validator_stash: T::AccountId, era: EraIndex, + page: PageIndex, ) -> DispatchResultWithPostInfo { // Validate input data let current_era = CurrentEra::::get().ok_or_else(|| { @@ -180,11 +178,11 @@ impl Pallet { // .defensive_map_err(|_| Error::::BoundNotMet)?, // } - if EraInfo::::temp_is_rewards_claimed(era, &ledger, &ledger.stash, 0) { + if EraInfo::::temp_is_rewards_claimed(era, &ledger, &ledger.stash, page) { return Err(Error::::AlreadyClaimed .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))) } else { - EraInfo::::set_rewards_as_claimed(era, &ledger.stash, 0); + EraInfo::::set_rewards_as_claimed(era, &ledger.stash, page); } // Input data seems good, no errors allowed after this point @@ -196,7 +194,8 @@ impl Pallet { // Then look at the validator, figure out the proportion of their reward // which goes to them and each of their nominators. - let exposure = >::get(&era, &ledger.stash); + let exposure = EraInfo::::get_validator_exposure(era, &ledger.stash, page); + // let exposure = EraInfo::::get_validator_exposure(&era, &ledger.stash, page); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 10e0bc3980e45..5558cd55d6582 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -59,6 +59,7 @@ pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; #[frame_support::pallet] pub mod pallet { use frame_election_provider_support::ElectionDataProvider; + use frame_support::metadata::StorageEntryModifier::Default; use crate::BenchmarkingConfig; @@ -460,7 +461,7 @@ pub mod pallet { NMapKey, ), Exposure>, - ValueQuery, + OptionQuery, >; /// History of rewards claimed by validator by era and page. @@ -607,9 +608,9 @@ pub mod pallet { /// `ErasRewardsPaged`, `ErasTotalStake`. pub(crate) struct EraInfo(sp_std::marker::PhantomData); impl EraInfo { - - // TODO: Clean up in 84 eras - // looks at ledger for older non paged rewards, and `ClaimedRewards` for newer paged rewards. + // TODO(ank4n): doc and clean up in 84 eras + // looks at ledger for older non paged rewards, and `ClaimedRewards` for newer paged + // rewards. pub(crate) fn temp_is_rewards_claimed( era: EraIndex, ledger: &StakingLedger, @@ -624,6 +625,19 @@ pub mod pallet { ClaimedRewards::::get(era, validator).iter().find(|&&p| page == p).is_some() } + pub(crate) fn get_validator_exposure( + era: EraIndex, + validator: &T::AccountId, + page: PageIndex, + ) -> Exposure> { + return match >::get((era, validator, page)) { + Some(paged_exposure) => paged_exposure, + // only return clipped exposure if page zero and no paged exposure entry + None if page == 0 => >::get(&era, &ledger.stash), + _ => Default::Default(), + } + } + pub(crate) fn set_rewards_as_claimed( era: EraIndex, validator: &T::AccountId, @@ -649,7 +663,7 @@ pub mod pallet { >::insert((era, &validator, page as u32), &paged_exposure); }); - // FIXME: get rid of clipped exposure + // fixme(ank4n): no need to keep storing new clipped exposure let mut exposure_clipped = exposure; let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; if exposure_clipped.others.len() > clipped_max_len { @@ -1589,9 +1603,10 @@ pub mod pallet { origin: OriginFor, validator_stash: T::AccountId, era: EraIndex, + page: PageIndex, ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; - Self::do_payout_stakers(validator_stash, era) + Self::do_payout_stakers(validator_stash, era, page) } /// Rebond a portion of the stash scheduled to be unlocked. From eb7d34e2aeeb0ceaaa8162e24d8e7d982a19fb72 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 10 Jan 2023 21:56:48 +0100 Subject: [PATCH 013/131] fix names --- frame/staking/src/pallet/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 5558cd55d6582..e03fe6184d5b3 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -604,8 +604,8 @@ pub mod pallet { #[pallet::getter(fn current_planned_session)] pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; - /// Wrapper struct for `ErasRewards`, `ClaimedRewards`, `ErasRewardsClipped`, - /// `ErasRewardsPaged`, `ErasTotalStake`. + /// Wrapper struct for `ErasStakers`, `ClaimedRewards`, `ErasStakersClipped`, + /// `ErasStakersPaged`, `ErasTotalStake`. pub(crate) struct EraInfo(sp_std::marker::PhantomData); impl EraInfo { // TODO(ank4n): doc and clean up in 84 eras From 423c6ca2f8dc5b7cc302b288093bfc0f5fb89bbd Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 21:03:11 +0100 Subject: [PATCH 014/131] add page as 0 for payout stakers, tests failing currently. --- frame/staking/src/benchmarking.rs | 3 +- frame/staking/src/mock.rs | 2 +- frame/staking/src/pallet/impls.rs | 25 +++------ frame/staking/src/pallet/mod.rs | 33 ++++++------ frame/staking/src/tests.rs | 85 +++++++++++++++++++------------ 5 files changed, 79 insertions(+), 69 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index ad7aab984bdca..7e36f7b4eb97b 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -990,7 +990,8 @@ mod tests { assert_ok!(Staking::payout_stakers( RuntimeOrigin::signed(1337), validator_stash, - current_era + current_era, + 0 )); let new_free_balance = Balances::free_balance(&validator_stash); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 2f1803fbf077c..f0eda820d8507 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -758,7 +758,7 @@ pub(crate) fn make_all_reward_payment(era: EraIndex) { // reward validators for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) { let ledger = >::get(&validator_controller).unwrap(); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), ledger.stash, era)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), ledger.stash, era, 0)); } } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a439285cb998e..7c9d820213c32 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -25,19 +25,21 @@ use frame_support::{ dispatch::WithPostDispatchInfo, pallet_prelude::*, traits::{ - Currency, CurrencyToVote, Defensive, DefensiveResult, EstimateNextNewSession, Get, - Imbalance, Len, LockableCurrency, OnUnbalanced, TryCollect, UnixTime, WithdrawReasons, + Currency, CurrencyToVote, Defensive, EstimateNextNewSession, Get, Imbalance, Len, + LockableCurrency, OnUnbalanced, TryCollect, UnixTime, WithdrawReasons, }, weights::Weight, }; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use pallet_session::historical; use sp_runtime::{ - generic::Era, traits::{Bounded, Convert, One, SaturatedConversion, Saturating, StaticLookup, Zero}, Perbill, }; -use sp_staking::{offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, EraIndex, SessionIndex, Stake, StakingInterface, PageIndex}; +use sp_staking::{ + offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, + EraIndex, PageIndex, SessionIndex, Stake, StakingInterface, +}; use sp_std::prelude::*; use crate::{ @@ -139,6 +141,7 @@ impl Pallet { Error::::InvalidEraToReward .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) })?; + let history_depth = T::HistoryDepth::get(); ensure!( era <= current_era && era >= current_era.saturating_sub(history_depth), @@ -164,20 +167,6 @@ impl Pallet { .retain(|&x| x >= current_era.saturating_sub(history_depth)); >::insert(&controller, &ledger); - // todo(ank4n): remove - // match ledger.claimed_rewards.binary_search(&era) { - // Ok(_) => - // return Err(Error::::AlreadyClaimed - // .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))), - // Err(pos) => ledger - // .claimed_rewards - // .try_insert(pos, era) - // // Since we retain era entries in `claimed_rewards` only upto - // // `HistoryDepth`, following bound is always expected to be - // // satisfied. - // .defensive_map_err(|_| Error::::BoundNotMet)?, - // } - if EraInfo::::temp_is_rewards_claimed(era, &ledger, &ledger.stash, page) { return Err(Error::::AlreadyClaimed .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e03fe6184d5b3..f23bdc6ce76c3 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -59,7 +59,6 @@ pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; #[frame_support::pallet] pub mod pallet { use frame_election_provider_support::ElectionDataProvider; - use frame_support::metadata::StorageEntryModifier::Default; use crate::BenchmarkingConfig; @@ -609,8 +608,8 @@ pub mod pallet { pub(crate) struct EraInfo(sp_std::marker::PhantomData); impl EraInfo { // TODO(ank4n): doc and clean up in 84 eras - // looks at ledger for older non paged rewards, and `ClaimedRewards` for newer paged - // rewards. + // looks at `T::StakingLedger` for older non paged rewards, and `T::ClaimedRewards` for + // newer paged rewards. pub(crate) fn temp_is_rewards_claimed( era: EraIndex, ledger: &StakingLedger, @@ -633,8 +632,8 @@ pub mod pallet { return match >::get((era, validator, page)) { Some(paged_exposure) => paged_exposure, // only return clipped exposure if page zero and no paged exposure entry - None if page == 0 => >::get(&era, &ledger.stash), - _ => Default::Default(), + None if page == 0 => >::get(&era, validator), + _ => Default::default(), } } @@ -662,15 +661,6 @@ pub mod pallet { .for_each(|(page, paged_exposure)| { >::insert((era, &validator, page as u32), &paged_exposure); }); - - // fixme(ank4n): no need to keep storing new clipped exposure - let mut exposure_clipped = exposure; - let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; - if exposure_clipped.others.len() > clipped_max_len { - exposure_clipped.others.sort_by(|a, b| a.value.cmp(&b.value).reverse()); - exposure_clipped.others.truncate(clipped_max_len); - } - >::insert(era, &validator, exposure_clipped); } pub(crate) fn set_total_stake(era: EraIndex, total_stake: BalanceOf) { @@ -1593,8 +1583,19 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// ## Complexity - /// - At most O(MaxNominatorRewardedPerValidator). + /// # + /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). + /// - Contains a limited number of reads and writes. + /// ----------- + /// N is the Number of payouts for the validator (including the validator) + /// Weight: + /// - Reward Destination Staked: O(N) + /// - Reward Destination Controller (Creating): O(N) + /// + /// NOTE: weights are assuming that payouts are made to alive stash account (Staked). + /// Paying even a dead controller is cheaper weight-wise. We don't do any refunds here. + /// # + // todo(ank4n): fix weights. #[pallet::call_index(18)] #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( T::MaxNominatorRewardedPerValidator::get() diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 9cad8ecf02eb3..c29bf00b731a0 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2194,7 +2194,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { ErasStakers::::insert(0, 11, &exposure); ErasStakersClipped::::insert(0, 11, exposure); ErasValidatorReward::::insert(0, stake); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); // Set staker @@ -3562,19 +3562,19 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // Last kept is 1: assert!(current_era - HistoryDepth::get() == 1); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0), // Fail: Era out of history Error::::InvalidEraToReward.with_weight(err_weight) ); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0)); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0), // Fail: Double claim Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, active_era), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, active_era, 0), // Fail: Era not finished yet Error::::InvalidEraToReward.with_weight(err_weight) ); @@ -3752,7 +3752,7 @@ fn test_payout_stakers() { let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); assert_eq_error_rate!( Balances::total_issuance(), pre_payout_total_issuance + actual_paid_out, @@ -3793,7 +3793,7 @@ fn test_payout_stakers() { mock::start_active_era(i); RewardOnUnbalanceWasCalled::set(false); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, i - 1)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, i - 1, 0)); assert_eq_error_rate!( Balances::total_issuance(), pre_payout_total_issuance + actual_paid_out, @@ -3829,12 +3829,14 @@ fn test_payout_stakers() { assert_ok!(Staking::payout_stakers( RuntimeOrigin::signed(1337), 11, - expected_start_reward_era + expected_start_reward_era, + 0 )); assert_ok!(Staking::payout_stakers( RuntimeOrigin::signed(1337), 11, - expected_last_reward_era + expected_last_reward_era, + 0 )); assert_eq!( Staking::ledger(&10), @@ -3848,9 +3850,9 @@ fn test_payout_stakers() { ); // Out of order claims works. - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 69)); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 23)); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 42)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 69, 0)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 23, 0)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 42, 0)); assert_eq!( Staking::ledger(&10), Some(StakingLedger { @@ -3896,12 +3898,12 @@ fn payout_stakers_handles_basic_errors() { // Wrong Era, too big assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0), Error::::InvalidEraToReward.with_weight(err_weight) ); // Wrong Staker assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 10, 1), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 10, 1, 0), Error::::NotStash.with_weight(err_weight) ); @@ -3921,31 +3923,43 @@ fn payout_stakers_handles_basic_errors() { // to payout era starting from expected_start_reward_era=19 through // expected_last_reward_era=98 (80 total eras), but not 18 or 99. assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_start_reward_era - 1), + Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + expected_start_reward_era - 1, + 0 + ), Error::::InvalidEraToReward.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era + 1), + Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + expected_last_reward_era + 1, + 0 + ), Error::::InvalidEraToReward.with_weight(err_weight) ); assert_ok!(Staking::payout_stakers( RuntimeOrigin::signed(1337), 11, - expected_start_reward_era + expected_start_reward_era, + 0 )); assert_ok!(Staking::payout_stakers( RuntimeOrigin::signed(1337), 11, - expected_last_reward_era + expected_last_reward_era, + 0 )); // Can't claim again assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_start_reward_era), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_start_reward_era, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era), + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); }); @@ -3993,7 +4007,8 @@ fn payout_stakers_handles_weight_refund() { start_active_era(2); // Collect payouts when there are no nominators - let call = TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 1 }); + let call = + TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 1, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4006,7 +4021,8 @@ fn payout_stakers_handles_weight_refund() { start_active_era(3); // Collect payouts for an era where the validator did not receive any points. - let call = TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 2 }); + let call = + TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 2, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4019,7 +4035,8 @@ fn payout_stakers_handles_weight_refund() { start_active_era(4); // Collect payouts when the validator has `half_max_nom_rewarded` nominators. - let call = TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 3 }); + let call = + TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 3, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4042,14 +4059,16 @@ fn payout_stakers_handles_weight_refund() { start_active_era(6); // Collect payouts when the validator had `half_max_nom_rewarded` nominators. - let call = TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5 }); + let call = + TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); assert_eq!(extract_actual_weight(&result, &info), max_nom_rewarded_weight); // Try and collect payouts for an era that has already been collected. - let call = TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5 }); + let call = + TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert!(result.is_err()); @@ -4195,7 +4214,7 @@ fn payout_creates_controller() { // compute and ensure the reward amount is greater than zero. let _ = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(2); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); // Controller is created assert!(Balances::free_balance(1337) > 0); @@ -4223,7 +4242,7 @@ fn payout_to_any_account_works() { // compute and ensure the reward amount is greater than zero. let _ = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(2); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); // Payment is successful assert!(Balances::free_balance(42) > 0); @@ -5524,14 +5543,14 @@ fn pre_bonding_era_cannot_be_claimed() { mock::start_active_era(current_era); // claiming reward for last era in which validator was active works - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1, 0)); // consumed weight for all payout_stakers dispatches that fail let err_weight = ::WeightInfo::payout_stakers_alive_staked(0); // cannot claim rewards for an era before bonding occured as it is // already marked as claimed. assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 2), + Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 2, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); @@ -5541,7 +5560,7 @@ fn pre_bonding_era_cannot_be_claimed() { // make sure stakers still cannot claim rewards that they are not meant to assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 2), + Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 2, 0), Error::::NotController ); @@ -5590,7 +5609,7 @@ fn reducing_history_depth_abrupt() { mock::start_active_era(current_era); // claiming reward for last era in which validator was active works - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1)); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1, 0)); // next era current_era = current_era + 1; @@ -5601,7 +5620,7 @@ fn reducing_history_depth_abrupt() { HistoryDepth::set(history_depth); // claiming reward does not work anymore assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1), + Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1, 0), Error::::NotController ); From 56fbe4e8881a23b65832a689d19c21ff6d686044 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 21:53:25 +0100 Subject: [PATCH 015/131] fix double claim --- frame/staking/src/pallet/mod.rs | 2 +- frame/staking/src/tests.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index f23bdc6ce76c3..ecf57f356867e 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -616,7 +616,7 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) -> bool { - ledger.claimed_rewards.binary_search(&era).is_ok() && + ledger.claimed_rewards.binary_search(&era).is_ok() || Self::is_rewards_claimed(era, validator, page) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index c29bf00b731a0..2e516c8e672be 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3536,8 +3536,9 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { mock::start_active_era(1); Pallet::::reward_by_ids(vec![(11, 1)]); - // Change total issuance in order to modify total payout + // Increase total token issuance to affect the total payout. let _ = Balances::deposit_creating(&999, 1_000_000_000); + // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); assert!(total_payout_1 != total_payout_0); @@ -3545,7 +3546,7 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { mock::start_active_era(2); Pallet::::reward_by_ids(vec![(11, 1)]); - // Change total issuance in order to modify total payout + // Increase total token issuance to affect the total payout. let _ = Balances::deposit_creating(&999, 1_000_000_000); // Compute total payout now for whole duration as other parameter won't change let total_payout_2 = current_total_payout_for_duration(reward_time_per_era()); From 2ea2e6b36cd9337809207a27210c6f50a485667b Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 21:59:43 +0100 Subject: [PATCH 016/131] don't store claimed rewards for previous eras in the ledger --- frame/staking/src/pallet/mod.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index ecf57f356867e..922aac70ba1b8 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -988,10 +988,6 @@ pub mod pallet { >::insert(&stash, &controller); >::insert(&stash, payee); - let current_era = CurrentEra::::get().unwrap_or(0); - let history_depth = T::HistoryDepth::get(); - let last_reward_era = current_era.saturating_sub(history_depth); - let stash_balance = T::Currency::free_balance(&stash); let value = value.min(stash_balance); Self::deposit_event(Event::::Bonded { stash: stash.clone(), amount: value }); @@ -1000,12 +996,7 @@ pub mod pallet { total: value, active: value, unlocking: Default::default(), - claimed_rewards: (last_reward_era..current_era) - .try_collect() - // Since last_reward_era is calculated as `current_era - - // HistoryDepth`, following bound is always expected to be - // satisfied. - .defensive_map_err(|_| Error::::BoundNotMet)?, + claimed_rewards: Default::default(), }; Self::update_ledger(&controller, &item); Ok(()) From e0af61872c0ce4ab9af7e50de903366956ea54dc Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 22:04:06 +0100 Subject: [PATCH 017/131] mark claimed_rewards in Staking ledger as legacy --- frame/staking/src/benchmarking.rs | 2 +- frame/staking/src/lib.rs | 6 +- frame/staking/src/pallet/impls.rs | 12 +-- frame/staking/src/pallet/mod.rs | 9 +-- frame/staking/src/tests.rs | 120 +++++++++++++++--------------- 5 files changed, 74 insertions(+), 75 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 7e36f7b4eb97b..0366809f2d5a8 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -681,7 +681,7 @@ benchmarks! { active: T::Currency::minimum_balance() - One::one(), total: T::Currency::minimum_balance() - One::one(), unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), }; Ledger::::insert(&controller, l); diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 379078fee2edf..8b4f83657c261 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -468,7 +468,7 @@ pub struct StakingLedger { pub unlocking: BoundedVec>, T::MaxUnlockingChunks>, /// List of eras for which the stakers behind a validator have claimed rewards. Only updated /// for validators. - pub claimed_rewards: BoundedVec, + pub legacy_claimed_rewards: BoundedVec, } impl StakingLedger { @@ -479,7 +479,7 @@ impl StakingLedger { total: Zero::zero(), active: Zero::zero(), unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), } } @@ -509,7 +509,7 @@ impl StakingLedger { total, active: self.active, unlocking, - claimed_rewards: self.claimed_rewards, + legacy_claimed_rewards: self.legacy_claimed_rewards, } } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 7c9d820213c32..1b154b4e3390a 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -150,7 +150,7 @@ impl Pallet { ); // Note: if era has no reward to be claimed, era may be future. better not to update - // `ledger.claimed_rewards` in this case. + // `ledger.legacy_claimed_rewards` in this case. let era_payout = >::get(&era).ok_or_else(|| { Error::::InvalidEraToReward .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) @@ -163,7 +163,7 @@ impl Pallet { // clean up older claimed rewards ledger - .claimed_rewards + .legacy_claimed_rewards .retain(|&x| x >= current_era.saturating_sub(history_depth)); >::insert(&controller, &ledger); @@ -1055,7 +1055,7 @@ impl ElectionDataProvider for Pallet { active: stake, total: stake, unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), }, ); @@ -1073,7 +1073,7 @@ impl ElectionDataProvider for Pallet { active: stake, total: stake, unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), }, ); Self::do_add_validator( @@ -1114,7 +1114,7 @@ impl ElectionDataProvider for Pallet { active: stake, total: stake, unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), }, ); Self::do_add_validator( @@ -1135,7 +1135,7 @@ impl ElectionDataProvider for Pallet { active: stake, total: stake, unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), }, ); Self::do_add_nominator( diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 922aac70ba1b8..9a5e29cb4d9a2 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -139,8 +139,7 @@ pub mod pallet { /// Following information is kept for eras in `[current_era - /// HistoryDepth, current_era]`: `ErasStakers`, `ErasStakersClipped`, /// `ErasValidatorPrefs`, `ErasValidatorReward`, `ErasRewardPoints`, - /// `ErasTotalStake`, `ErasStartSessionIndex`, - /// `StakingLedger.claimed_rewards`. + /// `ErasTotalStake`, `ErasStartSessionIndex`, `ClaimedRewards`. /// /// Must be more than the number of eras delayed by session. /// I.e. active era must always be in history. I.e. `active_era > @@ -150,7 +149,7 @@ pub mod pallet { /// this should be set to same value or greater as in storage. /// /// Note: `HistoryDepth` is used as the upper bound for the `BoundedVec` - /// item `StakingLedger.claimed_rewards`. Setting this value lower than + /// item `StakingLedger.legacy_claimed_rewards`. Setting this value lower than /// the existing value can lead to inconsistencies in the /// `StakingLedger` and will need to be handled properly in a migration. /// The test `reducing_history_depth_abrupt` shows this effect. @@ -616,7 +615,7 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) -> bool { - ledger.claimed_rewards.binary_search(&era).is_ok() || + ledger.legacy_claimed_rewards.binary_search(&era).is_ok() || Self::is_rewards_claimed(era, validator, page) } @@ -996,7 +995,7 @@ pub mod pallet { total: value, active: value, unlocking: Default::default(), - claimed_rewards: Default::default(), + legacy_claimed_rewards: Default::default(), }; Self::update_ledger(&controller, &item); Ok(()) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 2e516c8e672be..a53dea8d986d3 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -154,7 +154,7 @@ fn basic_setup_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); // Account 20 controls the stash from account 21, which is 200 * balance_factor units @@ -165,7 +165,7 @@ fn basic_setup_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); // Account 1 does not control any stash @@ -188,7 +188,7 @@ fn basic_setup_works() { total: 500, active: 500, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); @@ -441,7 +441,7 @@ fn staking_should_work() { total: 1500, active: 1500, unlocking: Default::default(), - claimed_rewards: bounded_vec![0], + legacy_claimed_rewards: bounded_vec![0], }) ); // e.g. it cannot reserve more than 500 that it has free from the total 2000 @@ -1030,7 +1030,7 @@ fn reward_destination_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1053,7 +1053,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: Default::default(), - claimed_rewards: bounded_vec![0], + legacy_claimed_rewards: bounded_vec![0], }) ); @@ -1081,7 +1081,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: Default::default(), - claimed_rewards: bounded_vec![0, 1], + legacy_claimed_rewards: bounded_vec![0, 1], }) ); @@ -1110,7 +1110,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: Default::default(), - claimed_rewards: bounded_vec![0, 1, 2], + legacy_claimed_rewards: bounded_vec![0, 1, 2], }) ); // Check that amount in staked account is NOT increased. @@ -1172,7 +1172,7 @@ fn bond_extra_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1189,7 +1189,7 @@ fn bond_extra_works() { total: 1000 + 100, active: 1000 + 100, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1203,7 +1203,7 @@ fn bond_extra_works() { total: 1000000, active: 1000000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); }); @@ -1241,7 +1241,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); assert_eq!( @@ -1259,7 +1259,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); // Exposure is a snapshot! only updated after the next era update. @@ -1280,7 +1280,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); // Exposure is now updated. @@ -1298,7 +1298,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 100, unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }), ); @@ -1311,7 +1311,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 100, unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }), ); @@ -1327,7 +1327,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 100, unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }), ); @@ -1343,7 +1343,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 100, active: 100, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }), ); }) @@ -1446,7 +1446,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1465,7 +1465,7 @@ fn rebond_works() { total: 1000, active: 100, unlocking: bounded_vec![UnlockChunk { value: 900, era: 2 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1478,7 +1478,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1491,7 +1491,7 @@ fn rebond_works() { total: 1000, active: 100, unlocking: bounded_vec![UnlockChunk { value: 900, era: 5 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1504,7 +1504,7 @@ fn rebond_works() { total: 1000, active: 600, unlocking: bounded_vec![UnlockChunk { value: 400, era: 5 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1517,7 +1517,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1532,7 +1532,7 @@ fn rebond_works() { total: 1000, active: 100, unlocking: bounded_vec![UnlockChunk { value: 900, era: 5 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1545,7 +1545,7 @@ fn rebond_works() { total: 1000, active: 600, unlocking: bounded_vec![UnlockChunk { value: 400, era: 5 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); }) @@ -1572,7 +1572,7 @@ fn rebond_is_fifo() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1587,7 +1587,7 @@ fn rebond_is_fifo() { total: 1000, active: 600, unlocking: bounded_vec![UnlockChunk { value: 400, era: 2 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1605,7 +1605,7 @@ fn rebond_is_fifo() { UnlockChunk { value: 400, era: 2 + 3 }, UnlockChunk { value: 300, era: 3 + 3 }, ], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1624,7 +1624,7 @@ fn rebond_is_fifo() { UnlockChunk { value: 300, era: 3 + 3 }, UnlockChunk { value: 200, era: 4 + 3 }, ], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1640,7 +1640,7 @@ fn rebond_is_fifo() { UnlockChunk { value: 400, era: 2 + 3 }, UnlockChunk { value: 100, era: 3 + 3 }, ], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); }) @@ -1669,7 +1669,7 @@ fn rebond_emits_right_value_in_event() { total: 1000, active: 100, unlocking: bounded_vec![UnlockChunk { value: 900, era: 1 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -1682,7 +1682,7 @@ fn rebond_emits_right_value_in_event() { total: 1000, active: 200, unlocking: bounded_vec![UnlockChunk { value: 800, era: 1 + 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); // Event emitted should be correct @@ -1697,7 +1697,7 @@ fn rebond_emits_right_value_in_event() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); // Event emitted should be correct, only 800 @@ -1733,7 +1733,7 @@ fn reward_to_stake_works() { total: 69, active: 69, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }, ); @@ -1797,7 +1797,7 @@ fn reap_stash_works() { total: 5, active: 5, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }, ); @@ -1932,7 +1932,7 @@ fn bond_with_no_staked_value() { active: 0, total: 5, unlocking: bounded_vec![UnlockChunk { value: 5, era: 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); @@ -3035,7 +3035,7 @@ fn staker_cannot_bail_deferred_slash() { active: 0, total: 500, stash: 101, - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], unlocking: bounded_vec![UnlockChunk { era: 4u32, value: 500 }], } ); @@ -3772,7 +3772,7 @@ fn test_payout_stakers() { assert_eq!(Balances::free_balance(&(100 + i)), balance + i as Balance); } - // We track rewards in `claimed_rewards` vec + // We track rewards in `legacy_claimed_rewards` vec assert_eq!( Staking::ledger(&10), Some(StakingLedger { @@ -3780,7 +3780,7 @@ fn test_payout_stakers() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![1] + legacy_claimed_rewards: bounded_vec![1] }) ); @@ -3811,7 +3811,7 @@ fn test_payout_stakers() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: (1..=14).collect::>().try_into().unwrap() + legacy_claimed_rewards: (1..=14).collect::>().try_into().unwrap() }) ); @@ -3846,7 +3846,7 @@ fn test_payout_stakers() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![expected_start_reward_era, expected_last_reward_era] + legacy_claimed_rewards: bounded_vec![expected_start_reward_era, expected_last_reward_era] }) ); @@ -3861,7 +3861,7 @@ fn test_payout_stakers() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![ + legacy_claimed_rewards: bounded_vec![ expected_start_reward_era, 23, 42, @@ -4090,7 +4090,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }) ); mock::start_active_era(5); @@ -4102,7 +4102,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: (0..5).collect::>().try_into().unwrap(), + legacy_claimed_rewards: (0..5).collect::>().try_into().unwrap(), }) ); @@ -4118,7 +4118,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { total: 1000, active: 1000, unlocking: Default::default(), - claimed_rewards: (last_reward_era..current_era) + legacy_claimed_rewards: (last_reward_era..current_era) .collect::>() .try_into() .unwrap(), @@ -4366,7 +4366,7 @@ fn cannot_rebond_to_lower_than_ed() { total: 10 * 1000, active: 10 * 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); @@ -4380,7 +4380,7 @@ fn cannot_rebond_to_lower_than_ed() { total: 10 * 1000, active: 0, unlocking: bounded_vec![UnlockChunk { value: 10 * 1000, era: 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); @@ -4406,7 +4406,7 @@ fn cannot_bond_extra_to_lower_than_ed() { total: 10 * 1000, active: 10 * 1000, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); @@ -4420,7 +4420,7 @@ fn cannot_bond_extra_to_lower_than_ed() { total: 10 * 1000, active: 0, unlocking: bounded_vec![UnlockChunk { value: 10 * 1000, era: 3 }], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); @@ -4447,7 +4447,7 @@ fn do_not_die_when_active_is_ed() { total: 1000 * ed, active: 1000 * ed, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); @@ -4464,7 +4464,7 @@ fn do_not_die_when_active_is_ed() { total: ed, active: ed, unlocking: Default::default(), - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], } ); }) @@ -5271,7 +5271,7 @@ fn proportional_slash_stop_slashing_if_remaining_zero() { active: 20, // we have some chunks, but they are not affected. unlocking: bounded_vec![c(1, 10), c(2, 10)], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }; assert_eq!(BondingDuration::get(), 3); @@ -5289,7 +5289,7 @@ fn proportional_ledger_slash_works() { total: 10, active: 10, unlocking: bounded_vec![], - claimed_rewards: bounded_vec![], + legacy_claimed_rewards: bounded_vec![], }; assert_eq!(BondingDuration::get(), 3); @@ -5526,7 +5526,7 @@ fn pre_bonding_era_cannot_be_claimed() { // add a new candidate for being a validator. account 3 controlled by 4. assert_ok!(Staking::bond(RuntimeOrigin::signed(3), 4, 1500, RewardDestination::Controller)); - let claimed_rewards: BoundedVec<_, _> = + let legacy_claimed_rewards: BoundedVec<_, _> = (start_reward_era..=last_reward_era).collect::>().try_into().unwrap(); assert_eq!( Staking::ledger(&4).unwrap(), @@ -5535,7 +5535,7 @@ fn pre_bonding_era_cannot_be_claimed() { total: 1500, active: 1500, unlocking: Default::default(), - claimed_rewards, + legacy_claimed_rewards: legacy_claimed_rewards, } ); @@ -5592,7 +5592,7 @@ fn reducing_history_depth_abrupt() { // all previous era before the bonding action should be marked as // claimed. - let claimed_rewards: BoundedVec<_, _> = + let legacy_claimed_rewards: BoundedVec<_, _> = (start_reward_era..=last_reward_era).collect::>().try_into().unwrap(); assert_eq!( Staking::ledger(&4).unwrap(), @@ -5601,7 +5601,7 @@ fn reducing_history_depth_abrupt() { total: 1500, active: 1500, unlocking: Default::default(), - claimed_rewards, + legacy_claimed_rewards: legacy_claimed_rewards, } ); @@ -5631,7 +5631,7 @@ fn reducing_history_depth_abrupt() { // new staking ledgers created will be bounded by the current history depth let last_reward_era = current_era - 1; let start_reward_era = current_era - history_depth; - let claimed_rewards: BoundedVec<_, _> = + let legacy_claimed_rewards: BoundedVec<_, _> = (start_reward_era..=last_reward_era).collect::>().try_into().unwrap(); assert_eq!( Staking::ledger(&6).unwrap(), @@ -5640,7 +5640,7 @@ fn reducing_history_depth_abrupt() { total: 1200, active: 1200, unlocking: Default::default(), - claimed_rewards, + legacy_claimed_rewards: legacy_claimed_rewards, } ); From 09f2384703c22a0973a84cd2be2727f0597fd1b7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 22:07:57 +0100 Subject: [PATCH 018/131] test for not populating legacy claimed rewards anymore --- frame/staking/src/tests.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index a53dea8d986d3..aada44f27d88c 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4079,7 +4079,7 @@ fn payout_stakers_handles_weight_refund() { } #[test] -fn bond_during_era_correctly_populates_claimed_rewards() { +fn bond_during_era_does_not_populate_legacy_claimed_rewards() { ExtBuilder::default().has_stakers(false).build_and_execute(|| { // Era = None bond_validator(9, 8, 1000); @@ -4102,13 +4102,12 @@ fn bond_during_era_correctly_populates_claimed_rewards() { total: 1000, active: 1000, unlocking: Default::default(), - legacy_claimed_rewards: (0..5).collect::>().try_into().unwrap(), + legacy_claimed_rewards: bounded_vec![], }) ); // make sure only era upto history depth is stored let current_era = 99; - let last_reward_era = 99 - HistoryDepth::get(); mock::start_active_era(current_era); bond_validator(13, 12, 1000); assert_eq!( @@ -4118,10 +4117,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { total: 1000, active: 1000, unlocking: Default::default(), - legacy_claimed_rewards: (last_reward_era..current_era) - .collect::>() - .try_into() - .unwrap(), + legacy_claimed_rewards: Default::default(), }) ); }); From 07d8725d1429cfc62f8b68d9679744ccbbe1fdba Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 22:08:47 +0100 Subject: [PATCH 019/131] test is not accurate since for prebonded era, there cannot be any reward points to claim --- frame/staking/src/tests.rs | 143 ------------------------------------- 1 file changed, 143 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index aada44f27d88c..1665caa792f7c 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -5502,149 +5502,6 @@ fn proportional_ledger_slash_works() { ); } -#[test] -fn pre_bonding_era_cannot_be_claimed() { - // Verifies initial conditions of mock - ExtBuilder::default().nominate(false).build_and_execute(|| { - let history_depth = HistoryDepth::get(); - // jump to some era above history_depth - let mut current_era = history_depth + 10; - let last_reward_era = current_era - 1; - let start_reward_era = current_era - history_depth; - - // put some money in stash=3 and controller=4. - for i in 3..5 { - let _ = Balances::make_free_balance_be(&i, 2000); - } - - mock::start_active_era(current_era); - - // add a new candidate for being a validator. account 3 controlled by 4. - assert_ok!(Staking::bond(RuntimeOrigin::signed(3), 4, 1500, RewardDestination::Controller)); - - let legacy_claimed_rewards: BoundedVec<_, _> = - (start_reward_era..=last_reward_era).collect::>().try_into().unwrap(); - assert_eq!( - Staking::ledger(&4).unwrap(), - StakingLedger { - stash: 3, - total: 1500, - active: 1500, - unlocking: Default::default(), - legacy_claimed_rewards: legacy_claimed_rewards, - } - ); - - // start next era - current_era = current_era + 1; - mock::start_active_era(current_era); - - // claiming reward for last era in which validator was active works - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1, 0)); - - // consumed weight for all payout_stakers dispatches that fail - let err_weight = ::WeightInfo::payout_stakers_alive_staked(0); - // cannot claim rewards for an era before bonding occured as it is - // already marked as claimed. - assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 2, 0), - Error::::AlreadyClaimed.with_weight(err_weight) - ); - - // decoding will fail now since Staking Ledger is in corrupt state - HistoryDepth::set(history_depth - 1); - assert_eq!(Staking::ledger(&4), None); - - // make sure stakers still cannot claim rewards that they are not meant to - assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 2, 0), - Error::::NotController - ); - - // fix the corrupted state for post conditions check - HistoryDepth::set(history_depth); - }); -} - -#[test] -fn reducing_history_depth_abrupt() { - // Verifies initial conditions of mock - ExtBuilder::default().nominate(false).build_and_execute(|| { - let original_history_depth = HistoryDepth::get(); - let mut current_era = original_history_depth + 10; - let last_reward_era = current_era - 1; - let start_reward_era = current_era - original_history_depth; - - // put some money in (stash, controller)=(3,4),(5,6). - for i in 3..7 { - let _ = Balances::make_free_balance_be(&i, 2000); - } - - // start current era - mock::start_active_era(current_era); - - // add a new candidate for being a staker. account 3 controlled by 4. - assert_ok!(Staking::bond(RuntimeOrigin::signed(3), 4, 1500, RewardDestination::Controller)); - - // all previous era before the bonding action should be marked as - // claimed. - let legacy_claimed_rewards: BoundedVec<_, _> = - (start_reward_era..=last_reward_era).collect::>().try_into().unwrap(); - assert_eq!( - Staking::ledger(&4).unwrap(), - StakingLedger { - stash: 3, - total: 1500, - active: 1500, - unlocking: Default::default(), - legacy_claimed_rewards: legacy_claimed_rewards, - } - ); - - // next era - current_era = current_era + 1; - mock::start_active_era(current_era); - - // claiming reward for last era in which validator was active works - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1, 0)); - - // next era - current_era = current_era + 1; - mock::start_active_era(current_era); - - // history_depth reduced without migration - let history_depth = original_history_depth - 1; - HistoryDepth::set(history_depth); - // claiming reward does not work anymore - assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(4), 3, current_era - 1, 0), - Error::::NotController - ); - - // new stakers can still bond - assert_ok!(Staking::bond(RuntimeOrigin::signed(5), 6, 1200, RewardDestination::Controller)); - - // new staking ledgers created will be bounded by the current history depth - let last_reward_era = current_era - 1; - let start_reward_era = current_era - history_depth; - let legacy_claimed_rewards: BoundedVec<_, _> = - (start_reward_era..=last_reward_era).collect::>().try_into().unwrap(); - assert_eq!( - Staking::ledger(&6).unwrap(), - StakingLedger { - stash: 5, - total: 1200, - active: 1200, - unlocking: Default::default(), - legacy_claimed_rewards: legacy_claimed_rewards, - } - ); - - // fix the corrupted state for post conditions check - HistoryDepth::set(original_history_depth); - }); -} - #[test] fn reducing_max_unlocking_chunks_abrupt() { // Concern is on validators only From c962bf567c201c2b1cc1a006b24e2d9797ec55c8 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 22:14:29 +0100 Subject: [PATCH 020/131] fmt --- frame/staking/src/pallet/mod.rs | 5 ++--- frame/staking/src/tests.rs | 5 ++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 9a5e29cb4d9a2..20312f5a34719 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -24,9 +24,8 @@ use frame_support::{ dispatch::Codec, pallet_prelude::*, traits::{ - Currency, CurrencyToVote, Defensive, DefensiveResult, DefensiveSaturating, EnsureOrigin, - EstimateNextNewSession, Get, LockIdentifier, LockableCurrency, OnUnbalanced, TryCollect, - UnixTime, + Currency, CurrencyToVote, Defensive, DefensiveSaturating, EnsureOrigin, + EstimateNextNewSession, Get, LockIdentifier, LockableCurrency, OnUnbalanced, UnixTime, }, weights::Weight, BoundedVec, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 1665caa792f7c..0a48cac41892e 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3846,7 +3846,10 @@ fn test_payout_stakers() { total: 1000, active: 1000, unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![expected_start_reward_era, expected_last_reward_era] + legacy_claimed_rewards: bounded_vec![ + expected_start_reward_era, + expected_last_reward_era + ] }) ); From 8a55bb2b29b72b115ce92bebe6a461aea877b0c8 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 14 Jan 2023 22:34:51 +0100 Subject: [PATCH 021/131] assert claimed rewards is populated --- frame/staking/src/mock.rs | 1 + frame/staking/src/pallet/impls.rs | 1 - frame/staking/src/tests.rs | 16 +++++++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index f0eda820d8507..42f77e17c68ba 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -748,6 +748,7 @@ pub(crate) fn add_slash(who: &AccountId) { } /// Make all validator and nominator request their payment +// TODO(ank4n) pay out all the paged nominators. pub(crate) fn make_all_reward_payment(era: EraIndex) { let validators_with_reward = ErasRewardPoints::::get(era) .individual diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 1b154b4e3390a..d8e4cc429ffc0 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -184,7 +184,6 @@ impl Pallet { // which goes to them and each of their nominators. let exposure = EraInfo::::get_validator_exposure(era, &ledger.stash, page); - // let exposure = EraInfo::::get_validator_exposure(&era, &ledger.stash, page); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 0a48cac41892e..a9626e453a304 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1053,10 +1053,13 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![0], + legacy_claimed_rewards: bounded_vec![], }) ); + // (era 0, page 0) is claimed + assert_eq!(Staking::claimed_rewards(0, &11), vec![0]); + // Change RewardDestination to Stash >::insert(&11, RewardDestination::Stash); @@ -1081,10 +1084,13 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![0, 1], + legacy_claimed_rewards: bounded_vec![], }) ); + // (era 1, page 0) is claimed + assert_eq!(Staking::claimed_rewards(1, &11), vec![0]); + // Change RewardDestination to Controller >::insert(&11, RewardDestination::Controller); @@ -1110,9 +1116,13 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![0, 1, 2], + legacy_claimed_rewards: bounded_vec![], }) ); + + // (era 2, page 0) is claimed + assert_eq!(Staking::claimed_rewards(2, &11), vec![0]); + // Check that amount in staked account is NOT increased. assert_eq!(Balances::free_balance(11), recorded_stash_balance); }); From fae1d0a37083d2bd24b15e46836b9aa5e4ab8d81 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 15 Jan 2023 02:54:55 +0100 Subject: [PATCH 022/131] introduce struct ExposurePage --- frame/staking/src/lib.rs | 48 +++++++++++++++++++++++++++---- frame/staking/src/mock.rs | 2 +- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 10 +++---- frame/staking/src/tests.rs | 17 +++++++---- 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 8b4f83657c261..30c34af22c2a0 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -736,22 +736,24 @@ impl Default for Exposure Exposure { - fn in_chunks_of(&self, page_size: usize) -> Vec { + fn as_pages(&self, page_size: usize) -> Vec> { let individual_chunks = self.others.chunks(page_size); - let mut paged_exposure: Vec = Vec::with_capacity(individual_chunks.len()); + let mut paged_exposure: Vec> = + Vec::with_capacity(individual_chunks.len()); // own balance that has not been accounted for in the paged exposure let mut own_left = self.own; for chunk in individual_chunks { let own = own_left; - let mut total = own; + let mut page_total = own; for individual in chunk.iter() { - total = total.saturating_add(individual.value); + page_total = page_total.saturating_add(individual.value); } - paged_exposure.push(Exposure { - total, + paged_exposure.push(ExposurePage { + total: self.total, + page_total, own, others: chunk .iter() @@ -767,6 +769,40 @@ impl } } +/// A snapshot of the stake backing a single validator in the system. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ExposurePage { + /// The total balance backing this validator. + #[codec(compact)] + pub total: Balance, + /// The total balance of this chunk/page. + #[codec(compact)] + pub page_total: Balance, + /// The validator's own stash that is exposed. + #[codec(compact)] + pub own: Balance, + /// The portions of nominators stashes that are exposed. + pub others: Vec>, +} + +impl Default for ExposurePage { + fn default() -> Self { + Self { total: Default::default(), page_total: Default::default(), own: Default::default(), others: vec![] } + } +} + +impl + From> for ExposurePage +{ + fn from(exposure: Exposure) -> Self { + Self { + total: exposure.total, + page_total: exposure.total, + own: exposure.own, + others: exposure.others, + } + } +} /// A pending slash record. The value of the slash has been computed but not applied yet, /// rather deferred for several eras. #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 42f77e17c68ba..1d94e0de45d80 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -293,7 +293,7 @@ impl crate::pallet::pallet::Config for Test { type EraPayout = ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = ConstU32<64>; - type ExposurePageSize = ConstU32<10>; + type ExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index d8e4cc429ffc0..95b5aa2d2710e 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -184,7 +184,7 @@ impl Pallet { // which goes to them and each of their nominators. let exposure = EraInfo::::get_validator_exposure(era, &ledger.stash, page); - + println!("exposure: {:?}", exposure); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; let validator_reward_points = era_reward_points diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 20312f5a34719..eca1d0dbd5dbd 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -44,7 +44,7 @@ pub use impls::*; use crate::{ slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout, - EraRewardPoints, Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, + EraRewardPoints, Exposure, ExposurePage, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, }; @@ -457,7 +457,7 @@ pub mod pallet { NMapKey, NMapKey, ), - Exposure>, + ExposurePage>, OptionQuery, >; @@ -626,11 +626,11 @@ pub mod pallet { era: EraIndex, validator: &T::AccountId, page: PageIndex, - ) -> Exposure> { + ) -> ExposurePage> { return match >::get((era, validator, page)) { Some(paged_exposure) => paged_exposure, // only return clipped exposure if page zero and no paged exposure entry - None if page == 0 => >::get(&era, validator), + None if page == 0 => >::get(&era, validator).into(), _ => Default::default(), } } @@ -653,7 +653,7 @@ pub mod pallet { >::insert(era, &validator, &exposure); exposure - .in_chunks_of(T::ExposurePageSize::get() as usize) + .as_pages(T::ExposurePageSize::get() as usize) .iter() .enumerate() .for_each(|(page, paged_exposure)| { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index a9626e453a304..3b9f45c94126e 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -441,7 +441,7 @@ fn staking_should_work() { total: 1500, active: 1500, unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![0], + legacy_claimed_rewards: bounded_vec![], }) ); // e.g. it cannot reserve more than 500 that it has free from the total 2000 @@ -2194,6 +2194,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { let _ = Balances::make_free_balance_be(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; + let exposure_page: ExposurePage = exposure.clone().into(); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -2202,7 +2203,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { // Check reward ErasRewardPoints::::insert(0, reward); ErasStakers::::insert(0, 11, &exposure); - ErasStakersClipped::::insert(0, 11, exposure); + ErasStakersPaged::::insert((0, 11, 0,), exposure_page); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); @@ -3764,6 +3765,7 @@ fn test_payout_stakers() { let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + // FIXME(ank4n): this won't work since the exposure page is not sorted anymore. assert_eq_error_rate!( Balances::total_issuance(), pre_payout_total_issuance + actual_paid_out, @@ -5679,16 +5681,19 @@ fn can_page_exposure() { Exposure { total: total_stake, own: own_stake, others }; // when - let paged_exposures: Vec> = exposure.clone().in_chunks_of(3); + let paged_exposures: Vec> = exposure.clone().as_pages(3); // then + // 7 pages of nominators. assert_eq!(paged_exposures.len(), (19 / 3) + 1); // first page stake = 500 (own) + 100 + 200 + 300 - assert!(matches!(paged_exposures[0], Exposure { total: 1100, own: 500, .. })); + assert!(matches!(paged_exposures[0], ExposurePage { total: 19_500, page_total: 1100, own: 500, .. })); // second page stake = 0 + 400 + 500 + 600 - assert!(matches!(paged_exposures[1], Exposure { total: 1500, own: 0, .. })); + assert!(matches!(paged_exposures[1], ExposurePage { total: 19_500, page_total: 1500, own: 0, .. })); + // verify total is always the total stake backing a validator for all the pages. + assert_eq!(paged_exposures.iter().filter(|a| a.total == 19_500).count(), 7); // verify total stake is same as in the original exposure. - assert_eq!(paged_exposures.iter().map(|a| a.total).reduce(|a, b| a + b).unwrap(), 19_500); + assert_eq!(paged_exposures.iter().map(|a| a.page_total).reduce(|a, b| a + b).unwrap(), 19_500); // verify own stake is same as in the original exposure. assert_eq!(paged_exposures.iter().map(|a| a.own).reduce(|a, b| a + b).unwrap(), 500); // verify number of nominators are same as in the original exposure. From 1271d93265ab9f01a8459649bda3d45259810976 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 15 Jan 2023 02:55:57 +0100 Subject: [PATCH 023/131] fmt --- frame/staking/src/lib.rs | 7 ++++++- frame/staking/src/pallet/impls.rs | 1 - frame/staking/src/pallet/mod.rs | 6 +++--- frame/staking/src/tests.rs | 12 +++++++++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 30c34af22c2a0..723c0ecbf2c24 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -787,7 +787,12 @@ pub struct ExposurePage { impl Default for ExposurePage { fn default() -> Self { - Self { total: Default::default(), page_total: Default::default(), own: Default::default(), others: vec![] } + Self { + total: Default::default(), + page_total: Default::default(), + own: Default::default(), + others: vec![], + } } } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 95b5aa2d2710e..bd6e27b2c08d8 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -184,7 +184,6 @@ impl Pallet { // which goes to them and each of their nominators. let exposure = EraInfo::::get_validator_exposure(era, &ledger.stash, page); - println!("exposure: {:?}", exposure); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; let validator_reward_points = era_reward_points diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index eca1d0dbd5dbd..b583bbfccc528 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -44,9 +44,9 @@ pub use impls::*; use crate::{ slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout, - EraRewardPoints, Exposure, ExposurePage, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, - RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, - ValidatorPrefs, + EraRewardPoints, Exposure, ExposurePage, Forcing, NegativeImbalanceOf, Nominations, + PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, + UnlockChunk, ValidatorPrefs, }; const STAKING_ID: LockIdentifier = *b"staking "; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 3b9f45c94126e..ae894359dfe8e 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2203,7 +2203,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { // Check reward ErasRewardPoints::::insert(0, reward); ErasStakers::::insert(0, 11, &exposure); - ErasStakersPaged::::insert((0, 11, 0,), exposure_page); + ErasStakersPaged::::insert((0, 11, 0), exposure_page); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); @@ -5687,9 +5687,15 @@ fn can_page_exposure() { // 7 pages of nominators. assert_eq!(paged_exposures.len(), (19 / 3) + 1); // first page stake = 500 (own) + 100 + 200 + 300 - assert!(matches!(paged_exposures[0], ExposurePage { total: 19_500, page_total: 1100, own: 500, .. })); + assert!(matches!( + paged_exposures[0], + ExposurePage { total: 19_500, page_total: 1100, own: 500, .. } + )); // second page stake = 0 + 400 + 500 + 600 - assert!(matches!(paged_exposures[1], ExposurePage { total: 19_500, page_total: 1500, own: 0, .. })); + assert!(matches!( + paged_exposures[1], + ExposurePage { total: 19_500, page_total: 1500, own: 0, .. } + )); // verify total is always the total stake backing a validator for all the pages. assert_eq!(paged_exposures.iter().filter(|a| a.total == 19_500).count(), 7); // verify total stake is same as in the original exposure. From 1a317f0cf6831a49c0938532a53d4ea7a54b83e2 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 15 Jan 2023 15:15:53 +0100 Subject: [PATCH 024/131] some docs --- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 28 ++++++++++++++++++++-------- frame/staking/src/tests.rs | 3 ++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index bd6e27b2c08d8..3314a163f66da 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -167,7 +167,7 @@ impl Pallet { .retain(|&x| x >= current_era.saturating_sub(history_depth)); >::insert(&controller, &ledger); - if EraInfo::::temp_is_rewards_claimed(era, &ledger, &ledger.stash, page) { + if EraInfo::::is_rewards_claimed_temp(era, &ledger, &ledger.stash, page) { return Err(Error::::AlreadyClaimed .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))) } else { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index b583bbfccc528..76fdf52dc4e62 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -601,14 +601,18 @@ pub mod pallet { #[pallet::getter(fn current_planned_session)] pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; - /// Wrapper struct for `ErasStakers`, `ClaimedRewards`, `ErasStakersClipped`, - /// `ErasStakersPaged`, `ErasTotalStake`. + /// Wrapper struct for Era related information. It is not a pure encapsulation as these storage + /// items can be accessed directly but nevertheless recommended to use `EraInfo` for accesing + /// the following: (1) `ErasStakers`, (2) `ClaimedRewards`, (3) `ErasStakersClipped`, + /// (4) `ErasStakersPaged`, (5) `ErasTotalStake`. + // TODO(ank4n): docs, tests and add more methods to `EraInfo` for the supported storage items. pub(crate) struct EraInfo(sp_std::marker::PhantomData); impl EraInfo { - // TODO(ank4n): doc and clean up in 84 eras - // looks at `T::StakingLedger` for older non paged rewards, and `T::ClaimedRewards` for - // newer paged rewards. - pub(crate) fn temp_is_rewards_claimed( + /// Temporary function which looks at both (1) `T::StakingLedger` for legacy non-paged + /// rewards, and (2) `T::ClaimedRewards` for paged rewards. This can be removed once + /// `$HistoryDepth` eras have passed and none of the older non-paged rewards are claimable. + // TODO: Cleanup tracking issue: #13034 + pub(crate) fn is_rewards_claimed_temp( era: EraIndex, ledger: &StakingLedger, validator: &T::AccountId, @@ -618,6 +622,10 @@ pub mod pallet { Self::is_rewards_claimed(era, validator, page) } + /// 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_temp` can be removed and this function can be made public. fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: PageIndex) -> bool { ClaimedRewards::::get(era, validator).iter().find(|&&p| page == p).is_some() } @@ -1563,7 +1571,7 @@ pub mod pallet { Ok(()) } - /// Pay out all the stakers behind a single validator for a single era. + /// Pay out all the stakers behind a single validator for a single era and page. /// /// - `validator_stash` is the stash account of the validator. Their nominators, up to /// `T::MaxNominatorRewardedPerValidator`, will also receive their rewards. @@ -1572,8 +1580,12 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// + /// The list of nominators is paged, each page being capped at `T::ExposurePageSize`. For + /// rewarding all the nominators, the call needs to be called for each page. If rewards are + /// not claimed in `${HistoryDepth}` eras, they are lost. + /// /// # - /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). + /// - Time complexity: at most O(ExposurePageSize). /// - Contains a limited number of reads and writes. /// ----------- /// N is the Number of payouts for the validator (including the validator) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index ae894359dfe8e..aa162df453db0 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3765,7 +3765,8 @@ fn test_payout_stakers() { let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); - // FIXME(ank4n): this won't work since the exposure page is not sorted anymore. + // FIXME(ank4n): this won't work since the exposure page is not sorted anymore. Instead fix + // it with multi block reward payout expectation. assert_eq_error_rate!( Balances::total_issuance(), pre_payout_total_issuance + actual_paid_out, From f7f654c07b36f920d2e1bb5624d5cb026c54c9ca Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 16 Jan 2023 16:39:43 +0100 Subject: [PATCH 025/131] rename to into_pages --- frame/staking/src/lib.rs | 2 +- frame/staking/src/pallet/impls.rs | 2 ++ frame/staking/src/pallet/mod.rs | 2 +- frame/staking/src/tests.rs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 723c0ecbf2c24..0aaa55a420a76 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -736,7 +736,7 @@ impl Default for Exposure Exposure { - fn as_pages(&self, page_size: usize) -> Vec> { + fn into_pages(&self, page_size: usize) -> Vec> { let individual_chunks = self.others.chunks(page_size); let mut paged_exposure: Vec> = Vec::with_capacity(individual_chunks.len()); diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 3314a163f66da..892e31ba62acd 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -662,6 +662,8 @@ impl Pallet { >::remove_prefix(era_index, None); #[allow(deprecated)] >::remove_prefix(era_index, None); + #[allow(deprecated)] + >::remove_prefix(era_index, None); >::remove(era_index); >::remove(era_index); >::remove(era_index); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 76fdf52dc4e62..00fe203bebc16 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -661,7 +661,7 @@ pub mod pallet { >::insert(era, &validator, &exposure); exposure - .as_pages(T::ExposurePageSize::get() as usize) + .into_pages(T::ExposurePageSize::get() as usize) .iter() .enumerate() .for_each(|(page, paged_exposure)| { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index aa162df453db0..28739b3e30211 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -5682,7 +5682,7 @@ fn can_page_exposure() { Exposure { total: total_stake, own: own_stake, others }; // when - let paged_exposures: Vec> = exposure.clone().as_pages(3); + let paged_exposures: Vec> = exposure.clone().into_pages(3); // then // 7 pages of nominators. From 0aef2795df38fe05b95e073641fb2dc4b6b152b9 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 16 Jan 2023 17:29:59 +0100 Subject: [PATCH 026/131] verify claimed rewards and era stakers is cleared --- frame/staking/src/pallet/impls.rs | 3 +++ frame/staking/src/pallet/mod.rs | 18 +++++++-------- frame/staking/src/tests.rs | 37 ++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 892e31ba62acd..38caae862220e 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -664,6 +664,9 @@ impl Pallet { >::remove_prefix(era_index, None); #[allow(deprecated)] >::remove_prefix(era_index, None); + #[allow(deprecated)] + >::remove_prefix(era_index, None); + >::remove(era_index); >::remove(era_index); >::remove(era_index); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 00fe203bebc16..0578014bf248f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -450,18 +450,17 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn eras_stakers_paged)] #[pallet::unbounded] - pub type ErasStakersPaged = StorageNMap< + pub type ErasStakersPaged = StorageDoubleMap< _, - ( - NMapKey, - NMapKey, - NMapKey, - ), + Twox64Concat, + EraIndex, + Twox64Concat, + (T::AccountId, PageIndex), ExposurePage>, OptionQuery, >; - /// History of rewards claimed by validator by era and page. + /// History of claimed paged rewards by era and validator. /// /// This is keyed by era and validator stash which maps to the set of page indexes which have /// been claimed. @@ -475,7 +474,6 @@ pub mod pallet { Twox64Concat, EraIndex, Twox64Concat, - // Validator stash T::AccountId, Vec, ValueQuery, @@ -635,7 +633,7 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) -> ExposurePage> { - return match >::get((era, validator, page)) { + return match >::get(era, (validator, page)) { Some(paged_exposure) => paged_exposure, // only return clipped exposure if page zero and no paged exposure entry None if page == 0 => >::get(&era, validator).into(), @@ -665,7 +663,7 @@ pub mod pallet { .iter() .enumerate() .for_each(|(page, paged_exposure)| { - >::insert((era, &validator, page as u32), &paged_exposure); + >::insert(era, (&validator, page as u32), &paged_exposure); }); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 28739b3e30211..cf5d4b9722aa5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2203,7 +2203,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { // Check reward ErasRewardPoints::::insert(0, reward); ErasStakers::::insert(0, 11, &exposure); - ErasStakersPaged::::insert((0, 11, 0), exposure_page); + ErasStakersPaged::::insert(0, (11, 0), exposure_page); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); @@ -5707,6 +5707,41 @@ fn can_page_exposure() { assert_eq!(paged_exposures.iter().map(|a| a.others.len()).reduce(|a, b| a + b).unwrap(), 19); } +#[test] +fn should_retain_era_info_only_upto_history_depth() { + ExtBuilder::default().build_and_execute(|| { + // remove existing exposure + Pallet::::clear_era_information(0); + let validator_stash = 10; + + for era in 0..4 { + ClaimedRewards::::insert(era, &validator_stash, vec![0, 1, 2]); + for page in 0..3 { + ErasStakersPaged::::insert( + era, (&validator_stash, page), + ExposurePage { total: 100, page_total: 100, own: 100, others: vec![] }, + ); + } + } + + for i in 0..4 { + // Count of entries remaining in ClaimedRewards = total - cleared_count + assert_eq!(ClaimedRewards::::iter().count(), (4 - i)); + // 1 claimed_rewards entry for each era + assert_eq!(ClaimedRewards::::iter_prefix(i as EraIndex).count(), 1); + // 3 entries (pages) for each era + assert_eq!(ErasStakersPaged::::iter_prefix(i as EraIndex).count(), 3); + + // when clear era info + Pallet::::clear_era_information(i as EraIndex); + + // then all era entries are cleared + assert_eq!(ClaimedRewards::::iter_prefix(i as EraIndex).count(), 0); + assert_eq!(ErasStakersPaged::::iter_prefix(i as EraIndex).count(), 0); + } + }); +} + mod staking_interface { use frame_support::storage::with_storage_layer; use sp_staking::StakingInterface; From 08d7366eaebd2c545a7a26910f2c9c14d764e490 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 16 Jan 2023 17:32:49 +0100 Subject: [PATCH 027/131] small comment --- frame/staking/src/pallet/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 0578014bf248f..8de5d05dee61a 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -442,10 +442,10 @@ pub mod pallet { /// Paginated exposure of a validator at given era. /// - /// This is keyed first by the era index to allow bulk deletion, then the stash account and - /// finally the page. + /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account + /// and page. /// - /// It is removed after `HISTORY_DEPTH` eras. + /// This uses DoubleMap instead of NMap to efficiently clear this after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. #[pallet::storage] #[pallet::getter(fn eras_stakers_paged)] From 53389c69a9595d26ec174913d5c086a323670ac2 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 16 Jan 2023 17:39:39 +0100 Subject: [PATCH 028/131] reuse MaxNominatorRewardedPerValidator --- frame/staking/src/mock.rs | 1 - frame/staking/src/pallet/mod.rs | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 1d94e0de45d80..7da1d01085769 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -293,7 +293,6 @@ impl crate::pallet::pallet::Config for Test { type EraPayout = ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = ConstU32<64>; - type ExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 8de5d05dee61a..51048a61a9602 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -205,12 +205,10 @@ pub mod pallet { /// /// For each validator only the `$MaxNominatorRewardedPerValidator` biggest stakers can /// claim their reward. This used to limit the i/o cost for the nominator payout. + // TODO(ank4n): Refactor into a better name to indicate that this is a per-page limit. #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; - #[pallet::constant] - type ExposurePageSize: Get; - /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. type OffendingValidatorsThreshold: Get; @@ -659,7 +657,7 @@ pub mod pallet { >::insert(era, &validator, &exposure); exposure - .into_pages(T::ExposurePageSize::get() as usize) + .into_pages(T::MaxNominatorRewardedPerValidator::get() as usize) .iter() .enumerate() .for_each(|(page, paged_exposure)| { @@ -1578,12 +1576,12 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// The list of nominators is paged, each page being capped at `T::ExposurePageSize`. For + /// The list of nominators is paged, each page being capped at `T::MaxNominatorRewardedPerValidator`. For /// rewarding all the nominators, the call needs to be called for each page. If rewards are /// not claimed in `${HistoryDepth}` eras, they are lost. /// /// # - /// - Time complexity: at most O(ExposurePageSize). + /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). /// - Contains a limited number of reads and writes. /// ----------- /// N is the Number of payouts for the validator (including the validator) From 97744d79993bd9b3e252bcdf46ace9987be0ed96 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 19 Jan 2023 00:18:25 +0100 Subject: [PATCH 029/131] get to the same stage as 1st attempt --- frame/staking/src/lib.rs | 76 ++++++++++++++++++--------------- frame/staking/src/mock.rs | 3 +- frame/staking/src/pallet/mod.rs | 47 ++++++++++++++------ frame/staking/src/tests.rs | 53 ++++++++++++----------- 4 files changed, 105 insertions(+), 74 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 0aaa55a420a76..40da1b800210e 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -313,7 +313,7 @@ use sp_runtime::{ }; use sp_staking::{ offence::{Offence, OffenceError, ReportOffence}, - EraIndex, SessionIndex, + EraIndex, PageIndex, SessionIndex, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; pub use weights::WeightInfo; @@ -736,63 +736,54 @@ impl Default for Exposure Exposure { - fn into_pages(&self, page_size: usize) -> Vec> { - let individual_chunks = self.others.chunks(page_size); - let mut paged_exposure: Vec> = + fn as_pages( + &self, + page_size: u32, + ) -> (ExposureOverview, Vec>) { + let individual_chunks = self.others.chunks(page_size as usize); + let mut exposure_pages: Vec> = Vec::with_capacity(individual_chunks.len()); - // own balance that has not been accounted for in the paged exposure - let mut own_left = self.own; - for chunk in individual_chunks { - let own = own_left; - let mut page_total = own; + let mut page_total: Balance = Zero::zero(); for individual in chunk.iter() { page_total = page_total.saturating_add(individual.value); } - paged_exposure.push(ExposurePage { - total: self.total, + exposure_pages.push(ExposurePage { page_total, - own, others: chunk .iter() .map(|c| IndividualExposure { who: c.who.clone(), value: c.value }) .collect(), }); - - // subtract own that has been accounted - own_left = own_left.saturating_sub(own); } - paged_exposure + ( + ExposureOverview { + total: self.total, + own: self.own, + nominator_count: self.others.len() as u32, + page_count: exposure_pages.len() as PageIndex, + }, + exposure_pages, + ) } } /// A snapshot of the stake backing a single validator in the system. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct ExposurePage { - /// The total balance backing this validator. - #[codec(compact)] - pub total: Balance, /// The total balance of this chunk/page. #[codec(compact)] pub page_total: Balance, - /// The validator's own stash that is exposed. - #[codec(compact)] - pub own: Balance, /// The portions of nominators stashes that are exposed. pub others: Vec>, } impl Default for ExposurePage { fn default() -> Self { - Self { - total: Default::default(), - page_total: Default::default(), - own: Default::default(), - others: vec![], - } + Self { page_total: Default::default(), others: vec![] } } } @@ -800,14 +791,31 @@ impl From> for ExposurePage { fn from(exposure: Exposure) -> Self { - Self { - total: exposure.total, - page_total: exposure.total, - own: exposure.own, - others: exposure.others, - } + Self { page_total: exposure.total, others: exposure.others } } } + +/// A snapshot of the stake backing a single validator in the system. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ExposureOverview { + /// The total balance backing this validator. + #[codec(compact)] + pub total: Balance, + /// The validator's own stash that is exposed. + #[codec(compact)] + pub own: Balance, + /// Number of nominators backing this validator. + pub nominator_count: u32, + /// Number of pages of backers. + pub page_count: PageIndex, +} + +impl Default for ExposureOverview { + fn default() -> Self { + Self { total: Default::default(), own: Default::default(), nominator_count: Default::default(), page_count: Default::default() } + } +} + /// A pending slash record. The value of the slash has been computed but not applied yet, /// rather deferred for several eras. #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 7da1d01085769..7a99a16ce3f25 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -230,6 +230,7 @@ parameter_types! { pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; pub static MaxNominations: u32 = 16; pub static HistoryDepth: u32 = 80; + pub static MaxNominatorRewardedPerValidator: u32 = 64; pub static MaxUnlockingChunks: u32 = 32; pub static RewardOnUnbalanceWasCalled: bool = false; pub static LedgerSlashPerEra: (BalanceOf, BTreeMap>) = (Zero::zero(), BTreeMap::new()); @@ -292,7 +293,7 @@ impl crate::pallet::pallet::Config for Test { type SessionInterface = Self; type EraPayout = ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 51048a61a9602..7136aa3eb273b 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -59,7 +59,7 @@ pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; pub mod pallet { use frame_election_provider_support::ElectionDataProvider; - use crate::BenchmarkingConfig; + use crate::{BenchmarkingConfig, ExposureOverview}; use super::*; @@ -414,6 +414,20 @@ pub mod pallet { ValueQuery, >; + // TODO(ank4n) + #[pallet::storage] + #[pallet::getter(fn eras_stakers_overview)] + #[pallet::unbounded] + pub type ErasStakersOverview = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + T::AccountId, + ExposureOverview>, + ValueQuery, + >; + /// Clipped Exposure of validator at era. /// /// This is similar to [`ErasStakers`] but number of nominators exposed is reduced to the @@ -630,11 +644,15 @@ pub mod pallet { era: EraIndex, validator: &T::AccountId, page: PageIndex, - ) -> ExposurePage> { + ) -> Exposure> { return match >::get(era, (validator, page)) { - Some(paged_exposure) => paged_exposure, // only return clipped exposure if page zero and no paged exposure entry - None if page == 0 => >::get(&era, validator).into(), + None if page == 0 => >::get(&era, validator), + Some(page) => { + // TODO(ank4n): more due diligence on the correctness of this. + let overview = >::get(&era, validator); + Exposure { total: overview.total, own: overview.own, others: page.others } + }, _ => Default::default(), } } @@ -656,13 +674,13 @@ pub mod pallet { ) { >::insert(era, &validator, &exposure); - exposure - .into_pages(T::MaxNominatorRewardedPerValidator::get() as usize) - .iter() - .enumerate() - .for_each(|(page, paged_exposure)| { - >::insert(era, (&validator, page as u32), &paged_exposure); - }); + let (exposure_overview, exposure_pages) = + exposure.as_pages(T::MaxNominatorRewardedPerValidator::get()); + + >::insert(era, &validator, &exposure_overview); + exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { + >::insert(era, (&validator, page as u32), &paged_exposure); + }); } pub(crate) fn set_total_stake(era: EraIndex, total_stake: BalanceOf) { @@ -1576,9 +1594,10 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// The list of nominators is paged, each page being capped at `T::MaxNominatorRewardedPerValidator`. For - /// rewarding all the nominators, the call needs to be called for each page. If rewards are - /// not claimed in `${HistoryDepth}` eras, they are lost. + /// The list of nominators is paged, each page being capped at + /// `T::MaxNominatorRewardedPerValidator`. For rewarding all the nominators, the call needs + /// to be called for each page. If rewards are not claimed in `${HistoryDepth}` eras, they + /// are lost. /// /// # /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index cf5d4b9722aa5..fa558fb3e4891 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2194,7 +2194,8 @@ fn reward_validator_slashing_validator_does_not_overflow() { let _ = Balances::make_free_balance_be(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; - let exposure_page: ExposurePage = exposure.clone().into(); + let (exposure_overview, _) = + exposure.clone().as_pages(MaxNominatorRewardedPerValidator::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -2203,7 +2204,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { // Check reward ErasRewardPoints::::insert(0, reward); ErasStakers::::insert(0, 11, &exposure); - ErasStakersPaged::::insert(0, (11, 0), exposure_page); + ErasStakersOverview::::insert(0, 11, exposure_overview); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); @@ -3693,7 +3694,7 @@ fn six_session_delay() { #[test] fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward() { ExtBuilder::default().build_and_execute(|| { - for i in 0..=<::MaxNominatorRewardedPerValidator as Get<_>>::get() { + for i in 0..=MaxNominatorRewardedPerValidator::get() { let stash = 10_000 + i as AccountId; let controller = 20_000 + i as AccountId; let balance = 10_000 + i as Balance; @@ -3716,7 +3717,7 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( mock::make_all_reward_payment(1); // Assert only nominators from 1 to Max are rewarded - for i in 0..=<::MaxNominatorRewardedPerValidator as Get<_>>::get() { + for i in 0..=MaxNominatorRewardedPerValidator::get() { let stash = 10_000 + i as AccountId; let balance = 10_000 + i as Balance; if stash == 10_000 { @@ -3987,8 +3988,7 @@ fn payout_stakers_handles_weight_refund() { // Note: this test relies on the assumption that `payout_stakers_alive_staked` is solely used by // `payout_stakers` to calculate the weight of each payout op. ExtBuilder::default().has_stakers(false).build_and_execute(|| { - let max_nom_rewarded = - <::MaxNominatorRewardedPerValidator as Get<_>>::get(); + let max_nom_rewarded = MaxNominatorRewardedPerValidator::get(); // Make sure the configured value is meaningful for our use. assert!(max_nom_rewarded >= 4); let half_max_nom_rewarded = max_nom_rewarded / 2; @@ -5682,29 +5682,31 @@ fn can_page_exposure() { Exposure { total: total_stake, own: own_stake, others }; // when - let paged_exposures: Vec> = exposure.clone().into_pages(3); + let (exposure_overview, exposure_page): ( + ExposureOverview, + Vec>, + ) = exposure.clone().as_pages(3); // then // 7 pages of nominators. - assert_eq!(paged_exposures.len(), (19 / 3) + 1); - // first page stake = 500 (own) + 100 + 200 + 300 - assert!(matches!( - paged_exposures[0], - ExposurePage { total: 19_500, page_total: 1100, own: 500, .. } - )); + assert_eq!(exposure_page.len(), 7); + assert_eq!(exposure_overview.page_count, 7); + // first page stake = 100 + 200 + 300 + assert!(matches!(exposure_page[0], ExposurePage { page_total: 600, .. })); // second page stake = 0 + 400 + 500 + 600 - assert!(matches!( - paged_exposures[1], - ExposurePage { total: 19_500, page_total: 1500, own: 0, .. } - )); - // verify total is always the total stake backing a validator for all the pages. - assert_eq!(paged_exposures.iter().filter(|a| a.total == 19_500).count(), 7); + assert!(matches!(exposure_page[1], ExposurePage { page_total: 1500, .. })); + // verify overview has the total + assert_eq!(exposure_overview.total, 19_500); // verify total stake is same as in the original exposure. - assert_eq!(paged_exposures.iter().map(|a| a.page_total).reduce(|a, b| a + b).unwrap(), 19_500); - // verify own stake is same as in the original exposure. - assert_eq!(paged_exposures.iter().map(|a| a.own).reduce(|a, b| a + b).unwrap(), 500); + assert_eq!( + exposure_page.iter().map(|a| a.page_total).reduce(|a, b| a + b).unwrap(), + 19_500 - exposure_overview.own + ); + // verify own stake is correct + assert_eq!(exposure_overview.own, 500); // verify number of nominators are same as in the original exposure. - assert_eq!(paged_exposures.iter().map(|a| a.others.len()).reduce(|a, b| a + b).unwrap(), 19); + assert_eq!(exposure_page.iter().map(|a| a.others.len()).reduce(|a, b| a + b).unwrap(), 19); + assert_eq!(exposure_overview.nominator_count, 19); } #[test] @@ -5718,8 +5720,9 @@ fn should_retain_era_info_only_upto_history_depth() { ClaimedRewards::::insert(era, &validator_stash, vec![0, 1, 2]); for page in 0..3 { ErasStakersPaged::::insert( - era, (&validator_stash, page), - ExposurePage { total: 100, page_total: 100, own: 100, others: vec![] }, + era, + (&validator_stash, page), + ExposurePage { page_total: 100, others: vec![] }, ); } } From 57eb16fd903e641de317b8422033815023a77588 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 21 Jan 2023 20:29:52 +0100 Subject: [PATCH 030/131] pay all pages --- frame/staking/src/mock.rs | 5 ++++- frame/staking/src/pallet/mod.rs | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 7a99a16ce3f25..df7e7f3eae71f 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -759,7 +759,10 @@ pub(crate) fn make_all_reward_payment(era: EraIndex) { // reward validators for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) { let ledger = >::get(&validator_controller).unwrap(); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), ledger.stash, era, 0)); + for page in 0..EraInfo::::get_page_count(era, &ledger.stash) { + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), ledger.stash, era, page)); + } + } } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 7136aa3eb273b..811c1976e26d7 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -657,6 +657,10 @@ pub mod pallet { } } + // return atleast one page of exposure to be backward compatible to `EraStakersClipped` exposures. + pub(crate) fn get_page_count(era: EraIndex, validator: &T::AccountId) -> PageIndex { + >::get(&era, validator).page_count.max(1) + } pub(crate) fn set_rewards_as_claimed( era: EraIndex, validator: &T::AccountId, From 122ac2cba49eb4a5392387c324606e2f4e86fca4 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 21 Jan 2023 20:42:54 +0100 Subject: [PATCH 031/131] introduce invalid page error --- frame/staking/src/pallet/impls.rs | 2 ++ frame/staking/src/pallet/mod.rs | 17 +++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 38caae862220e..0fcb2ee34dbef 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -149,6 +149,8 @@ impl Pallet { .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) ); + ensure!(page < EraInfo::::get_page_count(era, &validator_stash), Error::::InvalidPage); + // Note: if era has no reward to be claimed, era may be future. better not to update // `ledger.legacy_claimed_rewards` in this case. let era_payout = >::get(&era).ok_or_else(|| { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 811c1976e26d7..6a80f9a8e497b 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -657,10 +657,14 @@ pub mod pallet { } } - // return atleast one page of exposure to be backward compatible to `EraStakersClipped` exposures. + /// Returns the number of pages of exposure a validator has for the given era. + /// + /// This will always return at minimum one count of exposure to be backward compatible to + /// non-paged reward payouts. pub(crate) fn get_page_count(era: EraIndex, validator: &T::AccountId) -> PageIndex { >::get(&era, validator).page_count.max(1) } + pub(crate) fn set_rewards_as_claimed( era: EraIndex, validator: &T::AccountId, @@ -885,6 +889,8 @@ pub mod pallet { NotSortedAndUnique, /// Rewards for this era have already been claimed for this validator. AlreadyClaimed, + /// No nominators exist on this page. + InvalidPage, /// Incorrect previous history depth input provided. IncorrectHistoryDepth, /// Incorrect number of slashing spans provided. @@ -1598,10 +1604,10 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// The list of nominators is paged, each page being capped at - /// `T::MaxNominatorRewardedPerValidator`. For rewarding all the nominators, the call needs - /// to be called for each page. If rewards are not claimed in `${HistoryDepth}` eras, they - /// are lost. + /// The list of nominators is paged, with each page being capped at + /// `T::MaxNominatorRewardedPerValidator`. If a validator has multiple pages of nominators, + /// the call needs to be made for each page such that all nominators receive the reward. If + /// rewards are not claimed in `${HistoryDepth}` eras, they are lost. /// /// # /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). @@ -1615,7 +1621,6 @@ pub mod pallet { /// NOTE: weights are assuming that payouts are made to alive stash account (Staked). /// Paying even a dead controller is cheaper weight-wise. We don't do any refunds here. /// # - // todo(ank4n): fix weights. #[pallet::call_index(18)] #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( T::MaxNominatorRewardedPerValidator::get() From 9d317b29f2449990618c3ac06c2a6e2a47c5de20 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 21 Jan 2023 20:59:18 +0100 Subject: [PATCH 032/131] docs --- frame/staking/src/mock.rs | 1 - frame/staking/src/pallet/mod.rs | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index df7e7f3eae71f..64dfe82aa51ee 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -748,7 +748,6 @@ pub(crate) fn add_slash(who: &AccountId) { } /// Make all validator and nominator request their payment -// TODO(ank4n) pay out all the paged nominators. pub(crate) fn make_all_reward_payment(era: EraIndex) { let validators_with_reward = ErasRewardPoints::::get(era) .individual diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 6a80f9a8e497b..fc5b84f13896f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -414,7 +414,17 @@ pub mod pallet { ValueQuery, >; - // TODO(ank4n) + /// Summary of validator exposure at a given era. + /// + /// This contains the total stake in support of the validator and their own stake. In addition, + /// it can also be used to get the number of nominators backing this validator and the number of + /// exposure pages they are divided into. The page count is useful to determine the number of + /// pages of rewards that needs to be claimed. + /// + /// This is keyed first by the era index to allow bulk deletion and then the stash account. + /// + /// Is it removed after `HISTORY_DEPTH` eras. + /// If stakers hasn't been set or has been removed then empty overview is returned. #[pallet::storage] #[pallet::getter(fn eras_stakers_overview)] #[pallet::unbounded] @@ -640,6 +650,10 @@ pub mod pallet { ClaimedRewards::::get(era, validator).iter().find(|&&p| page == p).is_some() } + /// Get exposure info for a validator at a given era and page. + /// + /// This builds a paged exposure from `ExposureOverview` and `ExposurePage` of the + /// validator. For older non-paged exposure, it returns the clipped exposure directly. pub(crate) fn get_validator_exposure( era: EraIndex, validator: &T::AccountId, @@ -665,6 +679,7 @@ pub mod pallet { >::get(&era, validator).page_count.max(1) } + /// Creates an entry to track validator reward has been claimed for a given era and page. pub(crate) fn set_rewards_as_claimed( era: EraIndex, validator: &T::AccountId, @@ -675,6 +690,7 @@ pub mod pallet { }) } + /// Store exposure for elected validators at start of an era. pub(crate) fn set_validator_exposure( era: EraIndex, validator: &T::AccountId, @@ -691,6 +707,7 @@ pub mod pallet { }); } + /// Store total exposure for all the elected validators in the era. pub(crate) fn set_total_stake(era: EraIndex, total_stake: BalanceOf) { >::insert(era, total_stake); } From 32fe2d0e9821ad908edc831db96220f89e43e0d5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 21 Jan 2023 21:33:03 +0100 Subject: [PATCH 033/131] test all nominators are paid --- frame/staking/src/pallet/mod.rs | 2 +- frame/staking/src/tests.rs | 31 ++++++++++++++++++++----------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index fc5b84f13896f..e2245491071a9 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -622,7 +622,7 @@ pub mod pallet { pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; /// Wrapper struct for Era related information. It is not a pure encapsulation as these storage - /// items can be accessed directly but nevertheless recommended to use `EraInfo` for accesing + /// items can be accessed directly but nevertheless recommended to use `EraInfo` for accessing /// the following: (1) `ErasStakers`, (2) `ClaimedRewards`, (3) `ErasStakersClipped`, /// (4) `ErasStakersPaged`, (5) `ErasTotalStake`. // TODO(ank4n): docs, tests and add more methods to `EraInfo` for the supported storage items. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index fa558fb3e4891..222e509485c66 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3692,9 +3692,12 @@ fn six_session_delay() { } #[test] -fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward() { +fn test_nominators_are_rewarded_for_all_exposure_page() { ExtBuilder::default().build_and_execute(|| { - for i in 0..=MaxNominatorRewardedPerValidator::get() { + // 3 pages of exposure + let nominator_count = 2 * MaxNominatorRewardedPerValidator::get() + 1; + + for i in 0..nominator_count { let stash = 10_000 + i as AccountId; let controller = 20_000 + i as AccountId; let balance = 10_000 + i as Balance; @@ -3716,15 +3719,21 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( mock::start_active_era(2); mock::make_all_reward_payment(1); - // Assert only nominators from 1 to Max are rewarded - for i in 0..=MaxNominatorRewardedPerValidator::get() { - let stash = 10_000 + i as AccountId; - let balance = 10_000 + i as Balance; - if stash == 10_000 { - assert!(Balances::free_balance(&stash) == balance); - } else { - assert!(Balances::free_balance(&stash) > balance); - } + assert_eq!(EraInfo::::get_page_count(1, &11), 3); + + // Assert all nominators are rewarded according to their stake + for i in 0..nominator_count { + // balance of the nominator after the reward payout. + let current_balance = Balances::free_balance(&((10000 + i) as AccountId)); + // balance of the nominator in the previous iteration. + let previous_balance = Balances::free_balance(&((10000 + i - 1) as AccountId)); + // balance before the reward. + let original_balance = 10_000 + i as Balance; + + assert!(current_balance > original_balance); + // since the stake of the nominator is increasing for each iteration, the final balance + // after the reward should also be higher than the previous iteration. + assert!(current_balance > previous_balance); } }); } From 30c46c8352f51bf8f1ff988389b65ac3a735cd6c Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 21 Jan 2023 23:34:17 +0100 Subject: [PATCH 034/131] all test pass --- frame/staking/src/pallet/mod.rs | 7 +- frame/staking/src/tests.rs | 160 +++++++++++++++++--------------- 2 files changed, 90 insertions(+), 77 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e2245491071a9..dfa181ac91251 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -662,10 +662,11 @@ pub mod pallet { return match >::get(era, (validator, page)) { // only return clipped exposure if page zero and no paged exposure entry None if page == 0 => >::get(&era, validator), - Some(page) => { - // TODO(ank4n): more due diligence on the correctness of this. + Some(exposure_page) => { let overview = >::get(&era, validator); - Exposure { total: overview.total, own: overview.own, others: page.others } + // own stake is included only once in the first page. + let own = if page == 0 { overview.own } else { Zero::zero() }; + Exposure { total: overview.total, own, others: exposure_page.others } }, _ => Default::default(), } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 222e509485c66..5461566a54516 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3739,7 +3739,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { } #[test] -fn test_payout_stakers() { +fn test_multi_page_payout_stakers() { // Test that payout_stakers work in general, including that only the top // `T::MaxNominatorRewardedPerValidator` nominators are rewarded. ExtBuilder::default().has_stakers(false).build_and_execute(|| { @@ -3757,45 +3757,65 @@ fn test_payout_stakers() { let bond_amount = balance + i as Balance; bond_nominator(1000 + i, 100 + i, bond_amount, vec![11]); total_exposure += bond_amount; - if i >= 36 { - payout_exposure += bond_amount; - }; + // with multi page reward payout, payout exposure is same as total exposure. + payout_exposure += bond_amount; } + let payout_exposure_part = Perbill::from_rational(payout_exposure, total_exposure); mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); + // Since `MaxNominatorRewardedPerValidator = 64`, there are two pages of validator exposure. + assert_eq!(EraInfo::::get_page_count(1, &11), 2); + // compute and ensure the reward amount is greater than zero. let payout = current_total_payout_for_duration(reward_time_per_era()); let actual_paid_out = payout_exposure_part * payout; - + println!("Actual paid out {:?}", actual_paid_out); mock::start_active_era(2); + // verify the exposures are calculated correctly. + let actual_exposure_0 = EraInfo::::get_validator_exposure(1, &11, 0); + assert_eq!(actual_exposure_0.total, total_exposure); + assert_eq!(actual_exposure_0.own, 1000); + assert_eq!(actual_exposure_0.others.len(), 64); + let actual_exposure_1 = EraInfo::::get_validator_exposure(1, &11, 1); + assert_eq!(actual_exposure_1.total, total_exposure); + // own stake is only included once in the first page + assert_eq!(actual_exposure_1.own, 0); + assert_eq!(actual_exposure_1.others.len(), 100 - 64); + let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); + + // Payout rewards for first exposure page assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); - // FIXME(ank4n): this won't work since the exposure page is not sorted anymore. Instead fix - // it with multi block reward payout expectation. + + // verify rewards have been paid out but still some left + assert!(Balances::total_issuance() > pre_payout_total_issuance); + assert!(Balances::total_issuance() < pre_payout_total_issuance + actual_paid_out); + + // Payout the second and last page of nominators + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 1)); + + // verify all rewards have been paid out assert_eq_error_rate!( Balances::total_issuance(), pre_payout_total_issuance + actual_paid_out, - 1 + 2 ); assert!(RewardOnUnbalanceWasCalled::get()); - // Top 64 nominators of validator 11 automatically paid out, including the validator + // verify all nominators of validator 11 are paid out, including the validator // Validator payout goes to controller. assert!(Balances::free_balance(&10) > balance); - for i in 36..100 { + for i in 0..100 { assert!(Balances::free_balance(&(100 + i)) > balance + i as Balance); } - // The bottom 36 do not - for i in 0..36 { - assert_eq!(Balances::free_balance(&(100 + i)), balance + i as Balance); - } - // We track rewards in `legacy_claimed_rewards` vec + // verify we no longer track rewards in `legacy_claimed_rewards` vec + let ledger = Staking::ledger(&10); assert_eq!( Staking::ledger(&10), Some(StakingLedger { @@ -3803,10 +3823,18 @@ fn test_payout_stakers() { total: 1000, active: 1000, unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![1] + legacy_claimed_rewards: bounded_vec![] }) ); + // verify rewards are tracked to prevent double claims + for page in 0..EraInfo::::get_page_count(1, &11) { + assert_eq!( + EraInfo::::is_rewards_claimed_temp(1, ledger.as_ref().unwrap(), &11, page), + true + ); + } + for i in 3..16 { Staking::reward_by_ids(vec![(11, 1)]); @@ -3817,31 +3845,34 @@ fn test_payout_stakers() { mock::start_active_era(i); RewardOnUnbalanceWasCalled::set(false); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, i - 1, 0)); + mock::make_all_reward_payment(i - 1); assert_eq_error_rate!( Balances::total_issuance(), pre_payout_total_issuance + actual_paid_out, - 1 + 2 ); assert!(RewardOnUnbalanceWasCalled::get()); + + // verify we track rewards for each era and page + for page in 0..EraInfo::::get_page_count(i - 1, &11) { + assert_eq!( + EraInfo::::is_rewards_claimed_temp( + i - 1, + Staking::ledger(&10).as_ref().unwrap(), + &11, + page + ), + true + ); + } } - // We track rewards in `claimed_rewards` vec - assert_eq!( - Staking::ledger(&10), - Some(StakingLedger { - stash: 11, - total: 1000, - active: 1000, - unlocking: Default::default(), - legacy_claimed_rewards: (1..=14).collect::>().try_into().unwrap() - }) - ); + assert_eq!(Staking::claimed_rewards(14, &11), vec![0, 1]); let last_era = 99; let history_depth = HistoryDepth::get(); - let expected_last_reward_era = last_era - 1; - let expected_start_reward_era = last_era - history_depth; + let last_reward_era = last_era - 1; + let first_claimable_reward_era = last_era - history_depth; for i in 16..=last_era { Staking::reward_by_ids(vec![(11, 1)]); // compute and ensure the reward amount is greater than zero. @@ -3849,53 +3880,34 @@ fn test_payout_stakers() { mock::start_active_era(i); } - // We clean it up as history passes - assert_ok!(Staking::payout_stakers( - RuntimeOrigin::signed(1337), - 11, - expected_start_reward_era, - 0 - )); - assert_ok!(Staking::payout_stakers( - RuntimeOrigin::signed(1337), - 11, - expected_last_reward_era, - 0 - )); - assert_eq!( - Staking::ledger(&10), - Some(StakingLedger { - stash: 11, - total: 1000, - active: 1000, - unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![ - expected_start_reward_era, - expected_last_reward_era - ] - }) - ); + // verify we clean up history as we go + for era in 0..15 { + assert_eq!(Staking::claimed_rewards(era, &11), Vec::::new()); + } + + // verify only page 0 is marked as claimed + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, first_claimable_reward_era, 0)); + assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0]); + + // verify page 0 and 1 are marked as claimed + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, first_claimable_reward_era, 1)); + assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0, 1]); + + // verify only page 0 is marked as claimed + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era, 0)); + assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0]); + + // verify page 0 and 1 are marked as claimed + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era, 1)); + assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0, 1]); // Out of order claims works. assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 69, 0)); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 23, 0)); + assert_eq!(Staking::claimed_rewards(69, &11), vec![0]); + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 23, 1)); + assert_eq!(Staking::claimed_rewards(23, &11), vec![1]); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 42, 0)); - assert_eq!( - Staking::ledger(&10), - Some(StakingLedger { - stash: 11, - total: 1000, - active: 1000, - unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![ - expected_start_reward_era, - 23, - 42, - 69, - expected_last_reward_era - ] - }) - ); + assert_eq!(Staking::claimed_rewards(42, &11), vec![0]); }); } From c2906d0a8bbe4a0b94e7e5105804b2a60fc1cb16 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 22 Jan 2023 00:45:47 +0100 Subject: [PATCH 035/131] cargo fmt --- frame/staking/src/lib.rs | 7 ++++++- frame/staking/src/mock.rs | 8 ++++++-- frame/staking/src/pallet/impls.rs | 5 ++++- frame/staking/src/pallet/mod.rs | 13 +++++++------ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 40da1b800210e..b7a97ea216a9b 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -812,7 +812,12 @@ pub struct ExposureOverview { impl Default for ExposureOverview { fn default() -> Self { - Self { total: Default::default(), own: Default::default(), nominator_count: Default::default(), page_count: Default::default() } + Self { + total: Default::default(), + own: Default::default(), + nominator_count: Default::default(), + page_count: Default::default(), + } } } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 64dfe82aa51ee..119fc71f2b4e5 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -759,9 +759,13 @@ pub(crate) fn make_all_reward_payment(era: EraIndex) { for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) { let ledger = >::get(&validator_controller).unwrap(); for page in 0..EraInfo::::get_page_count(era, &ledger.stash) { - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), ledger.stash, era, page)); + assert_ok!(Staking::payout_stakers( + RuntimeOrigin::signed(1337), + ledger.stash, + era, + page + )); } - } } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 0fcb2ee34dbef..c3222ef15621d 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -149,7 +149,10 @@ impl Pallet { .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) ); - ensure!(page < EraInfo::::get_page_count(era, &validator_stash), Error::::InvalidPage); + ensure!( + page < EraInfo::::get_page_count(era, &validator_stash), + Error::::InvalidPage + ); // Note: if era has no reward to be claimed, era may be future. better not to update // `ledger.legacy_claimed_rewards` in this case. diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index dfa181ac91251..711d05506b58a 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -622,15 +622,16 @@ pub mod pallet { pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; /// Wrapper struct for Era related information. It is not a pure encapsulation as these storage - /// items can be accessed directly but nevertheless recommended to use `EraInfo` for accessing - /// the following: (1) `ErasStakers`, (2) `ClaimedRewards`, (3) `ErasStakersClipped`, + /// items can be accessed directly but nevertheless, its recommended to use `EraInfo` for + /// accessing the following: (1) `ErasStakers`, (2) `ClaimedRewards`, (3) `ErasStakersClipped`, /// (4) `ErasStakersPaged`, (5) `ErasTotalStake`. - // TODO(ank4n): docs, tests and add more methods to `EraInfo` for the supported storage items. + // TODO(Ank4n): add all era related storage items in this struct pub(crate) struct EraInfo(sp_std::marker::PhantomData); impl EraInfo { - /// Temporary function which looks at both (1) `T::StakingLedger` for legacy non-paged - /// rewards, and (2) `T::ClaimedRewards` for paged rewards. This can be removed once - /// `$HistoryDepth` eras have passed and none of the older non-paged rewards are claimable. + /// 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 `$HistoryDepth` eras have passed and none of the older non-paged rewards + /// are relevant/claimable. // TODO: Cleanup tracking issue: #13034 pub(crate) fn is_rewards_claimed_temp( era: EraIndex, From 68302f2241026ee599e3985b407f79692efd5d40 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 22 Jan 2023 02:32:49 +0100 Subject: [PATCH 036/131] add more tests --- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/tests.rs | 199 +++++++++++++++++++++++++++++- 2 files changed, 198 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index c3222ef15621d..ee14eb1e94b15 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -151,7 +151,7 @@ impl Pallet { ensure!( page < EraInfo::::get_page_count(era, &validator_stash), - Error::::InvalidPage + Error::::InvalidPage.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) ); // Note: if era has no reward to be claimed, era may be future. better not to update diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 5461566a54516..8eb65094bc5e5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -25,6 +25,7 @@ use frame_support::{ pallet_prelude::*, traits::{Currency, Get, ReservableCurrency}, }; + use mock::*; use pallet_balances::Error as BalancesError; use sp_runtime::{ @@ -3886,11 +3887,21 @@ fn test_multi_page_payout_stakers() { } // verify only page 0 is marked as claimed - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, first_claimable_reward_era, 0)); + assert_ok!(Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + first_claimable_reward_era, + 0 + )); assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0]); // verify page 0 and 1 are marked as claimed - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, first_claimable_reward_era, 1)); + assert_ok!(Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + first_claimable_reward_era, + 1 + )); assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0, 1]); // verify only page 0 is marked as claimed @@ -5766,6 +5777,190 @@ fn should_retain_era_info_only_upto_history_depth() { }); } +#[test] +fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + // Create a validator: + bond_validator(11, 10, 1000); + + // reward validator for next 2 eras + mock::start_active_era(1); + Pallet::::reward_by_ids(vec![(11, 1)]); + mock::start_active_era(2); + Pallet::::reward_by_ids(vec![(11, 1)]); + mock::start_active_era(3); + + //verify rewards are not claimed + assert_eq!( + EraInfo::::is_rewards_claimed_temp( + 1, + Staking::ledger(10).as_ref().unwrap(), + &11, + 0 + ), + false + ); + assert_eq!( + EraInfo::::is_rewards_claimed_temp( + 2, + Staking::ledger(10).as_ref().unwrap(), + &11, + 0 + ), + false + ); + + // assume reward claim for era 1 was stored in legacy storage + Ledger::::insert( + 10, + StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: Default::default(), + legacy_claimed_rewards: bounded_vec![1], + }, + ); + + // verify rewards for era 1 cannot be claimed + assert_noop!( + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0), + Error::::AlreadyClaimed + .with_weight(::WeightInfo::payout_stakers_alive_staked(0)), + ); + assert_eq!( + EraInfo::::is_rewards_claimed_temp( + 1, + Staking::ledger(10).as_ref().unwrap(), + &11, + 0 + ), + true + ); + + // verify rewards for era 2 can be claimed + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0)); + assert_eq!( + EraInfo::::is_rewards_claimed_temp( + 2, + Staking::ledger(10).as_ref().unwrap(), + &11, + 0 + ), + true + ); + // but the new claimed rewards for era 2 is not stored in legacy storage + assert_eq!( + Ledger::::get(10).unwrap(), + StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: Default::default(), + legacy_claimed_rewards: bounded_vec![1], + }, + ); + // instead it is kept in `ClaimedRewards` + assert_eq!(ClaimedRewards::::get(2, 11), vec![0]); + }); +} + +#[test] +fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout() { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + // case 1: exposure exist in clipped. + // set page cap to 10 + MaxNominatorRewardedPerValidator::set(10); + bond_validator(11, 10, 1000); + let mut expected_individual_exposures: Vec> = vec![]; + let mut total_exposure: Balance = 0; + // 1st exposure page + for i in 0..10 { + let who = 1000 + i; + let value = 1000 + i as Balance; + bond_nominator(who, 100 + i, value, vec![11]); + expected_individual_exposures.push(IndividualExposure { who, value }); + total_exposure += value; + } + + for i in 10..15 { + let who = 1000 + i; + let value = 1000 + i as Balance; + bond_nominator(who, 100 + i, value, vec![11]); + expected_individual_exposures.push(IndividualExposure { who, value }); + total_exposure += value; + } + + mock::start_active_era(1); + // reward validator for current era + Pallet::::reward_by_ids(vec![(11, 1)]); + + // start new era + mock::start_active_era(2); + // verify exposure for era 1 is stored in paged storage, that each exposure is stored in + // one and only one page, and no exposure is repeated. + let actual_exposure_page_0 = ErasStakersPaged::::get(1, (11, 0)).unwrap(); + let actual_exposure_page_1 = ErasStakersPaged::::get(1, (11, 1)).unwrap(); + expected_individual_exposures.iter().for_each(|exposure| { + assert!( + actual_exposure_page_0.others.contains(exposure) || + actual_exposure_page_1.others.contains(exposure) + ); + }); + assert_eq!( + expected_individual_exposures.len(), + actual_exposure_page_0.others.len() + actual_exposure_page_1.others.len() + ); + // verify `EraInfo` returns page from paged storage + assert_eq!( + EraInfo::::get_validator_exposure(1, &11, 0).others, + actual_exposure_page_0.others + ); + assert_eq!( + EraInfo::::get_validator_exposure(1, &11, 1).others, + actual_exposure_page_1.others + ); + assert_eq!(EraInfo::::get_page_count(1, &11), 2); + + // case 2: exposure exist in clipped storage. + // delete paged storage and add exposure to clipped storage + >::remove(1, (11, 0)); + >::remove(1, (11, 1)); + >::remove(1, 11); + let mut clipped_exposure = expected_individual_exposures.clone(); + clipped_exposure.sort_by(|a, b| b.who.cmp(&a.who)); + clipped_exposure.truncate(10); + >::insert(1, 11, Exposure { + total: total_exposure, + own: 1000, + others: clipped_exposure.clone(), + }); + + // verify `EraInfo` returns exposure from clipped storage + assert!(matches!( + EraInfo::::get_validator_exposure(1, &11, 0), + Exposure { + own, + others, + .. + } if others == clipped_exposure && own == 1000)); + + // for pages other than 0, clipped storage returns empty exposure + assert_eq!( + EraInfo::::get_validator_exposure(1, &11, 1), + Default::default() + ); + // page size is 1 for clipped storage + assert_eq!(EraInfo::::get_page_count(1, &11), 1); + + // payout for page 0 works + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); + // payout for page 1 fails + assert_noop!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 1), + Error::::InvalidPage.with_weight(::WeightInfo::payout_stakers_alive_staked(0))); + }); +} + mod staking_interface { use frame_support::storage::with_storage_layer; use sp_staking::StakingInterface; From 12627ffceb0c9ba21417bef215de85bc2f58f895 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 22 Jan 2023 02:33:13 +0100 Subject: [PATCH 037/131] cargo fmt --- frame/staking/src/tests.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 8eb65094bc5e5..ed95ff169c9ca 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -5930,11 +5930,11 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( let mut clipped_exposure = expected_individual_exposures.clone(); clipped_exposure.sort_by(|a, b| b.who.cmp(&a.who)); clipped_exposure.truncate(10); - >::insert(1, 11, Exposure { - total: total_exposure, - own: 1000, - others: clipped_exposure.clone(), - }); + >::insert( + 1, + 11, + Exposure { total: total_exposure, own: 1000, others: clipped_exposure.clone() }, + ); // verify `EraInfo` returns exposure from clipped storage assert!(matches!( @@ -5946,18 +5946,18 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( } if others == clipped_exposure && own == 1000)); // for pages other than 0, clipped storage returns empty exposure - assert_eq!( - EraInfo::::get_validator_exposure(1, &11, 1), - Default::default() - ); + assert_eq!(EraInfo::::get_validator_exposure(1, &11, 1), Default::default()); // page size is 1 for clipped storage assert_eq!(EraInfo::::get_page_count(1, &11), 1); // payout for page 0 works assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); // payout for page 1 fails - assert_noop!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 1), - Error::::InvalidPage.with_weight(::WeightInfo::payout_stakers_alive_staked(0))); + assert_noop!( + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 1), + Error::::InvalidPage + .with_weight(::WeightInfo::payout_stakers_alive_staked(0)) + ); }); } From bbcd5f7b325a105ee6569ec5fe58998dd3e87a2c Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 12:43:01 +0100 Subject: [PATCH 038/131] fix benchmarks --- frame/staking/src/benchmarking.rs | 6 +++--- frame/staking/src/lib.rs | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 0366809f2d5a8..df42ad77ea7e2 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -565,7 +565,7 @@ benchmarks! { let balance = T::Currency::free_balance(controller); ensure!(balance.is_zero(), "Controller has balance, but should be dead."); } - }: payout_stakers(RawOrigin::Signed(caller), validator, current_era) + }: payout_stakers(RawOrigin::Signed(caller), validator, current_era, 0) verify { let balance_after = T::Currency::free_balance(&validator_controller); ensure!( @@ -598,7 +598,7 @@ benchmarks! { let balance = T::Currency::free_balance(stash); nominator_balances_before.push(balance); } - }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era) + }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era, 0) verify { let balance_after = T::Currency::free_balance(&validator); ensure!( @@ -754,7 +754,7 @@ benchmarks! { let caller: T::AccountId = whitelisted_caller(); let origin = RawOrigin::Signed(caller); let calls: Vec<_> = payout_calls_arg.iter().map(|arg| - Call::::payout_stakers { validator_stash: arg.0.clone(), era: arg.1 }.encode() + Call::::payout_stakers { validator_stash: arg.0.clone(), era: arg.1, page: 0 }.encode() ).collect(); }: { for call in calls { diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index b7a97ea216a9b..1410bdb29444a 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -318,7 +318,6 @@ use sp_staking::{ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; pub use weights::WeightInfo; -use frame_support::traits::ConstU32; pub use pallet::{pallet::*, *}; pub(crate) const LOG_TARGET: &str = "runtime::staking"; @@ -1044,6 +1043,6 @@ pub struct TestBenchmarkingConfig; #[cfg(feature = "std")] impl BenchmarkingConfig for TestBenchmarkingConfig { - type MaxValidators = ConstU32<100>; - type MaxNominators = ConstU32<100>; + type MaxValidators = frame_support::traits::ConstU32<100>; + type MaxNominators = frame_support::traits::ConstU32<100>; } From f766fee86eecd98079cc67aade9e464e6eae67bb Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 13:05:30 +0100 Subject: [PATCH 039/131] fix clippy suggestion --- frame/staking/src/pallet/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 711d05506b58a..0b451e2e1e63c 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -648,7 +648,7 @@ pub mod pallet { /// This is only used for paged rewards. Once older non-paged rewards are no longer /// relevant, `is_rewards_claimed_temp` can be removed and this function can be made public. fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: PageIndex) -> bool { - ClaimedRewards::::get(era, validator).iter().find(|&&p| page == p).is_some() + ClaimedRewards::::get(era, validator).iter().any(|&p| page == p) } /// Get exposure info for a validator at a given era and page. From 43cbe72105cb90c0f41a22c0c3776b262ddde237 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Mon, 23 Jan 2023 17:03:59 +0000 Subject: [PATCH 040/131] ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_staking --- frame/staking/src/weights.rs | 1934 ++++++++++++---------------------- 1 file changed, 690 insertions(+), 1244 deletions(-) diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 2c9e1b2669c8b..dc62a86201be6 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) Parity Technologies (UK) Ltd. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,25 +18,25 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2023-01-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate +// /home/benchbot/cargo_target_dir/production/substrate // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_staking // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/staking/src/weights.rs +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_staking +// --chain=dev // --header=./HEADER-APACHE2 +// --output=./frame/staking/src/weights.rs // --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -83,1404 +83,850 @@ pub trait WeightInfo { /// Weights for pallet_staking using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Proof Size summary in bytes: - // Measured: `1079` - // Estimated: `10386` - // Minimum execution time: 40_015 nanoseconds. - Weight::from_parts(40_601_000, 10386) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - } - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + // Minimum execution time: 51_611 nanoseconds. + Weight::from_ref_time(52_566_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) + } + // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) + // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Proof Size summary in bytes: - // Measured: `2252` - // Estimated: `22888` - // Minimum execution time: 74_781 nanoseconds. - Weight::from_parts(75_188_000, 22888) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + // Minimum execution time: 92_297 nanoseconds. + Weight::from_ref_time(93_016_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) + } + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking Nominators (r:1 w:0) + // Storage: Staking MinNominatorBond (r:1 w:0) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Proof Size summary in bytes: - // Measured: `2457` - // Estimated: `29534` - // Minimum execution time: 81_299 nanoseconds. - Weight::from_parts(82_242_000, 29534) - .saturating_add(T::DbWeight::get().reads(12_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + // Minimum execution time: 98_447 nanoseconds. + Weight::from_ref_time(99_317_000) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(8)) + } + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1085` - // Estimated: `10442` - // Minimum execution time: 31_479 nanoseconds. - Weight::from_parts(32_410_035, 10442) - // Standard Error: 313 - .saturating_add(Weight::from_ref_time(9_090).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:1) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Staking SpanSlash (r:0 w:100) - /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) + // Minimum execution time: 45_142 nanoseconds. + Weight::from_ref_time(46_003_517) + // Standard Error: 564 + .saturating_add(Weight::from_ref_time(60_400).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking SlashingSpans (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2486 + s * (4 ±0)` - // Estimated: `32303 + s * (4 ±0)` - // Minimum execution time: 71_968 nanoseconds. - Weight::from_parts(76_631_804, 32303) - // Standard Error: 1_613 - .saturating_add(Weight::from_ref_time(1_058_968).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(13_u64)) - .saturating_add(T::DbWeight::get().writes(12_u64)) + // Minimum execution time: 86_176 nanoseconds. + Weight::from_ref_time(91_591_693) + // Standard Error: 2_162 + .saturating_add(Weight::from_ref_time(1_089_160).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinValidatorBond (r:1 w:0) - /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking MinCommission (r:1 w:0) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:1) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking MaxValidatorsCount (r:1 w:0) - /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForValidators (r:1 w:1) - /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking MinValidatorBond (r:1 w:0) + // Storage: Staking MinCommission (r:1 w:0) + // Storage: Staking Validators (r:1 w:1) + // Storage: Staking MaxValidatorsCount (r:1 w:0) + // Storage: Staking Nominators (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListNodes (r:1 w:1) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Proof Size summary in bytes: - // Measured: `1446` - // Estimated: `19359` - // Minimum execution time: 51_963 nanoseconds. - Weight::from_parts(52_418_000, 19359) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Minimum execution time: 65_754 nanoseconds. + Weight::from_ref_time(66_793_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:128 w:128) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1292 + k * (601 ±0)` - // Estimated: `3566 + k * (3033 ±0)` - // Minimum execution time: 25_685 nanoseconds. - Weight::from_parts(25_290_286, 3566) - // Standard Error: 5_164 - .saturating_add(Weight::from_ref_time(6_445_608).saturating_mul(k.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 44_020 nanoseconds. + Weight::from_ref_time(41_692_773) + // Standard Error: 12_148 + .saturating_add(Weight::from_ref_time(7_092_259).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) - .saturating_add(Weight::from_proof_size(3033).saturating_mul(k.into())) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:17 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking MinNominatorBond (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking MaxNominatorsCount (r:1 w:0) + // Storage: Staking Validators (r:2 w:0) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1984 + n * (105 ±0)` - // Estimated: `21988 + n * (2520 ±0)` - // Minimum execution time: 59_542 nanoseconds. - Weight::from_parts(57_558_678, 21988) - // Standard Error: 10_364 - .saturating_add(Weight::from_ref_time(2_759_713).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(12_u64)) + // Minimum execution time: 72_131 nanoseconds. + Weight::from_ref_time(71_703_530) + // Standard Error: 6_947 + .saturating_add(Weight::from_ref_time(2_757_165).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(6_u64)) - .saturating_add(Weight::from_proof_size(2520).saturating_mul(n.into())) - } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + .saturating_add(T::DbWeight::get().writes(6)) + } + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Proof Size summary in bytes: - // Measured: `1876` - // Estimated: `17932` - // Minimum execution time: 52_132 nanoseconds. - Weight::from_parts(52_648_000, 17932) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + // Minimum execution time: 66_151 nanoseconds. + Weight::from_ref_time(66_596_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Proof Size summary in bytes: - // Measured: `840` - // Estimated: `3566` - // Minimum execution time: 13_399 nanoseconds. - Weight::from_parts(13_567_000, 3566) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 17_305 nanoseconds. + Weight::from_ref_time(17_506_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:2 w:2) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Proof Size summary in bytes: - // Measured: `939` - // Estimated: `9679` - // Minimum execution time: 20_425 nanoseconds. - Weight::from_parts(20_713_000, 9679) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Minimum execution time: 24_482 nanoseconds. + Weight::from_ref_time(25_101_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Staking ValidatorCount (r:0 w:1) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_069 nanoseconds. - Weight::from_ref_time(3_176_000) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 5_100 nanoseconds. + Weight::from_ref_time(5_274_000) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking ForceEra (r:0 w:1) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_386 nanoseconds. - Weight::from_ref_time(11_672_000) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 19_788 nanoseconds. + Weight::from_ref_time(20_313_000) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking ForceEra (r:0 w:1) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_591 nanoseconds. - Weight::from_ref_time(11_799_000) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 19_499 nanoseconds. + Weight::from_ref_time(19_987_000) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking ForceEra (r:0 w:1) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_553 nanoseconds. - Weight::from_ref_time(11_871_000) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 19_846 nanoseconds. + Weight::from_ref_time(20_127_000) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking Invulnerables (r:0 w:1) - /// Proof Skipped: Staking Invulnerables (max_values: Some(1), max_size: None, mode: Measured) + // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_292 nanoseconds. - Weight::from_ref_time(3_754_352) - // Standard Error: 40 - .saturating_add(Weight::from_ref_time(9_838).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:1) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:0 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Staking SpanSlash (r:0 w:100) - /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) + // Minimum execution time: 5_301 nanoseconds. + Weight::from_ref_time(6_147_935) + // Standard Error: 32 + .saturating_add(Weight::from_ref_time(10_076).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking SlashingSpans (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Ledger (r:0 w:1) + // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2178 + s * (4 ±0)` - // Estimated: `27930 + s * (4 ±0)` - // Minimum execution time: 65_307 nanoseconds. - Weight::from_parts(70_227_980, 27930) - // Standard Error: 2_113 - .saturating_add(Weight::from_ref_time(1_059_856).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(12_u64)) + // Minimum execution time: 79_381 nanoseconds. + Weight::from_ref_time(85_216_285) + // Standard Error: 2_681 + .saturating_add(Weight::from_ref_time(1_100_353).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - /// Storage: Staking UnappliedSlashes (r:1 w:1) - /// Proof Skipped: Staking UnappliedSlashes (max_values: None, max_size: None, mode: Measured) + // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `66671` - // Estimated: `69146` - // Minimum execution time: 89_123 nanoseconds. - Weight::from_parts(890_989_741, 69146) - // Standard Error: 58_282 - .saturating_add(Weight::from_ref_time(4_920_413).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasValidatorReward (r:1 w:0) - /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:257 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking ErasStakersClipped (r:1 w:0) - /// Proof Skipped: Staking ErasStakersClipped (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasRewardPoints (r:1 w:0) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasValidatorPrefs (r:1 w:0) - /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:257 w:0) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: System Account (r:257 w:257) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + // Minimum execution time: 92_049 nanoseconds. + Weight::from_ref_time(894_164_159) + // Standard Error: 58_104 + .saturating_add(Weight::from_ref_time(4_961_170).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking ErasStakersOverview (r:1 w:0) + // Storage: Staking ErasValidatorReward (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking ClaimedRewards (r:1 w:1) + // Storage: Staking ErasStakersPaged (r:1 w:0) + // Storage: Staking ErasStakersClipped (r:1 w:0) + // Storage: Staking ErasRewardPoints (r:1 w:0) + // Storage: Staking ErasValidatorPrefs (r:1 w:0) + // Storage: Staking Payee (r:1 w:0) + // Storage: System Account (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `20345 + n * (143 ±0)` - // Estimated: `54756 + n * (8024 ±1)` - // Minimum execution time: 73_652 nanoseconds. - Weight::from_parts(127_839_483, 54756) - // Standard Error: 14_195 - .saturating_add(Weight::from_ref_time(21_932_079).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Minimum execution time: 134_548 nanoseconds. + Weight::from_ref_time(195_909_318) + // Standard Error: 17_825 + .saturating_add(Weight::from_ref_time(22_179_182).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_proof_size(8024).saturating_mul(n.into())) } - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasValidatorReward (r:1 w:0) - /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:257 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:257 w:257) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking ErasStakersClipped (r:1 w:0) - /// Proof Skipped: Staking ErasStakersClipped (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasRewardPoints (r:1 w:0) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasValidatorPrefs (r:1 w:0) - /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:257 w:0) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: System Account (r:257 w:257) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:257 w:257) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking ErasStakersOverview (r:1 w:0) + // Storage: Staking ErasValidatorReward (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking ClaimedRewards (r:1 w:1) + // Storage: Staking ErasStakersPaged (r:1 w:0) + // Storage: Staking ErasStakersClipped (r:1 w:0) + // Storage: Staking ErasRewardPoints (r:1 w:0) + // Storage: Staking ErasValidatorPrefs (r:1 w:0) + // Storage: Staking Payee (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `35099 + n * (465 ±0)` - // Estimated: `83594 + n * (16026 ±0)` - // Minimum execution time: 94_560 nanoseconds. - Weight::from_parts(154_033_219, 83594) - // Standard Error: 26_663 - .saturating_add(Weight::from_ref_time(31_269_223).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(10_u64)) + // Minimum execution time: 167_574 nanoseconds. + Weight::from_ref_time(232_044_473) + // Standard Error: 25_865 + .saturating_add(Weight::from_ref_time(31_272_789).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_proof_size(16026).saturating_mul(n.into())) } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2253 + l * (7 ±0)` - // Estimated: `25491` - // Minimum execution time: 74_764 nanoseconds. - Weight::from_parts(75_814_067, 25491) - // Standard Error: 1_217 - .saturating_add(Weight::from_ref_time(64_725).saturating_mul(l.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:1) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Staking SpanSlash (r:0 w:100) - /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) + // Minimum execution time: 91_739 nanoseconds. + Weight::from_ref_time(93_123_333) + // Standard Error: 3_580 + .saturating_add(Weight::from_ref_time(69_425).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) + } + // Storage: System Account (r:1 w:1) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking SlashingSpans (r:1 w:1) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2486 + s * (4 ±0)` - // Estimated: `31810 + s * (4 ±0)` - // Minimum execution time: 77_611 nanoseconds. - Weight::from_parts(79_760_034, 31810) - // Standard Error: 1_597 - .saturating_add(Weight::from_ref_time(1_039_268).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(12_u64)) - .saturating_add(T::DbWeight::get().writes(12_u64)) + // Minimum execution time: 90_792 nanoseconds. + Weight::from_ref_time(93_893_087) + // Standard Error: 4_158 + .saturating_add(Weight::from_ref_time(1_084_858).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - /// Storage: VoterList CounterForListNodes (r:1 w:0) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:200 w:0) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:110 w:0) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:110 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:11 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:110 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:110 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CounterForValidators (r:1 w:0) - /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ValidatorCount (r:1 w:0) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinimumValidatorCount (r:1 w:0) - /// Proof: Staking MinimumValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:1) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasStakersClipped (r:0 w:10) - /// Proof Skipped: Staking ErasStakersClipped (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasValidatorPrefs (r:0 w:10) - /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Staking ErasStakers (r:0 w:10) - /// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasTotalStake (r:0 w:1) - /// Proof: Staking ErasTotalStake (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Staking ErasStartSessionIndex (r:0 w:1) - /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: Staking MinimumActiveStake (r:0 w:1) - /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + // Storage: VoterList CounterForListNodes (r:1 w:0) + // Storage: VoterList ListBags (r:200 w:0) + // Storage: VoterList ListNodes (r:101 w:0) + // Storage: Staking Nominators (r:101 w:0) + // Storage: Staking Validators (r:2 w:0) + // Storage: Staking Bonded (r:101 w:0) + // Storage: Staking Ledger (r:101 w:0) + // Storage: Staking CounterForValidators (r:1 w:0) + // Storage: Staking ValidatorCount (r:1 w:0) + // Storage: Staking MinimumValidatorCount (r:1 w:0) + // Storage: Staking CurrentEra (r:1 w:1) + // Storage: Staking ErasValidatorPrefs (r:0 w:1) + // Storage: Staking ErasStakersPaged (r:0 w:1) + // Storage: Staking ErasStakersOverview (r:0 w:1) + // Storage: Staking ErasStakers (r:0 w:1) + // Storage: Staking ErasTotalStake (r:0 w:1) + // Storage: Staking ErasStartSessionIndex (r:0 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + v * (3662 ±0) + n * (816 ±0)` - // Estimated: `528203 + v * (16743 ±0) + n * (12947 ±0)` - // Minimum execution time: 489_824 nanoseconds. - Weight::from_parts(491_687_000, 528203) - // Standard Error: 1_787_577 - .saturating_add(Weight::from_ref_time(58_719_498).saturating_mul(v.into())) - // Standard Error: 178_122 - .saturating_add(Weight::from_ref_time(13_273_555).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(206_u64)) + // Minimum execution time: 506_210 nanoseconds. + Weight::from_ref_time(508_476_000) + // Standard Error: 1_787_036 + .saturating_add(Weight::from_ref_time(60_417_557).saturating_mul(v.into())) + // Standard Error: 178_068 + .saturating_add(Weight::from_ref_time(13_499_037).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(206)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_proof_size(16743).saturating_mul(v.into())) - .saturating_add(Weight::from_proof_size(12947).saturating_mul(n.into())) - } - /// Storage: VoterList CounterForListNodes (r:1 w:0) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:200 w:0) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2000 w:0) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:2000 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1000 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:2000 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:2000 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinimumActiveStake (r:0 w:1) - /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(v.into()))) + } + // Storage: VoterList CounterForListNodes (r:1 w:0) + // Storage: VoterList ListBags (r:200 w:0) + // Storage: VoterList ListNodes (r:1500 w:0) + // Storage: Staking Nominators (r:1500 w:0) + // Storage: Staking Validators (r:500 w:0) + // Storage: Staking Bonded (r:1500 w:0) + // Storage: Staking Ledger (r:1500 w:0) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `3167 + v * (459 ±0) + n * (1007 ±0)` - // Estimated: `511899 + v * (14295 ±0) + n * (11775 ±0)` - // Minimum execution time: 23_373_467 nanoseconds. - Weight::from_parts(23_497_257_000, 511899) - // Standard Error: 299_205 - .saturating_add(Weight::from_ref_time(3_434_000).saturating_mul(v.into())) - // Standard Error: 299_205 - .saturating_add(Weight::from_ref_time(2_568_954).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(201_u64)) + // Minimum execution time: 24_070_794 nanoseconds. + Weight::from_ref_time(24_294_007_000) + // Standard Error: 322_618 + .saturating_add(Weight::from_ref_time(3_570_673).saturating_mul(v.into())) + // Standard Error: 322_618 + .saturating_add(Weight::from_ref_time(2_900_021).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(201)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_proof_size(14295).saturating_mul(v.into())) - .saturating_add(Weight::from_proof_size(11775).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking CounterForValidators (r:1 w:0) - /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1001 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + // Storage: Staking CounterForValidators (r:1 w:0) + // Storage: Staking Validators (r:501 w:0) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `983 + v * (50 ±0)` - // Estimated: `3019 + v * (2520 ±0)` - // Minimum execution time: 3_882_120 nanoseconds. - Weight::from_parts(3_951_993_000, 3019) - // Standard Error: 46_729 - .saturating_add(Weight::from_ref_time(2_856_043).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 4_776_351 nanoseconds. + Weight::from_ref_time(4_849_553_000) + // Standard Error: 55_132 + .saturating_add(Weight::from_ref_time(3_604_980).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_proof_size(2520).saturating_mul(v.into())) } - /// Storage: Staking MinCommission (r:0 w:1) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinValidatorBond (r:0 w:1) - /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking MaxValidatorsCount (r:0 w:1) - /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ChillThreshold (r:0 w:1) - /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:0 w:1) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:0 w:1) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + // Storage: Staking MinCommission (r:0 w:1) + // Storage: Staking MinValidatorBond (r:0 w:1) + // Storage: Staking MaxValidatorsCount (r:0 w:1) + // Storage: Staking ChillThreshold (r:0 w:1) + // Storage: Staking MaxNominatorsCount (r:0 w:1) + // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 8_427 nanoseconds. - Weight::from_ref_time(8_794_000) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } - /// Storage: Staking MinCommission (r:0 w:1) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinValidatorBond (r:0 w:1) - /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking MaxValidatorsCount (r:0 w:1) - /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ChillThreshold (r:0 w:1) - /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:0 w:1) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:0 w:1) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + // Minimum execution time: 10_781 nanoseconds. + Weight::from_ref_time(11_034_000) + .saturating_add(T::DbWeight::get().writes(6)) + } + // Storage: Staking MinCommission (r:0 w:1) + // Storage: Staking MinValidatorBond (r:0 w:1) + // Storage: Staking MaxValidatorsCount (r:0 w:1) + // Storage: Staking ChillThreshold (r:0 w:1) + // Storage: Staking MaxNominatorsCount (r:0 w:1) + // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 7_620 nanoseconds. - Weight::from_ref_time(7_901_000) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking ChillThreshold (r:1 w:0) - /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Minimum execution time: 9_418 nanoseconds. + Weight::from_ref_time(10_150_000) + .saturating_add(T::DbWeight::get().writes(6)) + } + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking ChillThreshold (r:1 w:0) + // Storage: Staking MaxNominatorsCount (r:1 w:0) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: Staking MinNominatorBond (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Proof Size summary in bytes: - // Measured: `2031` - // Estimated: `19438` - // Minimum execution time: 66_188 nanoseconds. - Weight::from_parts(66_767_000, 19438) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + // Minimum execution time: 82_590 nanoseconds. + Weight::from_ref_time(83_718_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Staking MinCommission (r:1 w:0) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:1) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + // Storage: Staking MinCommission (r:1 w:0) + // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Proof Size summary in bytes: - // Measured: `694` - // Estimated: `3019` - // Minimum execution time: 14_703 nanoseconds. - Weight::from_parts(15_031_000, 3019) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 19_367 nanoseconds. + Weight::from_ref_time(19_668_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Staking MinCommission (r:0 w:1) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking MinCommission (r:0 w:1) fn set_min_commission() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 4_518 nanoseconds. - Weight::from_ref_time(4_656_000) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 6_107 nanoseconds. + Weight::from_ref_time(6_449_000) + .saturating_add(T::DbWeight::get().writes(1)) } } // For backwards compatibility and tests impl WeightInfo for () { - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Proof Size summary in bytes: - // Measured: `1079` - // Estimated: `10386` - // Minimum execution time: 40_015 nanoseconds. - Weight::from_parts(40_601_000, 10386) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + // Minimum execution time: 51_611 nanoseconds. + Weight::from_ref_time(52_566_000) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) + // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Proof Size summary in bytes: - // Measured: `2252` - // Estimated: `22888` - // Minimum execution time: 74_781 nanoseconds. - Weight::from_parts(75_188_000, 22888) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + // Minimum execution time: 92_297 nanoseconds. + Weight::from_ref_time(93_016_000) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().writes(7)) + } + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking Nominators (r:1 w:0) + // Storage: Staking MinNominatorBond (r:1 w:0) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Proof Size summary in bytes: - // Measured: `2457` - // Estimated: `29534` - // Minimum execution time: 81_299 nanoseconds. - Weight::from_parts(82_242_000, 29534) - .saturating_add(RocksDbWeight::get().reads(12_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + // Minimum execution time: 98_447 nanoseconds. + Weight::from_ref_time(99_317_000) + .saturating_add(RocksDbWeight::get().reads(12)) + .saturating_add(RocksDbWeight::get().writes(8)) + } + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1085` - // Estimated: `10442` - // Minimum execution time: 31_479 nanoseconds. - Weight::from_parts(32_410_035, 10442) - // Standard Error: 313 - .saturating_add(Weight::from_ref_time(9_090).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:1) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Staking SpanSlash (r:0 w:100) - /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) + // Minimum execution time: 45_142 nanoseconds. + Weight::from_ref_time(46_003_517) + // Standard Error: 564 + .saturating_add(Weight::from_ref_time(60_400).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(4)) + .saturating_add(RocksDbWeight::get().writes(3)) + } + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking SlashingSpans (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2486 + s * (4 ±0)` - // Estimated: `32303 + s * (4 ±0)` - // Minimum execution time: 71_968 nanoseconds. - Weight::from_parts(76_631_804, 32303) - // Standard Error: 1_613 - .saturating_add(Weight::from_ref_time(1_058_968).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(13_u64)) - .saturating_add(RocksDbWeight::get().writes(12_u64)) + // Minimum execution time: 86_176 nanoseconds. + Weight::from_ref_time(91_591_693) + // Standard Error: 2_162 + .saturating_add(Weight::from_ref_time(1_089_160).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(13)) + .saturating_add(RocksDbWeight::get().writes(12)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinValidatorBond (r:1 w:0) - /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking MinCommission (r:1 w:0) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:1) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking MaxValidatorsCount (r:1 w:0) - /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForValidators (r:1 w:1) - /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking MinValidatorBond (r:1 w:0) + // Storage: Staking MinCommission (r:1 w:0) + // Storage: Staking Validators (r:1 w:1) + // Storage: Staking MaxValidatorsCount (r:1 w:0) + // Storage: Staking Nominators (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListNodes (r:1 w:1) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Proof Size summary in bytes: - // Measured: `1446` - // Estimated: `19359` - // Minimum execution time: 51_963 nanoseconds. - Weight::from_parts(52_418_000, 19359) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Minimum execution time: 65_754 nanoseconds. + Weight::from_ref_time(66_793_000) + .saturating_add(RocksDbWeight::get().reads(11)) + .saturating_add(RocksDbWeight::get().writes(5)) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:128 w:128) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1292 + k * (601 ±0)` - // Estimated: `3566 + k * (3033 ±0)` - // Minimum execution time: 25_685 nanoseconds. - Weight::from_parts(25_290_286, 3566) - // Standard Error: 5_164 - .saturating_add(Weight::from_ref_time(6_445_608).saturating_mul(k.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Minimum execution time: 44_020 nanoseconds. + Weight::from_ref_time(41_692_773) + // Standard Error: 12_148 + .saturating_add(Weight::from_ref_time(7_092_259).saturating_mul(k.into())) + .saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) - .saturating_add(Weight::from_proof_size(3033).saturating_mul(k.into())) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:17 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking MinNominatorBond (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking MaxNominatorsCount (r:1 w:0) + // Storage: Staking Validators (r:2 w:0) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1984 + n * (105 ±0)` - // Estimated: `21988 + n * (2520 ±0)` - // Minimum execution time: 59_542 nanoseconds. - Weight::from_parts(57_558_678, 21988) - // Standard Error: 10_364 - .saturating_add(Weight::from_ref_time(2_759_713).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(12_u64)) + // Minimum execution time: 72_131 nanoseconds. + Weight::from_ref_time(71_703_530) + // Standard Error: 6_947 + .saturating_add(Weight::from_ref_time(2_757_165).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - .saturating_add(Weight::from_proof_size(2520).saturating_mul(n.into())) - } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + .saturating_add(RocksDbWeight::get().writes(6)) + } + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Proof Size summary in bytes: - // Measured: `1876` - // Estimated: `17932` - // Minimum execution time: 52_132 nanoseconds. - Weight::from_parts(52_648_000, 17932) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + // Minimum execution time: 66_151 nanoseconds. + Weight::from_ref_time(66_596_000) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().writes(6)) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Proof Size summary in bytes: - // Measured: `840` - // Estimated: `3566` - // Minimum execution time: 13_399 nanoseconds. - Weight::from_parts(13_567_000, 3566) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 17_305 nanoseconds. + Weight::from_ref_time(17_506_000) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:2 w:2) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Proof Size summary in bytes: - // Measured: `939` - // Estimated: `9679` - // Minimum execution time: 20_425 nanoseconds. - Weight::from_parts(20_713_000, 9679) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Minimum execution time: 24_482 nanoseconds. + Weight::from_ref_time(25_101_000) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(3)) } - /// Storage: Staking ValidatorCount (r:0 w:1) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_069 nanoseconds. - Weight::from_ref_time(3_176_000) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 5_100 nanoseconds. + Weight::from_ref_time(5_274_000) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking ForceEra (r:0 w:1) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_386 nanoseconds. - Weight::from_ref_time(11_672_000) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 19_788 nanoseconds. + Weight::from_ref_time(20_313_000) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking ForceEra (r:0 w:1) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_591 nanoseconds. - Weight::from_ref_time(11_799_000) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 19_499 nanoseconds. + Weight::from_ref_time(19_987_000) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking ForceEra (r:0 w:1) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_553 nanoseconds. - Weight::from_ref_time(11_871_000) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 19_846 nanoseconds. + Weight::from_ref_time(20_127_000) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking Invulnerables (r:0 w:1) - /// Proof Skipped: Staking Invulnerables (max_values: Some(1), max_size: None, mode: Measured) + // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_292 nanoseconds. - Weight::from_ref_time(3_754_352) - // Standard Error: 40 - .saturating_add(Weight::from_ref_time(9_838).saturating_mul(v.into())) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:1) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:0 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Staking SpanSlash (r:0 w:100) - /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) + // Minimum execution time: 5_301 nanoseconds. + Weight::from_ref_time(6_147_935) + // Standard Error: 32 + .saturating_add(Weight::from_ref_time(10_076).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().writes(1)) + } + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking SlashingSpans (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Ledger (r:0 w:1) + // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2178 + s * (4 ±0)` - // Estimated: `27930 + s * (4 ±0)` - // Minimum execution time: 65_307 nanoseconds. - Weight::from_parts(70_227_980, 27930) - // Standard Error: 2_113 - .saturating_add(Weight::from_ref_time(1_059_856).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(12_u64)) + // Minimum execution time: 79_381 nanoseconds. + Weight::from_ref_time(85_216_285) + // Standard Error: 2_681 + .saturating_add(Weight::from_ref_time(1_100_353).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(11)) + .saturating_add(RocksDbWeight::get().writes(12)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - /// Storage: Staking UnappliedSlashes (r:1 w:1) - /// Proof Skipped: Staking UnappliedSlashes (max_values: None, max_size: None, mode: Measured) + // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `66671` - // Estimated: `69146` - // Minimum execution time: 89_123 nanoseconds. - Weight::from_parts(890_989_741, 69146) - // Standard Error: 58_282 - .saturating_add(Weight::from_ref_time(4_920_413).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasValidatorReward (r:1 w:0) - /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:257 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking ErasStakersClipped (r:1 w:0) - /// Proof Skipped: Staking ErasStakersClipped (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasRewardPoints (r:1 w:0) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasValidatorPrefs (r:1 w:0) - /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:257 w:0) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: System Account (r:257 w:257) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + // Minimum execution time: 92_049 nanoseconds. + Weight::from_ref_time(894_164_159) + // Standard Error: 58_104 + .saturating_add(Weight::from_ref_time(4_961_170).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) + } + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking ErasStakersOverview (r:1 w:0) + // Storage: Staking ErasValidatorReward (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking ClaimedRewards (r:1 w:1) + // Storage: Staking ErasStakersPaged (r:1 w:0) + // Storage: Staking ErasStakersClipped (r:1 w:0) + // Storage: Staking ErasRewardPoints (r:1 w:0) + // Storage: Staking ErasValidatorPrefs (r:1 w:0) + // Storage: Staking Payee (r:1 w:0) + // Storage: System Account (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `20345 + n * (143 ±0)` - // Estimated: `54756 + n * (8024 ±1)` - // Minimum execution time: 73_652 nanoseconds. - Weight::from_parts(127_839_483, 54756) - // Standard Error: 14_195 - .saturating_add(Weight::from_ref_time(21_932_079).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Minimum execution time: 134_548 nanoseconds. + Weight::from_ref_time(195_909_318) + // Standard Error: 17_825 + .saturating_add(Weight::from_ref_time(22_179_182).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_proof_size(8024).saturating_mul(n.into())) } - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasValidatorReward (r:1 w:0) - /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:257 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:257 w:257) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking ErasStakersClipped (r:1 w:0) - /// Proof Skipped: Staking ErasStakersClipped (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasRewardPoints (r:1 w:0) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasValidatorPrefs (r:1 w:0) - /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:257 w:0) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: System Account (r:257 w:257) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:257 w:257) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking ErasStakersOverview (r:1 w:0) + // Storage: Staking ErasValidatorReward (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking ClaimedRewards (r:1 w:1) + // Storage: Staking ErasStakersPaged (r:1 w:0) + // Storage: Staking ErasStakersClipped (r:1 w:0) + // Storage: Staking ErasRewardPoints (r:1 w:0) + // Storage: Staking ErasValidatorPrefs (r:1 w:0) + // Storage: Staking Payee (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `35099 + n * (465 ±0)` - // Estimated: `83594 + n * (16026 ±0)` - // Minimum execution time: 94_560 nanoseconds. - Weight::from_parts(154_033_219, 83594) - // Standard Error: 26_663 - .saturating_add(Weight::from_ref_time(31_269_223).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(10_u64)) + // Minimum execution time: 167_574 nanoseconds. + Weight::from_ref_time(232_044_473) + // Standard Error: 25_865 + .saturating_add(Weight::from_ref_time(31_272_789).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_proof_size(16026).saturating_mul(n.into())) } - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) + // Storage: Staking Bonded (r:1 w:0) + // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2253 + l * (7 ±0)` - // Estimated: `25491` - // Minimum execution time: 74_764 nanoseconds. - Weight::from_parts(75_814_067, 25491) - // Standard Error: 1_217 - .saturating_add(Weight::from_ref_time(64_725).saturating_mul(l.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:1) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Staking SpanSlash (r:0 w:100) - /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) + // Minimum execution time: 91_739 nanoseconds. + Weight::from_ref_time(93_123_333) + // Standard Error: 3_580 + .saturating_add(Weight::from_ref_time(69_425).saturating_mul(l.into())) + .saturating_add(RocksDbWeight::get().reads(9)) + .saturating_add(RocksDbWeight::get().writes(8)) + } + // Storage: System Account (r:1 w:1) + // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) + // Storage: Staking SlashingSpans (r:1 w:1) + // Storage: Staking Validators (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2486 + s * (4 ±0)` - // Estimated: `31810 + s * (4 ±0)` - // Minimum execution time: 77_611 nanoseconds. - Weight::from_parts(79_760_034, 31810) - // Standard Error: 1_597 - .saturating_add(Weight::from_ref_time(1_039_268).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(12_u64)) - .saturating_add(RocksDbWeight::get().writes(12_u64)) + // Minimum execution time: 90_792 nanoseconds. + Weight::from_ref_time(93_893_087) + // Standard Error: 4_158 + .saturating_add(Weight::from_ref_time(1_084_858).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(12)) + .saturating_add(RocksDbWeight::get().writes(12)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - /// Storage: VoterList CounterForListNodes (r:1 w:0) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:200 w:0) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:110 w:0) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:110 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:11 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:110 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:110 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CounterForValidators (r:1 w:0) - /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ValidatorCount (r:1 w:0) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinimumValidatorCount (r:1 w:0) - /// Proof: Staking MinimumValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:1) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasStakersClipped (r:0 w:10) - /// Proof Skipped: Staking ErasStakersClipped (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasValidatorPrefs (r:0 w:10) - /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Staking ErasStakers (r:0 w:10) - /// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking ErasTotalStake (r:0 w:1) - /// Proof: Staking ErasTotalStake (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Staking ErasStartSessionIndex (r:0 w:1) - /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: Staking MinimumActiveStake (r:0 w:1) - /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + // Storage: VoterList CounterForListNodes (r:1 w:0) + // Storage: VoterList ListBags (r:200 w:0) + // Storage: VoterList ListNodes (r:101 w:0) + // Storage: Staking Nominators (r:101 w:0) + // Storage: Staking Validators (r:2 w:0) + // Storage: Staking Bonded (r:101 w:0) + // Storage: Staking Ledger (r:101 w:0) + // Storage: Staking CounterForValidators (r:1 w:0) + // Storage: Staking ValidatorCount (r:1 w:0) + // Storage: Staking MinimumValidatorCount (r:1 w:0) + // Storage: Staking CurrentEra (r:1 w:1) + // Storage: Staking ErasValidatorPrefs (r:0 w:1) + // Storage: Staking ErasStakersPaged (r:0 w:1) + // Storage: Staking ErasStakersOverview (r:0 w:1) + // Storage: Staking ErasStakers (r:0 w:1) + // Storage: Staking ErasTotalStake (r:0 w:1) + // Storage: Staking ErasStartSessionIndex (r:0 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + v * (3662 ±0) + n * (816 ±0)` - // Estimated: `528203 + v * (16743 ±0) + n * (12947 ±0)` - // Minimum execution time: 489_824 nanoseconds. - Weight::from_parts(491_687_000, 528203) - // Standard Error: 1_787_577 - .saturating_add(Weight::from_ref_time(58_719_498).saturating_mul(v.into())) - // Standard Error: 178_122 - .saturating_add(Weight::from_ref_time(13_273_555).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(206_u64)) + // Minimum execution time: 506_210 nanoseconds. + Weight::from_ref_time(508_476_000) + // Standard Error: 1_787_036 + .saturating_add(Weight::from_ref_time(60_417_557).saturating_mul(v.into())) + // Standard Error: 178_068 + .saturating_add(Weight::from_ref_time(13_499_037).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(206)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_proof_size(16743).saturating_mul(v.into())) - .saturating_add(Weight::from_proof_size(12947).saturating_mul(n.into())) - } - /// Storage: VoterList CounterForListNodes (r:1 w:0) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:200 w:0) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2000 w:0) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:2000 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1000 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:2000 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:2000 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinimumActiveStake (r:0 w:1) - /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + .saturating_add(RocksDbWeight::get().writes(3)) + .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(v.into()))) + } + // Storage: VoterList CounterForListNodes (r:1 w:0) + // Storage: VoterList ListBags (r:200 w:0) + // Storage: VoterList ListNodes (r:1500 w:0) + // Storage: Staking Nominators (r:1500 w:0) + // Storage: Staking Validators (r:500 w:0) + // Storage: Staking Bonded (r:1500 w:0) + // Storage: Staking Ledger (r:1500 w:0) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `3167 + v * (459 ±0) + n * (1007 ±0)` - // Estimated: `511899 + v * (14295 ±0) + n * (11775 ±0)` - // Minimum execution time: 23_373_467 nanoseconds. - Weight::from_parts(23_497_257_000, 511899) - // Standard Error: 299_205 - .saturating_add(Weight::from_ref_time(3_434_000).saturating_mul(v.into())) - // Standard Error: 299_205 - .saturating_add(Weight::from_ref_time(2_568_954).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(201_u64)) + // Minimum execution time: 24_070_794 nanoseconds. + Weight::from_ref_time(24_294_007_000) + // Standard Error: 322_618 + .saturating_add(Weight::from_ref_time(3_570_673).saturating_mul(v.into())) + // Standard Error: 322_618 + .saturating_add(Weight::from_ref_time(2_900_021).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(201)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_proof_size(14295).saturating_mul(v.into())) - .saturating_add(Weight::from_proof_size(11775).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking CounterForValidators (r:1 w:0) - /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1001 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + // Storage: Staking CounterForValidators (r:1 w:0) + // Storage: Staking Validators (r:501 w:0) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `983 + v * (50 ±0)` - // Estimated: `3019 + v * (2520 ±0)` - // Minimum execution time: 3_882_120 nanoseconds. - Weight::from_parts(3_951_993_000, 3019) - // Standard Error: 46_729 - .saturating_add(Weight::from_ref_time(2_856_043).saturating_mul(v.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 4_776_351 nanoseconds. + Weight::from_ref_time(4_849_553_000) + // Standard Error: 55_132 + .saturating_add(Weight::from_ref_time(3_604_980).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_proof_size(2520).saturating_mul(v.into())) } - /// Storage: Staking MinCommission (r:0 w:1) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinValidatorBond (r:0 w:1) - /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking MaxValidatorsCount (r:0 w:1) - /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ChillThreshold (r:0 w:1) - /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:0 w:1) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:0 w:1) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + // Storage: Staking MinCommission (r:0 w:1) + // Storage: Staking MinValidatorBond (r:0 w:1) + // Storage: Staking MaxValidatorsCount (r:0 w:1) + // Storage: Staking ChillThreshold (r:0 w:1) + // Storage: Staking MaxNominatorsCount (r:0 w:1) + // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 8_427 nanoseconds. - Weight::from_ref_time(8_794_000) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - } - /// Storage: Staking MinCommission (r:0 w:1) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinValidatorBond (r:0 w:1) - /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking MaxValidatorsCount (r:0 w:1) - /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ChillThreshold (r:0 w:1) - /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:0 w:1) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:0 w:1) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + // Minimum execution time: 10_781 nanoseconds. + Weight::from_ref_time(11_034_000) + .saturating_add(RocksDbWeight::get().writes(6)) + } + // Storage: Staking MinCommission (r:0 w:1) + // Storage: Staking MinValidatorBond (r:0 w:1) + // Storage: Staking MaxValidatorsCount (r:0 w:1) + // Storage: Staking ChillThreshold (r:0 w:1) + // Storage: Staking MaxNominatorsCount (r:0 w:1) + // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 7_620 nanoseconds. - Weight::from_ref_time(7_901_000) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking ChillThreshold (r:1 w:0) - /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Minimum execution time: 9_418 nanoseconds. + Weight::from_ref_time(10_150_000) + .saturating_add(RocksDbWeight::get().writes(6)) + } + // Storage: Staking Ledger (r:1 w:0) + // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking ChillThreshold (r:1 w:0) + // Storage: Staking MaxNominatorsCount (r:1 w:0) + // Storage: Staking CounterForNominators (r:1 w:1) + // Storage: Staking MinNominatorBond (r:1 w:0) + // Storage: Staking Validators (r:1 w:0) + // Storage: VoterList ListNodes (r:2 w:2) + // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Proof Size summary in bytes: - // Measured: `2031` - // Estimated: `19438` - // Minimum execution time: 66_188 nanoseconds. - Weight::from_parts(66_767_000, 19438) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + // Minimum execution time: 82_590 nanoseconds. + Weight::from_ref_time(83_718_000) + .saturating_add(RocksDbWeight::get().reads(11)) + .saturating_add(RocksDbWeight::get().writes(6)) } - /// Storage: Staking MinCommission (r:1 w:0) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:1) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + // Storage: Staking MinCommission (r:1 w:0) + // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Proof Size summary in bytes: - // Measured: `694` - // Estimated: `3019` - // Minimum execution time: 14_703 nanoseconds. - Weight::from_parts(15_031_000, 3019) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 19_367 nanoseconds. + Weight::from_ref_time(19_668_000) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: Staking MinCommission (r:0 w:1) - /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: Staking MinCommission (r:0 w:1) fn set_min_commission() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 4_518 nanoseconds. - Weight::from_ref_time(4_656_000) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 6_107 nanoseconds. + Weight::from_ref_time(6_449_000) + .saturating_add(RocksDbWeight::get().writes(1)) } } From 95f1455ec5439e16c6677828034c3853c8778a7c Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 17:20:05 +0100 Subject: [PATCH 041/131] doc for split into pages --- frame/staking/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1410bdb29444a..51e1673bf4fc7 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -735,6 +735,8 @@ impl Default for Exposure Exposure { + /// Splits an `Exposure` into `ExposureOverview` and multiple chunks of `IndividualExposure` + /// with each chunk having maximum of `page_size` elements. fn as_pages( &self, page_size: u32, From 261b8eef92b0677edfa819cb356932e4e03e7fae Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 17:20:35 +0100 Subject: [PATCH 042/131] remove unused from --- frame/staking/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 51e1673bf4fc7..c07a46ab91c51 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -788,14 +788,6 @@ impl Default for ExposurePage - From> for ExposurePage -{ - fn from(exposure: Exposure) -> Self { - Self { page_total: exposure.total, others: exposure.others } - } -} - /// A snapshot of the stake backing a single validator in the system. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct ExposureOverview { From 562873aea288211c1948ed96cc94a0ae5c081b5e Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 17:26:16 +0100 Subject: [PATCH 043/131] fix doc --- frame/staking/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index c07a46ab91c51..3f16a36d69063 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -788,7 +788,10 @@ impl Default for ExposurePage { /// The total balance backing this validator. From a4ae4f99add2cf4f02c6b53d8fd0e4f214606021 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 18:05:21 +0100 Subject: [PATCH 044/131] rename MaxNominatorRewardedPerValidator --- bin/node/runtime/src/lib.rs | 4 +-- frame/babe/src/mock.rs | 2 +- frame/fast-unstake/src/mock.rs | 2 +- frame/grandpa/src/mock.rs | 2 +- .../nomination-pools/benchmarking/src/mock.rs | 2 +- .../nomination-pools/test-staking/src/mock.rs | 2 +- frame/offences/benchmarking/src/mock.rs | 2 +- frame/root-offences/src/mock.rs | 2 +- frame/session/benchmarking/src/mock.rs | 2 +- frame/staking/README.md | 6 ++-- frame/staking/src/benchmarking.rs | 12 +++---- frame/staking/src/lib.rs | 13 ++++--- frame/staking/src/mock.rs | 4 +-- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 35 +++++++++++-------- frame/staking/src/tests.rs | 12 +++---- 16 files changed, 55 insertions(+), 49 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index f8589036f7853..39edd41b3472e 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -538,7 +538,7 @@ parameter_types! { pub const BondingDuration: sp_staking::EraIndex = 24 * 28; pub const SlashDeferDuration: sp_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const MaxNominatorRewardedPerValidator: u32 = 256; + pub const MaxNominatorRewardedPerPage: u32 = 256; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); pub OffchainRepeat: BlockNumber = 5; pub HistoryDepth: u32 = 84; @@ -571,7 +571,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerPage = MaxNominatorRewardedPerPage; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainExecution; diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index b130677897883..fb9c5713920ca 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -192,7 +192,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index b20ba43ab3758..175ba9af0e33c 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -146,7 +146,7 @@ impl pallet_staking::Config for Runtime { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); type HistoryDepth = ConstU32<84>; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = MockElection; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index a33fbb22d6ff8..eadff6fd12b1b 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -196,7 +196,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/nomination-pools/benchmarking/src/mock.rs b/frame/nomination-pools/benchmarking/src/mock.rs index 4e188ea7ef189..8e59d3cd92b07 100644 --- a/frame/nomination-pools/benchmarking/src/mock.rs +++ b/frame/nomination-pools/benchmarking/src/mock.rs @@ -107,7 +107,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; diff --git a/frame/nomination-pools/test-staking/src/mock.rs b/frame/nomination-pools/test-staking/src/mock.rs index 3d0ab2c6f35f3..51a65081efd31 100644 --- a/frame/nomination-pools/test-staking/src/mock.rs +++ b/frame/nomination-pools/test-staking/src/mock.rs @@ -121,7 +121,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 233aa449d391c..bd6ca8650acfa 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -170,7 +170,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/root-offences/src/mock.rs b/frame/root-offences/src/mock.rs index 0937c43d6e519..219a64cb284d6 100644 --- a/frame/root-offences/src/mock.rs +++ b/frame/root-offences/src/mock.rs @@ -184,7 +184,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 4c4accbbfac8f..517f0618531d2 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -172,7 +172,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxNominatorRewardedPerPage = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/README.md b/frame/staking/README.md index bbd5bd18f6e81..094b102b38955 100644 --- a/frame/staking/README.md +++ b/frame/staking/README.md @@ -90,9 +90,9 @@ valid behavior_ while _punishing any misbehavior or lack of availability_. Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerValidator`] -biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each -nominator's account. +validator as well as its nominators. Rewards are paged to maximum of [`Config::MaxNominatorRewardedPerPage`] +nominators per call. Each page of staker payout needs to be called separately to ensure all nominators are +paid. This is to limit the i/o cost to mutate storage for each nominator's account. Slashing can occur at any point in time, once misbehavior is reported. Once slashing is determined, a value is deducted from the balance of the validator and all the nominators who diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index df42ad77ea7e2..15506f512008c 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -546,10 +546,10 @@ benchmarks! { } payout_stakers_dead_controller { - let n in 0 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; let (validator, nominators) = create_validator_with_nominators::( n, - T::MaxNominatorRewardedPerValidator::get() as u32, + T::MaxNominatorRewardedPerPage::get() as u32, true, RewardDestination::Controller, )?; @@ -579,10 +579,10 @@ benchmarks! { } payout_stakers_alive_staked { - let n in 0 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; let (validator, nominators) = create_validator_with_nominators::( n, - T::MaxNominatorRewardedPerValidator::get() as u32, + T::MaxNominatorRewardedPerPage::get() as u32, false, RewardDestination::Staked, )?; @@ -976,7 +976,7 @@ mod tests { let (validator_stash, nominators) = create_validator_with_nominators::( n, - <::MaxNominatorRewardedPerValidator as Get<_>>::get(), + <::MaxNominatorRewardedPerPage as Get<_>>::get(), false, RewardDestination::Staked, ) @@ -1006,7 +1006,7 @@ mod tests { let (validator_stash, _nominators) = create_validator_with_nominators::( n, - <::MaxNominatorRewardedPerValidator as Get<_>>::get(), + <::MaxNominatorRewardedPerPage as Get<_>>::get(), false, RewardDestination::Staked, ) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3f16a36d69063..6d136a8aed4cd 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -114,7 +114,7 @@ //! //! Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the //! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -//! validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerValidator`] +//! validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerPage`] //! biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each //! nominator's account. //! @@ -224,13 +224,12 @@ //! The validator can declare an amount, named [`commission`](ValidatorPrefs::commission), that does //! not get shared with the nominators at each reward payout through its [`ValidatorPrefs`]. This //! value gets deducted from the total reward that is paid to the validator and its nominators. The -//! remaining portion is split pro rata among the validator and the top -//! [`Config::MaxNominatorRewardedPerValidator`] nominators that nominated the validator, -//! proportional to the value staked behind the validator (_i.e._ dividing the +//! remaining portion is split pro rata among the validator and the nominators that nominated the +//! validator, proportional to the value staked behind the validator (_i.e._ dividing the //! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in -//! [`Exposure`]). Note that the pro rata division of rewards uses the total exposure behind the -//! validator, *not* just the exposure of the validator and the top -//! [`Config::MaxNominatorRewardedPerValidator`] nominators. +//! [`Exposure`]). Note that payouts are made in pages with each page capped at +//! [`T::MaxNominatorRewardedPerPage`] nominators. The distribution of nominators across pages are +//! unsorted and depends on the election result provided by [`T::ElectionProvider`]. //! //! All entities who receive a reward have the option to choose their reward destination through the //! [`Payee`] storage item (see diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 119fc71f2b4e5..a7904b95a790f 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -230,7 +230,7 @@ parameter_types! { pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; pub static MaxNominations: u32 = 16; pub static HistoryDepth: u32 = 80; - pub static MaxNominatorRewardedPerValidator: u32 = 64; + pub static MaxNominatorRewardedPerPage: u32 = 64; pub static MaxUnlockingChunks: u32 = 32; pub static RewardOnUnbalanceWasCalled: bool = false; pub static LedgerSlashPerEra: (BalanceOf, BTreeMap>) = (Zero::zero(), BTreeMap::new()); @@ -293,7 +293,7 @@ impl crate::pallet::pallet::Config for Test { type SessionInterface = Self; type EraPayout = ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerPage = MaxNominatorRewardedPerPage; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index ee14eb1e94b15..34d8d35018548 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -261,7 +261,7 @@ impl Pallet { } T::Reward::on_unbalanced(total_imbalance); - debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerValidator::get()); + debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerPage::get()); Ok(Some(T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count)).into()) } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 0b451e2e1e63c..285d0a2ecb174 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -203,11 +203,11 @@ pub mod pallet { /// The maximum number of nominators rewarded for each validator. /// - /// For each validator only the `$MaxNominatorRewardedPerValidator` biggest stakers can - /// claim their reward. This used to limit the i/o cost for the nominator payout. - // TODO(ank4n): Refactor into a better name to indicate that this is a per-page limit. + /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerPage` nominators + /// in a single call. This used to limit the i/o cost for the nominator payout. + /// See [`payout_stakers`] for more details. #[pallet::constant] - type MaxNominatorRewardedPerValidator: Get; + type MaxNominatorRewardedPerPage: Get; /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. @@ -440,8 +440,11 @@ pub mod pallet { /// Clipped Exposure of validator at era. /// + /// Note: This is deprecated, should be used as read-only and will be removed in the future. + /// New `Exposure`s are stored in a paged manner in `ErasStakersPaged` instead. + /// /// This is similar to [`ErasStakers`] but number of nominators exposed is reduced to the - /// `T::MaxNominatorRewardedPerValidator` biggest stakers. + /// `T::MaxNominatorRewardedPerPage` biggest stakers. /// (Note: the field `total` and `own` of the exposure remains unchanged). /// This is used to limit the i/o cost for the nominator payout. /// @@ -701,7 +704,7 @@ pub mod pallet { >::insert(era, &validator, &exposure); let (exposure_overview, exposure_pages) = - exposure.as_pages(T::MaxNominatorRewardedPerValidator::get()); + exposure.as_pages(T::MaxNominatorRewardedPerPage::get()); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { @@ -1616,20 +1619,24 @@ pub mod pallet { /// Pay out all the stakers behind a single validator for a single era and page. /// - /// - `validator_stash` is the stash account of the validator. Their nominators, up to - /// `T::MaxNominatorRewardedPerValidator`, will also receive their rewards. + /// - `validator_stash` is the stash account of the validator. /// - `era` may be any era between `[current_era - history_depth; current_era]`. + /// - `page` is the page index of nominators to pay out with value between 0 and + /// `num_nominators / T::MaxNominatorRewardedPerPage`. /// /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// The list of nominators is paged, with each page being capped at - /// `T::MaxNominatorRewardedPerValidator`. If a validator has multiple pages of nominators, - /// the call needs to be made for each page such that all nominators receive the reward. If - /// rewards are not claimed in `${HistoryDepth}` eras, they are lost. + /// If a validator has more than `T::MaxMaxNominatorRewardedPerPage` nominators backing + /// them, then the list of nominators is paged, with each page being capped at + /// `T::MaxNominatorRewardedPerPage`. If a validator has more than one page of nominators, + /// the call needs to be made for each page separately in order for all the nominators + /// backing a validator receive the reward. The nominators are not sorted across pages and + /// so it should not be assumed the highest staker would be on the topmost page and vice + /// versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. /// /// # - /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). + /// - Time complexity: at most O(MaxNominatorRewardedPerPage). /// - Contains a limited number of reads and writes. /// ----------- /// N is the Number of payouts for the validator (including the validator) @@ -1642,7 +1649,7 @@ pub mod pallet { /// # #[pallet::call_index(18)] #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( - T::MaxNominatorRewardedPerValidator::get() + T::MaxNominatorRewardedPerPage::get() ))] pub fn payout_stakers( origin: OriginFor, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index ed95ff169c9ca..45fa56752d9f1 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2196,7 +2196,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; let (exposure_overview, _) = - exposure.clone().as_pages(MaxNominatorRewardedPerValidator::get()); + exposure.clone().as_pages(MaxNominatorRewardedPerPage::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -3696,7 +3696,7 @@ fn six_session_delay() { fn test_nominators_are_rewarded_for_all_exposure_page() { ExtBuilder::default().build_and_execute(|| { // 3 pages of exposure - let nominator_count = 2 * MaxNominatorRewardedPerValidator::get() + 1; + let nominator_count = 2 * MaxNominatorRewardedPerPage::get() + 1; for i in 0..nominator_count { let stash = 10_000 + i as AccountId; @@ -3742,7 +3742,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { #[test] fn test_multi_page_payout_stakers() { // Test that payout_stakers work in general, including that only the top - // `T::MaxNominatorRewardedPerValidator` nominators are rewarded. + // `T::MaxNominatorRewardedPerPage` nominators are rewarded. ExtBuilder::default().has_stakers(false).build_and_execute(|| { let balance = 1000; // Track the exposure of the validator and all nominators. @@ -3767,7 +3767,7 @@ fn test_multi_page_payout_stakers() { mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); - // Since `MaxNominatorRewardedPerValidator = 64`, there are two pages of validator exposure. + // Since `MaxNominatorRewardedPerPage = 64`, there are two pages of validator exposure. assert_eq!(EraInfo::::get_page_count(1, &11), 2); // compute and ensure the reward amount is greater than zero. @@ -4020,7 +4020,7 @@ fn payout_stakers_handles_weight_refund() { // Note: this test relies on the assumption that `payout_stakers_alive_staked` is solely used by // `payout_stakers` to calculate the weight of each payout op. ExtBuilder::default().has_stakers(false).build_and_execute(|| { - let max_nom_rewarded = MaxNominatorRewardedPerValidator::get(); + let max_nom_rewarded = MaxNominatorRewardedPerPage::get(); // Make sure the configured value is meaningful for our use. assert!(max_nom_rewarded >= 4); let half_max_nom_rewarded = max_nom_rewarded / 2; @@ -5870,7 +5870,7 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ExtBuilder::default().has_stakers(false).build_and_execute(|| { // case 1: exposure exist in clipped. // set page cap to 10 - MaxNominatorRewardedPerValidator::set(10); + MaxNominatorRewardedPerPage::set(10); bond_validator(11, 10, 1000); let mut expected_individual_exposures: Vec> = vec![]; let mut total_exposure: Balance = 0; From 6aeb3206cc7f77b94d2759da3c8e853a7d103ad9 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 19:22:58 +0100 Subject: [PATCH 045/131] add weight for pages other than 0 --- frame/staking/src/benchmarking.rs | 43 +++++++++++++++++++++++++++++++ frame/staking/src/pallet/impls.rs | 9 ++++++- frame/staking/src/tests.rs | 1 - frame/staking/src/weights.rs | 8 ++++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 15506f512008c..664bd1444cd34 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -614,6 +614,49 @@ benchmarks! { } } + payout_stakers_alive_staked_exclude_validator { + let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; + + // create nominators between MaxNominatorRewardedPerPage .. 2 * MaxNominatorRewardedPerPage + let (validator, nominators) = create_validator_with_nominators::( + T::MaxNominatorRewardedPerPage::get() + n, + 2*T::MaxNominatorRewardedPerPage::get() as u32, + false, + RewardDestination::Staked, + )?; + + let current_era = CurrentEra::::get().unwrap(); + // set the commission for this particular era as well. + >::insert(current_era, validator.clone(), >::validators(&validator)); + + let caller = whitelisted_caller(); + let balance_before = T::Currency::free_balance(&validator); + let mut nominator_balances_before = Vec::new(); + for (stash, _) in &nominators { + let balance = T::Currency::free_balance(stash); + nominator_balances_before.push(balance); + } + }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era, 1) + verify { + let balance_after = T::Currency::free_balance(&validator); + ensure!( + balance_before == balance_after, + "Balance of validator stash should have stayed same after payout since its not page 0.", + ); + let mut nominator_payout_count = 0; + for ((stash, _), balance_before) in nominators.iter().zip(nominator_balances_before.iter()) { + let balance_after = T::Currency::free_balance(stash); + if balance_before < &balance_after { + nominator_payout_count += 1; + } + } + ensure!( + nominator_payout_count == n, + "n nominators must have been paid.", + ); + } + + rebond { let l in 1 .. T::MaxUnlockingChunks::get() as u32; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 34d8d35018548..63f307c35e272 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -262,7 +262,14 @@ impl Pallet { T::Reward::on_unbalanced(total_imbalance); debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerPage::get()); - Ok(Some(T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count)).into()) + + let payout_weight = if page == 0 { + T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count) + } else { + T::WeightInfo::payout_stakers_alive_staked_exclude_validator(nominator_payout_count) + }; + + Ok(Some(payout_weight).into()) } /// Update the ledger for a controller. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 45fa56752d9f1..24027fed4e65f 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3773,7 +3773,6 @@ fn test_multi_page_payout_stakers() { // compute and ensure the reward amount is greater than zero. let payout = current_total_payout_for_duration(reward_time_per_era()); let actual_paid_out = payout_exposure_part * payout; - println!("Actual paid out {:?}", actual_paid_out); mock::start_active_era(2); // verify the exposures are calculated correctly. diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index dc62a86201be6..17f63d836e73c 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -68,6 +68,7 @@ pub trait WeightInfo { fn cancel_deferred_slash(s: u32, ) -> Weight; fn payout_stakers_dead_controller(n: u32, ) -> Weight; fn payout_stakers_alive_staked(n: u32, ) -> Weight; + fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight; fn rebond(l: u32, ) -> Weight; fn reap_stash(s: u32, ) -> Weight; fn new_era(v: u32, n: u32, ) -> Weight; @@ -348,6 +349,9 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } + fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight { + Weight::from_ref_time(0) + } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -773,6 +777,10 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(4)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) } + fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight { + // Minimum execution time: 164_719 nanoseconds. + Weight::from_ref_time(0) + } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) From 9cbd08f91d0a7cefd32be85b4fd1b383bccafb01 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 19:26:23 +0100 Subject: [PATCH 046/131] fmt --- frame/staking/src/tests.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 24027fed4e65f..5ba5b8071f33f 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2195,8 +2195,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { let _ = Balances::make_free_balance_be(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; - let (exposure_overview, _) = - exposure.clone().as_pages(MaxNominatorRewardedPerPage::get()); + let (exposure_overview, _) = exposure.clone().as_pages(MaxNominatorRewardedPerPage::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), From 3ecc3987fd8001ace8d271c6ecec0efe4b24582a Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 19:34:40 +0100 Subject: [PATCH 047/131] use n to make the compiler happy --- frame/staking/src/weights.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 17f63d836e73c..601e0c341524d 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -350,7 +350,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight { - Weight::from_ref_time(0) + Weight::from_ref_time(n.into()) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -779,7 +779,7 @@ impl WeightInfo for () { } fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight { // Minimum execution time: 164_719 nanoseconds. - Weight::from_ref_time(0) + Weight::from_ref_time(n.into()) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) From daf7609f1a98b6c32c77d3d434bb6e0af5939383 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 21:00:26 +0100 Subject: [PATCH 048/131] fix minimum count --- frame/staking/src/benchmarking.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 664bd1444cd34..5fd9dc6f38f43 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -617,10 +617,10 @@ benchmarks! { payout_stakers_alive_staked_exclude_validator { let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; - // create nominators between MaxNominatorRewardedPerPage .. 2 * MaxNominatorRewardedPerPage + // create nominators between MaxNominatorRewardedPerPage+1 .. =2 * MaxNominatorRewardedPerPage let (validator, nominators) = create_validator_with_nominators::( - T::MaxNominatorRewardedPerPage::get() + n, - 2*T::MaxNominatorRewardedPerPage::get() as u32, + T::MaxNominatorRewardedPerPage::get() + 1 + n, + 2 * T::MaxNominatorRewardedPerPage::get() as u32, false, RewardDestination::Staked, )?; From fc51915cd1e94df4a68ca938d78421ffc189e0b9 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 21:29:53 +0100 Subject: [PATCH 049/131] correct number of nominators --- frame/staking/src/benchmarking.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 5fd9dc6f38f43..96ec8c8989b30 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -616,11 +616,13 @@ benchmarks! { payout_stakers_alive_staked_exclude_validator { let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; - // create nominators between MaxNominatorRewardedPerPage+1 .. =2 * MaxNominatorRewardedPerPage + let nominator_lower_bound = T::MaxNominatorRewardedPerPage::get() + 1; + let nominator_upper_bound = 2 * T::MaxNominatorRewardedPerPage::get() + 1; + let (validator, nominators) = create_validator_with_nominators::( - T::MaxNominatorRewardedPerPage::get() + 1 + n, - 2 * T::MaxNominatorRewardedPerPage::get() as u32, + nominator_lower_bound + n, + nominator_upper_bound as u32, false, RewardDestination::Staked, )?; From 85d3dc5c7a915174e84779c34dedae0b93e4c8bc Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 22:43:25 +0100 Subject: [PATCH 050/131] fix benchmark and commission payout --- frame/staking/src/benchmarking.rs | 14 +++++++++----- frame/staking/src/pallet/impls.rs | 15 ++++++++++----- frame/staking/src/weights.rs | 6 +++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 96ec8c8989b30..1e5296aa32db3 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -614,11 +614,11 @@ benchmarks! { } } - payout_stakers_alive_staked_exclude_validator { - let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; + payout_stakers_nominators_only { + let n in 1 .. T::MaxNominatorRewardedPerPage::get() as u32; // create nominators between MaxNominatorRewardedPerPage+1 .. =2 * MaxNominatorRewardedPerPage - let nominator_lower_bound = T::MaxNominatorRewardedPerPage::get() + 1; - let nominator_upper_bound = 2 * T::MaxNominatorRewardedPerPage::get() + 1; + let nominator_lower_bound = T::MaxNominatorRewardedPerPage::get(); + let nominator_upper_bound = 2 * T::MaxNominatorRewardedPerPage::get(); let (validator, nominators) = create_validator_with_nominators::( nominator_lower_bound + n, @@ -638,13 +638,16 @@ benchmarks! { let balance = T::Currency::free_balance(stash); nominator_balances_before.push(balance); } + }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era, 1) verify { let balance_after = T::Currency::free_balance(&validator); + ensure!( balance_before == balance_after, - "Balance of validator stash should have stayed same after payout since its not page 0.", + "Validator should not have received payout for pages other than 0.", ); + let mut nominator_payout_count = 0; for ((stash, _), balance_before) in nominators.iter().zip(nominator_balances_before.iter()) { let balance_after = T::Currency::free_balance(stash); @@ -652,6 +655,7 @@ benchmarks! { nominator_payout_count += 1; } } + ensure!( nominator_payout_count == n, "n nominators must have been paid.", diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 63f307c35e272..3c06d3b37a41f 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -210,10 +210,15 @@ impl Pallet { // This is how much validator + nominators are entitled to. let validator_total_payout = validator_total_reward_part * era_payout; - let validator_prefs = Self::eras_validator_prefs(&era, &validator_stash); - // Validator first gets a cut off the top. - let validator_commission = validator_prefs.commission; - let validator_commission_payout = validator_commission * validator_total_payout; + // TODO(ank4n) add test and refactor this logic + let validator_commission_payout = if page == 0 { + let validator_prefs = Self::eras_validator_prefs(&era, &validator_stash); + // Validator first gets a cut off the top. + let validator_commission = validator_prefs.commission; + validator_commission * validator_total_payout + } else { + Zero::zero() + }; let validator_leftover_payout = validator_total_payout - validator_commission_payout; // Now let's calculate how this is split to the validator. @@ -266,7 +271,7 @@ impl Pallet { let payout_weight = if page == 0 { T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count) } else { - T::WeightInfo::payout_stakers_alive_staked_exclude_validator(nominator_payout_count) + T::WeightInfo::payout_stakers_nominators_only(nominator_payout_count) }; Ok(Some(payout_weight).into()) diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 601e0c341524d..afb4fc0df6b68 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -68,7 +68,7 @@ pub trait WeightInfo { fn cancel_deferred_slash(s: u32, ) -> Weight; fn payout_stakers_dead_controller(n: u32, ) -> Weight; fn payout_stakers_alive_staked(n: u32, ) -> Weight; - fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight; + fn payout_stakers_nominators_only(n: u32, ) -> Weight; fn rebond(l: u32, ) -> Weight; fn reap_stash(s: u32, ) -> Weight; fn new_era(v: u32, n: u32, ) -> Weight; @@ -349,7 +349,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } - fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight { + fn payout_stakers_nominators_only(n: u32, ) -> Weight { Weight::from_ref_time(n.into()) } // Storage: Staking Ledger (r:1 w:1) @@ -777,7 +777,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(4)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) } - fn payout_stakers_alive_staked_exclude_validator(n: u32, ) -> Weight { + fn payout_stakers_nominators_only(n: u32, ) -> Weight { // Minimum execution time: 164_719 nanoseconds. Weight::from_ref_time(n.into()) } From 651c489907cad33495571f9450d156e322d4eaa0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 22:53:19 +0100 Subject: [PATCH 051/131] refactor --- frame/staking/src/pallet/impls.rs | 11 ++--------- frame/staking/src/pallet/mod.rs | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 3c06d3b37a41f..b619499053c7c 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -210,15 +210,8 @@ impl Pallet { // This is how much validator + nominators are entitled to. let validator_total_payout = validator_total_reward_part * era_payout; - // TODO(ank4n) add test and refactor this logic - let validator_commission_payout = if page == 0 { - let validator_prefs = Self::eras_validator_prefs(&era, &validator_stash); - // Validator first gets a cut off the top. - let validator_commission = validator_prefs.commission; - validator_commission * validator_total_payout - } else { - Zero::zero() - }; + let validator_commission = EraInfo::::get_validator_commission(era, &ledger.stash, page); + let validator_commission_payout = validator_commission * validator_total_payout; let validator_leftover_payout = validator_total_payout - validator_commission_payout; // Now let's calculate how this is split to the validator. diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 285d0a2ecb174..901bc1fbf6ac7 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -684,11 +684,26 @@ pub mod pallet { >::get(&era, validator).page_count.max(1) } - /// Creates an entry to track validator reward has been claimed for a given era and page. - pub(crate) fn set_rewards_as_claimed( + // TODO(ank4n) add commission should only be paid in page 0 test + /// Returns validator commission for this era and page. + pub(crate) fn get_validator_commission( era: EraIndex, - validator: &T::AccountId, + validator_stash: &T::AccountId, page: PageIndex, + ) -> Perbill { + if page != 0 { + // commission is only paid in the first page + return Zero::zero() + } + + >::get(&era, validator_stash).commission + } + + /// Creates an entry to track validator reward has been claimed for a given era and page. + pub(crate) fn set_rewards_as_claimed( + era: EraIndex, + validator: &T::AccountId, + page: PageIndex, ) { ClaimedRewards::::mutate(era, validator, |pages| { pages.push(page); @@ -697,14 +712,14 @@ pub mod pallet { /// Store exposure for elected validators at start of an era. pub(crate) fn set_validator_exposure( - era: EraIndex, - validator: &T::AccountId, - exposure: Exposure>, + era: EraIndex, + validator: &T::AccountId, + exposure: Exposure>, ) { >::insert(era, &validator, &exposure); let (exposure_overview, exposure_pages) = - exposure.as_pages(T::MaxNominatorRewardedPerPage::get()); + exposure.as_pages(T::MaxNominatorRewardedPerPage::get()); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { @@ -716,6 +731,7 @@ pub mod pallet { pub(crate) fn set_total_stake(era: EraIndex, total_stake: BalanceOf) { >::insert(era, total_stake); } + } /// Indices of validators that have offended in the active era and whether they are currently From 658ea3670d82e6c13e03786db1e811c8c0242e1a Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 23:19:15 +0100 Subject: [PATCH 052/131] verify is paid only once per era for their own stake --- frame/staking/src/tests.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 5ba5b8071f33f..fa68479cd1054 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3746,8 +3746,6 @@ fn test_multi_page_payout_stakers() { let balance = 1000; // Track the exposure of the validator and all nominators. let mut total_exposure = balance; - // Track the exposure of the validator and the nominators that will get paid out. - let mut payout_exposure = balance; // Create a validator: bond_validator(11, 10, balance); // Default(64) assert_eq!(Validators::::count(), 1); @@ -3756,13 +3754,10 @@ fn test_multi_page_payout_stakers() { for i in 0..100 { let bond_amount = balance + i as Balance; bond_nominator(1000 + i, 100 + i, bond_amount, vec![11]); - total_exposure += bond_amount; // with multi page reward payout, payout exposure is same as total exposure. - payout_exposure += bond_amount; + total_exposure += bond_amount; } - let payout_exposure_part = Perbill::from_rational(payout_exposure, total_exposure); - mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); @@ -3771,7 +3766,6 @@ fn test_multi_page_payout_stakers() { // compute and ensure the reward amount is greater than zero. let payout = current_total_payout_for_duration(reward_time_per_era()); - let actual_paid_out = payout_exposure_part * payout; mock::start_active_era(2); // verify the exposures are calculated correctly. @@ -3788,20 +3782,29 @@ fn test_multi_page_payout_stakers() { let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); + let controller_balance_before_p0_payout = Balances::free_balance(&10); // Payout rewards for first exposure page assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + let controller_balance_after_p0_payout = Balances::free_balance(&10); + // verify rewards have been paid out but still some left assert!(Balances::total_issuance() > pre_payout_total_issuance); - assert!(Balances::total_issuance() < pre_payout_total_issuance + actual_paid_out); + assert!(Balances::total_issuance() < pre_payout_total_issuance + payout); + + // verify the validator has been rewarded + assert!(controller_balance_after_p0_payout > controller_balance_before_p0_payout); // Payout the second and last page of nominators assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 1)); + // verify the validator was not rewarded the second time + assert_eq!(Balances::free_balance(&10), controller_balance_after_p0_payout); + // verify all rewards have been paid out assert_eq_error_rate!( Balances::total_issuance(), - pre_payout_total_issuance + actual_paid_out, + pre_payout_total_issuance + payout, 2 ); assert!(RewardOnUnbalanceWasCalled::get()); @@ -3839,7 +3842,6 @@ fn test_multi_page_payout_stakers() { // compute and ensure the reward amount is greater than zero. let payout = current_total_payout_for_duration(reward_time_per_era()); - let actual_paid_out = payout_exposure_part * payout; let pre_payout_total_issuance = Balances::total_issuance(); mock::start_active_era(i); @@ -3847,7 +3849,7 @@ fn test_multi_page_payout_stakers() { mock::make_all_reward_payment(i - 1); assert_eq_error_rate!( Balances::total_issuance(), - pre_payout_total_issuance + actual_paid_out, + pre_payout_total_issuance + payout, 2 ); assert!(RewardOnUnbalanceWasCalled::get()); From 63e03ce303e8826d75e128832737bd169367591f Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 23:22:47 +0100 Subject: [PATCH 053/131] fmt --- frame/staking/src/pallet/mod.rs | 15 +++++++-------- frame/staking/src/tests.rs | 6 +----- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 901bc1fbf6ac7..cb41569766243 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -701,9 +701,9 @@ pub mod pallet { /// Creates an entry to track validator reward has been claimed for a given era and page. pub(crate) fn set_rewards_as_claimed( - era: EraIndex, - validator: &T::AccountId, - page: PageIndex, + era: EraIndex, + validator: &T::AccountId, + page: PageIndex, ) { ClaimedRewards::::mutate(era, validator, |pages| { pages.push(page); @@ -712,14 +712,14 @@ pub mod pallet { /// Store exposure for elected validators at start of an era. pub(crate) fn set_validator_exposure( - era: EraIndex, - validator: &T::AccountId, - exposure: Exposure>, + era: EraIndex, + validator: &T::AccountId, + exposure: Exposure>, ) { >::insert(era, &validator, &exposure); let (exposure_overview, exposure_pages) = - exposure.as_pages(T::MaxNominatorRewardedPerPage::get()); + exposure.as_pages(T::MaxNominatorRewardedPerPage::get()); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { @@ -731,7 +731,6 @@ pub mod pallet { pub(crate) fn set_total_stake(era: EraIndex, total_stake: BalanceOf) { >::insert(era, total_stake); } - } /// Indices of validators that have offended in the active era and whether they are currently diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index fa68479cd1054..842a993743a22 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3802,11 +3802,7 @@ fn test_multi_page_payout_stakers() { assert_eq!(Balances::free_balance(&10), controller_balance_after_p0_payout); // verify all rewards have been paid out - assert_eq_error_rate!( - Balances::total_issuance(), - pre_payout_total_issuance + payout, - 2 - ); + assert_eq_error_rate!(Balances::total_issuance(), pre_payout_total_issuance + payout, 2); assert!(RewardOnUnbalanceWasCalled::get()); // verify all nominators of validator 11 are paid out, including the validator From 052ed04825384f05b7cbc9a868204ccf8063ff3a Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 23:40:48 +0100 Subject: [PATCH 054/131] fix rustdoc --- frame/staking/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 6d136a8aed4cd..3f05a9b8340a8 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -228,8 +228,8 @@ //! validator, proportional to the value staked behind the validator (_i.e._ dividing the //! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in //! [`Exposure`]). Note that payouts are made in pages with each page capped at -//! [`T::MaxNominatorRewardedPerPage`] nominators. The distribution of nominators across pages are -//! unsorted and depends on the election result provided by [`T::ElectionProvider`]. +//! [`Config::MaxNominatorRewardedPerPage`] nominators. The distribution of nominators across pages are +//! unsorted and depends on the election result provided by [`Config::ElectionProvider`]. //! //! All entities who receive a reward have the option to choose their reward destination through the //! [`Payee`] storage item (see From db1aa464940e9e76d2b7d8af2fa507400e308dfd Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 23 Jan 2023 23:47:47 +0100 Subject: [PATCH 055/131] fmt --- frame/staking/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3f05a9b8340a8..9d366ada04908 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -228,8 +228,8 @@ //! validator, proportional to the value staked behind the validator (_i.e._ dividing the //! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in //! [`Exposure`]). Note that payouts are made in pages with each page capped at -//! [`Config::MaxNominatorRewardedPerPage`] nominators. The distribution of nominators across pages are -//! unsorted and depends on the election result provided by [`Config::ElectionProvider`]. +//! [`Config::MaxNominatorRewardedPerPage`] nominators. The distribution of nominators across pages +//! are unsorted and depends on the election result provided by [`Config::ElectionProvider`]. //! //! All entities who receive a reward have the option to choose their reward destination through the //! [`Payee`] storage item (see From 6089eb5f8c521305834f07c6a06425350a97a6af Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Mon, 23 Jan 2023 23:46:29 +0000 Subject: [PATCH 056/131] ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_staking --- frame/staking/src/weights.rs | 415 +++++++++++++++++++---------------- 1 file changed, 226 insertions(+), 189 deletions(-) diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index afb4fc0df6b68..dea9175460e0a 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -89,8 +89,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Minimum execution time: 51_611 nanoseconds. - Weight::from_ref_time(52_566_000) + // Minimum execution time: 51_815 nanoseconds. + Weight::from_ref_time(52_367_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -100,8 +100,8 @@ impl WeightInfo for SubstrateWeight { // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Minimum execution time: 92_297 nanoseconds. - Weight::from_ref_time(93_016_000) + // Minimum execution time: 91_792 nanoseconds. + Weight::from_ref_time(92_729_000) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -115,8 +115,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Minimum execution time: 98_447 nanoseconds. - Weight::from_ref_time(99_317_000) + // Minimum execution time: 97_647 nanoseconds. + Weight::from_ref_time(98_731_000) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(8)) } @@ -126,10 +126,10 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 45_142 nanoseconds. - Weight::from_ref_time(46_003_517) - // Standard Error: 564 - .saturating_add(Weight::from_ref_time(60_400).saturating_mul(s.into())) + // Minimum execution time: 44_744 nanoseconds. + Weight::from_ref_time(45_658_968) + // Standard Error: 692 + .saturating_add(Weight::from_ref_time(65_958).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -149,10 +149,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 86_176 nanoseconds. - Weight::from_ref_time(91_591_693) - // Standard Error: 2_162 - .saturating_add(Weight::from_ref_time(1_089_160).saturating_mul(s.into())) + // Minimum execution time: 86_013 nanoseconds. + Weight::from_ref_time(91_544_236) + // Standard Error: 2_273 + .saturating_add(Weight::from_ref_time(1_073_291).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13)) .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -169,8 +169,8 @@ impl WeightInfo for SubstrateWeight { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Minimum execution time: 65_754 nanoseconds. - Weight::from_ref_time(66_793_000) + // Minimum execution time: 66_579 nanoseconds. + Weight::from_ref_time(67_026_000) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -178,10 +178,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 44_020 nanoseconds. - Weight::from_ref_time(41_692_773) - // Standard Error: 12_148 - .saturating_add(Weight::from_ref_time(7_092_259).saturating_mul(k.into())) + // Minimum execution time: 40_716 nanoseconds. + Weight::from_ref_time(43_678_932) + // Standard Error: 15_099 + .saturating_add(Weight::from_ref_time(6_814_991).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -199,10 +199,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 72_131 nanoseconds. - Weight::from_ref_time(71_703_530) - // Standard Error: 6_947 - .saturating_add(Weight::from_ref_time(2_757_165).saturating_mul(n.into())) + // Minimum execution time: 71_258 nanoseconds. + Weight::from_ref_time(70_901_125) + // Standard Error: 6_183 + .saturating_add(Weight::from_ref_time(2_777_341).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(6)) @@ -215,58 +215,58 @@ impl WeightInfo for SubstrateWeight { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 66_151 nanoseconds. - Weight::from_ref_time(66_596_000) + // Minimum execution time: 66_052 nanoseconds. + Weight::from_ref_time(66_480_000) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Minimum execution time: 17_305 nanoseconds. - Weight::from_ref_time(17_506_000) + // Minimum execution time: 18_008 nanoseconds. + Weight::from_ref_time(18_360_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Minimum execution time: 24_482 nanoseconds. - Weight::from_ref_time(25_101_000) + // Minimum execution time: 25_979 nanoseconds. + Weight::from_ref_time(26_350_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Minimum execution time: 5_100 nanoseconds. - Weight::from_ref_time(5_274_000) + // Minimum execution time: 5_009 nanoseconds. + Weight::from_ref_time(5_248_000) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Minimum execution time: 19_788 nanoseconds. - Weight::from_ref_time(20_313_000) + // Minimum execution time: 19_493 nanoseconds. + Weight::from_ref_time(19_888_000) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Minimum execution time: 19_499 nanoseconds. - Weight::from_ref_time(19_987_000) + // Minimum execution time: 19_425 nanoseconds. + Weight::from_ref_time(19_991_000) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Minimum execution time: 19_846 nanoseconds. - Weight::from_ref_time(20_127_000) + // Minimum execution time: 19_690 nanoseconds. + Weight::from_ref_time(20_010_000) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 5_301 nanoseconds. - Weight::from_ref_time(6_147_935) - // Standard Error: 32 - .saturating_add(Weight::from_ref_time(10_076).saturating_mul(v.into())) + // Minimum execution time: 5_375 nanoseconds. + Weight::from_ref_time(6_217_068) + // Standard Error: 43 + .saturating_add(Weight::from_ref_time(9_885).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) @@ -284,10 +284,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 79_381 nanoseconds. - Weight::from_ref_time(85_216_285) - // Standard Error: 2_681 - .saturating_add(Weight::from_ref_time(1_100_353).saturating_mul(s.into())) + // Minimum execution time: 79_630 nanoseconds. + Weight::from_ref_time(85_354_738) + // Standard Error: 2_555 + .saturating_add(Weight::from_ref_time(1_086_827).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -295,10 +295,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 92_049 nanoseconds. - Weight::from_ref_time(894_164_159) - // Standard Error: 58_104 - .saturating_add(Weight::from_ref_time(4_961_170).saturating_mul(s.into())) + // Minimum execution time: 92_209 nanoseconds. + Weight::from_ref_time(901_022_610) + // Standard Error: 59_320 + .saturating_add(Weight::from_ref_time(4_943_518).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -316,10 +316,10 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 134_548 nanoseconds. - Weight::from_ref_time(195_909_318) - // Standard Error: 17_825 - .saturating_add(Weight::from_ref_time(22_179_182).saturating_mul(n.into())) + // Minimum execution time: 134_323 nanoseconds. + Weight::from_ref_time(200_066_020) + // Standard Error: 16_654 + .saturating_add(Weight::from_ref_time(21_841_097).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(3)) @@ -340,17 +340,36 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 167_574 nanoseconds. - Weight::from_ref_time(232_044_473) - // Standard Error: 25_865 - .saturating_add(Weight::from_ref_time(31_272_789).saturating_mul(n.into())) + // Minimum execution time: 166_885 nanoseconds. + Weight::from_ref_time(231_648_127) + // Standard Error: 30_392 + .saturating_add(Weight::from_ref_time(30_760_443).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } - fn payout_stakers_nominators_only(n: u32, ) -> Weight { - Weight::from_ref_time(n.into()) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking ErasStakersOverview (r:1 w:0) + // Storage: Staking ErasValidatorReward (r:1 w:0) + // Storage: Staking Bonded (r:2 w:0) + // Storage: Staking Ledger (r:2 w:2) + // Storage: Staking ClaimedRewards (r:1 w:1) + // Storage: Staking ErasStakersPaged (r:1 w:0) + // Storage: Staking ErasRewardPoints (r:1 w:0) + // Storage: Staking Payee (r:2 w:0) + // Storage: Balances Locks (r:2 w:2) + // Storage: System Account (r:2 w:2) + /// The range of component `n` is `[1, 256]`. + fn payout_stakers_nominators_only(n: u32, ) -> Weight { + // Minimum execution time: 272_243 nanoseconds. + Weight::from_ref_time(228_003_618) + // Standard Error: 35_442 + .saturating_add(Weight::from_ref_time(34_057_392).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -360,10 +379,10 @@ impl WeightInfo for SubstrateWeight { // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 91_739 nanoseconds. - Weight::from_ref_time(93_123_333) - // Standard Error: 3_580 - .saturating_add(Weight::from_ref_time(69_425).saturating_mul(l.into())) + // Minimum execution time: 92_462 nanoseconds. + Weight::from_ref_time(93_684_047) + // Standard Error: 2_000 + .saturating_add(Weight::from_ref_time(51_643).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(8)) } @@ -382,10 +401,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 90_792 nanoseconds. - Weight::from_ref_time(93_893_087) - // Standard Error: 4_158 - .saturating_add(Weight::from_ref_time(1_084_858).saturating_mul(s.into())) + // Minimum execution time: 92_003 nanoseconds. + Weight::from_ref_time(93_936_550) + // Standard Error: 2_091 + .saturating_add(Weight::from_ref_time(1_088_847).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -411,12 +430,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 506_210 nanoseconds. - Weight::from_ref_time(508_476_000) - // Standard Error: 1_787_036 - .saturating_add(Weight::from_ref_time(60_417_557).saturating_mul(v.into())) - // Standard Error: 178_068 - .saturating_add(Weight::from_ref_time(13_499_037).saturating_mul(n.into())) + // Minimum execution time: 504_224 nanoseconds. + Weight::from_ref_time(506_290_000) + // Standard Error: 1_802_746 + .saturating_add(Weight::from_ref_time(60_725_475).saturating_mul(v.into())) + // Standard Error: 179_633 + .saturating_add(Weight::from_ref_time(13_820_500).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(206)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -434,12 +453,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 24_070_794 nanoseconds. - Weight::from_ref_time(24_294_007_000) - // Standard Error: 322_618 - .saturating_add(Weight::from_ref_time(3_570_673).saturating_mul(v.into())) - // Standard Error: 322_618 - .saturating_add(Weight::from_ref_time(2_900_021).saturating_mul(n.into())) + // Minimum execution time: 24_224_895 nanoseconds. + Weight::from_ref_time(24_374_544_000) + // Standard Error: 319_103 + .saturating_add(Weight::from_ref_time(3_422_743).saturating_mul(v.into())) + // Standard Error: 319_103 + .saturating_add(Weight::from_ref_time(2_914_359).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(201)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -449,10 +468,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Validators (r:501 w:0) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 4_776_351 nanoseconds. - Weight::from_ref_time(4_849_553_000) - // Standard Error: 55_132 - .saturating_add(Weight::from_ref_time(3_604_980).saturating_mul(v.into())) + // Minimum execution time: 4_765_318 nanoseconds. + Weight::from_ref_time(4_816_708_000) + // Standard Error: 54_677 + .saturating_add(Weight::from_ref_time(3_541_818).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) } @@ -463,8 +482,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 10_781 nanoseconds. - Weight::from_ref_time(11_034_000) + // Minimum execution time: 10_480 nanoseconds. + Weight::from_ref_time(10_914_000) .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:0 w:1) @@ -474,8 +493,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 9_418 nanoseconds. - Weight::from_ref_time(10_150_000) + // Minimum execution time: 9_529 nanoseconds. + Weight::from_ref_time(10_159_000) .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) @@ -489,23 +508,23 @@ impl WeightInfo for SubstrateWeight { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Minimum execution time: 82_590 nanoseconds. - Weight::from_ref_time(83_718_000) + // Minimum execution time: 81_347 nanoseconds. + Weight::from_ref_time(81_957_000) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 19_367 nanoseconds. - Weight::from_ref_time(19_668_000) + // Minimum execution time: 19_153 nanoseconds. + Weight::from_ref_time(19_621_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking MinCommission (r:0 w:1) fn set_min_commission() -> Weight { - // Minimum execution time: 6_107 nanoseconds. - Weight::from_ref_time(6_449_000) + // Minimum execution time: 6_058 nanoseconds. + Weight::from_ref_time(6_278_000) .saturating_add(T::DbWeight::get().writes(1)) } } @@ -517,8 +536,8 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Minimum execution time: 51_611 nanoseconds. - Weight::from_ref_time(52_566_000) + // Minimum execution time: 51_815 nanoseconds. + Weight::from_ref_time(52_367_000) .saturating_add(RocksDbWeight::get().reads(3)) .saturating_add(RocksDbWeight::get().writes(4)) } @@ -528,8 +547,8 @@ impl WeightInfo for () { // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Minimum execution time: 92_297 nanoseconds. - Weight::from_ref_time(93_016_000) + // Minimum execution time: 91_792 nanoseconds. + Weight::from_ref_time(92_729_000) .saturating_add(RocksDbWeight::get().reads(8)) .saturating_add(RocksDbWeight::get().writes(7)) } @@ -543,8 +562,8 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Minimum execution time: 98_447 nanoseconds. - Weight::from_ref_time(99_317_000) + // Minimum execution time: 97_647 nanoseconds. + Weight::from_ref_time(98_731_000) .saturating_add(RocksDbWeight::get().reads(12)) .saturating_add(RocksDbWeight::get().writes(8)) } @@ -554,10 +573,10 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 45_142 nanoseconds. - Weight::from_ref_time(46_003_517) - // Standard Error: 564 - .saturating_add(Weight::from_ref_time(60_400).saturating_mul(s.into())) + // Minimum execution time: 44_744 nanoseconds. + Weight::from_ref_time(45_658_968) + // Standard Error: 692 + .saturating_add(Weight::from_ref_time(65_958).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4)) .saturating_add(RocksDbWeight::get().writes(3)) } @@ -577,10 +596,10 @@ impl WeightInfo for () { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 86_176 nanoseconds. - Weight::from_ref_time(91_591_693) - // Standard Error: 2_162 - .saturating_add(Weight::from_ref_time(1_089_160).saturating_mul(s.into())) + // Minimum execution time: 86_013 nanoseconds. + Weight::from_ref_time(91_544_236) + // Standard Error: 2_273 + .saturating_add(Weight::from_ref_time(1_073_291).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13)) .saturating_add(RocksDbWeight::get().writes(12)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -597,8 +616,8 @@ impl WeightInfo for () { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Minimum execution time: 65_754 nanoseconds. - Weight::from_ref_time(66_793_000) + // Minimum execution time: 66_579 nanoseconds. + Weight::from_ref_time(67_026_000) .saturating_add(RocksDbWeight::get().reads(11)) .saturating_add(RocksDbWeight::get().writes(5)) } @@ -606,10 +625,10 @@ impl WeightInfo for () { // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 44_020 nanoseconds. - Weight::from_ref_time(41_692_773) - // Standard Error: 12_148 - .saturating_add(Weight::from_ref_time(7_092_259).saturating_mul(k.into())) + // Minimum execution time: 40_716 nanoseconds. + Weight::from_ref_time(43_678_932) + // Standard Error: 15_099 + .saturating_add(Weight::from_ref_time(6_814_991).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -627,10 +646,10 @@ impl WeightInfo for () { // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 72_131 nanoseconds. - Weight::from_ref_time(71_703_530) - // Standard Error: 6_947 - .saturating_add(Weight::from_ref_time(2_757_165).saturating_mul(n.into())) + // Minimum execution time: 71_258 nanoseconds. + Weight::from_ref_time(70_901_125) + // Standard Error: 6_183 + .saturating_add(Weight::from_ref_time(2_777_341).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(6)) @@ -643,58 +662,58 @@ impl WeightInfo for () { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 66_151 nanoseconds. - Weight::from_ref_time(66_596_000) + // Minimum execution time: 66_052 nanoseconds. + Weight::from_ref_time(66_480_000) .saturating_add(RocksDbWeight::get().reads(8)) .saturating_add(RocksDbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Minimum execution time: 17_305 nanoseconds. - Weight::from_ref_time(17_506_000) + // Minimum execution time: 18_008 nanoseconds. + Weight::from_ref_time(18_360_000) .saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Minimum execution time: 24_482 nanoseconds. - Weight::from_ref_time(25_101_000) + // Minimum execution time: 25_979 nanoseconds. + Weight::from_ref_time(26_350_000) .saturating_add(RocksDbWeight::get().reads(3)) .saturating_add(RocksDbWeight::get().writes(3)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Minimum execution time: 5_100 nanoseconds. - Weight::from_ref_time(5_274_000) + // Minimum execution time: 5_009 nanoseconds. + Weight::from_ref_time(5_248_000) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Minimum execution time: 19_788 nanoseconds. - Weight::from_ref_time(20_313_000) + // Minimum execution time: 19_493 nanoseconds. + Weight::from_ref_time(19_888_000) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Minimum execution time: 19_499 nanoseconds. - Weight::from_ref_time(19_987_000) + // Minimum execution time: 19_425 nanoseconds. + Weight::from_ref_time(19_991_000) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Minimum execution time: 19_846 nanoseconds. - Weight::from_ref_time(20_127_000) + // Minimum execution time: 19_690 nanoseconds. + Weight::from_ref_time(20_010_000) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 5_301 nanoseconds. - Weight::from_ref_time(6_147_935) - // Standard Error: 32 - .saturating_add(Weight::from_ref_time(10_076).saturating_mul(v.into())) + // Minimum execution time: 5_375 nanoseconds. + Weight::from_ref_time(6_217_068) + // Standard Error: 43 + .saturating_add(Weight::from_ref_time(9_885).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) @@ -712,10 +731,10 @@ impl WeightInfo for () { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 79_381 nanoseconds. - Weight::from_ref_time(85_216_285) - // Standard Error: 2_681 - .saturating_add(Weight::from_ref_time(1_100_353).saturating_mul(s.into())) + // Minimum execution time: 79_630 nanoseconds. + Weight::from_ref_time(85_354_738) + // Standard Error: 2_555 + .saturating_add(Weight::from_ref_time(1_086_827).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(11)) .saturating_add(RocksDbWeight::get().writes(12)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -723,10 +742,10 @@ impl WeightInfo for () { // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 92_049 nanoseconds. - Weight::from_ref_time(894_164_159) - // Standard Error: 58_104 - .saturating_add(Weight::from_ref_time(4_961_170).saturating_mul(s.into())) + // Minimum execution time: 92_209 nanoseconds. + Weight::from_ref_time(901_022_610) + // Standard Error: 59_320 + .saturating_add(Weight::from_ref_time(4_943_518).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().writes(1)) } @@ -744,10 +763,10 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 134_548 nanoseconds. - Weight::from_ref_time(195_909_318) - // Standard Error: 17_825 - .saturating_add(Weight::from_ref_time(22_179_182).saturating_mul(n.into())) + // Minimum execution time: 134_323 nanoseconds. + Weight::from_ref_time(200_066_020) + // Standard Error: 16_654 + .saturating_add(Weight::from_ref_time(21_841_097).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(3)) @@ -768,18 +787,36 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) /// The range of component `n` is `[0, 256]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 167_574 nanoseconds. - Weight::from_ref_time(232_044_473) - // Standard Error: 25_865 - .saturating_add(Weight::from_ref_time(31_272_789).saturating_mul(n.into())) + // Minimum execution time: 166_885 nanoseconds. + Weight::from_ref_time(231_648_127) + // Standard Error: 30_392 + .saturating_add(Weight::from_ref_time(30_760_443).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(4)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) } - fn payout_stakers_nominators_only(n: u32, ) -> Weight { - // Minimum execution time: 164_719 nanoseconds. - Weight::from_ref_time(n.into()) + // Storage: Staking CurrentEra (r:1 w:0) + // Storage: Staking ErasStakersOverview (r:1 w:0) + // Storage: Staking ErasValidatorReward (r:1 w:0) + // Storage: Staking Bonded (r:2 w:0) + // Storage: Staking Ledger (r:2 w:2) + // Storage: Staking ClaimedRewards (r:1 w:1) + // Storage: Staking ErasStakersPaged (r:1 w:0) + // Storage: Staking ErasRewardPoints (r:1 w:0) + // Storage: Staking Payee (r:2 w:0) + // Storage: Balances Locks (r:2 w:2) + // Storage: System Account (r:2 w:2) + /// The range of component `n` is `[1, 256]`. + fn payout_stakers_nominators_only(n: u32, ) -> Weight { + // Minimum execution time: 272_243 nanoseconds. + Weight::from_ref_time(228_003_618) + // Standard Error: 35_442 + .saturating_add(Weight::from_ref_time(34_057_392).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11)) + .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes(4)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -789,10 +826,10 @@ impl WeightInfo for () { // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 91_739 nanoseconds. - Weight::from_ref_time(93_123_333) - // Standard Error: 3_580 - .saturating_add(Weight::from_ref_time(69_425).saturating_mul(l.into())) + // Minimum execution time: 92_462 nanoseconds. + Weight::from_ref_time(93_684_047) + // Standard Error: 2_000 + .saturating_add(Weight::from_ref_time(51_643).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(9)) .saturating_add(RocksDbWeight::get().writes(8)) } @@ -811,10 +848,10 @@ impl WeightInfo for () { // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 90_792 nanoseconds. - Weight::from_ref_time(93_893_087) - // Standard Error: 4_158 - .saturating_add(Weight::from_ref_time(1_084_858).saturating_mul(s.into())) + // Minimum execution time: 92_003 nanoseconds. + Weight::from_ref_time(93_936_550) + // Standard Error: 2_091 + .saturating_add(Weight::from_ref_time(1_088_847).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(12)) .saturating_add(RocksDbWeight::get().writes(12)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -840,12 +877,12 @@ impl WeightInfo for () { /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 506_210 nanoseconds. - Weight::from_ref_time(508_476_000) - // Standard Error: 1_787_036 - .saturating_add(Weight::from_ref_time(60_417_557).saturating_mul(v.into())) - // Standard Error: 178_068 - .saturating_add(Weight::from_ref_time(13_499_037).saturating_mul(n.into())) + // Minimum execution time: 504_224 nanoseconds. + Weight::from_ref_time(506_290_000) + // Standard Error: 1_802_746 + .saturating_add(Weight::from_ref_time(60_725_475).saturating_mul(v.into())) + // Standard Error: 179_633 + .saturating_add(Weight::from_ref_time(13_820_500).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(206)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -863,12 +900,12 @@ impl WeightInfo for () { /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 24_070_794 nanoseconds. - Weight::from_ref_time(24_294_007_000) - // Standard Error: 322_618 - .saturating_add(Weight::from_ref_time(3_570_673).saturating_mul(v.into())) - // Standard Error: 322_618 - .saturating_add(Weight::from_ref_time(2_900_021).saturating_mul(n.into())) + // Minimum execution time: 24_224_895 nanoseconds. + Weight::from_ref_time(24_374_544_000) + // Standard Error: 319_103 + .saturating_add(Weight::from_ref_time(3_422_743).saturating_mul(v.into())) + // Standard Error: 319_103 + .saturating_add(Weight::from_ref_time(2_914_359).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(201)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -878,10 +915,10 @@ impl WeightInfo for () { // Storage: Staking Validators (r:501 w:0) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 4_776_351 nanoseconds. - Weight::from_ref_time(4_849_553_000) - // Standard Error: 55_132 - .saturating_add(Weight::from_ref_time(3_604_980).saturating_mul(v.into())) + // Minimum execution time: 4_765_318 nanoseconds. + Weight::from_ref_time(4_816_708_000) + // Standard Error: 54_677 + .saturating_add(Weight::from_ref_time(3_541_818).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) } @@ -892,8 +929,8 @@ impl WeightInfo for () { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 10_781 nanoseconds. - Weight::from_ref_time(11_034_000) + // Minimum execution time: 10_480 nanoseconds. + Weight::from_ref_time(10_914_000) .saturating_add(RocksDbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:0 w:1) @@ -903,8 +940,8 @@ impl WeightInfo for () { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 9_418 nanoseconds. - Weight::from_ref_time(10_150_000) + // Minimum execution time: 9_529 nanoseconds. + Weight::from_ref_time(10_159_000) .saturating_add(RocksDbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) @@ -918,23 +955,23 @@ impl WeightInfo for () { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Minimum execution time: 82_590 nanoseconds. - Weight::from_ref_time(83_718_000) + // Minimum execution time: 81_347 nanoseconds. + Weight::from_ref_time(81_957_000) .saturating_add(RocksDbWeight::get().reads(11)) .saturating_add(RocksDbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 19_367 nanoseconds. - Weight::from_ref_time(19_668_000) + // Minimum execution time: 19_153 nanoseconds. + Weight::from_ref_time(19_621_000) .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: Staking MinCommission (r:0 w:1) fn set_min_commission() -> Weight { - // Minimum execution time: 6_107 nanoseconds. - Weight::from_ref_time(6_449_000) + // Minimum execution time: 6_058 nanoseconds. + Weight::from_ref_time(6_278_000) .saturating_add(RocksDbWeight::get().writes(1)) } } From 2d9994f226c47d671ff9eed994ec510fcdbe298d Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 24 Jan 2023 00:01:21 +0100 Subject: [PATCH 057/131] fix rust doc --- frame/staking/src/pallet/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index cb41569766243..378979d50b9f7 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -205,7 +205,7 @@ pub mod pallet { /// /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerPage` nominators /// in a single call. This used to limit the i/o cost for the nominator payout. - /// See [`payout_stakers`] for more details. + /// See call `payout_stakers` for more details. #[pallet::constant] type MaxNominatorRewardedPerPage: Get; From de4a5298a559d66e42b006893ccdb04defcc4057 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 20:48:28 +0100 Subject: [PATCH 058/131] handles errors --- frame/staking/src/tests.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 842a993743a22..7d9a85164d783 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3999,15 +3999,35 @@ fn payout_stakers_handles_basic_errors() { 0 )); + // can call page 1 + assert_ok!(Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + expected_last_reward_era, + 1 + )); + // Can't claim again assert_noop!( Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_start_reward_era, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); + assert_noop!( Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); + + assert_noop!( + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 1), + Error::::AlreadyClaimed.with_weight(err_weight) + ); + + // invalid page + assert_noop!( + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 2), + Error::::InvalidPage.with_weight(err_weight) + ); }); } From cc825419084a50f1e7e5a20eb4cc320419d91ee5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 21:02:11 +0100 Subject: [PATCH 059/131] commission test --- frame/staking/src/pallet/mod.rs | 1 - frame/staking/src/tests.rs | 54 +++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 378979d50b9f7..6765bfb989634 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -684,7 +684,6 @@ pub mod pallet { >::get(&era, validator).page_count.max(1) } - // TODO(ank4n) add commission should only be paid in page 0 test /// Returns validator commission for this era and page. pub(crate) fn get_validator_commission( era: EraIndex, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 7d9a85164d783..9fce758c93b16 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3740,8 +3740,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { #[test] fn test_multi_page_payout_stakers() { - // Test that payout_stakers work in general, including that only the top - // `T::MaxNominatorRewardedPerPage` nominators are rewarded. + // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { let balance = 1000; // Track the exposure of the validator and all nominators. @@ -4031,6 +4030,57 @@ fn payout_stakers_handles_basic_errors() { }); } +#[test] +fn test_commission_paid_only_once() { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + let balance = 1; + let commission = 50; + // Create a validator: + bond_validator(11, 10, balance); + assert_ok!(Staking::validate( + RuntimeOrigin::signed(10), + ValidatorPrefs { commission: Perbill::from_percent(commission), blocked: false } + )); + assert_eq!(Validators::::count(), 1); + + // Create nominators, targeting stash of validators + for i in 0..200 { + let bond_amount = balance + i as Balance; + bond_nominator(1000 + i, 100 + i, bond_amount, vec![11]); + } + + mock::start_active_era(1); + Staking::reward_by_ids(vec![(11, 1)]); + + // Since `MaxNominatorRewardedPerPage = 64`, there are four pages of validator exposure. + assert_eq!(EraInfo::::get_page_count(1, &11), 4); + + // compute and ensure the reward amount is greater than zero. + let payout = current_total_payout_for_duration(reward_time_per_era()); + mock::start_active_era(2); + + let controller_balance_before_p0_payout = Balances::free_balance(&10); + // Payout rewards for first exposure page + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + + let controller_balance_after_p0_payout = Balances::free_balance(&10); + + // half of the payout goes to validator since commission is 50% + assert_eq_error_rate!( + controller_balance_after_p0_payout, + controller_balance_before_p0_payout + payout / 2, + 1, + ); + + for i in 1..4 { + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, i)); + // no reward paid to validator for pages other than 0 + Balances::free_balance(&10); + } + + }); +} + #[test] fn payout_stakers_handles_weight_refund() { // Note: this test relies on the assumption that `payout_stakers_alive_staked` is solely used by From 66dfdc5563b3c603a491eee46e24d3ed8c8c75d2 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 21:07:09 +0100 Subject: [PATCH 060/131] some things to discuss --- frame/staking/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 9d366ada04908..6b45e7f0c403f 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -803,6 +803,8 @@ pub struct ExposureOverview { pub nominator_count: u32, /// Number of pages of backers. pub page_count: PageIndex, + // TODO(ank4n): to discuss: should we keep a snapshot of validator commission for each era? + // Seems more fair to calculate rewards according to validator's commission at that era. } impl Default for ExposureOverview { From f5fa2dd15cc5ce297bf324ef378560627eda045d Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 21:26:54 +0100 Subject: [PATCH 061/131] try state checks --- frame/staking/src/pallet/impls.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index b619499053c7c..69f02faa9cf79 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1730,9 +1730,12 @@ impl Pallet { fn check_exposures() -> Result<(), &'static str> { // a check per validator to ensure the exposure struct is always sane. + // FIXME(ank4n): This will fail before the code goes live, so probably add this change after + // being in production? Not sure how to test this nicely. Ideally could run it for a while + // on a test chain and make sure this is correct before going to production. let era = Self::active_era().unwrap().index; - ErasStakers::::iter_prefix_values(era) - .map(|expo| { + ErasStakers::::iter_prefix(era) + .map(|key, expo| { ensure!( expo.total == expo.own + @@ -1742,6 +1745,25 @@ impl Pallet { .fold(Zero::zero(), |acc, x| acc + x), "wrong total exposure.", ); + // look at exposure pages + let mut total = Zero::zero(); + let mut own = Zero::zero(); + let page_count = EraInfo::::get_page_count(era, key); + for page in 0..page_count { + let page = EraInfo::::get_page(era, key, page); + let paged_exposure = EraInfo::::get_validator_exposure(era, key, page); + ensure!(paged_exposure.total == expo.total, "wrong total exposure in page."); + own += paged_exposure.own; + total = paged_exposure.own + + paged_exposure + .others + .iter() + .map(|e| e.value) + .fold(Zero::zero(), |acc, x| acc + x); + } + ensure!(total == expo.total, "wrong total exposure in pages."); + ensure!(own == expo.own, "wrong own exposure in pages."); + Ok(()) }) .collect::>() From 702d1bb114c7a31183f15ff28ed0f21ca2fca784 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 21:29:52 +0100 Subject: [PATCH 062/131] fmt --- frame/staking/src/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 9fce758c93b16..c14633c4073a6 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4077,7 +4077,6 @@ fn test_commission_paid_only_once() { // no reward paid to validator for pages other than 0 Balances::free_balance(&10); } - }); } From 519fe2c7b919ea239ff060e2040009e2a1c1ecef Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 21:39:29 +0100 Subject: [PATCH 063/131] Revert "try state checks" This reverts commit 455294b52637c8b4b29bd3fe1d734763009b7985. --- frame/staking/src/pallet/impls.rs | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 69f02faa9cf79..b619499053c7c 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1730,12 +1730,9 @@ impl Pallet { fn check_exposures() -> Result<(), &'static str> { // a check per validator to ensure the exposure struct is always sane. - // FIXME(ank4n): This will fail before the code goes live, so probably add this change after - // being in production? Not sure how to test this nicely. Ideally could run it for a while - // on a test chain and make sure this is correct before going to production. let era = Self::active_era().unwrap().index; - ErasStakers::::iter_prefix(era) - .map(|key, expo| { + ErasStakers::::iter_prefix_values(era) + .map(|expo| { ensure!( expo.total == expo.own + @@ -1745,25 +1742,6 @@ impl Pallet { .fold(Zero::zero(), |acc, x| acc + x), "wrong total exposure.", ); - // look at exposure pages - let mut total = Zero::zero(); - let mut own = Zero::zero(); - let page_count = EraInfo::::get_page_count(era, key); - for page in 0..page_count { - let page = EraInfo::::get_page(era, key, page); - let paged_exposure = EraInfo::::get_validator_exposure(era, key, page); - ensure!(paged_exposure.total == expo.total, "wrong total exposure in page."); - own += paged_exposure.own; - total = paged_exposure.own + - paged_exposure - .others - .iter() - .map(|e| e.value) - .fold(Zero::zero(), |acc, x| acc + x); - } - ensure!(total == expo.total, "wrong total exposure in pages."); - ensure!(own == expo.own, "wrong own exposure in pages."); - Ok(()) }) .collect::>() From 327ceb630dd35aef7a96816f8e0ecb60d8dc8bec Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 25 Jan 2023 21:46:01 +0100 Subject: [PATCH 064/131] cleanup era overview in history depth eras --- frame/staking/src/pallet/impls.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index b619499053c7c..9b824b06a2786 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -676,6 +676,8 @@ impl Pallet { >::remove_prefix(era_index, None); #[allow(deprecated)] >::remove_prefix(era_index, None); + #[allow(deprecated)] + >::remove_prefix(era_index, None); >::remove(era_index); >::remove(era_index); From 5bffaa25c40232fb0bf2622d5c60022b26d6a765 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 28 Jan 2023 22:17:18 +0100 Subject: [PATCH 065/131] todos --- frame/staking/src/lib.rs | 2 -- frame/staking/src/pallet/mod.rs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 6b45e7f0c403f..9d366ada04908 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -803,8 +803,6 @@ pub struct ExposureOverview { pub nominator_count: u32, /// Number of pages of backers. pub page_count: PageIndex, - // TODO(ank4n): to discuss: should we keep a snapshot of validator commission for each era? - // Seems more fair to calculate rewards according to validator's commission at that era. } impl Default for ExposureOverview { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 6765bfb989634..709c8fa148ca1 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -206,6 +206,7 @@ pub mod pallet { /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerPage` nominators /// in a single call. This used to limit the i/o cost for the nominator payout. /// See call `payout_stakers` for more details. + /// // TODO(ank4n) keep old one and create new one. #[pallet::constant] type MaxNominatorRewardedPerPage: Get; From e59f6583ddef9d9008802e73d0346f4d40256788 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 31 Jan 2023 14:19:58 +0100 Subject: [PATCH 066/131] remove store --- frame/staking/src/tests.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index c14633c4073a6..1b0b02b939bc1 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2444,7 +2444,7 @@ fn slash_in_old_span_does_not_deselect() { ); // the validator doesn't get chilled again - assert!(::Validators::iter().any(|(stash, _)| stash == 11)); + assert!(Validators::::iter().any(|(stash, _)| stash == 11)); // but we are still forcing a new era assert_eq!(Staking::force_era(), Forcing::ForceNew); @@ -2461,7 +2461,7 @@ fn slash_in_old_span_does_not_deselect() { ); // the validator doesn't get chilled again - assert!(::Validators::iter().any(|(stash, _)| stash == 11)); + assert!(Validators::::iter().any(|(stash, _)| stash == 11)); // but it's disabled assert!(is_disabled(10)); @@ -3204,7 +3204,7 @@ fn remove_multi_deferred() { &[Perbill::from_percent(25)], ); - assert_eq!(::UnappliedSlashes::get(&4).len(), 5); + assert_eq!(UnappliedSlashes::::get(&4).len(), 5); // fails if list is not sorted assert_noop!( @@ -3224,7 +3224,7 @@ fn remove_multi_deferred() { assert_ok!(Staking::cancel_deferred_slash(RuntimeOrigin::root(), 4, vec![0, 2, 4])); - let slashes = ::UnappliedSlashes::get(&4); + let slashes = UnappliedSlashes::::get(&4); assert_eq!(slashes.len(), 2); assert_eq!(slashes[0].validator, 21); assert_eq!(slashes[1].validator, 42); @@ -3279,7 +3279,7 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid assert_eq!(Balances::free_balance(101), 2000 - nominator_slash_amount_11); // check that validator was chilled. - assert!(::Validators::iter().all(|(stash, _)| stash != 11)); + assert!(Validators::::iter().all(|(stash, _)| stash != 11)); // actually re-bond the slashed validator assert_ok!(Staking::validate(RuntimeOrigin::signed(10), Default::default())); @@ -3625,7 +3625,7 @@ fn zero_slash_keeps_nominators() { assert_eq!(Balances::free_balance(101), 2000); // 11 is still removed.. - assert!(::Validators::iter().all(|(stash, _)| stash != 11)); + assert!(Validators::::iter().all(|(stash, _)| stash != 11)); // but their nominations are kept. assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); }); From 266ce384618f4e716412f89cc2230ebb4eb87c3c Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 31 Jan 2023 14:29:48 +0100 Subject: [PATCH 067/131] [Revert] keep the same name of page size --- bin/node/runtime/src/lib.rs | 4 +-- frame/babe/src/mock.rs | 2 +- frame/fast-unstake/src/mock.rs | 2 +- frame/grandpa/src/mock.rs | 2 +- .../nomination-pools/benchmarking/src/mock.rs | 2 +- .../nomination-pools/test-staking/src/mock.rs | 2 +- frame/offences/benchmarking/src/mock.rs | 2 +- frame/root-offences/src/mock.rs | 2 +- frame/session/benchmarking/src/mock.rs | 2 +- frame/staking/README.md | 2 +- frame/staking/src/benchmarking.rs | 20 ++++++------- frame/staking/src/lib.rs | 6 ++-- frame/staking/src/mock.rs | 4 +-- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 28 +++++++++---------- frame/staking/src/tests.rs | 14 ++++++---- 16 files changed, 49 insertions(+), 47 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 39edd41b3472e..f8589036f7853 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -538,7 +538,7 @@ parameter_types! { pub const BondingDuration: sp_staking::EraIndex = 24 * 28; pub const SlashDeferDuration: sp_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const MaxNominatorRewardedPerPage: u32 = 256; + pub const MaxNominatorRewardedPerValidator: u32 = 256; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); pub OffchainRepeat: BlockNumber = 5; pub HistoryDepth: u32 = 84; @@ -571,7 +571,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerPage = MaxNominatorRewardedPerPage; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainExecution; diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index fb9c5713920ca..b130677897883 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -192,7 +192,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index 175ba9af0e33c..b20ba43ab3758 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -146,7 +146,7 @@ impl pallet_staking::Config for Runtime { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); type HistoryDepth = ConstU32<84>; - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = MockElection; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index eadff6fd12b1b..a33fbb22d6ff8 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -196,7 +196,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/nomination-pools/benchmarking/src/mock.rs b/frame/nomination-pools/benchmarking/src/mock.rs index 8e59d3cd92b07..4e188ea7ef189 100644 --- a/frame/nomination-pools/benchmarking/src/mock.rs +++ b/frame/nomination-pools/benchmarking/src/mock.rs @@ -107,7 +107,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; diff --git a/frame/nomination-pools/test-staking/src/mock.rs b/frame/nomination-pools/test-staking/src/mock.rs index 51a65081efd31..3d0ab2c6f35f3 100644 --- a/frame/nomination-pools/test-staking/src/mock.rs +++ b/frame/nomination-pools/test-staking/src/mock.rs @@ -121,7 +121,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index bd6ca8650acfa..233aa449d391c 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -170,7 +170,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/root-offences/src/mock.rs b/frame/root-offences/src/mock.rs index 219a64cb284d6..0937c43d6e519 100644 --- a/frame/root-offences/src/mock.rs +++ b/frame/root-offences/src/mock.rs @@ -184,7 +184,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 517f0618531d2..4c4accbbfac8f 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -172,7 +172,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerPage = ConstU32<64>; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/README.md b/frame/staking/README.md index 094b102b38955..2958ecf8dc2fb 100644 --- a/frame/staking/README.md +++ b/frame/staking/README.md @@ -90,7 +90,7 @@ valid behavior_ while _punishing any misbehavior or lack of availability_. Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -validator as well as its nominators. Rewards are paged to maximum of [`Config::MaxNominatorRewardedPerPage`] +validator as well as its nominators. Rewards are paged to maximum of [`Config::MaxNominatorRewardedPerValidator`] nominators per call. Each page of staker payout needs to be called separately to ensure all nominators are paid. This is to limit the i/o cost to mutate storage for each nominator's account. diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 1e5296aa32db3..a2b24f391cdfd 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -546,10 +546,10 @@ benchmarks! { } payout_stakers_dead_controller { - let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; + let n in 0 .. T::MaxNominatorRewardedPerValidator::get() as u32; let (validator, nominators) = create_validator_with_nominators::( n, - T::MaxNominatorRewardedPerPage::get() as u32, + T::MaxNominatorRewardedPerValidator::get() as u32, true, RewardDestination::Controller, )?; @@ -579,10 +579,10 @@ benchmarks! { } payout_stakers_alive_staked { - let n in 0 .. T::MaxNominatorRewardedPerPage::get() as u32; + let n in 0 .. T::MaxNominatorRewardedPerValidator::get() as u32; let (validator, nominators) = create_validator_with_nominators::( n, - T::MaxNominatorRewardedPerPage::get() as u32, + T::MaxNominatorRewardedPerValidator::get() as u32, false, RewardDestination::Staked, )?; @@ -615,10 +615,10 @@ benchmarks! { } payout_stakers_nominators_only { - let n in 1 .. T::MaxNominatorRewardedPerPage::get() as u32; - // create nominators between MaxNominatorRewardedPerPage+1 .. =2 * MaxNominatorRewardedPerPage - let nominator_lower_bound = T::MaxNominatorRewardedPerPage::get(); - let nominator_upper_bound = 2 * T::MaxNominatorRewardedPerPage::get(); + let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32; + // create nominators between MaxNominatorRewardedPerValidator+1 .. =2 * MaxNominatorRewardedPerValidator + let nominator_lower_bound = T::MaxNominatorRewardedPerValidator::get(); + let nominator_upper_bound = 2 * T::MaxNominatorRewardedPerValidator::get(); let (validator, nominators) = create_validator_with_nominators::( nominator_lower_bound + n, @@ -1025,7 +1025,7 @@ mod tests { let (validator_stash, nominators) = create_validator_with_nominators::( n, - <::MaxNominatorRewardedPerPage as Get<_>>::get(), + <::MaxNominatorRewardedPerValidator as Get<_>>::get(), false, RewardDestination::Staked, ) @@ -1055,7 +1055,7 @@ mod tests { let (validator_stash, _nominators) = create_validator_with_nominators::( n, - <::MaxNominatorRewardedPerPage as Get<_>>::get(), + <::MaxNominatorRewardedPerValidator as Get<_>>::get(), false, RewardDestination::Staked, ) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 9d366ada04908..6ebe3c8fa6401 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -114,7 +114,7 @@ //! //! Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the //! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -//! validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerPage`] +//! validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerValidator`] //! biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each //! nominator's account. //! @@ -228,8 +228,8 @@ //! validator, proportional to the value staked behind the validator (_i.e._ dividing the //! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in //! [`Exposure`]). Note that payouts are made in pages with each page capped at -//! [`Config::MaxNominatorRewardedPerPage`] nominators. The distribution of nominators across pages -//! are unsorted and depends on the election result provided by [`Config::ElectionProvider`]. +//! [`Config::MaxNominatorRewardedPerValidator`] nominators. The distribution of nominators across +//! pages are unsorted and depends on the election result provided by [`Config::ElectionProvider`]. //! //! All entities who receive a reward have the option to choose their reward destination through the //! [`Payee`] storage item (see diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index a7904b95a790f..119fc71f2b4e5 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -230,7 +230,7 @@ parameter_types! { pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; pub static MaxNominations: u32 = 16; pub static HistoryDepth: u32 = 80; - pub static MaxNominatorRewardedPerPage: u32 = 64; + pub static MaxNominatorRewardedPerValidator: u32 = 64; pub static MaxUnlockingChunks: u32 = 32; pub static RewardOnUnbalanceWasCalled: bool = false; pub static LedgerSlashPerEra: (BalanceOf, BTreeMap>) = (Zero::zero(), BTreeMap::new()); @@ -293,7 +293,7 @@ impl crate::pallet::pallet::Config for Test { type SessionInterface = Self; type EraPayout = ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerPage = MaxNominatorRewardedPerPage; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 9b824b06a2786..39d36d3ba9dac 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -259,7 +259,7 @@ impl Pallet { } T::Reward::on_unbalanced(total_imbalance); - debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerPage::get()); + debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerValidator::get()); let payout_weight = if page == 0 { T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 709c8fa148ca1..1c09bd04d8eb8 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -203,12 +203,12 @@ pub mod pallet { /// The maximum number of nominators rewarded for each validator. /// - /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerPage` nominators - /// in a single call. This used to limit the i/o cost for the nominator payout. + /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerValidator` + /// nominators in a single call. This used to limit the i/o cost for the nominator payout. /// See call `payout_stakers` for more details. /// // TODO(ank4n) keep old one and create new one. #[pallet::constant] - type MaxNominatorRewardedPerPage: Get; + type MaxNominatorRewardedPerValidator: Get; /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. @@ -445,7 +445,7 @@ pub mod pallet { /// New `Exposure`s are stored in a paged manner in `ErasStakersPaged` instead. /// /// This is similar to [`ErasStakers`] but number of nominators exposed is reduced to the - /// `T::MaxNominatorRewardedPerPage` biggest stakers. + /// `T::MaxNominatorRewardedPerValidator` biggest stakers. /// (Note: the field `total` and `own` of the exposure remains unchanged). /// This is used to limit the i/o cost for the nominator payout. /// @@ -719,7 +719,7 @@ pub mod pallet { >::insert(era, &validator, &exposure); let (exposure_overview, exposure_pages) = - exposure.as_pages(T::MaxNominatorRewardedPerPage::get()); + exposure.as_pages(T::MaxNominatorRewardedPerValidator::get()); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { @@ -1637,21 +1637,21 @@ pub mod pallet { /// - `validator_stash` is the stash account of the validator. /// - `era` may be any era between `[current_era - history_depth; current_era]`. /// - `page` is the page index of nominators to pay out with value between 0 and - /// `num_nominators / T::MaxNominatorRewardedPerPage`. + /// `num_nominators / T::MaxNominatorRewardedPerValidator`. /// /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// If a validator has more than `T::MaxMaxNominatorRewardedPerPage` nominators backing + /// If a validator has more than `T::MaxMaxNominatorRewardedPerValidator` nominators backing /// them, then the list of nominators is paged, with each page being capped at - /// `T::MaxNominatorRewardedPerPage`. If a validator has more than one page of nominators, - /// the call needs to be made for each page separately in order for all the nominators - /// backing a validator receive the reward. The nominators are not sorted across pages and - /// so it should not be assumed the highest staker would be on the topmost page and vice - /// versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. + /// `T::MaxNominatorRewardedPerValidator`. If a validator has more than one page of + /// nominators, the call needs to be made for each page separately in order for all the + /// nominators backing a validator receive the reward. The nominators are not sorted across + /// pages and so it should not be assumed the highest staker would be on the topmost page + /// and vice versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. /// /// # - /// - Time complexity: at most O(MaxNominatorRewardedPerPage). + /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). /// - Contains a limited number of reads and writes. /// ----------- /// N is the Number of payouts for the validator (including the validator) @@ -1664,7 +1664,7 @@ pub mod pallet { /// # #[pallet::call_index(18)] #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( - T::MaxNominatorRewardedPerPage::get() + T::MaxNominatorRewardedPerValidator::get() ))] pub fn payout_stakers( origin: OriginFor, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 1b0b02b939bc1..5d0b99df7485d 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2195,7 +2195,8 @@ fn reward_validator_slashing_validator_does_not_overflow() { let _ = Balances::make_free_balance_be(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; - let (exposure_overview, _) = exposure.clone().as_pages(MaxNominatorRewardedPerPage::get()); + let (exposure_overview, _) = + exposure.clone().as_pages(MaxNominatorRewardedPerValidator::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -3695,7 +3696,7 @@ fn six_session_delay() { fn test_nominators_are_rewarded_for_all_exposure_page() { ExtBuilder::default().build_and_execute(|| { // 3 pages of exposure - let nominator_count = 2 * MaxNominatorRewardedPerPage::get() + 1; + let nominator_count = 2 * MaxNominatorRewardedPerValidator::get() + 1; for i in 0..nominator_count { let stash = 10_000 + i as AccountId; @@ -3760,7 +3761,7 @@ fn test_multi_page_payout_stakers() { mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); - // Since `MaxNominatorRewardedPerPage = 64`, there are two pages of validator exposure. + // Since `MaxNominatorRewardedPerValidator = 64`, there are two pages of validator exposure. assert_eq!(EraInfo::::get_page_count(1, &11), 2); // compute and ensure the reward amount is greater than zero. @@ -4052,7 +4053,8 @@ fn test_commission_paid_only_once() { mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); - // Since `MaxNominatorRewardedPerPage = 64`, there are four pages of validator exposure. + // Since `MaxNominatorRewardedPerValidator = 64`, there are four pages of validator + // exposure. assert_eq!(EraInfo::::get_page_count(1, &11), 4); // compute and ensure the reward amount is greater than zero. @@ -4085,7 +4087,7 @@ fn payout_stakers_handles_weight_refund() { // Note: this test relies on the assumption that `payout_stakers_alive_staked` is solely used by // `payout_stakers` to calculate the weight of each payout op. ExtBuilder::default().has_stakers(false).build_and_execute(|| { - let max_nom_rewarded = MaxNominatorRewardedPerPage::get(); + let max_nom_rewarded = MaxNominatorRewardedPerValidator::get(); // Make sure the configured value is meaningful for our use. assert!(max_nom_rewarded >= 4); let half_max_nom_rewarded = max_nom_rewarded / 2; @@ -5935,7 +5937,7 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ExtBuilder::default().has_stakers(false).build_and_execute(|| { // case 1: exposure exist in clipped. // set page cap to 10 - MaxNominatorRewardedPerPage::set(10); + MaxNominatorRewardedPerValidator::set(10); bond_validator(11, 10, 1000); let mut expected_individual_exposures: Vec> = vec![]; let mut total_exposure: Balance = 0; From ce771358427e5c8619775ff258e53da79e23d805 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 31 Jan 2023 14:36:27 +0100 Subject: [PATCH 068/131] consume exposure --- frame/staking/src/lib.rs | 4 ++-- frame/staking/src/pallet/mod.rs | 4 ++-- frame/staking/src/tests.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 6ebe3c8fa6401..da4250bf3d3e6 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -736,8 +736,8 @@ impl { /// Splits an `Exposure` into `ExposureOverview` and multiple chunks of `IndividualExposure` /// with each chunk having maximum of `page_size` elements. - fn as_pages( - &self, + fn into_pages( + self, page_size: u32, ) -> (ExposureOverview, Vec>) { let individual_chunks = self.others.chunks(page_size as usize); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 1c09bd04d8eb8..cf7d65ecfca3c 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -206,7 +206,7 @@ pub mod pallet { /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerValidator` /// nominators in a single call. This used to limit the i/o cost for the nominator payout. /// See call `payout_stakers` for more details. - /// // TODO(ank4n) keep old one and create new one. + // TODO(ank4n): Should we change this name? Breaking changes! #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; @@ -719,7 +719,7 @@ pub mod pallet { >::insert(era, &validator, &exposure); let (exposure_overview, exposure_pages) = - exposure.as_pages(T::MaxNominatorRewardedPerValidator::get()); + exposure.into_pages(T::MaxNominatorRewardedPerValidator::get()); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 5d0b99df7485d..d65ffbbde5d51 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2196,7 +2196,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; let (exposure_overview, _) = - exposure.clone().as_pages(MaxNominatorRewardedPerValidator::get()); + exposure.clone().into_pages(MaxNominatorRewardedPerValidator::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -5784,7 +5784,7 @@ fn can_page_exposure() { let (exposure_overview, exposure_page): ( ExposureOverview, Vec>, - ) = exposure.clone().as_pages(3); + ) = exposure.clone().into_pages(3); // then // 7 pages of nominators. From b435e8779a30d11e933337bbf47d3122897e47f0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 17:46:20 +0100 Subject: [PATCH 069/131] some new definitions --- frame/staking/src/mock.rs | 1 + frame/staking/src/pallet/mod.rs | 73 +++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 119fc71f2b4e5..0bd671c9f36f4 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -294,6 +294,7 @@ impl crate::pallet::pallet::Config for Test { type EraPayout = ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxExposurePageSize = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index cf7d65ecfca3c..e5dad3c2e3e5e 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -201,15 +201,24 @@ pub mod pallet { /// guess. type NextNewSession: EstimateNextNewSession; - /// The maximum number of nominators rewarded for each validator. + /// The maximum number of nominators rewarded for each validator when using + /// `ErasStakersClipped`. /// - /// A reward payout is restricted to a maximum of `MaxNominatorRewardedPerValidator` - /// nominators in a single call. This used to limit the i/o cost for the nominator payout. - /// See call `payout_stakers` for more details. - // TODO(ank4n): Should we change this name? Breaking changes! + /// For older non-paged exposure, a reward payout is restricted to the top + /// `MaxNominatorRewardedPerValidator` nominators. This is to limit the i/o cost for the + /// nominator payout. + // TODO(ank4n) #[deprecated(note = "This constant is no longer used and will be removed in the future.")] #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; + /// The maximum size of each `T::ExposurePage`. + /// + /// An `ExposurePage` is bounded to a maximum of `MaxExposurePageSize` nominators. The + /// actual page size is a dynamic value that is determined by the storage item + /// `T::ExposurePageSize`. + #[pallet::constant] + type MaxExposurePageSize: Get; + /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. type OffendingValidatorsThreshold: Get; @@ -466,6 +475,12 @@ pub mod pallet { ValueQuery, >; + /// The nominator count each `ExposurePage` is capped at. + /// + /// This cannot be greater than `T::MaxExposurePageSize`. + #[pallet::storage] + pub type ExposurePageSize = StorageValue<_, u32, OptionQuery>; + /// Paginated exposure of a validator at given era. /// /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account @@ -1632,7 +1647,7 @@ pub mod pallet { Ok(()) } - /// Pay out all the stakers behind a single validator for a single era and page. + /// Pay out next page of the stakers behind a validator for the given era. /// /// - `validator_stash` is the stash account of the validator. /// - `era` may be any era between `[current_era - history_depth; current_era]`. @@ -1642,7 +1657,7 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// If a validator has more than `T::MaxMaxNominatorRewardedPerValidator` nominators backing + /// If a validator has more than `T::MaxNominatorRewardedPerValidator` nominators backing /// them, then the list of nominators is paged, with each page being capped at /// `T::MaxNominatorRewardedPerValidator`. If a validator has more than one page of /// nominators, the call needs to be made for each page separately in order for all the @@ -1963,6 +1978,50 @@ pub mod pallet { MinCommission::::put(new); Ok(()) } + + /// Pay out a page of the stakers behind a validator for the given era and page. + /// + /// - `validator_stash` is the stash account of the validator. + /// - `era` may be any era between `[current_era - history_depth; current_era]`. + /// - `page` is the page index of nominators to pay out with value between 0 and + /// `num_nominators / T::MaxNominatorRewardedPerValidator`. + /// + /// The origin of this call must be _Signed_. Any account can call this function, even if + /// it is not one of the stakers. + /// + /// If a validator has more than `T::MaxNominatorRewardedPerValidator` nominators backing + /// them, then the list of nominators is paged, with each page being capped at + /// `T::MaxNominatorRewardedPerValidator`. If a validator has more than one page of + /// nominators, the call needs to be made for each page separately in order for all the + /// nominators backing a validator receive the reward. The nominators are not sorted across + /// pages and so it should not be assumed the highest staker would be on the topmost page + /// and vice versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. + /// + /// # + /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). + /// - Contains a limited number of reads and writes. + /// ----------- + /// N is the Number of payouts for the validator (including the validator) + /// Weight: + /// - Reward Destination Staked: O(N) + /// - Reward Destination Controller (Creating): O(N) + /// + /// NOTE: weights are assuming that payouts are made to alive stash account (Staked). + /// Paying even a dead controller is cheaper weight-wise. We don't do any refunds here. + /// # + #[pallet::call_index(26)] + #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( + T::MaxNominatorRewardedPerValidator::get() + ))] + pub fn payout_stakers_by_page( + origin: OriginFor, + validator_stash: T::AccountId, + era: EraIndex, + page: PageIndex, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + Self::do_payout_stakers(validator_stash, era, page) + } } } From 85f670bc9cee7006a1832ed1b8a111a09d9e7300 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 18:39:59 +0100 Subject: [PATCH 070/131] new call to payout staekers by page --- frame/staking/src/lib.rs | 1 + frame/staking/src/mock.rs | 2 +- frame/staking/src/pallet/impls.rs | 56 ++++++++++++++++++++++ frame/staking/src/pallet/mod.rs | 31 ++++++++---- frame/staking/src/tests.rs | 80 +++++++++++++++---------------- 5 files changed, 119 insertions(+), 51 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index da4250bf3d3e6..6f6931055e71d 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -778,6 +778,7 @@ pub struct ExposurePage { #[codec(compact)] pub page_total: Balance, /// The portions of nominators stashes that are exposed. + /// TODO(ank4n): BoundedVec touches lot of code, skip for now. pub others: Vec>, } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 0bd671c9f36f4..15af194f089e1 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -760,7 +760,7 @@ pub(crate) fn make_all_reward_payment(era: EraIndex) { for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) { let ledger = >::get(&validator_controller).unwrap(); for page in 0..EraInfo::::get_page_count(era, &ledger.stash) { - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), ledger.stash, era, diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 39d36d3ba9dac..5aa7fe5e4ab27 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -131,9 +131,65 @@ impl Pallet { Ok(used_weight) } + fn validate_payout_stakers( + validator_stash: T::AccountId, + era: EraIndex, + ) -> Result<(), Error> { + // Validate input data + let current_era = CurrentEra::::get().ok_or_else(|| { + Error::::InvalidEraToReward + })?; + + let history_depth = T::HistoryDepth::get(); + ensure!( + era <= current_era && era >= current_era.saturating_sub(history_depth), + Error::::InvalidEraToReward + ); + + // ensure!( + // page < EraInfo::::get_page_count(era, &validator_stash), + // Error::::InvalidPage.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) + // ); + + // Note: if era has no reward to be claimed, era may be future. better not to update + // `ledger.legacy_claimed_rewards` in this case. + let era_payout = >::get(&era).ok_or_else(|| { + Error::::InvalidEraToReward + })?; + + let controller = Self::bonded(&validator_stash).ok_or_else(|| { + Error::::NotStash + })?; + let mut ledger = >::get(&controller).ok_or(Error::::NotController)?; + + // // clean up legacy claimed rewards + ledger + .legacy_claimed_rewards + .retain(|&x| x >= current_era.saturating_sub(history_depth)); + >::insert(&controller, &ledger); + + // if EraInfo::::is_rewards_claimed_temp(era, &ledger, &ledger.stash, page) { + // Error::::AlreadyClaimed + // .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) + // } + + + Ok(()) + } + + + pub(super) fn do_payout_stakers( validator_stash: T::AccountId, era: EraIndex, + ) -> DispatchResultWithPostInfo { + EraInfo::::get_page_count(era, &validator_stash); + Self::do_payout_stakers_by_page(validator_stash, era, 0) + } + + pub(super) fn do_payout_stakers_by_page( + validator_stash: T::AccountId, + era: EraIndex, page: PageIndex, ) -> DispatchResultWithPostInfo { // Validate input data diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e5dad3c2e3e5e..3a27383a8d822 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -207,7 +207,8 @@ pub mod pallet { /// For older non-paged exposure, a reward payout is restricted to the top /// `MaxNominatorRewardedPerValidator` nominators. This is to limit the i/o cost for the /// nominator payout. - // TODO(ank4n) #[deprecated(note = "This constant is no longer used and will be removed in the future.")] + // TODO(ank4n) #[deprecated(note = "This constant is no longer used and will be removed in + // the future.")] #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; @@ -667,7 +668,7 @@ pub mod pallet { /// This is only used for paged rewards. Once older non-paged rewards are no longer /// relevant, `is_rewards_claimed_temp` can be removed and this function can be made public. fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: PageIndex) -> bool { - ClaimedRewards::::get(era, validator).iter().any(|&p| page == p) + ClaimedRewards::::get(era, validator).binary_search(&page).is_ok() } /// Get exposure info for a validator at a given era and page. @@ -720,9 +721,18 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) { - ClaimedRewards::::mutate(era, validator, |pages| { - pages.push(page); - }) + let mut claimed_pages = ClaimedRewards::::get(era, validator); + let search = claimed_pages.binary_search(&page); + // this should never be called if the reward has already been claimed + debug_assert!(search.is_err()); + + match search { + Err(index) => { + claimed_pages.insert(index, page); + ClaimedRewards::::insert(era, validator, claimed_pages); + }, + _ => {}, + } } /// Store exposure for elected validators at start of an era. @@ -1651,12 +1661,14 @@ pub mod pallet { /// /// - `validator_stash` is the stash account of the validator. /// - `era` may be any era between `[current_era - history_depth; current_era]`. - /// - `page` is the page index of nominators to pay out with value between 0 and - /// `num_nominators / T::MaxNominatorRewardedPerValidator`. + /// `num_nominators / T::ExposurePageSize`. /// /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// + /// This pays out the earliest exposure page not claimed for the era. If all pages are + /// claimed, it returns an error `InvalidPage`. + /// /// If a validator has more than `T::MaxNominatorRewardedPerValidator` nominators backing /// them, then the list of nominators is paged, with each page being capped at /// `T::MaxNominatorRewardedPerValidator`. If a validator has more than one page of @@ -1685,10 +1697,9 @@ pub mod pallet { origin: OriginFor, validator_stash: T::AccountId, era: EraIndex, - page: PageIndex, ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; - Self::do_payout_stakers(validator_stash, era, page) + Self::do_payout_stakers(validator_stash, era) } /// Rebond a portion of the stash scheduled to be unlocked. @@ -2020,7 +2031,7 @@ pub mod pallet { page: PageIndex, ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; - Self::do_payout_stakers(validator_stash, era, page) + Self::do_payout_stakers_by_page(validator_stash, era, page) } } } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index d65ffbbde5d51..d87f81b69d188 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2207,7 +2207,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { ErasStakers::::insert(0, 11, &exposure); ErasStakersOverview::::insert(0, 11, exposure_overview); ErasValidatorReward::::insert(0, stake); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); // Set staker @@ -3576,19 +3576,19 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // Last kept is 1: assert!(current_era - HistoryDepth::get() == 1); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 0), // Fail: Era out of history Error::::InvalidEraToReward.with_weight(err_weight) ); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 2, 0)); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 2, 0), // Fail: Double claim Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, active_era, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, active_era, 0), // Fail: Era not finished yet Error::::InvalidEraToReward.with_weight(err_weight) ); @@ -3740,7 +3740,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { } #[test] -fn test_multi_page_payout_stakers() { +fn test_multi_page_payout_stakers_by_page() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { let balance = 1000; @@ -3784,7 +3784,7 @@ fn test_multi_page_payout_stakers() { let controller_balance_before_p0_payout = Balances::free_balance(&10); // Payout rewards for first exposure page - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); let controller_balance_after_p0_payout = Balances::free_balance(&10); @@ -3796,7 +3796,7 @@ fn test_multi_page_payout_stakers() { assert!(controller_balance_after_p0_payout > controller_balance_before_p0_payout); // Payout the second and last page of nominators - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 1)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 1)); // verify the validator was not rewarded the second time assert_eq!(Balances::free_balance(&10), controller_balance_after_p0_payout); @@ -3883,7 +3883,7 @@ fn test_multi_page_payout_stakers() { } // verify only page 0 is marked as claimed - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, first_claimable_reward_era, @@ -3892,7 +3892,7 @@ fn test_multi_page_payout_stakers() { assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0]); // verify page 0 and 1 are marked as claimed - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, first_claimable_reward_era, @@ -3901,19 +3901,19 @@ fn test_multi_page_payout_stakers() { assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0, 1]); // verify only page 0 is marked as claimed - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, last_reward_era, 0)); assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0]); // verify page 0 and 1 are marked as claimed - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era, 1)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, last_reward_era, 1)); assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0, 1]); // Out of order claims works. - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 69, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 69, 0)); assert_eq!(Staking::claimed_rewards(69, &11), vec![0]); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 23, 1)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 23, 1)); assert_eq!(Staking::claimed_rewards(23, &11), vec![1]); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 42, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 42, 0)); assert_eq!(Staking::claimed_rewards(42, &11), vec![0]); }); } @@ -3944,12 +3944,12 @@ fn payout_stakers_handles_basic_errors() { // Wrong Era, too big assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 2, 0), Error::::InvalidEraToReward.with_weight(err_weight) ); // Wrong Staker assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 10, 1, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 10, 1, 0), Error::::NotStash.with_weight(err_weight) ); @@ -3969,7 +3969,7 @@ fn payout_stakers_handles_basic_errors() { // to payout era starting from expected_start_reward_era=19 through // expected_last_reward_era=98 (80 total eras), but not 18 or 99. assert_noop!( - Staking::payout_stakers( + Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, expected_start_reward_era - 1, @@ -3978,7 +3978,7 @@ fn payout_stakers_handles_basic_errors() { Error::::InvalidEraToReward.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers( + Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, expected_last_reward_era + 1, @@ -3986,13 +3986,13 @@ fn payout_stakers_handles_basic_errors() { ), Error::::InvalidEraToReward.with_weight(err_weight) ); - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, expected_start_reward_era, 0 )); - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, expected_last_reward_era, @@ -4000,7 +4000,7 @@ fn payout_stakers_handles_basic_errors() { )); // can call page 1 - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), 11, expected_last_reward_era, @@ -4009,23 +4009,23 @@ fn payout_stakers_handles_basic_errors() { // Can't claim again assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_start_reward_era, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_start_reward_era, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 0), Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 1), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 1), Error::::AlreadyClaimed.with_weight(err_weight) ); // invalid page assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 2), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 2), Error::::InvalidPage.with_weight(err_weight) ); }); @@ -4063,7 +4063,7 @@ fn test_commission_paid_only_once() { let controller_balance_before_p0_payout = Balances::free_balance(&10); // Payout rewards for first exposure page - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); let controller_balance_after_p0_payout = Balances::free_balance(&10); @@ -4075,7 +4075,7 @@ fn test_commission_paid_only_once() { ); for i in 1..4 { - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, i)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, i)); // no reward paid to validator for pages other than 0 Balances::free_balance(&10); } @@ -4124,7 +4124,7 @@ fn payout_stakers_handles_weight_refund() { // Collect payouts when there are no nominators let call = - TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 1, page: 0 }); + TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 1, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4138,7 +4138,7 @@ fn payout_stakers_handles_weight_refund() { // Collect payouts for an era where the validator did not receive any points. let call = - TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 2, page: 0 }); + TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 2, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4152,7 +4152,7 @@ fn payout_stakers_handles_weight_refund() { // Collect payouts when the validator has `half_max_nom_rewarded` nominators. let call = - TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 3, page: 0 }); + TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 3, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4176,7 +4176,7 @@ fn payout_stakers_handles_weight_refund() { // Collect payouts when the validator had `half_max_nom_rewarded` nominators. let call = - TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5, page: 0 }); + TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 5, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4184,7 +4184,7 @@ fn payout_stakers_handles_weight_refund() { // Try and collect payouts for an era that has already been collected. let call = - TestCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5, page: 0 }); + TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 5, page: 0 }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert!(result.is_err()); @@ -4326,7 +4326,7 @@ fn payout_creates_controller() { // compute and ensure the reward amount is greater than zero. let _ = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(2); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); // Controller is created assert!(Balances::free_balance(1337) > 0); @@ -4354,7 +4354,7 @@ fn payout_to_any_account_works() { // compute and ensure the reward amount is greater than zero. let _ = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(2); - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); // Payment is successful assert!(Balances::free_balance(42) > 0); @@ -5891,7 +5891,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { // verify rewards for era 1 cannot be claimed assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1, 0), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0), Error::::AlreadyClaimed .with_weight(::WeightInfo::payout_stakers_alive_staked(0)), ); @@ -5906,7 +5906,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { ); // verify rewards for era 2 can be claimed - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 2, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 2, 0)); assert_eq!( EraInfo::::is_rewards_claimed_temp( 2, @@ -6018,10 +6018,10 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( assert_eq!(EraInfo::::get_page_count(1, &11), 1); // payout for page 0 works - assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 0)); + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 0)); // payout for page 1 fails assert_noop!( - Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 0, 1), + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 1), Error::::InvalidPage .with_weight(::WeightInfo::payout_stakers_alive_staked(0)) ); From 2b5dbc6cce8ac8904efe366f4ebd7862f4ed7828 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 18:42:09 +0100 Subject: [PATCH 071/131] fix benchmark --- frame/staking/src/benchmarking.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index a2b24f391cdfd..231e5d2520d9e 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -565,7 +565,7 @@ benchmarks! { let balance = T::Currency::free_balance(controller); ensure!(balance.is_zero(), "Controller has balance, but should be dead."); } - }: payout_stakers(RawOrigin::Signed(caller), validator, current_era, 0) + }: payout_stakers_by_page(RawOrigin::Signed(caller), validator, current_era, 0) verify { let balance_after = T::Currency::free_balance(&validator_controller); ensure!( @@ -598,7 +598,7 @@ benchmarks! { let balance = T::Currency::free_balance(stash); nominator_balances_before.push(balance); } - }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era, 0) + }: payout_stakers_by_page(RawOrigin::Signed(caller), validator.clone(), current_era, 0) verify { let balance_after = T::Currency::free_balance(&validator); ensure!( @@ -639,7 +639,7 @@ benchmarks! { nominator_balances_before.push(balance); } - }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era, 1) + }: payout_stakers_by_page(RawOrigin::Signed(caller), validator.clone(), current_era, 1) verify { let balance_after = T::Currency::free_balance(&validator); @@ -803,7 +803,7 @@ benchmarks! { let caller: T::AccountId = whitelisted_caller(); let origin = RawOrigin::Signed(caller); let calls: Vec<_> = payout_calls_arg.iter().map(|arg| - Call::::payout_stakers { validator_stash: arg.0.clone(), era: arg.1, page: 0 }.encode() + Call::::payout_stakers_by_page { validator_stash: arg.0.clone(), era: arg.1, page: 0 }.encode() ).collect(); }: { for call in calls { @@ -1036,7 +1036,7 @@ mod tests { let current_era = CurrentEra::::get().unwrap(); let original_free_balance = Balances::free_balance(&validator_stash); - assert_ok!(Staking::payout_stakers( + assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), validator_stash, current_era, From 091463b9d00bba6ea1fec68938e472f766c87e55 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 19:21:40 +0100 Subject: [PATCH 072/131] keep payout_stakers backward compatible --- frame/staking/src/pallet/impls.rs | 61 ++++++------------------------- frame/staking/src/pallet/mod.rs | 37 +++++++++++++++++++ 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 5aa7fe5e4ab27..a22ed35188099 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -131,60 +131,21 @@ impl Pallet { Ok(used_weight) } - fn validate_payout_stakers( - validator_stash: T::AccountId, - era: EraIndex, - ) -> Result<(), Error> { - // Validate input data - let current_era = CurrentEra::::get().ok_or_else(|| { - Error::::InvalidEraToReward - })?; - - let history_depth = T::HistoryDepth::get(); - ensure!( - era <= current_era && era >= current_era.saturating_sub(history_depth), - Error::::InvalidEraToReward - ); - - // ensure!( - // page < EraInfo::::get_page_count(era, &validator_stash), - // Error::::InvalidPage.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) - // ); - - // Note: if era has no reward to be claimed, era may be future. better not to update - // `ledger.legacy_claimed_rewards` in this case. - let era_payout = >::get(&era).ok_or_else(|| { - Error::::InvalidEraToReward - })?; - - let controller = Self::bonded(&validator_stash).ok_or_else(|| { - Error::::NotStash - })?; - let mut ledger = >::get(&controller).ok_or(Error::::NotController)?; - - // // clean up legacy claimed rewards - ledger - .legacy_claimed_rewards - .retain(|&x| x >= current_era.saturating_sub(history_depth)); - >::insert(&controller, &ledger); - - // if EraInfo::::is_rewards_claimed_temp(era, &ledger, &ledger.stash, page) { - // Error::::AlreadyClaimed - // .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) - // } - - - Ok(()) - } - - - pub(super) fn do_payout_stakers( validator_stash: T::AccountId, era: EraIndex, ) -> DispatchResultWithPostInfo { - EraInfo::::get_page_count(era, &validator_stash); - Self::do_payout_stakers_by_page(validator_stash, era, 0) + let controller = Self::bonded(&validator_stash).ok_or_else(|| { + Error::::NotStash.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) + })?; + let ledger = >::get(&controller).ok_or(Error::::NotController)?; + let page = EraInfo::::get_next_claimable_page(era, &validator_stash, &ledger) + .ok_or_else(|| { + Error::::AlreadyClaimed + .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) + })?; + + Self::do_payout_stakers_by_page(validator_stash, era, page) } pub(super) fn do_payout_stakers_by_page( diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 3a27383a8d822..d722adc68a3fe 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -701,6 +701,43 @@ pub mod pallet { >::get(&era, validator).page_count.max(1) } + /// Returns the next page that can be claimed or `None` if nothing to claim. + // TODO(ank4n): Test and refactor + pub(crate) fn get_next_claimable_page( + era: EraIndex, + validator: &T::AccountId, + ledger: &StakingLedger, + ) -> Option { + 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), + } + } + + // Find next claimable page of paged exposure. + let page_count = Self::get_page_count(era, validator); + let claimed_pages = ClaimedRewards::::get(era, validator); + let claimed_page_count = claimed_pages.len() as PageIndex; + + // find the first page that is not claimed. + for page in 0..claimed_page_count as PageIndex { + debug_assert!(page <= claimed_pages[page as usize]); + if page < claimed_pages[page as usize] { + return Some(page) + } + } + // all pages are claimed + return if claimed_page_count < page_count { Some(claimed_page_count) } else { None } + } + + /// Checks if exposure is paged or not. + fn is_non_paged_exposure(era: EraIndex, validator: &T::AccountId) -> bool { + >::contains_key(&era, validator) + } + /// Returns validator commission for this era and page. pub(crate) fn get_validator_commission( era: EraIndex, From 628c1fc7dbacfa14150baa2277538eb281605bdd Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 20:05:01 +0100 Subject: [PATCH 073/131] split exposure by ExposurePageSize --- frame/staking/src/pallet/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index d722adc68a3fe..7db6295e9c081 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -779,9 +779,14 @@ pub mod pallet { exposure: Exposure>, ) { >::insert(era, &validator, &exposure); + // FIXME(ankan) Should we sort exposure.others for backward compatibility? + + let page_size = >::get() + .unwrap_or_else(|| T::MaxExposurePageSize::get()) + .clamp(1, T::MaxExposurePageSize::get()); let (exposure_overview, exposure_pages) = - exposure.into_pages(T::MaxNominatorRewardedPerValidator::get()); + exposure.into_pages(page_size); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { From 3763e1a939375013072e13eddc83a4df07f4976b Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 23:26:37 +0100 Subject: [PATCH 074/131] return both overview and page --- frame/staking/src/pallet/impls.rs | 8 +-- frame/staking/src/pallet/mod.rs | 29 +++++++-- frame/staking/src/tests.rs | 100 ++++++++++++++++++++++-------- 3 files changed, 102 insertions(+), 35 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a22ed35188099..9c1c9bf5e14e6 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -205,7 +205,7 @@ impl Pallet { // Then look at the validator, figure out the proportion of their reward // which goes to them and each of their nominators. - let exposure = EraInfo::::get_validator_exposure(era, &ledger.stash, page); + let (exposure_overview, exposure_page) = EraInfo::::get_validator_exposure(era, &ledger.stash, page); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; let validator_reward_points = era_reward_points @@ -232,7 +232,7 @@ impl Pallet { let validator_leftover_payout = validator_total_payout - validator_commission_payout; // Now let's calculate how this is split to the validator. - let validator_exposure_part = Perbill::from_rational(exposure.own, exposure.total); + let validator_exposure_part = Perbill::from_rational(exposure_overview.own, exposure_overview.total); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; Self::deposit_event(Event::::PayoutStarted { @@ -259,8 +259,8 @@ impl Pallet { // Lets now calculate how this is split to the nominators. // Reward only the clipped exposures. Note this is not necessarily sorted. - for nominator in exposure.others.iter() { - let nominator_exposure_part = Perbill::from_rational(nominator.value, exposure.total); + for nominator in exposure_page.others.iter() { + let nominator_exposure_part = Perbill::from_rational(nominator.value, exposure_overview.total); let nominator_reward: BalanceOf = nominator_exposure_part * validator_leftover_payout; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 7db6295e9c081..3ef083369aef4 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -679,20 +679,40 @@ pub mod pallet { era: EraIndex, validator: &T::AccountId, page: PageIndex, - ) -> Exposure> { + ) -> (ExposureOverview>, ExposurePage>) { return match >::get(era, (validator, page)) { // only return clipped exposure if page zero and no paged exposure entry - None if page == 0 => >::get(&era, validator), + None if page == 0 => Self::get_clipped_exposure_as_page(era, validator), Some(exposure_page) => { let overview = >::get(&era, validator); // own stake is included only once in the first page. let own = if page == 0 { overview.own } else { Zero::zero() }; - Exposure { total: overview.total, own, others: exposure_page.others } + (ExposureOverview { + own, + ..overview + }, exposure_page) }, _ => Default::default(), } } + /// Get clipped exposure and convert it as `ExposurePage`. + fn get_clipped_exposure_as_page( + era: EraIndex, + validator: &T::AccountId, + ) -> (ExposureOverview>, ExposurePage>) { + let exposure = >::get(&era, validator); + ( + ExposureOverview { + total: exposure.total, + own: exposure.own, + nominator_count: exposure.others.len() as u32, + page_count: 1, + }, + ExposurePage { page_total: exposure.total, others: exposure.others }, + ) + } + /// Returns the number of pages of exposure a validator has for the given era. /// /// This will always return at minimum one count of exposure to be backward compatible to @@ -785,8 +805,7 @@ pub mod pallet { .unwrap_or_else(|| T::MaxExposurePageSize::get()) .clamp(1, T::MaxExposurePageSize::get()); - let (exposure_overview, exposure_pages) = - exposure.into_pages(page_size); + let (exposure_overview, exposure_pages) = exposure.into_pages(page_size); >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index d87f81b69d188..3505d5e4caca2 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3770,14 +3770,14 @@ fn test_multi_page_payout_stakers_by_page() { // verify the exposures are calculated correctly. let actual_exposure_0 = EraInfo::::get_validator_exposure(1, &11, 0); - assert_eq!(actual_exposure_0.total, total_exposure); - assert_eq!(actual_exposure_0.own, 1000); - assert_eq!(actual_exposure_0.others.len(), 64); + assert_eq!(actual_exposure_0.0.total, total_exposure); + assert_eq!(actual_exposure_0.0.own, 1000); + assert_eq!(actual_exposure_0.1.others.len(), 64); let actual_exposure_1 = EraInfo::::get_validator_exposure(1, &11, 1); - assert_eq!(actual_exposure_1.total, total_exposure); + assert_eq!(actual_exposure_1.0.total, total_exposure); // own stake is only included once in the first page - assert_eq!(actual_exposure_1.own, 0); - assert_eq!(actual_exposure_1.others.len(), 100 - 64); + assert_eq!(actual_exposure_1.0.own, 0); + assert_eq!(actual_exposure_1.1.others.len(), 100 - 64); let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); @@ -3901,11 +3901,21 @@ fn test_multi_page_payout_stakers_by_page() { assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0, 1]); // verify only page 0 is marked as claimed - assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, last_reward_era, 0)); + assert_ok!(Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + last_reward_era, + 0 + )); assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0]); // verify page 0 and 1 are marked as claimed - assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, last_reward_era, 1)); + assert_ok!(Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + last_reward_era, + 1 + )); assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0, 1]); // Out of order claims works. @@ -4009,23 +4019,43 @@ fn payout_stakers_handles_basic_errors() { // Can't claim again assert_noop!( - Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_start_reward_era, 0), + Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + expected_start_reward_era, + 0 + ), Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 0), + Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + expected_last_reward_era, + 0 + ), Error::::AlreadyClaimed.with_weight(err_weight) ); assert_noop!( - Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 1), + Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + expected_last_reward_era, + 1 + ), Error::::AlreadyClaimed.with_weight(err_weight) ); // invalid page assert_noop!( - Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, expected_last_reward_era, 2), + Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + expected_last_reward_era, + 2 + ), Error::::InvalidPage.with_weight(err_weight) ); }); @@ -4123,8 +4153,11 @@ fn payout_stakers_handles_weight_refund() { start_active_era(2); // Collect payouts when there are no nominators - let call = - TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 1, page: 0 }); + let call = TestCall::Staking(StakingCall::payout_stakers_by_page { + validator_stash: 11, + era: 1, + page: 0, + }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4137,8 +4170,11 @@ fn payout_stakers_handles_weight_refund() { start_active_era(3); // Collect payouts for an era where the validator did not receive any points. - let call = - TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 2, page: 0 }); + let call = TestCall::Staking(StakingCall::payout_stakers_by_page { + validator_stash: 11, + era: 2, + page: 0, + }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4151,8 +4187,11 @@ fn payout_stakers_handles_weight_refund() { start_active_era(4); // Collect payouts when the validator has `half_max_nom_rewarded` nominators. - let call = - TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 3, page: 0 }); + let call = TestCall::Staking(StakingCall::payout_stakers_by_page { + validator_stash: 11, + era: 3, + page: 0, + }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); @@ -4175,16 +4214,22 @@ fn payout_stakers_handles_weight_refund() { start_active_era(6); // Collect payouts when the validator had `half_max_nom_rewarded` nominators. - let call = - TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 5, page: 0 }); + let call = TestCall::Staking(StakingCall::payout_stakers_by_page { + validator_stash: 11, + era: 5, + page: 0, + }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert_ok!(result); assert_eq!(extract_actual_weight(&result, &info), max_nom_rewarded_weight); // Try and collect payouts for an era that has already been collected. - let call = - TestCall::Staking(StakingCall::payout_stakers_by_page { validator_stash: 11, era: 5, page: 0 }); + let call = TestCall::Staking(StakingCall::payout_stakers_by_page { + validator_stash: 11, + era: 5, + page: 0, + }); let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(20)); assert!(result.is_err()); @@ -5980,11 +6025,11 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ); // verify `EraInfo` returns page from paged storage assert_eq!( - EraInfo::::get_validator_exposure(1, &11, 0).others, + EraInfo::::get_validator_exposure(1, &11, 0).1.others, actual_exposure_page_0.others ); assert_eq!( - EraInfo::::get_validator_exposure(1, &11, 1).others, + EraInfo::::get_validator_exposure(1, &11, 1).1.others, actual_exposure_page_1.others ); assert_eq!(EraInfo::::get_page_count(1, &11), 2); @@ -6006,11 +6051,14 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( // verify `EraInfo` returns exposure from clipped storage assert!(matches!( EraInfo::::get_validator_exposure(1, &11, 0), - Exposure { + (ExposureOverview { own, + page_count, + .. + }, ExposurePage { others, .. - } if others == clipped_exposure && own == 1000)); + }) if others == clipped_exposure && own == 1000 && page_count == 1)); // for pages other than 0, clipped storage returns empty exposure assert_eq!(EraInfo::::get_validator_exposure(1, &11, 1), Default::default()); From d232f9d740689257b4b149cb6dd787df4b4175dc Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 5 Feb 2023 23:34:30 +0100 Subject: [PATCH 075/131] fmt --- frame/staking/src/pallet/impls.rs | 9 ++++++--- frame/staking/src/pallet/mod.rs | 5 +---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 9c1c9bf5e14e6..f1c9aaebffbf9 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -205,7 +205,8 @@ impl Pallet { // Then look at the validator, figure out the proportion of their reward // which goes to them and each of their nominators. - let (exposure_overview, exposure_page) = EraInfo::::get_validator_exposure(era, &ledger.stash, page); + let (exposure_overview, exposure_page) = + EraInfo::::get_validator_exposure(era, &ledger.stash, page); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; let validator_reward_points = era_reward_points @@ -232,7 +233,8 @@ impl Pallet { let validator_leftover_payout = validator_total_payout - validator_commission_payout; // Now let's calculate how this is split to the validator. - let validator_exposure_part = Perbill::from_rational(exposure_overview.own, exposure_overview.total); + let validator_exposure_part = + Perbill::from_rational(exposure_overview.own, exposure_overview.total); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; Self::deposit_event(Event::::PayoutStarted { @@ -260,7 +262,8 @@ impl Pallet { // Lets now calculate how this is split to the nominators. // Reward only the clipped exposures. Note this is not necessarily sorted. for nominator in exposure_page.others.iter() { - let nominator_exposure_part = Perbill::from_rational(nominator.value, exposure_overview.total); + let nominator_exposure_part = + Perbill::from_rational(nominator.value, exposure_overview.total); let nominator_reward: BalanceOf = nominator_exposure_part * validator_leftover_payout; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 3ef083369aef4..1fb939694fd0d 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -687,10 +687,7 @@ pub mod pallet { let overview = >::get(&era, validator); // own stake is included only once in the first page. let own = if page == 0 { overview.own } else { Zero::zero() }; - (ExposureOverview { - own, - ..overview - }, exposure_page) + (ExposureOverview { own, ..overview }, exposure_page) }, _ => Default::default(), } From 6a747f75554d745a5a66d503bae1158a529d077e Mon Sep 17 00:00:00 2001 From: Ankan <10196091+Ank4n@users.noreply.github.com> Date: Mon, 6 Feb 2023 10:47:38 +0100 Subject: [PATCH 076/131] Update frame/staking/README.md Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- frame/staking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/README.md b/frame/staking/README.md index 2958ecf8dc2fb..043dc2088c0c1 100644 --- a/frame/staking/README.md +++ b/frame/staking/README.md @@ -88,7 +88,7 @@ An account can become a nominator via the [`nominate`](https://docs.rs/pallet-st The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. -Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the +Rewards must be claimed for each era before it gets too old by [`HistoryDeth`] using the `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the validator as well as its nominators. Rewards are paged to maximum of [`Config::MaxNominatorRewardedPerValidator`] nominators per call. Each page of staker payout needs to be called separately to ensure all nominators are From a591104a4b4f88147e63402570e4042049a45e22 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 21:51:12 +0100 Subject: [PATCH 077/131] introduce exposure extension --- frame/staking/src/lib.rs | 43 +++++++++++++++++++++++++++++++ frame/staking/src/pallet/impls.rs | 14 ++++++---- frame/staking/src/pallet/mod.rs | 36 ++++++++++---------------- frame/staking/src/tests.rs | 40 ++++++++++++---------------- 4 files changed, 82 insertions(+), 51 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 6f6931055e71d..55413d3ef9643 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -817,6 +817,49 @@ impl Default for ExposureOverview { } } +#[derive(Encode, Decode, RuntimeDebug, TypeInfo, PartialEq, Eq)] +struct ExposureExt { + exposure_overview: ExposureOverview, + exposure_page: ExposurePage, +} + +impl ExposureExt { + pub fn from_clipped(exposure: Exposure) -> Self { + Self { + exposure_overview: ExposureOverview { + total: exposure.total, + own: exposure.own, + nominator_count: exposure.others.len() as u32, + page_count: 1, + }, + exposure_page: ExposurePage { page_total: exposure.total, others: exposure.others }, + } + } + pub fn total(&self) -> Balance { + self.exposure_overview.total + } + + pub fn own(&self) -> Balance { + self.exposure_overview.own + } + + pub fn nominator_count(&self) -> u32 { + self.exposure_overview.nominator_count + } + + pub fn page_count(&self) -> PageIndex { + self.exposure_overview.page_count + } + + pub fn page_total(&self) -> Balance { + self.exposure_page.page_total + } + + pub fn others(&self) -> &Vec> { + &self.exposure_page.others + } +} + /// A pending slash record. The value of the slash has been computed but not applied yet, /// rather deferred for several eras. #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index f1c9aaebffbf9..a8aac851e9ab0 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -196,6 +196,12 @@ impl Pallet { EraInfo::::set_rewards_as_claimed(era, &ledger.stash, page); } + let exposure = + EraInfo::::get_validator_exposure(era, &ledger.stash, page).ok_or_else(|| { + Error::::InvalidEraToReward + .with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) + })?; + // Input data seems good, no errors allowed after this point // Get Era reward points. It has TOTAL and INDIVIDUAL @@ -205,8 +211,6 @@ impl Pallet { // Then look at the validator, figure out the proportion of their reward // which goes to them and each of their nominators. - let (exposure_overview, exposure_page) = - EraInfo::::get_validator_exposure(era, &ledger.stash, page); let era_reward_points = >::get(&era); let total_reward_points = era_reward_points.total; let validator_reward_points = era_reward_points @@ -234,7 +238,7 @@ impl Pallet { let validator_leftover_payout = validator_total_payout - validator_commission_payout; // Now let's calculate how this is split to the validator. let validator_exposure_part = - Perbill::from_rational(exposure_overview.own, exposure_overview.total); + Perbill::from_rational(exposure.own(), exposure.total()); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; Self::deposit_event(Event::::PayoutStarted { @@ -261,9 +265,9 @@ impl Pallet { // Lets now calculate how this is split to the nominators. // Reward only the clipped exposures. Note this is not necessarily sorted. - for nominator in exposure_page.others.iter() { + for nominator in exposure.others().iter() { let nominator_exposure_part = - Perbill::from_rational(nominator.value, exposure_overview.total); + Perbill::from_rational(nominator.value, exposure.total()); let nominator_reward: BalanceOf = nominator_exposure_part * validator_leftover_payout; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 1fb939694fd0d..9074f2655ed74 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -59,7 +59,7 @@ pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; pub mod pallet { use frame_election_provider_support::ElectionDataProvider; - use crate::{BenchmarkingConfig, ExposureOverview}; + use crate::{BenchmarkingConfig, ExposureExt, ExposureOverview}; use super::*; @@ -679,35 +679,25 @@ pub mod pallet { era: EraIndex, validator: &T::AccountId, page: PageIndex, - ) -> (ExposureOverview>, ExposurePage>) { + ) -> Option>> { return match >::get(era, (validator, page)) { - // only return clipped exposure if page zero and no paged exposure entry - None if page == 0 => Self::get_clipped_exposure_as_page(era, validator), + // return clipped exposure if page zero and paged exposure does not exist + None if page == 0 => + Some(ExposureExt::from_clipped(>::get(era, validator))), + + // return paged exposure if it exists Some(exposure_page) => { let overview = >::get(&era, validator); // own stake is included only once in the first page. let own = if page == 0 { overview.own } else { Zero::zero() }; - (ExposureOverview { own, ..overview }, exposure_page) - }, - _ => Default::default(), - } - } - /// Get clipped exposure and convert it as `ExposurePage`. - fn get_clipped_exposure_as_page( - era: EraIndex, - validator: &T::AccountId, - ) -> (ExposureOverview>, ExposurePage>) { - let exposure = >::get(&era, validator); - ( - ExposureOverview { - total: exposure.total, - own: exposure.own, - nominator_count: exposure.others.len() as u32, - page_count: 1, + Some(ExposureExt { + exposure_overview: ExposureOverview { own, ..overview }, + exposure_page, + }) }, - ExposurePage { page_total: exposure.total, others: exposure.others }, - ) + _ => None, + } } /// Returns the number of pages of exposure a validator has for the given era. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 3505d5e4caca2..a436d6c3ea67b 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3769,15 +3769,15 @@ fn test_multi_page_payout_stakers_by_page() { mock::start_active_era(2); // verify the exposures are calculated correctly. - let actual_exposure_0 = EraInfo::::get_validator_exposure(1, &11, 0); - assert_eq!(actual_exposure_0.0.total, total_exposure); - assert_eq!(actual_exposure_0.0.own, 1000); - assert_eq!(actual_exposure_0.1.others.len(), 64); - let actual_exposure_1 = EraInfo::::get_validator_exposure(1, &11, 1); - assert_eq!(actual_exposure_1.0.total, total_exposure); + let actual_exposure_0 = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); + assert_eq!(actual_exposure_0.total(), total_exposure); + assert_eq!(actual_exposure_0.own(), 1000); + assert_eq!(actual_exposure_0.others().len(), 64); + let actual_exposure_1 = EraInfo::::get_validator_exposure(1, &11, 1).unwrap(); + assert_eq!(actual_exposure_1.total(), total_exposure); // own stake is only included once in the first page - assert_eq!(actual_exposure_1.0.own, 0); - assert_eq!(actual_exposure_1.1.others.len(), 100 - 64); + assert_eq!(actual_exposure_1.own(), 0); + assert_eq!(actual_exposure_1.others().len(), 100 - 64); let pre_payout_total_issuance = Balances::total_issuance(); RewardOnUnbalanceWasCalled::set(false); @@ -6025,12 +6025,12 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ); // verify `EraInfo` returns page from paged storage assert_eq!( - EraInfo::::get_validator_exposure(1, &11, 0).1.others, - actual_exposure_page_0.others + EraInfo::::get_validator_exposure(1, &11, 0).unwrap().others(), + &actual_exposure_page_0.others ); assert_eq!( - EraInfo::::get_validator_exposure(1, &11, 1).1.others, - actual_exposure_page_1.others + EraInfo::::get_validator_exposure(1, &11, 1).unwrap().others(), + &actual_exposure_page_1.others ); assert_eq!(EraInfo::::get_page_count(1, &11), 2); @@ -6049,19 +6049,13 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ); // verify `EraInfo` returns exposure from clipped storage - assert!(matches!( - EraInfo::::get_validator_exposure(1, &11, 0), - (ExposureOverview { - own, - page_count, - .. - }, ExposurePage { - others, - .. - }) if others == clipped_exposure && own == 1000 && page_count == 1)); + let actual_exposure = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); + assert_eq!(actual_exposure.others(), &clipped_exposure); + assert_eq!(actual_exposure.own(), 1000); + assert_eq!(actual_exposure.page_count(), 1); // for pages other than 0, clipped storage returns empty exposure - assert_eq!(EraInfo::::get_validator_exposure(1, &11, 1), Default::default()); + assert_eq!(EraInfo::::get_validator_exposure(1, &11, 1), None); // page size is 1 for clipped storage assert_eq!(EraInfo::::get_page_count(1, &11), 1); From 00b300f14bba959cc385b531fee1dd585ca2636c Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 21:54:41 +0100 Subject: [PATCH 078/131] doc --- frame/staking/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 55413d3ef9643..51baf4ff25482 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -817,6 +817,7 @@ impl Default for ExposureOverview { } } +/// Extended view of Exposure comprising of `ExposureOverview` and a single page of `ExposurePage`. #[derive(Encode, Decode, RuntimeDebug, TypeInfo, PartialEq, Eq)] struct ExposureExt { exposure_overview: ExposureOverview, From 9399131760e9d6f23100d681662d54010dab1c05 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 21:55:11 +0100 Subject: [PATCH 079/131] format --- frame/staking/src/pallet/impls.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a8aac851e9ab0..a6f263d91168e 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -237,8 +237,7 @@ impl Pallet { let validator_leftover_payout = validator_total_payout - validator_commission_payout; // Now let's calculate how this is split to the validator. - let validator_exposure_part = - Perbill::from_rational(exposure.own(), exposure.total()); + let validator_exposure_part = Perbill::from_rational(exposure.own(), exposure.total()); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; Self::deposit_event(Event::::PayoutStarted { @@ -266,8 +265,7 @@ impl Pallet { // Lets now calculate how this is split to the nominators. // Reward only the clipped exposures. Note this is not necessarily sorted. for nominator in exposure.others().iter() { - let nominator_exposure_part = - Perbill::from_rational(nominator.value, exposure.total()); + let nominator_exposure_part = Perbill::from_rational(nominator.value, exposure.total()); let nominator_reward: BalanceOf = nominator_exposure_part * validator_leftover_payout; From 353ebd3733c1ddb272718db9fbf067a665a82e45 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 22:12:26 +0100 Subject: [PATCH 080/131] pay commission in parts; failing tests --- frame/staking/src/pallet/impls.rs | 10 +++++++--- frame/staking/src/pallet/mod.rs | 6 ------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a6f263d91168e..09743fac43db1 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -232,13 +232,17 @@ impl Pallet { // This is how much validator + nominators are entitled to. let validator_total_payout = validator_total_reward_part * era_payout; - let validator_commission = EraInfo::::get_validator_commission(era, &ledger.stash, page); - let validator_commission_payout = validator_commission * validator_total_payout; + let validator_commission = EraInfo::::get_validator_commission(era, &ledger.stash); + // total commission validator takes across all nominator pages + let validator_total_commission_payout = validator_commission * validator_total_payout; - let validator_leftover_payout = validator_total_payout - validator_commission_payout; + let validator_leftover_payout = validator_total_payout - validator_total_commission_payout; // Now let's calculate how this is split to the validator. let validator_exposure_part = Perbill::from_rational(exposure.own(), exposure.total()); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; + let page_stake_part = Perbill::from_rational(exposure.page_total(), exposure.total()); + // validator commission is paid out in fraction across pages proportional to the page stake. + let validator_commission_payout = page_stake_part * validator_total_commission_payout; Self::deposit_event(Event::::PayoutStarted { era_index: era, diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 9074f2655ed74..a59d09de287a6 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -749,13 +749,7 @@ pub mod pallet { pub(crate) fn get_validator_commission( era: EraIndex, validator_stash: &T::AccountId, - page: PageIndex, ) -> Perbill { - if page != 0 { - // commission is only paid in the first page - return Zero::zero() - } - >::get(&era, validator_stash).commission } From 02d7ff8c45cdf670b51c6e566040c662269c4db0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 22:40:44 +0100 Subject: [PATCH 081/131] verify commission are paid across pages --- frame/staking/src/benchmarking.rs | 49 ------------------------------- frame/staking/src/lib.rs | 11 +++---- frame/staking/src/pallet/impls.rs | 14 ++++----- frame/staking/src/tests.rs | 25 +++++++++------- frame/staking/src/weights.rs | 46 +---------------------------- 5 files changed, 26 insertions(+), 119 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 231e5d2520d9e..ded83b6d80c78 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -614,55 +614,6 @@ benchmarks! { } } - payout_stakers_nominators_only { - let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32; - // create nominators between MaxNominatorRewardedPerValidator+1 .. =2 * MaxNominatorRewardedPerValidator - let nominator_lower_bound = T::MaxNominatorRewardedPerValidator::get(); - let nominator_upper_bound = 2 * T::MaxNominatorRewardedPerValidator::get(); - - let (validator, nominators) = create_validator_with_nominators::( - nominator_lower_bound + n, - nominator_upper_bound as u32, - false, - RewardDestination::Staked, - )?; - - let current_era = CurrentEra::::get().unwrap(); - // set the commission for this particular era as well. - >::insert(current_era, validator.clone(), >::validators(&validator)); - - let caller = whitelisted_caller(); - let balance_before = T::Currency::free_balance(&validator); - let mut nominator_balances_before = Vec::new(); - for (stash, _) in &nominators { - let balance = T::Currency::free_balance(stash); - nominator_balances_before.push(balance); - } - - }: payout_stakers_by_page(RawOrigin::Signed(caller), validator.clone(), current_era, 1) - verify { - let balance_after = T::Currency::free_balance(&validator); - - ensure!( - balance_before == balance_after, - "Validator should not have received payout for pages other than 0.", - ); - - let mut nominator_payout_count = 0; - for ((stash, _), balance_before) in nominators.iter().zip(nominator_balances_before.iter()) { - let balance_after = T::Currency::free_balance(stash); - if balance_before < &balance_after { - nominator_payout_count += 1; - } - } - - ensure!( - nominator_payout_count == n, - "n nominators must have been paid.", - ); - } - - rebond { let l in 1 .. T::MaxUnlockingChunks::get() as u32; diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 51baf4ff25482..fa49c9da2020d 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -824,7 +824,7 @@ struct ExposureExt { exposure_page: ExposurePage, } -impl ExposureExt { +impl ExposureExt { pub fn from_clipped(exposure: Exposure) -> Self { Self { exposure_overview: ExposureOverview { @@ -844,16 +844,13 @@ impl ExposureExt { self.exposure_overview.own } - pub fn nominator_count(&self) -> u32 { - self.exposure_overview.nominator_count - } - pub fn page_count(&self) -> PageIndex { self.exposure_overview.page_count } - pub fn page_total(&self) -> Balance { - self.exposure_page.page_total + // Returns the total stake of this page. + pub fn current_total(&self) -> Balance { + self.exposure_page.page_total + self.exposure_overview.own } pub fn others(&self) -> &Vec> { diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 09743fac43db1..16420a0ed8f6e 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -240,9 +240,13 @@ impl Pallet { // Now let's calculate how this is split to the validator. let validator_exposure_part = Perbill::from_rational(exposure.own(), exposure.total()); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; - let page_stake_part = Perbill::from_rational(exposure.page_total(), exposure.total()); + let page_stake_part = Perbill::from_rational(exposure.current_total(), exposure.total()); // validator commission is paid out in fraction across pages proportional to the page stake. let validator_commission_payout = page_stake_part * validator_total_commission_payout; + println!( + "validator_commission_payout: {:?}, validator_total_commission_payout: {:?}, exposure_total: {:?}, exposure_page_total: {:?}, page_count: {:?}, own: {:?}", + validator_commission_payout, validator_total_commission_payout, exposure.total(), exposure.current_total(), exposure.page_count(), exposure.own() + ); Self::deposit_event(Event::::PayoutStarted { era_index: era, @@ -287,13 +291,7 @@ impl Pallet { T::Reward::on_unbalanced(total_imbalance); debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerValidator::get()); - let payout_weight = if page == 0 { - T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count) - } else { - T::WeightInfo::payout_stakers_nominators_only(nominator_payout_count) - }; - - Ok(Some(payout_weight).into()) + Ok(Some(T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count)).into()) } /// Update the ledger for a controller. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index a436d6c3ea67b..3449bb9e28b02 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4062,7 +4062,7 @@ fn payout_stakers_handles_basic_errors() { } #[test] -fn test_commission_paid_only_once() { +fn test_commission_paid_across_pages() { ExtBuilder::default().has_stakers(false).build_and_execute(|| { let balance = 1; let commission = 50; @@ -4091,24 +4091,29 @@ fn test_commission_paid_only_once() { let payout = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(2); - let controller_balance_before_p0_payout = Balances::free_balance(&10); + let initial_balance = Balances::free_balance(&10); // Payout rewards for first exposure page assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); let controller_balance_after_p0_payout = Balances::free_balance(&10); - // half of the payout goes to validator since commission is 50% - assert_eq_error_rate!( - controller_balance_after_p0_payout, - controller_balance_before_p0_payout + payout / 2, - 1, - ); + // some commission is paid + assert!(initial_balance < controller_balance_after_p0_payout); + // payout all pages for i in 1..4 { + let before_balance = Balances::free_balance(&10); assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, i)); - // no reward paid to validator for pages other than 0 - Balances::free_balance(&10); + let after_balance = Balances::free_balance(&10); + // some commission is paid for every page + assert!(before_balance < after_balance); } + + assert_eq_error_rate!( + Balances::free_balance(&10), + initial_balance + payout / 2, + 1, + ); }); } diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index dea9175460e0a..2a3b04d7c555f 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -68,7 +68,6 @@ pub trait WeightInfo { fn cancel_deferred_slash(s: u32, ) -> Weight; fn payout_stakers_dead_controller(n: u32, ) -> Weight; fn payout_stakers_alive_staked(n: u32, ) -> Weight; - fn payout_stakers_nominators_only(n: u32, ) -> Weight; fn rebond(l: u32, ) -> Weight; fn reap_stash(s: u32, ) -> Weight; fn new_era(v: u32, n: u32, ) -> Weight; @@ -349,28 +348,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakersOverview (r:1 w:0) - // Storage: Staking ErasValidatorReward (r:1 w:0) - // Storage: Staking Bonded (r:2 w:0) - // Storage: Staking Ledger (r:2 w:2) - // Storage: Staking ClaimedRewards (r:1 w:1) - // Storage: Staking ErasStakersPaged (r:1 w:0) - // Storage: Staking ErasRewardPoints (r:1 w:0) - // Storage: Staking Payee (r:2 w:0) - // Storage: Balances Locks (r:2 w:2) - // Storage: System Account (r:2 w:2) - /// The range of component `n` is `[1, 256]`. - fn payout_stakers_nominators_only(n: u32, ) -> Weight { - // Minimum execution time: 272_243 nanoseconds. - Weight::from_ref_time(228_003_618) - // Standard Error: 35_442 - .saturating_add(Weight::from_ref_time(34_057_392).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(11)) - .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(4)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) - } + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -796,28 +774,6 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(4)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) } - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakersOverview (r:1 w:0) - // Storage: Staking ErasValidatorReward (r:1 w:0) - // Storage: Staking Bonded (r:2 w:0) - // Storage: Staking Ledger (r:2 w:2) - // Storage: Staking ClaimedRewards (r:1 w:1) - // Storage: Staking ErasStakersPaged (r:1 w:0) - // Storage: Staking ErasRewardPoints (r:1 w:0) - // Storage: Staking Payee (r:2 w:0) - // Storage: Balances Locks (r:2 w:2) - // Storage: System Account (r:2 w:2) - /// The range of component `n` is `[1, 256]`. - fn payout_stakers_nominators_only(n: u32, ) -> Weight { - // Minimum execution time: 272_243 nanoseconds. - Weight::from_ref_time(228_003_618) - // Standard Error: 35_442 - .saturating_add(Weight::from_ref_time(34_057_392).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(11)) - .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(4)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) - } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) From ca5d5f99f453e871e3d77b67d154b01d40ce480e Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 22:41:46 +0100 Subject: [PATCH 082/131] fmt --- frame/staking/src/pallet/impls.rs | 4 ---- frame/staking/src/tests.rs | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 16420a0ed8f6e..8846316854574 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -243,10 +243,6 @@ impl Pallet { let page_stake_part = Perbill::from_rational(exposure.current_total(), exposure.total()); // validator commission is paid out in fraction across pages proportional to the page stake. let validator_commission_payout = page_stake_part * validator_total_commission_payout; - println!( - "validator_commission_payout: {:?}, validator_total_commission_payout: {:?}, exposure_total: {:?}, exposure_page_total: {:?}, page_count: {:?}, own: {:?}", - validator_commission_payout, validator_total_commission_payout, exposure.total(), exposure.current_total(), exposure.page_count(), exposure.own() - ); Self::deposit_event(Event::::PayoutStarted { era_index: era, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 3449bb9e28b02..9549e9a0c7def 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4109,11 +4109,7 @@ fn test_commission_paid_across_pages() { assert!(before_balance < after_balance); } - assert_eq_error_rate!( - Balances::free_balance(&10), - initial_balance + payout / 2, - 1, - ); + assert_eq_error_rate!(Balances::free_balance(&10), initial_balance + payout / 2, 1,); }); } From 345b55a451016b320974b1037dda2385e7451377 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 22:45:44 +0100 Subject: [PATCH 083/131] docs --- frame/staking/src/lib.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index fa49c9da2020d..6803d5da8eb0d 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -825,6 +825,7 @@ struct ExposureExt { } impl ExposureExt { + /// Create a new instance of `ExposureExt` from legacy clipped exposures. pub fn from_clipped(exposure: Exposure) -> Self { Self { exposure_overview: ExposureOverview { @@ -836,23 +837,23 @@ impl ExposureExt Balance { self.exposure_overview.total } - pub fn own(&self) -> Balance { - self.exposure_overview.own - } - - pub fn page_count(&self) -> PageIndex { - self.exposure_overview.page_count - } - - // Returns the total stake of this page. + /// Returns total exposure of this validator for current page pub fn current_total(&self) -> Balance { self.exposure_page.page_total + self.exposure_overview.own } + /// Returns validator's own stake that is exposed + pub fn own(&self) -> Balance { + self.exposure_overview.own + } + + /// Returns the portions of nominators stashes that are exposed in this page pub fn others(&self) -> &Vec> { &self.exposure_page.others } From 6a269318f24e2cb83170d444b77ed7a3cce64ed0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 6 Feb 2023 22:47:54 +0100 Subject: [PATCH 084/131] fix test --- frame/staking/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 6803d5da8eb0d..f2ee79bb7e9f5 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -853,10 +853,16 @@ impl ExposureExt &Vec> { &self.exposure_page.others } + + /// Returns the number of pages of nominators stashes that are exposed. + #[allow(dead_code)] + pub fn page_count(&self) -> PageIndex { + self.exposure_overview.page_count + } } /// A pending slash record. The value of the slash has been computed but not applied yet, From 2ae47d9a22fdc4fe4dae3665f13c72246700b55e Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 7 Feb 2023 17:52:44 +0100 Subject: [PATCH 085/131] only use one constant --- frame/staking/src/mock.rs | 1 - frame/staking/src/pallet/mod.rs | 31 +++++++++++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 15af194f089e1..c78eba7c2b66e 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -294,7 +294,6 @@ impl crate::pallet::pallet::Config for Test { type EraPayout = ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; - type MaxExposurePageSize = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index a59d09de287a6..688ed77ddc099 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -201,24 +201,23 @@ pub mod pallet { /// guess. type NextNewSession: EstimateNextNewSession; - /// The maximum number of nominators rewarded for each validator when using - /// `ErasStakersClipped`. + /// The maximum size of each `T::ExposurePage`. + /// + /// An `ExposurePage` is bounded to a maximum of `MaxNominatorRewardedPerValidator` + /// nominators. The actual page size is a dynamic value that is determined by the storage + /// item `T::ExposurePageSize`. /// - /// For older non-paged exposure, a reward payout is restricted to the top + /// For older non-paged exposure, a reward payout was restricted to the top /// `MaxNominatorRewardedPerValidator` nominators. This is to limit the i/o cost for the /// nominator payout. - // TODO(ank4n) #[deprecated(note = "This constant is no longer used and will be removed in - // the future.")] - #[pallet::constant] - type MaxNominatorRewardedPerValidator: Get; - - /// The maximum size of each `T::ExposurePage`. /// - /// An `ExposurePage` is bounded to a maximum of `MaxExposurePageSize` nominators. The - /// actual page size is a dynamic value that is determined by the storage item - /// `T::ExposurePageSize`. + /// The name is a bit misleading, because historically we used to reward the top + /// `MaxNominatorRewardedPerValidator` nominators by stake when we did not had paged + /// exposures. In future we should rename this to something like `ExposurePageSize` when we + /// are ready to get rid of `ErasStakersClipped`. + /// Refer issue: #13034 #[pallet::constant] - type MaxExposurePageSize: Get; + type MaxNominatorRewardedPerValidator: Get; /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. @@ -478,7 +477,7 @@ pub mod pallet { /// The nominator count each `ExposurePage` is capped at. /// - /// This cannot be greater than `T::MaxExposurePageSize`. + /// This cannot be greater than `T::MaxNominatorRewardedPerValidator`. #[pallet::storage] pub type ExposurePageSize = StorageValue<_, u32, OptionQuery>; @@ -783,8 +782,8 @@ pub mod pallet { // FIXME(ankan) Should we sort exposure.others for backward compatibility? let page_size = >::get() - .unwrap_or_else(|| T::MaxExposurePageSize::get()) - .clamp(1, T::MaxExposurePageSize::get()); + .unwrap_or_else(|| T::MaxNominatorRewardedPerValidator::get()) + .clamp(1, T::MaxNominatorRewardedPerValidator::get()); let (exposure_overview, exposure_pages) = exposure.into_pages(page_size); From 7a4ce0d4ddfd3f0fee0dc9322abcfe9e01d79ee6 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 7 Feb 2023 18:21:29 +0100 Subject: [PATCH 086/131] payout_stakers still work nicely --- frame/staking/src/tests.rs | 228 +++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 9549e9a0c7def..8aaf0c264b251 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3928,6 +3928,234 @@ fn test_multi_page_payout_stakers_by_page() { }); } +#[test] +//todo +fn test_multi_page_payout_stakers_backward_compatible() { + // Test that payout_stakers work in general and that it pays the correct amount of reward. + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + let balance = 1000; + // Track the exposure of the validator and all nominators. + let mut total_exposure = balance; + // Create a validator: + bond_validator(11, 10, balance); // Default(64) + assert_eq!(Validators::::count(), 1); + + let err_weight = ::WeightInfo::payout_stakers_alive_staked(0); + + // Create nominators, targeting stash of validators + for i in 0..100 { + let bond_amount = balance + i as Balance; + bond_nominator(1000 + i, 100 + i, bond_amount, vec![11]); + // with multi page reward payout, payout exposure is same as total exposure. + total_exposure += bond_amount; + } + + mock::start_active_era(1); + Staking::reward_by_ids(vec![(11, 1)]); + + // Since `MaxNominatorRewardedPerValidator = 64`, there are two pages of validator exposure. + assert_eq!(EraInfo::::get_page_count(1, &11), 2); + + // compute and ensure the reward amount is greater than zero. + let payout = current_total_payout_for_duration(reward_time_per_era()); + mock::start_active_era(2); + + // verify the exposures are calculated correctly. + let actual_exposure_0 = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); + assert_eq!(actual_exposure_0.total(), total_exposure); + assert_eq!(actual_exposure_0.own(), 1000); + assert_eq!(actual_exposure_0.others().len(), 64); + let actual_exposure_1 = EraInfo::::get_validator_exposure(1, &11, 1).unwrap(); + assert_eq!(actual_exposure_1.total(), total_exposure); + // own stake is only included once in the first page + assert_eq!(actual_exposure_1.own(), 0); + assert_eq!(actual_exposure_1.others().len(), 100 - 64); + + let pre_payout_total_issuance = Balances::total_issuance(); + RewardOnUnbalanceWasCalled::set(false); + + let controller_balance_before_p0_payout = Balances::free_balance(&10); + // Payout rewards for first exposure page + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); + // page 0 is claimed + assert_noop!( + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0), + Error::::AlreadyClaimed.with_weight(err_weight) + ); + + let controller_balance_after_p0_payout = Balances::free_balance(&10); + + // verify rewards have been paid out but still some left + assert!(Balances::total_issuance() > pre_payout_total_issuance); + assert!(Balances::total_issuance() < pre_payout_total_issuance + payout); + + // verify the validator has been rewarded + assert!(controller_balance_after_p0_payout > controller_balance_before_p0_payout); + + // This should payout the second and last page of nominators + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); + + // cannot claim any more pages + assert_noop!( + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1), + Error::::AlreadyClaimed.with_weight(err_weight) + ); + + // verify the validator was not rewarded the second time + assert_eq!(Balances::free_balance(&10), controller_balance_after_p0_payout); + + // verify all rewards have been paid out + assert_eq_error_rate!(Balances::total_issuance(), pre_payout_total_issuance + payout, 2); + assert!(RewardOnUnbalanceWasCalled::get()); + + // verify all nominators of validator 11 are paid out, including the validator + // Validator payout goes to controller. + assert!(Balances::free_balance(&10) > balance); + for i in 0..100 { + assert!(Balances::free_balance(&(100 + i)) > balance + i as Balance); + } + + // verify we no longer track rewards in `legacy_claimed_rewards` vec + let ledger = Staking::ledger(&10); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: Default::default(), + legacy_claimed_rewards: bounded_vec![] + }) + ); + + // verify rewards are tracked to prevent double claims + for page in 0..EraInfo::::get_page_count(1, &11) { + assert_eq!( + EraInfo::::is_rewards_claimed_temp(1, ledger.as_ref().unwrap(), &11, page), + true + ); + } + + for i in 3..16 { + Staking::reward_by_ids(vec![(11, 1)]); + + // compute and ensure the reward amount is greater than zero. + let payout = current_total_payout_for_duration(reward_time_per_era()); + let pre_payout_total_issuance = Balances::total_issuance(); + + mock::start_active_era(i); + RewardOnUnbalanceWasCalled::set(false); + mock::make_all_reward_payment(i - 1); + assert_eq_error_rate!( + Balances::total_issuance(), + pre_payout_total_issuance + payout, + 2 + ); + assert!(RewardOnUnbalanceWasCalled::get()); + + // verify we track rewards for each era and page + for page in 0..EraInfo::::get_page_count(i - 1, &11) { + assert_eq!( + EraInfo::::is_rewards_claimed_temp( + i - 1, + Staking::ledger(&10).as_ref().unwrap(), + &11, + page + ), + true + ); + } + } + + assert_eq!(Staking::claimed_rewards(14, &11), vec![0, 1]); + + let last_era = 99; + let history_depth = HistoryDepth::get(); + let last_reward_era = last_era - 1; + let first_claimable_reward_era = last_era - history_depth; + for i in 16..=last_era { + Staking::reward_by_ids(vec![(11, 1)]); + // compute and ensure the reward amount is greater than zero. + let _ = current_total_payout_for_duration(reward_time_per_era()); + mock::start_active_era(i); + } + + // verify we clean up history as we go + for era in 0..15 { + assert_eq!(Staking::claimed_rewards(era, &11), Vec::::new()); + } + + // verify only page 0 is marked as claimed + assert_ok!(Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + first_claimable_reward_era + )); + assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0]); + + // verify page 0 and 1 are marked as claimed + assert_ok!(Staking::payout_stakers( + RuntimeOrigin::signed(1337), + 11, + first_claimable_reward_era, + )); + assert_eq!(Staking::claimed_rewards(first_claimable_reward_era, &11), vec![0, 1]); + + // change order and verify only page 1 is marked as claimed + assert_ok!(Staking::payout_stakers_by_page( + RuntimeOrigin::signed(1337), + 11, + last_reward_era, + 1 + )); + assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![1]); + + // verify page 0 is claimed even when explicit page is not passed + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era,)); + + assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0, 1]); + + // cannot claim any more pages + assert_noop!( + Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era), + Error::::AlreadyClaimed.with_weight(err_weight) + ); + + // Create 4 nominator pages + for i in 100..200 { + let bond_amount = balance + i as Balance; + bond_nominator(1000 + i, 100 + i, bond_amount, vec![11]); + } + + let test_era = last_era + 1; + mock::start_active_era(test_era); + + Staking::reward_by_ids(vec![(11, 1)]); + // compute and ensure the reward amount is greater than zero. + let _ = current_total_payout_for_duration(reward_time_per_era()); + mock::start_active_era(test_era + 1); + + // Out of order claims works. + assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, test_era, 2)); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![2]); + + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, test_era)); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![0, 2]); + + // cannot claim page 2 again + assert_noop!( + Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, test_era, 2), + Error::::AlreadyClaimed.with_weight(err_weight) + ); + + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, test_era)); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![0, 1, 2]); + + assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, test_era)); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![0, 1, 2, 3]); + }); +} + #[test] fn payout_stakers_handles_basic_errors() { // Here we will test payouts handle all errors. From 1abcad43c6d9748084ca97060288a5571788ab51 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 7 Feb 2023 18:25:27 +0100 Subject: [PATCH 087/131] remove todo --- frame/staking/src/pallet/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 688ed77ddc099..4224bea528ece 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -708,7 +708,6 @@ pub mod pallet { } /// Returns the next page that can be claimed or `None` if nothing to claim. - // TODO(ank4n): Test and refactor pub(crate) fn get_next_claimable_page( era: EraIndex, validator: &T::AccountId, From 3792f3fcc9887c3f7c34240d4792d9dafee4cda8 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 8 Feb 2023 00:11:51 +0100 Subject: [PATCH 088/131] benchmark against implicit page payout stakers since thats worst case --- frame/staking/src/benchmarking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index ded83b6d80c78..940b0234f8b58 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -598,7 +598,7 @@ benchmarks! { let balance = T::Currency::free_balance(stash); nominator_balances_before.push(balance); } - }: payout_stakers_by_page(RawOrigin::Signed(caller), validator.clone(), current_era, 0) + }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era) verify { let balance_after = T::Currency::free_balance(&validator); ensure!( From 2605e524f6aaa5bad3488c7a5d46ad425ff1d04b Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 8 Feb 2023 20:32:15 +0100 Subject: [PATCH 089/131] add a working draft of changelog --- frame/staking/CHANGELOG.md | 35 +++++++++++++++++++++++++++++++++ frame/staking/src/pallet/mod.rs | 1 + 2 files changed, 36 insertions(+) create mode 100644 frame/staking/CHANGELOG.md diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md new file mode 100644 index 0000000000000..01630c1270be4 --- /dev/null +++ b/frame/staking/CHANGELOG.md @@ -0,0 +1,35 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +The semantic versioning guarantees cover the interface to the substrate runtime which +includes this pallet as a dependency. This module will also add storage migrations whenever +changes require it. Stability with regard to offchain tooling is explicitly excluded from +this guarantee: For example adding a new field to an in-storage data structure will require +changes to frontends to properly display it. However, those changes will still be regarded +as a minor version bump. + +## [5.0.0] - UNRELEASED + +### Added + +- Unlimited number of nominators can be rewarded. +- New storage item `ExposurePageSize` to limit the number of nominators rewarded for a single call for reward payout. +- New storage item `ErasStakersPaged` that keeps upto `ExposurePageSize` individual nominator exposures by era, validator and page. +- New storage item `ErasStakersOverview` which complements `ErasStakersPaged` and keeps track of validator's own stake and total backing stake for each era. +- New call `payout_stakers_by_page` that allows to payout rewards for a single validator by passing the page explicitly. +- New storage item `ClaimedRewards` that keeps track of claimed reward history of a validator by era and page. + +### Changed +- `payout_stakers` can be called multiple times for the same era if the validator has more than `ExposurePageSize` nominators backing them. +- `MaxNominatorRewardedPerValidator` is renamed to `MaxExposurePageSize`. + +### Deprecated +- `ErasStakersClipped` is deprecated in favor of `ErasStakersPaged`. In 84 eras, `ErasStakersClipped` will be removed. +- `StakingLedger.claimed_rewards` is renamed to `StakingLedger.legacy_claimed_rewards` and is deprecated. + +### PRs +[#13059](https://github.com/paritytech/substrate/pull/13059) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 4224bea528ece..04c6ff8b44321 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -216,6 +216,7 @@ pub mod pallet { /// exposures. In future we should rename this to something like `ExposurePageSize` when we /// are ready to get rid of `ErasStakersClipped`. /// Refer issue: #13034 + /// TODO(ank4n): rename this to `MaxExposurePageSize`. #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; From 4104eb3b3f691eff9dbe4f566f206bbeb2d8e221 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 8 Feb 2023 20:50:18 +0100 Subject: [PATCH 090/131] small doc update --- frame/staking/src/lib.rs | 3 +++ frame/staking/src/pallet/mod.rs | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index f2ee79bb7e9f5..950fad52df264 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -818,6 +818,9 @@ impl Default for ExposureOverview { } /// Extended view of Exposure comprising of `ExposureOverview` and a single page of `ExposurePage`. +/// +/// 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 ExposureExt { exposure_overview: ExposureOverview, diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 04c6ff8b44321..4b54efe408bbe 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -642,10 +642,8 @@ pub mod pallet { pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; /// 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` for - /// accessing the following: (1) `ErasStakers`, (2) `ClaimedRewards`, (3) `ErasStakersClipped`, - /// (4) `ErasStakersPaged`, (5) `ErasTotalStake`. - // TODO(Ank4n): add all era related storage items in this struct + /// 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(sp_std::marker::PhantomData); impl EraInfo { /// Temporary function which looks at both (1) passed param `T::StakingLedger` for legacy From c1635b055fe2234fd64c95fb34c805481c609cb5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 12 Feb 2023 20:30:03 +0100 Subject: [PATCH 091/131] have a way to disable pages --- frame/staking/src/mock.rs | 4 ++++ frame/staking/src/pallet/mod.rs | 36 +++++++++++++++++++++++++++++++-- frame/staking/src/tests.rs | 19 +++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index c78eba7c2b66e..834c330bebeb9 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -819,3 +819,7 @@ pub(crate) fn staking_events_since_last_call() -> Vec> { pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) { (Balances::free_balance(who), Balances::reserved_balance(who)) } + +pub(crate) fn allow_exposure_pages(max_count: u32) { + MaxExposurePageCount::::put(max_count.max(1)); +} diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 4b54efe408bbe..566835208fdfb 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -482,6 +482,16 @@ pub mod pallet { #[pallet::storage] pub type ExposurePageSize = StorageValue<_, u32, OptionQuery>; + /// Maximum number of exposure pages that can be stored for a single validator in an era. + /// + /// Must be greater than 0. + /// + /// When this is set to 1, the reward payout behaviour is similar to how it used to work before + /// we had paged exposures. + #[pallet::storage] + // TODO(ank4n): Does it need #[pallet::getter(...)] + pub type MaxExposurePageCount = StorageValue<_, PageIndex, OptionQuery>; + /// Paginated exposure of a validator at given era. /// /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account @@ -650,7 +660,7 @@ pub mod pallet { /// non-paged rewards, and (2) `T::ClaimedRewards` for paged rewards. This function can be /// removed once `$HistoryDepth` eras have passed and none of the older non-paged rewards /// are relevant/claimable. - // TODO: Cleanup tracking issue: #13034 + // Refer tracker issue for cleanup: #13034 pub(crate) fn is_rewards_claimed_temp( era: EraIndex, ledger: &StakingLedger, @@ -742,6 +752,11 @@ pub mod pallet { >::contains_key(&era, validator) } + /// Returns the maximum number of pages of exposure we can store. + fn get_max_exposure_page_count() -> PageIndex { + return >::get().unwrap_or_default().max(1) + } + /// Returns validator commission for this era and page. pub(crate) fn get_validator_commission( era: EraIndex, @@ -777,12 +792,29 @@ pub mod pallet { exposure: Exposure>, ) { >::insert(era, &validator, &exposure); - // FIXME(ankan) Should we sort exposure.others for backward compatibility? let page_size = >::get() .unwrap_or_else(|| T::MaxNominatorRewardedPerValidator::get()) .clamp(1, T::MaxNominatorRewardedPerValidator::get()); + let max_page_count = Self::get_max_exposure_page_count(); + + let nominator_count = exposure.others.len(); + let page_count = nominator_count.saturating_add(page_size as usize - 1)/page_size as usize; + + // clip nominators if it exceeds the maximum page count. + let exposure = if page_count as PageIndex > max_page_count { + // sort before clipping. + let mut exposure_clipped = exposure; + let clipped_max_len = max_page_count * page_size; + + exposure_clipped.others.sort_by(|a, b| b.value.cmp(&a.value)); + exposure_clipped.others.truncate(clipped_max_len as usize); + exposure_clipped + } else { + exposure + }; + let (exposure_overview, exposure_pages) = exposure.into_pages(page_size); >::insert(era, &validator, &exposure_overview); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 8aaf0c264b251..ffbe4af9a35af 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3695,6 +3695,9 @@ fn six_session_delay() { #[test] fn test_nominators_are_rewarded_for_all_exposure_page() { ExtBuilder::default().build_and_execute(|| { + // enable multi paged rewards payout + allow_exposure_pages(3); + // 3 pages of exposure let nominator_count = 2 * MaxNominatorRewardedPerValidator::get() + 1; @@ -3743,6 +3746,10 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { fn test_multi_page_payout_stakers_by_page() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { + + // enable multi paged rewards payout + allow_exposure_pages(10); + let balance = 1000; // Track the exposure of the validator and all nominators. let mut total_exposure = balance; @@ -3933,6 +3940,9 @@ fn test_multi_page_payout_stakers_by_page() { fn test_multi_page_payout_stakers_backward_compatible() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { + // enable multi paged rewards payout + allow_exposure_pages(10); + let balance = 1000; // Track the exposure of the validator and all nominators. let mut total_exposure = balance; @@ -4160,6 +4170,9 @@ fn test_multi_page_payout_stakers_backward_compatible() { fn payout_stakers_handles_basic_errors() { // Here we will test payouts handle all errors. ExtBuilder::default().has_stakers(false).build_and_execute(|| { + // enable multi paged rewards payout + allow_exposure_pages(2); + // Consumed weight for all payout_stakers dispatches that fail let err_weight = ::WeightInfo::payout_stakers_alive_staked(0); @@ -4292,6 +4305,9 @@ fn payout_stakers_handles_basic_errors() { #[test] fn test_commission_paid_across_pages() { ExtBuilder::default().has_stakers(false).build_and_execute(|| { + // enable multi paged rewards payout + allow_exposure_pages(4); + let balance = 1; let commission = 50; // Create a validator: @@ -6209,6 +6225,9 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { #[test] fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout() { ExtBuilder::default().has_stakers(false).build_and_execute(|| { + // enable multi paged rewards payout + allow_exposure_pages(2); + // case 1: exposure exist in clipped. // set page cap to 10 MaxNominatorRewardedPerValidator::set(10); From 2985543ab1f3c66d943b3b43a152a8fa781fd26b Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 12 Feb 2023 20:58:25 +0100 Subject: [PATCH 092/131] fmt --- frame/staking/src/pallet/mod.rs | 3 ++- frame/staking/src/tests.rs | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 566835208fdfb..cd5b527cd25fe 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -800,7 +800,8 @@ pub mod pallet { let max_page_count = Self::get_max_exposure_page_count(); let nominator_count = exposure.others.len(); - let page_count = nominator_count.saturating_add(page_size as usize - 1)/page_size as usize; + let page_count = + nominator_count.saturating_add(page_size as usize - 1) / page_size as usize; // clip nominators if it exceeds the maximum page count. let exposure = if page_count as PageIndex > max_page_count { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index ffbe4af9a35af..99d9a31c5e778 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3746,7 +3746,6 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { fn test_multi_page_payout_stakers_by_page() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { - // enable multi paged rewards payout allow_exposure_pages(10); From fe5746b8069cc0fa939f2d0e79d55d95f1c6b0d6 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 12 Feb 2023 21:21:30 +0100 Subject: [PATCH 093/131] simple rename --- frame/staking/src/mock.rs | 4 ++-- frame/staking/src/tests.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 834c330bebeb9..5c339f7fb2c65 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -820,6 +820,6 @@ pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) { (Balances::free_balance(who), Balances::reserved_balance(who)) } -pub(crate) fn allow_exposure_pages(max_count: u32) { - MaxExposurePageCount::::put(max_count.max(1)); +pub(crate) fn allow_paged_rewards(max_pages: u32) { + MaxExposurePageCount::::put(max_pages.max(1)); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 99d9a31c5e778..0318074183617 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3696,7 +3696,7 @@ fn six_session_delay() { fn test_nominators_are_rewarded_for_all_exposure_page() { ExtBuilder::default().build_and_execute(|| { // enable multi paged rewards payout - allow_exposure_pages(3); + allow_paged_rewards(3); // 3 pages of exposure let nominator_count = 2 * MaxNominatorRewardedPerValidator::get() + 1; @@ -3747,7 +3747,7 @@ fn test_multi_page_payout_stakers_by_page() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { // enable multi paged rewards payout - allow_exposure_pages(10); + allow_paged_rewards(10); let balance = 1000; // Track the exposure of the validator and all nominators. @@ -3940,7 +3940,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { // enable multi paged rewards payout - allow_exposure_pages(10); + allow_paged_rewards(10); let balance = 1000; // Track the exposure of the validator and all nominators. @@ -4170,7 +4170,7 @@ fn payout_stakers_handles_basic_errors() { // Here we will test payouts handle all errors. ExtBuilder::default().has_stakers(false).build_and_execute(|| { // enable multi paged rewards payout - allow_exposure_pages(2); + allow_paged_rewards(2); // Consumed weight for all payout_stakers dispatches that fail let err_weight = ::WeightInfo::payout_stakers_alive_staked(0); @@ -4305,7 +4305,7 @@ fn payout_stakers_handles_basic_errors() { fn test_commission_paid_across_pages() { ExtBuilder::default().has_stakers(false).build_and_execute(|| { // enable multi paged rewards payout - allow_exposure_pages(4); + allow_paged_rewards(4); let balance = 1; let commission = 50; @@ -6225,7 +6225,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout() { ExtBuilder::default().has_stakers(false).build_and_execute(|| { // enable multi paged rewards payout - allow_exposure_pages(2); + allow_paged_rewards(2); // case 1: exposure exist in clipped. // set page cap to 10 From 43582af72678b612934955d8e0c6727869a832e5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 12 Feb 2023 21:51:19 +0100 Subject: [PATCH 094/131] test for page size and count --- frame/staking/src/pallet/mod.rs | 1 - frame/staking/src/tests.rs | 75 ++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index cd5b527cd25fe..0728d94d978a7 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -796,7 +796,6 @@ pub mod pallet { let page_size = >::get() .unwrap_or_else(|| T::MaxNominatorRewardedPerValidator::get()) .clamp(1, T::MaxNominatorRewardedPerValidator::get()); - let max_page_count = Self::get_max_exposure_page_count(); let nominator_count = exposure.others.len(); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 0318074183617..5edb776e2c780 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3935,7 +3935,6 @@ fn test_multi_page_payout_stakers_by_page() { } #[test] -//todo fn test_multi_page_payout_stakers_backward_compatible() { // Test that payout_stakers work in general and that it pays the correct amount of reward. ExtBuilder::default().has_stakers(false).build_and_execute(|| { @@ -4165,6 +4164,80 @@ fn test_multi_page_payout_stakers_backward_compatible() { }); } +#[test] +fn test_page_count_and_size() { + // Test that payout_stakers work in general and that it pays the correct amount of reward. + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + let balance = 1000; + // Track the exposure of the validator and all nominators. + // Create a validator: + bond_validator(11, 10, balance); // Default(64) + assert_eq!(Validators::::count(), 1); + + // Create nominators, targeting stash of validators + for i in 0..100 { + let bond_amount = balance + i as Balance; + bond_nominator(1000 + i, 100 + i, bond_amount, vec![11]); + } + + mock::start_active_era(1); + + // Since max exposure page count is 1, we should only have 1 page with clipped and sorted + // nominators. + assert_eq!(EraInfo::::get_page_count(1, &11), 1); + let exposure = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); + let mut previous_nominator_balance: Balance = u32::MAX as Balance; + exposure.others().iter().for_each(|e| { + // Nominators are sorted by balance in descending order. + assert!(e.value < previous_nominator_balance); + previous_nominator_balance = e.value; + }); + + // the last nominator balance is higher than the last 36 clipped nominators. + assert_eq!(previous_nominator_balance, 1000 + 36); + + // increase max page size + allow_paged_rewards(10); + mock::start_active_era(2); + + assert_eq!(EraInfo::::get_page_count(2, &11), 2); + // first page has 64 nominators + assert_eq!(EraInfo::::get_validator_exposure(2, &11, 0).unwrap().others().len(), 64); + // second page has 36 nominators + assert_eq!(EraInfo::::get_validator_exposure(2, &11, 1).unwrap().others().len(), 36); + + // now lets decrease page size + ExposurePageSize::::put(32); + mock::start_active_era(3); + // now we expect 4 pages. + assert_eq!(EraInfo::::get_page_count(3, &11), 4); + // first 3 pages have 32 nominators each + assert_eq!(EraInfo::::get_validator_exposure(3, &11, 0).unwrap().others().len(), 32); + assert_eq!(EraInfo::::get_validator_exposure(3, &11, 1).unwrap().others().len(), 32); + assert_eq!(EraInfo::::get_validator_exposure(3, &11, 2).unwrap().others().len(), 32); + assert_eq!(EraInfo::::get_validator_exposure(3, &11, 3).unwrap().others().len(), 4); + + // now lets decrease page size even more + ExposurePageSize::::put(9); + mock::start_active_era(4); + // now we expect the max 10 pages with each page having 9 nominators. + assert_eq!(EraInfo::::get_page_count(4, &11), 10); + + // all nominators are sorted by balance in descending order. + let mut previous_nominator_balance: Balance = u32::MAX as Balance; + for page in 0..10 { + let exposure = EraInfo::::get_validator_exposure(4, &11, page).unwrap(); + exposure.others().iter().for_each(|e| { + assert!(e.value < previous_nominator_balance); + previous_nominator_balance = e.value; + }); + } + + // the last nominator balance is higher than the last 10 clipped nominators. + assert_eq!(previous_nominator_balance, 1000 + 10); + }); +} + #[test] fn payout_stakers_handles_basic_errors() { // Here we will test payouts handle all errors. From 9fb0ad1becf6406b0011b9d531afab66949eb16f Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 12 Feb 2023 21:58:46 +0100 Subject: [PATCH 095/131] add the old test back --- frame/staking/src/tests.rs | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 5edb776e2c780..02221419e0f18 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3692,6 +3692,45 @@ fn six_session_delay() { }); } +#[test] +fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward() { + // with max exposure page count set to 1, clipped exposure logic works exactly as before. + ExtBuilder::default().build_and_execute(|| { + for i in 0..=MaxNominatorRewardedPerValidator::get() { + let stash = 10_000 + i as AccountId; + let controller = 20_000 + i as AccountId; + let balance = 10_000 + i as Balance; + Balances::make_free_balance_be(&stash, balance); + assert_ok!(Staking::bond( + RuntimeOrigin::signed(stash), + controller, + balance, + RewardDestination::Stash + )); + assert_ok!(Staking::nominate(RuntimeOrigin::signed(controller), vec![11])); + } + mock::start_active_era(1); + + Pallet::::reward_by_ids(vec![(11, 1)]); + // compute and ensure the reward amount is greater than zero. + let _ = current_total_payout_for_duration(reward_time_per_era()); + + mock::start_active_era(2); + mock::make_all_reward_payment(1); + + // Assert only nominators from 1 to Max are rewarded + for i in 0..=MaxNominatorRewardedPerValidator::get() { + let stash = 10_000 + i as AccountId; + let balance = 10_000 + i as Balance; + if stash == 10_000 { + assert!(Balances::free_balance(&stash) == balance); + } else { + assert!(Balances::free_balance(&stash) > balance); + } + } + }); +} + #[test] fn test_nominators_are_rewarded_for_all_exposure_page() { ExtBuilder::default().build_and_execute(|| { From df5054b7ab46639e09950e3cb979e774b6c029b0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 13 Feb 2023 00:10:23 +0100 Subject: [PATCH 096/131] update changelog --- frame/staking/CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 01630c1270be4..1854f2c9094c2 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -18,6 +18,8 @@ as a minor version bump. - Unlimited number of nominators can be rewarded. - New storage item `ExposurePageSize` to limit the number of nominators rewarded for a single call for reward payout. +- New storage item `MaxExposurePageCount` to limit the maximum number of exposure pages that can be created. If this +- value is not set, it defaults to 1, resulting in the same behaviour as we have today with clipped exposures. - New storage item `ErasStakersPaged` that keeps upto `ExposurePageSize` individual nominator exposures by era, validator and page. - New storage item `ErasStakersOverview` which complements `ErasStakersPaged` and keeps track of validator's own stake and total backing stake for each era. - New call `payout_stakers_by_page` that allows to payout rewards for a single validator by passing the page explicitly. @@ -31,5 +33,5 @@ as a minor version bump. - `ErasStakersClipped` is deprecated in favor of `ErasStakersPaged`. In 84 eras, `ErasStakersClipped` will be removed. - `StakingLedger.claimed_rewards` is renamed to `StakingLedger.legacy_claimed_rewards` and is deprecated. -### PRs -[#13059](https://github.com/paritytech/substrate/pull/13059) + +[5.0.0]: https://github.com/paritytech/substrate/pull/13059 From 33362c6e87b9bf282156b4a982d6f1d40418dc2f Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 19:09:50 +0100 Subject: [PATCH 097/131] todo tags --- frame/staking/CHANGELOG.md | 1 + frame/staking/src/pallet/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 1854f2c9094c2..263f5f6acf2d5 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -12,6 +12,7 @@ this guarantee: For example adding a new field to an in-storage data structure w changes to frontends to properly display it. However, those changes will still be regarded as a minor version bump. +[//]: # TODO(ank4n) these versions should be same as storage version ## [5.0.0] - UNRELEASED ### Added diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 0728d94d978a7..0b32688a7a9bf 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -64,6 +64,7 @@ pub mod pallet { use super::*; /// The current storage version. + /// TODO(ank4n) bump up const STORAGE_VERSION: StorageVersion = StorageVersion::new(13); #[pallet::pallet] From 773d24023b62ded782713224a386f3c4aad2f8cb Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 19:25:54 +0100 Subject: [PATCH 098/131] some renames and config vals --- bin/node/runtime/src/lib.rs | 6 +- frame/babe/src/mock.rs | 2 +- frame/fast-unstake/src/mock.rs | 2 +- frame/grandpa/src/mock.rs | 2 +- .../nomination-pools/benchmarking/src/mock.rs | 2 +- .../nomination-pools/test-staking/src/mock.rs | 2 +- frame/offences/benchmarking/src/mock.rs | 2 +- frame/root-offences/src/mock.rs | 2 +- frame/session/benchmarking/src/mock.rs | 2 +- frame/staking/CHANGELOG.md | 2 +- frame/staking/README.md | 2 +- frame/staking/src/benchmarking.rs | 12 +-- frame/staking/src/lib.rs | 4 +- frame/staking/src/mock.rs | 8 +- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 77 ++++++++----------- frame/staking/src/tests.rs | 18 ++--- 17 files changed, 68 insertions(+), 79 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index f8589036f7853..972bb44b729c9 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -538,7 +538,7 @@ parameter_types! { pub const BondingDuration: sp_staking::EraIndex = 24 * 28; pub const SlashDeferDuration: sp_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const MaxNominatorRewardedPerValidator: u32 = 256; + pub const MaxExposurePageSize: u32 = 256; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); pub OffchainRepeat: BlockNumber = 5; pub HistoryDepth: u32 = 84; @@ -571,7 +571,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxExposurePageSize = MaxExposurePageSize; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainExecution; @@ -594,7 +594,7 @@ impl pallet_fast_unstake::Config for Runtime { type Staking = Staking; type MaxErasToCheckPerBlock = ConstU32<1>; #[cfg(feature = "runtime-benchmarks")] - type MaxBackersPerValidator = MaxNominatorRewardedPerValidator; + type MaxBackersPerValidator = MaxExposurePageSize; type WeightInfo = (); } diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index b130677897883..9d4adfc28412f 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -192,7 +192,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index b20ba43ab3758..74bb5454f9cd3 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -146,7 +146,7 @@ impl pallet_staking::Config for Runtime { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); type HistoryDepth = ConstU32<84>; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = MockElection; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index a33fbb22d6ff8..e5d9b88ac0407 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -196,7 +196,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/nomination-pools/benchmarking/src/mock.rs b/frame/nomination-pools/benchmarking/src/mock.rs index 4e188ea7ef189..e60f726d6785e 100644 --- a/frame/nomination-pools/benchmarking/src/mock.rs +++ b/frame/nomination-pools/benchmarking/src/mock.rs @@ -107,7 +107,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; diff --git a/frame/nomination-pools/test-staking/src/mock.rs b/frame/nomination-pools/test-staking/src/mock.rs index 3d0ab2c6f35f3..6677907082f65 100644 --- a/frame/nomination-pools/test-staking/src/mock.rs +++ b/frame/nomination-pools/test-staking/src/mock.rs @@ -121,7 +121,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 233aa449d391c..ab49c29399d53 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -170,7 +170,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/root-offences/src/mock.rs b/frame/root-offences/src/mock.rs index 0937c43d6e519..4f0eb57c8620e 100644 --- a/frame/root-offences/src/mock.rs +++ b/frame/root-offences/src/mock.rs @@ -184,7 +184,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 4c4accbbfac8f..123bb3df88117 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -172,7 +172,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 263f5f6acf2d5..4345c9f261a28 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -28,7 +28,7 @@ as a minor version bump. ### Changed - `payout_stakers` can be called multiple times for the same era if the validator has more than `ExposurePageSize` nominators backing them. -- `MaxNominatorRewardedPerValidator` is renamed to `MaxExposurePageSize`. +- `MaxExposurePageSize` is renamed to `MaxExposurePageSize`. ### Deprecated - `ErasStakersClipped` is deprecated in favor of `ErasStakersPaged`. In 84 eras, `ErasStakersClipped` will be removed. diff --git a/frame/staking/README.md b/frame/staking/README.md index 043dc2088c0c1..d09f777ac8bbf 100644 --- a/frame/staking/README.md +++ b/frame/staking/README.md @@ -90,7 +90,7 @@ valid behavior_ while _punishing any misbehavior or lack of availability_. Rewards must be claimed for each era before it gets too old by [`HistoryDeth`] using the `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -validator as well as its nominators. Rewards are paged to maximum of [`Config::MaxNominatorRewardedPerValidator`] +validator as well as its nominators. Rewards are paged to maximum of [`Config::MaxExposurePageSize`] nominators per call. Each page of staker payout needs to be called separately to ensure all nominators are paid. This is to limit the i/o cost to mutate storage for each nominator's account. diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 940b0234f8b58..62d386e1ee959 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -546,10 +546,10 @@ benchmarks! { } payout_stakers_dead_controller { - let n in 0 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let n in 0 .. T::MaxExposurePageSize::get() as u32; let (validator, nominators) = create_validator_with_nominators::( n, - T::MaxNominatorRewardedPerValidator::get() as u32, + T::MaxExposurePageSize::get() as u32, true, RewardDestination::Controller, )?; @@ -579,10 +579,10 @@ benchmarks! { } payout_stakers_alive_staked { - let n in 0 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let n in 0 .. T::MaxExposurePageSize::get() as u32; let (validator, nominators) = create_validator_with_nominators::( n, - T::MaxNominatorRewardedPerValidator::get() as u32, + T::MaxExposurePageSize::get() as u32, false, RewardDestination::Staked, )?; @@ -976,7 +976,7 @@ mod tests { let (validator_stash, nominators) = create_validator_with_nominators::( n, - <::MaxNominatorRewardedPerValidator as Get<_>>::get(), + <::MaxExposurePageSize as Get<_>>::get(), false, RewardDestination::Staked, ) @@ -1006,7 +1006,7 @@ mod tests { let (validator_stash, _nominators) = create_validator_with_nominators::( n, - <::MaxNominatorRewardedPerValidator as Get<_>>::get(), + <::MaxExposurePageSize as Get<_>>::get(), false, RewardDestination::Staked, ) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 950fad52df264..d7410f432b487 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -114,7 +114,7 @@ //! //! Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the //! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -//! validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerValidator`] +//! validator as well as its nominators. Only the [`Config::MaxExposurePageSize`] //! biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each //! nominator's account. //! @@ -228,7 +228,7 @@ //! validator, proportional to the value staked behind the validator (_i.e._ dividing the //! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in //! [`Exposure`]). Note that payouts are made in pages with each page capped at -//! [`Config::MaxNominatorRewardedPerValidator`] nominators. The distribution of nominators across +//! [`Config::MaxExposurePageSize`] nominators. The distribution of nominators across //! pages are unsorted and depends on the election result provided by [`Config::ElectionProvider`]. //! //! All entities who receive a reward have the option to choose their reward destination through the diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 5c339f7fb2c65..4b6f4a92c25d1 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -230,7 +230,8 @@ parameter_types! { pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; pub static MaxNominations: u32 = 16; pub static HistoryDepth: u32 = 80; - pub static MaxNominatorRewardedPerValidator: u32 = 64; + pub static MaxExposurePageSize: u32 = 64; + pub static MaxExposurePageCount: u32 = 1; pub static MaxUnlockingChunks: u32 = 32; pub static RewardOnUnbalanceWasCalled: bool = false; pub static LedgerSlashPerEra: (BalanceOf, BTreeMap>) = (Zero::zero(), BTreeMap::new()); @@ -293,7 +294,8 @@ impl crate::pallet::pallet::Config for Test { type SessionInterface = Self; type EraPayout = ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxExposurePageSize = MaxExposurePageSize; + type MaxExposurePageCount = MaxExposurePageCount; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; type GenesisElectionProvider = Self::ElectionProvider; @@ -821,5 +823,5 @@ pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) { } pub(crate) fn allow_paged_rewards(max_pages: u32) { - MaxExposurePageCount::::put(max_pages.max(1)); + MaxExposurePageCount::set(max_pages.max(1)); } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 8846316854574..8b59759053914 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -285,7 +285,7 @@ impl Pallet { } T::Reward::on_unbalanced(total_imbalance); - debug_assert!(nominator_payout_count <= T::MaxNominatorRewardedPerValidator::get()); + debug_assert!(nominator_payout_count <= T::MaxExposurePageSize::get()); Ok(Some(T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count)).into()) } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 0b32688a7a9bf..e55ac7b4031f2 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -204,22 +204,26 @@ pub mod pallet { /// The maximum size of each `T::ExposurePage`. /// - /// An `ExposurePage` is bounded to a maximum of `MaxNominatorRewardedPerValidator` + /// An `ExposurePage` is bounded to a maximum of `MaxExposurePageSize` /// nominators. The actual page size is a dynamic value that is determined by the storage /// item `T::ExposurePageSize`. /// /// For older non-paged exposure, a reward payout was restricted to the top - /// `MaxNominatorRewardedPerValidator` nominators. This is to limit the i/o cost for the + /// `MaxExposurePageSize` nominators. This is to limit the i/o cost for the /// nominator payout. /// - /// The name is a bit misleading, because historically we used to reward the top - /// `MaxNominatorRewardedPerValidator` nominators by stake when we did not had paged - /// exposures. In future we should rename this to something like `ExposurePageSize` when we - /// are ready to get rid of `ErasStakersClipped`. - /// Refer issue: #13034 - /// TODO(ank4n): rename this to `MaxExposurePageSize`. + /// Note: `MaxExposurePageSize` is used to bound `ClaimedRewards` and is unsafe to reduce + /// without handling it in a migration. #[pallet::constant] - type MaxNominatorRewardedPerValidator: Get; + type MaxExposurePageSize: Get; + + /// Maximum number of exposure pages that can be stored for a single validator in an era. + /// + /// Must be greater than 0. + /// + /// When this is set to 1, the reward payout behaviour is similar to how it used to work + /// before we had paged exposures. + type MaxExposurePageCount: Get; /// The fraction of the validator set that is safe to be offending. /// After the threshold is reached a new era will be forced. @@ -456,7 +460,7 @@ pub mod pallet { /// New `Exposure`s are stored in a paged manner in `ErasStakersPaged` instead. /// /// This is similar to [`ErasStakers`] but number of nominators exposed is reduced to the - /// `T::MaxNominatorRewardedPerValidator` biggest stakers. + /// `T::MaxExposurePageSize` biggest stakers. /// (Note: the field `total` and `own` of the exposure remains unchanged). /// This is used to limit the i/o cost for the nominator payout. /// @@ -479,20 +483,10 @@ pub mod pallet { /// The nominator count each `ExposurePage` is capped at. /// - /// This cannot be greater than `T::MaxNominatorRewardedPerValidator`. + /// This cannot be greater than `T::MaxExposurePageSize`. #[pallet::storage] pub type ExposurePageSize = StorageValue<_, u32, OptionQuery>; - /// Maximum number of exposure pages that can be stored for a single validator in an era. - /// - /// Must be greater than 0. - /// - /// When this is set to 1, the reward payout behaviour is similar to how it used to work before - /// we had paged exposures. - #[pallet::storage] - // TODO(ank4n): Does it need #[pallet::getter(...)] - pub type MaxExposurePageCount = StorageValue<_, PageIndex, OptionQuery>; - /// Paginated exposure of a validator at given era. /// /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account @@ -753,11 +747,6 @@ pub mod pallet { >::contains_key(&era, validator) } - /// Returns the maximum number of pages of exposure we can store. - fn get_max_exposure_page_count() -> PageIndex { - return >::get().unwrap_or_default().max(1) - } - /// Returns validator commission for this era and page. pub(crate) fn get_validator_commission( era: EraIndex, @@ -795,16 +784,16 @@ pub mod pallet { >::insert(era, &validator, &exposure); let page_size = >::get() - .unwrap_or_else(|| T::MaxNominatorRewardedPerValidator::get()) - .clamp(1, T::MaxNominatorRewardedPerValidator::get()); - let max_page_count = Self::get_max_exposure_page_count(); + .unwrap_or_else(|| T::MaxExposurePageSize::get()) + .clamp(1, T::MaxExposurePageSize::get()); + let max_page_count = T::MaxExposurePageCount::get(); let nominator_count = exposure.others.len(); - let page_count = + let required_page_count = nominator_count.saturating_add(page_size as usize - 1) / page_size as usize; // clip nominators if it exceeds the maximum page count. - let exposure = if page_count as PageIndex > max_page_count { + let exposure = if required_page_count as PageIndex > max_page_count { // sort before clipping. let mut exposure_clipped = exposure; let clipped_max_len = max_page_count * page_size; @@ -1741,16 +1730,16 @@ pub mod pallet { /// This pays out the earliest exposure page not claimed for the era. If all pages are /// claimed, it returns an error `InvalidPage`. /// - /// If a validator has more than `T::MaxNominatorRewardedPerValidator` nominators backing + /// If a validator has more than `T::MaxExposurePageSize` nominators backing /// them, then the list of nominators is paged, with each page being capped at - /// `T::MaxNominatorRewardedPerValidator`. If a validator has more than one page of + /// `T::MaxExposurePageSize`. If a validator has more than one page of /// nominators, the call needs to be made for each page separately in order for all the /// nominators backing a validator receive the reward. The nominators are not sorted across /// pages and so it should not be assumed the highest staker would be on the topmost page /// and vice versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. /// /// # - /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). + /// - Time complexity: at most O(MaxExposurePageSize). /// - Contains a limited number of reads and writes. /// ----------- /// N is the Number of payouts for the validator (including the validator) @@ -1761,10 +1750,10 @@ pub mod pallet { /// NOTE: weights are assuming that payouts are made to alive stash account (Staked). /// Paying even a dead controller is cheaper weight-wise. We don't do any refunds here. /// # + /// ## Complexity + /// - At most O(MaxExposurePageSize). #[pallet::call_index(18)] - #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( - T::MaxNominatorRewardedPerValidator::get() - ))] + #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked(T::MaxExposurePageSize::get()))] pub fn payout_stakers( origin: OriginFor, validator_stash: T::AccountId, @@ -2067,21 +2056,21 @@ pub mod pallet { /// - `validator_stash` is the stash account of the validator. /// - `era` may be any era between `[current_era - history_depth; current_era]`. /// - `page` is the page index of nominators to pay out with value between 0 and - /// `num_nominators / T::MaxNominatorRewardedPerValidator`. + /// `num_nominators / T::MaxExposurePageSize`. /// /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// If a validator has more than `T::MaxNominatorRewardedPerValidator` nominators backing + /// If a validator has more than `T::MaxExposurePageSize` nominators backing /// them, then the list of nominators is paged, with each page being capped at - /// `T::MaxNominatorRewardedPerValidator`. If a validator has more than one page of + /// `T::MaxExposurePageSize`. If a validator has more than one page of /// nominators, the call needs to be made for each page separately in order for all the /// nominators backing a validator receive the reward. The nominators are not sorted across /// pages and so it should not be assumed the highest staker would be on the topmost page /// and vice versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. /// /// # - /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). + /// - Time complexity: at most O(MaxExposurePageSize). /// - Contains a limited number of reads and writes. /// ----------- /// N is the Number of payouts for the validator (including the validator) @@ -2093,9 +2082,7 @@ pub mod pallet { /// Paying even a dead controller is cheaper weight-wise. We don't do any refunds here. /// # #[pallet::call_index(26)] - #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked( - T::MaxNominatorRewardedPerValidator::get() - ))] + #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked(T::MaxExposurePageSize::get()))] pub fn payout_stakers_by_page( origin: OriginFor, validator_stash: T::AccountId, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 02221419e0f18..39facf95be9a5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2196,7 +2196,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; let (exposure_overview, _) = - exposure.clone().into_pages(MaxNominatorRewardedPerValidator::get()); + exposure.clone().into_pages(MaxExposurePageSize::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -3696,7 +3696,7 @@ fn six_session_delay() { fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward() { // with max exposure page count set to 1, clipped exposure logic works exactly as before. ExtBuilder::default().build_and_execute(|| { - for i in 0..=MaxNominatorRewardedPerValidator::get() { + for i in 0..=MaxExposurePageSize::get() { let stash = 10_000 + i as AccountId; let controller = 20_000 + i as AccountId; let balance = 10_000 + i as Balance; @@ -3719,7 +3719,7 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( mock::make_all_reward_payment(1); // Assert only nominators from 1 to Max are rewarded - for i in 0..=MaxNominatorRewardedPerValidator::get() { + for i in 0..=MaxExposurePageSize::get() { let stash = 10_000 + i as AccountId; let balance = 10_000 + i as Balance; if stash == 10_000 { @@ -3738,7 +3738,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { allow_paged_rewards(3); // 3 pages of exposure - let nominator_count = 2 * MaxNominatorRewardedPerValidator::get() + 1; + let nominator_count = 2 * MaxExposurePageSize::get() + 1; for i in 0..nominator_count { let stash = 10_000 + i as AccountId; @@ -3806,7 +3806,7 @@ fn test_multi_page_payout_stakers_by_page() { mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); - // Since `MaxNominatorRewardedPerValidator = 64`, there are two pages of validator exposure. + // Since `MaxExposurePageSize = 64`, there are two pages of validator exposure. assert_eq!(EraInfo::::get_page_count(1, &11), 2); // compute and ensure the reward amount is greater than zero. @@ -4000,7 +4000,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); - // Since `MaxNominatorRewardedPerValidator = 64`, there are two pages of validator exposure. + // Since `MaxExposurePageSize = 64`, there are two pages of validator exposure. assert_eq!(EraInfo::::get_page_count(1, &11), 2); // compute and ensure the reward amount is greater than zero. @@ -4438,7 +4438,7 @@ fn test_commission_paid_across_pages() { mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); - // Since `MaxNominatorRewardedPerValidator = 64`, there are four pages of validator + // Since `MaxExposurePageSize = 64`, there are four pages of validator // exposure. assert_eq!(EraInfo::::get_page_count(1, &11), 4); @@ -4473,7 +4473,7 @@ fn payout_stakers_handles_weight_refund() { // Note: this test relies on the assumption that `payout_stakers_alive_staked` is solely used by // `payout_stakers` to calculate the weight of each payout op. ExtBuilder::default().has_stakers(false).build_and_execute(|| { - let max_nom_rewarded = MaxNominatorRewardedPerValidator::get(); + let max_nom_rewarded = MaxExposurePageSize::get(); // Make sure the configured value is meaningful for our use. assert!(max_nom_rewarded >= 4); let half_max_nom_rewarded = max_nom_rewarded / 2; @@ -6341,7 +6341,7 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( // case 1: exposure exist in clipped. // set page cap to 10 - MaxNominatorRewardedPerValidator::set(10); + MaxExposurePageSize::set(10); bond_validator(11, 10, 1000); let mut expected_individual_exposures: Vec> = vec![]; let mut total_exposure: Balance = 0; From 2bb73c62ffd4ff8b96bf6d64646b8eb090ca6242 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 19:33:33 +0100 Subject: [PATCH 099/131] do not iterate twice --- frame/staking/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d7410f432b487..5f4f7495c36c4 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -746,16 +746,15 @@ impl for chunk in individual_chunks { let mut page_total: Balance = Zero::zero(); + let mut others: Vec> = vec![]; for individual in chunk.iter() { page_total = page_total.saturating_add(individual.value); + others.push(IndividualExposure { who: individual.who.clone(), value: individual.value }) } exposure_pages.push(ExposurePage { page_total, - others: chunk - .iter() - .map(|c| IndividualExposure { who: c.who.clone(), value: c.value }) - .collect(), + others, }); } From 3a6d4a8773a6b1225271e2fff58cb6f6c8b7eb64 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 19:34:51 +0100 Subject: [PATCH 100/131] rename --- frame/staking/src/lib.rs | 4 ++-- frame/staking/src/pallet/impls.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 5f4f7495c36c4..ace50172ffa56 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -845,8 +845,8 @@ impl ExposureExt Balance { + /// Returns total exposure of this validator for the current page + pub fn page_total(&self) -> Balance { self.exposure_page.page_total + self.exposure_overview.own } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 8b59759053914..251e4b01e86d5 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -240,7 +240,7 @@ impl Pallet { // Now let's calculate how this is split to the validator. let validator_exposure_part = Perbill::from_rational(exposure.own(), exposure.total()); let validator_staking_payout = validator_exposure_part * validator_leftover_payout; - let page_stake_part = Perbill::from_rational(exposure.current_total(), exposure.total()); + let page_stake_part = Perbill::from_rational(exposure.page_total(), exposure.total()); // validator commission is paid out in fraction across pages proportional to the page stake. let validator_commission_payout = page_stake_part * validator_total_commission_payout; From b994878520f5fa1da10aed999fee8a595e2b26bd Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 19:36:03 +0100 Subject: [PATCH 101/131] clean up --- frame/staking/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ace50172ffa56..262acab722b91 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -777,16 +777,9 @@ pub struct ExposurePage { #[codec(compact)] pub page_total: Balance, /// The portions of nominators stashes that are exposed. - /// TODO(ank4n): BoundedVec touches lot of code, skip for now. pub others: Vec>, } -impl Default for ExposurePage { - fn default() -> Self { - Self { page_total: Default::default(), others: vec![] } - } -} - /// An overview of stake backing a single validator. /// /// It, in combination with a list of `ExposurePage`s, can be used to reconstruct a full `Exposure` From 42ad72a6e1a2dceb5be00e8fa3582d93375cd048 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 20:14:25 +0100 Subject: [PATCH 102/131] pr fixes --- frame/staking/CHANGELOG.md | 52 ++++++++++++++++++++++----------- frame/staking/src/lib.rs | 17 +++-------- frame/staking/src/pallet/mod.rs | 2 +- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 4345c9f261a28..a7f5ce7de8f47 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -3,36 +3,54 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -The semantic versioning guarantees cover the interface to the substrate runtime which -includes this pallet as a dependency. This module will also add storage migrations whenever -changes require it. Stability with regard to offchain tooling is explicitly excluded from -this guarantee: For example adding a new field to an in-storage data structure will require -changes to frontends to properly display it. However, those changes will still be regarded +and this project adheres +to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +The semantic versioning guarantees cover the interface to the substrate runtime +which +includes this pallet as a dependency. This module will also add storage +migrations whenever +changes require it. Stability with regard to offchain tooling is explicitly +excluded from +this guarantee: For example adding a new field to an in-storage data structure +will require +changes to frontends to properly display it. However, those changes will still +be regarded as a minor version bump. [//]: # TODO(ank4n) these versions should be same as storage version + ## [5.0.0] - UNRELEASED ### Added - Unlimited number of nominators can be rewarded. -- New storage item `ExposurePageSize` to limit the number of nominators rewarded for a single call for reward payout. -- New storage item `MaxExposurePageCount` to limit the maximum number of exposure pages that can be created. If this -- value is not set, it defaults to 1, resulting in the same behaviour as we have today with clipped exposures. -- New storage item `ErasStakersPaged` that keeps upto `ExposurePageSize` individual nominator exposures by era, validator and page. -- New storage item `ErasStakersOverview` which complements `ErasStakersPaged` and keeps track of validator's own stake and total backing stake for each era. -- New call `payout_stakers_by_page` that allows to payout rewards for a single validator by passing the page explicitly. -- New storage item `ClaimedRewards` that keeps track of claimed reward history of a validator by era and page. +- New storage item `ExposurePageSize` to limit the number of nominators rewarded + for a single call for reward payout. +- New config item `MaxExposurePageCount` to limit the maximum number of exposure + pages that can be created. When set + to 1, we get the same behaviour of top n nominators eligible for reward as + today. +- New storage item `ErasStakersPaged` that keeps up to `ExposurePageSize` + individual nominator exposures by era, validator and page. +- New storage item `ErasStakersOverview` which complements `ErasStakersPaged` + and keeps track of validator's own stake and total backing stake for each era. +- New call `payout_stakers_by_page` that allows to payout rewards for a single + validator by passing the page explicitly. +- New storage item `ClaimedRewards` that keeps track of claimed reward history + of a validator by era and page. ### Changed -- `payout_stakers` can be called multiple times for the same era if the validator has more than `ExposurePageSize` nominators backing them. + +- `payout_stakers` can be called multiple times for the same era if the + validator has more than `ExposurePageSize` nominators backing them. - `MaxExposurePageSize` is renamed to `MaxExposurePageSize`. ### Deprecated -- `ErasStakersClipped` is deprecated in favor of `ErasStakersPaged`. In 84 eras, `ErasStakersClipped` will be removed. -- `StakingLedger.claimed_rewards` is renamed to `StakingLedger.legacy_claimed_rewards` and is deprecated. +- `ErasStakersClipped` is deprecated in favor of `ErasStakersPaged`. In 84 + eras, `ErasStakersClipped` will be removed. +- `StakingLedger.claimed_rewards` is renamed + to `StakingLedger.legacy_claimed_rewards` and is deprecated. [5.0.0]: https://github.com/paritytech/substrate/pull/13059 diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 262acab722b91..4b49393f49890 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -466,6 +466,8 @@ pub struct StakingLedger { pub unlocking: BoundedVec>, T::MaxUnlockingChunks>, /// List of eras for which the stakers behind a validator have claimed rewards. Only updated /// for validators. + /// + /// This is deprecated as of V14 and will be removed in future. pub legacy_claimed_rewards: BoundedVec, } @@ -784,7 +786,7 @@ pub struct ExposurePage { /// /// It, in combination with a list of `ExposurePage`s, can be used to reconstruct a full `Exposure` /// struct. This is useful for cases where we want to query a single page of `Exposure`s. -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default)] pub struct ExposureOverview { /// The total balance backing this validator. #[codec(compact)] @@ -794,21 +796,10 @@ pub struct ExposureOverview { pub own: Balance, /// Number of nominators backing this validator. pub nominator_count: u32, - /// Number of pages of backers. + /// Number of pages of nominators. pub page_count: PageIndex, } -impl Default for ExposureOverview { - fn default() -> Self { - Self { - total: Default::default(), - own: Default::default(), - nominator_count: Default::default(), - page_count: Default::default(), - } - } -} - /// Extended view of Exposure comprising of `ExposureOverview` and a single page of `ExposurePage`. /// /// This is useful where we need to take into account the validator's own stake and total exposure diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e55ac7b4031f2..ae579780224eb 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -683,7 +683,7 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) -> Option>> { - return match >::get(era, (validator, page)) { + match >::get(era, (validator, page)) { // return clipped exposure if page zero and paged exposure does not exist None if page == 0 => Some(ExposureExt::from_clipped(>::get(era, validator))), From 32cf960eb7aa1cc8cef5f7402900b5c33f560ea5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 20:14:46 +0100 Subject: [PATCH 103/131] fmt --- frame/staking/src/lib.rs | 14 ++++++++------ frame/staking/src/tests.rs | 3 +-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 4b49393f49890..a4b012972f6c8 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -751,13 +751,13 @@ impl let mut others: Vec> = vec![]; for individual in chunk.iter() { page_total = page_total.saturating_add(individual.value); - others.push(IndividualExposure { who: individual.who.clone(), value: individual.value }) + others.push(IndividualExposure { + who: individual.who.clone(), + value: individual.value, + }) } - exposure_pages.push(ExposurePage { - page_total, - others, - }); + exposure_pages.push(ExposurePage { page_total, others }); } ( @@ -786,7 +786,9 @@ pub struct ExposurePage { /// /// It, in combination with a list of `ExposurePage`s, can be used to reconstruct a full `Exposure` /// struct. This is useful for cases where we want to query a single page of `Exposure`s. -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default)] +#[derive( + PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default, +)] pub struct ExposureOverview { /// The total balance backing this validator. #[codec(compact)] diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 39facf95be9a5..9cecdcc14c4f8 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2195,8 +2195,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { let _ = Balances::make_free_balance_be(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; - let (exposure_overview, _) = - exposure.clone().into_pages(MaxExposurePageSize::get()); + let (exposure_overview, _) = exposure.clone().into_pages(MaxExposurePageSize::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), From 92c70d6c5c26a3d1ef440cd77b2372f35883a41a Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 15 Feb 2023 20:45:42 +0100 Subject: [PATCH 104/131] make it compile --- bin/node/runtime/src/lib.rs | 1 + frame/babe/src/mock.rs | 1 + frame/fast-unstake/src/mock.rs | 1 + frame/grandpa/src/mock.rs | 1 + frame/nomination-pools/benchmarking/src/mock.rs | 1 + frame/nomination-pools/test-staking/src/mock.rs | 1 + frame/offences/benchmarking/src/mock.rs | 1 + frame/root-offences/src/mock.rs | 1 + frame/session/benchmarking/src/mock.rs | 1 + frame/staking/src/lib.rs | 3 ++- 10 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 972bb44b729c9..f8b5ae9b1ec96 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -572,6 +572,7 @@ impl pallet_staking::Config for Runtime { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; type MaxExposurePageSize = MaxExposurePageSize; + type MaxExposurePageCount = ConstU32<1>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainExecution; diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 9d4adfc28412f..d906106b2fd22 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -193,6 +193,7 @@ impl pallet_staking::Config for Test { type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; type MaxExposurePageSize = ConstU32<64>; + type MaxExposurePageCount = ConstU32<1>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index 74bb5454f9cd3..56a23555e6fd0 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -147,6 +147,7 @@ impl pallet_staking::Config for Runtime { type NextNewSession = (); type HistoryDepth = ConstU32<84>; type MaxExposurePageSize = ConstU32<64>; + type MaxExposurePageCount = ConstU32<1>; type OffendingValidatorsThreshold = (); type ElectionProvider = MockElection; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index e5d9b88ac0407..4d27d2cfe3bd4 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -197,6 +197,7 @@ impl pallet_staking::Config for Test { type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; type MaxExposurePageSize = ConstU32<64>; + type MaxExposurePageCount = ConstU32<1>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/nomination-pools/benchmarking/src/mock.rs b/frame/nomination-pools/benchmarking/src/mock.rs index e60f726d6785e..177f3311e8e2f 100644 --- a/frame/nomination-pools/benchmarking/src/mock.rs +++ b/frame/nomination-pools/benchmarking/src/mock.rs @@ -107,6 +107,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); + type MaxExposurePageCount = ConstU32<1>; type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = diff --git a/frame/nomination-pools/test-staking/src/mock.rs b/frame/nomination-pools/test-staking/src/mock.rs index 6677907082f65..027865ab5e356 100644 --- a/frame/nomination-pools/test-staking/src/mock.rs +++ b/frame/nomination-pools/test-staking/src/mock.rs @@ -121,6 +121,7 @@ impl pallet_staking::Config for Runtime { type SessionInterface = (); type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = (); + type MaxExposurePageCount = ConstU32<1>; type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index ab49c29399d53..b008f379ca5f8 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -170,6 +170,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; + type MaxExposurePageCount = ConstU32<1>; type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/root-offences/src/mock.rs b/frame/root-offences/src/mock.rs index 4f0eb57c8620e..d8bf065baec5f 100644 --- a/frame/root-offences/src/mock.rs +++ b/frame/root-offences/src/mock.rs @@ -184,6 +184,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; + type MaxExposurePageCount = ConstU32<1>; type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 123bb3df88117..249cb2d3fd789 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -172,6 +172,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; + type MaxExposurePageCount = ConstU32<1>; type MaxExposurePageSize = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainExecution; diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index a4b012972f6c8..119b4df5b3780 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -467,7 +467,8 @@ pub struct StakingLedger { /// List of eras for which the stakers behind a validator have claimed rewards. Only updated /// for validators. /// - /// This is deprecated as of V14 and will be removed in future. + /// This is deprecated as of V14 in favor of `T::ClaimedRewards` and will be removed in future. + /// Refer issue: #13034 pub legacy_claimed_rewards: BoundedVec, } From 9559ec2c64fa324da29cd296b3d0ee82fb98a109 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 19 Feb 2023 20:29:19 +0100 Subject: [PATCH 105/131] keep only config item for MaxExposurePageSize --- frame/staking/CHANGELOG.md | 13 ++++++------- frame/staking/src/pallet/mod.rs | 19 +++++-------------- frame/staking/src/tests.rs | 4 ++-- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index a7f5ce7de8f47..77d7cdd73a01b 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -25,13 +25,12 @@ as a minor version bump. ### Added - Unlimited number of nominators can be rewarded. -- New storage item `ExposurePageSize` to limit the number of nominators rewarded for a single call for reward payout. -- New config item `MaxExposurePageCount` to limit the maximum number of exposure - pages that can be created. When set - to 1, we get the same behaviour of top n nominators eligible for reward as +- New config item `MaxExposurePageCount` to weakly bound the maximum number of + exposure pages that can exist. When set to 1, we get the same behaviour of top + n nominators eligible for reward as today. -- New storage item `ErasStakersPaged` that keeps up to `ExposurePageSize` +- New storage item `ErasStakersPaged` that keeps up to `MaxExposurePageSize` individual nominator exposures by era, validator and page. - New storage item `ErasStakersOverview` which complements `ErasStakersPaged` and keeps track of validator's own stake and total backing stake for each era. @@ -43,8 +42,8 @@ as a minor version bump. ### Changed - `payout_stakers` can be called multiple times for the same era if the - validator has more than `ExposurePageSize` nominators backing them. -- `MaxExposurePageSize` is renamed to `MaxExposurePageSize`. + validator has more than `MaxExposurePageSize` nominators backing them. +- `MaxNominatorRewardedPerValidator` is renamed to `MaxExposurePageSize`. ### Deprecated diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index ae579780224eb..634c1685436c0 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -58,6 +58,7 @@ pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; #[frame_support::pallet] pub mod pallet { use frame_election_provider_support::ElectionDataProvider; + use frame_support::traits::DefensiveMax; use crate::{BenchmarkingConfig, ExposureExt, ExposureOverview}; @@ -204,9 +205,8 @@ pub mod pallet { /// The maximum size of each `T::ExposurePage`. /// - /// An `ExposurePage` is bounded to a maximum of `MaxExposurePageSize` - /// nominators. The actual page size is a dynamic value that is determined by the storage - /// item `T::ExposurePageSize`. + /// An `ExposurePage` is weakly bounded to a maximum of `MaxExposurePageSize` + /// nominators. /// /// For older non-paged exposure, a reward payout was restricted to the top /// `MaxExposurePageSize` nominators. This is to limit the i/o cost for the @@ -480,13 +480,7 @@ pub mod pallet { Exposure>, ValueQuery, >; - - /// The nominator count each `ExposurePage` is capped at. - /// - /// This cannot be greater than `T::MaxExposurePageSize`. - #[pallet::storage] - pub type ExposurePageSize = StorageValue<_, u32, OptionQuery>; - + /// Paginated exposure of a validator at given era. /// /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account @@ -783,9 +777,7 @@ pub mod pallet { ) { >::insert(era, &validator, &exposure); - let page_size = >::get() - .unwrap_or_else(|| T::MaxExposurePageSize::get()) - .clamp(1, T::MaxExposurePageSize::get()); + let page_size = T::MaxExposurePageSize::get().defensive_max(1); let max_page_count = T::MaxExposurePageCount::get(); let nominator_count = exposure.others.len(); @@ -1722,7 +1714,6 @@ pub mod pallet { /// /// - `validator_stash` is the stash account of the validator. /// - `era` may be any era between `[current_era - history_depth; current_era]`. - /// `num_nominators / T::ExposurePageSize`. /// /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 9cecdcc14c4f8..af9877a30bc0b 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4245,7 +4245,7 @@ fn test_page_count_and_size() { assert_eq!(EraInfo::::get_validator_exposure(2, &11, 1).unwrap().others().len(), 36); // now lets decrease page size - ExposurePageSize::::put(32); + MaxExposurePageSize::set(32); mock::start_active_era(3); // now we expect 4 pages. assert_eq!(EraInfo::::get_page_count(3, &11), 4); @@ -4256,7 +4256,7 @@ fn test_page_count_and_size() { assert_eq!(EraInfo::::get_validator_exposure(3, &11, 3).unwrap().others().len(), 4); // now lets decrease page size even more - ExposurePageSize::::put(9); + MaxExposurePageSize::set(9); mock::start_active_era(4); // now we expect the max 10 pages with each page having 9 nominators. assert_eq!(EraInfo::::get_page_count(4, &11), 10); From 35393264baf268c4618a5a74074819e4d82c7365 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 19 Feb 2023 21:03:19 +0100 Subject: [PATCH 106/131] safe maths --- frame/staking/src/pallet/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 634c1685436c0..1420e9319d94c 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -480,7 +480,7 @@ pub mod pallet { Exposure>, ValueQuery, >; - + /// Paginated exposure of a validator at given era. /// /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account @@ -788,7 +788,7 @@ pub mod pallet { let exposure = if required_page_count as PageIndex > max_page_count { // sort before clipping. let mut exposure_clipped = exposure; - let clipped_max_len = max_page_count * page_size; + let clipped_max_len = max_page_count.saturating_mul(page_size); exposure_clipped.others.sort_by(|a, b| b.value.cmp(&a.value)); exposure_clipped.others.truncate(clipped_max_len as usize); From 34f2b08d0ccf9193f5761c5153c7f64878387c7d Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 19 Feb 2023 21:07:29 +0100 Subject: [PATCH 107/131] pr comment --- frame/staking/src/pallet/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 1420e9319d94c..9125e1624f479 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -781,8 +781,9 @@ pub mod pallet { let max_page_count = T::MaxExposurePageCount::get(); let nominator_count = exposure.others.len(); - let required_page_count = - nominator_count.saturating_add(page_size as usize - 1) / page_size as usize; + let required_page_count = nominator_count + .defensive_saturating_add(page_size as usize - 1) / + page_size as usize; // clip nominators if it exceeds the maximum page count. let exposure = if required_page_count as PageIndex > max_page_count { From 44bf53dfac81e5ac92978e2571f1deb5fc6e0939 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 00:08:01 +0100 Subject: [PATCH 108/131] simplify next claimable page --- frame/staking/src/pallet/mod.rs | 34 +++++++++++++-------------------- frame/staking/src/tests.rs | 8 ++++---- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 9125e1624f479..28fa9848773cc 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -58,7 +58,7 @@ pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; #[frame_support::pallet] pub mod pallet { use frame_election_provider_support::ElectionDataProvider; - use frame_support::traits::DefensiveMax; + use frame_support::{defensive, traits::DefensiveMax}; use crate::{BenchmarkingConfig, ExposureExt, ExposureOverview}; @@ -665,7 +665,7 @@ pub mod pallet { /// This is only used for paged rewards. Once older non-paged rewards are no longer /// relevant, `is_rewards_claimed_temp` can be removed and this function can be made public. fn is_rewards_claimed(era: EraIndex, validator: &T::AccountId, page: PageIndex) -> bool { - ClaimedRewards::::get(era, validator).binary_search(&page).is_ok() + ClaimedRewards::::get(era, validator).contains(&page) } /// Get exposure info for a validator at a given era and page. @@ -722,18 +722,10 @@ pub mod pallet { // Find next claimable page of paged exposure. let page_count = Self::get_page_count(era, validator); + let all_claimable_pages: Vec = (0..page_count).collect(); let claimed_pages = ClaimedRewards::::get(era, validator); - let claimed_page_count = claimed_pages.len() as PageIndex; - // find the first page that is not claimed. - for page in 0..claimed_page_count as PageIndex { - debug_assert!(page <= claimed_pages[page as usize]); - if page < claimed_pages[page as usize] { - return Some(page) - } - } - // all pages are claimed - return if claimed_page_count < page_count { Some(claimed_page_count) } else { None } + all_claimable_pages.into_iter().filter(|p| !claimed_pages.contains(p)).next() } /// Checks if exposure is paged or not. @@ -756,17 +748,17 @@ pub mod pallet { page: PageIndex, ) { let mut claimed_pages = ClaimedRewards::::get(era, validator); - let search = claimed_pages.binary_search(&page); - // this should never be called if the reward has already been claimed - debug_assert!(search.is_err()); - match search { - Err(index) => { - claimed_pages.insert(index, page); - ClaimedRewards::::insert(era, validator, claimed_pages); - }, - _ => {}, + // this should never be called if the reward has already been claimed + if claimed_pages.contains(&page) { + defensive!("Trying to set an already claimed reward"); + // nevertheless don't do anything since the page already exist in claimed rewards. + return } + + // add page to claimed entries + claimed_pages.push(page); + ClaimedRewards::::insert(era, validator, claimed_pages); } /// Store exposure for elected validators at start of an era. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index af9877a30bc0b..6eb3c7595a8a5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4159,7 +4159,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { // verify page 0 is claimed even when explicit page is not passed assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, last_reward_era,)); - assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![0, 1]); + assert_eq!(Staking::claimed_rewards(last_reward_era, &11), vec![1, 0]); // cannot claim any more pages assert_noop!( @@ -4186,7 +4186,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { assert_eq!(Staking::claimed_rewards(test_era, &11), vec![2]); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, test_era)); - assert_eq!(Staking::claimed_rewards(test_era, &11), vec![0, 2]); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![2, 0]); // cannot claim page 2 again assert_noop!( @@ -4195,10 +4195,10 @@ fn test_multi_page_payout_stakers_backward_compatible() { ); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, test_era)); - assert_eq!(Staking::claimed_rewards(test_era, &11), vec![0, 1, 2]); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![2, 0, 1]); assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, test_era)); - assert_eq!(Staking::claimed_rewards(test_era, &11), vec![0, 1, 2, 3]); + assert_eq!(Staking::claimed_rewards(test_era, &11), vec![2, 0, 1, 3]); }); } From 7fb81631f39342c3bdb6ddc6ac3924ef67cd3a3b Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 00:14:46 +0100 Subject: [PATCH 109/131] fix build --- frame/beefy/src/mock.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index 72e3f83dff91c..a625f6fb81ac6 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -221,7 +221,8 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = ConstU32<64>; + type MaxExposurePageSize = ConstU32<64>; + type MaxExposurePageCount = ConstU32<1>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainExecution; From 16500bc1abc76c4a13dcb383709af86b608be42e Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 00:35:39 +0100 Subject: [PATCH 110/131] pr comments --- frame/staking/CHANGELOG.md | 3 +-- frame/staking/src/lib.rs | 2 +- frame/staking/src/pallet/mod.rs | 2 ++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 77d7cdd73a01b..8f39fe86c9937 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -28,8 +28,7 @@ as a minor version bump. for a single call for reward payout. - New config item `MaxExposurePageCount` to weakly bound the maximum number of exposure pages that can exist. When set to 1, we get the same behaviour of top - n nominators eligible for reward as - today. + n nominators eligible for reward as previously with non paged exposures. - New storage item `ErasStakersPaged` that keeps up to `MaxExposurePageSize` individual nominator exposures by era, validator and page. - New storage item `ErasStakersOverview` which complements `ErasStakersPaged` diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 119b4df5b3780..ca42bc5f1d38b 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -806,7 +806,7 @@ pub struct ExposureOverview { /// Extended view of Exposure comprising of `ExposureOverview` and a single page of `ExposurePage`. /// /// 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. +/// in consideration, in addition to the individual nominators backing them. #[derive(Encode, Decode, RuntimeDebug, TypeInfo, PartialEq, Eq)] struct ExposureExt { exposure_overview: ExposureOverview, diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 28fa9848773cc..ce3c50543018a 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -701,6 +701,7 @@ pub mod pallet { /// /// This will always return at minimum one count of exposure to be backward compatible to /// non-paged reward payouts. + // FIXME: No need to return minimum of one page after cleanup: #13034 pub(crate) fn get_page_count(era: EraIndex, validator: &T::AccountId) -> PageIndex { >::get(&era, validator).page_count.max(1) } @@ -742,6 +743,7 @@ pub mod pallet { } /// Creates an entry to track validator reward has been claimed for a given era and page. + /// Noop if already claimed. pub(crate) fn set_rewards_as_claimed( era: EraIndex, validator: &T::AccountId, From 1ab67e5e7fba8441ddb37e44d2e9b7070cec84ac Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 01:05:14 +0100 Subject: [PATCH 111/131] clippy suggestion --- frame/staking/src/pallet/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index ce3c50543018a..c526afd9e97e7 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -726,7 +726,7 @@ pub mod pallet { let all_claimable_pages: Vec = (0..page_count).collect(); let claimed_pages = ClaimedRewards::::get(era, validator); - all_claimable_pages.into_iter().filter(|p| !claimed_pages.contains(p)).next() + all_claimable_pages.into_iter().find(|p| !claimed_pages.contains(p)) } /// Checks if exposure is paged or not. From e3265985ea09a63b86230d27093dc850a2b81c3e Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 21:48:07 +0100 Subject: [PATCH 112/131] write a new eras stakers --- frame/babe/src/tests.rs | 8 +- frame/beefy/src/tests.rs | 12 +-- frame/grandpa/src/tests.rs | 12 +-- frame/root-offences/src/lib.rs | 2 +- frame/staking/src/lib.rs | 6 ++ frame/staking/src/mock.rs | 2 +- frame/staking/src/pallet/impls.rs | 22 +++-- frame/staking/src/pallet/mod.rs | 43 ++++++--- frame/staking/src/tests.rs | 144 +++++++++++++++--------------- 9 files changed, 142 insertions(+), 109 deletions(-) diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs index 68426d0a8636e..0c9a3f7db7c5c 100644 --- a/frame/babe/src/tests.rs +++ b/frame/babe/src/tests.rs @@ -437,7 +437,7 @@ fn report_equivocation_current_session_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(1, validator), + Staking::eras_stakers(1, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -478,7 +478,7 @@ fn report_equivocation_current_session_works() { assert_eq!(Balances::total_balance(&offending_validator_id), 10_000_000 - 10_000); assert_eq!(Staking::slashable_balance_of(&offending_validator_id), 0); assert_eq!( - Staking::eras_stakers(2, offending_validator_id), + Staking::eras_stakers(2, &offending_validator_id), pallet_staking::Exposure { total: 0, own: 0, others: vec![] }, ); @@ -491,7 +491,7 @@ fn report_equivocation_current_session_works() { assert_eq!(Balances::total_balance(validator), 10_000_000); assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(2, validator), + Staking::eras_stakers(2, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -550,7 +550,7 @@ fn report_equivocation_old_session_works() { assert_eq!(Balances::total_balance(&offending_validator_id), 10_000_000 - 10_000); assert_eq!(Staking::slashable_balance_of(&offending_validator_id), 0); assert_eq!( - Staking::eras_stakers(3, offending_validator_id), + Staking::eras_stakers(3, &offending_validator_id), pallet_staking::Exposure { total: 0, own: 0, others: vec![] }, ); }) diff --git a/frame/beefy/src/tests.rs b/frame/beefy/src/tests.rs index f9da20e90dc74..426109cea4428 100644 --- a/frame/beefy/src/tests.rs +++ b/frame/beefy/src/tests.rs @@ -277,7 +277,7 @@ fn report_equivocation_current_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(1, validator), + Staking::eras_stakers(1, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -315,7 +315,7 @@ fn report_equivocation_current_set_works() { assert_eq!(Balances::total_balance(&equivocation_validator_id), 10_000_000 - 10_000); assert_eq!(Staking::slashable_balance_of(&equivocation_validator_id), 0); assert_eq!( - Staking::eras_stakers(2, equivocation_validator_id), + Staking::eras_stakers(2, &equivocation_validator_id), pallet_staking::Exposure { total: 0, own: 0, others: vec![] }, ); @@ -329,7 +329,7 @@ fn report_equivocation_current_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(2, validator), + Staking::eras_stakers(2, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -365,7 +365,7 @@ fn report_equivocation_old_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(2, validator), + Staking::eras_stakers(2, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -399,7 +399,7 @@ fn report_equivocation_old_set_works() { assert_eq!(Balances::total_balance(&equivocation_validator_id), 10_000_000 - 10_000); assert_eq!(Staking::slashable_balance_of(&equivocation_validator_id), 0); assert_eq!( - Staking::eras_stakers(3, equivocation_validator_id), + Staking::eras_stakers(3, &equivocation_validator_id), pallet_staking::Exposure { total: 0, own: 0, others: vec![] }, ); @@ -413,7 +413,7 @@ fn report_equivocation_old_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(3, validator), + Staking::eras_stakers(3, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs index 0bf3c8ddf63dc..9ee96fb0e3814 100644 --- a/frame/grandpa/src/tests.rs +++ b/frame/grandpa/src/tests.rs @@ -334,7 +334,7 @@ fn report_equivocation_current_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(1, validator), + Staking::eras_stakers(1, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -372,7 +372,7 @@ fn report_equivocation_current_set_works() { assert_eq!(Balances::total_balance(&equivocation_validator_id), 10_000_000 - 10_000); assert_eq!(Staking::slashable_balance_of(&equivocation_validator_id), 0); assert_eq!( - Staking::eras_stakers(2, equivocation_validator_id), + Staking::eras_stakers(2, &equivocation_validator_id), pallet_staking::Exposure { total: 0, own: 0, others: vec![] }, ); @@ -386,7 +386,7 @@ fn report_equivocation_current_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(2, validator), + Staking::eras_stakers(2, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -418,7 +418,7 @@ fn report_equivocation_old_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(2, validator), + Staking::eras_stakers(2, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } @@ -451,7 +451,7 @@ fn report_equivocation_old_set_works() { assert_eq!(Staking::slashable_balance_of(&equivocation_validator_id), 0); assert_eq!( - Staking::eras_stakers(3, equivocation_validator_id), + Staking::eras_stakers(3, &equivocation_validator_id), pallet_staking::Exposure { total: 0, own: 0, others: vec![] }, ); @@ -465,7 +465,7 @@ fn report_equivocation_old_set_works() { assert_eq!(Staking::slashable_balance_of(validator), 10_000); assert_eq!( - Staking::eras_stakers(3, validator), + Staking::eras_stakers(3, &validator), pallet_staking::Exposure { total: 10_000, own: 10_000, others: vec![] }, ); } diff --git a/frame/root-offences/src/lib.rs b/frame/root-offences/src/lib.rs index 92f3e17b5e17e..692feef6c3a52 100644 --- a/frame/root-offences/src/lib.rs +++ b/frame/root-offences/src/lib.rs @@ -112,7 +112,7 @@ pub mod pallet { .clone() .into_iter() .map(|(o, _)| OffenceDetails:: { - offender: (o.clone(), Staking::::eras_stakers(now, o)), + offender: (o.clone(), Staking::::eras_stakers(now, &o)), reporters: vec![], }) .collect()) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ca42bc5f1d38b..31bc8f5ffdf3c 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -783,6 +783,12 @@ pub struct ExposurePage { pub others: Vec>, } +impl Default for ExposurePage { + fn default() -> Self { + ExposurePage { page_total: Default::default(), others: vec![] } + } +} + /// An overview of stake backing a single validator. /// /// It, in combination with a list of `ExposurePage`s, can be used to reconstruct a full `Exposure` diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 4b6f4a92c25d1..76c8532b9d8cd 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -742,7 +742,7 @@ pub(crate) fn on_offence_now( pub(crate) fn add_slash(who: &AccountId) { on_offence_now( &[OffenceDetails { - offender: (*who, Staking::eras_stakers(active_era(), *who)), + offender: (*who, Staking::eras_stakers(active_era(), who)), reporters: vec![], }], &[Perbill::from_percent(10)], diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 251e4b01e86d5..ed9c2d1fea577 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -42,11 +42,7 @@ use sp_staking::{ }; use sp_std::prelude::*; -use crate::{ - log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, Exposure, ExposureOf, - Forcing, IndividualExposure, MaxWinnersOf, Nominations, PositiveImbalanceOf, RewardDestination, - SessionInterface, StakingLedger, ValidatorPrefs, -}; +use crate::{log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, MaxWinnersOf, Nominations, PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs}; use super::{pallet::*, STAKING_ID}; @@ -995,6 +991,22 @@ impl Pallet { DispatchClass::Mandatory, ); } + + pub fn eras_stakers(era: EraIndex, account: &T::AccountId) -> Exposure> { + let overview = EraInfo::::get_validator_overview(era, &account).unwrap_or_default(); + if overview.page_count == 0 { + return Exposure { total: overview.total, own: overview.own, others: vec![] }; + } + + let mut others = Vec::with_capacity(overview.nominator_count as usize); + for page in 0..overview.page_count { + let nominators = EraInfo::::get_nominators_page(era, &account, page); + // TODO(ank4n) fix to defensive unwrap + others.append(&mut nominators.unwrap().others); + } + + Exposure { total: overview.total, own: overview.own, others } + } } impl Pallet { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index c526afd9e97e7..33728953f3fe7 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -418,7 +418,7 @@ pub mod pallet { /// Is it removed after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. #[pallet::storage] - #[pallet::getter(fn eras_stakers)] + // #[pallet::getter(fn eras_stakers)] #[pallet::unbounded] pub type ErasStakers = StorageDoubleMap< _, @@ -451,7 +451,7 @@ pub mod pallet { Twox64Concat, T::AccountId, ExposureOverview>, - ValueQuery, + OptionQuery, >; /// Clipped Exposure of validator at era. @@ -677,33 +677,50 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) -> Option>> { - match >::get(era, (validator, page)) { + match >::get(&era, validator) { // return clipped exposure if page zero and paged exposure does not exist None if page == 0 => Some(ExposureExt::from_clipped(>::get(era, validator))), // return paged exposure if it exists - Some(exposure_page) => { - let overview = >::get(&era, validator); - // own stake is included only once in the first page. + Some(overview) => { + let exposure_page = + >::get(era, (validator, page)).unwrap_or_default(); let own = if page == 0 { overview.own } else { Zero::zero() }; - - Some(ExposureExt { - exposure_overview: ExposureOverview { own, ..overview }, - exposure_page, - }) - }, + Some(ExposureExt { exposure_overview: ExposureOverview { own, ..overview }, exposure_page }) + } _ => None, } } + pub(crate) fn get_validator_overview( + era: EraIndex, + validator: &T::AccountId, + ) -> Option>> { + >::get(&era, validator) + } + + pub(crate) fn get_nominators_page( + era: EraIndex, + validator: &T::AccountId, + page: PageIndex, + ) -> Option>> { + >::get(era, (validator, page)) + } + /// Returns the number of pages of exposure a validator has for the given era. /// /// This will always return at minimum one count of exposure to be backward compatible to /// non-paged reward payouts. // FIXME: No need to return minimum of one page after cleanup: #13034 pub(crate) fn get_page_count(era: EraIndex, validator: &T::AccountId) -> PageIndex { - >::get(&era, validator).page_count.max(1) + if let Some(overview) = >::get(&era, validator) { + // Paged exposure + overview.page_count.max(1) + } else { + // Non-paged exposure + 1 + } } /// Returns the next page that can be claimed or `None` if nothing to claim. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 6eb3c7595a8a5..49c0803e53b43 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -195,7 +195,7 @@ fn basic_setup_works() { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( - Staking::eras_stakers(active_era(), 11), + Staking::eras_stakers(active_era(), &11), Exposure { total: 1125, own: 1000, @@ -203,7 +203,7 @@ fn basic_setup_works() { }, ); assert_eq!( - Staking::eras_stakers(active_era(), 21), + Staking::eras_stakers(active_era(), &21), Exposure { total: 1375, own: 1000, @@ -619,7 +619,7 @@ fn nominating_and_rewards_should_work() { assert_eq!(ErasStakers::::iter_prefix_values(active_era()).count(), 2); assert_eq!( - Staking::eras_stakers(active_era(), 11), + Staking::eras_stakers(active_era(), &11), Exposure { total: 1000 + 800, own: 1000, @@ -630,7 +630,7 @@ fn nominating_and_rewards_should_work() { }, ); assert_eq!( - Staking::eras_stakers(active_era(), 21), + Staking::eras_stakers(active_era(), &21), Exposure { total: 1000 + 1200, own: 1000, @@ -690,7 +690,7 @@ fn nominators_also_get_slashed_pro_rata() { ExtBuilder::default().build_and_execute(|| { mock::start_active_era(1); let slash_percent = Perbill::from_percent(5); - let initial_exposure = Staking::eras_stakers(active_era(), 11); + let initial_exposure = Staking::eras_stakers(active_era(), &11); // 101 is a nominator for 11 assert_eq!(initial_exposure.others.first().unwrap().who, 101); @@ -958,7 +958,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::eras_stakers(active_era(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(RuntimeOrigin::signed(11), 20, 1), @@ -983,7 +983,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 has some free balance assert_eq!(Balances::free_balance(21), 2000); // Confirm account 21 (via controller 20) is totally staked - assert_eq!(Staking::eras_stakers(active_era(), 21).total, 1000); + assert_eq!(Staking::eras_stakers(active_era(), &21).total, 1000); // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(RuntimeOrigin::signed(21), 20, 1001), @@ -1002,7 +1002,7 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::eras_stakers(active_era(), 11).own, 1000); + assert_eq!(Staking::eras_stakers(active_era(), &11).own, 1000); // Confirm account 11 cannot reserve as a result assert_noop!(Balances::reserve(&11, 1), BalancesError::::LiquidityRestrictions); @@ -1150,7 +1150,7 @@ fn validator_payment_prefs_work() { // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); - let exposure_1 = Staking::eras_stakers(active_era(), 11); + let exposure_1 = Staking::eras_stakers(active_era(), &11); Pallet::::reward_by_ids(vec![(11, 1)]); mock::start_active_era(2); @@ -1256,7 +1256,7 @@ fn bond_extra_and_withdraw_unbonded_works() { }) ); assert_eq!( - Staking::eras_stakers(active_era(), 11), + Staking::eras_stakers(active_era(), &11), Exposure { total: 1000, own: 1000, others: vec![] } ); @@ -1275,7 +1275,7 @@ fn bond_extra_and_withdraw_unbonded_works() { ); // Exposure is a snapshot! only updated after the next era update. assert_ne!( - Staking::eras_stakers(active_era(), 11), + Staking::eras_stakers(active_era(), &11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] } ); @@ -1296,7 +1296,7 @@ fn bond_extra_and_withdraw_unbonded_works() { ); // Exposure is now updated. assert_eq!( - Staking::eras_stakers(active_era(), 11), + Staking::eras_stakers(active_era(), &11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] } ); @@ -1728,8 +1728,8 @@ fn reward_to_stake_works() { // Confirm account 10 and 20 are validators assert!(>::contains_key(&11) && >::contains_key(&21)); - assert_eq!(Staking::eras_stakers(active_era(), 11).total, 1000); - assert_eq!(Staking::eras_stakers(active_era(), 21).total, 2000); + assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000); + assert_eq!(Staking::eras_stakers(active_era(), &21).total, 2000); // Give the man some money. let _ = Balances::make_free_balance_be(&10, 1000); @@ -1757,8 +1757,8 @@ fn reward_to_stake_works() { mock::start_active_era(1); mock::make_all_reward_payment(0); - assert_eq!(Staking::eras_stakers(active_era(), 11).total, 1000); - assert_eq!(Staking::eras_stakers(active_era(), 21).total, 69); + assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000); + assert_eq!(Staking::eras_stakers(active_era(), &21).total, 69); let _11_balance = Balances::free_balance(&11); assert_eq!(_11_balance, 1000 + total_payout_0 / 2); @@ -1767,8 +1767,8 @@ fn reward_to_stake_works() { mock::start_active_era(2); // -- new infos - assert_eq!(Staking::eras_stakers(active_era(), 11).total, 1000 + total_payout_0 / 2); - assert_eq!(Staking::eras_stakers(active_era(), 21).total, 69 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(active_era(), &21).total, 69 + total_payout_0 / 2); }); } @@ -1904,8 +1904,8 @@ fn wrong_vote_is_moot() { assert_eq_uvec!(validator_controllers(), vec![20, 10]); // our new voter is taken into account - assert!(Staking::eras_stakers(active_era(), 11).others.iter().any(|i| i.who == 61)); - assert!(Staking::eras_stakers(active_era(), 21).others.iter().any(|i| i.who == 61)); + assert!(Staking::eras_stakers(active_era(), &11).others.iter().any(|i| i.who == 61)); + assert!(Staking::eras_stakers(active_era(), &21).others.iter().any(|i| i.who == 61)); }); } @@ -2004,7 +2004,7 @@ fn bond_with_little_staked_value_bounded() { // 2 is elected. assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::eras_stakers(active_era(), 2).total, 0); + assert_eq!(Staking::eras_stakers(active_era(), &2).total, 0); // Old ones are rewarded. assert_eq_error_rate!( @@ -2022,7 +2022,7 @@ fn bond_with_little_staked_value_bounded() { mock::make_all_reward_payment(1); assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::eras_stakers(active_era(), 2).total, 0); + assert_eq!(Staking::eras_stakers(active_era(), &2).total, 0); // 2 is now rewarded. assert_eq_error_rate!( @@ -2177,8 +2177,8 @@ fn phragmen_should_not_overflow() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // We can safely convert back to values within [u64, u128]. - assert!(Staking::eras_stakers(active_era(), 3).total > Votes::max_value() as Balance); - assert!(Staking::eras_stakers(active_era(), 5).total > Votes::max_value() as Balance); + assert!(Staking::eras_stakers(active_era(), &3).total > Votes::max_value() as Balance); + assert!(Staking::eras_stakers(active_era(), &5).total > Votes::max_value() as Balance); }) } @@ -2195,7 +2195,6 @@ fn reward_validator_slashing_validator_does_not_overflow() { let _ = Balances::make_free_balance_be(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; - let (exposure_overview, _) = exposure.clone().into_pages(MaxExposurePageSize::get()); let reward = EraRewardPoints:: { total: 1, individual: vec![(11, 1)].into_iter().collect(), @@ -2203,8 +2202,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { // Check reward ErasRewardPoints::::insert(0, reward); - ErasStakers::::insert(0, 11, &exposure); - ErasStakersOverview::::insert(0, 11, exposure_overview); + EraInfo::::set_validator_exposure(0, &11, exposure); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 0)); assert_eq!(Balances::total_balance(&11), stake * 2); @@ -2217,9 +2215,9 @@ fn reward_validator_slashing_validator_does_not_overflow() { Staking::bond(RuntimeOrigin::signed(2), 20000, stake - 1, RewardDestination::default()) .unwrap(); // Override exposure of 11 - ErasStakers::::insert( + EraInfo::::set_validator_exposure( 0, - 11, + &11, Exposure { total: stake, own: 1, @@ -2230,7 +2228,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { // Check slashing on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(100)], @@ -2329,7 +2327,7 @@ fn offence_forces_new_era() { ExtBuilder::default().build_and_execute(|| { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(5)], @@ -2347,7 +2345,7 @@ fn offence_ensures_new_era_without_clobbering() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(5)], @@ -2365,7 +2363,7 @@ fn offence_deselects_validator_even_when_slash_is_zero() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(0)], @@ -2386,7 +2384,7 @@ fn slashing_performed_according_exposure() { // This test checks that slashing is performed according the exposure (or more precisely, // historical exposure), not the current balance. ExtBuilder::default().build_and_execute(|| { - assert_eq!(Staking::eras_stakers(active_era(), 11).own, 1000); + assert_eq!(Staking::eras_stakers(active_era(), &11).own, 1000); // Handle an offence with a historical exposure. on_offence_now( @@ -2412,7 +2410,7 @@ fn slash_in_old_span_does_not_deselect() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(0)], @@ -2435,7 +2433,7 @@ fn slash_in_old_span_does_not_deselect() { on_offence_in_era( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(0)], @@ -2451,7 +2449,7 @@ fn slash_in_old_span_does_not_deselect() { on_offence_in_era( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], // NOTE: A 100% slash here would clean up the account, causing de-registration. @@ -2478,11 +2476,11 @@ fn reporters_receive_their_slice() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(Staking::eras_stakers(active_era(), 11).total, initial_balance); + assert_eq!(Staking::eras_stakers(active_era(), &11).total, initial_balance); on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![1, 2], }], &[Perbill::from_percent(50)], @@ -2505,11 +2503,11 @@ fn subsequent_reports_in_same_span_pay_out_less() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(Staking::eras_stakers(active_era(), 11).total, initial_balance); + assert_eq!(Staking::eras_stakers(active_era(), &11).total, initial_balance); on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![1], }], &[Perbill::from_percent(20)], @@ -2522,7 +2520,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![1], }], &[Perbill::from_percent(50)], @@ -2544,7 +2542,7 @@ fn invulnerables_are_not_slashed() { assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Balances::free_balance(21), 2000); - let exposure = Staking::eras_stakers(active_era(), 21); + let exposure = Staking::eras_stakers(active_era(), &21); let initial_balance = Staking::slashable_balance_of(&21); let nominator_balances: Vec<_> = @@ -2553,11 +2551,11 @@ fn invulnerables_are_not_slashed() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }, OffenceDetails { - offender: (21, Staking::eras_stakers(active_era(), 21)), + offender: (21, Staking::eras_stakers(active_era(), &21)), reporters: vec![], }, ], @@ -2587,7 +2585,7 @@ fn dont_slash_if_fraction_is_zero() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(0)], @@ -2608,7 +2606,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(50)], @@ -2620,7 +2618,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(25)], @@ -2631,7 +2629,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(60)], @@ -2653,7 +2651,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -2665,7 +2663,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(100)], @@ -2702,12 +2700,12 @@ fn garbage_collection_on_window_pruning() { assert_eq!(Balances::free_balance(11), 1000); let now = active_era(); - let exposure = Staking::eras_stakers(now, 11); + let exposure = Staking::eras_stakers(now, &11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( - &[OffenceDetails { offender: (11, Staking::eras_stakers(now, 11)), reporters: vec![] }], + &[OffenceDetails { offender: (11, Staking::eras_stakers(now, &11)), reporters: vec![] }], &[Perbill::from_percent(10)], ); @@ -2742,14 +2740,14 @@ fn slashing_nominators_by_span_max() { assert_eq!(Balances::free_balance(101), 2000); assert_eq!(Staking::slashable_balance_of(&21), 1000); - let exposure_11 = Staking::eras_stakers(active_era(), 11); - let exposure_21 = Staking::eras_stakers(active_era(), 21); + let exposure_11 = Staking::eras_stakers(active_era(), &11); + let exposure_21 = Staking::eras_stakers(active_era(), &21); let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value; let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_in_era( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -2776,7 +2774,7 @@ fn slashing_nominators_by_span_max() { // second slash: higher era, higher value, same span. on_offence_in_era( &[OffenceDetails { - offender: (21, Staking::eras_stakers(active_era(), 21)), + offender: (21, Staking::eras_stakers(active_era(), &21)), reporters: vec![], }], &[Perbill::from_percent(30)], @@ -2798,7 +2796,7 @@ fn slashing_nominators_by_span_max() { // in-era value, but lower slash value than slash 2. on_offence_in_era( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(20)], @@ -2833,7 +2831,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[OffenceDetails { - offender: (21, Staking::eras_stakers(active_era(), 21)), + offender: (21, Staking::eras_stakers(active_era(), &21)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -2856,7 +2854,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[OffenceDetails { - offender: (21, Staking::eras_stakers(active_era(), 21)), + offender: (21, Staking::eras_stakers(active_era(), &21)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -2880,7 +2878,7 @@ fn deferred_slashes_are_deferred() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(active_era(), 11); + let exposure = Staking::eras_stakers(active_era(), &11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2888,7 +2886,7 @@ fn deferred_slashes_are_deferred() { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -2939,7 +2937,7 @@ fn retroactive_deferred_slashes_two_eras_before() { assert_eq!(BondingDuration::get(), 3); mock::start_active_era(1); - let exposure_11_at_era1 = Staking::eras_stakers(active_era(), 11); + let exposure_11_at_era1 = Staking::eras_stakers(active_era(), &11); mock::start_active_era(3); @@ -2975,7 +2973,7 @@ fn retroactive_deferred_slashes_one_before() { assert_eq!(BondingDuration::get(), 3); mock::start_active_era(1); - let exposure_11_at_era1 = Staking::eras_stakers(active_era(), 11); + let exposure_11_at_era1 = Staking::eras_stakers(active_era(), &11); // unbond at slash era. mock::start_active_era(2); @@ -3023,12 +3021,12 @@ fn staker_cannot_bail_deferred_slash() { assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Balances::free_balance(101), 2000); - let exposure = Staking::eras_stakers(active_era(), 11); + let exposure = Staking::eras_stakers(active_era(), &11); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -3097,7 +3095,7 @@ fn remove_deferred() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(active_era(), 11); + let exposure = Staking::eras_stakers(active_era(), &11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -3173,7 +3171,7 @@ fn remove_multi_deferred() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(active_era(), 11); + let exposure = Staking::eras_stakers(active_era(), &11); assert_eq!(Balances::free_balance(101), 2000); on_offence_now( @@ -3183,7 +3181,7 @@ fn remove_multi_deferred() { on_offence_now( &[OffenceDetails { - offender: (21, Staking::eras_stakers(active_era(), 21)), + offender: (21, Staking::eras_stakers(active_era(), &21)), reporters: vec![], }], &[Perbill::from_percent(10)], @@ -3613,7 +3611,7 @@ fn zero_slash_keeps_nominators() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(active_era(), 11); + let exposure = Staking::eras_stakers(active_era(), &11); assert_eq!(Balances::free_balance(101), 2000); on_offence_now( @@ -4661,7 +4659,7 @@ fn offences_weight_calculated_correctly() { >, > = (1..10) .map(|i| OffenceDetails { - offender: (i, Staking::eras_stakers(active_era(), i)), + offender: (i, Staking::eras_stakers(active_era(), &i)), reporters: vec![], }) .collect(); @@ -4677,7 +4675,7 @@ fn offences_weight_calculated_correctly() { // On Offence with one offenders, Applied let one_offender = [OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![1], }]; @@ -6457,7 +6455,7 @@ mod staking_interface { ExtBuilder::default().build_and_execute(|| { on_offence_now( &[OffenceDetails { - offender: (11, Staking::eras_stakers(active_era(), 11)), + offender: (11, Staking::eras_stakers(active_era(), &11)), reporters: vec![], }], &[Perbill::from_percent(100)], From c1477020ddad1941e43837b8c44d9e349f451eee Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 22:23:24 +0100 Subject: [PATCH 113/131] clean up page_count --- frame/staking/src/pallet/mod.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 33728953f3fe7..5c7c454040126 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -687,8 +687,11 @@ pub mod pallet { let exposure_page = >::get(era, (validator, page)).unwrap_or_default(); let own = if page == 0 { overview.own } else { Zero::zero() }; - Some(ExposureExt { exposure_overview: ExposureOverview { own, ..overview }, exposure_page }) - } + Some(ExposureExt { + exposure_overview: ExposureOverview { own, ..overview }, + exposure_page, + }) + }, _ => None, } } @@ -712,15 +715,19 @@ pub mod pallet { /// /// This will always return at minimum one count of exposure to be backward compatible to /// non-paged reward payouts. - // FIXME: No need to return minimum of one page after cleanup: #13034 pub(crate) fn get_page_count(era: EraIndex, validator: &T::AccountId) -> PageIndex { - if let Some(overview) = >::get(&era, validator) { - // Paged exposure - overview.page_count.max(1) - } else { - // Non-paged exposure - 1 - } + >::get(&era, validator) + .map(|overview| { + if overview.page_count == 0 && overview.own > Zero::zero() { + // this means the validator has their own stake but no nominators + 1 + } else { + overview.page_count + } + }) + // FIXME: Returns minimum of one page for backward compatibility with non paged + // exposure. Can be removed when we clean up issue #13034. + .unwrap_or(1) } /// Returns the next page that can be claimed or `None` if nothing to claim. From 7a76750edba1cbe75e61b508608852c73585a13a Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 22:35:38 +0100 Subject: [PATCH 114/131] more readable validator exposure calculation --- frame/staking/src/pallet/mod.rs | 41 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 5c7c454040126..05ece2db0692f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -677,23 +677,32 @@ pub mod pallet { validator: &T::AccountId, page: PageIndex, ) -> Option>> { - match >::get(&era, validator) { - // return clipped exposure if page zero and paged exposure does not exist - None if page == 0 => - Some(ExposureExt::from_clipped(>::get(era, validator))), - - // return paged exposure if it exists - Some(overview) => { - let exposure_page = - >::get(era, (validator, page)).unwrap_or_default(); - let own = if page == 0 { overview.own } else { Zero::zero() }; - Some(ExposureExt { - exposure_overview: ExposureOverview { own, ..overview }, - exposure_page, - }) - }, - _ => None, + let overview = >::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(ExposureExt::from_clipped(>::get(era, validator))) + } + + // no exposure for this validator + if overview.is_none() { + return None } + + let overview = overview.unwrap(); + + // validator stake is added only in page zero + let validator_stake = if page == 0 { overview.own } else { Zero::zero() }; + + let exposure_page = + >::get(era, (validator, page)).unwrap_or_default(); + + // build the exposure + Some(ExposureExt { + exposure_overview: ExposureOverview { own: validator_stake, ..overview }, + exposure_page, + }) } pub(crate) fn get_validator_overview( From 1a569922e1ada765ccbd7a1a7c257c5d22f030a1 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 22:35:58 +0100 Subject: [PATCH 115/131] fmt --- frame/staking/src/pallet/impls.rs | 13 ++++++++++--- frame/staking/src/tests.rs | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index ed9c2d1fea577..32fbfc29c5d80 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -42,7 +42,11 @@ use sp_staking::{ }; use sp_std::prelude::*; -use crate::{log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, MaxWinnersOf, Nominations, PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs}; +use crate::{ + log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, Exposure, ExposureOf, + Forcing, IndividualExposure, MaxWinnersOf, Nominations, PositiveImbalanceOf, RewardDestination, + SessionInterface, StakingLedger, ValidatorPrefs, +}; use super::{pallet::*, STAKING_ID}; @@ -992,10 +996,13 @@ impl Pallet { ); } - pub fn eras_stakers(era: EraIndex, account: &T::AccountId) -> Exposure> { + pub fn eras_stakers( + era: EraIndex, + account: &T::AccountId, + ) -> Exposure> { let overview = EraInfo::::get_validator_overview(era, &account).unwrap_or_default(); if overview.page_count == 0 { - return Exposure { total: overview.total, own: overview.own, others: vec![] }; + return Exposure { total: overview.total, own: overview.own, others: vec![] } } let mut others = Vec::with_capacity(overview.nominator_count as usize); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 49c0803e53b43..1c4987f7d51d1 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2705,7 +2705,10 @@ fn garbage_collection_on_window_pruning() { let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( - &[OffenceDetails { offender: (11, Staking::eras_stakers(now, &11)), reporters: vec![] }], + &[OffenceDetails { + offender: (11, Staking::eras_stakers(now, &11)), + reporters: vec![], + }], &[Perbill::from_percent(10)], ); From 5191eab1f72420d4858e5b7b0e27b011f3c1ff85 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 22:52:22 +0100 Subject: [PATCH 116/131] do not use ErasStakers anymore --- frame/staking/src/pallet/mod.rs | 2 +- frame/staking/src/tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 05ece2db0692f..cf7f426360d5b 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -802,7 +802,7 @@ pub mod pallet { validator: &T::AccountId, exposure: Exposure>, ) { - >::insert(era, &validator, &exposure); + // >::insert(era, &validator, &exposure); let page_size = T::MaxExposurePageSize::get().defensive_max(1); let max_page_count = T::MaxExposurePageCount::get(); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 1c4987f7d51d1..aa84e0e3ca20b 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -617,7 +617,7 @@ fn nominating_and_rewards_should_work() { assert_eq!(Balances::total_balance(&20), initial_balance_20 + total_payout_0 / 2); initial_balance_20 = Balances::total_balance(&20); - assert_eq!(ErasStakers::::iter_prefix_values(active_era()).count(), 2); + assert_eq!(ErasStakersPaged::::iter_prefix_values(active_era()).count(), 2); assert_eq!( Staking::eras_stakers(active_era(), &11), Exposure { From 05c3206522ec79b9479171a00dbb0eabedc43f19 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:14:26 +0100 Subject: [PATCH 117/131] defensive unwrap for appending nominator pages to eras stakers --- frame/staking/src/pallet/impls.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 32fbfc29c5d80..8bf90378dbbb9 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1000,7 +1000,14 @@ impl Pallet { era: EraIndex, account: &T::AccountId, ) -> Exposure> { - let overview = EraInfo::::get_validator_overview(era, &account).unwrap_or_default(); + let overview = EraInfo::::get_validator_overview(era, &account); + + if overview.is_none() { + return ErasStakers::::get(era, account); + } + + let overview = overview.unwrap(); + if overview.page_count == 0 { return Exposure { total: overview.total, own: overview.own, others: vec![] } } @@ -1008,8 +1015,7 @@ impl Pallet { let mut others = Vec::with_capacity(overview.nominator_count as usize); for page in 0..overview.page_count { let nominators = EraInfo::::get_nominators_page(era, &account, page); - // TODO(ank4n) fix to defensive unwrap - others.append(&mut nominators.unwrap().others); + others.append(&mut nominators.map(|n| n.others).defensive_unwrap_or_default()); } Exposure { total: overview.total, own: overview.own, others } From 5bdcbc72a1e2e007973fa64372b16f3e1728ada5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:18:13 +0100 Subject: [PATCH 118/131] better fn naming --- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 9 +++++---- frame/staking/src/tests.rs | 16 ++++++++-------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 8bf90378dbbb9..780507447a2c8 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -189,7 +189,7 @@ impl Pallet { .retain(|&x| x >= current_era.saturating_sub(history_depth)); >::insert(&controller, &ledger); - if EraInfo::::is_rewards_claimed_temp(era, &ledger, &ledger.stash, page) { + if EraInfo::::is_rewards_claimed_with_legacy_fallback(era, &ledger, &ledger.stash, page) { return Err(Error::::AlreadyClaimed .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))) } else { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index cf7f426360d5b..e3ac281384cb2 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -650,7 +650,7 @@ pub mod pallet { /// removed once `$HistoryDepth` eras have passed and none of the older non-paged rewards /// are relevant/claimable. // Refer tracker issue for cleanup: #13034 - pub(crate) fn is_rewards_claimed_temp( + pub(crate) fn is_rewards_claimed_with_legacy_fallback( era: EraIndex, ledger: &StakingLedger, validator: &T::AccountId, @@ -663,7 +663,8 @@ pub mod pallet { /// 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_temp` can be removed and this function can be made public. + /// 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: PageIndex) -> bool { ClaimedRewards::::get(era, validator).contains(&page) } @@ -734,8 +735,8 @@ pub mod pallet { overview.page_count } }) - // FIXME: Returns minimum of one page for backward compatibility with non paged - // exposure. Can be removed when we clean up issue #13034. + // Returns minimum of one page for backward compatibility with non paged exposure. + // FIXME: Can be cleaned up with issue #13034. .unwrap_or(1) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index aa84e0e3ca20b..35a4ccd374cae 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3873,7 +3873,7 @@ fn test_multi_page_payout_stakers_by_page() { // verify rewards are tracked to prevent double claims for page in 0..EraInfo::::get_page_count(1, &11) { assert_eq!( - EraInfo::::is_rewards_claimed_temp(1, ledger.as_ref().unwrap(), &11, page), + EraInfo::::is_rewards_claimed_with_legacy_fallback(1, ledger.as_ref().unwrap(), &11, page), true ); } @@ -3898,7 +3898,7 @@ fn test_multi_page_payout_stakers_by_page() { // verify we track rewards for each era and page for page in 0..EraInfo::::get_page_count(i - 1, &11) { assert_eq!( - EraInfo::::is_rewards_claimed_temp( + EraInfo::::is_rewards_claimed_with_legacy_fallback( i - 1, Staking::ledger(&10).as_ref().unwrap(), &11, @@ -4078,7 +4078,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { // verify rewards are tracked to prevent double claims for page in 0..EraInfo::::get_page_count(1, &11) { assert_eq!( - EraInfo::::is_rewards_claimed_temp(1, ledger.as_ref().unwrap(), &11, page), + EraInfo::::is_rewards_claimed_with_legacy_fallback(1, ledger.as_ref().unwrap(), &11, page), true ); } @@ -4103,7 +4103,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { // verify we track rewards for each era and page for page in 0..EraInfo::::get_page_count(i - 1, &11) { assert_eq!( - EraInfo::::is_rewards_claimed_temp( + EraInfo::::is_rewards_claimed_with_legacy_fallback( i - 1, Staking::ledger(&10).as_ref().unwrap(), &11, @@ -6260,7 +6260,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { //verify rewards are not claimed assert_eq!( - EraInfo::::is_rewards_claimed_temp( + EraInfo::::is_rewards_claimed_with_legacy_fallback( 1, Staking::ledger(10).as_ref().unwrap(), &11, @@ -6269,7 +6269,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { false ); assert_eq!( - EraInfo::::is_rewards_claimed_temp( + EraInfo::::is_rewards_claimed_with_legacy_fallback( 2, Staking::ledger(10).as_ref().unwrap(), &11, @@ -6297,7 +6297,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { .with_weight(::WeightInfo::payout_stakers_alive_staked(0)), ); assert_eq!( - EraInfo::::is_rewards_claimed_temp( + EraInfo::::is_rewards_claimed_with_legacy_fallback( 1, Staking::ledger(10).as_ref().unwrap(), &11, @@ -6309,7 +6309,7 @@ fn test_legacy_claimed_rewards_is_checked_at_reward_payout() { // verify rewards for era 2 can be claimed assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 2, 0)); assert_eq!( - EraInfo::::is_rewards_claimed_temp( + EraInfo::::is_rewards_claimed_with_legacy_fallback( 2, Staking::ledger(10).as_ref().unwrap(), &11, From 48aef5f440c6eeae7583e9c6e2f523a8e66b78f4 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:18:40 +0100 Subject: [PATCH 119/131] fmt --- frame/staking/src/pallet/impls.rs | 5 +++-- frame/staking/src/tests.rs | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 780507447a2c8..316123173f8cd 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -189,7 +189,8 @@ impl Pallet { .retain(|&x| x >= current_era.saturating_sub(history_depth)); >::insert(&controller, &ledger); - if EraInfo::::is_rewards_claimed_with_legacy_fallback(era, &ledger, &ledger.stash, page) { + if EraInfo::::is_rewards_claimed_with_legacy_fallback(era, &ledger, &ledger.stash, page) + { return Err(Error::::AlreadyClaimed .with_weight(T::WeightInfo::payout_stakers_alive_staked(0))) } else { @@ -1003,7 +1004,7 @@ impl Pallet { let overview = EraInfo::::get_validator_overview(era, &account); if overview.is_none() { - return ErasStakers::::get(era, account); + return ErasStakers::::get(era, account) } let overview = overview.unwrap(); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 35a4ccd374cae..fdc71e6cdcabe 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3873,7 +3873,12 @@ fn test_multi_page_payout_stakers_by_page() { // verify rewards are tracked to prevent double claims for page in 0..EraInfo::::get_page_count(1, &11) { assert_eq!( - EraInfo::::is_rewards_claimed_with_legacy_fallback(1, ledger.as_ref().unwrap(), &11, page), + EraInfo::::is_rewards_claimed_with_legacy_fallback( + 1, + ledger.as_ref().unwrap(), + &11, + page + ), true ); } @@ -4078,7 +4083,12 @@ fn test_multi_page_payout_stakers_backward_compatible() { // verify rewards are tracked to prevent double claims for page in 0..EraInfo::::get_page_count(1, &11) { assert_eq!( - EraInfo::::is_rewards_claimed_with_legacy_fallback(1, ledger.as_ref().unwrap(), &11, page), + EraInfo::::is_rewards_claimed_with_legacy_fallback( + 1, + ledger.as_ref().unwrap(), + &11, + page + ), true ); } From c4e3a372b1d14e10c684d700372c6b05d6e13c4f Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:30:20 +0100 Subject: [PATCH 120/131] move logic to combine all exposure into EraInfo --- frame/staking/src/pallet/impls.rs | 25 ++++++----------------- frame/staking/src/pallet/mod.rs | 34 +++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 316123173f8cd..926763bd59411 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -997,29 +997,16 @@ impl Pallet { ); } + /// 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. + /// 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. pub fn eras_stakers( era: EraIndex, account: &T::AccountId, ) -> Exposure> { - let overview = EraInfo::::get_validator_overview(era, &account); - - if overview.is_none() { - return ErasStakers::::get(era, account) - } - - let overview = overview.unwrap(); - - if overview.page_count == 0 { - return Exposure { total: overview.total, own: overview.own, others: vec![] } - } - - let mut others = Vec::with_capacity(overview.nominator_count as usize); - for page in 0..overview.page_count { - let nominators = EraInfo::::get_nominators_page(era, &account, page); - others.append(&mut nominators.map(|n| n.others).defensive_unwrap_or_default()); - } - - Exposure { total: overview.total, own: overview.own, others } + EraInfo::::get_non_paged_validator_exposure(era, &account) } } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e3ac281384cb2..5e9ea0a49259d 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -417,8 +417,9 @@ pub mod pallet { /// /// Is it removed after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. + /// + /// Note: Deprecated since v14. Use `EraInfo` instead to work with exposures. #[pallet::storage] - // #[pallet::getter(fn eras_stakers)] #[pallet::unbounded] pub type ErasStakers = StorageDoubleMap< _, @@ -706,19 +707,30 @@ pub mod pallet { }) } - pub(crate) fn get_validator_overview( + /// Get complete exposure of the validator at a given era. + pub(crate) fn get_non_paged_validator_exposure( era: EraIndex, validator: &T::AccountId, - ) -> Option>> { - >::get(&era, validator) - } + ) -> Exposure> { + let overview = >::get(&era, validator); - pub(crate) fn get_nominators_page( - era: EraIndex, - validator: &T::AccountId, - page: PageIndex, - ) -> Option>> { - >::get(era, (validator, page)) + if overview.is_none() { + return ErasStakers::::get(era, validator) + } + + let overview = overview.unwrap(); + + if overview.page_count == 0 { + return Exposure { total: overview.total, own: overview.own, others: vec![] } + } + + let mut others = Vec::with_capacity(overview.nominator_count as usize); + for page in 0..overview.page_count { + let nominators = >::get(era, (validator, page)); + others.append(&mut nominators.map(|n| n.others).defensive_unwrap_or_default()); + } + + Exposure { total: overview.total, own: overview.own, others } } /// Returns the number of pages of exposure a validator has for the given era. From 6fc1d90a908d1a7597634f3dfefa0b51750120a7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:39:33 +0100 Subject: [PATCH 121/131] remove useless getters --- frame/staking/src/lib.rs | 20 +++++++++++++++----- frame/staking/src/pallet/mod.rs | 9 ++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 31bc8f5ffdf3c..1ec7095ccabfb 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -734,7 +734,7 @@ impl Default for Exposure +impl Exposure { /// Splits an `Exposure` into `ExposureOverview` and multiple chunks of `IndividualExposure` @@ -794,9 +794,19 @@ impl Default for ExposurePage { /// It, in combination with a list of `ExposurePage`s, can be used to reconstruct a full `Exposure` /// struct. This is useful for cases where we want to query a single page of `Exposure`s. #[derive( - PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default, + PartialEq, + Eq, + PartialOrd, + Ord, + Clone, + Encode, + Decode, + RuntimeDebug, + TypeInfo, + Default, + MaxEncodedLen, )] -pub struct ExposureOverview { +pub struct ExposureOverview { /// The total balance backing this validator. #[codec(compact)] pub total: Balance, @@ -814,12 +824,12 @@ pub struct ExposureOverview { /// 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 ExposureExt { +struct ExposureExt { exposure_overview: ExposureOverview, exposure_page: ExposurePage, } -impl ExposureExt { +impl ExposureExt { /// Create a new instance of `ExposureExt` from legacy clipped exposures. pub fn from_clipped(exposure: Exposure) -> Self { Self { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 5e9ea0a49259d..92f0b519167f1 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -443,8 +443,6 @@ pub mod pallet { /// Is it removed after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty overview is returned. #[pallet::storage] - #[pallet::getter(fn eras_stakers_overview)] - #[pallet::unbounded] pub type ErasStakersOverview = StorageDoubleMap< _, Twox64Concat, @@ -469,6 +467,8 @@ pub mod pallet { /// /// It is removed after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. + /// + /// Note: Deprecated since v14. Use `EraInfo` instead to work with exposures. #[pallet::storage] #[pallet::unbounded] #[pallet::getter(fn eras_stakers_clipped)] @@ -489,8 +489,9 @@ pub mod pallet { /// /// This uses DoubleMap instead of NMap to efficiently clear this after `HISTORY_DEPTH` eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. + /// + /// TODO(ank4n): Use NMAP and make sure it can be cleared by 1st key. #[pallet::storage] - #[pallet::getter(fn eras_stakers_paged)] #[pallet::unbounded] pub type ErasStakersPaged = StorageDoubleMap< _, @@ -815,8 +816,6 @@ pub mod pallet { validator: &T::AccountId, exposure: Exposure>, ) { - // >::insert(era, &validator, &exposure); - let page_size = T::MaxExposurePageSize::get().defensive_max(1); let max_page_count = T::MaxExposurePageCount::get(); From 395e3818f3e80394c83c0445632b4d500e9efeeb Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:40:23 +0100 Subject: [PATCH 122/131] bounded ExposureOverview --- frame/staking/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1ec7095ccabfb..1e389392633f9 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -734,8 +734,10 @@ impl Default for Exposure - Exposure +impl< + AccountId: Clone, + Balance: HasCompact + AtLeast32BitUnsigned + Copy + codec::MaxEncodedLen, + > Exposure { /// Splits an `Exposure` into `ExposureOverview` and multiple chunks of `IndividualExposure` /// with each chunk having maximum of `page_size` elements. @@ -829,7 +831,9 @@ struct ExposureExt { exposure_page: ExposurePage, } -impl ExposureExt { +impl + ExposureExt +{ /// Create a new instance of `ExposureExt` from legacy clipped exposures. pub fn from_clipped(exposure: Exposure) -> Self { Self { From 1833898fc45beaf65937ff76af3189a379accd44 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 20 Feb 2023 23:50:28 +0100 Subject: [PATCH 123/131] remove unused fn --- frame/staking/src/lib.rs | 6 ------ frame/staking/src/tests.rs | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1e389392633f9..731d3c0dd3ca0 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -866,12 +866,6 @@ impl &Vec> { &self.exposure_page.others } - - /// Returns the number of pages of nominators stashes that are exposed. - #[allow(dead_code)] - pub fn page_count(&self) -> PageIndex { - self.exposure_overview.page_count - } } /// A pending slash record. The value of the slash has been computed but not applied yet, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index fdc71e6cdcabe..60f4da27ee68d 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -6421,7 +6421,7 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( let actual_exposure = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); assert_eq!(actual_exposure.others(), &clipped_exposure); assert_eq!(actual_exposure.own(), 1000); - assert_eq!(actual_exposure.page_count(), 1); + assert_eq!(actual_exposure.exposure_overview.page_count, 1); // for pages other than 0, clipped storage returns empty exposure assert_eq!(EraInfo::::get_validator_exposure(1, &11, 1), None); From 9df6956002ce646e9a712c40dcc0bdc5fd652e54 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 22 Feb 2023 11:34:22 +0100 Subject: [PATCH 124/131] ErasStakers backward compatible test --- frame/staking/src/tests.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 60f4da27ee68d..3ac438f540316 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -497,7 +497,7 @@ fn less_than_needed_candidates_works() { // But the exposure is updated in a simple way. No external votes exists. // This is purely self-vote. - assert!(ErasStakers::::iter_prefix_values(active_era()) + assert!(ErasStakersPaged::::iter_prefix_values(active_era()) .all(|exposure| exposure.others.is_empty())); }); } @@ -1736,7 +1736,7 @@ fn reward_to_stake_works() { let _ = Balances::make_free_balance_be(&20, 1000); // Bypass logic and change current exposure - ErasStakers::::insert(0, 21, Exposure { total: 69, own: 69, others: vec![] }); + EraInfo::::set_validator_exposure(0, &21, Exposure { total: 69, own: 69, others: vec![] }); >::insert( &20, StakingLedger { @@ -6403,11 +6403,13 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ); assert_eq!(EraInfo::::get_page_count(1, &11), 2); - // case 2: exposure exist in clipped storage. + // case 2: exposure exist in ErasStakers and ErasStakersClipped (legacy). // delete paged storage and add exposure to clipped storage >::remove(1, (11, 0)); >::remove(1, (11, 1)); >::remove(1, 11); + + >::insert(1, 11, Exposure { total: total_exposure, own: 1000, others: expected_individual_exposures.clone() }); let mut clipped_exposure = expected_individual_exposures.clone(); clipped_exposure.sort_by(|a, b| b.who.cmp(&a.who)); clipped_exposure.truncate(10); @@ -6418,10 +6420,15 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( ); // verify `EraInfo` returns exposure from clipped storage - let actual_exposure = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); - assert_eq!(actual_exposure.others(), &clipped_exposure); - assert_eq!(actual_exposure.own(), 1000); - assert_eq!(actual_exposure.exposure_overview.page_count, 1); + let actual_exposure_paged = EraInfo::::get_validator_exposure(1, &11, 0).unwrap(); + assert_eq!(actual_exposure_paged.others(), &clipped_exposure); + assert_eq!(actual_exposure_paged.own(), 1000); + assert_eq!(actual_exposure_paged.exposure_overview.page_count, 1); + + let actual_exposure_full = EraInfo::::get_non_paged_validator_exposure(1, &11); + assert_eq!(actual_exposure_full.others, expected_individual_exposures); + assert_eq!(actual_exposure_full.own, 1000); + assert_eq!(actual_exposure_full.total, total_exposure); // for pages other than 0, clipped storage returns empty exposure assert_eq!(EraInfo::::get_validator_exposure(1, &11, 1), None); From 75fb59b7c7edb1b009acab91555f06e2f8974fe9 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 22 Feb 2023 11:34:46 +0100 Subject: [PATCH 125/131] fmt --- frame/staking/src/tests.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 3ac438f540316..0ade0301cca6f 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1736,7 +1736,11 @@ fn reward_to_stake_works() { let _ = Balances::make_free_balance_be(&20, 1000); // Bypass logic and change current exposure - EraInfo::::set_validator_exposure(0, &21, Exposure { total: 69, own: 69, others: vec![] }); + EraInfo::::set_validator_exposure( + 0, + &21, + Exposure { total: 69, own: 69, others: vec![] }, + ); >::insert( &20, StakingLedger { @@ -6409,7 +6413,15 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( >::remove(1, (11, 1)); >::remove(1, 11); - >::insert(1, 11, Exposure { total: total_exposure, own: 1000, others: expected_individual_exposures.clone() }); + >::insert( + 1, + 11, + Exposure { + total: total_exposure, + own: 1000, + others: expected_individual_exposures.clone(), + }, + ); let mut clipped_exposure = expected_individual_exposures.clone(); clipped_exposure.sort_by(|a, b| b.who.cmp(&a.who)); clipped_exposure.truncate(10); From 6e59335ac1192320aaa78330e1b799c206119dc9 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 22 Feb 2023 12:22:31 +0100 Subject: [PATCH 126/131] update changelog --- frame/staking/CHANGELOG.md | 57 +++++++++------------------------ frame/staking/src/migrations.rs | 41 ++++++++++++++++++++++++ frame/staking/src/pallet/mod.rs | 4 +-- 3 files changed, 58 insertions(+), 44 deletions(-) diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 8f39fe86c9937..41b1e9ab7184c 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -2,53 +2,26 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres -to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -The semantic versioning guarantees cover the interface to the substrate runtime -which -includes this pallet as a dependency. This module will also add storage -migrations whenever -changes require it. Stability with regard to offchain tooling is explicitly -excluded from -this guarantee: For example adding a new field to an in-storage data structure -will require -changes to frontends to properly display it. However, those changes will still -be regarded -as a minor version bump. - -[//]: # TODO(ank4n) these versions should be same as storage version - -## [5.0.0] - UNRELEASED +The format is loosely based +on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). We maintain a +single integer version number for staking pallet to keep track of all storage +migrations. + +## [14] - UNRELEASED ### Added -- Unlimited number of nominators can be rewarded. - for a single call for reward payout. -- New config item `MaxExposurePageCount` to weakly bound the maximum number of - exposure pages that can exist. When set to 1, we get the same behaviour of top - n nominators eligible for reward as previously with non paged exposures. -- New storage item `ErasStakersPaged` that keeps up to `MaxExposurePageSize` +- New item `ErasStakersPaged` that keeps up to `MaxExposurePageSize` individual nominator exposures by era, validator and page. -- New storage item `ErasStakersOverview` which complements `ErasStakersPaged` - and keeps track of validator's own stake and total backing stake for each era. -- New call `payout_stakers_by_page` that allows to payout rewards for a single - validator by passing the page explicitly. -- New storage item `ClaimedRewards` that keeps track of claimed reward history - of a validator by era and page. - -### Changed - -- `payout_stakers` can be called multiple times for the same era if the - validator has more than `MaxExposurePageSize` nominators backing them. -- `MaxNominatorRewardedPerValidator` is renamed to `MaxExposurePageSize`. +- New item `ErasStakersOverview` complementary to `ErasStakersPaged` which keeps + state of own and total stake of the validator across pages. +- New item `ClaimedRewards` to support paged rewards payout. ### Deprecated -- `ErasStakersClipped` is deprecated in favor of `ErasStakersPaged`. In 84 - eras, `ErasStakersClipped` will be removed. -- `StakingLedger.claimed_rewards` is renamed - to `StakingLedger.legacy_claimed_rewards` and is deprecated. +- `ErasStakersClipped` is deprecated and may be removed after 84 eras. +- `ErasStakers` is deprecated and may be removed after 84 eras. +- Field `claimed_rewards` in item `Ledger` is renamed + to `legacy_claimed_rewards` and may be removed after 84 eras. -[5.0.0]: https://github.com/paritytech/substrate/pull/13059 +[14]: https://github.com/paritytech/substrate/pull/13059 diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 3c33ae2a35d62..1778ed12ea0f9 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -52,6 +52,47 @@ impl Default for ObsoleteReleases { #[storage_alias] type StorageVersion = StorageValue, ObsoleteReleases, ValueQuery>; +pub mod v14 { + use super::*; + + pub struct MigrateToV14(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for MigrateToV14 { + fn on_runtime_upgrade() -> Weight { + let current = Pallet::::current_storage_version(); + let on_chain = Pallet::::on_chain_storage_version(); + + if current == 14 && on_chain == 13 { + current.put::>(); + + log!(info, "v14 applied successfully."); + T::DbWeight::get().reads_writes(1, 1) + } else { + log!(warn, "v14 not applied."); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + frame_support::ensure!( + Pallet::::on_chain_storage_version() == 13, + "Required v13 before upgrading to v14." + ); + + Ok(Default::default()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_state: Vec) -> Result<(), &'static str> { + frame_support::ensure!( + Pallet::::on_chain_storage_version() == 14, + "v14 not applied" + ); + Ok(()) + } + } +} + pub mod v13 { use super::*; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 92f0b519167f1..0921385e7dde2 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -65,8 +65,7 @@ pub mod pallet { use super::*; /// The current storage version. - /// TODO(ank4n) bump up - const STORAGE_VERSION: StorageVersion = StorageVersion::new(13); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(14); #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] @@ -223,6 +222,7 @@ pub mod pallet { /// /// When this is set to 1, the reward payout behaviour is similar to how it used to work /// before we had paged exposures. + #[pallet::constant] type MaxExposurePageCount: Get; /// The fraction of the validator set that is safe to be offending. From c600139803baf6c6cd4073f760882f682c225f53 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 22 Feb 2023 13:31:48 +0100 Subject: [PATCH 127/131] Use NMap for ErasStakersPaged --- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 26 ++++++++++++-------------- frame/staking/src/tests.rs | 19 +++++++++---------- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 926763bd59411..f8222f37bf390 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -696,7 +696,7 @@ impl Pallet { #[allow(deprecated)] >::remove_prefix(era_index, None); #[allow(deprecated)] - >::remove_prefix(era_index, None); + >::remove_prefix((era_index,), None); #[allow(deprecated)] >::remove_prefix(era_index, None); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 0921385e7dde2..194411f530d3c 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -484,21 +484,19 @@ pub mod pallet { /// Paginated exposure of a validator at given era. /// - /// This is keyed first by the era index to allow bulk deletion, then the tuple of stash account - /// and page. + /// This is keyed first by the era index to allow bulk deletion, then stash account and finally + /// the page. /// - /// This uses DoubleMap instead of NMap to efficiently clear this after `HISTORY_DEPTH` eras. - /// If stakers hasn't been set or has been removed then empty exposure is returned. - /// - /// TODO(ank4n): Use NMAP and make sure it can be cleared by 1st key. + /// This is cleared after `HISTORY_DEPTH` eras. #[pallet::storage] #[pallet::unbounded] - pub type ErasStakersPaged = StorageDoubleMap< + pub type ErasStakersPaged = StorageNMap< _, - Twox64Concat, - EraIndex, - Twox64Concat, - (T::AccountId, PageIndex), + ( + NMapKey, + NMapKey, + NMapKey, + ), ExposurePage>, OptionQuery, >; @@ -699,7 +697,7 @@ pub mod pallet { let validator_stake = if page == 0 { overview.own } else { Zero::zero() }; let exposure_page = - >::get(era, (validator, page)).unwrap_or_default(); + >::get((era, validator, page)).unwrap_or_default(); // build the exposure Some(ExposureExt { @@ -727,7 +725,7 @@ pub mod pallet { let mut others = Vec::with_capacity(overview.nominator_count as usize); for page in 0..overview.page_count { - let nominators = >::get(era, (validator, page)); + let nominators = >::get((era, validator, page)); others.append(&mut nominators.map(|n| n.others).defensive_unwrap_or_default()); } @@ -841,7 +839,7 @@ pub mod pallet { >::insert(era, &validator, &exposure_overview); exposure_pages.iter().enumerate().for_each(|(page, paged_exposure)| { - >::insert(era, (&validator, page as u32), &paged_exposure); + >::insert((era, &validator, page as u32), &paged_exposure); }); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 0ade0301cca6f..d151aa9982fa8 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -497,7 +497,7 @@ fn less_than_needed_candidates_works() { // But the exposure is updated in a simple way. No external votes exists. // This is purely self-vote. - assert!(ErasStakersPaged::::iter_prefix_values(active_era()) + assert!(ErasStakersPaged::::iter_prefix_values((active_era(),)) .all(|exposure| exposure.others.is_empty())); }); } @@ -617,7 +617,7 @@ fn nominating_and_rewards_should_work() { assert_eq!(Balances::total_balance(&20), initial_balance_20 + total_payout_0 / 2); initial_balance_20 = Balances::total_balance(&20); - assert_eq!(ErasStakersPaged::::iter_prefix_values(active_era()).count(), 2); + assert_eq!(ErasStakersPaged::::iter_prefix_values((active_era(),)).count(), 2); assert_eq!( Staking::eras_stakers(active_era(), &11), Exposure { @@ -6234,8 +6234,7 @@ fn should_retain_era_info_only_upto_history_depth() { ClaimedRewards::::insert(era, &validator_stash, vec![0, 1, 2]); for page in 0..3 { ErasStakersPaged::::insert( - era, - (&validator_stash, page), + (era, &validator_stash, page), ExposurePage { page_total: 100, others: vec![] }, ); } @@ -6247,14 +6246,14 @@ fn should_retain_era_info_only_upto_history_depth() { // 1 claimed_rewards entry for each era assert_eq!(ClaimedRewards::::iter_prefix(i as EraIndex).count(), 1); // 3 entries (pages) for each era - assert_eq!(ErasStakersPaged::::iter_prefix(i as EraIndex).count(), 3); + assert_eq!(ErasStakersPaged::::iter_prefix((i as EraIndex,)).count(), 3); // when clear era info Pallet::::clear_era_information(i as EraIndex); // then all era entries are cleared assert_eq!(ClaimedRewards::::iter_prefix(i as EraIndex).count(), 0); - assert_eq!(ErasStakersPaged::::iter_prefix(i as EraIndex).count(), 0); + assert_eq!(ErasStakersPaged::::iter_prefix((i as EraIndex,)).count(), 0); } }); } @@ -6384,8 +6383,8 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( mock::start_active_era(2); // verify exposure for era 1 is stored in paged storage, that each exposure is stored in // one and only one page, and no exposure is repeated. - let actual_exposure_page_0 = ErasStakersPaged::::get(1, (11, 0)).unwrap(); - let actual_exposure_page_1 = ErasStakersPaged::::get(1, (11, 1)).unwrap(); + let actual_exposure_page_0 = ErasStakersPaged::::get((1, 11, 0)).unwrap(); + let actual_exposure_page_1 = ErasStakersPaged::::get((1, 11, 1)).unwrap(); expected_individual_exposures.iter().for_each(|exposure| { assert!( actual_exposure_page_0.others.contains(exposure) || @@ -6409,8 +6408,8 @@ fn test_validator_exposure_is_backward_compatible_with_non_paged_rewards_payout( // case 2: exposure exist in ErasStakers and ErasStakersClipped (legacy). // delete paged storage and add exposure to clipped storage - >::remove(1, (11, 0)); - >::remove(1, (11, 1)); + >::remove((1, 11, 0)); + >::remove((1, 11, 1)); >::remove(1, 11); >::insert( From c461209588eacf98cb7b3abcac08a27afabd51bb Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 22 Feb 2023 16:42:06 +0100 Subject: [PATCH 128/131] doc update --- frame/staking/src/lib.rs | 19 +++++++++++----- frame/staking/src/migrations.rs | 4 ++-- frame/staking/src/pallet/mod.rs | 39 ++++++++++++++++++--------------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 731d3c0dd3ca0..b761687184ebb 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -112,11 +112,17 @@ //! The **reward and slashing** procedure is the core of the Staking pallet, attempting to _embrace //! valid behavior_ while _punishing any misbehavior or lack of availability_. //! -//! Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the -//! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -//! validator as well as its nominators. Only the [`Config::MaxExposurePageSize`] -//! biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each -//! nominator's account. +//! Rewards must be claimed for each era before it gets too old by +//! [`HistoryDepth`](`Config::HistoryDepth`) using the `payout_stakers` call. Any account can call +//! `payout_stakers`, which pays the reward to the validator as well as its nominators. Only the +//! [`Config::MaxExposurePageSize`] nominator rewards can be claimed in a single call. When the +//! number of nominators exceeds [`Config::MaxExposurePageSize`], then the nominators are stored in +//! multiple pages of [`Config::MaxExposurePageSize`] each with upto maximum of +//! [`Config::MaxExposurePageCount`] pages. To pay out all nominators, `payout_stakers` must be +//! called once for each available page. In a scenario where number of nominators N exceed M where M +//! = [`Config::MaxExposurePageSize`] * [`Config::MaxExposurePageCount`], only top M nominators by +//! stake balance are paid out. The rest of the nominators are not paid out. Paging exists to limit +//! the i/o cost to mutate storage for each nominator's account. //! //! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is //! determined, a value is deducted from the balance of the validator and all the nominators who @@ -229,7 +235,8 @@ //! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in //! [`Exposure`]). Note that payouts are made in pages with each page capped at //! [`Config::MaxExposurePageSize`] nominators. The distribution of nominators across -//! pages are unsorted and depends on the election result provided by [`Config::ElectionProvider`]. +//! pages may be unsorted. The total commission is paid out proportionally across pages based on the +//! total stake of the page. //! //! All entities who receive a reward have the option to choose their reward destination through the //! [`Payee`] storage item (see diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 1778ed12ea0f9..b1c84d6c034fa 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -148,9 +148,9 @@ pub mod v12 { #[storage_alias] type HistoryDepth = StorageValue, u32, ValueQuery>; - /// Clean up `HistoryDepth` from storage. + /// Clean up `T::HistoryDepth` from storage. /// - /// We will be depending on the configurable value of `HistoryDepth` post + /// We will be depending on the configurable value of `T::HistoryDepth` post /// this release. pub struct MigrateToV12(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV12 { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 194411f530d3c..e92f00deb7692 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -139,7 +139,8 @@ pub mod pallet { /// Following information is kept for eras in `[current_era - /// HistoryDepth, current_era]`: `ErasStakers`, `ErasStakersClipped`, /// `ErasValidatorPrefs`, `ErasValidatorReward`, `ErasRewardPoints`, - /// `ErasTotalStake`, `ErasStartSessionIndex`, `ClaimedRewards`. + /// `ErasTotalStake`, `ErasStartSessionIndex`, `ClaimedRewards`, `ErasStakersPaged`, + /// `ErasStakersOverview`. /// /// Must be more than the number of eras delayed by session. /// I.e. active era must always be in history. I.e. `active_era > @@ -403,7 +404,7 @@ pub mod pallet { #[pallet::getter(fn active_era)] pub type ActiveEra = StorageValue<_, ActiveEraInfo>; - /// The session index at which the era start for the last `HISTORY_DEPTH` eras. + /// The session index at which the era start for the last [`Config::HistoryDepth`] eras. /// /// Note: This tracks the starting session (i.e. session index when era start being active) /// for the eras in `[CurrentEra - HISTORY_DEPTH, CurrentEra]`. @@ -415,7 +416,7 @@ pub mod pallet { /// /// This is keyed first by the era index to allow bulk deletion and then the stash account. /// - /// Is it removed after `HISTORY_DEPTH` eras. + /// Is it removed after [`Config::HistoryDepth`] eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. /// /// Note: Deprecated since v14. Use `EraInfo` instead to work with exposures. @@ -440,7 +441,7 @@ pub mod pallet { /// /// This is keyed first by the era index to allow bulk deletion and then the stash account. /// - /// Is it removed after `HISTORY_DEPTH` eras. + /// Is it removed after [`Config::HistoryDepth`] eras. /// If stakers hasn't been set or has been removed then empty overview is returned. #[pallet::storage] pub type ErasStakersOverview = StorageDoubleMap< @@ -465,7 +466,7 @@ pub mod pallet { /// /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// - /// It is removed after `HISTORY_DEPTH` eras. + /// It is removed after [`Config::HistoryDepth`] eras. /// If stakers hasn't been set or has been removed then empty exposure is returned. /// /// Note: Deprecated since v14. Use `EraInfo` instead to work with exposures. @@ -487,7 +488,7 @@ pub mod pallet { /// This is keyed first by the era index to allow bulk deletion, then stash account and finally /// the page. /// - /// This is cleared after `HISTORY_DEPTH` eras. + /// This is cleared after [`Config::HistoryDepth`] eras. #[pallet::storage] #[pallet::unbounded] pub type ErasStakersPaged = StorageNMap< @@ -506,7 +507,7 @@ pub mod pallet { /// This is keyed by era and validator stash which maps to the set of page indexes which have /// been claimed. /// - /// It is removed after `HISTORY_DEPTH` eras. + /// It is removed after [`Config::HistoryDepth`] eras. #[pallet::storage] #[pallet::getter(fn claimed_rewards)] #[pallet::unbounded] @@ -524,7 +525,7 @@ pub mod pallet { /// /// This is keyed first by the era index to allow bulk deletion and then the stash account. /// - /// Is it removed after `HISTORY_DEPTH` eras. + /// Is it removed after [`Config::HistoryDepth`] eras. // If prefs hasn't been set or has been removed then 0 commission is returned. #[pallet::storage] #[pallet::getter(fn eras_validator_prefs)] @@ -538,14 +539,14 @@ pub mod pallet { ValueQuery, >; - /// The total validator era payout for the last `HISTORY_DEPTH` eras. + /// The total validator era payout for the last [`Config::HistoryDepth`] eras. /// /// Eras that haven't finished yet or has been removed doesn't have reward. #[pallet::storage] #[pallet::getter(fn eras_validator_reward)] pub type ErasValidatorReward = StorageMap<_, Twox64Concat, EraIndex, BalanceOf>; - /// Rewards for the last `HISTORY_DEPTH` eras. + /// Rewards for the last [`Config::HistoryDepth`] eras. /// If reward hasn't been set or has been removed then 0 reward is returned. #[pallet::storage] #[pallet::unbounded] @@ -553,7 +554,7 @@ pub mod pallet { pub type ErasRewardPoints = StorageMap<_, Twox64Concat, EraIndex, EraRewardPoints, ValueQuery>; - /// The total amount staked for the last `HISTORY_DEPTH` eras. + /// The total amount staked for the last [`Config::HistoryDepth`] eras. /// If total hasn't been set or has been removed then 0 stake is returned. #[pallet::storage] #[pallet::getter(fn eras_total_stake)] @@ -647,7 +648,7 @@ pub mod pallet { impl EraInfo { /// 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 `$HistoryDepth` eras have passed and none of the older non-paged rewards + /// removed once `T::HistoryDepth` eras have passed and none of the older non-paged rewards /// are relevant/claimable. // Refer tracker issue for cleanup: #13034 pub(crate) fn is_rewards_claimed_with_legacy_fallback( @@ -1759,13 +1760,14 @@ pub mod pallet { /// This pays out the earliest exposure page not claimed for the era. If all pages are /// claimed, it returns an error `InvalidPage`. /// - /// If a validator has more than `T::MaxExposurePageSize` nominators backing + /// If a validator has more than [`Config::MaxExposurePageSize`] nominators backing /// them, then the list of nominators is paged, with each page being capped at - /// `T::MaxExposurePageSize`. If a validator has more than one page of + /// [`Config::MaxExposurePageSize`]. If a validator has more than one page of /// nominators, the call needs to be made for each page separately in order for all the /// nominators backing a validator receive the reward. The nominators are not sorted across /// pages and so it should not be assumed the highest staker would be on the topmost page - /// and vice versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. + /// and vice versa. If rewards are not claimed in [`Config::HistoryDepth`] eras, they are + /// lost. /// /// # /// - Time complexity: at most O(MaxExposurePageSize). @@ -2090,13 +2092,14 @@ pub mod pallet { /// The origin of this call must be _Signed_. Any account can call this function, even if /// it is not one of the stakers. /// - /// If a validator has more than `T::MaxExposurePageSize` nominators backing + /// If a validator has more than [`Config::MaxExposurePageSize`] nominators backing /// them, then the list of nominators is paged, with each page being capped at - /// `T::MaxExposurePageSize`. If a validator has more than one page of + /// [`Config::MaxExposurePageSize`.] If a validator has more than one page of /// nominators, the call needs to be made for each page separately in order for all the /// nominators backing a validator receive the reward. The nominators are not sorted across /// pages and so it should not be assumed the highest staker would be on the topmost page - /// and vice versa. If rewards are not claimed in `${HistoryDepth}` eras, they are lost. + /// and vice versa. If rewards are not claimed in [`Config::HistoryDepth`] eras, they are + /// lost. /// /// # /// - Time complexity: at most O(MaxExposurePageSize). From c3b40bbd81dc2eb33d2b29bc93d2240eb2be14b7 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Wed, 22 Feb 2023 18:56:57 +0000 Subject: [PATCH 129/131] ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_staking --- frame/staking/src/weights.rs | 2000 ++++++++++++++++++++++------------ 1 file changed, 1315 insertions(+), 685 deletions(-) diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 2a3b04d7c555f..f0a9d58725bee 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -18,12 +18,13 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2023-02-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-ehxwxxsd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// /home/benchbot/cargo_target_dir/production/substrate +// target/production/substrate // benchmark // pallet // --steps=50 @@ -32,7 +33,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/substrate/.git/.artifacts/bench.json +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json // --pallet=pallet_staking // --chain=dev // --header=./HEADER-APACHE2 @@ -83,851 +84,1480 @@ pub trait WeightInfo { /// Weights for pallet_staking using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Payee (r:0 w:1) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn bond() -> Weight { - // Minimum execution time: 51_815 nanoseconds. - Weight::from_ref_time(52_367_000) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(4)) - } - // Storage: Staking Bonded (r:1 w:0) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: VoterList ListNodes (r:3 w:3) - // Storage: VoterList ListBags (r:2 w:2) + // Proof Size summary in bytes: + // Measured: `1074` + // Estimated: `9887` + // Minimum execution time: 42_791 nanoseconds. + Weight::from_ref_time(43_964_000) + .saturating_add(Weight::from_proof_size(9887)) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn bond_extra() -> Weight { - // Minimum execution time: 91_792 nanoseconds. - Weight::from_ref_time(92_729_000) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(7)) - } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking Nominators (r:1 w:0) - // Storage: Staking MinNominatorBond (r:1 w:0) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListBags (r:2 w:2) + // Proof Size summary in bytes: + // Measured: `2214` + // Estimated: `22888` + // Minimum execution time: 87_712 nanoseconds. + Weight::from_ref_time(90_269_000) + .saturating_add(Weight::from_proof_size(22888)) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:1 w:0) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn unbond() -> Weight { - // Minimum execution time: 97_647 nanoseconds. - Weight::from_ref_time(98_731_000) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(8)) - } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `2419` + // Estimated: `29534` + // Minimum execution time: 95_748 nanoseconds. + Weight::from_ref_time(98_423_000) + .saturating_add(Weight::from_proof_size(29534)) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 44_744 nanoseconds. - Weight::from_ref_time(45_658_968) - // Standard Error: 692 - .saturating_add(Weight::from_ref_time(65_958).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) - } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Payee (r:0 w:1) - // Storage: Staking SpanSlash (r:0 w:2) + // Proof Size summary in bytes: + // Measured: `1080` + // Estimated: `10442` + // Minimum execution time: 34_556 nanoseconds. + Weight::from_ref_time(36_352_208) + .saturating_add(Weight::from_proof_size(10442)) + // Standard Error: 975 + .saturating_add(Weight::from_ref_time(42_685).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:1 w:1) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Staking SpanSlash (r:0 w:100) + /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 86_013 nanoseconds. - Weight::from_ref_time(91_544_236) - // Standard Error: 2_273 - .saturating_add(Weight::from_ref_time(1_073_291).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(13)) - .saturating_add(T::DbWeight::get().writes(12)) + // Proof Size summary in bytes: + // Measured: `2388 + s * (4 ±0)` + // Estimated: `32205 + s * (4 ±0)` + // Minimum execution time: 82_858 nanoseconds. + Weight::from_ref_time(90_123_003) + .saturating_add(Weight::from_proof_size(32205)) + // Standard Error: 3_084 + .saturating_add(Weight::from_ref_time(1_363_655).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(12_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking MinValidatorBond (r:1 w:0) - // Storage: Staking MinCommission (r:1 w:0) - // Storage: Staking Validators (r:1 w:1) - // Storage: Staking MaxValidatorsCount (r:1 w:0) - // Storage: Staking Nominators (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListNodes (r:1 w:1) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: Staking CounterForValidators (r:1 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking MinValidatorBond (r:1 w:0) + /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking MinCommission (r:1 w:0) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:1) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking MaxValidatorsCount (r:1 w:0) + /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:1 w:1) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CounterForValidators (r:1 w:1) + /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn validate() -> Weight { - // Minimum execution time: 66_579 nanoseconds. - Weight::from_ref_time(67_026_000) - .saturating_add(T::DbWeight::get().reads(11)) - .saturating_add(T::DbWeight::get().writes(5)) + // Proof Size summary in bytes: + // Measured: `1404` + // Estimated: `19359` + // Minimum execution time: 57_223 nanoseconds. + Weight::from_ref_time(59_188_000) + .saturating_add(Weight::from_proof_size(19359)) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:128 w:128) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 40_716 nanoseconds. - Weight::from_ref_time(43_678_932) - // Standard Error: 15_099 - .saturating_add(Weight::from_ref_time(6_814_991).saturating_mul(k.into())) - .saturating_add(T::DbWeight::get().reads(1)) + // Proof Size summary in bytes: + // Measured: `1287 + k * (601 ±0)` + // Estimated: `3566 + k * (3033 ±0)` + // Minimum execution time: 30_970 nanoseconds. + Weight::from_ref_time(32_205_531) + .saturating_add(Weight::from_proof_size(3566)) + // Standard Error: 12_307 + .saturating_add(Weight::from_ref_time(8_599_234).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) + .saturating_add(Weight::from_proof_size(3033).saturating_mul(k.into())) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking MinNominatorBond (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking MaxNominatorsCount (r:1 w:0) - // Storage: Staking Validators (r:2 w:0) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:1 w:0) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:1 w:0) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:17 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 71_258 nanoseconds. - Weight::from_ref_time(70_901_125) - // Standard Error: 6_183 - .saturating_add(Weight::from_ref_time(2_777_341).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(12)) + // Proof Size summary in bytes: + // Measured: `1942 + n * (105 ±0)` + // Estimated: `21988 + n * (2520 ±0)` + // Minimum execution time: 69_223 nanoseconds. + Weight::from_ref_time(68_719_145) + .saturating_add(Weight::from_proof_size(21988)) + // Standard Error: 19_229 + .saturating_add(Weight::from_ref_time(4_075_338).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(6)) - } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(Weight::from_proof_size(2520).saturating_mul(n.into())) + } + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn chill() -> Weight { - // Minimum execution time: 66_052 nanoseconds. - Weight::from_ref_time(66_480_000) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(6)) + // Proof Size summary in bytes: + // Measured: `1778` + // Estimated: `17932` + // Minimum execution time: 58_126 nanoseconds. + Weight::from_ref_time(59_792_000) + .saturating_add(Weight::from_proof_size(17932)) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Payee (r:0 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn set_payee() -> Weight { - // Minimum execution time: 18_008 nanoseconds. - Weight::from_ref_time(18_360_000) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `835` + // Estimated: `3566` + // Minimum execution time: 13_555 nanoseconds. + Weight::from_ref_time(14_016_000) + .saturating_add(Weight::from_proof_size(3566)) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Ledger (r:2 w:2) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:2 w:2) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) fn set_controller() -> Weight { - // Minimum execution time: 25_979 nanoseconds. - Weight::from_ref_time(26_350_000) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + // Proof Size summary in bytes: + // Measured: `934` + // Estimated: `9679` + // Minimum execution time: 21_301 nanoseconds. + Weight::from_ref_time(22_586_000) + .saturating_add(Weight::from_proof_size(9679)) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: Staking ValidatorCount (r:0 w:1) + /// Storage: Staking ValidatorCount (r:0 w:1) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn set_validator_count() -> Weight { - // Minimum execution time: 5_009 nanoseconds. - Weight::from_ref_time(5_248_000) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_830 nanoseconds. + Weight::from_ref_time(2_957_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - // Storage: Staking ForceEra (r:0 w:1) + /// Storage: Staking ForceEra (r:0 w:1) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) fn force_no_eras() -> Weight { - // Minimum execution time: 19_493 nanoseconds. - Weight::from_ref_time(19_888_000) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_600 nanoseconds. + Weight::from_ref_time(11_114_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - // Storage: Staking ForceEra (r:0 w:1) + /// Storage: Staking ForceEra (r:0 w:1) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) fn force_new_era() -> Weight { - // Minimum execution time: 19_425 nanoseconds. - Weight::from_ref_time(19_991_000) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_432 nanoseconds. + Weight::from_ref_time(10_984_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - // Storage: Staking ForceEra (r:0 w:1) + /// Storage: Staking ForceEra (r:0 w:1) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) fn force_new_era_always() -> Weight { - // Minimum execution time: 19_690 nanoseconds. - Weight::from_ref_time(20_010_000) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_565 nanoseconds. + Weight::from_ref_time(11_139_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - // Storage: Staking Invulnerables (r:0 w:1) + /// Storage: Staking Invulnerables (r:0 w:1) + /// Proof Skipped: Staking Invulnerables (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 5_375 nanoseconds. - Weight::from_ref_time(6_217_068) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_988 nanoseconds. + Weight::from_ref_time(3_521_842) + .saturating_add(Weight::from_proof_size(0)) // Standard Error: 43 - .saturating_add(Weight::from_ref_time(9_885).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().writes(1)) - } - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) - // Storage: Staking Payee (r:0 w:1) - // Storage: Staking SpanSlash (r:0 w:2) + .saturating_add(Weight::from_ref_time(9_580).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:1 w:1) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:0 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Staking SpanSlash (r:0 w:100) + /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 79_630 nanoseconds. - Weight::from_ref_time(85_354_738) - // Standard Error: 2_555 - .saturating_add(Weight::from_ref_time(1_086_827).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(11)) - .saturating_add(T::DbWeight::get().writes(12)) + // Proof Size summary in bytes: + // Measured: `2118 + s * (4 ±0)` + // Estimated: `27870 + s * (4 ±0)` + // Minimum execution time: 75_086 nanoseconds. + Weight::from_ref_time(82_863_879) + .saturating_add(Weight::from_proof_size(27870)) + // Standard Error: 3_873 + .saturating_add(Weight::from_ref_time(1_339_680).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(12_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - // Storage: Staking UnappliedSlashes (r:1 w:1) + /// Storage: Staking UnappliedSlashes (r:1 w:1) + /// Proof Skipped: Staking UnappliedSlashes (max_values: None, max_size: None, mode: Measured) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 92_209 nanoseconds. - Weight::from_ref_time(901_022_610) - // Standard Error: 59_320 - .saturating_add(Weight::from_ref_time(4_943_518).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakersOverview (r:1 w:0) - // Storage: Staking ErasValidatorReward (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking ClaimedRewards (r:1 w:1) - // Storage: Staking ErasStakersPaged (r:1 w:0) - // Storage: Staking ErasStakersClipped (r:1 w:0) - // Storage: Staking ErasRewardPoints (r:1 w:0) - // Storage: Staking ErasValidatorPrefs (r:1 w:0) - // Storage: Staking Payee (r:1 w:0) - // Storage: System Account (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `66704` + // Estimated: `69179` + // Minimum execution time: 99_616 nanoseconds. + Weight::from_ref_time(910_033_266) + .saturating_add(Weight::from_proof_size(69179)) + // Standard Error: 58_519 + .saturating_add(Weight::from_ref_time(4_878_008).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersOverview (r:1 w:0) + /// Proof: Staking ErasStakersOverview (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) + /// Storage: Staking ErasValidatorReward (r:1 w:0) + /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:257 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking ClaimedRewards (r:1 w:1) + /// Proof Skipped: Staking ClaimedRewards (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasStakersPaged (r:1 w:0) + /// Proof Skipped: Staking ErasStakersPaged (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasRewardPoints (r:1 w:0) + /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasValidatorPrefs (r:1 w:0) + /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:257 w:0) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:257 w:257) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[0, 256]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 134_323 nanoseconds. - Weight::from_ref_time(200_066_020) - // Standard Error: 16_654 - .saturating_add(Weight::from_ref_time(21_841_097).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(11)) + // Proof Size summary in bytes: + // Measured: `20450 + n * (143 ±0)` + // Estimated: `76596 + n * (8187 ±1)` + // Minimum execution time: 120_810 nanoseconds. + Weight::from_ref_time(153_474_546) + .saturating_add(Weight::from_proof_size(76596)) + // Standard Error: 18_966 + .saturating_add(Weight::from_ref_time(28_752_414).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_proof_size(8187).saturating_mul(n.into())) } - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakersOverview (r:1 w:0) - // Storage: Staking ErasValidatorReward (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking ClaimedRewards (r:1 w:1) - // Storage: Staking ErasStakersPaged (r:1 w:0) - // Storage: Staking ErasStakersClipped (r:1 w:0) - // Storage: Staking ErasRewardPoints (r:1 w:0) - // Storage: Staking ErasValidatorPrefs (r:1 w:0) - // Storage: Staking Payee (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) + /// Storage: Staking Bonded (r:257 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:257 w:257) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersClipped (r:1 w:0) + /// Proof Skipped: 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) + /// Proof Skipped: Staking ClaimedRewards (max_values: None, 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 ErasValidatorReward (r:1 w:0) + /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersPaged (r:1 w:0) + /// Proof Skipped: Staking ErasStakersPaged (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasRewardPoints (r:1 w:0) + /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasValidatorPrefs (r:1 w:0) + /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:257 w:0) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:257 w:257) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:257 w:257) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) /// The range of component `n` is `[0, 256]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 166_885 nanoseconds. - Weight::from_ref_time(231_648_127) - // Standard Error: 30_392 - .saturating_add(Weight::from_ref_time(30_760_443).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(12)) + // Proof Size summary in bytes: + // Measured: `35204 + n * (465 ±0)` + // Estimated: `149575 + n * (17014 ±3)` + // Minimum execution time: 150_324 nanoseconds. + Weight::from_ref_time(148_039_697) + .saturating_add(Weight::from_proof_size(149575)) + // Standard Error: 39_048 + .saturating_add(Weight::from_ref_time(43_172_238).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_proof_size(17014).saturating_mul(n.into())) } - - // Storage: Staking Ledger (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListBags (r:2 w:2) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 92_462 nanoseconds. - Weight::from_ref_time(93_684_047) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(51_643).saturating_mul(l.into())) - .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(8)) - } - // Storage: System Account (r:1 w:1) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking SlashingSpans (r:1 w:1) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Payee (r:0 w:1) - // Storage: Staking SpanSlash (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `2215 + l * (7 ±0)` + // Estimated: `25491` + // Minimum execution time: 86_750 nanoseconds. + Weight::from_ref_time(90_496_328) + .saturating_add(Weight::from_proof_size(25491)) + // Standard Error: 5_292 + .saturating_add(Weight::from_ref_time(58_052).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:1 w:1) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Staking SpanSlash (r:0 w:100) + /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 92_003 nanoseconds. - Weight::from_ref_time(93_936_550) - // Standard Error: 2_091 - .saturating_add(Weight::from_ref_time(1_088_847).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(12)) + // Proof Size summary in bytes: + // Measured: `2388 + s * (4 ±0)` + // Estimated: `31712 + s * (4 ±0)` + // Minimum execution time: 89_155 nanoseconds. + Weight::from_ref_time(94_547_569) + .saturating_add(Weight::from_proof_size(31712)) + // Standard Error: 4_227 + .saturating_add(Weight::from_ref_time(1_330_189).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(12_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: VoterList ListBags (r:200 w:0) - // Storage: VoterList ListNodes (r:101 w:0) - // Storage: Staking Nominators (r:101 w:0) - // Storage: Staking Validators (r:2 w:0) - // Storage: Staking Bonded (r:101 w:0) - // Storage: Staking Ledger (r:101 w:0) - // Storage: Staking CounterForValidators (r:1 w:0) - // Storage: Staking ValidatorCount (r:1 w:0) - // Storage: Staking MinimumValidatorCount (r:1 w:0) - // Storage: Staking CurrentEra (r:1 w:1) - // Storage: Staking ErasValidatorPrefs (r:0 w:1) - // Storage: Staking ErasStakersPaged (r:0 w:1) - // Storage: Staking ErasStakersOverview (r:0 w:1) - // Storage: Staking ErasStakers (r:0 w:1) - // Storage: Staking ErasTotalStake (r:0 w:1) - // Storage: Staking ErasStartSessionIndex (r:0 w:1) - // Storage: Staking MinimumActiveStake (r:0 w:1) + /// Storage: VoterList CounterForListNodes (r:1 w:0) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:200 w:0) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:110 w:0) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:110 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:11 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:110 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:110 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking CounterForValidators (r:1 w:0) + /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ValidatorCount (r:1 w:0) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinimumValidatorCount (r:1 w:0) + /// Proof: Staking MinimumValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:1) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasValidatorPrefs (r:0 w:10) + /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersPaged (r:0 w:10) + /// Proof Skipped: Staking ErasStakersPaged (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasStakersOverview (r:0 w:10) + /// Proof: Staking ErasStakersOverview (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) + /// Storage: Staking ErasTotalStake (r:0 w:1) + /// Proof: Staking ErasTotalStake (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Staking ErasStartSessionIndex (r:0 w:1) + /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: Staking MinimumActiveStake (r:0 w:1) + /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 504_224 nanoseconds. - Weight::from_ref_time(506_290_000) - // Standard Error: 1_802_746 - .saturating_add(Weight::from_ref_time(60_725_475).saturating_mul(v.into())) - // Standard Error: 179_633 - .saturating_add(Weight::from_ref_time(13_820_500).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(206)) + // Proof Size summary in bytes: + // Measured: `0 + v * (3662 ±0) + n * (816 ±0)` + // Estimated: `523708 + v * (15469 ±41) + n * (12348 ±4)` + // Minimum execution time: 577_839 nanoseconds. + Weight::from_ref_time(587_063_000) + .saturating_add(Weight::from_proof_size(523708)) + // Standard Error: 2_193_535 + .saturating_add(Weight::from_ref_time(72_675_973).saturating_mul(v.into())) + // Standard Error: 218_573 + .saturating_add(Weight::from_ref_time(19_272_321).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(206_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(3)) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(v.into()))) - } - // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: VoterList ListBags (r:200 w:0) - // Storage: VoterList ListNodes (r:1500 w:0) - // Storage: Staking Nominators (r:1500 w:0) - // Storage: Staking Validators (r:500 w:0) - // Storage: Staking Bonded (r:1500 w:0) - // Storage: Staking Ledger (r:1500 w:0) - // Storage: Staking MinimumActiveStake (r:0 w:1) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) + .saturating_add(Weight::from_proof_size(15469).saturating_mul(v.into())) + .saturating_add(Weight::from_proof_size(12348).saturating_mul(n.into())) + } + /// Storage: VoterList CounterForListNodes (r:1 w:0) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:200 w:0) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2000 w:0) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:2000 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1000 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:2000 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:2000 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking MinimumActiveStake (r:0 w:1) + /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 24_224_895 nanoseconds. - Weight::from_ref_time(24_374_544_000) - // Standard Error: 319_103 - .saturating_add(Weight::from_ref_time(3_422_743).saturating_mul(v.into())) - // Standard Error: 319_103 - .saturating_add(Weight::from_ref_time(2_914_359).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(201)) + // Proof Size summary in bytes: + // Measured: `3125 + v * (459 ±0) + n * (1007 ±0)` + // Estimated: `511899 + v * (14295 ±0) + n * (11775 ±0)` + // Minimum execution time: 38_014_741 nanoseconds. + Weight::from_ref_time(39_016_264_000) + .saturating_add(Weight::from_proof_size(511899)) + // Standard Error: 409_554 + .saturating_add(Weight::from_ref_time(4_585_268).saturating_mul(v.into())) + // Standard Error: 409_554 + .saturating_add(Weight::from_ref_time(5_027_951).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(201_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(Weight::from_proof_size(14295).saturating_mul(v.into())) + .saturating_add(Weight::from_proof_size(11775).saturating_mul(n.into())) } - // Storage: Staking CounterForValidators (r:1 w:0) - // Storage: Staking Validators (r:501 w:0) + /// Storage: Staking CounterForValidators (r:1 w:0) + /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1001 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 4_765_318 nanoseconds. - Weight::from_ref_time(4_816_708_000) - // Standard Error: 54_677 - .saturating_add(Weight::from_ref_time(3_541_818).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(2)) + // Proof Size summary in bytes: + // Measured: `979 + v * (50 ±0)` + // Estimated: `3019 + v * (2520 ±0)` + // Minimum execution time: 4_283_114 nanoseconds. + Weight::from_ref_time(4_393_678_000) + .saturating_add(Weight::from_proof_size(3019)) + // Standard Error: 49_897 + .saturating_add(Weight::from_ref_time(3_190_372).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(Weight::from_proof_size(2520).saturating_mul(v.into())) } - // Storage: Staking MinCommission (r:0 w:1) - // Storage: Staking MinValidatorBond (r:0 w:1) - // Storage: Staking MaxValidatorsCount (r:0 w:1) - // Storage: Staking ChillThreshold (r:0 w:1) - // Storage: Staking MaxNominatorsCount (r:0 w:1) - // Storage: Staking MinNominatorBond (r:0 w:1) + /// Storage: Staking MinCommission (r:0 w:1) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinValidatorBond (r:0 w:1) + /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking MaxValidatorsCount (r:0 w:1) + /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ChillThreshold (r:0 w:1) + /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:0 w:1) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:0 w:1) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 10_480 nanoseconds. - Weight::from_ref_time(10_914_000) - .saturating_add(T::DbWeight::get().writes(6)) - } - // Storage: Staking MinCommission (r:0 w:1) - // Storage: Staking MinValidatorBond (r:0 w:1) - // Storage: Staking MaxValidatorsCount (r:0 w:1) - // Storage: Staking ChillThreshold (r:0 w:1) - // Storage: Staking MaxNominatorsCount (r:0 w:1) - // Storage: Staking MinNominatorBond (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_398 nanoseconds. + Weight::from_ref_time(7_711_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: Staking MinCommission (r:0 w:1) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinValidatorBond (r:0 w:1) + /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking MaxValidatorsCount (r:0 w:1) + /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ChillThreshold (r:0 w:1) + /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:0 w:1) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:0 w:1) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 9_529 nanoseconds. - Weight::from_ref_time(10_159_000) - .saturating_add(T::DbWeight::get().writes(6)) - } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking ChillThreshold (r:1 w:0) - // Storage: Staking MaxNominatorsCount (r:1 w:0) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: Staking MinNominatorBond (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_598 nanoseconds. + Weight::from_ref_time(6_970_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking ChillThreshold (r:1 w:0) + /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:1 w:0) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:1 w:0) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn chill_other() -> Weight { - // Minimum execution time: 81_347 nanoseconds. - Weight::from_ref_time(81_957_000) - .saturating_add(T::DbWeight::get().reads(11)) - .saturating_add(T::DbWeight::get().writes(6)) + // Proof Size summary in bytes: + // Measured: `1933` + // Estimated: `19438` + // Minimum execution time: 72_003 nanoseconds. + Weight::from_ref_time(73_575_000) + .saturating_add(Weight::from_proof_size(19438)) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - // Storage: Staking MinCommission (r:1 w:0) - // Storage: Staking Validators (r:1 w:1) + /// Storage: Staking MinCommission (r:1 w:0) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:1) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 19_153 nanoseconds. - Weight::from_ref_time(19_621_000) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `691` + // Estimated: `3019` + // Minimum execution time: 13_540 nanoseconds. + Weight::from_ref_time(14_129_000) + .saturating_add(Weight::from_proof_size(3019)) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - // Storage: Staking MinCommission (r:0 w:1) + /// Storage: Staking MinCommission (r:0 w:1) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn set_min_commission() -> Weight { - // Minimum execution time: 6_058 nanoseconds. - Weight::from_ref_time(6_278_000) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_511 nanoseconds. + Weight::from_ref_time(3_633_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Payee (r:0 w:1) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn bond() -> Weight { - // Minimum execution time: 51_815 nanoseconds. - Weight::from_ref_time(52_367_000) - .saturating_add(RocksDbWeight::get().reads(3)) - .saturating_add(RocksDbWeight::get().writes(4)) - } - // Storage: Staking Bonded (r:1 w:0) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: VoterList ListNodes (r:3 w:3) - // Storage: VoterList ListBags (r:2 w:2) + // Proof Size summary in bytes: + // Measured: `1074` + // Estimated: `9887` + // Minimum execution time: 42_791 nanoseconds. + Weight::from_ref_time(43_964_000) + .saturating_add(Weight::from_proof_size(9887)) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + } + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn bond_extra() -> Weight { - // Minimum execution time: 91_792 nanoseconds. - Weight::from_ref_time(92_729_000) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().writes(7)) - } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking Nominators (r:1 w:0) - // Storage: Staking MinNominatorBond (r:1 w:0) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListBags (r:2 w:2) + // Proof Size summary in bytes: + // Measured: `2214` + // Estimated: `22888` + // Minimum execution time: 87_712 nanoseconds. + Weight::from_ref_time(90_269_000) + .saturating_add(Weight::from_proof_size(22888)) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:1 w:0) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn unbond() -> Weight { - // Minimum execution time: 97_647 nanoseconds. - Weight::from_ref_time(98_731_000) - .saturating_add(RocksDbWeight::get().reads(12)) - .saturating_add(RocksDbWeight::get().writes(8)) - } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `2419` + // Estimated: `29534` + // Minimum execution time: 95_748 nanoseconds. + Weight::from_ref_time(98_423_000) + .saturating_add(Weight::from_proof_size(29534)) + .saturating_add(RocksDbWeight::get().reads(12_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 44_744 nanoseconds. - Weight::from_ref_time(45_658_968) - // Standard Error: 692 - .saturating_add(Weight::from_ref_time(65_958).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(4)) - .saturating_add(RocksDbWeight::get().writes(3)) - } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Payee (r:0 w:1) - // Storage: Staking SpanSlash (r:0 w:2) + // Proof Size summary in bytes: + // Measured: `1080` + // Estimated: `10442` + // Minimum execution time: 34_556 nanoseconds. + Weight::from_ref_time(36_352_208) + .saturating_add(Weight::from_proof_size(10442)) + // Standard Error: 975 + .saturating_add(Weight::from_ref_time(42_685).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:1 w:1) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Staking SpanSlash (r:0 w:100) + /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 86_013 nanoseconds. - Weight::from_ref_time(91_544_236) - // Standard Error: 2_273 - .saturating_add(Weight::from_ref_time(1_073_291).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(13)) - .saturating_add(RocksDbWeight::get().writes(12)) + // Proof Size summary in bytes: + // Measured: `2388 + s * (4 ±0)` + // Estimated: `32205 + s * (4 ±0)` + // Minimum execution time: 82_858 nanoseconds. + Weight::from_ref_time(90_123_003) + .saturating_add(Weight::from_proof_size(32205)) + // Standard Error: 3_084 + .saturating_add(Weight::from_ref_time(1_363_655).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(13_u64)) + .saturating_add(RocksDbWeight::get().writes(12_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking MinValidatorBond (r:1 w:0) - // Storage: Staking MinCommission (r:1 w:0) - // Storage: Staking Validators (r:1 w:1) - // Storage: Staking MaxValidatorsCount (r:1 w:0) - // Storage: Staking Nominators (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListNodes (r:1 w:1) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: Staking CounterForValidators (r:1 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking MinValidatorBond (r:1 w:0) + /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking MinCommission (r:1 w:0) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:1) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking MaxValidatorsCount (r:1 w:0) + /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:1 w:1) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CounterForValidators (r:1 w:1) + /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn validate() -> Weight { - // Minimum execution time: 66_579 nanoseconds. - Weight::from_ref_time(67_026_000) - .saturating_add(RocksDbWeight::get().reads(11)) - .saturating_add(RocksDbWeight::get().writes(5)) + // Proof Size summary in bytes: + // Measured: `1404` + // Estimated: `19359` + // Minimum execution time: 57_223 nanoseconds. + Weight::from_ref_time(59_188_000) + .saturating_add(Weight::from_proof_size(19359)) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:128 w:128) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 40_716 nanoseconds. - Weight::from_ref_time(43_678_932) - // Standard Error: 15_099 - .saturating_add(Weight::from_ref_time(6_814_991).saturating_mul(k.into())) - .saturating_add(RocksDbWeight::get().reads(1)) + // Proof Size summary in bytes: + // Measured: `1287 + k * (601 ±0)` + // Estimated: `3566 + k * (3033 ±0)` + // Minimum execution time: 30_970 nanoseconds. + Weight::from_ref_time(32_205_531) + .saturating_add(Weight::from_proof_size(3566)) + // Standard Error: 12_307 + .saturating_add(Weight::from_ref_time(8_599_234).saturating_mul(k.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) + .saturating_add(Weight::from_proof_size(3033).saturating_mul(k.into())) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking MinNominatorBond (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking MaxNominatorsCount (r:1 w:0) - // Storage: Staking Validators (r:2 w:0) - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:1 w:0) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:1 w:0) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:17 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 71_258 nanoseconds. - Weight::from_ref_time(70_901_125) - // Standard Error: 6_183 - .saturating_add(Weight::from_ref_time(2_777_341).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(12)) + // Proof Size summary in bytes: + // Measured: `1942 + n * (105 ±0)` + // Estimated: `21988 + n * (2520 ±0)` + // Minimum execution time: 69_223 nanoseconds. + Weight::from_ref_time(68_719_145) + .saturating_add(Weight::from_proof_size(21988)) + // Standard Error: 19_229 + .saturating_add(Weight::from_ref_time(4_075_338).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(6)) - } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(Weight::from_proof_size(2520).saturating_mul(n.into())) + } + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn chill() -> Weight { - // Minimum execution time: 66_052 nanoseconds. - Weight::from_ref_time(66_480_000) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().writes(6)) + // Proof Size summary in bytes: + // Measured: `1778` + // Estimated: `17932` + // Minimum execution time: 58_126 nanoseconds. + Weight::from_ref_time(59_792_000) + .saturating_add(Weight::from_proof_size(17932)) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Payee (r:0 w:1) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn set_payee() -> Weight { - // Minimum execution time: 18_008 nanoseconds. - Weight::from_ref_time(18_360_000) - .saturating_add(RocksDbWeight::get().reads(1)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `835` + // Estimated: `3566` + // Minimum execution time: 13_555 nanoseconds. + Weight::from_ref_time(14_016_000) + .saturating_add(Weight::from_proof_size(3566)) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Ledger (r:2 w:2) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:2 w:2) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) fn set_controller() -> Weight { - // Minimum execution time: 25_979 nanoseconds. - Weight::from_ref_time(26_350_000) - .saturating_add(RocksDbWeight::get().reads(3)) - .saturating_add(RocksDbWeight::get().writes(3)) + // Proof Size summary in bytes: + // Measured: `934` + // Estimated: `9679` + // Minimum execution time: 21_301 nanoseconds. + Weight::from_ref_time(22_586_000) + .saturating_add(Weight::from_proof_size(9679)) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: Staking ValidatorCount (r:0 w:1) + /// Storage: Staking ValidatorCount (r:0 w:1) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn set_validator_count() -> Weight { - // Minimum execution time: 5_009 nanoseconds. - Weight::from_ref_time(5_248_000) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_830 nanoseconds. + Weight::from_ref_time(2_957_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - // Storage: Staking ForceEra (r:0 w:1) + /// Storage: Staking ForceEra (r:0 w:1) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) fn force_no_eras() -> Weight { - // Minimum execution time: 19_493 nanoseconds. - Weight::from_ref_time(19_888_000) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_600 nanoseconds. + Weight::from_ref_time(11_114_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - // Storage: Staking ForceEra (r:0 w:1) + /// Storage: Staking ForceEra (r:0 w:1) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) fn force_new_era() -> Weight { - // Minimum execution time: 19_425 nanoseconds. - Weight::from_ref_time(19_991_000) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_432 nanoseconds. + Weight::from_ref_time(10_984_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - // Storage: Staking ForceEra (r:0 w:1) + /// Storage: Staking ForceEra (r:0 w:1) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) fn force_new_era_always() -> Weight { - // Minimum execution time: 19_690 nanoseconds. - Weight::from_ref_time(20_010_000) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_565 nanoseconds. + Weight::from_ref_time(11_139_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - // Storage: Staking Invulnerables (r:0 w:1) + /// Storage: Staking Invulnerables (r:0 w:1) + /// Proof Skipped: Staking Invulnerables (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 5_375 nanoseconds. - Weight::from_ref_time(6_217_068) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_988 nanoseconds. + Weight::from_ref_time(3_521_842) + .saturating_add(Weight::from_proof_size(0)) // Standard Error: 43 - .saturating_add(Weight::from_ref_time(9_885).saturating_mul(v.into())) - .saturating_add(RocksDbWeight::get().writes(1)) - } - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) - // Storage: Staking Payee (r:0 w:1) - // Storage: Staking SpanSlash (r:0 w:2) + .saturating_add(Weight::from_ref_time(9_580).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:1 w:1) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:0 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Staking SpanSlash (r:0 w:100) + /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 79_630 nanoseconds. - Weight::from_ref_time(85_354_738) - // Standard Error: 2_555 - .saturating_add(Weight::from_ref_time(1_086_827).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(11)) - .saturating_add(RocksDbWeight::get().writes(12)) + // Proof Size summary in bytes: + // Measured: `2118 + s * (4 ±0)` + // Estimated: `27870 + s * (4 ±0)` + // Minimum execution time: 75_086 nanoseconds. + Weight::from_ref_time(82_863_879) + .saturating_add(Weight::from_proof_size(27870)) + // Standard Error: 3_873 + .saturating_add(Weight::from_ref_time(1_339_680).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(12_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - // Storage: Staking UnappliedSlashes (r:1 w:1) + /// Storage: Staking UnappliedSlashes (r:1 w:1) + /// Proof Skipped: Staking UnappliedSlashes (max_values: None, max_size: None, mode: Measured) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 92_209 nanoseconds. - Weight::from_ref_time(901_022_610) - // Standard Error: 59_320 - .saturating_add(Weight::from_ref_time(4_943_518).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(1)) - .saturating_add(RocksDbWeight::get().writes(1)) - } - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakersOverview (r:1 w:0) - // Storage: Staking ErasValidatorReward (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking ClaimedRewards (r:1 w:1) - // Storage: Staking ErasStakersPaged (r:1 w:0) - // Storage: Staking ErasStakersClipped (r:1 w:0) - // Storage: Staking ErasRewardPoints (r:1 w:0) - // Storage: Staking ErasValidatorPrefs (r:1 w:0) - // Storage: Staking Payee (r:1 w:0) - // Storage: System Account (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `66704` + // Estimated: `69179` + // Minimum execution time: 99_616 nanoseconds. + Weight::from_ref_time(910_033_266) + .saturating_add(Weight::from_proof_size(69179)) + // Standard Error: 58_519 + .saturating_add(Weight::from_ref_time(4_878_008).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersOverview (r:1 w:0) + /// Proof: Staking ErasStakersOverview (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) + /// Storage: Staking ErasValidatorReward (r:1 w:0) + /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:257 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking ClaimedRewards (r:1 w:1) + /// Proof Skipped: Staking ClaimedRewards (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasStakersPaged (r:1 w:0) + /// Proof Skipped: Staking ErasStakersPaged (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasRewardPoints (r:1 w:0) + /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasValidatorPrefs (r:1 w:0) + /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:257 w:0) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:257 w:257) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[0, 256]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 134_323 nanoseconds. - Weight::from_ref_time(200_066_020) - // Standard Error: 16_654 - .saturating_add(Weight::from_ref_time(21_841_097).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(11)) + // Proof Size summary in bytes: + // Measured: `20450 + n * (143 ±0)` + // Estimated: `76596 + n * (8187 ±1)` + // Minimum execution time: 120_810 nanoseconds. + Weight::from_ref_time(153_474_546) + .saturating_add(Weight::from_proof_size(76596)) + // Standard Error: 18_966 + .saturating_add(Weight::from_ref_time(28_752_414).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(3)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_proof_size(8187).saturating_mul(n.into())) } - // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakersOverview (r:1 w:0) - // Storage: Staking ErasValidatorReward (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking ClaimedRewards (r:1 w:1) - // Storage: Staking ErasStakersPaged (r:1 w:0) - // Storage: Staking ErasStakersClipped (r:1 w:0) - // Storage: Staking ErasRewardPoints (r:1 w:0) - // Storage: Staking ErasValidatorPrefs (r:1 w:0) - // Storage: Staking Payee (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) + /// Storage: Staking Bonded (r:257 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:257 w:257) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersClipped (r:1 w:0) + /// Proof Skipped: 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) + /// Proof Skipped: Staking ClaimedRewards (max_values: None, 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 ErasValidatorReward (r:1 w:0) + /// Proof: Staking ErasValidatorReward (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersPaged (r:1 w:0) + /// Proof Skipped: Staking ErasStakersPaged (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasRewardPoints (r:1 w:0) + /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasValidatorPrefs (r:1 w:0) + /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:257 w:0) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:257 w:257) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:257 w:257) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) /// The range of component `n` is `[0, 256]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 166_885 nanoseconds. - Weight::from_ref_time(231_648_127) - // Standard Error: 30_392 - .saturating_add(Weight::from_ref_time(30_760_443).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(12)) + // Proof Size summary in bytes: + // Measured: `35204 + n * (465 ±0)` + // Estimated: `149575 + n * (17014 ±3)` + // Minimum execution time: 150_324 nanoseconds. + Weight::from_ref_time(148_039_697) + .saturating_add(Weight::from_proof_size(149575)) + // Standard Error: 39_048 + .saturating_add(Weight::from_ref_time(43_172_238).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(4)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_proof_size(17014).saturating_mul(n.into())) } - // Storage: Staking Ledger (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) - // Storage: VoterList ListBags (r:2 w:2) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 92_462 nanoseconds. - Weight::from_ref_time(93_684_047) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(51_643).saturating_mul(l.into())) - .saturating_add(RocksDbWeight::get().reads(9)) - .saturating_add(RocksDbWeight::get().writes(8)) - } - // Storage: System Account (r:1 w:1) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) - // Storage: Staking SlashingSpans (r:1 w:1) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Payee (r:0 w:1) - // Storage: Staking SpanSlash (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `2215 + l * (7 ±0)` + // Estimated: `25491` + // Minimum execution time: 86_750 nanoseconds. + Weight::from_ref_time(90_496_328) + .saturating_add(Weight::from_proof_size(25491)) + // Standard Error: 5_292 + .saturating_add(Weight::from_ref_time(58_052).saturating_mul(l.into())) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:1) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:1 w:1) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:1) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Staking SpanSlash (r:0 w:100) + /// Proof: Staking SpanSlash (max_values: None, max_size: Some(76), added: 2551, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 92_003 nanoseconds. - Weight::from_ref_time(93_936_550) - // Standard Error: 2_091 - .saturating_add(Weight::from_ref_time(1_088_847).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(12)) - .saturating_add(RocksDbWeight::get().writes(12)) + // Proof Size summary in bytes: + // Measured: `2388 + s * (4 ±0)` + // Estimated: `31712 + s * (4 ±0)` + // Minimum execution time: 89_155 nanoseconds. + Weight::from_ref_time(94_547_569) + .saturating_add(Weight::from_proof_size(31712)) + // Standard Error: 4_227 + .saturating_add(Weight::from_ref_time(1_330_189).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) + .saturating_add(RocksDbWeight::get().writes(12_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_proof_size(4).saturating_mul(s.into())) } - // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: VoterList ListBags (r:200 w:0) - // Storage: VoterList ListNodes (r:101 w:0) - // Storage: Staking Nominators (r:101 w:0) - // Storage: Staking Validators (r:2 w:0) - // Storage: Staking Bonded (r:101 w:0) - // Storage: Staking Ledger (r:101 w:0) - // Storage: Staking CounterForValidators (r:1 w:0) - // Storage: Staking ValidatorCount (r:1 w:0) - // Storage: Staking MinimumValidatorCount (r:1 w:0) - // Storage: Staking CurrentEra (r:1 w:1) - // Storage: Staking ErasValidatorPrefs (r:0 w:1) - // Storage: Staking ErasStakersPaged (r:0 w:1) - // Storage: Staking ErasStakersOverview (r:0 w:1) - // Storage: Staking ErasStakers (r:0 w:1) - // Storage: Staking ErasTotalStake (r:0 w:1) - // Storage: Staking ErasStartSessionIndex (r:0 w:1) - // Storage: Staking MinimumActiveStake (r:0 w:1) + /// Storage: VoterList CounterForListNodes (r:1 w:0) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:200 w:0) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:110 w:0) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:110 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:11 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:110 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:110 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking CounterForValidators (r:1 w:0) + /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ValidatorCount (r:1 w:0) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinimumValidatorCount (r:1 w:0) + /// Proof: Staking MinimumValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:1) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasValidatorPrefs (r:0 w:10) + /// Proof: Staking ErasValidatorPrefs (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) + /// Storage: Staking ErasStakersPaged (r:0 w:10) + /// Proof Skipped: Staking ErasStakersPaged (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking ErasStakersOverview (r:0 w:10) + /// Proof: Staking ErasStakersOverview (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) + /// Storage: Staking ErasTotalStake (r:0 w:1) + /// Proof: Staking ErasTotalStake (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Staking ErasStartSessionIndex (r:0 w:1) + /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: Staking MinimumActiveStake (r:0 w:1) + /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 504_224 nanoseconds. - Weight::from_ref_time(506_290_000) - // Standard Error: 1_802_746 - .saturating_add(Weight::from_ref_time(60_725_475).saturating_mul(v.into())) - // Standard Error: 179_633 - .saturating_add(Weight::from_ref_time(13_820_500).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(206)) + // Proof Size summary in bytes: + // Measured: `0 + v * (3662 ±0) + n * (816 ±0)` + // Estimated: `523708 + v * (15469 ±41) + n * (12348 ±4)` + // Minimum execution time: 577_839 nanoseconds. + Weight::from_ref_time(587_063_000) + .saturating_add(Weight::from_proof_size(523708)) + // Standard Error: 2_193_535 + .saturating_add(Weight::from_ref_time(72_675_973).saturating_mul(v.into())) + // Standard Error: 218_573 + .saturating_add(Weight::from_ref_time(19_272_321).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(206_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(3)) - .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(v.into()))) - } - // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: VoterList ListBags (r:200 w:0) - // Storage: VoterList ListNodes (r:1500 w:0) - // Storage: Staking Nominators (r:1500 w:0) - // Storage: Staking Validators (r:500 w:0) - // Storage: Staking Bonded (r:1500 w:0) - // Storage: Staking Ledger (r:1500 w:0) - // Storage: Staking MinimumActiveStake (r:0 w:1) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(v.into()))) + .saturating_add(Weight::from_proof_size(15469).saturating_mul(v.into())) + .saturating_add(Weight::from_proof_size(12348).saturating_mul(n.into())) + } + /// Storage: VoterList CounterForListNodes (r:1 w:0) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:200 w:0) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2000 w:0) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:2000 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1000 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:2000 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:2000 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking MinimumActiveStake (r:0 w:1) + /// Proof: Staking MinimumActiveStake (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 24_224_895 nanoseconds. - Weight::from_ref_time(24_374_544_000) - // Standard Error: 319_103 - .saturating_add(Weight::from_ref_time(3_422_743).saturating_mul(v.into())) - // Standard Error: 319_103 - .saturating_add(Weight::from_ref_time(2_914_359).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(201)) + // Proof Size summary in bytes: + // Measured: `3125 + v * (459 ±0) + n * (1007 ±0)` + // Estimated: `511899 + v * (14295 ±0) + n * (11775 ±0)` + // Minimum execution time: 38_014_741 nanoseconds. + Weight::from_ref_time(39_016_264_000) + .saturating_add(Weight::from_proof_size(511899)) + // Standard Error: 409_554 + .saturating_add(Weight::from_ref_time(4_585_268).saturating_mul(v.into())) + // Standard Error: 409_554 + .saturating_add(Weight::from_ref_time(5_027_951).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(201_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(1)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(Weight::from_proof_size(14295).saturating_mul(v.into())) + .saturating_add(Weight::from_proof_size(11775).saturating_mul(n.into())) } - // Storage: Staking CounterForValidators (r:1 w:0) - // Storage: Staking Validators (r:501 w:0) + /// Storage: Staking CounterForValidators (r:1 w:0) + /// Proof: Staking CounterForValidators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1001 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 4_765_318 nanoseconds. - Weight::from_ref_time(4_816_708_000) - // Standard Error: 54_677 - .saturating_add(Weight::from_ref_time(3_541_818).saturating_mul(v.into())) - .saturating_add(RocksDbWeight::get().reads(2)) + // Proof Size summary in bytes: + // Measured: `979 + v * (50 ±0)` + // Estimated: `3019 + v * (2520 ±0)` + // Minimum execution time: 4_283_114 nanoseconds. + Weight::from_ref_time(4_393_678_000) + .saturating_add(Weight::from_proof_size(3019)) + // Standard Error: 49_897 + .saturating_add(Weight::from_ref_time(3_190_372).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(Weight::from_proof_size(2520).saturating_mul(v.into())) } - // Storage: Staking MinCommission (r:0 w:1) - // Storage: Staking MinValidatorBond (r:0 w:1) - // Storage: Staking MaxValidatorsCount (r:0 w:1) - // Storage: Staking ChillThreshold (r:0 w:1) - // Storage: Staking MaxNominatorsCount (r:0 w:1) - // Storage: Staking MinNominatorBond (r:0 w:1) + /// Storage: Staking MinCommission (r:0 w:1) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinValidatorBond (r:0 w:1) + /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking MaxValidatorsCount (r:0 w:1) + /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ChillThreshold (r:0 w:1) + /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:0 w:1) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:0 w:1) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 10_480 nanoseconds. - Weight::from_ref_time(10_914_000) - .saturating_add(RocksDbWeight::get().writes(6)) - } - // Storage: Staking MinCommission (r:0 w:1) - // Storage: Staking MinValidatorBond (r:0 w:1) - // Storage: Staking MaxValidatorsCount (r:0 w:1) - // Storage: Staking ChillThreshold (r:0 w:1) - // Storage: Staking MaxNominatorsCount (r:0 w:1) - // Storage: Staking MinNominatorBond (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_398 nanoseconds. + Weight::from_ref_time(7_711_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: Staking MinCommission (r:0 w:1) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinValidatorBond (r:0 w:1) + /// Proof: Staking MinValidatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking MaxValidatorsCount (r:0 w:1) + /// Proof: Staking MaxValidatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ChillThreshold (r:0 w:1) + /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:0 w:1) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:0 w:1) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 9_529 nanoseconds. - Weight::from_ref_time(10_159_000) - .saturating_add(RocksDbWeight::get().writes(6)) - } - // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking Nominators (r:1 w:1) - // Storage: Staking ChillThreshold (r:1 w:0) - // Storage: Staking MaxNominatorsCount (r:1 w:0) - // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: Staking MinNominatorBond (r:1 w:0) - // Storage: Staking Validators (r:1 w:0) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) - // Storage: VoterList CounterForListNodes (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_598 nanoseconds. + Weight::from_ref_time(6_970_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking ChillThreshold (r:1 w:0) + /// Proof: Staking ChillThreshold (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Staking MaxNominatorsCount (r:1 w:0) + /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking MinNominatorBond (r:1 w:0) + /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:2 w:2) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn chill_other() -> Weight { - // Minimum execution time: 81_347 nanoseconds. - Weight::from_ref_time(81_957_000) - .saturating_add(RocksDbWeight::get().reads(11)) - .saturating_add(RocksDbWeight::get().writes(6)) + // Proof Size summary in bytes: + // Measured: `1933` + // Estimated: `19438` + // Minimum execution time: 72_003 nanoseconds. + Weight::from_ref_time(73_575_000) + .saturating_add(Weight::from_proof_size(19438)) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - // Storage: Staking MinCommission (r:1 w:0) - // Storage: Staking Validators (r:1 w:1) + /// Storage: Staking MinCommission (r:1 w:0) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:1) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 19_153 nanoseconds. - Weight::from_ref_time(19_621_000) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `691` + // Estimated: `3019` + // Minimum execution time: 13_540 nanoseconds. + Weight::from_ref_time(14_129_000) + .saturating_add(Weight::from_proof_size(3019)) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - // Storage: Staking MinCommission (r:0 w:1) + /// Storage: Staking MinCommission (r:0 w:1) + /// Proof: Staking MinCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn set_min_commission() -> Weight { - // Minimum execution time: 6_058 nanoseconds. - Weight::from_ref_time(6_278_000) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_511 nanoseconds. + Weight::from_ref_time(3_633_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } From f9235c02431c95ed89bf1f6e2920aa8807c1e12d Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 22 Feb 2023 18:58:57 +0100 Subject: [PATCH 130/131] rename to consistent names --- bin/node/runtime/src/lib.rs | 2 +- frame/fast-unstake/src/benchmarking.rs | 2 +- frame/fast-unstake/src/lib.rs | 2 +- frame/fast-unstake/src/mock.rs | 2 +- frame/staking/CHANGELOG.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index f8b5ae9b1ec96..8f3e76ad820f4 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -595,7 +595,7 @@ impl pallet_fast_unstake::Config for Runtime { type Staking = Staking; type MaxErasToCheckPerBlock = ConstU32<1>; #[cfg(feature = "runtime-benchmarks")] - type MaxBackersPerValidator = MaxExposurePageSize; + type MaxExposurePageSize = MaxExposurePageSize; type WeightInfo = (); } diff --git a/frame/fast-unstake/src/benchmarking.rs b/frame/fast-unstake/src/benchmarking.rs index 5ec997e8eaa2a..5d31c1f9ded41 100644 --- a/frame/fast-unstake/src/benchmarking.rs +++ b/frame/fast-unstake/src/benchmarking.rs @@ -74,7 +74,7 @@ fn setup_staking(v: u32, until: EraIndex) { .collect::>(); for era in 0..=until { - let others = (0..T::MaxBackersPerValidator::get()) + let others = (0..T::MaxExposurePageSize::get()) .map(|s| { let who = frame_benchmarking::account::("nominator", era, s); let value = ed; diff --git a/frame/fast-unstake/src/lib.rs b/frame/fast-unstake/src/lib.rs index 81eb3087b998e..8b05e9b553b0a 100644 --- a/frame/fast-unstake/src/lib.rs +++ b/frame/fast-unstake/src/lib.rs @@ -142,7 +142,7 @@ pub mod pallet { /// Use only for benchmarking. #[cfg(feature = "runtime-benchmarks")] - type MaxBackersPerValidator: Get; + type MaxExposurePageSize: Get; } /// The current "head of the queue" being unstaked. diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index 56a23555e6fd0..49b29c448e27b 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -188,7 +188,7 @@ impl fast_unstake::Config for Runtime { type WeightInfo = (); type MaxErasToCheckPerBlock = ConstU32<16>; #[cfg(feature = "runtime-benchmarks")] - type MaxBackersPerValidator = ConstU32<128>; + type MaxExposurePageSize = ConstU32<128>; } type Block = frame_system::mocking::MockBlock; diff --git a/frame/staking/CHANGELOG.md b/frame/staking/CHANGELOG.md index 41b1e9ab7184c..411f63b397c7e 100644 --- a/frame/staking/CHANGELOG.md +++ b/frame/staking/CHANGELOG.md @@ -7,7 +7,7 @@ on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). We maintain a single integer version number for staking pallet to keep track of all storage migrations. -## [14] - UNRELEASED +## [14] ### Added From b4abd8a878555f78765e1fae040855b96bb33778 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 27 Feb 2023 00:26:30 +0100 Subject: [PATCH 131/131] some docs --- frame/staking/src/pallet/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e92f00deb7692..be7a5b3f18034 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -440,6 +440,7 @@ pub mod pallet { /// pages of rewards that needs to be claimed. /// /// This is keyed first by the era index to allow bulk deletion and then the stash account. + /// Should only be accessed through `EraInfo`. /// /// Is it removed after [`Config::HistoryDepth`] eras. /// If stakers hasn't been set or has been removed then empty overview is returned. @@ -486,7 +487,7 @@ pub mod pallet { /// Paginated exposure of a validator at given era. /// /// This is keyed first by the era index to allow bulk deletion, then stash account and finally - /// the page. + /// the page. Should only be accessed through `EraInfo`. /// /// This is cleared after [`Config::HistoryDepth`] eras. #[pallet::storage] @@ -697,6 +698,8 @@ pub mod pallet { // validator stake is added only in page zero let validator_stake = if page == 0 { overview.own } else { Zero::zero() }; + // since overview is present, paged exposure will always be present except when a + // validator has only own stake and no nominator stake. let exposure_page = >::get((era, validator, page)).unwrap_or_default();