From d723499750d5c3f9226597a841c0b54c64300aa2 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 20 Jul 2022 14:30:07 +0200 Subject: [PATCH 01/34] wip: poc --- pallets/parachain-staking/src/lib.rs | 244 ++++++++++++++++++--------- 1 file changed, 161 insertions(+), 83 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index e76aed0659..3e7687e4cb 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -440,6 +440,8 @@ pub mod pallet { StakeNotFound, /// Cannot unlock when Unstaked is empty. UnstakingIsEmpty, + /// Cannot claim rewards if empty. + RewardsNotFound, } #[pallet::event] @@ -664,6 +666,22 @@ pub mod pallet { #[pallet::getter(fn last_reward_reduction)] pub(crate) type LastRewardReduction = StorageValue<_, T::BlockNumber, ValueQuery>; + /// The counter of accumulated rewards for a collator candidate. + /// + /// It maps from collator accounts to the number of block authored by them + /// since the last payout. + // TODO: Maybe rather use u64. Assuming 30 validators, u32 would suffice for 27 years of constant 12s blocktime. + #[pallet::storage] + #[pallet::getter(fn reward_count)] + pub(crate) type RewardCount = StorageMap<_, Twox64Concat, T::AccountId, u32, ValueQuery>; + + /// The accumulated rewards for collator candidates and delegators. + /// + /// It maps from accounts to their total rewards since the last payout. + #[pallet::storage] + #[pallet::getter(fn rewards)] + pub(crate) type Rewards = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf, ValueQuery>; + pub type GenesisStaker = Vec<( ::AccountId, Option<::AccountId>, @@ -700,7 +718,7 @@ pub mod pallet { "Invalid inflation configuration" ); - >::put(self.inflation_config.clone()); + InflationConfig::::put(self.inflation_config.clone()); MaxCollatorCandidateStake::::put(self.max_candidate_stake); // Setup delegate & collators @@ -776,6 +794,7 @@ pub mod pallet { /// - Reads: [Origin Account] /// - Writes: InflationConfig /// # + // TODO: Refactor to set rewards for all network participants #[pallet::weight(::WeightInfo::set_inflation())] pub fn set_inflation( origin: OriginFor, @@ -804,7 +823,7 @@ pub mod pallet { inflation.delegator.max_rate, inflation.delegator.reward_rate.per_block, )); - >::put(inflation); + InflationConfig::::put(inflation); Ok(()) } @@ -907,6 +926,7 @@ pub mod pallet { /// - Reads: [Origin Account], Round /// - Writes: Round /// # + // TODO: Maybe refactor to set rewards for all network participants #[pallet::weight(::WeightInfo::set_blocks_per_round())] pub fn set_blocks_per_round(origin: OriginFor, new: T::BlockNumber) -> DispatchResult { ensure_root(origin)?; @@ -984,6 +1004,7 @@ pub mod pallet { /// - Kills: CandidatePool, DelegatorState for all delegators which only /// delegated to the candidate /// # + // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::force_remove_candidate( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1141,6 +1162,7 @@ pub mod pallet { /// TotalCollatorStake /// - Writes: CandidatePool, TopCandidates, TotalCollatorStake /// # + // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::init_leave_candidates( T::MaxTopCandidates::get(), T::MaxTopCandidates::get().saturating_mul(T::MaxDelegatorsPerCollator::get()) @@ -1314,6 +1336,7 @@ pub mod pallet { /// MaxCollatorCandidateStake, TopCandidates, CandidatePool /// - Writes: Locks, TotalCollatorStake, CandidatePool, TopCandidates /// # + // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::candidate_stake_more( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1356,6 +1379,9 @@ pub mod pallet { }; CandidatePool::::insert(&collator, state); + // increment rewards for origin + their delegators and reset reward counter + Self::inc_collator_reward(&collator, before_stake); + Self::deposit_event(Event::CollatorStakedMore(collator, before_stake, after_stake)); Ok(Some(::WeightInfo::candidate_stake_more( n, @@ -1389,6 +1415,7 @@ pub mod pallet { /// MaxSelectedCandidates, CandidatePool /// - Writes: Unstaking, CandidatePool, TotalCollatorStake /// # + // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::candidate_stake_less( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1430,6 +1457,9 @@ pub mod pallet { }; CandidatePool::::insert(&collator, state); + // increment rewards for origin + their delegators and reset reward counter + Self::inc_collator_reward(&collator, before_stake); + Self::deposit_event(Event::CollatorStakedLess(collator, before_stake, after)); Ok(Some(::WeightInfo::candidate_stake_less( n, @@ -1569,6 +1599,9 @@ pub mod pallet { DelegatorState::::insert(&acc, delegator_state); >::insert(&acc, delegation_counter); + // initiate reward counter to match the current state of the candidate + RewardCount::::insert(&acc, RewardCount::::get(&collator)); + // update or clear storage of potentially kicked delegator Self::update_kicked_delegator_storage(maybe_kicked_delegator); @@ -1627,6 +1660,7 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] + // TODO: Refactor to set rewards for origin pub fn delegate_another_candidate( origin: OriginFor, collator: ::Source, @@ -1761,6 +1795,7 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] + // TODO: Refactor to set rewards for origin pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { let acc = ensure_signed(origin)?; let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; @@ -1891,6 +1926,8 @@ pub mod pallet { 0u32 }; + // set rewards and reset reward counter + Self::inc_delegator_reward(&delegator, delegations.total, &candidate); CandidatePool::::insert(&candidate, collator); DelegatorState::::insert(&delegator, delegations); @@ -1931,6 +1968,7 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] + // TODO: Refactor to set rewards for origin pub fn delegator_stake_less( origin: OriginFor, candidate: ::Source, @@ -2014,6 +2052,25 @@ pub mod pallet { Ok(Some(::WeightInfo::unlock_unstaked(unstaking_len)).into()) } + + // TODO: Benchmark, unit tests, docs + #[pallet::weight(0)] + pub fn claim_rewards_for(origin: OriginFor, target: ::Source) -> DispatchResult { + ensure_signed(origin)?; + let target = T::Lookup::lookup(target)?; + + // we could kill the storage entry but let's be safe in case the deposit fails + let rewards = Rewards::::get(&target); + ensure!(rewards.is_zero(), Error::::RewardsNotFound); + + // mint into target and reset rewards + let rewards = T::Currency::deposit_into_existing(&target, rewards)?; + Rewards::::remove(&target); + + Self::deposit_event(Event::Rewarded(target, rewards.peek())); + + Ok(()) + } } impl Pallet { @@ -2434,6 +2491,9 @@ pub mod pallet { // update total stake state.total = state.total.saturating_sub(stake_to_remove.amount); + // set rewards for kicked delegator + Self::inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); + // update storage of kicked delegator let kicked_delegator = Self::prep_kick_delegator(&stake_to_remove, &state.id)?; @@ -2662,20 +2722,6 @@ pub mod pallet { Ok(unstaking_len) } - /// Process the coinbase rewards for the production of a new block. - /// - /// # - /// Weight: O(1) - /// - Reads: Balance - /// - Writes: Balance - /// # - fn do_reward(who: &T::AccountId, reward: BalanceOf) { - // mint - if let Ok(imb) = T::Currency::deposit_into_existing(who, reward) { - Self::deposit_event(Event::Rewarded(who.clone(), imb.peek())); - } - } - /// Annually reduce the reward rates for collators and delegators. /// /// # @@ -2687,7 +2733,7 @@ pub mod pallet { let year = now / T::BLOCKS_PER_YEAR; let last_update = >::get(); if year > last_update { - let inflation = >::get(); + let inflation = InflationConfig::::get(); // collator reward rate decreases by 2% of the previous one per year let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); // delegator reward rate should be 6% in 2nd year and 0% afterwards @@ -2704,7 +2750,7 @@ pub mod pallet { inflation.delegator.max_rate, d_reward_rate, ); - >::put(new_inflation.clone()); + InflationConfig::::put(new_inflation.clone()); >::put(year); Self::deposit_event(Event::RoundInflationSet( new_inflation.collator.max_rate, @@ -2773,6 +2819,94 @@ pub mod pallet { T::Currency::issue(network_reward) } + // TODO: Docs and naming improvement + fn calc_block_rewards_collator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { + let total_issuance = T::Currency::total_issuance(); + let TotalStake { + collators: total_collators, + .. + } = >::get(); + let staking_rate = Perquintill::from_rational(total_collators, total_issuance); + + InflationConfig::::get() + .collator + .compute_reward::(stake, staking_rate, multiplier) + } + + // TODO: Docs and naming improvement + fn calc_block_rewards_delegator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { + let total_issuance = T::Currency::total_issuance(); + let TotalStake { + delegators: total_delegators, + .. + } = >::get(); + let staking_rate = Perquintill::from_rational(total_delegators, total_issuance); + + InflationConfig::::get() + .delegator + .compute_reward::(stake, staking_rate, multiplier) + } + + /// Increment the accumulated rewards of a collator by consuming their + /// current rewards counter. + /// + /// Moreover, automatically increments all associated delegators since + /// their reward increment is dependend on the collator reward counter. + /// + /// Resets all reward counters of the collator and their delegators to + /// zero. + fn inc_collator_reward(collator: &T::AccountId, stake: BalanceOf) -> Weight { + let mut post_weight = Weight::zero(); + // get reward counters + let col_reward_count = RewardCount::::get(collator); + + // set reward data for collator + Rewards::::mutate(collator, |reward| { + reward.saturating_add(Self::calc_block_rewards_collator(stake, col_reward_count.into())) + }); + + // set reward data for delegators + if let Some(state) = CandidatePool::::get(collator.clone()) { + for Stake { owner, amount } in state.delegators { + post_weight = post_weight.saturating_add(Self::inc_delegator_reward(&owner, amount, collator)); + // Reset delegator counter since collator counter will be reset + RewardCount::::insert(owner, 0); + post_weight = post_weight.saturating_add(T::DbWeight::get().reads(1)); + } + } + + // Reset collator reward count + RewardCount::::insert(collator, 0); + + // 4 reads from calc rewards + post_weight.saturating_add(T::DbWeight::get().reads_writes(5, 1)) + } + + /// Increment the accumulated rewards of a delegator by consuming their + /// current rewards counter. The counter will be reset to the collator + /// counter. + fn inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) -> Weight { + // get reward counters + let del_reward_count = RewardCount::::get(acc); + let col_reward_count = RewardCount::::get(col); + let diff = col_reward_count.saturating_sub(del_reward_count); + + // only update if collator has higher reward count + if diff > 0 { + Rewards::::mutate(acc, |reward| { + reward.saturating_add(Self::calc_block_rewards_delegator(stake, diff.into())) + }); + // TODO: Investigate whether we want to set this to some input variable to + // improve `add_collator_reward` + RewardCount::::insert(acc, col_reward_count); + + // 4 reads from reward calc + T::DbWeight::get().reads_writes(6, 2) + } else { + T::DbWeight::get().reads(2) + } + } + // [Post-launch TODO] Think about Collator stake or total stake? // /// Attempts to add a collator candidate to the set of collator // /// candidates which already reached its maximum size. On success, @@ -2790,78 +2924,22 @@ pub mod pallet { where T: Config + pallet_authorship::Config + pallet_session::Config, { - /// Compute coinbase rewards for block production and distribute it to - /// collator's (block producer) and its delegators according to their - /// stake and the current InflationInfo. - /// - /// The rewards are split between collators and delegators with - /// different reward rates and maximum staking rates. The latter is - /// required to have at most our targeted inflation because rewards are - /// minted. Rewards are immediately available without any restrictions - /// after minting. - /// - /// If the current staking rate is below the maximum, each collator and - /// delegator receives the corresponding `reward_rate * stake / - /// blocks_per_year`. Since a collator can only author blocks every - /// `MaxSelectedCandidates` many rounds, we multiply the reward with - /// this number. As a result, a collator who has been in the set of - /// selected candidates, eventually receives `reward_rate * stake` after - /// one year. - /// - /// However, if the current staking rate exceeds the max staking rate, - /// the reward will be reduced by `max_rate / current_rate`. E.g., if - /// the current rate is at 50% and the max rate at 40%, the reward is - /// reduced by 20%. - /// - /// # - /// Weight: O(D) where D is the number of delegators of this collator - /// block author bounded by `MaxDelegatorsPerCollator`. - /// - Reads: CandidatePool, TotalCollatorStake, Balance, - /// InflationConfig, MaxSelectedCandidates, Validators, - /// DisabledValidators - /// - Writes: (D + 1) * Balance - /// # + // TODO: Docs + /// Increments the reward counter of the block author by the number of + /// collators. fn note_author(author: T::AccountId) { - let mut reads = Weight::one(); - let mut writes = Weight::zero(); // should always include state except if the collator has been forcedly removed // via `force_remove_candidate` in the current or previous round - if let Some(state) = CandidatePool::::get(author.clone()) { - let total_issuance = T::Currency::total_issuance(); - let TotalStake { - collators: total_collators, - delegators: total_delegators, - } = >::get(); - let c_staking_rate = Perquintill::from_rational(total_collators, total_issuance); - let d_staking_rate = Perquintill::from_rational(total_delegators, total_issuance); - let inflation_config = >::get(); + if CandidatePool::::get(author.clone()).is_some() { + // necessary to compensate for a potentially fluctuating number of collators let authors = pallet_session::Pallet::::validators(); - let authors_per_round = >::from(authors.len().saturated_into::()); - - // Reward collator - let amt_due_collator = - inflation_config - .collator - .compute_reward::(state.stake, c_staking_rate, authors_per_round); - Self::do_reward(&author, amt_due_collator); - writes = writes.saturating_add(Weight::one()); - - // Reward delegators - for Stake { owner, amount } in state.delegators { - if amount >= T::MinDelegatorStake::get() { - let due = - inflation_config - .delegator - .compute_reward::(amount, d_staking_rate, authors_per_round); - Self::do_reward(&owner, due); - writes = writes.saturating_add(Weight::one()); - } - } - reads = reads.saturating_add(4); + RewardCount::::mutate(&author, |count| { + count.saturating_add(authors.len().saturated_into::()) + }); } frame_system::Pallet::::register_extra_weight_unchecked( - T::DbWeight::get().reads_writes(reads, writes), + T::DbWeight::get().reads_writes(2, 1), DispatchClass::Mandatory, ); } From 82da1d9220fddf0766f08e00ede4fc144ee24631 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 28 Jul 2022 17:18:09 +0200 Subject: [PATCH 02/34] refactor: extrinsics and inherents --- pallets/parachain-staking/src/lib.rs | 218 +++++++++++++++++-------- pallets/parachain-staking/src/types.rs | 7 +- 2 files changed, 155 insertions(+), 70 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 3e7687e4cb..d87eddf4ff 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -436,6 +436,8 @@ pub mod pallet { /// The staking reward being unlocked does not exist. /// Max unlocking requests reached. NoMoreUnstaking, + /// There is no pending reward change. + NoPendingRewardChange, /// Provided staked value is zero. Should never be thrown. StakeNotFound, /// Cannot unlock when Unstaked is empty. @@ -537,23 +539,26 @@ pub mod pallet { fn on_initialize(now: T::BlockNumber) -> frame_support::weights::Weight { let mut post_weight = ::WeightInfo::on_initialize_no_action(); let mut round = >::get(); + let year = now / T::BLOCKS_PER_YEAR; + let last_update = LastRewardReduction::::get(); // check for round update if round.should_update(now) { // mutate round round.update(now); - // start next round >::put(round); Self::deposit_event(Event::NewRound(round.first, round.current)); post_weight = ::WeightInfo::on_initialize_round_update(); } - // check for InflationInfo update - if now > T::BLOCKS_PER_YEAR.saturated_into::() { - post_weight = post_weight.saturating_add(Self::adjust_reward_rates(now)); + // check for annual update of staking reward rates + if year > last_update { + PendingRewardChange::::put(true); + post_weight = post_weight.saturating_add(T::DbWeight::get().writes(1)); } - // check for network reward + // check for network reward and mint + // on success, mint each block if now > T::NetworkRewardStart::get() { T::NetworkRewardBeneficiary::on_unbalanced(Self::get_network_reward()); post_weight = post_weight.saturating_add(::WeightInfo::on_initialize_network_rewards()); @@ -682,6 +687,11 @@ pub mod pallet { #[pallet::getter(fn rewards)] pub(crate) type Rewards = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf, ValueQuery>; + // TODO: Docs + #[pallet::storage] + #[pallet::getter(fn pending_reward_change)] + pub(crate) type PendingRewardChange = StorageValue<_, bool, OptionQuery>; + pub type GenesisStaker = Vec<( ::AccountId, Option<::AccountId>, @@ -794,7 +804,6 @@ pub mod pallet { /// - Reads: [Origin Account] /// - Writes: InflationConfig /// # - // TODO: Refactor to set rewards for all network participants #[pallet::weight(::WeightInfo::set_inflation())] pub fn set_inflation( origin: OriginFor, @@ -803,6 +812,9 @@ pub mod pallet { delegator_max_rate_percentage: Perquintill, delegator_annual_reward_rate_percentage: Perquintill, ) -> DispatchResult { + // TODO: Enable after refactoring bench + // ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; let inflation = InflationInfo::new( @@ -817,6 +829,12 @@ pub mod pallet { inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), Error::::InvalidSchedule ); + + // set rewards for all collators and delegators due + CandidatePool::::iter().for_each(|(id, state)| { + Self::inc_collator_reward(&id, state.stake); + }); + Self::deposit_event(Event::RoundInflationSet( inflation.collator.max_rate, inflation.collator.reward_rate.per_block, @@ -825,6 +843,10 @@ pub mod pallet { )); InflationConfig::::put(inflation); Ok(()) + // TODO: Enable after refactoring bench + // Ok(Some(::WeightInfo::set_inflation(CandidatePool:::: + // count()))) } /// Set the maximum number of collator candidates that can be selected @@ -984,7 +1006,10 @@ pub mod pallet { /// /// Prepares unstaking of the candidates and their delegators stake /// which can be unlocked via `unlock_unstaked` after waiting at - /// least `StakeDuration` many blocks. + /// least `StakeDuration` many blocks. Also increments rewards for the + /// collator and their delegators. + /// + /// Increments rewards of candidate and their delegators. /// /// Emits `CandidateRemoved`. /// @@ -1004,7 +1029,6 @@ pub mod pallet { /// - Kills: CandidatePool, DelegatorState for all delegators which only /// delegated to the candidate /// # - // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::force_remove_candidate( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1026,6 +1050,7 @@ pub mod pallet { // *** No Fail except during remove_candidate beyond this point *** + // remove candidate storage and increment rewards Self::remove_candidate(&collator, &state)?; let (num_collators, num_delegators) = if candidates @@ -1139,7 +1164,7 @@ pub mod pallet { /// updated even though the funds of the candidate who signaled to leave /// are still locked for `ExitDelay` + `StakeDuration` more blocks. /// - /// NOTE: Upon starting a new session_i in `new_session`, the current + /// NOTE 1: Upon starting a new session_i in `new_session`, the current /// top candidates are selected to be block authors for session_i+1. Any /// changes to the top candidates afterwards do not effect the set of /// authors for session_i+1. @@ -1147,6 +1172,10 @@ pub mod pallet { /// leave before session_i+1 ends by delaying their /// exit for `ExitDelay` many blocks. /// + /// NOTE 2: We do not increment rewards in this extrinsic as the + /// candidate could still author blocks, and thus be eligible to receive + /// rewards, until the end of the next session. + /// /// Emits `CollatorScheduledExit`. /// /// # @@ -1162,7 +1191,6 @@ pub mod pallet { /// TotalCollatorStake /// - Writes: CandidatePool, TopCandidates, TotalCollatorStake /// # - // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::init_leave_candidates( T::MaxTopCandidates::get(), T::MaxTopCandidates::get().saturating_mul(T::MaxDelegatorsPerCollator::get()) @@ -1251,6 +1279,7 @@ pub mod pallet { // *** No Fail except during remove_candidate beyond this point *** + // remove candidate storage and increment rewards Self::remove_candidate(&collator, &state)?; Self::deposit_event(Event::CandidateLeft(collator, total_amount)); @@ -1336,7 +1365,6 @@ pub mod pallet { /// MaxCollatorCandidateStake, TopCandidates, CandidatePool /// - Writes: Locks, TotalCollatorStake, CandidatePool, TopCandidates /// # - // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::candidate_stake_more( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1415,7 +1443,6 @@ pub mod pallet { /// MaxSelectedCandidates, CandidatePool /// - Writes: Unstaking, CandidatePool, TotalCollatorStake /// # - // TODO: Refactor to set rewards for the collator and their delegators #[pallet::weight(::WeightInfo::candidate_stake_less( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1565,7 +1592,7 @@ pub mod pallet { } = state; // update state and potentially prepare kicking a delegator with less staked - // amount + // amount (includes setting rewards for kicked delegator) let (state, maybe_kicked_delegator) = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() { Self::do_update_delegator(delegation, state)? @@ -1660,7 +1687,6 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] - // TODO: Refactor to set rewards for origin pub fn delegate_another_candidate( origin: OriginFor, collator: ::Source, @@ -1724,7 +1750,7 @@ pub mod pallet { } = state; // update state and potentially prepare kicking a delegator with less staked - // amount + // amount (includes reward setting for kicked delegator) let (state, maybe_kicked_delegator) = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() { Self::do_update_delegator(delegation, state)? @@ -1753,11 +1779,14 @@ pub mod pallet { 0u32 }; - // Update states + // update states CandidatePool::::insert(&collator, state); DelegatorState::::insert(&acc, delegator); >::insert(&acc, delegation_counter); + // initiate reward counter to match the current state of the candidate + RewardCount::::insert(&acc, RewardCount::::get(&collator)); + // update or clear storage of potentially kicked delegator Self::update_kicked_delegator_storage(maybe_kicked_delegator); @@ -1781,6 +1810,9 @@ pub mod pallet { /// their chances to be included in the set of candidates in the next /// rounds. /// + /// Automatically increments the accumulated rewards of the origin for + /// each delegation. + /// /// Emits `DelegatorLeft`. /// /// # @@ -1795,11 +1827,12 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] - // TODO: Refactor to set rewards for origin pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { let acc = ensure_signed(origin)?; let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; let num_delegations: u32 = delegator.delegations.len().saturated_into(); + + // remove delegations and increment rewards for stake in delegator.delegations.into_iter() { Self::delegator_leaves_collator(acc.clone(), stake.owner.clone())?; } @@ -1852,6 +1885,7 @@ pub mod pallet { // *** No Fail except during delegator_revokes_collator beyond this point *** + // revoke delegation and increment rewards let num_delegations = Self::delegator_revokes_collator(delegator, collator)?; Ok(Some(::WeightInfo::revoke_delegation( @@ -1895,14 +1929,14 @@ pub mod pallet { let mut delegations = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let delegator_total = delegations + let stake_after = delegations .inc_delegation(candidate.clone(), more) .ok_or(Error::::DelegationNotFound)?; // *** No Fail except during increase_lock beyond this point *** // update lock - let unstaking_len = Self::increase_lock(&delegator, delegator_total, more)?; + let unstaking_len = Self::increase_lock(&delegator, stake_after, more)?; let CandidateOf:: { stake: before_stake, @@ -1927,7 +1961,8 @@ pub mod pallet { }; // set rewards and reset reward counter - Self::inc_delegator_reward(&delegator, delegations.total, &candidate); + Self::inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); + CandidatePool::::insert(&candidate, collator); DelegatorState::::insert(&delegator, delegations); @@ -1968,7 +2003,6 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] - // TODO: Refactor to set rewards for origin pub fn delegator_stake_less( origin: OriginFor, candidate: ::Source, @@ -1981,12 +2015,12 @@ pub mod pallet { let mut delegations = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let remaining = delegations + let stake_after = delegations .dec_delegation(candidate.clone(), less) .ok_or(Error::::DelegationNotFound)? .ok_or(Error::::Underflow)?; - ensure!(remaining >= T::MinDelegation::get(), Error::::DelegationBelowMin); + ensure!(stake_after >= T::MinDelegation::get(), Error::::DelegationBelowMin); ensure!( delegations.total >= T::MinDelegatorStake::get(), Error::::NomStakeBelowMin @@ -2017,6 +2051,10 @@ pub mod pallet { } else { 0u32 }; + + // set rewards and reset reward counter + Self::inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); + CandidatePool::::insert(&candidate, collator); DelegatorState::::insert(&delegator, delegations); @@ -2071,6 +2109,74 @@ pub mod pallet { Ok(()) } + + /// Executes the annual reduction of the reward rates for collators and + /// delegators. Moreover, sets rewards for all collators and delegators + /// before adjusting the inflation. + /// + /// Requires PendingRewardChange to be set to Some(true) which happens + /// once per year in `on_initialize`. + /// + /// Emits `RoundInflationSet`. + // TODO: benchmark + #[pallet::weight(0)] + pub fn execute_pending_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + + ensure!( + PendingRewardChange::::get() == Some(true), + Error::::NoPendingRewardChange + ); + + // Calculate new inflation based on last year + let now = frame_system::Pallet::::block_number(); + let year = now / T::BLOCKS_PER_YEAR; + let inflation = InflationConfig::::get(); + + // collator reward rate decreases by 2% p.a. of the previous one + let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); + // delegator reward rate should be 6% in 2nd year and 0% afterwards + let d_reward_rate = if year == T::BlockNumber::one() { + Perquintill::from_percent(6) + } else { + Perquintill::zero() + }; + let new_inflation = InflationInfo::new( + T::BLOCKS_PER_YEAR.saturated_into(), + inflation.collator.max_rate, + c_reward_rate, + inflation.delegator.max_rate, + d_reward_rate, + ); + // should never fail + ensure!( + new_inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), + Error::::InvalidSchedule + ); + + // set rewards for all collators and delegators before updating reward rates + CandidatePool::::iter().for_each(|(id, state)| { + Self::inc_collator_reward(&id, state.stake); + }); + // reset pending reward change + PendingRewardChange::::put(false); + + // update inflation config + InflationConfig::::put(new_inflation.clone()); + LastRewardReduction::::put(year); + Self::deposit_event(Event::RoundInflationSet( + new_inflation.collator.max_rate, + new_inflation.collator.reward_rate.per_block, + new_inflation.delegator.max_rate, + new_inflation.delegator.reward_rate.per_block, + )); + + Ok(Some( + T::DbWeight::get() + .reads_writes(2, CandidatePool::::count().saturated_into::().saturating_add(3)), + ) + .into()) + } } impl Pallet { @@ -2087,6 +2193,8 @@ pub mod pallet { /// Check whether an account is currently a collator candidate and /// whether their state is CollatorStatus::Active. /// + /// Returns Some(is_active) if the account is a candidate, else None. + /// /// # /// Weight: O(1) /// - Reads: CandidatePool @@ -2297,9 +2405,9 @@ pub mod pallet { .rm_delegation(&collator) .ok_or(Error::::DelegationNotFound)?; - // edge case; if no delegations remaining, leave set of delegators + // remove delegation and increment rewards if delegator.delegations.is_empty() { - // leave the set of delegators because no delegations left + // edge case; if no delegations remaining, leave set of delegators Self::delegator_leaves_collator(acc.clone(), collator)?; DelegatorState::::remove(&acc); Self::deposit_event(Event::DelegatorLeft(acc, old_total)); @@ -2313,7 +2421,8 @@ pub mod pallet { } /// Update the collator's state by removing the delegator's stake and - /// starting the process to unlock the delegator's staked funds. + /// starting the process to unlock the delegator's staked funds as well + /// as incrementing their accumulated rewards. /// /// This operation affects the pallet's total stake. /// @@ -2344,6 +2453,9 @@ pub mod pallet { state.total = state.total.saturating_sub(delegator_stake); let new_total = state.total; + // set rewards + Self::inc_delegator_reward(&delegator, delegator_stake, &collator); + // we don't unlock immediately Self::prep_unstake(&delegator, delegator_stake, false)?; @@ -2449,6 +2561,8 @@ pub mod pallet { /// amount is at most the minimum staked value of the original delegator /// set, an error is returned. /// + /// Sets rewards for the removed delegator. + /// /// Returns a tuple which contains the updated candidate state as well /// as the potentially replaced delegation which will be used later when /// updating the storage of the replaced delegator. @@ -2631,6 +2745,8 @@ pub mod pallet { ) -> DispatchResult { // iterate over delegators for stake in &state.delegators[..] { + // // increment rewards of delegator + // Self::inc_delegator_reward(&stake.owner, stake.amount, collator); // prepare unstaking of delegator Self::prep_unstake(&stake.owner, stake.amount, true)?; // remove delegation from delegator state @@ -2649,6 +2765,9 @@ pub mod pallet { // *** No Fail beyond this point *** + // increment rewards of collator and their delegators + Self::inc_collator_reward(collator, state.stake); + // disable validator for next session if they were in the set of validators pallet_session::Pallet::::validators() .into_iter() @@ -2722,47 +2841,6 @@ pub mod pallet { Ok(unstaking_len) } - /// Annually reduce the reward rates for collators and delegators. - /// - /// # - /// Weight: O(1) - /// - Reads: LastRewardReduction, InflationConfig - /// - Writes: LastRewardReduction, InflationConfig - /// # - fn adjust_reward_rates(now: T::BlockNumber) -> Weight { - let year = now / T::BLOCKS_PER_YEAR; - let last_update = >::get(); - if year > last_update { - let inflation = InflationConfig::::get(); - // collator reward rate decreases by 2% of the previous one per year - let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); - // delegator reward rate should be 6% in 2nd year and 0% afterwards - let d_reward_rate = if year == T::BlockNumber::one() { - Perquintill::from_percent(6) - } else { - Perquintill::zero() - }; - - let new_inflation = InflationInfo::new( - T::BLOCKS_PER_YEAR.saturated_into(), - inflation.collator.max_rate, - c_reward_rate, - inflation.delegator.max_rate, - d_reward_rate, - ); - InflationConfig::::put(new_inflation.clone()); - >::put(year); - Self::deposit_event(Event::RoundInflationSet( - new_inflation.collator.max_rate, - new_inflation.collator.reward_rate.per_block, - new_inflation.delegator.max_rate, - new_inflation.delegator.reward_rate.per_block, - )); - ::WeightInfo::on_initialize_new_year(); - } - T::DbWeight::get().reads(1) - } - /// Checks whether a delegator can still delegate in this round, e.g., /// if they have not delegated MaxDelegationsPerRound many times /// already in this round. @@ -2797,6 +2875,12 @@ pub mod pallet { /// in `on_initialize` by adding it to the free balance of /// `NetworkRewardBeneficiary`. /// + /// Over the course of an entire year, the network rewards equal the + /// maximum annual collator staking rewards multiplied with the + /// NetworkRewardRate. E.g., assuming 10% annual collator reward rate, + /// 10% max staking rate, 200k KILT max collator stake and 30 collators: + /// NetworkRewards = NetworkRewardRate * 10% * 10% * 200_000 KILT * 30 + /// /// The expected rewards are the product of /// * the current total maximum collator rewards /// * and the configured NetworkRewardRate diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index a253396d12..64bb6b7392 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -269,7 +269,8 @@ where } } - /// Returns None if delegation was not found. + /// Returns Some(delegated_amount) if successfull, None if delegation was + /// not found. pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Option { if let Ok(i) = self.delegations.linear_search(&Stake:: { owner: collator, @@ -285,8 +286,8 @@ where } } - /// Returns Some(Some(balance)) if successful, None if delegation was not - /// found and Some(None) if delegated stake would underflow. + /// Returns Some(Some(delegated_amount)) if successful, None if delegation + /// was not found and Some(None) if delegated stake would underflow. pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Option> { if let Ok(i) = self.delegations.linear_search(&Stake:: { owner: collator, From 03cd34d88be046723c0041a3ad3c17281d38efb5 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Fri, 29 Jul 2022 08:28:44 +0200 Subject: [PATCH 03/34] refactor: remove storage redundancy --- pallets/parachain-staking/src/lib.rs | 34 +++++++--------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index d87eddf4ff..aa4513c55a 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -436,8 +436,9 @@ pub mod pallet { /// The staking reward being unlocked does not exist. /// Max unlocking requests reached. NoMoreUnstaking, - /// There is no pending reward change. - NoPendingRewardChange, + /// The reward rate cannot be adjusted yet as an entire year has not + /// passed. + TooEarly, /// Provided staked value is zero. Should never be thrown. StakeNotFound, /// Cannot unlock when Unstaked is empty. @@ -539,8 +540,6 @@ pub mod pallet { fn on_initialize(now: T::BlockNumber) -> frame_support::weights::Weight { let mut post_weight = ::WeightInfo::on_initialize_no_action(); let mut round = >::get(); - let year = now / T::BLOCKS_PER_YEAR; - let last_update = LastRewardReduction::::get(); // check for round update if round.should_update(now) { @@ -552,11 +551,6 @@ pub mod pallet { Self::deposit_event(Event::NewRound(round.first, round.current)); post_weight = ::WeightInfo::on_initialize_round_update(); } - // check for annual update of staking reward rates - if year > last_update { - PendingRewardChange::::put(true); - post_weight = post_weight.saturating_add(T::DbWeight::get().writes(1)); - } // check for network reward and mint // on success, mint each block if now > T::NetworkRewardStart::get() { @@ -687,11 +681,6 @@ pub mod pallet { #[pallet::getter(fn rewards)] pub(crate) type Rewards = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf, ValueQuery>; - // TODO: Docs - #[pallet::storage] - #[pallet::getter(fn pending_reward_change)] - pub(crate) type PendingRewardChange = StorageValue<_, bool, OptionQuery>; - pub type GenesisStaker = Vec<( ::AccountId, Option<::AccountId>, @@ -2114,25 +2103,20 @@ pub mod pallet { /// delegators. Moreover, sets rewards for all collators and delegators /// before adjusting the inflation. /// - /// Requires PendingRewardChange to be set to Some(true) which happens - /// once per year in `on_initialize`. - /// /// Emits `RoundInflationSet`. // TODO: benchmark #[pallet::weight(0)] pub fn execute_pending_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { ensure_signed(origin)?; - ensure!( - PendingRewardChange::::get() == Some(true), - Error::::NoPendingRewardChange - ); - - // Calculate new inflation based on last year let now = frame_system::Pallet::::block_number(); let year = now / T::BLOCKS_PER_YEAR; - let inflation = InflationConfig::::get(); + let last_update = LastRewardReduction::::get(); + ensure!(year > last_update, Error::::TooEarly); + + // Calculate new inflation based on last year + let inflation = InflationConfig::::get(); // collator reward rate decreases by 2% p.a. of the previous one let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); // delegator reward rate should be 6% in 2nd year and 0% afterwards @@ -2158,8 +2142,6 @@ pub mod pallet { CandidatePool::::iter().for_each(|(id, state)| { Self::inc_collator_reward(&id, state.stake); }); - // reset pending reward change - PendingRewardChange::::put(false); // update inflation config InflationConfig::::put(new_inflation.clone()); From 766c7778383b6e0be2fc345e90e3d8f41efdee27 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Fri, 29 Jul 2022 11:40:06 +0200 Subject: [PATCH 04/34] tests: fix existing ones for staking --- pallets/parachain-staking/src/lib.rs | 107 +++++++++++++++++++------ pallets/parachain-staking/src/mock.rs | 26 +++++- pallets/parachain-staking/src/tests.rs | 47 ++++++----- 3 files changed, 136 insertions(+), 44 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index aa4513c55a..44ef3e2ccd 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -821,7 +821,7 @@ pub mod pallet { // set rewards for all collators and delegators due CandidatePool::::iter().for_each(|(id, state)| { - Self::inc_collator_reward(&id, state.stake); + Self::do_inc_collator_reward(&id, state.stake); }); Self::deposit_event(Event::RoundInflationSet( @@ -937,7 +937,6 @@ pub mod pallet { /// - Reads: [Origin Account], Round /// - Writes: Round /// # - // TODO: Maybe refactor to set rewards for all network participants #[pallet::weight(::WeightInfo::set_blocks_per_round())] pub fn set_blocks_per_round(origin: OriginFor, new: T::BlockNumber) -> DispatchResult { ensure_root(origin)?; @@ -1397,7 +1396,7 @@ pub mod pallet { CandidatePool::::insert(&collator, state); // increment rewards for origin + their delegators and reset reward counter - Self::inc_collator_reward(&collator, before_stake); + Self::do_inc_collator_reward(&collator, before_stake); Self::deposit_event(Event::CollatorStakedMore(collator, before_stake, after_stake)); Ok(Some(::WeightInfo::candidate_stake_more( @@ -1474,7 +1473,7 @@ pub mod pallet { CandidatePool::::insert(&collator, state); // increment rewards for origin + their delegators and reset reward counter - Self::inc_collator_reward(&collator, before_stake); + Self::do_inc_collator_reward(&collator, before_stake); Self::deposit_event(Event::CollatorStakedLess(collator, before_stake, after)); Ok(Some(::WeightInfo::candidate_stake_less( @@ -1950,7 +1949,7 @@ pub mod pallet { }; // set rewards and reset reward counter - Self::inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); + Self::do_inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); CandidatePool::::insert(&candidate, collator); DelegatorState::::insert(&delegator, delegations); @@ -2042,7 +2041,7 @@ pub mod pallet { }; // set rewards and reset reward counter - Self::inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); + Self::do_inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); CandidatePool::::insert(&candidate, collator); DelegatorState::::insert(&delegator, delegations); @@ -2080,7 +2079,22 @@ pub mod pallet { Ok(Some(::WeightInfo::unlock_unstaked(unstaking_len)).into()) } - // TODO: Benchmark, unit tests, docs + /// Claim block authoring rewards for the target address. + /// + /// Requires `Rewards` to be set beforehand, which can by triggered by + /// any of the following options + /// * Calling increment_{collator, delegator}_rewards (active) + /// * Altering your stake (active) + /// * Leaving the network as a collator (active) + /// * Revoking a delegation as a delegator (active) + /// * Being a delegator whose collator left the network, altered their + /// stake or incremented rewards (passive) + /// + /// The dispatch origin can be any signed one, e.g., anyone can claim + /// for anyone. + /// + /// Emits `Rewarded`. + // TODO: Benchmark, unit tests #[pallet::weight(0)] pub fn claim_rewards_for(origin: OriginFor, target: ::Source) -> DispatchResult { ensure_signed(origin)?; @@ -2088,7 +2102,7 @@ pub mod pallet { // we could kill the storage entry but let's be safe in case the deposit fails let rewards = Rewards::::get(&target); - ensure!(rewards.is_zero(), Error::::RewardsNotFound); + ensure!(!rewards.is_zero(), Error::::RewardsNotFound); // mint into target and reset rewards let rewards = T::Currency::deposit_into_existing(&target, rewards)?; @@ -2099,6 +2113,56 @@ pub mod pallet { Ok(()) } + /// Actively increment the rewards of a collator and their delegators. + /// + /// The same effect is triggered by changing the stake or leaving the + /// network. + /// + /// The dispatch origin must be a collator. + // TODO: Benchmark, unit tests + #[pallet::weight(0)] + pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + + // early exit + let reward_count = RewardCount::::get(&collator); + ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); + + let weight = Self::do_inc_collator_reward(&collator, state.stake); + Ok(Some(weight).into()) + } + + /// Actively increment the rewards of a delegator for all their + /// delegations. + /// + /// The same effect is triggered by changing the stake or revoking + /// delegations. + /// + /// The dispatch origin must be a delegator. + // TODO: Benchmark, unit tests + #[pallet::weight(0)] + pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + let state = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + + // early exit + let reward_count = RewardCount::::take(&delegator); + ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); + + // iterate delegations + let mut post_weight: Weight = 0; + for delegation in state.delegations.into_iter() { + post_weight = post_weight.saturating_add(Self::do_inc_delegator_reward( + &delegator, + delegation.amount, + &delegation.owner, + )); + } + + Ok(Some(post_weight).into()) + } + /// Executes the annual reduction of the reward rates for collators and /// delegators. Moreover, sets rewards for all collators and delegators /// before adjusting the inflation. @@ -2140,7 +2204,7 @@ pub mod pallet { // set rewards for all collators and delegators before updating reward rates CandidatePool::::iter().for_each(|(id, state)| { - Self::inc_collator_reward(&id, state.stake); + Self::do_inc_collator_reward(&id, state.stake); }); // update inflation config @@ -2436,7 +2500,7 @@ pub mod pallet { let new_total = state.total; // set rewards - Self::inc_delegator_reward(&delegator, delegator_stake, &collator); + Self::do_inc_delegator_reward(&delegator, delegator_stake, &collator); // we don't unlock immediately Self::prep_unstake(&delegator, delegator_stake, false)?; @@ -2588,7 +2652,7 @@ pub mod pallet { state.total = state.total.saturating_sub(stake_to_remove.amount); // set rewards for kicked delegator - Self::inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); + Self::do_inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); // update storage of kicked delegator let kicked_delegator = Self::prep_kick_delegator(&stake_to_remove, &state.id)?; @@ -2727,8 +2791,6 @@ pub mod pallet { ) -> DispatchResult { // iterate over delegators for stake in &state.delegators[..] { - // // increment rewards of delegator - // Self::inc_delegator_reward(&stake.owner, stake.amount, collator); // prepare unstaking of delegator Self::prep_unstake(&stake.owner, stake.amount, true)?; // remove delegation from delegator state @@ -2748,7 +2810,7 @@ pub mod pallet { // *** No Fail beyond this point *** // increment rewards of collator and their delegators - Self::inc_collator_reward(collator, state.stake); + Self::do_inc_collator_reward(collator, state.stake); // disable validator for next session if they were in the set of validators pallet_session::Pallet::::validators() @@ -2921,20 +2983,20 @@ pub mod pallet { /// /// Resets all reward counters of the collator and their delegators to /// zero. - fn inc_collator_reward(collator: &T::AccountId, stake: BalanceOf) -> Weight { + fn do_inc_collator_reward(collator: &T::AccountId, stake: BalanceOf) -> Weight { let mut post_weight = Weight::zero(); // get reward counters let col_reward_count = RewardCount::::get(collator); // set reward data for collator Rewards::::mutate(collator, |reward| { - reward.saturating_add(Self::calc_block_rewards_collator(stake, col_reward_count.into())) + *reward = reward.saturating_add(Self::calc_block_rewards_collator(stake, col_reward_count.into())); }); // set reward data for delegators if let Some(state) = CandidatePool::::get(collator.clone()) { for Stake { owner, amount } in state.delegators { - post_weight = post_weight.saturating_add(Self::inc_delegator_reward(&owner, amount, collator)); + post_weight = post_weight.saturating_add(Self::do_inc_delegator_reward(&owner, amount, collator)); // Reset delegator counter since collator counter will be reset RewardCount::::insert(owner, 0); post_weight = post_weight.saturating_add(T::DbWeight::get().reads(1)); @@ -2951,7 +3013,7 @@ pub mod pallet { /// Increment the accumulated rewards of a delegator by consuming their /// current rewards counter. The counter will be reset to the collator /// counter. - fn inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) -> Weight { + fn do_inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) -> Weight { // get reward counters let del_reward_count = RewardCount::::get(acc); let col_reward_count = RewardCount::::get(col); @@ -2960,7 +3022,7 @@ pub mod pallet { // only update if collator has higher reward count if diff > 0 { Rewards::::mutate(acc, |reward| { - reward.saturating_add(Self::calc_block_rewards_delegator(stake, diff.into())) + *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, diff.into())); }); // TODO: Investigate whether we want to set this to some input variable to // improve `add_collator_reward` @@ -2990,9 +3052,8 @@ pub mod pallet { where T: Config + pallet_authorship::Config + pallet_session::Config, { - // TODO: Docs - /// Increments the reward counter of the block author by the number of - /// collators. + /// Increments the reward counter of the block author by the current + /// number of collators in the session. fn note_author(author: T::AccountId) { // should always include state except if the collator has been forcedly removed // via `force_remove_candidate` in the current or previous round @@ -3000,7 +3061,7 @@ pub mod pallet { // necessary to compensate for a potentially fluctuating number of collators let authors = pallet_session::Pallet::::validators(); RewardCount::::mutate(&author, |count| { - count.saturating_add(authors.len().saturated_into::()) + *count = count.saturating_add(authors.len().saturated_into::()); }); } diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index 8a044d4f1c..cc2bb37f0a 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -22,7 +22,7 @@ use super::*; use crate::{self as stake, types::NegativeImbalanceOf}; use frame_support::{ - construct_runtime, parameter_types, + assert_ok, construct_runtime, parameter_types, traits::{Currency, GenesisBuild, OnFinalize, OnInitialize, OnUnbalanced}, weights::Weight, }; @@ -370,6 +370,30 @@ pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { } } +#[allow(unused_must_use)] +pub(crate) fn roll_to_claim_rewards(n: BlockNumber, authors: Vec>) { + while System::block_number() < n { + if let Some(Some(author)) = authors.get((System::block_number()) as usize) { + StakePallet::note_author(*author); + // author must convert RewardCount to Rewards before claiming + assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(*author))); + // author claims rewards + assert_ok!(StakePallet::claim_rewards_for(Origin::signed(*author), *author)); + + // claim rewards for delegators + let col_state = StakePallet::candidate_pool(author).expect("Block author must be candidate"); + for delegation in col_state.delegators { + // NOTE: cannot use assert_ok! as we sometimes expect zero rewards for + // delegators such that the claiming would throw + StakePallet::claim_rewards_for(Origin::signed(*author), delegation.owner); + } + } + >::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + >::on_initialize(System::block_number()); + } +} + pub(crate) fn last_event() -> Event { System::events().pop().expect("Event expected").event } diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 20e651a4e4..bef86d0807 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -30,8 +30,9 @@ use sp_runtime::{traits::Zero, Perbill, Permill, Perquintill, SaturatedConversio use crate::{ mock::{ - almost_equal, events, last_event, roll_to, AccountId, Balance, Balances, BlockNumber, Event as MetaEvent, - ExtBuilder, Origin, Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, TREASURY_ACC, + almost_equal, events, last_event, roll_to, roll_to_claim_rewards, AccountId, Balance, Balances, BlockNumber, + Event as MetaEvent, ExtBuilder, Origin, Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, + TREASURY_ACC, }, set::OrderedSet, types::{ @@ -1628,7 +1629,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_eq!(Balances::usable_balance(&5), user_5); // 1 is block author for 1st block - roll_to(2, authors.clone()); + roll_to_claim_rewards(2, authors.clone()); assert_eq!(Balances::usable_balance(&1), user_1 + c_rewards); assert_eq!(Balances::usable_balance(&2), user_2); assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2); @@ -1636,7 +1637,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_eq!(Balances::usable_balance(&5), user_5); // 1 is block author for 2nd block - roll_to(3, authors.clone()); + roll_to_claim_rewards(3, authors.clone()); assert_eq!(Balances::usable_balance(&1), user_1 + 2 * c_rewards); assert_eq!(Balances::usable_balance(&2), user_2); assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards); @@ -1644,7 +1645,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_eq!(Balances::usable_balance(&5), user_5); // 1 is block author for 3rd block - roll_to(4, authors.clone()); + roll_to_claim_rewards(4, authors.clone()); assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); assert_eq!(Balances::usable_balance(&2), user_2); assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); @@ -1652,7 +1653,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_eq!(Balances::usable_balance(&5), user_5); // 2 is block author for 4th block - roll_to(5, authors.clone()); + roll_to_claim_rewards(5, authors.clone()); assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); assert_eq!(Balances::usable_balance(&2), user_2 + c_rewards); assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); @@ -1661,7 +1662,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_ok!(StakePallet::revoke_delegation(Origin::signed(5), 2)); // 2 is block author for 5th block - roll_to(6, authors); + roll_to_claim_rewards(6, authors); assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); assert_eq!(Balances::usable_balance(&2), user_2 + 2 * c_rewards); assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); @@ -1685,7 +1686,7 @@ fn delegator_should_not_receive_rewards_after_revoking() { let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); assert_eq!(Balances::usable_balance(&1), Balance::zero()); assert_eq!(Balances::usable_balance(&2), Balance::zero()); - roll_to(100, authors); + roll_to_claim_rewards(100, authors); assert!(Balances::usable_balance(&1) > Balance::zero()); assert_ok!(StakePallet::unlock_unstaked(Origin::signed(2), 2)); assert_eq!(Balances::usable_balance(&2), 10_000_000 * DECIMALS); @@ -1707,7 +1708,7 @@ fn delegator_should_not_receive_rewards_after_revoking() { assert_eq!(Balances::usable_balance(&1), Balance::zero()); assert_eq!(Balances::usable_balance(&2), Balance::zero()); assert_eq!(Balances::usable_balance(&3), Balance::zero()); - roll_to(100, authors); + roll_to_claim_rewards(100, authors); assert!(Balances::usable_balance(&1) > Balance::zero()); assert!(Balances::usable_balance(&2) > Balance::zero()); assert_ok!(StakePallet::unlock_unstaked(Origin::signed(3), 3)); @@ -1740,7 +1741,7 @@ fn coinbase_rewards_many_blocks_simple_check() { let end_block: BlockNumber = num_of_years * Test::BLOCKS_PER_YEAR as BlockNumber; // set round robin authoring let authors: Vec> = (0u64..=end_block).map(|i| Some(i % 2 + 1)).collect(); - roll_to(end_block, authors); + roll_to_claim_rewards(end_block, authors); let rewards_1 = Balances::free_balance(&1).saturating_sub(40_000_000 * DECIMALS); let rewards_2 = Balances::free_balance(&2).saturating_sub(40_000_000 * DECIMALS); @@ -1847,7 +1848,7 @@ fn should_not_reward_delegators_below_min_stake() { assert_eq!(Balances::usable_balance(&4), 5); // should only reward 1 - roll_to(4, authors); + roll_to_claim_rewards(4, authors); assert!(Balances::usable_balance(&1) > Balance::zero()); assert_eq!(Balances::usable_balance(&4), 5); assert_eq!(Balances::usable_balance(&2), Balance::zero()); @@ -2806,7 +2807,7 @@ fn adjust_reward_rates() { let authors: Vec> = (0u64..=num_of_years).map(|_| Some(1u64)).collect(); // reward once in first year - roll_to(2, authors.clone()); + roll_to_claim_rewards(2, authors.clone()); let c_rewards_0 = Balances::free_balance(&1).saturating_sub(10_000_000 * DECIMALS); let d_rewards_0 = Balances::free_balance(&2).saturating_sub(90_000_000 * DECIMALS); assert!(!c_rewards_0.is_zero()); @@ -2814,7 +2815,10 @@ fn adjust_reward_rates() { // finish first year System::set_block_number(::BLOCKS_PER_YEAR); - roll_to(::BLOCKS_PER_YEAR + 1, vec![]); + roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); + // reward reduction should not happen automatically anymore + assert_eq!(StakePallet::last_reward_reduction(), 0u64); + assert_ok!(StakePallet::execute_pending_reward_change(Origin::signed(1))); assert_eq!(StakePallet::last_reward_reduction(), 1u64); let inflation_1 = InflationInfo::new( ::BLOCKS_PER_YEAR, @@ -2825,7 +2829,7 @@ fn adjust_reward_rates() { ); assert_eq!(StakePallet::inflation_config(), inflation_1); // reward once in 2nd year - roll_to(::BLOCKS_PER_YEAR + 2, authors.clone()); + roll_to_claim_rewards(::BLOCKS_PER_YEAR + 2, authors.clone()); let c_rewards_1 = Balances::free_balance(&1) .saturating_sub(10_000_000 * DECIMALS) .saturating_sub(c_rewards_0); @@ -2842,7 +2846,10 @@ fn adjust_reward_rates() { // finish 2nd year System::set_block_number(2 * ::BLOCKS_PER_YEAR); - roll_to(2 * ::BLOCKS_PER_YEAR + 1, vec![]); + roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 1, vec![]); + // reward reduction should not happen automatically anymore + assert_eq!(StakePallet::last_reward_reduction(), 1u64); + assert_ok!(StakePallet::execute_pending_reward_change(Origin::signed(1))); assert_eq!(StakePallet::last_reward_reduction(), 2u64); let inflation_2 = InflationInfo::new( ::BLOCKS_PER_YEAR, @@ -2853,7 +2860,7 @@ fn adjust_reward_rates() { ); assert_eq!(StakePallet::inflation_config(), inflation_2); // reward once in 3rd year - roll_to(2 * ::BLOCKS_PER_YEAR + 2, authors); + roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 2, authors); let c_rewards_2 = Balances::free_balance(&1) .saturating_sub(10_000_000 * DECIMALS) .saturating_sub(c_rewards_0) @@ -3418,7 +3425,7 @@ fn authorities_per_round() { let inflation = StakePallet::inflation_config(); // roll to last block of round 0 - roll_to(4, authors.clone()); + roll_to_claim_rewards(4, authors.clone()); let reward_0 = inflation.collator.reward_rate.per_block * stake * 2; assert_eq!(Balances::free_balance(1), stake + reward_0); // increase max selected candidates which will become effective in round 2 @@ -3427,19 +3434,19 @@ fn authorities_per_round() { // roll to last block of round 1 // should still multiply with 2 because the Authority set was chosen at start of // round 1 - roll_to(9, authors.clone()); + roll_to_claim_rewards(9, authors.clone()); let reward_1 = inflation.collator.reward_rate.per_block * stake * 2; assert_eq!(Balances::free_balance(1), stake + reward_0 + reward_1); // roll to last block of round 2 // should multiply with 4 because there are only 4 candidates - roll_to(14, authors.clone()); + roll_to_claim_rewards(14, authors.clone()); let reward_2 = inflation.collator.reward_rate.per_block * stake * 4; assert_eq!(Balances::free_balance(1), stake + reward_0 + reward_1 + reward_2); // roll to last block of round 3 // should multiply with 4 because there are only 4 candidates - roll_to(19, authors); + roll_to_claim_rewards(19, authors); let reward_3 = inflation.collator.reward_rate.per_block * stake * 4; assert_eq!( Balances::free_balance(1), From 791ef9c623e53370ab61fd8441b53e59ef98700f Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 1 Aug 2022 11:15:01 +0200 Subject: [PATCH 05/34] tests: 80% --- pallets/parachain-staking/src/lib.rs | 2 +- pallets/parachain-staking/src/tests.rs | 311 ++++++++++++++++++++++++- 2 files changed, 305 insertions(+), 8 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 44ef3e2ccd..de95c8b6ee 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -3057,7 +3057,7 @@ pub mod pallet { fn note_author(author: T::AccountId) { // should always include state except if the collator has been forcedly removed // via `force_remove_candidate` in the current or previous round - if CandidatePool::::get(author.clone()).is_some() { + if CandidatePool::::get(&author).is_some() { // necessary to compensate for a potentially fluctuating number of collators let authors = pallet_session::Pallet::::validators(); RewardCount::::mutate(&author, |count| { diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index bef86d0807..5692b7be66 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -24,6 +24,7 @@ use frame_support::{ assert_noop, assert_ok, storage::bounded_btree_map::BoundedBTreeMap, traits::EstimateNextSessionRotation, BoundedVec, }; +use pallet_authorship::EventHandler; use pallet_balances::{BalanceLock, Error as BalancesError, Reasons}; use pallet_session::{SessionManager, ShouldEndSession}; use sp_runtime::{traits::Zero, Perbill, Permill, Perquintill, SaturatedConversion}; @@ -935,7 +936,10 @@ fn multiple_delegations() { .build() .execute_with(|| { assert_ok!(StakePallet::set_max_selected_candidates(Origin::root(), 5)); - roll_to(8, vec![]); + roll_to( + 8, + vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(1), Some(2), Some(3)], + ); // chooses top MaxSelectedCandidates (5), in order assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; @@ -957,7 +961,10 @@ fn multiple_delegations() { Error::::MaxCollatorsPerDelegatorExceeded, ); - roll_to(16, vec![]); + roll_to( + 16, + vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(1), Some(2), Some(3)], + ); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); let mut new = vec![ Event::Delegation(6, 10, 2, 50), @@ -969,7 +976,7 @@ fn multiple_delegations() { expected.append(&mut new); assert_eq!(events(), expected); - roll_to(21, vec![]); + roll_to(21, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(7), 2, 80)); assert_noop!( StakePallet::delegate_another_candidate(Origin::signed(7), 3, 11), @@ -986,7 +993,11 @@ fn multiple_delegations() { assert_eq!(StakePallet::unstaking(6).get(&23), Some(&10u128)); // kick 9 assert!(StakePallet::unstaking(9).is_empty()); + assert!(StakePallet::rewards(9).is_zero()); assert_ok!(StakePallet::join_delegators(Origin::signed(11), 2, 11)); + // 11 should be initiated with the same reward counter as their collator 2 + assert_eq!(StakePallet::reward_count(2), StakePallet::reward_count(11)); + assert!(StakePallet::delegator_state(9).is_none()); assert_eq!(StakePallet::unstaking(9).get(&23), Some(&10u128)); assert!(!StakePallet::candidate_pool(2) @@ -994,7 +1005,7 @@ fn multiple_delegations() { .delegators .contains(&StakeOf:: { owner: 9, amount: 10 })); - roll_to(26, vec![]); + roll_to(26, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 4, 3, 5]); let mut new2 = vec![ Event::NewRound(20, 4), @@ -1014,7 +1025,7 @@ fn multiple_delegations() { MetaEvent::StakePallet(Event::CollatorScheduledExit(5, 2, 7)) ); - roll_to(31, vec![]); + roll_to(31, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); let mut new3 = vec![ Event::LeftTopCandidates(2), Event::CollatorScheduledExit(5, 2, 7), @@ -1046,7 +1057,7 @@ fn multiple_delegations() { assert_eq!(Balances::free_balance(&7), 100); assert_eq!(Balances::free_balance(&11), 100); - roll_to(35, vec![]); + roll_to(35, vec![Some(1), Some(2), Some(3), Some(4)]); assert_ok!(StakePallet::execute_leave_candidates(Origin::signed(2), 2)); let mut unbonding_7: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); @@ -1057,7 +1068,7 @@ fn multiple_delegations() { assert_ok!(unbonding_11.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); assert_eq!(StakePallet::unstaking(11), unbonding_11); - roll_to(37, vec![]); + roll_to(37, vec![Some(1), Some(2)]); assert_eq!(StakePallet::delegator_state(7).unwrap().total, 10); assert!(StakePallet::delegator_state(11).is_none()); assert_eq!(StakePallet::delegator_state(7).unwrap().delegations.len(), 1usize); @@ -3933,3 +3944,289 @@ fn update_total_stake_no_collator_changes() { ); }); } + +#[test] +fn rewards_candidate_stake_more() { + ExtBuilder::default() + .with_balances(vec![(1, 2 * DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // stake more to trigger reward incrementing + assert_ok!(StakePallet::candidate_stake_more(Origin::signed(1), DECIMALS)); + (1..=3).for_each(|id| { + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + +#[test] +fn rewards_candidate_stake_less() { + ExtBuilder::default() + .with_balances(vec![(1, 2 * DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, 2 * DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero()); + }); + + // stake more to trigger reward incrementing + assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), DECIMALS)); + (1..=3).for_each(|id| { + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + }); + }); +} +#[test] +fn rewards_candidate_leave_network() { + ExtBuilder::default() + .with_balances(vec![ + (1, 2 * DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, 2 * DECIMALS), (4, DECIMALS), (5, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // init does not increment rewards + assert_ok!(StakePallet::init_leave_candidates(Origin::signed(1))); + + // advance two rounds to enable leaving + roll_to( + 10, + vec![ + // we're in block 1 already, so cannot note_author in roll_to + None, + Some(1), + Some(2), + Some(1), + Some(2), + Some(1), + Some(2), + Some(1), + Some(2), + ], + ); + assert_eq!(StakePallet::reward_count(1), 4 * 2); + + // count for delegators should not be incremented + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + + // rewards should not be incremented + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero()); + }); + + // execute leave intent to trigger reward incrementing + assert_ok!(StakePallet::execute_leave_candidates(Origin::signed(1), 1)); + (1..=3).for_each(|id| { + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + +#[test] +fn reward_count_join_delegators() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + // delegator should have same counter as collator upon joining + assert_eq!(StakePallet::reward_count(2), 1); + }); +} + +#[test] +fn rewards_delegator_stake_more() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // stake more to trigger reward incrementing just for 3 + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, DECIMALS)); + // 1 should still have counter 1 but no rewards + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::rewards(1).is_zero()); + // 2 should still have neither rewards nor counter + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + // 3 should have rewards and the same counter as 1 + assert_eq!(StakePallet::reward_count(3), 1); + assert!(!StakePallet::rewards(3).is_zero()); + }); +} + +#[test] +fn rewards_delegator_stake_less() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, 2 * DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // stake more to trigger reward incrementing just for 3 + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(3), 1, DECIMALS)); + // 1 should still have counter 1 but no rewards + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::rewards(1).is_zero()); + // 2 should still have neither rewards nor counter + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + // 3 should have rewards and the same counter as 1 + assert_eq!(StakePallet::reward_count(3), 1); + assert!(!StakePallet::rewards(3).is_zero()); + }); +} + +#[test] +fn rewards_delegator_replaced() { + ExtBuilder::default() + .with_balances(vec![ + (1, 2 * DECIMALS), + (2, 2 * DECIMALS), + (3, 2 * DECIMALS), + (4, 2 * DECIMALS), + (5, 2 * DECIMALS), + (6, 2 * DECIMALS), + ]) + .with_collators(vec![(1, 2 * DECIMALS)]) + .with_delegators(vec![ + (2, 1, 2 * DECIMALS), + (3, 1, 2 * DECIMALS), + (4, 1, 2 * DECIMALS), + (5, 1, DECIMALS), + ]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + + // 6 kicks 5 + assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 2 * DECIMALS)); + // 5 should have rewards and counter updated + assert!(!StakePallet::rewards(5).is_zero()); + assert_eq!(StakePallet::reward_count(5), 1); + // 6 should not have rewards but same counter as former collator + assert!(StakePallet::rewards(6).is_zero()); + assert_eq!(StakePallet::reward_count(6), 1); + }); +} + +#[test] +fn rewards_delegator_revokes_single_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, 2 * DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // stake more to trigger reward incrementing just for 3 + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, DECIMALS)); + // 1 should still have counter 1 but no rewards + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::rewards(1).is_zero()); + // 2 should still have neither rewards nor counter + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + // 3 should have rewards and the same counter as 1 + assert_eq!(StakePallet::reward_count(3), 1); + assert!(!StakePallet::rewards(3).is_zero()); + }); +} + +#[test] +fn rewards_delegator_leaves() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) + .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) + .with_delegators(vec![(3, 1, DECIMALS)]) + .build() + .execute_with(|| { + assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(3), 2, DECIMALS)); + // note both collators once to set their counter to 2 + StakePallet::note_author(1); + StakePallet::note_author(2); + assert_eq!(StakePallet::reward_count(1), 2); + assert_eq!(StakePallet::reward_count(2), 2); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // only 3 should have non-zero rewards and counter reset + assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); + (1..=2).for_each(|id| { + assert_eq!(StakePallet::reward_count(id), 2, "acc_id {:?}", id); + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + assert!(!StakePallet::rewards(3).is_zero()); + assert_eq!(StakePallet::reward_count(3), 4); + }); +} + +// TODO: +// rewards_delegator_revokes_single_delegation +// rewards_delegator_revokes_all_delegations +// rewards_delegator_delegates_another_candidate +// rewards_delegator_delegates_another_candidate_replacing +// rewards_set_inflation +// rewards_annual_inflation_adjustment From 38e92ddda7ea2de480aebbb727b4e98aba396db1 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 1 Aug 2022 18:08:37 +0200 Subject: [PATCH 06/34] feat: rm delegate_another_candidate and more --- pallets/parachain-staking/src/benchmarking.rs | 97 +-- pallets/parachain-staking/src/lib.rs | 557 ++---------------- pallets/parachain-staking/src/mock.rs | 8 +- pallets/parachain-staking/src/tests.rs | 530 +++++++---------- pallets/parachain-staking/src/types.rs | 115 ++-- runtimes/common/src/constants.rs | 3 - runtimes/peregrine/src/lib.rs | 2 - runtimes/spiritnet/src/lib.rs | 2 - 8 files changed, 305 insertions(+), 1009 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 1555c549da..235189666e 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -418,22 +418,22 @@ benchmarks! { // make sure delegator collated to collator let state = >::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, amount); + assert_eq!(>::get(&delegator).unwrap().amount, amount); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::from(u as u64))); - assert_eq!(>::get(&delegator).unwrap().total, amount + T::CurrencyBalance::from(u as u64)); + assert_eq!(>::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&collator, Some(&delegator), u as u64); - assert_eq!(>::get(&delegator).unwrap().total, amount); + assert_eq!(>::get(&delegator).unwrap().amount, amount); let unlookup_collator = T::Lookup::unlookup(collator.clone()); }: _(RawOrigin::Signed(delegator.clone()), unlookup_collator, amount) verify { let state = >::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(>::get(&delegator).unwrap().total, amount + amount); + assert_eq!(>::get(&delegator).unwrap().amount, amount + amount); assert!(>::get(&delegator).is_empty()); } @@ -453,16 +453,16 @@ benchmarks! { // make sure delegator collated to collator let state = >::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); assert_eq!(>::get(&delegator).len(), 1); let unlookup_collator = T::Lookup::unlookup(collator.clone()); @@ -470,44 +470,7 @@ benchmarks! { verify { let state = >::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); - assert_eq!(>::get(&delegator).len(), 2); - } - - revoke_delegation { - // we need at least 1 collators - let n in 1 .. T::MaxTopCandidates::get(); - // we need at least 1 delegator - let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - let amount = T::CurrencyBalance::one(); - - // make sure delegator collated to collator - let state = >::get(&collator).unwrap(); - let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); - - // increase stake so we can unstake, because current stake is minimum - T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount + amount); - - // decrease stake once so we have an unstaking entry for this block - assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount); - assert_eq!(>::get(&delegator).len(), 1); - let unlookup_collator = T::Lookup::unlookup(collator.clone()); - - }: _(RawOrigin::Signed(delegator.clone()), unlookup_collator) - verify { - let state = >::get(&collator).unwrap(); - assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); - assert!(>::get(&delegator).is_none()); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); assert_eq!(>::get(&delegator).len(), 2); } @@ -527,16 +490,16 @@ benchmarks! { // make sure delegator collated to collator let state = >::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); assert_eq!(>::get(&delegator).len(), 1); }: _(RawOrigin::Signed(delegator.clone())) @@ -585,44 +548,6 @@ benchmarks! { verify { assert_eq!(>::get(), new); } - - // [Post-launch TODO]: Activate after increasing MaxCollatorsPerDelegator to at least 2. Expected to throw otherwise. - // delegate_another_candidate { - // // we need at least 2 collators - // let n in 2 .. T::MaxTopCandidates::get(); - // // we need at least 1 delegator - // let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - // let u in 0 .. (T::MaxUnstakeRequests::get().saturated_into::() - 1); - - // let candidates = setup_collator_candidates::(n, None); - // for (i, c) in candidates.iter().enumerate() { - // fill_delegators::(m, c.clone(), i.saturated_into::()); - // } - // let collator_delegated = candidates[0].clone(); - // let collator = candidates.last().unwrap().clone(); - // let amount = T::MinDelegatorStake::get(); - - // // make sure delegator collated to collator_delegated - // let state_delegated = >::get(&collator_delegated).unwrap(); - // let delegator = state_delegated.delegators.into_bounded_vec()[0].owner.clone(); - // assert!(>::get(&delegator).is_some()); - - // // should not have delegated to collator yet - // let state = >::get(&collator).unwrap(); - // assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); - - // // increase stake so we can unstake, because current stake is minimum - // T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - // assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator_delegated.clone()), T::CurrencyBalance::from(u as u64))); - - // // fill unstake BTreeMap by unstaked many entries of 1 - // fill_unstaking::(&collator_delegated, Some(&delegator), u as u64); - - // }: _(RawOrigin::Signed(delegator.clone()), T::Lookup::unlookup(collator.clone()), amount) - // verify { - // let state = >::get(&collator).unwrap(); - // assert!(state.delegators.into_iter().any(|x| x.owner == delegator); - // } } impl_benchmark_test_suite!( diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index de95c8b6ee..93d1c243e2 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -126,10 +126,8 @@ //! by the provided amount down to `MinCandidateStake`. //! - `join_delegators` - Join the set of delegators by delegating to a collator //! candidate. -//! - `delegate_another_candidate` - Delegate to another collator candidate by -//! staking for them. -//! - `leave_delegators` - Leave the set of delegators and revoke all -//! delegations. Since delegators do not have to run a node and cannot be +//! - `leave_delegators` - Leave the set of delegators and revoke your +//! delegation. Since delegators do not have to run a node and cannot be //! selected to become block authors, this exit is not delayed like it is for //! collator candidates. //! - `revoke_delegation` - Revoke a single delegation to a collator candidate. @@ -171,7 +169,6 @@ mod types; use frame_support::pallet; pub use crate::{default_weights::WeightInfo, pallet::*}; -use types::ReplacedDelegator; #[pallet] pub mod pallet { @@ -291,10 +288,6 @@ pub mod pallet { #[pallet::constant] type MaxDelegatorsPerCollator: Get + Debug + PartialEq; - /// Maximum number of collators a single delegator can delegate. - #[pallet::constant] - type MaxCollatorsPerDelegator: Get + Debug + PartialEq; - /// Maximum size of the top candidates set. #[pallet::constant] type MaxTopCandidates: Get + Debug + PartialEq; @@ -309,10 +302,6 @@ pub mod pallet { #[pallet::constant] type MinCollatorCandidateStake: Get>; - /// Minimum stake required for any account to be able to delegate. - #[pallet::constant] - type MinDelegation: Get>; - /// Minimum stake required for any account to become a delegator. #[pallet::constant] type MinDelegatorStake: Get>; @@ -368,8 +357,6 @@ pub mod pallet { ValStakeBelowMin, /// The account has already staked the maximum amount of funds possible. ValStakeAboveMax, - /// The account has not staked enough funds to become a delegator. - NomStakeBelowMin, /// The account has not staked enough funds to delegate a collator /// candidate. DelegationBelowMin, @@ -586,13 +573,8 @@ pub mod pallet { /// It maps from an account to its delegation details. #[pallet::storage] #[pallet::getter(fn delegator_state)] - pub(crate) type DelegatorState = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegator, T::MaxCollatorsPerDelegator>, - OptionQuery, - >; + pub(crate) type DelegatorState = + StorageMap<_, Twox64Concat, T::AccountId, Delegator>, OptionQuery>; /// The staking information for a candidate. /// @@ -1000,23 +982,6 @@ pub mod pallet { /// Increments rewards of candidate and their delegators. /// /// Emits `CandidateRemoved`. - /// - /// # - /// - The transaction's complexity is mainly dependent on updating the - /// `SelectedCandidates` storage in `select_top_candidates` which in - /// return depends on the number of `MaxSelectedCandidates` (N). - /// - For each N, we read `CandidatePool` from the storage. - /// --------- - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators of the - /// collator candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: MaxCollatorCandidateStake, 2 * N * CandidatePool, - /// TopCandidates, BlockNumber, D * DelegatorState, D * Unstaking - /// - Writes: MaxCollatorCandidateStake, N * CandidatePool, D * - /// DelegatorState, (D + 1) * Unstaking - /// - Kills: CandidatePool, DelegatorState for all delegators which only - /// delegated to the candidate - /// # #[pallet::weight(::WeightInfo::force_remove_candidate( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1084,14 +1049,6 @@ pub mod pallet { /// Emits `JoinedCollatorCandidates`. /// /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], DelegatorState, - /// MaxCollatorCandidateStake, Locks, TotalCollatorStake, - /// TopCandidates, MaxSelectedCandidates, CandidatePool, - /// - Writes: Locks, TotalCollatorStake, CandidatePool, TopCandidates, - /// # #[pallet::weight(::WeightInfo::join_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1165,20 +1122,6 @@ pub mod pallet { /// rewards, until the end of the next session. /// /// Emits `CollatorScheduledExit`. - /// - /// # - /// - The transaction's complexity is mainly dependent on updating the - /// `SelectedCandidates` storage in `select_top_candidates` which in - /// return depends on the number of `MaxSelectedCandidates` (N). - /// - For each N, we read `CandidatePool` from the storage. - /// --------- - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], TopCandidates, (N + 1) * CandidatePool, - /// TotalCollatorStake - /// - Writes: CandidatePool, TopCandidates, TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::init_leave_candidates( T::MaxTopCandidates::get(), T::MaxTopCandidates::get().saturating_mul(T::MaxDelegatorsPerCollator::get()) @@ -1237,17 +1180,6 @@ pub mod pallet { /// `cancel_leave_candidates`. /// /// Emits `CollatorLeft`. - /// - /// # - /// Weight: O(N + D + U) where where N is `MaxSelectedCandidates` - /// bounded by `MaxTopCandidates`, D is the number of delegators for - /// this candidate bounded by `MaxDelegatorsPerCollator` and U is the - /// number of locked unstaking requests bounded by `MaxUnstakeRequests`. - /// - Reads: CandidatePool, Round, D * DelegatorState, D - /// * BlockNumber, D * Unstaking - /// - Writes: D * Unstaking, D * DelegatorState, Total - /// - Kills: CandidatePool, DelegatorState - /// # #[pallet::weight(::WeightInfo::execute_leave_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1287,15 +1219,6 @@ pub mod pallet { /// `init_leave_candidates`. /// /// Emits `CollatorCanceledExit`. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], TotalCollatorStake, TopCandidates, - /// CandidatePool - /// - Writes: TotalCollatorStake, CandidatePool, TopCandidates - /// # #[pallet::weight(::WeightInfo::cancel_leave_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1343,16 +1266,6 @@ pub mod pallet { /// allowed range as set in the pallet's configuration. /// /// Emits `CollatorStakedMore`. - /// - /// # - /// Weight: O(N + D + U) where where N is `MaxSelectedCandidates` - /// bounded by `MaxTopCandidates`, D is the number of delegators for - /// this candidate bounded by `MaxDelegatorsPerCollator` and U is the - /// number of locked unstaking requests bounded by `MaxUnstakeRequests`. - /// - Reads: [Origin Account], Locks, TotalCollatorStake, - /// MaxCollatorCandidateStake, TopCandidates, CandidatePool - /// - Writes: Locks, TotalCollatorStake, CandidatePool, TopCandidates - /// # #[pallet::weight(::WeightInfo::candidate_stake_more( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1422,15 +1335,6 @@ pub mod pallet { /// allowed range as set in the pallet's configuration. /// /// Emits `CollatorStakedLess`. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], Unstaking, TopCandidates, - /// MaxSelectedCandidates, CandidatePool - /// - Writes: Unstaking, CandidatePool, TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::candidate_stake_less( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1488,8 +1392,8 @@ pub mod pallet { /// The account that wants to delegate cannot be part of the collator /// candidates set as well. /// - /// The caller must _not_ have delegated before. Otherwise, - /// `delegate_another_candidate` should be called. + /// The caller must _not_ have a delegation. If that is the case, they + /// are required to first remove the delegation. /// /// The amount staked must be larger than the minimum required to become /// a delegator as set in the pallet's configuration. @@ -1505,16 +1409,6 @@ pub mod pallet { /// Emits `DelegationReplaced` if the candidate has /// `MaxDelegatorsPerCollator` many delegations but this delegator /// staked more than one of the other delegators of this candidate. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], DelegatorState, TopCandidates, - /// MaxSelectedCandidates, CandidatePool, LastDelegation, Round - /// - Writes: Locks, CandidatePool, DelegatorState, TotalCollatorStake, - /// LastDelegation - /// # #[pallet::weight(::WeightInfo::join_delegators( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1535,7 +1429,7 @@ pub mod pallet { // first delegation ensure!(DelegatorState::::get(&acc).is_none(), Error::::AlreadyDelegating); - ensure!(amount >= T::MinDelegatorStake::get(), Error::::NomStakeBelowMin); + ensure!(amount >= T::MinDelegatorStake::get(), Error::::DelegationBelowMin); // cannot be a collator candidate and delegator with same AccountId ensure!(Self::is_active_candidate(&acc).is_none(), Error::::CandidateExists); @@ -1568,11 +1462,10 @@ pub mod pallet { // should never fail but let's be safe ensure!(insert_delegator, Error::::DelegatorExists); - // can only throw if MaxCollatorsPerDelegator is set to 0 which should never - // occur in practice, even if the delegator rewards are set to 0 - let delegator_state = Delegator::try_new(collator.clone(), amount) - .map_err(|_| Error::::MaxCollatorsPerDelegatorExceeded)?; - + let delegator_state = Delegator { + amount, + owner: Some(collator.clone()), + }; let CandidateOf:: { stake: old_stake, total: old_total, @@ -1581,12 +1474,11 @@ pub mod pallet { // update state and potentially prepare kicking a delegator with less staked // amount (includes setting rewards for kicked delegator) - let (state, maybe_kicked_delegator) = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() - { + let state = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() { Self::do_update_delegator(delegation, state)? } else { state.total = state.total.saturating_add(amount); - (state, None) + state }; let new_total = state.total; @@ -1617,9 +1509,6 @@ pub mod pallet { // initiate reward counter to match the current state of the candidate RewardCount::::insert(&acc, RewardCount::::get(&collator)); - // update or clear storage of potentially kicked delegator - Self::update_kicked_delegator_storage(maybe_kicked_delegator); - Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); Ok(Some(::WeightInfo::join_delegators( n, @@ -1628,166 +1517,8 @@ pub mod pallet { .into()) } - /// Delegate another collator's candidate by staking some funds and - /// increasing the pallet's as well as the collator's total stake. - /// - /// The account that wants to delegate cannot be part of the collator - /// candidates set as well. - /// - /// The caller _must_ have delegated before. Otherwise, - /// `join_delegators` should be called. - /// - /// If the delegator has already delegated the maximum number of - /// collator candidates, this operation will fail. - /// - /// The amount staked must be larger than the minimum required to become - /// a delegator as set in the pallet's configuration. - /// - /// As only `MaxDelegatorsPerCollator` are allowed to delegate a given - /// collator, the amount staked must be larger than the lowest one in - /// the current set of delegator for the operation to be meaningful. - /// - /// The collator's total stake as well as the pallet's total stake are - /// increased accordingly. - /// - /// NOTE: This transaction is expected to throw until we increase - /// `MaxCollatorsPerDelegator` by at least one, since it is currently - /// set to one. - /// - /// Emits `Delegation`. - /// Emits `DelegationReplaced` if the candidate has - /// `MaxDelegatorsPerCollator` many delegations but this delegator - /// staked more than one of the other delegators of this candidate. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], DelegatorState, TopCandidates, - /// MaxSelectedCandidates, CandidatePool, LastDelegation, Round - /// - Writes: Locks, CandidatePool, DelegatorState, TotalCollatorStake, - /// LastDelegation - /// # - // - // NOTE: We can't benchmark this extrinsic until we have increased `MaxCollatorsPerDelegator` by at least 1, - // thus we use the closest weight we can get. - #[pallet::weight(::WeightInfo::join_delegators( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn delegate_another_candidate( - origin: OriginFor, - collator: ::Source, - amount: BalanceOf, - ) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - let collator = T::Lookup::lookup(collator)?; - let mut delegator = DelegatorState::::get(&acc).ok_or(Error::::NotYetDelegating)?; - - // check balance - ensure!( - pallet_balances::Pallet::::free_balance(acc.clone()) - >= delegator.total.saturating_add(amount).into(), - pallet_balances::Error::::InsufficientBalance - ); - - // delegation after first - ensure!(amount >= T::MinDelegation::get(), Error::::DelegationBelowMin); - ensure!( - (delegator.delegations.len().saturated_into::()) < T::MaxCollatorsPerDelegator::get(), - Error::::MaxCollatorsPerDelegatorExceeded - ); - // cannot delegate if number of delegations in this round exceeds - // MaxDelegationsPerRound - let delegation_counter = Self::get_delegation_counter(&acc)?; - - // prepare new collator state - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - let num_delegations_pre_insertion: u32 = state.delegators.len().saturated_into(); - ensure!(!state.is_leaving(), Error::::CannotDelegateIfLeaving); - - // attempt to insert delegation, check for uniqueness and update total delegated - // amount - // NOTE: excess is handled below because we support replacing a delegator - // with fewer stake - ensure!( - delegator - .add_delegation(Stake { - owner: collator.clone(), - amount - }) - .unwrap_or(true), - Error::::AlreadyDelegatedCollator - ); - let delegation = Stake { - owner: acc.clone(), - amount, - }; - - // throws if delegation insertion exceeds bounded vec limit which we will handle - // below in Self::do_update_delegator - ensure!( - state.delegators.try_insert(delegation.clone()).unwrap_or(true), - Error::::DelegatorExists - ); - - let CandidateOf:: { - stake: old_stake, - total: old_total, - .. - } = state; - - // update state and potentially prepare kicking a delegator with less staked - // amount (includes reward setting for kicked delegator) - let (state, maybe_kicked_delegator) = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() - { - Self::do_update_delegator(delegation, state)? - } else { - state.total = state.total.saturating_add(amount); - (state, None) - }; - let new_total = state.total; - - // *** No Fail except during increase_lock beyond this point *** - - // lock stake - Self::increase_lock(&acc, delegator.total, amount)?; - - // update top candidates and total amount at stake - let n = if state.is_active() { - Self::update_top_candidates( - collator.clone(), - old_stake, - // safe because total >= stake - old_total - old_stake, - state.stake, - state.total - state.stake, - ) - } else { - 0u32 - }; - - // update states - CandidatePool::::insert(&collator, state); - DelegatorState::::insert(&acc, delegator); - >::insert(&acc, delegation_counter); - - // initiate reward counter to match the current state of the candidate - RewardCount::::insert(&acc, RewardCount::::get(&collator)); - - // update or clear storage of potentially kicked delegator - Self::update_kicked_delegator_storage(maybe_kicked_delegator); - - Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); - Ok(Some(::WeightInfo::join_delegators( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Leave the set of delegators and, by implication, revoke all ongoing - /// delegations. + /// Leave the set of delegators and, by implication, revoke the ingoing + /// delegation. /// /// All staked funds are not unlocked immediately, but they are added to /// the queue of pending unstaking, and will effectively be released @@ -1798,19 +1529,10 @@ pub mod pallet { /// their chances to be included in the set of candidates in the next /// rounds. /// - /// Automatically increments the accumulated rewards of the origin for - /// each delegation. + /// Automatically increments the accumulated rewards of the origin the + /// current delegation. /// /// Emits `DelegatorLeft`. - /// - /// # - /// Weight: O(C) where C is the number of delegations for this delegator - /// which is bounded by by `MaxCollatorsPerDelegator`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// TopCandidates, MaxSelectedCandidates, C * CandidatePool, - /// - Writes: Unstaking, CandidatePool, TotalCollatorStake, - /// - Kills: DelegatorState - /// # #[pallet::weight(::WeightInfo::leave_delegators( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1818,66 +1540,17 @@ pub mod pallet { pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { let acc = ensure_signed(origin)?; let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; - let num_delegations: u32 = delegator.delegations.len().saturated_into(); - - // remove delegations and increment rewards - for stake in delegator.delegations.into_iter() { - Self::delegator_leaves_collator(acc.clone(), stake.owner.clone())?; - } + // should never throw + let collator = delegator.owner.ok_or(Error::::DelegationNotFound)?; + Self::delegator_leaves_collator(acc.clone(), collator)?; // *** No Fail beyond this point *** DelegatorState::::remove(&acc); - Self::deposit_event(Event::DelegatorLeft(acc, delegator.total)); + Self::deposit_event(Event::DelegatorLeft(acc, delegator.amount)); Ok(Some(::WeightInfo::leave_delegators( - num_delegations, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Terminates an ongoing delegation for a given collator candidate. - /// - /// The staked funds are not unlocked immediately, but they are added to - /// the queue of pending unstaking, and will effectively be released - /// after `StakeDuration` blocks from the moment the delegation is - /// terminated. - /// - /// This operation reduces the total stake of the pallet as well as the - /// stakes of the collator involved, potentially affecting its chances - /// to be included in the set of candidates in the next rounds. - /// - /// Emits `DelegatorLeft`. - /// - /// # - /// Weight: O(C) where C is the number of delegations for this delegator - /// which is bounded by by `MaxCollatorsPerDelegator`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// Locks, TopCandidates, CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, Locks, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// - Kills: DelegatorState if the delegator has not delegated to - /// another collator - /// # - #[pallet::weight(::WeightInfo::revoke_delegation( - T::MaxCollatorsPerDelegator::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn revoke_delegation( - origin: OriginFor, - collator: ::Source, - ) -> DispatchResultWithPostInfo { - let collator = T::Lookup::lookup(collator)?; - let delegator = ensure_signed(origin)?; - - // *** No Fail except during delegator_revokes_collator beyond this point *** - - // revoke delegation and increment rewards - let num_delegations = Self::delegator_revokes_collator(delegator, collator)?; - - Ok(Some(::WeightInfo::revoke_delegation( - num_delegations, + 1, T::MaxDelegatorsPerCollator::get(), )) .into()) @@ -1889,17 +1562,6 @@ pub mod pallet { /// collator candidate to be added to it. /// /// Emits `DelegatorStakedMore`. - /// - /// # - /// Weight: O(N) + O(D) where N is `MaxSelectedCandidates` bounded - /// by `MaxTopCandidates` and D the number of total delegators for - /// this collator bounded by `MaxCollatorsPerDelegator`. - /// bounded by `MaxUnstakeRequests`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// Locks, TopCandidates, CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, Locks, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::delegator_stake_more( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1914,12 +1576,12 @@ pub mod pallet { ensure!(!more.is_zero(), Error::::ValStakeZero); let candidate = T::Lookup::lookup(candidate)?; - let mut delegations = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let stake_after = delegations + let stake_after = delegation .inc_delegation(candidate.clone(), more) - .ok_or(Error::::DelegationNotFound)?; + .map_err(|_| Error::::DelegationNotFound)?; // *** No Fail except during increase_lock beyond this point *** @@ -1952,7 +1614,7 @@ pub mod pallet { Self::do_inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); CandidatePool::::insert(&candidate, collator); - DelegatorState::::insert(&delegator, delegations); + DelegatorState::::insert(&delegator, delegation); Self::deposit_event(Event::DelegatorStakedMore(delegator, candidate, before_total, after)); Ok(Some(::WeightInfo::delegator_stake_more( @@ -2005,13 +1667,12 @@ pub mod pallet { ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); let stake_after = delegations .dec_delegation(candidate.clone(), less) - .ok_or(Error::::DelegationNotFound)? + .map_err(|_| Error::::DelegationNotFound)? .ok_or(Error::::Underflow)?; - ensure!(stake_after >= T::MinDelegation::get(), Error::::DelegationBelowMin); ensure!( - delegations.total >= T::MinDelegatorStake::get(), - Error::::NomStakeBelowMin + stake_after >= T::MinDelegatorStake::get(), + Error::::DelegationBelowMin ); // *** No Fail except during prep_unstake beyond this point *** @@ -2142,25 +1803,19 @@ pub mod pallet { /// The dispatch origin must be a delegator. // TODO: Benchmark, unit tests #[pallet::weight(0)] - pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { + pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { let delegator = ensure_signed(origin)?; - let state = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + // should never throw + let collator = delegation.owner.ok_or(Error::::DelegationNotFound)?; // early exit let reward_count = RewardCount::::take(&delegator); ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); - // iterate delegations - let mut post_weight: Weight = 0; - for delegation in state.delegations.into_iter() { - post_weight = post_weight.saturating_add(Self::do_inc_delegator_reward( - &delegator, - delegation.amount, - &delegation.owner, - )); - } + Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); - Ok(Some(post_weight).into()) + Ok(()) } /// Executes the annual reduction of the reward rates for collators and @@ -2391,14 +2046,6 @@ pub mod pallet { /// guarantee a single candidate's stake has changed, e.g. on genesis or /// when a collator leaves. Otherwise, please use /// [update_total_stake_by]. - /// - /// # - /// Weight: O(N) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` - /// - Reads: TopCandidates, MaxSelectedCandidates, N * CandidatePool, - /// TotalCollatorStake - /// - Writes: TotalCollatorStake - /// # fn update_total_stake() -> (u32, u32) { let mut num_of_delegators = 0u32; let mut collator_stake = BalanceOf::::zero(); @@ -2430,54 +2077,11 @@ pub mod pallet { (collators.len().saturated_into(), num_of_delegators) } - /// Update the delegator's state by removing the collator candidate from - /// the set of ongoing delegations. - /// - /// # - /// Weight: O(D) where D is the number of total delegators for - /// this collator bounded by `MaxCollatorsPerDelegator`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// Locks, TopCandidates, D * CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, Locks, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// - Kills: DelegatorState if the delegator has not delegated to - /// another collator - /// # - fn delegator_revokes_collator(acc: T::AccountId, collator: T::AccountId) -> Result { - let mut delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; - let old_total = delegator.total; - let num_delegations: u32 = delegator.delegations.len().saturated_into::(); - let remaining = delegator - .rm_delegation(&collator) - .ok_or(Error::::DelegationNotFound)?; - - // remove delegation and increment rewards - if delegator.delegations.is_empty() { - // edge case; if no delegations remaining, leave set of delegators - Self::delegator_leaves_collator(acc.clone(), collator)?; - DelegatorState::::remove(&acc); - Self::deposit_event(Event::DelegatorLeft(acc, old_total)); - } else { - // can never fail iff MinDelegatorStake == MinDelegation - ensure!(remaining >= T::MinDelegatorStake::get(), Error::::NomStakeBelowMin); - Self::delegator_leaves_collator(acc.clone(), collator)?; - DelegatorState::::insert(&acc, delegator); - } - Ok(num_delegations) - } - /// Update the collator's state by removing the delegator's stake and /// starting the process to unlock the delegator's staked funds as well /// as incrementing their accumulated rewards. /// /// This operation affects the pallet's total stake. - /// - /// # - /// Weight: O(D) where D is the number of delegators for this - /// collator bounded by `MaxDelegatorsPerCollator`. - /// - Reads: CandidatePool, BlockNumber, Unstaking - /// - Writes: Unstaking, TotalCollatorStake, CandidatePool - /// # fn delegator_leaves_collator(delegator: T::AccountId, collator: T::AccountId) -> DispatchResult { let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; @@ -2527,51 +2131,6 @@ pub mod pallet { Ok(()) } - /// Check for remaining delegations of the delegator which has been - /// removed from the given collator. - /// - /// Returns the removed delegator's address and - /// * Either the updated delegator state if other delegations are still - /// remaining - /// * Or `None`, signalling the delegator state should be cleared once - /// the transaction cannot fail anymore. - fn prep_kick_delegator( - delegation: &StakeOf, - collator: &T::AccountId, - ) -> Result, DispatchError> { - let mut state = DelegatorState::::get(&delegation.owner).ok_or(Error::::DelegatorNotFound)?; - state.rm_delegation(collator); - - // we don't unlock immediately - Self::prep_unstake(&delegation.owner, delegation.amount, true)?; - - // return state if not empty for later removal after all checks have passed - if state.delegations.is_empty() { - Ok(ReplacedDelegator { - who: delegation.owner.clone(), - state: None, - }) - } else { - Ok(ReplacedDelegator { - who: delegation.owner.clone(), - state: Some(state), - }) - } - } - - /// Either clear the storage of a kicked delegator or update its - /// delegation state if it still contains other delegations. - fn update_kicked_delegator_storage(delegator: Option>) { - match delegator { - Some(ReplacedDelegator { - who, - state: Some(state), - }) => DelegatorState::::insert(who, state), - Some(ReplacedDelegator { who, .. }) => DelegatorState::::remove(who), - _ => (), - } - } - /// Return the best `MaxSelectedCandidates` many candidates. /// /// In case a collator from last round was replaced by a candidate with @@ -2625,13 +2184,7 @@ pub mod pallet { fn do_update_delegator( stake: Stake>, mut state: Candidate, T::MaxDelegatorsPerCollator>, - ) -> Result< - ( - CandidateOf, - Option>, - ), - DispatchError, - > { + ) -> Result, DispatchError> { // attempt to replace the last element of the set let stake_to_remove = state .delegators @@ -2653,9 +2206,10 @@ pub mod pallet { // set rewards for kicked delegator Self::do_inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); - - // update storage of kicked delegator - let kicked_delegator = Self::prep_kick_delegator(&stake_to_remove, &state.id)?; + // prepare unstaking for kicked delegator + Self::prep_unstake(&stake_to_remove.owner, stake_to_remove.amount, true)?; + // remove Delegator state for kicked delegator + DelegatorState::::remove(&stake_to_remove.owner); Self::deposit_event(Event::DelegationReplaced( stake.owner, @@ -2665,11 +2219,9 @@ pub mod pallet { state.id.clone(), state.total, )); - - Ok((state, Some(kicked_delegator))) - } else { - Ok((state, None)) } + + Ok(state) } /// Either set or increase the BalanceLock of target account to @@ -2795,13 +2347,10 @@ pub mod pallet { Self::prep_unstake(&stake.owner, stake.amount, true)?; // remove delegation from delegator state if let Some(mut delegator) = DelegatorState::::get(&stake.owner) { - if let Some(remaining) = delegator.rm_delegation(collator) { - if remaining.is_zero() { - DelegatorState::::remove(&stake.owner); - } else { - DelegatorState::::insert(&stake.owner, delegator); - } - } + delegator + .rm_delegation(collator.clone()) + .map_err(|_| Error::::DelegationNotFound)?; + DelegatorState::::remove(&stake.owner); } } // prepare unstaking of collator candidate @@ -2888,15 +2437,11 @@ pub mod pallet { /// Checks whether a delegator can still delegate in this round, e.g., /// if they have not delegated MaxDelegationsPerRound many times /// already in this round. - /// - /// # - /// Weight: O(1) - /// - Reads: LastDelegation, Round - /// # fn get_delegation_counter(delegator: &T::AccountId) -> Result { let last_delegation = >::get(delegator); let round = >::get(); + // reset counter if the round advanced since last delegation let counter = if last_delegation.round < round.current { 0u32 } else { @@ -2904,7 +2449,7 @@ pub mod pallet { }; ensure!( - T::MaxDelegationsPerRound::get() > counter, + counter < T::MaxDelegationsPerRound::get(), Error::::DelegationsPerRoundExceeded ); @@ -2931,12 +2476,6 @@ pub mod pallet { /// /// `col_reward_rate_per_block * col_max_stake * max_num_of_collators * /// NetworkRewardRate` - /// - /// # - /// Weight: O(1) - /// - Reads: InflationConfig, MaxCollatorCandidateStake, - /// MaxSelectedCandidates - /// # fn get_network_reward() -> NegativeImbalanceOf { // Multiplication with Perquintill cannot overflow let max_col_rewards = InflationConfig::::get().collator.reward_rate.per_block diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index cc2bb37f0a..206a157821 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -134,15 +134,13 @@ parameter_types! { pub const ExitQueueDelay: u32 = 2; pub const DefaultBlocksPerRound: BlockNumber = BLOCKS_PER_ROUND; pub const MinCollators: u32 = 2; + pub const MaxDelegationsPerRound: u32 = 2; #[derive(Debug, PartialEq)] pub const MaxDelegatorsPerCollator: u32 = 4; - #[derive(Debug, PartialEq)] - pub const MaxCollatorsPerDelegator: u32 = 4; pub const MinCollatorStake: Balance = 10; #[derive(Debug, PartialEq)] pub const MaxCollatorCandidates: u32 = 10; pub const MinDelegatorStake: Balance = 5; - pub const MinDelegation: Balance = 3; pub const MaxUnstakeRequests: u32 = 6; pub const NetworkRewardRate: Perquintill = Perquintill::from_percent(10); pub const NetworkRewardStart: BlockNumber = 5 * 5 * 60 * 24 * 36525 / 100; @@ -166,14 +164,12 @@ impl Config for Test { type ExitQueueDelay = ExitQueueDelay; type MinCollators = MinCollators; type MinRequiredCollators = MinCollators; - type MaxDelegationsPerRound = MaxDelegatorsPerCollator; + type MaxDelegationsPerRound = MaxDelegationsPerRound; type MaxDelegatorsPerCollator = MaxDelegatorsPerCollator; - type MaxCollatorsPerDelegator = MaxCollatorsPerDelegator; type MinCollatorStake = MinCollatorStake; type MinCollatorCandidateStake = MinCollatorStake; type MaxTopCandidates = MaxCollatorCandidates; type MinDelegatorStake = MinDelegatorStake; - type MinDelegation = MinDelegation; type MaxUnstakeRequests = MaxUnstakeRequests; type NetworkRewardRate = NetworkRewardRate; type NetworkRewardStart = NetworkRewardStart; diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 5692b7be66..9a713081e7 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -349,6 +349,7 @@ fn collator_exit_executes_after_delay() { (7, 100), (8, 9), (9, 4), + (10, 10), ]) .with_collators(vec![(1, 500), (2, 200), (7, 100)]) .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) @@ -382,7 +383,7 @@ fn collator_exit_executes_after_delay() { // Still three, candidate didn't leave yet assert_eq!(CandidatePool::::count(), 3); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(3), 2, 10), + StakePallet::join_delegators(Origin::signed(10), 2, 10), Error::::CannotDelegateIfLeaving ); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 7]); @@ -713,47 +714,31 @@ fn execute_leave_candidates_with_delay() { } assert_eq!( StakePallet::delegator_state(11), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 110 }].try_into().unwrap() - ), - total: 110 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 110, + }) ); assert_eq!( StakePallet::delegator_state(12), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 120 }].try_into().unwrap() - ), - total: 120 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 120 + }) ); assert_eq!( StakePallet::delegator_state(13), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 130 }].try_into().unwrap() - ), - total: 130 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 130 + }) ); assert_eq!( StakePallet::delegator_state(14), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 140 }].try_into().unwrap() - ), - total: 140 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 140 + }) ); for delegator in 11u64..=14u64 { assert!(StakePallet::is_delegator(&delegator)); @@ -830,47 +815,31 @@ fn execute_leave_candidates_with_delay() { } assert_eq!( StakePallet::delegator_state(11), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 110 }].try_into().unwrap() - ), - total: 110 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 110 + }) ); assert_eq!( StakePallet::delegator_state(12), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 120 }].try_into().unwrap() - ), - total: 120 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 120 + }) ); assert_eq!( StakePallet::delegator_state(13), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 130 }].try_into().unwrap() - ), - total: 130 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 130 + }) ); assert_eq!( StakePallet::delegator_state(14), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 140 }].try_into().unwrap() - ), - total: 140 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 140 + }) ); for delegator in 11u64..=14u64 { assert!(StakePallet::is_delegator(&delegator)); @@ -913,6 +882,7 @@ fn execute_leave_candidates_with_delay() { }); } +// FIXME: Re-enable or potentially remove entirely #[test] fn multiple_delegations() { ExtBuilder::default() @@ -929,6 +899,14 @@ fn multiple_delegations() { (10, 100), (11, 100), (12, 100), + // new + (13, 100), + (14, 100), + (15, 100), + (16, 100), + (17, 100), + (18, 100), + (99, 1), ]) .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) @@ -945,20 +923,16 @@ fn multiple_delegations() { let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; assert_eq!(events(), expected); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 1, 10), - Error::::AlreadyDelegatedCollator, - ); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 2, 2), + StakePallet::join_delegators(Origin::signed(13), 2, 2), Error::::DelegationBelowMin, ); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 2, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 4, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 3, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(13), 2, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(14), 4, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(15), 3, 10)); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 5, 10), - Error::::MaxCollatorsPerDelegatorExceeded, + StakePallet::join_delegators(Origin::signed(6), 5, 10), + Error::::AlreadyDelegating, ); roll_to( @@ -967,9 +941,9 @@ fn multiple_delegations() { ); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); let mut new = vec![ - Event::Delegation(6, 10, 2, 50), - Event::Delegation(6, 10, 4, 30), - Event::Delegation(6, 10, 3, 30), + Event::Delegation(13, 10, 2, 50), + Event::Delegation(14, 10, 4, 30), + Event::Delegation(15, 10, 3, 30), Event::NewRound(10, 2), Event::NewRound(15, 3), ]; @@ -977,21 +951,21 @@ fn multiple_delegations() { assert_eq!(events(), expected); roll_to(21, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(7), 2, 80)); + assert_ok!(StakePallet::join_delegators(Origin::signed(16), 2, 80)); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(7), 3, 11), + StakePallet::join_delegators(Origin::signed(99), 3, 11), BalancesError::::InsufficientBalance ); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(10), 2, 10), + StakePallet::join_delegators(Origin::signed(17), 2, 10), Error::::TooManyDelegators ); - // kick 6 - assert!(StakePallet::unstaking(6).is_empty()); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(10), 2, 11)); - assert!(StakePallet::delegator_state(6).is_some()); - assert_eq!(StakePallet::unstaking(6).get(&23), Some(&10u128)); - // kick 9 + // kick 13 by staking 1 more (11 > 10) + assert!(StakePallet::unstaking(13).is_empty()); + assert_ok!(StakePallet::join_delegators(Origin::signed(17), 2, 11)); + assert!(StakePallet::delegator_state(13).is_none()); + assert_eq!(StakePallet::unstaking(13).get(&23), Some(&10u128)); + // kick 9 by staking 1 more (11 > 10) assert!(StakePallet::unstaking(9).is_empty()); assert!(StakePallet::rewards(9).is_zero()); assert_ok!(StakePallet::join_delegators(Origin::signed(11), 2, 11)); @@ -1009,9 +983,9 @@ fn multiple_delegations() { assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 4, 3, 5]); let mut new2 = vec![ Event::NewRound(20, 4), - Event::Delegation(7, 80, 2, 130), - Event::DelegationReplaced(10, 11, 6, 10, 2, 131), - Event::Delegation(10, 11, 2, 131), + Event::Delegation(16, 80, 2, 130), + Event::DelegationReplaced(17, 11, 13, 10, 2, 131), + Event::Delegation(17, 11, 2, 131), Event::DelegationReplaced(11, 11, 9, 10, 2, 132), Event::Delegation(11, 11, 2, 132), Event::NewRound(25, 5), @@ -1035,53 +1009,53 @@ fn multiple_delegations() { assert_eq!(events(), expected); // test join_delegator errors - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(8), 1, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(18), 1, 10)); assert_noop!( StakePallet::join_delegators(Origin::signed(12), 1, 10), Error::::TooManyDelegators ); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(12), 1, 10), - Error::::NotYetDelegating - ); assert_ok!(StakePallet::join_delegators(Origin::signed(12), 1, 11)); // verify that delegations are removed after collator leaves, not before - assert_eq!(StakePallet::delegator_state(7).unwrap().total, 90); - assert_eq!(StakePallet::delegator_state(7).unwrap().delegations.len(), 2usize); - assert_eq!(StakePallet::delegator_state(11).unwrap().total, 11); - assert_eq!(StakePallet::delegator_state(11).unwrap().delegations.len(), 1usize); - // 6 already has 10 in - assert_eq!(Balances::usable_balance(&7), 10); - assert_eq!(Balances::usable_balance(&11), 89); - assert_eq!(Balances::free_balance(&7), 100); - assert_eq!(Balances::free_balance(&11), 100); + assert!(StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 8, amount: 10 })); + assert!(StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 17, amount: 11 })); + assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); + assert_eq!(StakePallet::delegator_state(17).unwrap().amount, 11); + assert_eq!(Balances::usable_balance(&8), 90); + assert_eq!(Balances::usable_balance(&17), 89); + assert_eq!(Balances::free_balance(&8), 100); + assert_eq!(Balances::free_balance(&17), 100); roll_to(35, vec![Some(1), Some(2), Some(3), Some(4)]); assert_ok!(StakePallet::execute_leave_candidates(Origin::signed(2), 2)); - let mut unbonding_7: BoundedBTreeMap, ::MaxUnstakeRequests> = + let mut unbonding_8: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); - assert_ok!(unbonding_7.try_insert(35u64 + ::StakeDuration::get() as u64, 80)); - assert_eq!(StakePallet::unstaking(7), unbonding_7); - let mut unbonding_11: BoundedBTreeMap, ::MaxUnstakeRequests> = + assert_ok!(unbonding_8.try_insert(35u64 + ::StakeDuration::get() as u64, 10)); + assert_eq!(StakePallet::unstaking(8), unbonding_8); + let mut unbonding_17: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); - assert_ok!(unbonding_11.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); - assert_eq!(StakePallet::unstaking(11), unbonding_11); + assert_ok!(unbonding_17.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); + assert_eq!(StakePallet::unstaking(17), unbonding_17); roll_to(37, vec![Some(1), Some(2)]); - assert_eq!(StakePallet::delegator_state(7).unwrap().total, 10); - assert!(StakePallet::delegator_state(11).is_none()); - assert_eq!(StakePallet::delegator_state(7).unwrap().delegations.len(), 1usize); - assert_ok!(StakePallet::unlock_unstaked(Origin::signed(7), 7)); - assert_ok!(StakePallet::unlock_unstaked(Origin::signed(11), 11)); + assert!(StakePallet::delegator_state(8).is_none()); + assert!(StakePallet::delegator_state(17).is_none()); + assert_ok!(StakePallet::unlock_unstaked(Origin::signed(8), 8)); + assert_ok!(StakePallet::unlock_unstaked(Origin::signed(17), 17)); assert_noop!( StakePallet::unlock_unstaked(Origin::signed(12), 12), Error::::UnstakingIsEmpty ); - assert_eq!(Balances::usable_balance(&11), 100); - assert_eq!(Balances::usable_balance(&7), 90); - assert_eq!(Balances::free_balance(&11), 100); - assert_eq!(Balances::free_balance(&7), 100); + assert_eq!(Balances::usable_balance(&17), 100); + assert_eq!(Balances::usable_balance(&8), 100); + assert_eq!(Balances::free_balance(&17), 100); + assert_eq!(Balances::free_balance(&8), 100); }); } @@ -1172,29 +1146,19 @@ fn should_update_total_stake() { ); old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(11), 2, 150)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators + 150, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::delegator_state(11).unwrap().total, 350); + assert_eq!(StakePallet::delegator_state(11).unwrap().amount, 200); assert_ok!(StakePallet::leave_delegators(Origin::signed(11))); assert_eq!( StakePallet::total_collator_stake(), TotalStake { - delegators: old_stake.delegators - 350, + delegators: old_stake.delegators - 200, ..old_stake } ); let old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::delegator_state(8).unwrap().total, 10); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(8), 2)); + assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); + assert_ok!(StakePallet::leave_delegators(Origin::signed(8))); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -1261,10 +1225,6 @@ fn collators_bond() { StakePallet::candidate_stake_less(Origin::signed(6), 50), Error::::CandidateNotFound ); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 50, 10), - Error::::CandidateNotFound - ); assert_ok!(StakePallet::candidate_stake_more(Origin::signed(1), 50)); assert_noop!( StakePallet::candidate_stake_more(Origin::signed(1), 40), @@ -1376,10 +1336,6 @@ fn delegators_bond() { StakePallet::delegator_stake_less(Origin::signed(6), 1, 8), Error::::DelegationBelowMin ); - assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(6), 1, 6), - Error::::NomStakeBelowMin - ); assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 1, 10)); assert_noop!( StakePallet::delegator_stake_less(Origin::signed(6), 2, 5), @@ -1391,7 +1347,7 @@ fn delegators_bond() { ); assert_noop!( StakePallet::join_delegators(Origin::signed(10), 1, 4), - Error::::NomStakeBelowMin + Error::::DelegationBelowMin ); roll_to(9, vec![]); @@ -1411,55 +1367,27 @@ fn delegators_bond() { } #[test] -fn revoke_delegation_or_leave_delegators() { +fn should_leave_delegators() { ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .set_blocks_per_round(5) + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - roll_to(4, vec![]); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); + assert!(StakePallet::delegator_state(2).is_none()); + assert!(!StakePallet::candidate_pool(1) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 2, amount: 100 })); assert_noop!( - StakePallet::revoke_delegation(Origin::signed(1), 2), + StakePallet::leave_delegators(Origin::signed(2)), Error::::DelegatorNotFound ); - assert_noop!( - StakePallet::revoke_delegation(Origin::signed(6), 2), - Error::::DelegationNotFound - ); assert_noop!( StakePallet::leave_delegators(Origin::signed(1)), Error::::DelegatorNotFound ); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 2, 3)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 3, 3)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(6), 1)); - // cannot revoke delegation because would leave remaining total below - // MinDelegatorStake - assert_noop!( - StakePallet::revoke_delegation(Origin::signed(6), 2), - Error::::NomStakeBelowMin - ); - assert_noop!( - StakePallet::revoke_delegation(Origin::signed(6), 3), - Error::::NomStakeBelowMin - ); - // can revoke both remaining by calling leave delegators - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - // this leads to 8 leaving set of delegators - assert_ok!(StakePallet::revoke_delegation(Origin::signed(8), 2)); }); } @@ -1670,7 +1598,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); assert_eq!(Balances::usable_balance(&5), user_5 + d_rewards / 4); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(5), 2)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(5))); // 2 is block author for 5th block roll_to_claim_rewards(6, authors); @@ -1693,7 +1621,7 @@ fn delegator_should_not_receive_rewards_after_revoking() { .with_inflation(10, 15, 40, 15, 5) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); assert_eq!(Balances::usable_balance(&1), Balance::zero()); assert_eq!(Balances::usable_balance(&2), Balance::zero()); @@ -1714,7 +1642,7 @@ fn delegator_should_not_receive_rewards_after_revoking() { .with_inflation(10, 15, 40, 15, 5) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(3), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); assert_eq!(Balances::usable_balance(&1), Balance::zero()); assert_eq!(Balances::usable_balance(&2), Balance::zero()); @@ -2267,7 +2195,7 @@ fn unlock_unstaked() { .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 100)); @@ -2286,7 +2214,7 @@ fn unlock_unstaked() { // join delegators and revoke again --> consume unstaking at block 3 roll_to(2, vec![]); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); unstaking.remove(&3); assert_ok!(unstaking.try_insert(4, 100)); assert_eq!(StakePallet::unstaking(2), unstaking); @@ -2325,7 +2253,7 @@ fn unlock_unstaked() { .with_delegators(vec![(2, 1, 10)]) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 10)); @@ -2344,7 +2272,7 @@ fn unlock_unstaked() { // join delegators and revoke again roll_to(2, vec![]); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); unstaking.remove(&3); assert_ok!(unstaking.try_insert(4, 100)); lock.amount = 100; @@ -2385,7 +2313,7 @@ fn unlock_unstaked() { .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 100)); @@ -2404,7 +2332,7 @@ fn unlock_unstaked() { // join delegators and revoke again roll_to(2, vec![]); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); assert_ok!(unstaking.try_insert(3, 90)); assert_ok!(unstaking.try_insert(4, 10)); assert_eq!(StakePallet::unstaking(2), unstaking); @@ -2979,60 +2907,49 @@ fn decrease_max_candidate_stake() { #[test] fn exceed_delegations_per_round() { ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)]) - .with_delegators(vec![(6, 1, 10)]) + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 2, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 3, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 4, 10)); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 5, 10), - Error::::MaxCollatorsPerDelegatorExceeded - ); - - // revoke delegation to allow one more collator for this delegator - assert_ok!(StakePallet::revoke_delegation(Origin::signed(6), 4)); + // leave and re-join to set counter to 2 (= MaxDelegationsPerRound) + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); // reached max delegations in this round assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 5, 10), - Error::::DelegationsPerRoundExceeded - ); - - // revoke all delegations in the same round - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_noop!( - StakePallet::join_delegators(Origin::signed(6), 1, 10), + StakePallet::join_delegators(Origin::signed(2), 1, 100), Error::::DelegationsPerRoundExceeded ); // roll to next round to clear DelegationCounter roll_to(5, vec![]); assert_eq!( - StakePallet::last_delegation(6), - DelegationCounter { round: 0, counter: 4 } + StakePallet::last_delegation(2), + DelegationCounter { round: 0, counter: 2 } ); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + // counter should be reset because the round changed assert_eq!( - StakePallet::last_delegation(6), + StakePallet::last_delegation(2), DelegationCounter { round: 1, counter: 1 } ); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_eq!( - StakePallet::last_delegation(6), - DelegationCounter { round: 1, counter: 4 } + // leave and re-join to set counter to 2 (= MaxDelegationsPerRound)) + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + assert_noop!( + StakePallet::join_delegators(Origin::signed(2), 1, 100), + Error::::AlreadyDelegating ); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); assert_noop!( - StakePallet::join_delegators(Origin::signed(6), 1, 10), + StakePallet::join_delegators(Origin::signed(2), 1, 100), Error::::DelegationsPerRoundExceeded ); + assert_eq!( + StakePallet::last_delegation(2), + DelegationCounter { round: 1, counter: 2 } + ); }); } @@ -3045,7 +2962,7 @@ fn force_remove_candidate() { .build() .execute_with(|| { assert_eq!(CandidatePool::::count(), 3); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(4), 2, 50)); + assert_ok!(StakePallet::join_delegators(Origin::signed(6), 2, 50)); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); assert!(StakePallet::unstaking(1).get(&3).is_none()); assert!(StakePallet::unstaking(2).get(&3).is_none()); @@ -3076,14 +2993,8 @@ fn force_remove_candidate() { assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); assert_eq!(CandidatePool::::count(), 2); assert!(StakePallet::candidate_pool(1).is_none()); + assert!(StakePallet::delegator_state(4).is_none()); assert!(StakePallet::delegator_state(5).is_none()); - assert_eq!( - StakePallet::delegator_state(4), - Some(Delegator { - delegations: OrderedSet::from(vec![StakeOf:: { owner: 2, amount: 50 }].try_into().unwrap()), - total: 50 - }) - ); assert_eq!(StakePallet::unstaking(1).get(&3), Some(&100)); assert_eq!(StakePallet::unstaking(4).get(&3), Some(&50)); assert_eq!(StakePallet::unstaking(5).get(&3), Some(&50)); @@ -3275,7 +3186,7 @@ fn prioritize_collators() { .unwrap() ) ); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(7), 5)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(7))); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 5]); assert_eq!( StakePallet::top_candidates(), @@ -3305,9 +3216,11 @@ fn prioritize_delegators() { (5, 1000), (6, 1000), (7, 1000), + (8, 1000), + (9, 1000), ]) .with_collators(vec![(1, 100), (2, 100), (3, 100)]) - .with_delegators(vec![(5, 1, 100), (4, 2, 100), (7, 2, 100), (6, 2, 100)]) + .with_delegators(vec![(4, 2, 100), (7, 2, 100), (6, 2, 100)]) .build() .execute_with(|| { assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1]); @@ -3323,7 +3236,7 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(5), 2, 110)); + assert_ok!(StakePallet::join_delegators(Origin::signed(5), 2, 110)); assert_eq!( StakePallet::candidate_pool(2).unwrap().delegators, OrderedSet::from_sorted_set( @@ -3337,17 +3250,6 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_eq!( - StakePallet::delegator_state(5).unwrap().delegations, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 2, amount: 110 }, - StakeOf:: { owner: 1, amount: 100 } - ] - .try_into() - .unwrap() - ) - ); // delegate_less assert_ok!(StakePallet::delegator_stake_less(Origin::signed(5), 2, 10)); @@ -3364,17 +3266,6 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_eq!( - StakePallet::delegator_state(5).unwrap().delegations, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 2, amount: 100 }, - StakeOf:: { owner: 1, amount: 100 } - ] - .try_into() - .unwrap() - ) - ); // delegate_more assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 2, 10)); @@ -4162,66 +4053,67 @@ fn rewards_delegator_replaced() { }); } -#[test] -fn rewards_delegator_revokes_single_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, 2 * DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // stake more to trigger reward incrementing just for 3 - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, DECIMALS)); - // 1 should still have counter 1 but no rewards - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::rewards(1).is_zero()); - // 2 should still have neither rewards nor counter - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::rewards(2).is_zero()); - // 3 should have rewards and the same counter as 1 - assert_eq!(StakePallet::reward_count(3), 1); - assert!(!StakePallet::rewards(3).is_zero()); - }); -} - -#[test] -fn rewards_delegator_leaves() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) - .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) - .with_delegators(vec![(3, 1, DECIMALS)]) - .build() - .execute_with(|| { - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(3), 2, DECIMALS)); - // note both collators once to set their counter to 2 - StakePallet::note_author(1); - StakePallet::note_author(2); - assert_eq!(StakePallet::reward_count(1), 2); - assert_eq!(StakePallet::reward_count(2), 2); - assert!(StakePallet::reward_count(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // only 3 should have non-zero rewards and counter reset - assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); - (1..=2).for_each(|id| { - assert_eq!(StakePallet::reward_count(id), 2, "acc_id {:?}", id); - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - assert!(!StakePallet::rewards(3).is_zero()); - assert_eq!(StakePallet::reward_count(3), 4); - }); -} +// FIXME: Re-enable +// #[test] +// fn rewards_delegator_revokes_single_delegation() { +// ExtBuilder::default() +// .with_balances(vec![(1, DECIMALS), (2, 2 * DECIMALS)]) +// .with_collators(vec![(1, DECIMALS)]) +// .with_delegators(vec![(2, 1, DECIMALS)]) +// .build() +// .execute_with(|| { +// // note once to set counter to 1 +// StakePallet::note_author(1); +// assert_eq!(StakePallet::reward_count(1), 1); +// assert!(StakePallet::reward_count(2).is_zero()); +// assert!(StakePallet::reward_count(3).is_zero()); +// (1..=3).for_each(|id| { +// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); +// }); + +// // stake more to trigger reward incrementing just for 3 +// assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, +// DECIMALS)); // 1 should still have counter 1 but no rewards +// assert_eq!(StakePallet::reward_count(1), 1); +// assert!(StakePallet::rewards(1).is_zero()); +// // 2 should still have neither rewards nor counter +// assert!(StakePallet::reward_count(2).is_zero()); +// assert!(StakePallet::rewards(2).is_zero()); +// // 3 should have rewards and the same counter as 1 +// assert_eq!(StakePallet::reward_count(3), 1); +// assert!(!StakePallet::rewards(3).is_zero()); +// }); +// } + +// #[test] +// fn rewards_delegator_leaves() { +// ExtBuilder::default() +// .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) +// .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) +// .with_delegators(vec![(3, 1, DECIMALS)]) +// .build() +// .execute_with(|| { +// assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(3), 2, +// DECIMALS)); // note both collators once to set their counter to 2 +// StakePallet::note_author(1); +// StakePallet::note_author(2); +// assert_eq!(StakePallet::reward_count(1), 2); +// assert_eq!(StakePallet::reward_count(2), 2); +// assert!(StakePallet::reward_count(3).is_zero()); +// (1..=3).for_each(|id| { +// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); +// }); + +// // only 3 should have non-zero rewards and counter reset +// assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); +// (1..=2).for_each(|id| { +// assert_eq!(StakePallet::reward_count(id), 2, "acc_id {:?}", id); +// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); +// }); +// assert!(!StakePallet::rewards(3).is_zero()); +// assert_eq!(StakePallet::reward_count(3), 4); +// }); +// } // TODO: // rewards_delegator_revokes_single_delegation diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index 64bb6b7392..6c8ccaa117 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -26,10 +26,8 @@ use sp_runtime::{ use sp_staking::SessionIndex; use sp_std::{ cmp::Ordering, - convert::TryInto, fmt::Debug, ops::{Add, Sub}, - vec, }; use crate::{set::OrderedSet, Config}; @@ -211,100 +209,60 @@ where } } -#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(MaxCollatorsPerDelegator))] -#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] -pub struct Delegator> { - pub delegations: OrderedSet, MaxCollatorsPerDelegator>, - pub total: Balance, -} - -impl Delegator +pub type Delegator = Stake, Balance>; +impl Delegator where AccountId: Eq + Ord + Clone + Debug, - Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero, - MaxCollatorsPerDelegator: Get + Debug + PartialEq, + Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default, { - pub fn try_new(collator: AccountId, amount: Balance) -> Result { - Ok(Delegator { - delegations: OrderedSet::from( - vec![Stake { - owner: collator, - amount, - }] - .try_into()?, - ), - total: amount, - }) - } - /// Adds a new delegation. /// - /// If already delegating to the same account, this call returns false and - /// doesn't insert the new delegation. - pub fn add_delegation(&mut self, stake: Stake) -> Result { - let amt = stake.amount; - if self.delegations.try_insert(stake).map_err(|_| ())? { - self.total = self.total.saturating_add(amt); - Ok(true) + /// If already delegating to someone, this call will fail. + pub fn add_delegation(&mut self, stake: Stake) -> Result<(), ()> { + if self.owner.is_none() && self.amount.is_zero() { + self.owner = Some(stake.owner); + self.amount = stake.amount; + Ok(()) } else { - Ok(false) + Err(()) } } - /// Returns Some(remaining stake for delegator) if the delegation for the - /// collator exists. Returns `None` otherwise. - pub fn rm_delegation(&mut self, collator: &AccountId) -> Option { - let amt = self.delegations.remove(&Stake:: { - owner: collator.clone(), - // amount is irrelevant for removal - amount: Balance::zero(), - }); - - if let Some(Stake:: { amount: balance, .. }) = amt { - self.total = self.total.saturating_sub(balance); - Some(self.total) + /// Returns Ok if the delegation for the + /// collator exists and `Err` otherwise. + pub fn rm_delegation(&mut self, collator: AccountId) -> Result<(), ()> { + if self.owner == Some(collator) { + self.amount = Balance::zero(); + self.owner = None; + Ok(()) } else { - None + Err(()) } } - /// Returns Some(delegated_amount) if successfull, None if delegation was + /// Returns Ok(delegated_amount) if successfull, `Err` if delegation was /// not found. - pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Option { - if let Ok(i) = self.delegations.linear_search(&Stake:: { - owner: collator, - amount: Balance::zero(), - }) { - self.delegations - .mutate(|vec| vec[i].amount = vec[i].amount.saturating_add(more)); - self.total = self.total.saturating_add(more); - self.delegations.sort_greatest_to_lowest(); - Some(self.delegations[i].amount) + pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Result { + if self.owner == Some(collator) { + self.amount = self.amount.saturating_add(more); + Ok(self.amount) } else { - None + Err(()) } } - /// Returns Some(Some(delegated_amount)) if successful, None if delegation - /// was not found and Some(None) if delegated stake would underflow. - pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Option> { - if let Ok(i) = self.delegations.linear_search(&Stake:: { - owner: collator, - amount: Balance::zero(), - }) { - if self.delegations[i].amount > less { - self.delegations - .mutate(|vec| vec[i].amount = vec[i].amount.saturating_sub(less)); - self.total = self.total.saturating_sub(less); - self.delegations.sort_greatest_to_lowest(); - Some(Some(self.delegations[i].amount)) + /// Returns Ok(Some(delegated_amount)) if successful, `Err` if delegation + /// was not found and Ok(None) if delegated stake would underflow. + pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Result, ()> { + if self.owner == Some(collator) { + if self.amount > less { + self.amount = self.amount.saturating_sub(less); + Ok(Some(self.amount)) } else { - // underflow error; should rm entire delegation - Some(None) + Ok(None) } } else { - None + Err(()) } } } @@ -372,13 +330,6 @@ pub struct DelegationCounter { pub counter: u32, } -/// Internal type which is only used when a delegator is replaced by another -/// one to delay the storage entry removal until failure cannot happen anymore. -pub(crate) struct ReplacedDelegator { - pub who: AccountIdOf, - pub state: Option, BalanceOf, T::MaxCollatorsPerDelegator>>, -} - pub type AccountIdOf = ::AccountId; pub type BalanceOf = <::Currency as Currency>>::Balance; pub type CandidateOf = Candidate, BalanceOf, S>; diff --git a/runtimes/common/src/constants.rs b/runtimes/common/src/constants.rs index 06b4b38415..e0033a45ff 100644 --- a/runtimes/common/src/constants.rs +++ b/runtimes/common/src/constants.rs @@ -203,9 +203,6 @@ pub mod staking { /// Maximum 25 delegators per collator at launch, might be increased later #[derive(Debug, PartialEq)] pub const MaxDelegatorsPerCollator: u32 = MAX_DELEGATORS_PER_COLLATOR; - /// Maximum 1 collator per delegator at launch, will be increased later - #[derive(Debug, PartialEq)] - pub const MaxCollatorsPerDelegator: u32 = 1; /// Minimum stake required to be reserved to be a collator is 10_000 pub const MinCollatorStake: Balance = 10_000 * KILT; /// Minimum stake required to be reserved to be a delegator is 1000 diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index c93fd8e367..44ca67e127 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -624,11 +624,9 @@ impl parachain_staking::Config for Runtime { type MinRequiredCollators = constants::staking::MinRequiredCollators; type MaxDelegationsPerRound = constants::staking::MaxDelegationsPerRound; type MaxDelegatorsPerCollator = constants::staking::MaxDelegatorsPerCollator; - type MaxCollatorsPerDelegator = constants::staking::MaxCollatorsPerDelegator; type MinCollatorStake = constants::staking::MinCollatorStake; type MinCollatorCandidateStake = constants::staking::MinCollatorStake; type MaxTopCandidates = constants::staking::MaxCollatorCandidates; - type MinDelegation = constants::staking::MinDelegatorStake; type MinDelegatorStake = constants::staking::MinDelegatorStake; type MaxUnstakeRequests = constants::staking::MaxUnstakeRequests; type NetworkRewardRate = constants::staking::NetworkRewardRate; diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index a62ebaf100..5e81a21974 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -619,11 +619,9 @@ impl parachain_staking::Config for Runtime { type MinRequiredCollators = constants::staking::MinRequiredCollators; type MaxDelegationsPerRound = constants::staking::MaxDelegationsPerRound; type MaxDelegatorsPerCollator = constants::staking::MaxDelegatorsPerCollator; - type MaxCollatorsPerDelegator = constants::staking::MaxCollatorsPerDelegator; type MinCollatorStake = constants::staking::MinCollatorStake; type MinCollatorCandidateStake = constants::staking::MinCollatorStake; type MaxTopCandidates = constants::staking::MaxCollatorCandidates; - type MinDelegation = constants::staking::MinDelegatorStake; type MinDelegatorStake = constants::staking::MinDelegatorStake; type MaxUnstakeRequests = constants::staking::MaxUnstakeRequests; type NetworkRewardRate = constants::staking::NetworkRewardRate; From d8bb95564ec38a0af7acca2968f152009e19d086 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 1 Aug 2022 18:16:36 +0200 Subject: [PATCH 07/34] docs: remove deprecated weight --- pallets/parachain-staking/src/lib.rs | 106 --------------------------- 1 file changed, 106 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 93d1c243e2..55d8626635 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -740,12 +740,6 @@ pub mod pallet { /// ShouldEndSession<_>>::should_end_session. /// /// The dispatch origin must be Root. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account] - /// - Writes: ForceNewRound - /// # #[pallet::weight(::WeightInfo::set_inflation())] pub fn force_new_round(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; @@ -769,12 +763,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `RoundInflationSet`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account] - /// - Writes: InflationConfig - /// # #[pallet::weight(::WeightInfo::set_inflation())] pub fn set_inflation( origin: OriginFor, @@ -831,20 +819,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `MaxSelectedCandidatesSet`. - /// - /// - /// # - /// - The transaction's complexity is mainly dependent on updating the - /// `SelectedCandidates` storage in `select_top_candidates` which in - /// return depends on the number of `MaxSelectedCandidates` (N). - /// - For each N, we read `CandidatePool` from the storage. - /// --------- - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators of a - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: MaxSelectedCandidates, TopCandidates, N * CandidatePool - /// - Writes: MaxSelectedCandidates - /// # #[pallet::weight(::WeightInfo::set_max_selected_candidates( *new, T::MaxDelegatorsPerCollator::get() @@ -913,12 +887,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `BlocksPerRoundSet`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account], Round - /// - Writes: Round - /// # #[pallet::weight(::WeightInfo::set_blocks_per_round())] pub fn set_blocks_per_round(origin: OriginFor, new: T::BlockNumber) -> DispatchResult { ensure_root(origin)?; @@ -948,12 +916,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `MaxCandidateStakeChanged`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account], MaxCollatorCandidateStake - /// - Writes: Round - /// # #[pallet::weight(::WeightInfo::set_max_candidate_stake())] pub fn set_max_candidate_stake(origin: OriginFor, new: BalanceOf) -> DispatchResult { ensure_root(origin)?; @@ -1047,8 +1009,6 @@ pub mod pallet { /// candidates nor of the delegators set. /// /// Emits `JoinedCollatorCandidates`. - /// - /// # #[pallet::weight(::WeightInfo::join_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1641,14 +1601,6 @@ pub mod pallet { /// allowed range as set in the pallet's configuration. /// /// Emits `DelegatorStakedLess`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// TopCandidates, CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::delegator_stake_less( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1882,11 +1834,6 @@ pub mod pallet { impl Pallet { /// Check whether an account is currently delegating. - /// - /// # - /// Weight: O(1) - /// - Reads: DelegatorState - /// # pub fn is_delegator(acc: &T::AccountId) -> bool { DelegatorState::::get(acc).is_some() } @@ -1895,11 +1842,6 @@ pub mod pallet { /// whether their state is CollatorStatus::Active. /// /// Returns Some(is_active) if the account is a candidate, else None. - /// - /// # - /// Weight: O(1) - /// - Reads: CandidatePool - /// # pub fn is_active_candidate(acc: &T::AccountId) -> Option { if let Some(state) = CandidatePool::::get(acc) { Some(state.status == CandidateStatus::Active) @@ -1913,12 +1855,6 @@ pub mod pallet { /// /// NOTE: It is assumed that the calling context checks whether the /// collator candidate is currently active before calling this function. - /// - /// # - /// Weight: O(1) - /// - Reads: TopCandidates, CandidatePool, TotalCollatorStake - /// - Writes: TopCandidates, TotalCollatorStake - /// # fn update_top_candidates( candidate: T::AccountId, old_self: BalanceOf, @@ -2136,11 +2072,6 @@ pub mod pallet { /// In case a collator from last round was replaced by a candidate with /// the same total stake during sorting, we revert this swap to /// prioritize collators over candidates. - /// - /// # - /// Weight: O(1) - /// - Reads: TopCandidates, MaxSelectedCandidates - /// # pub fn selected_candidates() -> BoundedVec { let candidates = TopCandidates::::get(); @@ -2174,12 +2105,6 @@ pub mod pallet { /// /// Emits `DelegationReplaced` if the stake exceeds one of the current /// delegations. - /// - /// # - /// Weight: O(D) where D is the number of delegators for this collator - /// bounded by `MaxDelegatorsPerCollator`. - /// - Reads/Writes: 0 - /// # #[allow(clippy::type_complexity)] fn do_update_delegator( stake: Stake>, @@ -2229,13 +2154,6 @@ pub mod pallet { /// /// Consumes unstaked balance which can be unlocked in the future up to /// amount and updates `Unstaking` storage accordingly. - /// - /// # - /// Weight: O(U) where U is the number of locked unstaking requests - /// bounded by `MaxUnstakeRequests`. - /// - Reads: Unstaking, Locks - /// - Writes: Unstaking, Locks - /// # fn increase_lock(who: &T::AccountId, amount: BalanceOf, more: BalanceOf) -> Result { ensure!( pallet_balances::Pallet::::free_balance(who) >= amount.into(), @@ -2288,12 +2206,6 @@ pub mod pallet { /// Throws if the amount is zero (unlikely) or if active unlocking /// requests exceed limit. The latter defends against stake reduction /// spamming. - /// - /// # - /// Weight: O(1) - /// - Reads: BlockNumber, Unstaking - /// - Writes: Unstaking - /// # fn prep_unstake(who: &T::AccountId, amount: BalanceOf, is_removal: bool) -> DispatchResult { // should never occur but let's be safe ensure!(!amount.is_zero(), Error::::StakeNotFound); @@ -2327,16 +2239,6 @@ pub mod pallet { /// Clear the CandidatePool of the candidate and remove all delegations /// to the candidate. Moreover, prepare unstaking for the candidate and /// their former delegations. - /// - /// # - /// Weight: O(D + U) where D is the number of delegators of the collator - /// candidate bounded by `MaxDelegatorsPerCollator` and U is the - /// number of locked unstaking requests bounded by `MaxUnstakeRequests`. - /// - Reads: BlockNumber, D * DelegatorState, D * Unstaking - /// - Writes: D * DelegatorState, (D + 1) * Unstaking - /// - Kills: CandidatePool, DelegatorState for all delegators which only - /// delegated to the candidate - /// # fn remove_candidate( collator: &T::AccountId, state: &CandidateOf, @@ -2382,14 +2284,6 @@ pub mod pallet { /// Withdraw all staked currency which was unstaked at least /// `StakeDuration` blocks ago. - /// - /// # - /// Weight: O(U) where U is the number of locked unstaking - /// requests bounded by `MaxUnstakeRequests`. - /// - Reads: Unstaking, Locks - /// - Writes: Unstaking, Locks - /// - Kills: Unstaking & Locks if no balance is locked anymore - /// # fn do_unlock(who: &T::AccountId) -> Result { let now = >::block_number(); let mut unstaking = >::get(who); From 24dc4bfbf4788cb3faf17d568c07eca5cc63530e Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 2 Aug 2022 13:46:12 +0200 Subject: [PATCH 08/34] Apply suggestions from code review Co-authored-by: Antonio --- pallets/parachain-staking/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 55d8626635..07ceef79b4 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1477,7 +1477,7 @@ pub mod pallet { .into()) } - /// Leave the set of delegators and, by implication, revoke the ingoing + /// Leave the set of delegators and, by implication, revoke the ongoing /// delegation. /// /// All staked funds are not unlocked immediately, but they are added to @@ -1489,7 +1489,7 @@ pub mod pallet { /// their chances to be included in the set of candidates in the next /// rounds. /// - /// Automatically increments the accumulated rewards of the origin the + /// Automatically increments the accumulated rewards of the origin of the /// current delegation. /// /// Emits `DelegatorLeft`. From 7789cdab043f7b191c467f02edd6fb9c9e1cca40 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 2 Aug 2022 17:07:29 +0200 Subject: [PATCH 09/34] tests: 100% --- pallets/parachain-staking/src/lib.rs | 29 +-- pallets/parachain-staking/src/tests.rs | 285 +++++++++++++++++++------ 2 files changed, 221 insertions(+), 93 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 07ceef79b4..19744a44c1 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1489,8 +1489,8 @@ pub mod pallet { /// their chances to be included in the set of candidates in the next /// rounds. /// - /// Automatically increments the accumulated rewards of the origin of the - /// current delegation. + /// Automatically increments the accumulated rewards of the origin of + /// the current delegation. /// /// Emits `DelegatorLeft`. #[pallet::weight(::WeightInfo::leave_delegators( @@ -1707,7 +1707,7 @@ pub mod pallet { /// for anyone. /// /// Emits `Rewarded`. - // TODO: Benchmark, unit tests + // TODO: Benchmark #[pallet::weight(0)] pub fn claim_rewards_for(origin: OriginFor, target: ::Source) -> DispatchResult { ensure_signed(origin)?; @@ -1732,7 +1732,7 @@ pub mod pallet { /// network. /// /// The dispatch origin must be a collator. - // TODO: Benchmark, unit tests + // TODO: Benchmark #[pallet::weight(0)] pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; @@ -1753,7 +1753,7 @@ pub mod pallet { /// delegations. /// /// The dispatch origin must be a delegator. - // TODO: Benchmark, unit tests + // TODO: Benchmark #[pallet::weight(0)] pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { let delegator = ensure_signed(origin)?; @@ -1761,11 +1761,8 @@ pub mod pallet { // should never throw let collator = delegation.owner.ok_or(Error::::DelegationNotFound)?; - // early exit - let reward_count = RewardCount::::take(&delegator); - ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); - Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); + ensure!(!Rewards::::get(&delegator).is_zero(), Error::::RewardsNotFound); Ok(()) } @@ -2457,8 +2454,6 @@ pub mod pallet { Rewards::::mutate(acc, |reward| { *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, diff.into())); }); - // TODO: Investigate whether we want to set this to some input variable to - // improve `add_collator_reward` RewardCount::::insert(acc, col_reward_count); // 4 reads from reward calc @@ -2467,18 +2462,6 @@ pub mod pallet { T::DbWeight::get().reads(2) } } - - // [Post-launch TODO] Think about Collator stake or total stake? - // /// Attempts to add a collator candidate to the set of collator - // /// candidates which already reached its maximum size. On success, - // /// another collator with the minimum total stake is removed from the - // /// set. On failure, an error is returned. removing an already existing - // fn check_collator_candidate_inclusion( - // stake: Stake>, - // mut candidates: OrderedSet>, - // T::MaxTopCandidates>, ) -> Result<(), DispatchError> { - // todo!() - // } } impl pallet_authorship::EventHandler for Pallet diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 9a713081e7..18472943cc 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -3887,6 +3887,7 @@ fn rewards_candidate_stake_less() { }); }); } + #[test] fn rewards_candidate_leave_network() { ExtBuilder::default() @@ -3908,7 +3909,7 @@ fn rewards_candidate_leave_network() { roll_to( 10, vec![ - // we're in block 1 already, so cannot note_author in roll_to + // we're already in block 1, so cant note_author for block 1 None, Some(1), Some(2), @@ -3940,6 +3941,37 @@ fn rewards_candidate_leave_network() { }); } +#[test] +fn rewards_force_remove_candidate() { + ExtBuilder::default() + .with_balances(vec![ + (1, DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, DECIMALS), (4, DECIMALS), (5, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // init does not increment rewards + StakePallet::note_author(1); + StakePallet::note_author(2); + + // removing triggers reward increment for collator 1 and delegators 4, 5 + assert_ok!(StakePallet::force_remove_candidate(Origin::root(), 1)); + (1..=3).for_each(|id| { + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + }); + (4..=5).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + #[test] fn reward_count_join_delegators() { ExtBuilder::default() @@ -4053,72 +4085,185 @@ fn rewards_delegator_replaced() { }); } -// FIXME: Re-enable -// #[test] -// fn rewards_delegator_revokes_single_delegation() { -// ExtBuilder::default() -// .with_balances(vec![(1, DECIMALS), (2, 2 * DECIMALS)]) -// .with_collators(vec![(1, DECIMALS)]) -// .with_delegators(vec![(2, 1, DECIMALS)]) -// .build() -// .execute_with(|| { -// // note once to set counter to 1 -// StakePallet::note_author(1); -// assert_eq!(StakePallet::reward_count(1), 1); -// assert!(StakePallet::reward_count(2).is_zero()); -// assert!(StakePallet::reward_count(3).is_zero()); -// (1..=3).for_each(|id| { -// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); -// }); - -// // stake more to trigger reward incrementing just for 3 -// assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, -// DECIMALS)); // 1 should still have counter 1 but no rewards -// assert_eq!(StakePallet::reward_count(1), 1); -// assert!(StakePallet::rewards(1).is_zero()); -// // 2 should still have neither rewards nor counter -// assert!(StakePallet::reward_count(2).is_zero()); -// assert!(StakePallet::rewards(2).is_zero()); -// // 3 should have rewards and the same counter as 1 -// assert_eq!(StakePallet::reward_count(3), 1); -// assert!(!StakePallet::rewards(3).is_zero()); -// }); -// } - -// #[test] -// fn rewards_delegator_leaves() { -// ExtBuilder::default() -// .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) -// .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) -// .with_delegators(vec![(3, 1, DECIMALS)]) -// .build() -// .execute_with(|| { -// assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(3), 2, -// DECIMALS)); // note both collators once to set their counter to 2 -// StakePallet::note_author(1); -// StakePallet::note_author(2); -// assert_eq!(StakePallet::reward_count(1), 2); -// assert_eq!(StakePallet::reward_count(2), 2); -// assert!(StakePallet::reward_count(3).is_zero()); -// (1..=3).for_each(|id| { -// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); -// }); - -// // only 3 should have non-zero rewards and counter reset -// assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); -// (1..=2).for_each(|id| { -// assert_eq!(StakePallet::reward_count(id), 2, "acc_id {:?}", id); -// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); -// }); -// assert!(!StakePallet::rewards(3).is_zero()); -// assert_eq!(StakePallet::reward_count(3), 4); -// }); -// } - -// TODO: -// rewards_delegator_revokes_single_delegation -// rewards_delegator_revokes_all_delegations -// rewards_delegator_delegates_another_candidate -// rewards_delegator_delegates_another_candidate_replacing -// rewards_set_inflation -// rewards_annual_inflation_adjustment +#[test] +fn rewards_delegator_leaves() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note collator once to set their counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // only 3 should have non-zero rewards and their counter reset + assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::rewards(1).is_zero()); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + assert!(!StakePallet::rewards(3).is_zero()); + assert_eq!(StakePallet::reward_count(3), 1); + }); +} + +#[test] +fn rewards_set_inflation() { + let hundred = Perquintill::from_percent(100); + ExtBuilder::default() + .with_balances(vec![ + (1, DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) + .with_delegators(vec![(3, 1, DECIMALS), (4, 1, DECIMALS), (5, 2, DECIMALS)]) + .build() + .execute_with(|| { + // note collators + StakePallet::note_author(1); + StakePallet::note_author(1); + StakePallet::note_author(2); + + // set inflation to trigger reward setting + assert_ok!(StakePallet::set_inflation( + Origin::root(), + hundred, + hundred, + hundred, + hundred + )); + // rewards should be set and counter rese + (1..=5).for_each(|id| { + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + +#[test] +fn rewards_yearly_inflation_adjustment() { + ExtBuilder::default() + .with_balances(vec![ + (1, DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) + .with_delegators(vec![(3, 1, DECIMALS), (4, 1, DECIMALS), (5, 2, DECIMALS)]) + .build() + .execute_with(|| { + // init counter and go to next year + StakePallet::note_author(1); + StakePallet::note_author(2); + System::set_block_number(::BLOCKS_PER_YEAR - 1); + roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); + + // rewards should not be triggered before executing pending adjustment + (1..=5).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // execute to trigger reward increment + assert_ok!(StakePallet::execute_pending_reward_change(Origin::signed(1))); + (1..=5).for_each(|id| { + assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + +#[test] +fn rewards_incrementing_and_claiming() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // claiming or incrementing should not be possible with zero counter + assert_noop!( + StakePallet::increment_collator_rewards(Origin::signed(1)), + Error::::RewardsNotFound + ); + assert_noop!( + StakePallet::increment_delegator_rewards(Origin::signed(2)), + Error::::RewardsNotFound + ); + (1..=3).for_each(|id| { + assert_noop!( + StakePallet::claim_rewards_for(Origin::signed(id), id), + Error::::RewardsNotFound, + ); + }); + + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::reward_count(2).is_zero()); + + // claiming should not be possible before incrementing rewards + (1..=3).for_each(|id| { + assert_noop!( + StakePallet::claim_rewards_for(Origin::signed(id), id), + Error::::RewardsNotFound + ); + }); + + // increment rewards for 2 and match counter to collator + assert_ok!(StakePallet::increment_delegator_rewards(Origin::signed(2))); + assert_eq!(StakePallet::reward_count(2), 1); + let rewards_2 = StakePallet::rewards(2); + assert!(!rewards_2.is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + assert!(StakePallet::rewards(3).is_zero()); + + // should set rewards for delegator 3 as well + assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(1))); + assert!(StakePallet::reward_count(1).is_zero()); + assert!(!StakePallet::rewards(1).is_zero()); + // counter of delegators should be reset to 0 (= cols counter) + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::reward_count(3).is_zero()); + // rewards of 2 should not be changed + assert_eq!(StakePallet::rewards(2), rewards_2); + // 3 should have rewards now (passively) + assert!(!StakePallet::rewards(3).is_zero()); + + // claim for 1 to move rewards into balance + assert_ok!(StakePallet::claim_rewards_for(Origin::signed(3), 1)); + assert!(StakePallet::reward_count(1).is_zero()); + assert!(StakePallet::rewards(1).is_zero()); + // delegator situation should be unchanged + assert!(Balances::free_balance(&1) > DECIMALS); + assert_eq!(Balances::free_balance(&2), DECIMALS); + assert_eq!(Balances::free_balance(&3), DECIMALS); + + // claim for 2 to move rewards into balance + assert_ok!(StakePallet::claim_rewards_for(Origin::signed(1), 2)); + assert!(Balances::free_balance(&2) > DECIMALS); + assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + assert_eq!(Balances::free_balance(&3), DECIMALS); + + // should not be able to claim for incorrect role + assert_noop!( + StakePallet::increment_collator_rewards(Origin::signed(2)), + Error::::CandidateNotFound + ); + assert_noop!( + StakePallet::increment_delegator_rewards(Origin::signed(1)), + Error::::DelegatorNotFound + ); + }); +} From 870b534ea4729a51ef01088b5ac8ec00ec1e1f39 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 3 Aug 2022 18:01:55 +0200 Subject: [PATCH 10/34] fix: benchmarks --- pallets/parachain-staking/src/benchmarking.rs | 95 ++- .../parachain-staking/src/default_weights.rs | 646 +++++++++++------- pallets/parachain-staking/src/lib.rs | 89 ++- .../src/weights/parachain_staking.rs | 319 +++++---- .../src/weights/parachain_staking.rs | 319 +++++---- 5 files changed, 938 insertions(+), 530 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 235189666e..168eef05b5 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -134,19 +134,6 @@ benchmarks! { assert_eq!(>::get().current, 1u32); } - on_initialize_new_year { - let old = >::get(); - assert_eq!(>::get(), T::BlockNumber::zero()); - let block = (T::BLOCKS_PER_YEAR + 1u32.into()).saturated_into::(); - }: { Pallet::::on_initialize(block) } - verify { - let new = >::get(); - assert_eq!(>::get(), T::BlockNumber::one()); - assert_eq!(new.collator.max_rate, old.collator.max_rate); - assert_eq!(new.delegator.max_rate, old.delegator.max_rate); - assert!(new.collator.reward_rate.annual < old.collator.reward_rate.annual); - } - on_initialize_network_rewards { let issuance = T::Currency::total_issuance(); // if we only add by one, we also initialize a new year @@ -185,6 +172,15 @@ benchmarks! { } set_inflation { + let n in 0 .. T::MaxTopCandidates::get(); + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + Rewards::::insert(&c, T::CurrencyBalance::one()); + } + let inflation = InflationInfo::new( T::BLOCKS_PER_YEAR.saturated_into(), Perquintill::from_percent(10), @@ -194,7 +190,10 @@ benchmarks! { ); }: _(RawOrigin::Root, inflation.collator.max_rate, inflation.collator.reward_rate.annual, inflation.delegator.max_rate, inflation.delegator.reward_rate.annual) verify { - assert_eq!(>::get(), inflation); + assert_eq!(InflationConfig::::get(), inflation); + candidates.into_iter().for_each(|candidate| { + assert!(!Rewards::::get(&candidate).is_zero()); + }); } set_max_selected_candidates { @@ -548,6 +547,74 @@ benchmarks! { verify { assert_eq!(>::get(), new); } + + increment_delegator_rewards { + let collator = setup_collator_candidates::(1, None)[0].clone(); + let delegator = fill_delegators::(1, collator.clone(), COLLATOR_ACCOUNT_SEED)[0].clone(); + + // mock high values to compensate for tiny values in unit test env + let stake = T::CurrencyBalance::from(1_000_000_000_000_000_000u128); + DelegatorState::::insert(&delegator, crate::types::Delegator { owner: Some(collator.clone()), amount: stake}); + RewardCount::::insert(&collator, u32::MAX); + + assert!(Rewards::::get(&delegator).is_zero()); + }: _(RawOrigin::Signed(delegator.clone())) + verify { + assert!(!Rewards::::get(&delegator).is_zero()); + } + + increment_collator_rewards { + let m in 1 .. T::MaxDelegatorsPerCollator::get(); + + let collator = setup_collator_candidates::(1, None)[0].clone(); + let delegators = fill_delegators::(m, collator.clone(), COLLATOR_ACCOUNT_SEED); + + // mock high counter to compensate for tiny amounts in unit test env + RewardCount::::insert(&collator, u32::MAX); + assert!(Rewards::::get(&collator).is_zero(), "reward {:?}", Rewards::::get(&collator)); + }: _(RawOrigin::Signed(collator.clone())) + verify { + assert!(!Rewards::::get(&collator).is_zero()); + } + + claim_rewards_for { + let beneficiary = account("beneficiary", 0, 0); + let amount = T::MinCollatorCandidateStake::get(); + T::Currency::make_free_balance_be(&beneficiary, amount); + Rewards::::insert(&beneficiary, amount); + assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), amount.into()); + let unlookup_beneficiary = T::Lookup::unlookup(beneficiary.clone()); + }: _(RawOrigin::Signed(beneficiary.clone()), unlookup_beneficiary) + verify { + assert!(Rewards::::get(&beneficiary).is_zero()); + assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), (amount + amount).into()); + } + + execute_pending_reward_change { + // we need at least 1 collators + let n in 0 .. T::MaxTopCandidates::get(); + // we need at least 1 delegator + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let collator = candidates[0].clone(); + + let old = InflationConfig::::get(); + assert_eq!(LastRewardReduction::::get(), T::BlockNumber::zero()); + System::::set_block_number(T::BLOCKS_PER_YEAR + T::BlockNumber::one()); + }: _(RawOrigin::Signed(collator)) + verify { + let new = InflationConfig::::get(); + assert_eq!(LastRewardReduction::::get(), T::BlockNumber::one()); + assert_eq!(new.collator.max_rate, old.collator.max_rate); + assert_eq!(new.delegator.max_rate, old.delegator.max_rate); + assert!(new.collator.reward_rate.annual < old.collator.reward_rate.annual); + assert!(new.delegator.reward_rate.annual < old.delegator.reward_rate.annual); + } + } impl_benchmark_test_suite!( diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs index 40c1af3224..b065745d92 100644 --- a/pallets/parachain-staking/src/default_weights.rs +++ b/pallets/parachain-staking/src/default_weights.rs @@ -48,10 +48,9 @@ use sp_std::marker::PhantomData; pub trait WeightInfo { fn on_initialize_no_action() -> Weight; fn on_initialize_round_update() -> Weight; - fn on_initialize_new_year() -> Weight; fn on_initialize_network_rewards() -> Weight; fn force_new_round() -> Weight; - fn set_inflation() -> Weight; + fn set_inflation(n: u32, m:u32 ) -> Weight; fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight; fn set_blocks_per_round() -> Weight; fn force_remove_candidate(n: u32, m: u32, ) -> Weight; @@ -64,10 +63,13 @@ pub trait WeightInfo { fn join_delegators(n: u32, m: u32, ) -> Weight; fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight; fn delegator_stake_less(n: u32, m: u32, ) -> Weight; - fn revoke_delegation(n: u32, m: u32, ) -> Weight; fn leave_delegators(n: u32, m: u32, ) -> Weight; fn unlock_unstaked(u: u32, ) -> Weight; fn set_max_candidate_stake() -> Weight; + fn increment_delegator_rewards() -> Weight; + fn increment_collator_rewards(_m: u32, ) -> Weight; + fn claim_rewards_for() -> Weight; + fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight; } /// Weights for parachain_staking using the Substrate node and recommended hardware. @@ -75,60 +77,66 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking Round (r:1 w:0) fn on_initialize_no_action() -> Weight { - (3_525_000 as Weight) + (3_103_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn on_initialize_round_update() -> Weight { - (14_459_000 as Weight) + (11_496_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - fn on_initialize_new_year() -> Weight { - (26_228_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: System Account (r:1 w:1) fn on_initialize_network_rewards() -> Weight { - (55_319_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + (35_227_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking ForceNewRound (r:0 w:1) fn force_new_round() -> Weight { - (1_768_000 as Weight) + (5_101_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: ParachainStaking InflationConfig (r:0 w:1) - fn set_inflation() -> Weight { - (12_952_000 as Weight) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_inflation(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 3_005_000 + .saturating_add((216_364_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 6_440_000 + .saturating_add((440_763_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking CandidatePool (r:59 w:0) + /// The range of component `n` is `[16, 75]`. + /// The range of component `m` is `[0, 35]`. fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((10_570_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 33_000 - .saturating_add((9_858_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 524_000 + .saturating_add((5_444_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 883_000 + .saturating_add((5_252_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn set_blocks_per_round() -> Weight { - (15_586_000 as Weight) + (24_978_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -136,22 +144,27 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 75]`. + /// The range of component `m` is `[0, 35]`. fn force_remove_candidate(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 18_000 - .saturating_add((3_615_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 32_000 - .saturating_add((23_037_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(25 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(T::DbWeight::get().writes(7 as Weight)) - .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + // Standard Error: 1_056_000 + .saturating_add((2_682_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_750_000 + .saturating_add((22_787_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(28 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:0) @@ -163,12 +176,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn join_candidates(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 18_000 - .saturating_add((2_514_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 44_000 - .saturating_add((4_377_000 as Weight).saturating_mul(m as Weight)) + (31_764_000 as Weight) + // Standard Error: 644_000 + .saturating_add((1_293_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_343_000 + .saturating_add((2_377_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -177,12 +192,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn init_leave_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 19_000 - .saturating_add((2_873_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 34_000 - .saturating_add((7_012_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 987_000 + .saturating_add((7_127_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_607_000 + .saturating_add((6_771_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(21 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -190,12 +207,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((2_709_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 30_000 - .saturating_add((5_483_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 26_390_000 + .saturating_add((13_197_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 42_978_000 + .saturating_add((24_662_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -203,20 +222,24 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 20_000 - .saturating_add((4_307_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 37_000 - .saturating_add((24_082_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn execute_leave_candidates(_n: u32, m: u32, ) -> Weight { + (998_775_000 as Weight) + // Standard Error: 431_000 + .saturating_add((20_295_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) @@ -226,30 +249,45 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + /// The range of component `u` is `[0, 9]`. fn candidate_stake_more(n: u32, m: u32, u: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((3_682_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 41_000 - .saturating_add((7_135_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 246_000 - .saturating_add((2_235_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) + // Standard Error: 332_000 + .saturating_add((2_506_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 693_000 + .saturating_add((9_543_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 2_698_000 + .saturating_add((5_104_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn candidate_stake_less(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((3_502_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 42_000 - .saturating_add((7_182_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + // Standard Error: 905_000 + .saturating_add((2_785_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_888_000 + .saturating_add((10_300_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: System Account (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -261,14 +299,17 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn join_delegators(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 20_000 - .saturating_add((3_803_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 54_000 - .saturating_add((8_007_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + (8_951_000 as Weight) + // Standard Error: 855_000 + .saturating_add((1_589_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_919_000 + .saturating_add((3_562_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) @@ -278,15 +319,19 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + /// The range of component `u` is `[1, 9]`. fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 21_000 - .saturating_add((3_810_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 58_000 - .saturating_add((7_940_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 371_000 - .saturating_add((3_810_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) + (56_774_000 as Weight) + // Standard Error: 883_000 + .saturating_add((1_562_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_981_000 + .saturating_add((867_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 8_175_000 + .saturating_add((5_717_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -295,120 +340,164 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn delegator_stake_less(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 19_000 - .saturating_add((3_567_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 51_000 - .saturating_add((7_292_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - fn revoke_delegation(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 17_000 - .saturating_add((3_516_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 45_000 - .saturating_add((7_157_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) + (1_844_000 as Weight) + // Standard Error: 138_000 + .saturating_add((1_192_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 310_000 + .saturating_add((2_218_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn leave_delegators(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 18_000 - .saturating_add((3_503_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 49_000 - .saturating_add((7_270_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) + (3_824_000 as Weight) + // Standard Error: 51_000 + .saturating_add((1_216_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 114_000 + .saturating_add((2_150_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_unstaked(u: u32, ) -> Weight { - (33_495_000 as Weight) - // Standard Error: 23_000 - .saturating_add((366_000 as Weight).saturating_mul(u as Weight)) + /// The range of component `u` is `[1, 9]`. + fn unlock_unstaked(_u: u32, ) -> Weight { + (30_399_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) fn set_max_candidate_stake() -> Weight { - (11_984_000 as Weight) + (13_991_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:2 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_delegator_rewards() -> Weight { + (25_796_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `m` is `[0, 35]`. + fn increment_collator_rewards(_m: u32, ) -> Weight { + (366_611_000 as Weight) + .saturating_add(T::DbWeight::get().reads(75 as Weight)) + .saturating_add(T::DbWeight::get().writes(72 as Weight)) + } + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn claim_rewards_for() -> Weight { + (29_833_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking LastRewardReduction (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 5_730_000 + .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 12_280_000 + .saturating_add((415_436_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) + } } // For backwards compatibility and tests impl WeightInfo for () { // Storage: ParachainStaking Round (r:1 w:0) fn on_initialize_no_action() -> Weight { - (3_525_000 as Weight) + (3_103_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn on_initialize_round_update() -> Weight { - (14_459_000 as Weight) + (11_496_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - fn on_initialize_new_year() -> Weight { - (26_228_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: System Account (r:1 w:1) fn on_initialize_network_rewards() -> Weight { - (55_319_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + (35_227_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking ForceNewRound (r:0 w:1) fn force_new_round() -> Weight { - (1_768_000 as Weight) + (5_101_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: ParachainStaking InflationConfig (r:0 w:1) - fn set_inflation() -> Weight { - (12_952_000 as Weight) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_inflation(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 3_005_000 + .saturating_add((216_364_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 6_440_000 + .saturating_add((440_763_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(RocksDbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(RocksDbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(RocksDbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking CandidatePool (r:59 w:0) + /// The range of component `n` is `[16, 75]`. + /// The range of component `m` is `[0, 35]`. fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((10_570_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 33_000 - .saturating_add((9_858_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 524_000 + .saturating_add((5_444_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 883_000 + .saturating_add((5_252_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn set_blocks_per_round() -> Weight { - (15_586_000 as Weight) + (24_978_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -416,22 +505,27 @@ impl WeightInfo for () { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 75]`. + /// The range of component `m` is `[0, 35]`. fn force_remove_candidate(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 18_000 - .saturating_add((3_615_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 32_000 - .saturating_add((23_037_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(25 as Weight)) - .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(RocksDbWeight::get().writes(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + // Standard Error: 1_056_000 + .saturating_add((2_682_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_750_000 + .saturating_add((22_787_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads(28 as Weight)) + .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(RocksDbWeight::get().writes(9 as Weight)) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:0) @@ -443,12 +537,14 @@ impl WeightInfo for () { // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn join_candidates(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 18_000 - .saturating_add((2_514_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 44_000 - .saturating_add((4_377_000 as Weight).saturating_mul(m as Weight)) + (31_764_000 as Weight) + // Standard Error: 644_000 + .saturating_add((1_293_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_343_000 + .saturating_add((2_377_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } @@ -457,12 +553,14 @@ impl WeightInfo for () { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn init_leave_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 19_000 - .saturating_add((2_873_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 34_000 - .saturating_add((7_012_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 987_000 + .saturating_add((7_127_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_607_000 + .saturating_add((6_771_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(21 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -470,12 +568,14 @@ impl WeightInfo for () { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((2_709_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 30_000 - .saturating_add((5_483_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 26_390_000 + .saturating_add((13_197_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 42_978_000 + .saturating_add((24_662_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -483,20 +583,24 @@ impl WeightInfo for () { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 20_000 - .saturating_add((4_307_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 37_000 - .saturating_add((24_082_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn execute_leave_candidates(_n: u32, m: u32, ) -> Weight { + (998_775_000 as Weight) + // Standard Error: 431_000 + .saturating_add((20_295_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads(11 as Weight)) + .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(RocksDbWeight::get().writes(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) @@ -506,30 +610,45 @@ impl WeightInfo for () { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + /// The range of component `u` is `[0, 9]`. fn candidate_stake_more(n: u32, m: u32, u: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((3_682_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 41_000 - .saturating_add((7_135_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 246_000 - .saturating_add((2_235_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(RocksDbWeight::get().reads(8 as Weight)) - .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + // Standard Error: 332_000 + .saturating_add((2_506_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 693_000 + .saturating_add((9_543_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 2_698_000 + .saturating_add((5_104_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(RocksDbWeight::get().reads(11 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn candidate_stake_less(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 17_000 - .saturating_add((3_502_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 42_000 - .saturating_add((7_182_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + // Standard Error: 905_000 + .saturating_add((2_785_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_888_000 + .saturating_add((10_300_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: System Account (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -541,14 +660,17 @@ impl WeightInfo for () { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn join_delegators(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 20_000 - .saturating_add((3_803_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 54_000 - .saturating_add((8_007_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(11 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + (8_951_000 as Weight) + // Standard Error: 855_000 + .saturating_add((1_589_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_919_000 + .saturating_add((3_562_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads(12 as Weight)) + .saturating_add(RocksDbWeight::get().writes(9 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) @@ -558,15 +680,19 @@ impl WeightInfo for () { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + /// The range of component `u` is `[1, 9]`. fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 21_000 - .saturating_add((3_810_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 58_000 - .saturating_add((7_940_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 371_000 - .saturating_add((3_810_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(RocksDbWeight::get().reads(8 as Weight)) + (56_774_000 as Weight) + // Standard Error: 883_000 + .saturating_add((1_562_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_981_000 + .saturating_add((867_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 8_175_000 + .saturating_add((5_717_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -575,58 +701,96 @@ impl WeightInfo for () { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn delegator_stake_less(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 19_000 - .saturating_add((3_567_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 51_000 - .saturating_add((7_292_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - fn revoke_delegation(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 17_000 - .saturating_add((3_516_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 45_000 - .saturating_add((7_157_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + (1_844_000 as Weight) + // Standard Error: 138_000 + .saturating_add((1_192_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 310_000 + .saturating_add((2_218_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn leave_delegators(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 18_000 - .saturating_add((3_503_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 49_000 - .saturating_add((7_270_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + (3_824_000 as Weight) + // Standard Error: 51_000 + .saturating_add((1_216_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 114_000 + .saturating_add((2_150_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_unstaked(u: u32, ) -> Weight { - (33_495_000 as Weight) - // Standard Error: 23_000 - .saturating_add((366_000 as Weight).saturating_mul(u as Weight)) + /// The range of component `u` is `[1, 9]`. + fn unlock_unstaked(_u: u32, ) -> Weight { + (30_399_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) fn set_max_candidate_stake() -> Weight { - (11_984_000 as Weight) + (13_991_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:2 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_delegator_rewards() -> Weight { + (25_796_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `m` is `[0, 35]`. + fn increment_collator_rewards(_m: u32, ) -> Weight { + (366_611_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(75 as Weight)) + .saturating_add(RocksDbWeight::get().writes(72 as Weight)) + } + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn claim_rewards_for() -> Weight { + (29_833_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking LastRewardReduction (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 5_730_000 + .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 12_280_000 + .saturating_add((415_436_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(RocksDbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(RocksDbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(RocksDbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(RocksDbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) + } } diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 19744a44c1..776e2ff3a8 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -740,7 +740,7 @@ pub mod pallet { /// ShouldEndSession<_>>::should_end_session. /// /// The dispatch origin must be Root. - #[pallet::weight(::WeightInfo::set_inflation())] + #[pallet::weight(::WeightInfo::force_new_round())] pub fn force_new_round(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; @@ -760,20 +760,21 @@ pub mod pallet { /// /// The estimated average block time is twelve seconds. /// + /// NOTE: Iterates over CandidatePool for each candidate over their + /// delegators to set rewards. Needs to be improved when scaling up + /// `MaxTopCandidates`. + /// /// The dispatch origin must be Root. /// /// Emits `RoundInflationSet`. - #[pallet::weight(::WeightInfo::set_inflation())] + #[pallet::weight(::WeightInfo::set_inflation(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] pub fn set_inflation( origin: OriginFor, collator_max_rate_percentage: Perquintill, collator_annual_reward_rate_percentage: Perquintill, delegator_max_rate_percentage: Perquintill, delegator_annual_reward_rate_percentage: Perquintill, - ) -> DispatchResult { - // TODO: Enable after refactoring bench - // ) -> DispatchResultWithPostInfo { - + ) -> DispatchResultWithPostInfo { ensure_root(origin)?; let inflation = InflationInfo::new( @@ -790,8 +791,9 @@ pub mod pallet { ); // set rewards for all collators and delegators due + let mut num_delegators = 0; CandidatePool::::iter().for_each(|(id, state)| { - Self::do_inc_collator_reward(&id, state.stake); + num_delegators = num_delegators.max(Self::do_inc_collator_reward(&id, state.stake)); }); Self::deposit_event(Event::RoundInflationSet( @@ -801,11 +803,11 @@ pub mod pallet { inflation.delegator.reward_rate.per_block, )); InflationConfig::::put(inflation); - Ok(()) - // TODO: Enable after refactoring bench - // Ok(Some(::WeightInfo::set_inflation(CandidatePool:::: - // count()))) + Ok(Some(::WeightInfo::set_inflation( + CandidatePool::::count(), + num_delegators.saturated_into(), + )) + .into()) } /// Set the maximum number of collator candidates that can be selected @@ -1139,6 +1141,10 @@ pub mod pallet { /// The exit request can be reversed by calling /// `cancel_leave_candidates`. /// + /// NOTE: Iterates over CandidatePool for each candidate over their + /// delegators to set rewards. Needs to be improved when scaling up + /// `MaxTopCandidates`. + /// /// Emits `CollatorLeft`. #[pallet::weight(::WeightInfo::execute_leave_candidates( T::MaxTopCandidates::get(), @@ -1707,8 +1713,7 @@ pub mod pallet { /// for anyone. /// /// Emits `Rewarded`. - // TODO: Benchmark - #[pallet::weight(0)] + #[pallet::weight(::WeightInfo::claim_rewards_for())] pub fn claim_rewards_for(origin: OriginFor, target: ::Source) -> DispatchResult { ensure_signed(origin)?; let target = T::Lookup::lookup(target)?; @@ -1732,8 +1737,7 @@ pub mod pallet { /// network. /// /// The dispatch origin must be a collator. - // TODO: Benchmark - #[pallet::weight(0)] + #[pallet::weight(::WeightInfo::increment_collator_rewards(T::MaxDelegatorsPerCollator::get()))] pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; @@ -1742,8 +1746,11 @@ pub mod pallet { let reward_count = RewardCount::::get(&collator); ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); - let weight = Self::do_inc_collator_reward(&collator, state.stake); - Ok(Some(weight).into()) + let num_delegators = Self::do_inc_collator_reward(&collator, state.stake); + Ok(Some(::WeightInfo::increment_collator_rewards( + num_delegators.saturated_into(), + )) + .into()) } /// Actively increment the rewards of a delegator for all their @@ -1753,8 +1760,7 @@ pub mod pallet { /// delegations. /// /// The dispatch origin must be a delegator. - // TODO: Benchmark - #[pallet::weight(0)] + #[pallet::weight(::WeightInfo::increment_delegator_rewards())] pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { let delegator = ensure_signed(origin)?; let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; @@ -1772,8 +1778,7 @@ pub mod pallet { /// before adjusting the inflation. /// /// Emits `RoundInflationSet`. - // TODO: benchmark - #[pallet::weight(0)] + #[pallet::weight(::WeightInfo::execute_pending_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] pub fn execute_pending_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { ensure_signed(origin)?; @@ -1807,8 +1812,9 @@ pub mod pallet { ); // set rewards for all collators and delegators before updating reward rates + let mut max_num_delegators = 0; CandidatePool::::iter().for_each(|(id, state)| { - Self::do_inc_collator_reward(&id, state.stake); + max_num_delegators = max_num_delegators.max(Self::do_inc_collator_reward(&id, state.stake)); }); // update inflation config @@ -1821,10 +1827,10 @@ pub mod pallet { new_inflation.delegator.reward_rate.per_block, )); - Ok(Some( - T::DbWeight::get() - .reads_writes(2, CandidatePool::::count().saturated_into::().saturating_add(3)), - ) + Ok(Some(::WeightInfo::execute_pending_reward_change( + CandidatePool::::count(), + max_num_delegators.saturated_into(), + )) .into()) } } @@ -2377,7 +2383,11 @@ pub mod pallet { T::Currency::issue(network_reward) } - // TODO: Docs and naming improvement + /// Calculates the collator staking rewards for authoring `multiplier` + /// many blocks based on the given stake. + /// + /// Depends on the current total issuance and staking reward + /// configuration for collators. fn calc_block_rewards_collator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { let total_issuance = T::Currency::total_issuance(); let TotalStake { @@ -2391,7 +2401,11 @@ pub mod pallet { .compute_reward::(stake, staking_rate, multiplier) } - // TODO: Docs and naming improvement + /// Calculates the delegator staking rewards for `multiplier` many + /// blocks based on the given stake. + /// + /// Depends on the current total issuance and staking reward + /// configuration for delegators. fn calc_block_rewards_delegator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { let total_issuance = T::Currency::total_issuance(); let TotalStake { @@ -2413,8 +2427,7 @@ pub mod pallet { /// /// Resets all reward counters of the collator and their delegators to /// zero. - fn do_inc_collator_reward(collator: &T::AccountId, stake: BalanceOf) -> Weight { - let mut post_weight = Weight::zero(); + fn do_inc_collator_reward(collator: &T::AccountId, stake: BalanceOf) -> usize { // get reward counters let col_reward_count = RewardCount::::get(collator); @@ -2424,20 +2437,22 @@ pub mod pallet { }); // set reward data for delegators - if let Some(state) = CandidatePool::::get(collator.clone()) { + let num_delegators = if let Some(state) = CandidatePool::::get(collator.clone()) { + let num_delegators = state.delegators.len(); for Stake { owner, amount } in state.delegators { - post_weight = post_weight.saturating_add(Self::do_inc_delegator_reward(&owner, amount, collator)); + Self::do_inc_delegator_reward(&owner, amount, collator); // Reset delegator counter since collator counter will be reset RewardCount::::insert(owner, 0); - post_weight = post_weight.saturating_add(T::DbWeight::get().reads(1)); } - } + num_delegators + } else { + 0usize + }; // Reset collator reward count RewardCount::::insert(collator, 0); - // 4 reads from calc rewards - post_weight.saturating_add(T::DbWeight::get().reads_writes(5, 1)) + num_delegators } /// Increment the accumulated rewards of a delegator by consuming their diff --git a/runtimes/peregrine/src/weights/parachain_staking.rs b/runtimes/peregrine/src/weights/parachain_staking.rs index 665223eaaa..633dd9be63 100644 --- a/runtimes/peregrine/src/weights/parachain_staking.rs +++ b/runtimes/peregrine/src/weights/parachain_staking.rs @@ -50,60 +50,66 @@ pub struct WeightInfo(PhantomData); impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking Round (r:1 w:0) fn on_initialize_no_action() -> Weight { - (3_723_000 as Weight) + (3_103_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn on_initialize_round_update() -> Weight { - (18_017_000 as Weight) + (11_496_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - fn on_initialize_new_year() -> Weight { - (31_315_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: System Account (r:1 w:1) fn on_initialize_network_rewards() -> Weight { - (62_389_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + (35_227_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking ForceNewRound (r:0 w:1) fn force_new_round() -> Weight { - (2_001_000 as Weight) + (5_101_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: ParachainStaking InflationConfig (r:0 w:1) - fn set_inflation() -> Weight { - (15_420_000 as Weight) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_inflation(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 3_005_000 + .saturating_add((216_364_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 6_440_000 + .saturating_add((440_763_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:59 w:0) + /// The range of component `n` is `[16, 75]`. + /// The range of component `m` is `[0, 35]`. fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 14_000 - .saturating_add((7_981_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 25_000 - .saturating_add((6_588_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 524_000 + .saturating_add((5_444_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 883_000 + .saturating_add((5_252_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn set_blocks_per_round() -> Weight { - (17_980_000 as Weight) + (24_978_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -111,22 +117,27 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 75]`. + /// The range of component `m` is `[0, 35]`. fn force_remove_candidate(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 31_000 - .saturating_add((3_278_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 52_000 - .saturating_add((21_750_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(25 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(T::DbWeight::get().writes(7 as Weight)) - .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + // Standard Error: 1_056_000 + .saturating_add((2_682_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_750_000 + .saturating_add((22_787_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(28 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:0) @@ -138,12 +149,14 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn join_candidates(n: u32, m: u32, ) -> Weight { - (17_637_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_338_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 10_000 - .saturating_add((2_867_000 as Weight).saturating_mul(m as Weight)) + (31_764_000 as Weight) + // Standard Error: 644_000 + .saturating_add((1_293_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_343_000 + .saturating_add((2_377_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -152,12 +165,14 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn init_leave_candidates(n: u32, m: u32, ) -> Weight { - (43_107_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_585_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 11_000 - .saturating_add((3_718_000 as Weight).saturating_mul(m as Weight)) + (0 as Weight) + // Standard Error: 987_000 + .saturating_add((7_127_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_607_000 + .saturating_add((6_771_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(21 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -165,12 +180,14 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 8_000 - .saturating_add((1_354_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 13_000 - .saturating_add((2_731_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 26_390_000 + .saturating_add((13_197_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 42_978_000 + .saturating_add((24_662_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -178,20 +195,24 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 25_000 - .saturating_add((2_586_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 41_000 - .saturating_add((20_179_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn execute_leave_candidates(_n: u32, m: u32, ) -> Weight { + (998_775_000 as Weight) + // Standard Error: 431_000 + .saturating_add((20_295_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) @@ -201,30 +222,45 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + /// The range of component `u` is `[0, 9]`. fn candidate_stake_more(n: u32, m: u32, u: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_000 - .saturating_add((1_577_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 11_000 - .saturating_add((3_284_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 46_000 - .saturating_add((976_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) + // Standard Error: 332_000 + .saturating_add((2_506_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 693_000 + .saturating_add((9_543_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 2_698_000 + .saturating_add((5_104_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn candidate_stake_less(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_000 - .saturating_add((1_469_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 12_000 - .saturating_add((2_996_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + // Standard Error: 905_000 + .saturating_add((2_785_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_888_000 + .saturating_add((10_300_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: System Account (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -236,14 +272,17 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn join_delegators(n: u32, m: u32, ) -> Weight { - (31_078_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_699_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 10_000 - .saturating_add((2_770_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + (8_951_000 as Weight) + // Standard Error: 855_000 + .saturating_add((1_589_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_919_000 + .saturating_add((3_562_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) @@ -253,15 +292,19 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + /// The range of component `u` is `[1, 9]`. fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight { - (13_240_000 as Weight) - // Standard Error: 7_000 - .saturating_add((1_666_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 16_000 - .saturating_add((2_759_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 68_000 - .saturating_add((766_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) + (56_774_000 as Weight) + // Standard Error: 883_000 + .saturating_add((1_562_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_981_000 + .saturating_add((867_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 8_175_000 + .saturating_add((5_717_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -270,58 +313,96 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn delegator_stake_less(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 4_000 - .saturating_add((1_569_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 10_000 - .saturating_add((2_722_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - fn revoke_delegation(n: u32, m: u32, ) -> Weight { - (2_496_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_619_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 12_000 - .saturating_add((2_730_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) + (1_844_000 as Weight) + // Standard Error: 138_000 + .saturating_add((1_192_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 310_000 + .saturating_add((2_218_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn leave_delegators(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 7_000 - .saturating_add((1_632_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 15_000 - .saturating_add((2_908_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) + (3_824_000 as Weight) + // Standard Error: 51_000 + .saturating_add((1_216_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 114_000 + .saturating_add((2_150_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_unstaked(u: u32, ) -> Weight { - (34_358_000 as Weight) - // Standard Error: 10_000 - .saturating_add((551_000 as Weight).saturating_mul(u as Weight)) + /// The range of component `u` is `[1, 9]`. + fn unlock_unstaked(_u: u32, ) -> Weight { + (30_399_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) fn set_max_candidate_stake() -> Weight { - (14_071_000 as Weight) + (13_991_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:2 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_delegator_rewards() -> Weight { + (25_796_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `m` is `[0, 35]`. + fn increment_collator_rewards(_m: u32, ) -> Weight { + (366_611_000 as Weight) + .saturating_add(T::DbWeight::get().reads(75 as Weight)) + .saturating_add(T::DbWeight::get().writes(72 as Weight)) + } + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn claim_rewards_for() -> Weight { + (29_833_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking LastRewardReduction (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 5_730_000 + .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 12_280_000 + .saturating_add((415_436_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) + } } diff --git a/runtimes/spiritnet/src/weights/parachain_staking.rs b/runtimes/spiritnet/src/weights/parachain_staking.rs index 57cd1a897c..0663d86aab 100644 --- a/runtimes/spiritnet/src/weights/parachain_staking.rs +++ b/runtimes/spiritnet/src/weights/parachain_staking.rs @@ -50,60 +50,66 @@ pub struct WeightInfo(PhantomData); impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking Round (r:1 w:0) fn on_initialize_no_action() -> Weight { - (3_693_000 as Weight) + (3_103_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn on_initialize_round_update() -> Weight { - (16_988_000 as Weight) + (11_496_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - fn on_initialize_new_year() -> Weight { - (30_201_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: System Account (r:1 w:1) fn on_initialize_network_rewards() -> Weight { - (59_372_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + (35_227_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking ForceNewRound (r:0 w:1) fn force_new_round() -> Weight { - (2_040_000 as Weight) + (5_101_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: ParachainStaking InflationConfig (r:0 w:1) - fn set_inflation() -> Weight { - (15_234_000 as Weight) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_inflation(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 3_005_000 + .saturating_add((216_364_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 6_440_000 + .saturating_add((440_763_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:59 w:0) + /// The range of component `n` is `[16, 75]`. + /// The range of component `m` is `[0, 35]`. fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 26_000 - .saturating_add((7_832_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 44_000 - .saturating_add((6_420_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 524_000 + .saturating_add((5_444_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 883_000 + .saturating_add((5_252_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: ParachainStaking Round (r:1 w:1) fn set_blocks_per_round() -> Weight { - (17_824_000 as Weight) + (24_978_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -111,22 +117,27 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 75]`. + /// The range of component `m` is `[0, 35]`. fn force_remove_candidate(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 34_000 - .saturating_add((2_953_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 57_000 - .saturating_add((21_593_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(25 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(T::DbWeight::get().writes(7 as Weight)) - .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + // Standard Error: 1_056_000 + .saturating_add((2_682_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_750_000 + .saturating_add((22_787_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(28 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:0) @@ -138,12 +149,14 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn join_candidates(n: u32, m: u32, ) -> Weight { - (18_166_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_324_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 9_000 - .saturating_add((2_825_000 as Weight).saturating_mul(m as Weight)) + (31_764_000 as Weight) + // Standard Error: 644_000 + .saturating_add((1_293_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_343_000 + .saturating_add((2_377_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -152,12 +165,14 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn init_leave_candidates(n: u32, m: u32, ) -> Weight { - (48_782_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_455_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 10_000 - .saturating_add((3_702_000 as Weight).saturating_mul(m as Weight)) + (0 as Weight) + // Standard Error: 987_000 + .saturating_add((7_127_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_607_000 + .saturating_add((6_771_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(21 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -165,12 +180,14 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_000 - .saturating_add((1_217_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 12_000 - .saturating_add((2_701_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 26_390_000 + .saturating_add((13_197_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 42_978_000 + .saturating_add((24_662_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -178,20 +195,24 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking Unstaking (r:36 w:36) // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: Session Validators (r:1 w:0) // Storage: Session DisabledValidators (r:1 w:1) // Storage: System Digest (r:1 w:1) // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 23_000 - .saturating_add((2_616_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 38_000 - .saturating_add((20_346_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(m as Weight))) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(m as Weight))) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn execute_leave_candidates(_n: u32, m: u32, ) -> Weight { + (998_775_000 as Weight) + // Standard Error: 431_000 + .saturating_add((20_295_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) @@ -201,30 +222,45 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + /// The range of component `u` is `[0, 9]`. fn candidate_stake_more(n: u32, m: u32, u: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_000 - .saturating_add((1_622_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 12_000 - .saturating_add((3_378_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 49_000 - .saturating_add((1_386_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) + // Standard Error: 332_000 + .saturating_add((2_506_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 693_000 + .saturating_add((9_543_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 2_698_000 + .saturating_add((5_104_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:36 w:36) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. fn candidate_stake_less(n: u32, m: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_000 - .saturating_add((1_458_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 13_000 - .saturating_add((3_010_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + // Standard Error: 905_000 + .saturating_add((2_785_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_888_000 + .saturating_add((10_300_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) } // Storage: System Account (r:1 w:1) // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -236,14 +272,17 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn join_delegators(n: u32, m: u32, ) -> Weight { - (29_422_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_661_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 14_000 - .saturating_add((2_847_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + (8_951_000 as Weight) + // Standard Error: 855_000 + .saturating_add((1_589_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_919_000 + .saturating_add((3_562_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) @@ -253,15 +292,19 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + /// The range of component `u` is `[1, 9]`. fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight { - (10_618_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_683_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 14_000 - .saturating_add((2_894_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 60_000 - .saturating_add((642_000 as Weight).saturating_mul(u as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) + (56_774_000 as Weight) + // Standard Error: 883_000 + .saturating_add((1_562_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 1_981_000 + .saturating_add((867_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 8_175_000 + .saturating_add((5_717_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) @@ -270,58 +313,96 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn delegator_stake_less(n: u32, m: u32, ) -> Weight { - (2_224_000 as Weight) - // Standard Error: 7_000 - .saturating_add((1_593_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 16_000 - .saturating_add((2_703_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - fn revoke_delegation(n: u32, m: u32, ) -> Weight { - (10_893_000 as Weight) - // Standard Error: 26_000 - .saturating_add((1_704_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 59_000 - .saturating_add((2_449_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) + (1_844_000 as Weight) + // Standard Error: 138_000 + .saturating_add((1_192_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 310_000 + .saturating_add((2_218_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking RewardCount (r:2 w:0) // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: ParachainStaking TopCandidates (r:1 w:1) // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. fn leave_delegators(n: u32, m: u32, ) -> Weight { - (703_000 as Weight) - // Standard Error: 7_000 - .saturating_add((1_686_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 17_000 - .saturating_add((2_839_000 as Weight).saturating_mul(m as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) + (3_824_000 as Weight) + // Standard Error: 51_000 + .saturating_add((1_216_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 114_000 + .saturating_add((2_150_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: ParachainStaking Unstaking (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_unstaked(u: u32, ) -> Weight { - (33_561_000 as Weight) - // Standard Error: 10_000 - .saturating_add((581_000 as Weight).saturating_mul(u as Weight)) + /// The range of component `u` is `[1, 9]`. + fn unlock_unstaked(_u: u32, ) -> Weight { + (30_399_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) fn set_max_candidate_stake() -> Weight { - (13_922_000 as Weight) + (13_991_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:2 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_delegator_rewards() -> Weight { + (25_796_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking RewardCount (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `m` is `[0, 35]`. + fn increment_collator_rewards(_m: u32, ) -> Weight { + (366_611_000 as Weight) + .saturating_add(T::DbWeight::get().reads(75 as Weight)) + .saturating_add(T::DbWeight::get().writes(72 as Weight)) + } + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn claim_rewards_for() -> Weight { + (29_833_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ParachainStaking LastRewardReduction (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking RewardCount (r:72 w:72) + // Storage: ParachainStaking Rewards (r:2 w:2) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 5_730_000 + .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 12_280_000 + .saturating_add((415_436_000 as Weight).saturating_mul(m as Weight)) + .saturating_add(T::DbWeight::get().reads((37 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().reads((75 as Weight).saturating_mul(m as Weight))) + .saturating_add(T::DbWeight::get().writes((36 as Weight).saturating_mul(n as Weight))) + .saturating_add(T::DbWeight::get().writes((75 as Weight).saturating_mul(m as Weight))) + } } From 8926e4c68e2b0dbbd0b5c71f5903d65d0e8fcde3 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 8 Aug 2022 10:13:08 +0200 Subject: [PATCH 11/34] feat: remove multiple delegations (#391) * tests: 80% * feat: rm delegate_another_candidate and more * docs: remove deprecated weight * Apply suggestions from code review Co-authored-by: Antonio Co-authored-by: Antonio --- pallets/parachain-staking/src/benchmarking.rs | 97 +-- pallets/parachain-staking/src/lib.rs | 663 ++---------------- pallets/parachain-staking/src/mock.rs | 8 +- pallets/parachain-staking/src/tests.rs | 530 ++++++-------- pallets/parachain-staking/src/types.rs | 115 +-- runtimes/common/src/constants.rs | 3 - runtimes/peregrine/src/lib.rs | 2 - runtimes/spiritnet/src/lib.rs | 2 - 8 files changed, 305 insertions(+), 1115 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 1555c549da..235189666e 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -418,22 +418,22 @@ benchmarks! { // make sure delegator collated to collator let state = >::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, amount); + assert_eq!(>::get(&delegator).unwrap().amount, amount); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::from(u as u64))); - assert_eq!(>::get(&delegator).unwrap().total, amount + T::CurrencyBalance::from(u as u64)); + assert_eq!(>::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&collator, Some(&delegator), u as u64); - assert_eq!(>::get(&delegator).unwrap().total, amount); + assert_eq!(>::get(&delegator).unwrap().amount, amount); let unlookup_collator = T::Lookup::unlookup(collator.clone()); }: _(RawOrigin::Signed(delegator.clone()), unlookup_collator, amount) verify { let state = >::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(>::get(&delegator).unwrap().total, amount + amount); + assert_eq!(>::get(&delegator).unwrap().amount, amount + amount); assert!(>::get(&delegator).is_empty()); } @@ -453,16 +453,16 @@ benchmarks! { // make sure delegator collated to collator let state = >::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); assert_eq!(>::get(&delegator).len(), 1); let unlookup_collator = T::Lookup::unlookup(collator.clone()); @@ -470,44 +470,7 @@ benchmarks! { verify { let state = >::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); - assert_eq!(>::get(&delegator).len(), 2); - } - - revoke_delegation { - // we need at least 1 collators - let n in 1 .. T::MaxTopCandidates::get(); - // we need at least 1 delegator - let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - let amount = T::CurrencyBalance::one(); - - // make sure delegator collated to collator - let state = >::get(&collator).unwrap(); - let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); - - // increase stake so we can unstake, because current stake is minimum - T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount + amount); - - // decrease stake once so we have an unstaking entry for this block - assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount); - assert_eq!(>::get(&delegator).len(), 1); - let unlookup_collator = T::Lookup::unlookup(collator.clone()); - - }: _(RawOrigin::Signed(delegator.clone()), unlookup_collator) - verify { - let state = >::get(&collator).unwrap(); - assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); - assert!(>::get(&delegator).is_none()); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); assert_eq!(>::get(&delegator).len(), 2); } @@ -527,16 +490,16 @@ benchmarks! { // make sure delegator collated to collator let state = >::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get()); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().total, T::MinDelegatorStake::get() + amount); + assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); assert_eq!(>::get(&delegator).len(), 1); }: _(RawOrigin::Signed(delegator.clone())) @@ -585,44 +548,6 @@ benchmarks! { verify { assert_eq!(>::get(), new); } - - // [Post-launch TODO]: Activate after increasing MaxCollatorsPerDelegator to at least 2. Expected to throw otherwise. - // delegate_another_candidate { - // // we need at least 2 collators - // let n in 2 .. T::MaxTopCandidates::get(); - // // we need at least 1 delegator - // let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - // let u in 0 .. (T::MaxUnstakeRequests::get().saturated_into::() - 1); - - // let candidates = setup_collator_candidates::(n, None); - // for (i, c) in candidates.iter().enumerate() { - // fill_delegators::(m, c.clone(), i.saturated_into::()); - // } - // let collator_delegated = candidates[0].clone(); - // let collator = candidates.last().unwrap().clone(); - // let amount = T::MinDelegatorStake::get(); - - // // make sure delegator collated to collator_delegated - // let state_delegated = >::get(&collator_delegated).unwrap(); - // let delegator = state_delegated.delegators.into_bounded_vec()[0].owner.clone(); - // assert!(>::get(&delegator).is_some()); - - // // should not have delegated to collator yet - // let state = >::get(&collator).unwrap(); - // assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); - - // // increase stake so we can unstake, because current stake is minimum - // T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - // assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator_delegated.clone()), T::CurrencyBalance::from(u as u64))); - - // // fill unstake BTreeMap by unstaked many entries of 1 - // fill_unstaking::(&collator_delegated, Some(&delegator), u as u64); - - // }: _(RawOrigin::Signed(delegator.clone()), T::Lookup::unlookup(collator.clone()), amount) - // verify { - // let state = >::get(&collator).unwrap(); - // assert!(state.delegators.into_iter().any(|x| x.owner == delegator); - // } } impl_benchmark_test_suite!( diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index de95c8b6ee..07ceef79b4 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -126,10 +126,8 @@ //! by the provided amount down to `MinCandidateStake`. //! - `join_delegators` - Join the set of delegators by delegating to a collator //! candidate. -//! - `delegate_another_candidate` - Delegate to another collator candidate by -//! staking for them. -//! - `leave_delegators` - Leave the set of delegators and revoke all -//! delegations. Since delegators do not have to run a node and cannot be +//! - `leave_delegators` - Leave the set of delegators and revoke your +//! delegation. Since delegators do not have to run a node and cannot be //! selected to become block authors, this exit is not delayed like it is for //! collator candidates. //! - `revoke_delegation` - Revoke a single delegation to a collator candidate. @@ -171,7 +169,6 @@ mod types; use frame_support::pallet; pub use crate::{default_weights::WeightInfo, pallet::*}; -use types::ReplacedDelegator; #[pallet] pub mod pallet { @@ -291,10 +288,6 @@ pub mod pallet { #[pallet::constant] type MaxDelegatorsPerCollator: Get + Debug + PartialEq; - /// Maximum number of collators a single delegator can delegate. - #[pallet::constant] - type MaxCollatorsPerDelegator: Get + Debug + PartialEq; - /// Maximum size of the top candidates set. #[pallet::constant] type MaxTopCandidates: Get + Debug + PartialEq; @@ -309,10 +302,6 @@ pub mod pallet { #[pallet::constant] type MinCollatorCandidateStake: Get>; - /// Minimum stake required for any account to be able to delegate. - #[pallet::constant] - type MinDelegation: Get>; - /// Minimum stake required for any account to become a delegator. #[pallet::constant] type MinDelegatorStake: Get>; @@ -368,8 +357,6 @@ pub mod pallet { ValStakeBelowMin, /// The account has already staked the maximum amount of funds possible. ValStakeAboveMax, - /// The account has not staked enough funds to become a delegator. - NomStakeBelowMin, /// The account has not staked enough funds to delegate a collator /// candidate. DelegationBelowMin, @@ -586,13 +573,8 @@ pub mod pallet { /// It maps from an account to its delegation details. #[pallet::storage] #[pallet::getter(fn delegator_state)] - pub(crate) type DelegatorState = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegator, T::MaxCollatorsPerDelegator>, - OptionQuery, - >; + pub(crate) type DelegatorState = + StorageMap<_, Twox64Concat, T::AccountId, Delegator>, OptionQuery>; /// The staking information for a candidate. /// @@ -758,12 +740,6 @@ pub mod pallet { /// ShouldEndSession<_>>::should_end_session. /// /// The dispatch origin must be Root. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account] - /// - Writes: ForceNewRound - /// # #[pallet::weight(::WeightInfo::set_inflation())] pub fn force_new_round(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; @@ -787,12 +763,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `RoundInflationSet`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account] - /// - Writes: InflationConfig - /// # #[pallet::weight(::WeightInfo::set_inflation())] pub fn set_inflation( origin: OriginFor, @@ -849,20 +819,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `MaxSelectedCandidatesSet`. - /// - /// - /// # - /// - The transaction's complexity is mainly dependent on updating the - /// `SelectedCandidates` storage in `select_top_candidates` which in - /// return depends on the number of `MaxSelectedCandidates` (N). - /// - For each N, we read `CandidatePool` from the storage. - /// --------- - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators of a - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: MaxSelectedCandidates, TopCandidates, N * CandidatePool - /// - Writes: MaxSelectedCandidates - /// # #[pallet::weight(::WeightInfo::set_max_selected_candidates( *new, T::MaxDelegatorsPerCollator::get() @@ -931,12 +887,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `BlocksPerRoundSet`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account], Round - /// - Writes: Round - /// # #[pallet::weight(::WeightInfo::set_blocks_per_round())] pub fn set_blocks_per_round(origin: OriginFor, new: T::BlockNumber) -> DispatchResult { ensure_root(origin)?; @@ -966,12 +916,6 @@ pub mod pallet { /// The dispatch origin must be Root. /// /// Emits `MaxCandidateStakeChanged`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account], MaxCollatorCandidateStake - /// - Writes: Round - /// # #[pallet::weight(::WeightInfo::set_max_candidate_stake())] pub fn set_max_candidate_stake(origin: OriginFor, new: BalanceOf) -> DispatchResult { ensure_root(origin)?; @@ -1000,23 +944,6 @@ pub mod pallet { /// Increments rewards of candidate and their delegators. /// /// Emits `CandidateRemoved`. - /// - /// # - /// - The transaction's complexity is mainly dependent on updating the - /// `SelectedCandidates` storage in `select_top_candidates` which in - /// return depends on the number of `MaxSelectedCandidates` (N). - /// - For each N, we read `CandidatePool` from the storage. - /// --------- - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators of the - /// collator candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: MaxCollatorCandidateStake, 2 * N * CandidatePool, - /// TopCandidates, BlockNumber, D * DelegatorState, D * Unstaking - /// - Writes: MaxCollatorCandidateStake, N * CandidatePool, D * - /// DelegatorState, (D + 1) * Unstaking - /// - Kills: CandidatePool, DelegatorState for all delegators which only - /// delegated to the candidate - /// # #[pallet::weight(::WeightInfo::force_remove_candidate( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1082,16 +1009,6 @@ pub mod pallet { /// candidates nor of the delegators set. /// /// Emits `JoinedCollatorCandidates`. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], DelegatorState, - /// MaxCollatorCandidateStake, Locks, TotalCollatorStake, - /// TopCandidates, MaxSelectedCandidates, CandidatePool, - /// - Writes: Locks, TotalCollatorStake, CandidatePool, TopCandidates, - /// # #[pallet::weight(::WeightInfo::join_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1165,20 +1082,6 @@ pub mod pallet { /// rewards, until the end of the next session. /// /// Emits `CollatorScheduledExit`. - /// - /// # - /// - The transaction's complexity is mainly dependent on updating the - /// `SelectedCandidates` storage in `select_top_candidates` which in - /// return depends on the number of `MaxSelectedCandidates` (N). - /// - For each N, we read `CandidatePool` from the storage. - /// --------- - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], TopCandidates, (N + 1) * CandidatePool, - /// TotalCollatorStake - /// - Writes: CandidatePool, TopCandidates, TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::init_leave_candidates( T::MaxTopCandidates::get(), T::MaxTopCandidates::get().saturating_mul(T::MaxDelegatorsPerCollator::get()) @@ -1237,17 +1140,6 @@ pub mod pallet { /// `cancel_leave_candidates`. /// /// Emits `CollatorLeft`. - /// - /// # - /// Weight: O(N + D + U) where where N is `MaxSelectedCandidates` - /// bounded by `MaxTopCandidates`, D is the number of delegators for - /// this candidate bounded by `MaxDelegatorsPerCollator` and U is the - /// number of locked unstaking requests bounded by `MaxUnstakeRequests`. - /// - Reads: CandidatePool, Round, D * DelegatorState, D - /// * BlockNumber, D * Unstaking - /// - Writes: D * Unstaking, D * DelegatorState, Total - /// - Kills: CandidatePool, DelegatorState - /// # #[pallet::weight(::WeightInfo::execute_leave_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1287,15 +1179,6 @@ pub mod pallet { /// `init_leave_candidates`. /// /// Emits `CollatorCanceledExit`. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], TotalCollatorStake, TopCandidates, - /// CandidatePool - /// - Writes: TotalCollatorStake, CandidatePool, TopCandidates - /// # #[pallet::weight(::WeightInfo::cancel_leave_candidates( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1343,16 +1226,6 @@ pub mod pallet { /// allowed range as set in the pallet's configuration. /// /// Emits `CollatorStakedMore`. - /// - /// # - /// Weight: O(N + D + U) where where N is `MaxSelectedCandidates` - /// bounded by `MaxTopCandidates`, D is the number of delegators for - /// this candidate bounded by `MaxDelegatorsPerCollator` and U is the - /// number of locked unstaking requests bounded by `MaxUnstakeRequests`. - /// - Reads: [Origin Account], Locks, TotalCollatorStake, - /// MaxCollatorCandidateStake, TopCandidates, CandidatePool - /// - Writes: Locks, TotalCollatorStake, CandidatePool, TopCandidates - /// # #[pallet::weight(::WeightInfo::candidate_stake_more( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1422,15 +1295,6 @@ pub mod pallet { /// allowed range as set in the pallet's configuration. /// /// Emits `CollatorStakedLess`. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], Unstaking, TopCandidates, - /// MaxSelectedCandidates, CandidatePool - /// - Writes: Unstaking, CandidatePool, TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::candidate_stake_less( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1488,8 +1352,8 @@ pub mod pallet { /// The account that wants to delegate cannot be part of the collator /// candidates set as well. /// - /// The caller must _not_ have delegated before. Otherwise, - /// `delegate_another_candidate` should be called. + /// The caller must _not_ have a delegation. If that is the case, they + /// are required to first remove the delegation. /// /// The amount staked must be larger than the minimum required to become /// a delegator as set in the pallet's configuration. @@ -1505,16 +1369,6 @@ pub mod pallet { /// Emits `DelegationReplaced` if the candidate has /// `MaxDelegatorsPerCollator` many delegations but this delegator /// staked more than one of the other delegators of this candidate. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], DelegatorState, TopCandidates, - /// MaxSelectedCandidates, CandidatePool, LastDelegation, Round - /// - Writes: Locks, CandidatePool, DelegatorState, TotalCollatorStake, - /// LastDelegation - /// # #[pallet::weight(::WeightInfo::join_delegators( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1535,7 +1389,7 @@ pub mod pallet { // first delegation ensure!(DelegatorState::::get(&acc).is_none(), Error::::AlreadyDelegating); - ensure!(amount >= T::MinDelegatorStake::get(), Error::::NomStakeBelowMin); + ensure!(amount >= T::MinDelegatorStake::get(), Error::::DelegationBelowMin); // cannot be a collator candidate and delegator with same AccountId ensure!(Self::is_active_candidate(&acc).is_none(), Error::::CandidateExists); @@ -1568,11 +1422,10 @@ pub mod pallet { // should never fail but let's be safe ensure!(insert_delegator, Error::::DelegatorExists); - // can only throw if MaxCollatorsPerDelegator is set to 0 which should never - // occur in practice, even if the delegator rewards are set to 0 - let delegator_state = Delegator::try_new(collator.clone(), amount) - .map_err(|_| Error::::MaxCollatorsPerDelegatorExceeded)?; - + let delegator_state = Delegator { + amount, + owner: Some(collator.clone()), + }; let CandidateOf:: { stake: old_stake, total: old_total, @@ -1581,12 +1434,11 @@ pub mod pallet { // update state and potentially prepare kicking a delegator with less staked // amount (includes setting rewards for kicked delegator) - let (state, maybe_kicked_delegator) = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() - { + let state = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() { Self::do_update_delegator(delegation, state)? } else { state.total = state.total.saturating_add(amount); - (state, None) + state }; let new_total = state.total; @@ -1617,9 +1469,6 @@ pub mod pallet { // initiate reward counter to match the current state of the candidate RewardCount::::insert(&acc, RewardCount::::get(&collator)); - // update or clear storage of potentially kicked delegator - Self::update_kicked_delegator_storage(maybe_kicked_delegator); - Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); Ok(Some(::WeightInfo::join_delegators( n, @@ -1628,166 +1477,8 @@ pub mod pallet { .into()) } - /// Delegate another collator's candidate by staking some funds and - /// increasing the pallet's as well as the collator's total stake. - /// - /// The account that wants to delegate cannot be part of the collator - /// candidates set as well. - /// - /// The caller _must_ have delegated before. Otherwise, - /// `join_delegators` should be called. - /// - /// If the delegator has already delegated the maximum number of - /// collator candidates, this operation will fail. - /// - /// The amount staked must be larger than the minimum required to become - /// a delegator as set in the pallet's configuration. - /// - /// As only `MaxDelegatorsPerCollator` are allowed to delegate a given - /// collator, the amount staked must be larger than the lowest one in - /// the current set of delegator for the operation to be meaningful. - /// - /// The collator's total stake as well as the pallet's total stake are - /// increased accordingly. - /// - /// NOTE: This transaction is expected to throw until we increase - /// `MaxCollatorsPerDelegator` by at least one, since it is currently - /// set to one. - /// - /// Emits `Delegation`. - /// Emits `DelegationReplaced` if the candidate has - /// `MaxDelegatorsPerCollator` many delegations but this delegator - /// staked more than one of the other delegators of this candidate. - /// - /// # - /// Weight: O(N + D) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` and D is the number of delegators for this - /// candidate bounded by `MaxDelegatorsPerCollator`. - /// - Reads: [Origin Account], DelegatorState, TopCandidates, - /// MaxSelectedCandidates, CandidatePool, LastDelegation, Round - /// - Writes: Locks, CandidatePool, DelegatorState, TotalCollatorStake, - /// LastDelegation - /// # - // - // NOTE: We can't benchmark this extrinsic until we have increased `MaxCollatorsPerDelegator` by at least 1, - // thus we use the closest weight we can get. - #[pallet::weight(::WeightInfo::join_delegators( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn delegate_another_candidate( - origin: OriginFor, - collator: ::Source, - amount: BalanceOf, - ) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - let collator = T::Lookup::lookup(collator)?; - let mut delegator = DelegatorState::::get(&acc).ok_or(Error::::NotYetDelegating)?; - - // check balance - ensure!( - pallet_balances::Pallet::::free_balance(acc.clone()) - >= delegator.total.saturating_add(amount).into(), - pallet_balances::Error::::InsufficientBalance - ); - - // delegation after first - ensure!(amount >= T::MinDelegation::get(), Error::::DelegationBelowMin); - ensure!( - (delegator.delegations.len().saturated_into::()) < T::MaxCollatorsPerDelegator::get(), - Error::::MaxCollatorsPerDelegatorExceeded - ); - // cannot delegate if number of delegations in this round exceeds - // MaxDelegationsPerRound - let delegation_counter = Self::get_delegation_counter(&acc)?; - - // prepare new collator state - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - let num_delegations_pre_insertion: u32 = state.delegators.len().saturated_into(); - ensure!(!state.is_leaving(), Error::::CannotDelegateIfLeaving); - - // attempt to insert delegation, check for uniqueness and update total delegated - // amount - // NOTE: excess is handled below because we support replacing a delegator - // with fewer stake - ensure!( - delegator - .add_delegation(Stake { - owner: collator.clone(), - amount - }) - .unwrap_or(true), - Error::::AlreadyDelegatedCollator - ); - let delegation = Stake { - owner: acc.clone(), - amount, - }; - - // throws if delegation insertion exceeds bounded vec limit which we will handle - // below in Self::do_update_delegator - ensure!( - state.delegators.try_insert(delegation.clone()).unwrap_or(true), - Error::::DelegatorExists - ); - - let CandidateOf:: { - stake: old_stake, - total: old_total, - .. - } = state; - - // update state and potentially prepare kicking a delegator with less staked - // amount (includes reward setting for kicked delegator) - let (state, maybe_kicked_delegator) = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() - { - Self::do_update_delegator(delegation, state)? - } else { - state.total = state.total.saturating_add(amount); - (state, None) - }; - let new_total = state.total; - - // *** No Fail except during increase_lock beyond this point *** - - // lock stake - Self::increase_lock(&acc, delegator.total, amount)?; - - // update top candidates and total amount at stake - let n = if state.is_active() { - Self::update_top_candidates( - collator.clone(), - old_stake, - // safe because total >= stake - old_total - old_stake, - state.stake, - state.total - state.stake, - ) - } else { - 0u32 - }; - - // update states - CandidatePool::::insert(&collator, state); - DelegatorState::::insert(&acc, delegator); - >::insert(&acc, delegation_counter); - - // initiate reward counter to match the current state of the candidate - RewardCount::::insert(&acc, RewardCount::::get(&collator)); - - // update or clear storage of potentially kicked delegator - Self::update_kicked_delegator_storage(maybe_kicked_delegator); - - Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); - Ok(Some(::WeightInfo::join_delegators( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Leave the set of delegators and, by implication, revoke all ongoing - /// delegations. + /// Leave the set of delegators and, by implication, revoke the ongoing + /// delegation. /// /// All staked funds are not unlocked immediately, but they are added to /// the queue of pending unstaking, and will effectively be released @@ -1798,19 +1489,10 @@ pub mod pallet { /// their chances to be included in the set of candidates in the next /// rounds. /// - /// Automatically increments the accumulated rewards of the origin for - /// each delegation. + /// Automatically increments the accumulated rewards of the origin of the + /// current delegation. /// /// Emits `DelegatorLeft`. - /// - /// # - /// Weight: O(C) where C is the number of delegations for this delegator - /// which is bounded by by `MaxCollatorsPerDelegator`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// TopCandidates, MaxSelectedCandidates, C * CandidatePool, - /// - Writes: Unstaking, CandidatePool, TotalCollatorStake, - /// - Kills: DelegatorState - /// # #[pallet::weight(::WeightInfo::leave_delegators( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -1818,66 +1500,17 @@ pub mod pallet { pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { let acc = ensure_signed(origin)?; let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; - let num_delegations: u32 = delegator.delegations.len().saturated_into(); - - // remove delegations and increment rewards - for stake in delegator.delegations.into_iter() { - Self::delegator_leaves_collator(acc.clone(), stake.owner.clone())?; - } + // should never throw + let collator = delegator.owner.ok_or(Error::::DelegationNotFound)?; + Self::delegator_leaves_collator(acc.clone(), collator)?; // *** No Fail beyond this point *** DelegatorState::::remove(&acc); - Self::deposit_event(Event::DelegatorLeft(acc, delegator.total)); + Self::deposit_event(Event::DelegatorLeft(acc, delegator.amount)); Ok(Some(::WeightInfo::leave_delegators( - num_delegations, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Terminates an ongoing delegation for a given collator candidate. - /// - /// The staked funds are not unlocked immediately, but they are added to - /// the queue of pending unstaking, and will effectively be released - /// after `StakeDuration` blocks from the moment the delegation is - /// terminated. - /// - /// This operation reduces the total stake of the pallet as well as the - /// stakes of the collator involved, potentially affecting its chances - /// to be included in the set of candidates in the next rounds. - /// - /// Emits `DelegatorLeft`. - /// - /// # - /// Weight: O(C) where C is the number of delegations for this delegator - /// which is bounded by by `MaxCollatorsPerDelegator`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// Locks, TopCandidates, CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, Locks, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// - Kills: DelegatorState if the delegator has not delegated to - /// another collator - /// # - #[pallet::weight(::WeightInfo::revoke_delegation( - T::MaxCollatorsPerDelegator::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn revoke_delegation( - origin: OriginFor, - collator: ::Source, - ) -> DispatchResultWithPostInfo { - let collator = T::Lookup::lookup(collator)?; - let delegator = ensure_signed(origin)?; - - // *** No Fail except during delegator_revokes_collator beyond this point *** - - // revoke delegation and increment rewards - let num_delegations = Self::delegator_revokes_collator(delegator, collator)?; - - Ok(Some(::WeightInfo::revoke_delegation( - num_delegations, + 1, T::MaxDelegatorsPerCollator::get(), )) .into()) @@ -1889,17 +1522,6 @@ pub mod pallet { /// collator candidate to be added to it. /// /// Emits `DelegatorStakedMore`. - /// - /// # - /// Weight: O(N) + O(D) where N is `MaxSelectedCandidates` bounded - /// by `MaxTopCandidates` and D the number of total delegators for - /// this collator bounded by `MaxCollatorsPerDelegator`. - /// bounded by `MaxUnstakeRequests`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// Locks, TopCandidates, CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, Locks, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::delegator_stake_more( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get(), @@ -1914,12 +1536,12 @@ pub mod pallet { ensure!(!more.is_zero(), Error::::ValStakeZero); let candidate = T::Lookup::lookup(candidate)?; - let mut delegations = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let stake_after = delegations + let stake_after = delegation .inc_delegation(candidate.clone(), more) - .ok_or(Error::::DelegationNotFound)?; + .map_err(|_| Error::::DelegationNotFound)?; // *** No Fail except during increase_lock beyond this point *** @@ -1952,7 +1574,7 @@ pub mod pallet { Self::do_inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); CandidatePool::::insert(&candidate, collator); - DelegatorState::::insert(&delegator, delegations); + DelegatorState::::insert(&delegator, delegation); Self::deposit_event(Event::DelegatorStakedMore(delegator, candidate, before_total, after)); Ok(Some(::WeightInfo::delegator_stake_more( @@ -1979,14 +1601,6 @@ pub mod pallet { /// allowed range as set in the pallet's configuration. /// /// Emits `DelegatorStakedLess`. - /// - /// # - /// Weight: O(1) - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// TopCandidates, CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// # #[pallet::weight(::WeightInfo::delegator_stake_less( T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() @@ -2005,13 +1619,12 @@ pub mod pallet { ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); let stake_after = delegations .dec_delegation(candidate.clone(), less) - .ok_or(Error::::DelegationNotFound)? + .map_err(|_| Error::::DelegationNotFound)? .ok_or(Error::::Underflow)?; - ensure!(stake_after >= T::MinDelegation::get(), Error::::DelegationBelowMin); ensure!( - delegations.total >= T::MinDelegatorStake::get(), - Error::::NomStakeBelowMin + stake_after >= T::MinDelegatorStake::get(), + Error::::DelegationBelowMin ); // *** No Fail except during prep_unstake beyond this point *** @@ -2142,25 +1755,19 @@ pub mod pallet { /// The dispatch origin must be a delegator. // TODO: Benchmark, unit tests #[pallet::weight(0)] - pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { + pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { let delegator = ensure_signed(origin)?; - let state = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + // should never throw + let collator = delegation.owner.ok_or(Error::::DelegationNotFound)?; // early exit let reward_count = RewardCount::::take(&delegator); ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); - // iterate delegations - let mut post_weight: Weight = 0; - for delegation in state.delegations.into_iter() { - post_weight = post_weight.saturating_add(Self::do_inc_delegator_reward( - &delegator, - delegation.amount, - &delegation.owner, - )); - } + Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); - Ok(Some(post_weight).into()) + Ok(()) } /// Executes the annual reduction of the reward rates for collators and @@ -2227,11 +1834,6 @@ pub mod pallet { impl Pallet { /// Check whether an account is currently delegating. - /// - /// # - /// Weight: O(1) - /// - Reads: DelegatorState - /// # pub fn is_delegator(acc: &T::AccountId) -> bool { DelegatorState::::get(acc).is_some() } @@ -2240,11 +1842,6 @@ pub mod pallet { /// whether their state is CollatorStatus::Active. /// /// Returns Some(is_active) if the account is a candidate, else None. - /// - /// # - /// Weight: O(1) - /// - Reads: CandidatePool - /// # pub fn is_active_candidate(acc: &T::AccountId) -> Option { if let Some(state) = CandidatePool::::get(acc) { Some(state.status == CandidateStatus::Active) @@ -2258,12 +1855,6 @@ pub mod pallet { /// /// NOTE: It is assumed that the calling context checks whether the /// collator candidate is currently active before calling this function. - /// - /// # - /// Weight: O(1) - /// - Reads: TopCandidates, CandidatePool, TotalCollatorStake - /// - Writes: TopCandidates, TotalCollatorStake - /// # fn update_top_candidates( candidate: T::AccountId, old_self: BalanceOf, @@ -2391,14 +1982,6 @@ pub mod pallet { /// guarantee a single candidate's stake has changed, e.g. on genesis or /// when a collator leaves. Otherwise, please use /// [update_total_stake_by]. - /// - /// # - /// Weight: O(N) where N is `MaxSelectedCandidates` bounded by - /// `MaxTopCandidates` - /// - Reads: TopCandidates, MaxSelectedCandidates, N * CandidatePool, - /// TotalCollatorStake - /// - Writes: TotalCollatorStake - /// # fn update_total_stake() -> (u32, u32) { let mut num_of_delegators = 0u32; let mut collator_stake = BalanceOf::::zero(); @@ -2430,54 +2013,11 @@ pub mod pallet { (collators.len().saturated_into(), num_of_delegators) } - /// Update the delegator's state by removing the collator candidate from - /// the set of ongoing delegations. - /// - /// # - /// Weight: O(D) where D is the number of total delegators for - /// this collator bounded by `MaxCollatorsPerDelegator`. - /// - Reads: [Origin Account], DelegatorState, BlockNumber, Unstaking, - /// Locks, TopCandidates, D * CandidatePool, MaxSelectedCandidates - /// - Writes: Unstaking, Locks, DelegatorState, CandidatePool, - /// TotalCollatorStake - /// - Kills: DelegatorState if the delegator has not delegated to - /// another collator - /// # - fn delegator_revokes_collator(acc: T::AccountId, collator: T::AccountId) -> Result { - let mut delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; - let old_total = delegator.total; - let num_delegations: u32 = delegator.delegations.len().saturated_into::(); - let remaining = delegator - .rm_delegation(&collator) - .ok_or(Error::::DelegationNotFound)?; - - // remove delegation and increment rewards - if delegator.delegations.is_empty() { - // edge case; if no delegations remaining, leave set of delegators - Self::delegator_leaves_collator(acc.clone(), collator)?; - DelegatorState::::remove(&acc); - Self::deposit_event(Event::DelegatorLeft(acc, old_total)); - } else { - // can never fail iff MinDelegatorStake == MinDelegation - ensure!(remaining >= T::MinDelegatorStake::get(), Error::::NomStakeBelowMin); - Self::delegator_leaves_collator(acc.clone(), collator)?; - DelegatorState::::insert(&acc, delegator); - } - Ok(num_delegations) - } - /// Update the collator's state by removing the delegator's stake and /// starting the process to unlock the delegator's staked funds as well /// as incrementing their accumulated rewards. /// /// This operation affects the pallet's total stake. - /// - /// # - /// Weight: O(D) where D is the number of delegators for this - /// collator bounded by `MaxDelegatorsPerCollator`. - /// - Reads: CandidatePool, BlockNumber, Unstaking - /// - Writes: Unstaking, TotalCollatorStake, CandidatePool - /// # fn delegator_leaves_collator(delegator: T::AccountId, collator: T::AccountId) -> DispatchResult { let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; @@ -2527,61 +2067,11 @@ pub mod pallet { Ok(()) } - /// Check for remaining delegations of the delegator which has been - /// removed from the given collator. - /// - /// Returns the removed delegator's address and - /// * Either the updated delegator state if other delegations are still - /// remaining - /// * Or `None`, signalling the delegator state should be cleared once - /// the transaction cannot fail anymore. - fn prep_kick_delegator( - delegation: &StakeOf, - collator: &T::AccountId, - ) -> Result, DispatchError> { - let mut state = DelegatorState::::get(&delegation.owner).ok_or(Error::::DelegatorNotFound)?; - state.rm_delegation(collator); - - // we don't unlock immediately - Self::prep_unstake(&delegation.owner, delegation.amount, true)?; - - // return state if not empty for later removal after all checks have passed - if state.delegations.is_empty() { - Ok(ReplacedDelegator { - who: delegation.owner.clone(), - state: None, - }) - } else { - Ok(ReplacedDelegator { - who: delegation.owner.clone(), - state: Some(state), - }) - } - } - - /// Either clear the storage of a kicked delegator or update its - /// delegation state if it still contains other delegations. - fn update_kicked_delegator_storage(delegator: Option>) { - match delegator { - Some(ReplacedDelegator { - who, - state: Some(state), - }) => DelegatorState::::insert(who, state), - Some(ReplacedDelegator { who, .. }) => DelegatorState::::remove(who), - _ => (), - } - } - /// Return the best `MaxSelectedCandidates` many candidates. /// /// In case a collator from last round was replaced by a candidate with /// the same total stake during sorting, we revert this swap to /// prioritize collators over candidates. - /// - /// # - /// Weight: O(1) - /// - Reads: TopCandidates, MaxSelectedCandidates - /// # pub fn selected_candidates() -> BoundedVec { let candidates = TopCandidates::::get(); @@ -2615,23 +2105,11 @@ pub mod pallet { /// /// Emits `DelegationReplaced` if the stake exceeds one of the current /// delegations. - /// - /// # - /// Weight: O(D) where D is the number of delegators for this collator - /// bounded by `MaxDelegatorsPerCollator`. - /// - Reads/Writes: 0 - /// # #[allow(clippy::type_complexity)] fn do_update_delegator( stake: Stake>, mut state: Candidate, T::MaxDelegatorsPerCollator>, - ) -> Result< - ( - CandidateOf, - Option>, - ), - DispatchError, - > { + ) -> Result, DispatchError> { // attempt to replace the last element of the set let stake_to_remove = state .delegators @@ -2653,9 +2131,10 @@ pub mod pallet { // set rewards for kicked delegator Self::do_inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); - - // update storage of kicked delegator - let kicked_delegator = Self::prep_kick_delegator(&stake_to_remove, &state.id)?; + // prepare unstaking for kicked delegator + Self::prep_unstake(&stake_to_remove.owner, stake_to_remove.amount, true)?; + // remove Delegator state for kicked delegator + DelegatorState::::remove(&stake_to_remove.owner); Self::deposit_event(Event::DelegationReplaced( stake.owner, @@ -2665,11 +2144,9 @@ pub mod pallet { state.id.clone(), state.total, )); - - Ok((state, Some(kicked_delegator))) - } else { - Ok((state, None)) } + + Ok(state) } /// Either set or increase the BalanceLock of target account to @@ -2677,13 +2154,6 @@ pub mod pallet { /// /// Consumes unstaked balance which can be unlocked in the future up to /// amount and updates `Unstaking` storage accordingly. - /// - /// # - /// Weight: O(U) where U is the number of locked unstaking requests - /// bounded by `MaxUnstakeRequests`. - /// - Reads: Unstaking, Locks - /// - Writes: Unstaking, Locks - /// # fn increase_lock(who: &T::AccountId, amount: BalanceOf, more: BalanceOf) -> Result { ensure!( pallet_balances::Pallet::::free_balance(who) >= amount.into(), @@ -2736,12 +2206,6 @@ pub mod pallet { /// Throws if the amount is zero (unlikely) or if active unlocking /// requests exceed limit. The latter defends against stake reduction /// spamming. - /// - /// # - /// Weight: O(1) - /// - Reads: BlockNumber, Unstaking - /// - Writes: Unstaking - /// # fn prep_unstake(who: &T::AccountId, amount: BalanceOf, is_removal: bool) -> DispatchResult { // should never occur but let's be safe ensure!(!amount.is_zero(), Error::::StakeNotFound); @@ -2775,16 +2239,6 @@ pub mod pallet { /// Clear the CandidatePool of the candidate and remove all delegations /// to the candidate. Moreover, prepare unstaking for the candidate and /// their former delegations. - /// - /// # - /// Weight: O(D + U) where D is the number of delegators of the collator - /// candidate bounded by `MaxDelegatorsPerCollator` and U is the - /// number of locked unstaking requests bounded by `MaxUnstakeRequests`. - /// - Reads: BlockNumber, D * DelegatorState, D * Unstaking - /// - Writes: D * DelegatorState, (D + 1) * Unstaking - /// - Kills: CandidatePool, DelegatorState for all delegators which only - /// delegated to the candidate - /// # fn remove_candidate( collator: &T::AccountId, state: &CandidateOf, @@ -2795,13 +2249,10 @@ pub mod pallet { Self::prep_unstake(&stake.owner, stake.amount, true)?; // remove delegation from delegator state if let Some(mut delegator) = DelegatorState::::get(&stake.owner) { - if let Some(remaining) = delegator.rm_delegation(collator) { - if remaining.is_zero() { - DelegatorState::::remove(&stake.owner); - } else { - DelegatorState::::insert(&stake.owner, delegator); - } - } + delegator + .rm_delegation(collator.clone()) + .map_err(|_| Error::::DelegationNotFound)?; + DelegatorState::::remove(&stake.owner); } } // prepare unstaking of collator candidate @@ -2833,14 +2284,6 @@ pub mod pallet { /// Withdraw all staked currency which was unstaked at least /// `StakeDuration` blocks ago. - /// - /// # - /// Weight: O(U) where U is the number of locked unstaking - /// requests bounded by `MaxUnstakeRequests`. - /// - Reads: Unstaking, Locks - /// - Writes: Unstaking, Locks - /// - Kills: Unstaking & Locks if no balance is locked anymore - /// # fn do_unlock(who: &T::AccountId) -> Result { let now = >::block_number(); let mut unstaking = >::get(who); @@ -2888,15 +2331,11 @@ pub mod pallet { /// Checks whether a delegator can still delegate in this round, e.g., /// if they have not delegated MaxDelegationsPerRound many times /// already in this round. - /// - /// # - /// Weight: O(1) - /// - Reads: LastDelegation, Round - /// # fn get_delegation_counter(delegator: &T::AccountId) -> Result { let last_delegation = >::get(delegator); let round = >::get(); + // reset counter if the round advanced since last delegation let counter = if last_delegation.round < round.current { 0u32 } else { @@ -2904,7 +2343,7 @@ pub mod pallet { }; ensure!( - T::MaxDelegationsPerRound::get() > counter, + counter < T::MaxDelegationsPerRound::get(), Error::::DelegationsPerRoundExceeded ); @@ -2931,12 +2370,6 @@ pub mod pallet { /// /// `col_reward_rate_per_block * col_max_stake * max_num_of_collators * /// NetworkRewardRate` - /// - /// # - /// Weight: O(1) - /// - Reads: InflationConfig, MaxCollatorCandidateStake, - /// MaxSelectedCandidates - /// # fn get_network_reward() -> NegativeImbalanceOf { // Multiplication with Perquintill cannot overflow let max_col_rewards = InflationConfig::::get().collator.reward_rate.per_block diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index cc2bb37f0a..206a157821 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -134,15 +134,13 @@ parameter_types! { pub const ExitQueueDelay: u32 = 2; pub const DefaultBlocksPerRound: BlockNumber = BLOCKS_PER_ROUND; pub const MinCollators: u32 = 2; + pub const MaxDelegationsPerRound: u32 = 2; #[derive(Debug, PartialEq)] pub const MaxDelegatorsPerCollator: u32 = 4; - #[derive(Debug, PartialEq)] - pub const MaxCollatorsPerDelegator: u32 = 4; pub const MinCollatorStake: Balance = 10; #[derive(Debug, PartialEq)] pub const MaxCollatorCandidates: u32 = 10; pub const MinDelegatorStake: Balance = 5; - pub const MinDelegation: Balance = 3; pub const MaxUnstakeRequests: u32 = 6; pub const NetworkRewardRate: Perquintill = Perquintill::from_percent(10); pub const NetworkRewardStart: BlockNumber = 5 * 5 * 60 * 24 * 36525 / 100; @@ -166,14 +164,12 @@ impl Config for Test { type ExitQueueDelay = ExitQueueDelay; type MinCollators = MinCollators; type MinRequiredCollators = MinCollators; - type MaxDelegationsPerRound = MaxDelegatorsPerCollator; + type MaxDelegationsPerRound = MaxDelegationsPerRound; type MaxDelegatorsPerCollator = MaxDelegatorsPerCollator; - type MaxCollatorsPerDelegator = MaxCollatorsPerDelegator; type MinCollatorStake = MinCollatorStake; type MinCollatorCandidateStake = MinCollatorStake; type MaxTopCandidates = MaxCollatorCandidates; type MinDelegatorStake = MinDelegatorStake; - type MinDelegation = MinDelegation; type MaxUnstakeRequests = MaxUnstakeRequests; type NetworkRewardRate = NetworkRewardRate; type NetworkRewardStart = NetworkRewardStart; diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 5692b7be66..9a713081e7 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -349,6 +349,7 @@ fn collator_exit_executes_after_delay() { (7, 100), (8, 9), (9, 4), + (10, 10), ]) .with_collators(vec![(1, 500), (2, 200), (7, 100)]) .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) @@ -382,7 +383,7 @@ fn collator_exit_executes_after_delay() { // Still three, candidate didn't leave yet assert_eq!(CandidatePool::::count(), 3); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(3), 2, 10), + StakePallet::join_delegators(Origin::signed(10), 2, 10), Error::::CannotDelegateIfLeaving ); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 7]); @@ -713,47 +714,31 @@ fn execute_leave_candidates_with_delay() { } assert_eq!( StakePallet::delegator_state(11), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 110 }].try_into().unwrap() - ), - total: 110 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 110, + }) ); assert_eq!( StakePallet::delegator_state(12), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 120 }].try_into().unwrap() - ), - total: 120 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 120 + }) ); assert_eq!( StakePallet::delegator_state(13), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 130 }].try_into().unwrap() - ), - total: 130 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 130 + }) ); assert_eq!( StakePallet::delegator_state(14), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 140 }].try_into().unwrap() - ), - total: 140 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 140 + }) ); for delegator in 11u64..=14u64 { assert!(StakePallet::is_delegator(&delegator)); @@ -830,47 +815,31 @@ fn execute_leave_candidates_with_delay() { } assert_eq!( StakePallet::delegator_state(11), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 110 }].try_into().unwrap() - ), - total: 110 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 110 + }) ); assert_eq!( StakePallet::delegator_state(12), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 1, amount: 120 }].try_into().unwrap() - ), - total: 120 - } - ) + Some(Delegator:: { + owner: Some(1), + amount: 120 + }) ); assert_eq!( StakePallet::delegator_state(13), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 130 }].try_into().unwrap() - ), - total: 130 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 130 + }) ); assert_eq!( StakePallet::delegator_state(14), - Some( - Delegator::::MaxCollatorsPerDelegator> { - delegations: OrderedSet::from( - vec![StakeOf:: { owner: 2, amount: 140 }].try_into().unwrap() - ), - total: 140 - } - ) + Some(Delegator:: { + owner: Some(2), + amount: 140 + }) ); for delegator in 11u64..=14u64 { assert!(StakePallet::is_delegator(&delegator)); @@ -913,6 +882,7 @@ fn execute_leave_candidates_with_delay() { }); } +// FIXME: Re-enable or potentially remove entirely #[test] fn multiple_delegations() { ExtBuilder::default() @@ -929,6 +899,14 @@ fn multiple_delegations() { (10, 100), (11, 100), (12, 100), + // new + (13, 100), + (14, 100), + (15, 100), + (16, 100), + (17, 100), + (18, 100), + (99, 1), ]) .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) @@ -945,20 +923,16 @@ fn multiple_delegations() { let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; assert_eq!(events(), expected); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 1, 10), - Error::::AlreadyDelegatedCollator, - ); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 2, 2), + StakePallet::join_delegators(Origin::signed(13), 2, 2), Error::::DelegationBelowMin, ); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 2, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 4, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 3, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(13), 2, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(14), 4, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(15), 3, 10)); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 5, 10), - Error::::MaxCollatorsPerDelegatorExceeded, + StakePallet::join_delegators(Origin::signed(6), 5, 10), + Error::::AlreadyDelegating, ); roll_to( @@ -967,9 +941,9 @@ fn multiple_delegations() { ); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); let mut new = vec![ - Event::Delegation(6, 10, 2, 50), - Event::Delegation(6, 10, 4, 30), - Event::Delegation(6, 10, 3, 30), + Event::Delegation(13, 10, 2, 50), + Event::Delegation(14, 10, 4, 30), + Event::Delegation(15, 10, 3, 30), Event::NewRound(10, 2), Event::NewRound(15, 3), ]; @@ -977,21 +951,21 @@ fn multiple_delegations() { assert_eq!(events(), expected); roll_to(21, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(7), 2, 80)); + assert_ok!(StakePallet::join_delegators(Origin::signed(16), 2, 80)); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(7), 3, 11), + StakePallet::join_delegators(Origin::signed(99), 3, 11), BalancesError::::InsufficientBalance ); assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(10), 2, 10), + StakePallet::join_delegators(Origin::signed(17), 2, 10), Error::::TooManyDelegators ); - // kick 6 - assert!(StakePallet::unstaking(6).is_empty()); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(10), 2, 11)); - assert!(StakePallet::delegator_state(6).is_some()); - assert_eq!(StakePallet::unstaking(6).get(&23), Some(&10u128)); - // kick 9 + // kick 13 by staking 1 more (11 > 10) + assert!(StakePallet::unstaking(13).is_empty()); + assert_ok!(StakePallet::join_delegators(Origin::signed(17), 2, 11)); + assert!(StakePallet::delegator_state(13).is_none()); + assert_eq!(StakePallet::unstaking(13).get(&23), Some(&10u128)); + // kick 9 by staking 1 more (11 > 10) assert!(StakePallet::unstaking(9).is_empty()); assert!(StakePallet::rewards(9).is_zero()); assert_ok!(StakePallet::join_delegators(Origin::signed(11), 2, 11)); @@ -1009,9 +983,9 @@ fn multiple_delegations() { assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 4, 3, 5]); let mut new2 = vec![ Event::NewRound(20, 4), - Event::Delegation(7, 80, 2, 130), - Event::DelegationReplaced(10, 11, 6, 10, 2, 131), - Event::Delegation(10, 11, 2, 131), + Event::Delegation(16, 80, 2, 130), + Event::DelegationReplaced(17, 11, 13, 10, 2, 131), + Event::Delegation(17, 11, 2, 131), Event::DelegationReplaced(11, 11, 9, 10, 2, 132), Event::Delegation(11, 11, 2, 132), Event::NewRound(25, 5), @@ -1035,53 +1009,53 @@ fn multiple_delegations() { assert_eq!(events(), expected); // test join_delegator errors - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(8), 1, 10)); + assert_ok!(StakePallet::join_delegators(Origin::signed(18), 1, 10)); assert_noop!( StakePallet::join_delegators(Origin::signed(12), 1, 10), Error::::TooManyDelegators ); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(12), 1, 10), - Error::::NotYetDelegating - ); assert_ok!(StakePallet::join_delegators(Origin::signed(12), 1, 11)); // verify that delegations are removed after collator leaves, not before - assert_eq!(StakePallet::delegator_state(7).unwrap().total, 90); - assert_eq!(StakePallet::delegator_state(7).unwrap().delegations.len(), 2usize); - assert_eq!(StakePallet::delegator_state(11).unwrap().total, 11); - assert_eq!(StakePallet::delegator_state(11).unwrap().delegations.len(), 1usize); - // 6 already has 10 in - assert_eq!(Balances::usable_balance(&7), 10); - assert_eq!(Balances::usable_balance(&11), 89); - assert_eq!(Balances::free_balance(&7), 100); - assert_eq!(Balances::free_balance(&11), 100); + assert!(StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 8, amount: 10 })); + assert!(StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 17, amount: 11 })); + assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); + assert_eq!(StakePallet::delegator_state(17).unwrap().amount, 11); + assert_eq!(Balances::usable_balance(&8), 90); + assert_eq!(Balances::usable_balance(&17), 89); + assert_eq!(Balances::free_balance(&8), 100); + assert_eq!(Balances::free_balance(&17), 100); roll_to(35, vec![Some(1), Some(2), Some(3), Some(4)]); assert_ok!(StakePallet::execute_leave_candidates(Origin::signed(2), 2)); - let mut unbonding_7: BoundedBTreeMap, ::MaxUnstakeRequests> = + let mut unbonding_8: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); - assert_ok!(unbonding_7.try_insert(35u64 + ::StakeDuration::get() as u64, 80)); - assert_eq!(StakePallet::unstaking(7), unbonding_7); - let mut unbonding_11: BoundedBTreeMap, ::MaxUnstakeRequests> = + assert_ok!(unbonding_8.try_insert(35u64 + ::StakeDuration::get() as u64, 10)); + assert_eq!(StakePallet::unstaking(8), unbonding_8); + let mut unbonding_17: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); - assert_ok!(unbonding_11.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); - assert_eq!(StakePallet::unstaking(11), unbonding_11); + assert_ok!(unbonding_17.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); + assert_eq!(StakePallet::unstaking(17), unbonding_17); roll_to(37, vec![Some(1), Some(2)]); - assert_eq!(StakePallet::delegator_state(7).unwrap().total, 10); - assert!(StakePallet::delegator_state(11).is_none()); - assert_eq!(StakePallet::delegator_state(7).unwrap().delegations.len(), 1usize); - assert_ok!(StakePallet::unlock_unstaked(Origin::signed(7), 7)); - assert_ok!(StakePallet::unlock_unstaked(Origin::signed(11), 11)); + assert!(StakePallet::delegator_state(8).is_none()); + assert!(StakePallet::delegator_state(17).is_none()); + assert_ok!(StakePallet::unlock_unstaked(Origin::signed(8), 8)); + assert_ok!(StakePallet::unlock_unstaked(Origin::signed(17), 17)); assert_noop!( StakePallet::unlock_unstaked(Origin::signed(12), 12), Error::::UnstakingIsEmpty ); - assert_eq!(Balances::usable_balance(&11), 100); - assert_eq!(Balances::usable_balance(&7), 90); - assert_eq!(Balances::free_balance(&11), 100); - assert_eq!(Balances::free_balance(&7), 100); + assert_eq!(Balances::usable_balance(&17), 100); + assert_eq!(Balances::usable_balance(&8), 100); + assert_eq!(Balances::free_balance(&17), 100); + assert_eq!(Balances::free_balance(&8), 100); }); } @@ -1172,29 +1146,19 @@ fn should_update_total_stake() { ); old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(11), 2, 150)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators + 150, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::delegator_state(11).unwrap().total, 350); + assert_eq!(StakePallet::delegator_state(11).unwrap().amount, 200); assert_ok!(StakePallet::leave_delegators(Origin::signed(11))); assert_eq!( StakePallet::total_collator_stake(), TotalStake { - delegators: old_stake.delegators - 350, + delegators: old_stake.delegators - 200, ..old_stake } ); let old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::delegator_state(8).unwrap().total, 10); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(8), 2)); + assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); + assert_ok!(StakePallet::leave_delegators(Origin::signed(8))); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -1261,10 +1225,6 @@ fn collators_bond() { StakePallet::candidate_stake_less(Origin::signed(6), 50), Error::::CandidateNotFound ); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 50, 10), - Error::::CandidateNotFound - ); assert_ok!(StakePallet::candidate_stake_more(Origin::signed(1), 50)); assert_noop!( StakePallet::candidate_stake_more(Origin::signed(1), 40), @@ -1376,10 +1336,6 @@ fn delegators_bond() { StakePallet::delegator_stake_less(Origin::signed(6), 1, 8), Error::::DelegationBelowMin ); - assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(6), 1, 6), - Error::::NomStakeBelowMin - ); assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 1, 10)); assert_noop!( StakePallet::delegator_stake_less(Origin::signed(6), 2, 5), @@ -1391,7 +1347,7 @@ fn delegators_bond() { ); assert_noop!( StakePallet::join_delegators(Origin::signed(10), 1, 4), - Error::::NomStakeBelowMin + Error::::DelegationBelowMin ); roll_to(9, vec![]); @@ -1411,55 +1367,27 @@ fn delegators_bond() { } #[test] -fn revoke_delegation_or_leave_delegators() { +fn should_leave_delegators() { ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .set_blocks_per_round(5) + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - roll_to(4, vec![]); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); + assert!(StakePallet::delegator_state(2).is_none()); + assert!(!StakePallet::candidate_pool(1) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 2, amount: 100 })); assert_noop!( - StakePallet::revoke_delegation(Origin::signed(1), 2), + StakePallet::leave_delegators(Origin::signed(2)), Error::::DelegatorNotFound ); - assert_noop!( - StakePallet::revoke_delegation(Origin::signed(6), 2), - Error::::DelegationNotFound - ); assert_noop!( StakePallet::leave_delegators(Origin::signed(1)), Error::::DelegatorNotFound ); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 2, 3)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 3, 3)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(6), 1)); - // cannot revoke delegation because would leave remaining total below - // MinDelegatorStake - assert_noop!( - StakePallet::revoke_delegation(Origin::signed(6), 2), - Error::::NomStakeBelowMin - ); - assert_noop!( - StakePallet::revoke_delegation(Origin::signed(6), 3), - Error::::NomStakeBelowMin - ); - // can revoke both remaining by calling leave delegators - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - // this leads to 8 leaving set of delegators - assert_ok!(StakePallet::revoke_delegation(Origin::signed(8), 2)); }); } @@ -1670,7 +1598,7 @@ fn coinbase_rewards_few_blocks_detailed_check() { assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); assert_eq!(Balances::usable_balance(&5), user_5 + d_rewards / 4); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(5), 2)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(5))); // 2 is block author for 5th block roll_to_claim_rewards(6, authors); @@ -1693,7 +1621,7 @@ fn delegator_should_not_receive_rewards_after_revoking() { .with_inflation(10, 15, 40, 15, 5) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); assert_eq!(Balances::usable_balance(&1), Balance::zero()); assert_eq!(Balances::usable_balance(&2), Balance::zero()); @@ -1714,7 +1642,7 @@ fn delegator_should_not_receive_rewards_after_revoking() { .with_inflation(10, 15, 40, 15, 5) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(3), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); assert_eq!(Balances::usable_balance(&1), Balance::zero()); assert_eq!(Balances::usable_balance(&2), Balance::zero()); @@ -2267,7 +2195,7 @@ fn unlock_unstaked() { .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 100)); @@ -2286,7 +2214,7 @@ fn unlock_unstaked() { // join delegators and revoke again --> consume unstaking at block 3 roll_to(2, vec![]); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); unstaking.remove(&3); assert_ok!(unstaking.try_insert(4, 100)); assert_eq!(StakePallet::unstaking(2), unstaking); @@ -2325,7 +2253,7 @@ fn unlock_unstaked() { .with_delegators(vec![(2, 1, 10)]) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 10)); @@ -2344,7 +2272,7 @@ fn unlock_unstaked() { // join delegators and revoke again roll_to(2, vec![]); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); unstaking.remove(&3); assert_ok!(unstaking.try_insert(4, 100)); lock.amount = 100; @@ -2385,7 +2313,7 @@ fn unlock_unstaked() { .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 100)); @@ -2404,7 +2332,7 @@ fn unlock_unstaked() { // join delegators and revoke again roll_to(2, vec![]); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(2), 1)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); assert_ok!(unstaking.try_insert(3, 90)); assert_ok!(unstaking.try_insert(4, 10)); assert_eq!(StakePallet::unstaking(2), unstaking); @@ -2979,60 +2907,49 @@ fn decrease_max_candidate_stake() { #[test] fn exceed_delegations_per_round() { ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)]) - .with_delegators(vec![(6, 1, 10)]) + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 100)]) .build() .execute_with(|| { - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 2, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 3, 10)); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(6), 4, 10)); - assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 5, 10), - Error::::MaxCollatorsPerDelegatorExceeded - ); - - // revoke delegation to allow one more collator for this delegator - assert_ok!(StakePallet::revoke_delegation(Origin::signed(6), 4)); + // leave and re-join to set counter to 2 (= MaxDelegationsPerRound) + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); // reached max delegations in this round assert_noop!( - StakePallet::delegate_another_candidate(Origin::signed(6), 5, 10), - Error::::DelegationsPerRoundExceeded - ); - - // revoke all delegations in the same round - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_noop!( - StakePallet::join_delegators(Origin::signed(6), 1, 10), + StakePallet::join_delegators(Origin::signed(2), 1, 100), Error::::DelegationsPerRoundExceeded ); // roll to next round to clear DelegationCounter roll_to(5, vec![]); assert_eq!( - StakePallet::last_delegation(6), - DelegationCounter { round: 0, counter: 4 } + StakePallet::last_delegation(2), + DelegationCounter { round: 0, counter: 2 } ); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + // counter should be reset because the round changed assert_eq!( - StakePallet::last_delegation(6), + StakePallet::last_delegation(2), DelegationCounter { round: 1, counter: 1 } ); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 10),); - assert_ok!(StakePallet::leave_delegators(Origin::signed(6))); - assert_eq!( - StakePallet::last_delegation(6), - DelegationCounter { round: 1, counter: 4 } + // leave and re-join to set counter to 2 (= MaxDelegationsPerRound)) + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); + assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); + assert_noop!( + StakePallet::join_delegators(Origin::signed(2), 1, 100), + Error::::AlreadyDelegating ); + assert_ok!(StakePallet::leave_delegators(Origin::signed(2))); assert_noop!( - StakePallet::join_delegators(Origin::signed(6), 1, 10), + StakePallet::join_delegators(Origin::signed(2), 1, 100), Error::::DelegationsPerRoundExceeded ); + assert_eq!( + StakePallet::last_delegation(2), + DelegationCounter { round: 1, counter: 2 } + ); }); } @@ -3045,7 +2962,7 @@ fn force_remove_candidate() { .build() .execute_with(|| { assert_eq!(CandidatePool::::count(), 3); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(4), 2, 50)); + assert_ok!(StakePallet::join_delegators(Origin::signed(6), 2, 50)); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); assert!(StakePallet::unstaking(1).get(&3).is_none()); assert!(StakePallet::unstaking(2).get(&3).is_none()); @@ -3076,14 +2993,8 @@ fn force_remove_candidate() { assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); assert_eq!(CandidatePool::::count(), 2); assert!(StakePallet::candidate_pool(1).is_none()); + assert!(StakePallet::delegator_state(4).is_none()); assert!(StakePallet::delegator_state(5).is_none()); - assert_eq!( - StakePallet::delegator_state(4), - Some(Delegator { - delegations: OrderedSet::from(vec![StakeOf:: { owner: 2, amount: 50 }].try_into().unwrap()), - total: 50 - }) - ); assert_eq!(StakePallet::unstaking(1).get(&3), Some(&100)); assert_eq!(StakePallet::unstaking(4).get(&3), Some(&50)); assert_eq!(StakePallet::unstaking(5).get(&3), Some(&50)); @@ -3275,7 +3186,7 @@ fn prioritize_collators() { .unwrap() ) ); - assert_ok!(StakePallet::revoke_delegation(Origin::signed(7), 5)); + assert_ok!(StakePallet::leave_delegators(Origin::signed(7))); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 5]); assert_eq!( StakePallet::top_candidates(), @@ -3305,9 +3216,11 @@ fn prioritize_delegators() { (5, 1000), (6, 1000), (7, 1000), + (8, 1000), + (9, 1000), ]) .with_collators(vec![(1, 100), (2, 100), (3, 100)]) - .with_delegators(vec![(5, 1, 100), (4, 2, 100), (7, 2, 100), (6, 2, 100)]) + .with_delegators(vec![(4, 2, 100), (7, 2, 100), (6, 2, 100)]) .build() .execute_with(|| { assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1]); @@ -3323,7 +3236,7 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(5), 2, 110)); + assert_ok!(StakePallet::join_delegators(Origin::signed(5), 2, 110)); assert_eq!( StakePallet::candidate_pool(2).unwrap().delegators, OrderedSet::from_sorted_set( @@ -3337,17 +3250,6 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_eq!( - StakePallet::delegator_state(5).unwrap().delegations, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 2, amount: 110 }, - StakeOf:: { owner: 1, amount: 100 } - ] - .try_into() - .unwrap() - ) - ); // delegate_less assert_ok!(StakePallet::delegator_stake_less(Origin::signed(5), 2, 10)); @@ -3364,17 +3266,6 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_eq!( - StakePallet::delegator_state(5).unwrap().delegations, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 2, amount: 100 }, - StakeOf:: { owner: 1, amount: 100 } - ] - .try_into() - .unwrap() - ) - ); // delegate_more assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 2, 10)); @@ -4162,66 +4053,67 @@ fn rewards_delegator_replaced() { }); } -#[test] -fn rewards_delegator_revokes_single_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, 2 * DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // stake more to trigger reward incrementing just for 3 - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, DECIMALS)); - // 1 should still have counter 1 but no rewards - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::rewards(1).is_zero()); - // 2 should still have neither rewards nor counter - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::rewards(2).is_zero()); - // 3 should have rewards and the same counter as 1 - assert_eq!(StakePallet::reward_count(3), 1); - assert!(!StakePallet::rewards(3).is_zero()); - }); -} - -#[test] -fn rewards_delegator_leaves() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) - .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) - .with_delegators(vec![(3, 1, DECIMALS)]) - .build() - .execute_with(|| { - assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(3), 2, DECIMALS)); - // note both collators once to set their counter to 2 - StakePallet::note_author(1); - StakePallet::note_author(2); - assert_eq!(StakePallet::reward_count(1), 2); - assert_eq!(StakePallet::reward_count(2), 2); - assert!(StakePallet::reward_count(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // only 3 should have non-zero rewards and counter reset - assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); - (1..=2).for_each(|id| { - assert_eq!(StakePallet::reward_count(id), 2, "acc_id {:?}", id); - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - assert!(!StakePallet::rewards(3).is_zero()); - assert_eq!(StakePallet::reward_count(3), 4); - }); -} +// FIXME: Re-enable +// #[test] +// fn rewards_delegator_revokes_single_delegation() { +// ExtBuilder::default() +// .with_balances(vec![(1, DECIMALS), (2, 2 * DECIMALS)]) +// .with_collators(vec![(1, DECIMALS)]) +// .with_delegators(vec![(2, 1, DECIMALS)]) +// .build() +// .execute_with(|| { +// // note once to set counter to 1 +// StakePallet::note_author(1); +// assert_eq!(StakePallet::reward_count(1), 1); +// assert!(StakePallet::reward_count(2).is_zero()); +// assert!(StakePallet::reward_count(3).is_zero()); +// (1..=3).for_each(|id| { +// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); +// }); + +// // stake more to trigger reward incrementing just for 3 +// assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, +// DECIMALS)); // 1 should still have counter 1 but no rewards +// assert_eq!(StakePallet::reward_count(1), 1); +// assert!(StakePallet::rewards(1).is_zero()); +// // 2 should still have neither rewards nor counter +// assert!(StakePallet::reward_count(2).is_zero()); +// assert!(StakePallet::rewards(2).is_zero()); +// // 3 should have rewards and the same counter as 1 +// assert_eq!(StakePallet::reward_count(3), 1); +// assert!(!StakePallet::rewards(3).is_zero()); +// }); +// } + +// #[test] +// fn rewards_delegator_leaves() { +// ExtBuilder::default() +// .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) +// .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) +// .with_delegators(vec![(3, 1, DECIMALS)]) +// .build() +// .execute_with(|| { +// assert_ok!(StakePallet::delegate_another_candidate(Origin::signed(3), 2, +// DECIMALS)); // note both collators once to set their counter to 2 +// StakePallet::note_author(1); +// StakePallet::note_author(2); +// assert_eq!(StakePallet::reward_count(1), 2); +// assert_eq!(StakePallet::reward_count(2), 2); +// assert!(StakePallet::reward_count(3).is_zero()); +// (1..=3).for_each(|id| { +// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); +// }); + +// // only 3 should have non-zero rewards and counter reset +// assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); +// (1..=2).for_each(|id| { +// assert_eq!(StakePallet::reward_count(id), 2, "acc_id {:?}", id); +// assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); +// }); +// assert!(!StakePallet::rewards(3).is_zero()); +// assert_eq!(StakePallet::reward_count(3), 4); +// }); +// } // TODO: // rewards_delegator_revokes_single_delegation diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index 64bb6b7392..6c8ccaa117 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -26,10 +26,8 @@ use sp_runtime::{ use sp_staking::SessionIndex; use sp_std::{ cmp::Ordering, - convert::TryInto, fmt::Debug, ops::{Add, Sub}, - vec, }; use crate::{set::OrderedSet, Config}; @@ -211,100 +209,60 @@ where } } -#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(MaxCollatorsPerDelegator))] -#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] -pub struct Delegator> { - pub delegations: OrderedSet, MaxCollatorsPerDelegator>, - pub total: Balance, -} - -impl Delegator +pub type Delegator = Stake, Balance>; +impl Delegator where AccountId: Eq + Ord + Clone + Debug, - Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero, - MaxCollatorsPerDelegator: Get + Debug + PartialEq, + Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default, { - pub fn try_new(collator: AccountId, amount: Balance) -> Result { - Ok(Delegator { - delegations: OrderedSet::from( - vec![Stake { - owner: collator, - amount, - }] - .try_into()?, - ), - total: amount, - }) - } - /// Adds a new delegation. /// - /// If already delegating to the same account, this call returns false and - /// doesn't insert the new delegation. - pub fn add_delegation(&mut self, stake: Stake) -> Result { - let amt = stake.amount; - if self.delegations.try_insert(stake).map_err(|_| ())? { - self.total = self.total.saturating_add(amt); - Ok(true) + /// If already delegating to someone, this call will fail. + pub fn add_delegation(&mut self, stake: Stake) -> Result<(), ()> { + if self.owner.is_none() && self.amount.is_zero() { + self.owner = Some(stake.owner); + self.amount = stake.amount; + Ok(()) } else { - Ok(false) + Err(()) } } - /// Returns Some(remaining stake for delegator) if the delegation for the - /// collator exists. Returns `None` otherwise. - pub fn rm_delegation(&mut self, collator: &AccountId) -> Option { - let amt = self.delegations.remove(&Stake:: { - owner: collator.clone(), - // amount is irrelevant for removal - amount: Balance::zero(), - }); - - if let Some(Stake:: { amount: balance, .. }) = amt { - self.total = self.total.saturating_sub(balance); - Some(self.total) + /// Returns Ok if the delegation for the + /// collator exists and `Err` otherwise. + pub fn rm_delegation(&mut self, collator: AccountId) -> Result<(), ()> { + if self.owner == Some(collator) { + self.amount = Balance::zero(); + self.owner = None; + Ok(()) } else { - None + Err(()) } } - /// Returns Some(delegated_amount) if successfull, None if delegation was + /// Returns Ok(delegated_amount) if successfull, `Err` if delegation was /// not found. - pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Option { - if let Ok(i) = self.delegations.linear_search(&Stake:: { - owner: collator, - amount: Balance::zero(), - }) { - self.delegations - .mutate(|vec| vec[i].amount = vec[i].amount.saturating_add(more)); - self.total = self.total.saturating_add(more); - self.delegations.sort_greatest_to_lowest(); - Some(self.delegations[i].amount) + pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Result { + if self.owner == Some(collator) { + self.amount = self.amount.saturating_add(more); + Ok(self.amount) } else { - None + Err(()) } } - /// Returns Some(Some(delegated_amount)) if successful, None if delegation - /// was not found and Some(None) if delegated stake would underflow. - pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Option> { - if let Ok(i) = self.delegations.linear_search(&Stake:: { - owner: collator, - amount: Balance::zero(), - }) { - if self.delegations[i].amount > less { - self.delegations - .mutate(|vec| vec[i].amount = vec[i].amount.saturating_sub(less)); - self.total = self.total.saturating_sub(less); - self.delegations.sort_greatest_to_lowest(); - Some(Some(self.delegations[i].amount)) + /// Returns Ok(Some(delegated_amount)) if successful, `Err` if delegation + /// was not found and Ok(None) if delegated stake would underflow. + pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Result, ()> { + if self.owner == Some(collator) { + if self.amount > less { + self.amount = self.amount.saturating_sub(less); + Ok(Some(self.amount)) } else { - // underflow error; should rm entire delegation - Some(None) + Ok(None) } } else { - None + Err(()) } } } @@ -372,13 +330,6 @@ pub struct DelegationCounter { pub counter: u32, } -/// Internal type which is only used when a delegator is replaced by another -/// one to delay the storage entry removal until failure cannot happen anymore. -pub(crate) struct ReplacedDelegator { - pub who: AccountIdOf, - pub state: Option, BalanceOf, T::MaxCollatorsPerDelegator>>, -} - pub type AccountIdOf = ::AccountId; pub type BalanceOf = <::Currency as Currency>>::Balance; pub type CandidateOf = Candidate, BalanceOf, S>; diff --git a/runtimes/common/src/constants.rs b/runtimes/common/src/constants.rs index 06b4b38415..e0033a45ff 100644 --- a/runtimes/common/src/constants.rs +++ b/runtimes/common/src/constants.rs @@ -203,9 +203,6 @@ pub mod staking { /// Maximum 25 delegators per collator at launch, might be increased later #[derive(Debug, PartialEq)] pub const MaxDelegatorsPerCollator: u32 = MAX_DELEGATORS_PER_COLLATOR; - /// Maximum 1 collator per delegator at launch, will be increased later - #[derive(Debug, PartialEq)] - pub const MaxCollatorsPerDelegator: u32 = 1; /// Minimum stake required to be reserved to be a collator is 10_000 pub const MinCollatorStake: Balance = 10_000 * KILT; /// Minimum stake required to be reserved to be a delegator is 1000 diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index c93fd8e367..44ca67e127 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -624,11 +624,9 @@ impl parachain_staking::Config for Runtime { type MinRequiredCollators = constants::staking::MinRequiredCollators; type MaxDelegationsPerRound = constants::staking::MaxDelegationsPerRound; type MaxDelegatorsPerCollator = constants::staking::MaxDelegatorsPerCollator; - type MaxCollatorsPerDelegator = constants::staking::MaxCollatorsPerDelegator; type MinCollatorStake = constants::staking::MinCollatorStake; type MinCollatorCandidateStake = constants::staking::MinCollatorStake; type MaxTopCandidates = constants::staking::MaxCollatorCandidates; - type MinDelegation = constants::staking::MinDelegatorStake; type MinDelegatorStake = constants::staking::MinDelegatorStake; type MaxUnstakeRequests = constants::staking::MaxUnstakeRequests; type NetworkRewardRate = constants::staking::NetworkRewardRate; diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index a62ebaf100..5e81a21974 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -619,11 +619,9 @@ impl parachain_staking::Config for Runtime { type MinRequiredCollators = constants::staking::MinRequiredCollators; type MaxDelegationsPerRound = constants::staking::MaxDelegationsPerRound; type MaxDelegatorsPerCollator = constants::staking::MaxDelegatorsPerCollator; - type MaxCollatorsPerDelegator = constants::staking::MaxCollatorsPerDelegator; type MinCollatorStake = constants::staking::MinCollatorStake; type MinCollatorCandidateStake = constants::staking::MinCollatorStake; type MaxTopCandidates = constants::staking::MaxCollatorCandidates; - type MinDelegation = constants::staking::MinDelegatorStake; type MinDelegatorStake = constants::staking::MinDelegatorStake; type MaxUnstakeRequests = constants::staking::MaxUnstakeRequests; type NetworkRewardRate = constants::staking::NetworkRewardRate; From f8c1419b5c913420cf96c085e513d5ab9b801a82 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 9 Aug 2022 10:38:40 +0200 Subject: [PATCH 12/34] Apply suggestions from code review Co-authored-by: Antonio --- pallets/parachain-staking/src/tests.rs | 6 +++--- pallets/parachain-staking/src/types.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 18472943cc..3676b5dea0 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -3879,7 +3879,7 @@ fn rewards_candidate_stake_less() { assert!(StakePallet::rewards(id).is_zero()); }); - // stake more to trigger reward incrementing + // stake less to trigger reward incrementing assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), DECIMALS)); (1..=3).for_each(|id| { assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); @@ -4036,7 +4036,7 @@ fn rewards_delegator_stake_less() { assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); }); - // stake more to trigger reward incrementing just for 3 + // stake less to trigger reward incrementing just for 3 assert_ok!(StakePallet::delegator_stake_less(Origin::signed(3), 1, DECIMALS)); // 1 should still have counter 1 but no rewards assert_eq!(StakePallet::reward_count(1), 1); @@ -4141,7 +4141,7 @@ fn rewards_set_inflation() { hundred, hundred )); - // rewards should be set and counter rese + // rewards should be set and counter reset (1..=5).for_each(|id| { assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index 6c8ccaa117..b7ad3b98f8 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -240,7 +240,7 @@ where } } - /// Returns Ok(delegated_amount) if successfull, `Err` if delegation was + /// Returns Ok(delegated_amount) if successful, `Err` if delegation was /// not found. pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Result { if self.owner == Some(collator) { From ad13650e92a6c87335b1ac3374bfc03531c6025f Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 9 Aug 2022 12:05:28 +0200 Subject: [PATCH 13/34] fix: suggestions from @ntn-x2 review --- pallets/parachain-staking/src/benchmarking.rs | 2 +- .../parachain-staking/src/default_weights.rs | 6 +++--- pallets/parachain-staking/src/lib.rs | 21 +++++++++++++------ pallets/parachain-staking/src/mock.rs | 17 +++++++++++++++ pallets/parachain-staking/src/tests.rs | 6 +++--- pallets/parachain-staking/src/types.rs | 14 ++++++------- .../src/weights/parachain_staking.rs | 2 +- .../src/weights/parachain_staking.rs | 2 +- 8 files changed, 47 insertions(+), 23 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 168eef05b5..4ce7549d7b 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -590,7 +590,7 @@ benchmarks! { assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), (amount + amount).into()); } - execute_pending_reward_change { + exectue_scheduled_reward_change { // we need at least 1 collators let n in 0 .. T::MaxTopCandidates::get(); // we need at least 1 delegator diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs index b065745d92..effa84e587 100644 --- a/pallets/parachain-staking/src/default_weights.rs +++ b/pallets/parachain-staking/src/default_weights.rs @@ -69,7 +69,7 @@ pub trait WeightInfo { fn increment_delegator_rewards() -> Weight; fn increment_collator_rewards(_m: u32, ) -> Weight; fn claim_rewards_for() -> Weight; - fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight; + fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight; } /// Weights for parachain_staking using the Substrate node and recommended hardware. @@ -421,7 +421,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) @@ -782,7 +782,7 @@ impl WeightInfo for () { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 776e2ff3a8..d1721748b4 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -647,10 +647,17 @@ pub mod pallet { #[pallet::getter(fn last_reward_reduction)] pub(crate) type LastRewardReduction = StorageValue<_, T::BlockNumber, ValueQuery>; - /// The counter of accumulated rewards for a collator candidate. + /// The counter of accumulated rewards for an account. /// - /// It maps from collator accounts to the number of block authored by them - /// since the last payout. + /// For collators, it reflects the number of authored blocks since the last + /// reward raise. Thus, everytime a collator authors a block, the + /// counter is increased. It is reset, when the collator increments their + /// rewards. + /// + /// For delegators, it is used to determine the difference between the + /// delegator and corresponding collator when incrementing the delegator's + /// rewards. In this case, the counter is never incremented but reset to the + /// collator one when the delegator reward increment happens. // TODO: Maybe rather use u64. Assuming 30 validators, u32 would suffice for 27 years of constant 12s blocktime. #[pallet::storage] #[pallet::getter(fn reward_count)] @@ -1778,8 +1785,8 @@ pub mod pallet { /// before adjusting the inflation. /// /// Emits `RoundInflationSet`. - #[pallet::weight(::WeightInfo::execute_pending_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] - pub fn execute_pending_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { + #[pallet::weight(::WeightInfo::exectue_scheduled_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] + pub fn exectue_scheduled_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { ensure_signed(origin)?; let now = frame_system::Pallet::::block_number(); @@ -1827,7 +1834,7 @@ pub mod pallet { new_inflation.delegator.reward_rate.per_block, )); - Ok(Some(::WeightInfo::execute_pending_reward_change( + Ok(Some(::WeightInfo::exectue_scheduled_reward_change( CandidatePool::::count(), max_num_delegators.saturated_into(), )) @@ -2469,6 +2476,8 @@ pub mod pallet { Rewards::::mutate(acc, |reward| { *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, diff.into())); }); + // align with collator counter such that incrementing would + // lead to 0 rewards until the collator counter increases RewardCount::::insert(acc, col_reward_count); // 4 reads from reward calc diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index 206a157821..8ad07d5dd1 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -355,6 +355,15 @@ pub(crate) fn almost_equal(left: Balance, right: Balance, precision: Perbill) -> left.max(right) - left.min(right) <= err } +/// Incrementelly traverses from the current block to the provided one and +/// potentially sets a block authors. +/// +/// If for a block `i` the corresponding index of the authors input is set, this +/// account is regarded to be the block author and thus gets noted. +/// +/// NOTE: At most, this updates the RewardCount of the block author but does not +/// increment rewards or claim them. Please use `roll_to_claim_rewards` in that +/// case. pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { while System::block_number() < n { if let Some(Some(author)) = authors.get((System::block_number()) as usize) { @@ -367,6 +376,14 @@ pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { } #[allow(unused_must_use)] +/// Incrementelly traverses from the current block to the provided one and +/// potentially sets a block authors. +/// +/// If existent, rewards of the block author and their delegators are +/// incremented and claimed. +/// +/// If for a block `i` the corresponding index of the authors input is set, this +/// account is regarded to be the block author and thus gets noted. pub(crate) fn roll_to_claim_rewards(n: BlockNumber, authors: Vec>) { while System::block_number() < n { if let Some(Some(author)) = authors.get((System::block_number()) as usize) { diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 3676b5dea0..f3809de592 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -2757,7 +2757,7 @@ fn adjust_reward_rates() { roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); // reward reduction should not happen automatically anymore assert_eq!(StakePallet::last_reward_reduction(), 0u64); - assert_ok!(StakePallet::execute_pending_reward_change(Origin::signed(1))); + assert_ok!(StakePallet::exectue_scheduled_reward_change(Origin::signed(1))); assert_eq!(StakePallet::last_reward_reduction(), 1u64); let inflation_1 = InflationInfo::new( ::BLOCKS_PER_YEAR, @@ -2788,7 +2788,7 @@ fn adjust_reward_rates() { roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 1, vec![]); // reward reduction should not happen automatically anymore assert_eq!(StakePallet::last_reward_reduction(), 1u64); - assert_ok!(StakePallet::execute_pending_reward_change(Origin::signed(1))); + assert_ok!(StakePallet::exectue_scheduled_reward_change(Origin::signed(1))); assert_eq!(StakePallet::last_reward_reduction(), 2u64); let inflation_2 = InflationInfo::new( ::BLOCKS_PER_YEAR, @@ -4175,7 +4175,7 @@ fn rewards_yearly_inflation_adjustment() { }); // execute to trigger reward increment - assert_ok!(StakePallet::execute_pending_reward_change(Origin::signed(1))); + assert_ok!(StakePallet::exectue_scheduled_reward_change(Origin::signed(1))); (1..=5).for_each(|id| { assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index b7ad3b98f8..f63ea86c61 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -20,7 +20,7 @@ use frame_support::traits::{Currency, Get}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Saturating, Zero}, + traits::{AtLeast32BitUnsigned, CheckedSub, Saturating, Zero}, RuntimeDebug, }; use sp_staking::SessionIndex; @@ -213,7 +213,7 @@ pub type Delegator = Stake, Balance>; impl Delegator where AccountId: Eq + Ord + Clone + Debug, - Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default, + Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default + CheckedSub, { /// Adds a new delegation. /// @@ -255,12 +255,10 @@ where /// was not found and Ok(None) if delegated stake would underflow. pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Result, ()> { if self.owner == Some(collator) { - if self.amount > less { - self.amount = self.amount.saturating_sub(less); - Ok(Some(self.amount)) - } else { - Ok(None) - } + Ok(self.amount.checked_sub(&less).map(|new| { + self.amount = new; + self.amount + })) } else { Err(()) } diff --git a/runtimes/peregrine/src/weights/parachain_staking.rs b/runtimes/peregrine/src/weights/parachain_staking.rs index 633dd9be63..3f86ca10be 100644 --- a/runtimes/peregrine/src/weights/parachain_staking.rs +++ b/runtimes/peregrine/src/weights/parachain_staking.rs @@ -394,7 +394,7 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) diff --git a/runtimes/spiritnet/src/weights/parachain_staking.rs b/runtimes/spiritnet/src/weights/parachain_staking.rs index 0663d86aab..f2875f3886 100644 --- a/runtimes/spiritnet/src/weights/parachain_staking.rs +++ b/runtimes/spiritnet/src/weights/parachain_staking.rs @@ -394,7 +394,7 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn execute_pending_reward_change(n: u32, m: u32, ) -> Weight { + fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) From adbcd46cbaf2d4f526c116465842f375b4d5eac1 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 9 Aug 2022 12:09:02 +0200 Subject: [PATCH 14/34] fmt --- pallets/parachain-staking/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index 8ad07d5dd1..9f1dd854d4 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -379,7 +379,7 @@ pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { /// Incrementelly traverses from the current block to the provided one and /// potentially sets a block authors. /// -/// If existent, rewards of the block author and their delegators are +/// If existent, rewards of the block author and their delegators are /// incremented and claimed. /// /// If for a block `i` the corresponding index of the authors input is set, this From ddebe3a5ae5feed6d5fc071892fe50c17181507d Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 9 Aug 2022 13:25:49 +0200 Subject: [PATCH 15/34] fix: typos --- pallets/parachain-staking/src/benchmarking.rs | 2 +- pallets/parachain-staking/src/default_weights.rs | 6 +++--- pallets/parachain-staking/src/lib.rs | 6 +++--- pallets/parachain-staking/src/mock.rs | 4 ++-- pallets/parachain-staking/src/tests.rs | 6 +++--- runtimes/peregrine/src/weights/parachain_staking.rs | 2 +- runtimes/spiritnet/src/weights/parachain_staking.rs | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 4ce7549d7b..39014ff98e 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -590,7 +590,7 @@ benchmarks! { assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), (amount + amount).into()); } - exectue_scheduled_reward_change { + execute_scheduled_reward_change { // we need at least 1 collators let n in 0 .. T::MaxTopCandidates::get(); // we need at least 1 delegator diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs index effa84e587..f458dc9586 100644 --- a/pallets/parachain-staking/src/default_weights.rs +++ b/pallets/parachain-staking/src/default_weights.rs @@ -69,7 +69,7 @@ pub trait WeightInfo { fn increment_delegator_rewards() -> Weight; fn increment_collator_rewards(_m: u32, ) -> Weight; fn claim_rewards_for() -> Weight; - fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight; + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight; } /// Weights for parachain_staking using the Substrate node and recommended hardware. @@ -421,7 +421,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) @@ -782,7 +782,7 @@ impl WeightInfo for () { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index d1721748b4..8bbb760bdf 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1785,8 +1785,8 @@ pub mod pallet { /// before adjusting the inflation. /// /// Emits `RoundInflationSet`. - #[pallet::weight(::WeightInfo::exectue_scheduled_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] - pub fn exectue_scheduled_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { + #[pallet::weight(::WeightInfo::execute_scheduled_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] + pub fn execute_scheduled_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { ensure_signed(origin)?; let now = frame_system::Pallet::::block_number(); @@ -1834,7 +1834,7 @@ pub mod pallet { new_inflation.delegator.reward_rate.per_block, )); - Ok(Some(::WeightInfo::exectue_scheduled_reward_change( + Ok(Some(::WeightInfo::execute_scheduled_reward_change( CandidatePool::::count(), max_num_delegators.saturated_into(), )) diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index 9f1dd854d4..302f533830 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -356,7 +356,7 @@ pub(crate) fn almost_equal(left: Balance, right: Balance, precision: Perbill) -> } /// Incrementelly traverses from the current block to the provided one and -/// potentially sets a block authors. +/// potentially sets block authors. /// /// If for a block `i` the corresponding index of the authors input is set, this /// account is regarded to be the block author and thus gets noted. @@ -377,7 +377,7 @@ pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { #[allow(unused_must_use)] /// Incrementelly traverses from the current block to the provided one and -/// potentially sets a block authors. +/// potentially sets block authors. /// /// If existent, rewards of the block author and their delegators are /// incremented and claimed. diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index f3809de592..1103914d65 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -2757,7 +2757,7 @@ fn adjust_reward_rates() { roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); // reward reduction should not happen automatically anymore assert_eq!(StakePallet::last_reward_reduction(), 0u64); - assert_ok!(StakePallet::exectue_scheduled_reward_change(Origin::signed(1))); + assert_ok!(StakePallet::execute_scheduled_reward_change(Origin::signed(1))); assert_eq!(StakePallet::last_reward_reduction(), 1u64); let inflation_1 = InflationInfo::new( ::BLOCKS_PER_YEAR, @@ -2788,7 +2788,7 @@ fn adjust_reward_rates() { roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 1, vec![]); // reward reduction should not happen automatically anymore assert_eq!(StakePallet::last_reward_reduction(), 1u64); - assert_ok!(StakePallet::exectue_scheduled_reward_change(Origin::signed(1))); + assert_ok!(StakePallet::execute_scheduled_reward_change(Origin::signed(1))); assert_eq!(StakePallet::last_reward_reduction(), 2u64); let inflation_2 = InflationInfo::new( ::BLOCKS_PER_YEAR, @@ -4175,7 +4175,7 @@ fn rewards_yearly_inflation_adjustment() { }); // execute to trigger reward increment - assert_ok!(StakePallet::exectue_scheduled_reward_change(Origin::signed(1))); + assert_ok!(StakePallet::execute_scheduled_reward_change(Origin::signed(1))); (1..=5).for_each(|id| { assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); diff --git a/runtimes/peregrine/src/weights/parachain_staking.rs b/runtimes/peregrine/src/weights/parachain_staking.rs index 3f86ca10be..080f3ca309 100644 --- a/runtimes/peregrine/src/weights/parachain_staking.rs +++ b/runtimes/peregrine/src/weights/parachain_staking.rs @@ -394,7 +394,7 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) diff --git a/runtimes/spiritnet/src/weights/parachain_staking.rs b/runtimes/spiritnet/src/weights/parachain_staking.rs index f2875f3886..ece13ab308 100644 --- a/runtimes/spiritnet/src/weights/parachain_staking.rs +++ b/runtimes/spiritnet/src/weights/parachain_staking.rs @@ -394,7 +394,7 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) /// The range of component `n` is `[0, 75]`. /// The range of component `m` is `[0, 35]`. - fn exectue_scheduled_reward_change(n: u32, m: u32, ) -> Weight { + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { (0 as Weight) // Standard Error: 5_730_000 .saturating_add((202_623_000 as Weight).saturating_mul(n as Weight)) From 7b9fda321f2d0dae181acd32970e4b11c2bf1f94 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 11 Aug 2022 18:02:54 +0200 Subject: [PATCH 16/34] fix: docker file --- .gitlab-ci.yml | 16 +- Cargo.lock | 860 +++++++++++++++++++++++++++---------------------- Dockerfile | 4 +- 3 files changed, 477 insertions(+), 403 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index af8a283641..6d34065625 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,8 +4,8 @@ stages: clippy: # Corresponds to paritytech/ci-linux:production at the time of this PR - # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6?context=explore - image: paritytech/ci-linux@sha256:3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6 + # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e?context=explore + image: paritytech/ci-linux@sha256:4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e stage: test timeout: 1 hours script: @@ -14,8 +14,8 @@ clippy: fmt: # Corresponds to paritytech/ci-linux:production at the time of this PR - # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6?context=explore - image: paritytech/ci-linux@sha256:3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6 + # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e?context=explore + image: paritytech/ci-linux@sha256:4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e stage: test timeout: 1 hours script: @@ -24,8 +24,8 @@ fmt: test: # Corresponds to paritytech/ci-linux:production at the time of this PR - # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6?context=explore - image: paritytech/ci-linux@sha256:3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6 + # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e?context=explore + image: paritytech/ci-linux@sha256:4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e stage: test timeout: 1 hours script: @@ -33,8 +33,8 @@ test: test-features: # Corresponds to paritytech/ci-linux:production at the time of this PR - # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6?context=explore - image: paritytech/ci-linux@sha256:3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6 + # https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e?context=explore + image: paritytech/ci-linux@sha256:4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e stage: test timeout: 1 hours script: diff --git a/Cargo.lock b/Cargo.lock index 136ae233b4..1e49f0ea04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", ] [[package]] @@ -68,7 +68,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", "once_cell", "version_check", ] @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.59" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "approx" @@ -188,14 +188,14 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.2.0" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5262ed948da60dd8956c6c5aca4d4163593dddb7b32d73267c93dab7b2e98940" +checksum = "c290043c9a95b05d45e952fb6383c67bcb61471f60cfa21e890dba6654234f43" dependencies = [ "async-channel", "async-executor", "async-io", - "async-lock", + "async-mutex", "blocking", "futures-lite", "num_cpus", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "async-io" -version = "1.7.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" +checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" dependencies = [ "concurrent-queue", "futures-lite", @@ -231,10 +231,19 @@ dependencies = [ ] [[package]] -name = "async-process" +name = "async-mutex" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-process" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" dependencies = [ "async-io", "blocking", @@ -249,9 +258,9 @@ dependencies = [ [[package]] name = "async-std" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "52580991739c5cdb36cde8b2a516371c0a3b70dda36d916cc08b82372916808c" dependencies = [ "async-attributes", "async-channel", @@ -268,6 +277,7 @@ dependencies = [ "kv-log-macro", "log", "memchr", + "num_cpus", "once_cell", "pin-project-lite 0.2.9", "pin-utils", @@ -292,15 +302,15 @@ dependencies = [ [[package]] name = "async-task" -version = "4.3.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" +checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" [[package]] name = "async-trait" -version = "0.1.57" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" dependencies = [ "proc-macro2", "quote", @@ -372,7 +382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", - "getrandom 0.2.7", + "getrandom 0.2.6", "instant", "pin-project-lite 0.2.9", "rand 0.8.5", @@ -381,24 +391,24 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.29.0", + "object", "rustc-demangle", ] [[package]] name = "base-x" -version = "0.2.11" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +checksum = "dc19a4937b4fbd3fe3379793130e42060d10627a360f2127802b10b87e7baf74" [[package]] name = "base16ct" @@ -420,9 +430,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "beef" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736" dependencies = [ "serde", ] @@ -546,9 +556,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" dependencies = [ "funty", "radium", @@ -630,7 +640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "block-padding 0.2.1", - "generic-array 0.14.6", + "generic-array 0.14.5", ] [[package]] @@ -639,7 +649,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", ] [[package]] @@ -706,9 +716,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-slice-cast" @@ -730,9 +740,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "bzip2-sys" @@ -753,9 +763,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "camino" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23" dependencies = [ "serde", ] @@ -777,7 +787,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.13", + "semver 1.0.7", "serde", "serde_json", ] @@ -820,9 +830,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chacha20" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" dependencies = [ "cfg-if 1.0.0", "cipher", @@ -832,9 +842,9 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.9.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" dependencies = [ "aead", "chacha20", @@ -845,15 +855,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.20" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6127248204b9aba09a362f6c930ef6a78f2c1b2215f8a7b398c06e1083f17af0" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "js-sys", + "libc", "num-integer", "num-traits", "time", - "wasm-bindgen", "winapi", ] @@ -876,7 +885,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", ] [[package]] @@ -890,9 +899,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.3.3" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21" dependencies = [ "glob", "libc", @@ -1034,9 +1043,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "1.2.4" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" dependencies = [ "cache-padded", ] @@ -1104,18 +1113,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749d0d6022c9038dccf480bdde2a38d435937335bf2bb0f14e815d94517cdce8" +checksum = "7901fbba05decc537080b07cb3f1cadf53be7b7602ca8255786288a8692ae29a" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94370cc7b37bf652ccd8bb8f09bd900997f7ccf97520edfc75554bb5c4abbea" +checksum = "37ba1b45d243a4a28e12d26cd5f2507da74e77c45927d40de8b6ffbf088b46b5" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -1131,33 +1140,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a3cea8fdab90e44018c5b9a1dfd460d8ee265ac354337150222a354628bdb6" +checksum = "54cc30032171bf230ce22b99c07c3a1de1221cb5375bd6dbe6dbe77d0eed743c" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac72f76f2698598951ab26d8c96eaa854810e693e7dd52523958b5909fde6b2" +checksum = "a23f2672426d2bb4c9c3ef53e023076cfc4d8922f0eeaebaf372c92fae8b5c69" [[package]] name = "cranelift-entity" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09eaeacfcd2356fe0e66b295e8f9d59fdd1ac3ace53ba50de14d628ec902f72d" +checksum = "886c59a5e0de1f06dbb7da80db149c75de10d5e2caca07cdd9fef8a5918a6336" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba69c9980d5ffd62c18a2bde927855fcd7c8dc92f29feaf8636052662cbd99c" +checksum = "ace74eeca11c439a9d4ed1a5cb9df31a54cd0f7fbddf82c8ce4ea8e9ad2a8fe0" dependencies = [ "cranelift-codegen", "log", @@ -1167,15 +1176,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2920dc1e05cac40304456ed3301fde2c09bd6a9b0210bcfa2f101398d628d5b" +checksum = "db1ae52a5cc2cad0d86fdd3dcb16b7217d2f1e65ab4f5814aa4f014ad335fa43" [[package]] name = "cranelift-native" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04dfa45f9b2a6f587c564d6b63388e00cd6589d2df6ea2758cf79e1a13285e6" +checksum = "dadcfb7852900780d37102bce5698bcd401736403f07b52e714ff7a180e0e22f" dependencies = [ "cranelift-codegen", "libc", @@ -1184,9 +1193,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.85.3" +version = "0.85.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31a46513ae6f26f3f267d8d75b5373d555fbbd1e68681f348d99df43f747ec54" +checksum = "c84e3410960389110b88f97776f39f6d2c8becdaa4cd59e390e6b76d9d0e7190" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1209,9 +1218,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1219,9 +1228,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -1230,23 +1239,23 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", + "lazy_static", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1254,12 +1263,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if 1.0.0", - "once_cell", + "lazy_static", ] [[package]] @@ -1274,7 +1283,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", "rand_core 0.6.3", "subtle", "zeroize", @@ -1282,11 +1291,11 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", "typenum", ] @@ -1296,7 +1305,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", "subtle", ] @@ -1306,15 +1315,15 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", "subtle", ] [[package]] name = "ctor" -version = "0.1.23" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ "quote", "syn", @@ -2006,7 +2015,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", ] [[package]] @@ -2068,7 +2077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" dependencies = [ "byteorder", - "quick-error", + "quick-error 1.2.3", ] [[package]] @@ -2079,9 +2088,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dtoa" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6053ff46b5639ceb91756a85a4c8914668393a03170efd79c8884a529d80656" +checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" [[package]] name = "dyn-clonable" @@ -2106,9 +2115,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" +checksum = "9d07a982d1fb29db01e5a59b1918e03da4df7297eaeee7686ac45542fd4e59c8" [[package]] name = "ecdsa" @@ -2124,9 +2133,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" dependencies = [ "signature", ] @@ -2147,9 +2156,9 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "elliptic-curve" @@ -2161,7 +2170,7 @@ dependencies = [ "crypto-bigint", "der", "ff", - "generic-array 0.14.6", + "generic-array 0.14.5", "group", "rand_core 0.6.3", "sec1", @@ -2203,9 +2212,9 @@ dependencies = [ [[package]] name = "enumn" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038b1afa59052df211f9efd58f8b1d84c242935ede1c3dbaed26b018a9e06ae2" +checksum = "052bc8773a98bd051ff37db74a8a25f00e6bfa2cbd03373390c72e9f7afbf344" dependencies = [ "proc-macro2", "quote", @@ -2254,9 +2263,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" [[package]] name = "exit-future" @@ -2306,9 +2315,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ "instant", ] @@ -2349,9 +2358,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e" dependencies = [ "rand_core 0.6.3", "subtle", @@ -2376,7 +2385,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2409,17 +2418,19 @@ dependencies = [ [[package]] name = "fixedbitset" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ + "cfg-if 1.0.0", "crc32fast", + "libc", "libz-sys", "miniz_oxide", ] @@ -2881,9 +2892,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -2914,13 +2925,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.10.0+wasi-snapshot-preview1", ] [[package]] @@ -2935,9 +2946,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" dependencies = [ "fallible-iterator", "indexmap", @@ -2952,9 +2963,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" dependencies = [ "aho-corasick", "bstr", @@ -3007,16 +3018,16 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.3.3" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17" +checksum = "99d6a30320f094710245150395bc763ad23128d6a1ebbad7594dc4164b62c56b" dependencies = [ "log", "pest", "pest_derive", + "quick-error 2.0.1", "serde", "serde_json", - "thiserror", ] [[package]] @@ -3045,9 +3056,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" dependencies = [ "ahash", ] @@ -3112,7 +3123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.6", + "generic-array 0.14.5", "hmac 0.8.1", ] @@ -3129,20 +3140,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa 1.0.3", + "itoa 1.0.1", ] [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes", "http", @@ -3169,9 +3180,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", @@ -3182,7 +3193,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.3", + "itoa 1.0.1", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -3229,9 +3240,9 @@ dependencies = [ [[package]] name = "if-watch" -version = "1.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015a7df1eb6dda30df37f34b63ada9b7b352984b0e84de2a20ed526345000791" +checksum = "ae8f4a3c3d4c89351ca83e120c1c00b27df945d38e05695668c9d4b4f7bc52f3" dependencies = [ "async-io", "core-foundation", @@ -3281,7 +3292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown 0.12.0", "serde", ] @@ -3296,9 +3307,9 @@ dependencies = [ [[package]] name = "integer-encoding" -version = "3.0.4" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" +checksum = "0e85a1509a128c855368e135cffcde7eac17d8e1083f41e2b98c58bc1a5074be" [[package]] name = "integer-sqrt" @@ -3362,9 +3373,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "jobserver" @@ -3377,9 +3388,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] @@ -3536,9 +3547,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "kilt-parachain" @@ -3796,9 +3807,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "libloading" @@ -3822,9 +3833,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da83a57f3f5ba3680950aa3cbc806fc297bc0b289d42e8942ed528ace71b8145" +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "libp2p" @@ -3835,7 +3846,7 @@ dependencies = [ "bytes", "futures 0.3.21", "futures-timer", - "getrandom 0.2.7", + "getrandom 0.2.6", "instant", "lazy_static", "libp2p-autonat", @@ -4008,7 +4019,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "lru 0.7.8", + "lru 0.7.7", "prost", "prost-build", "prost-codec", @@ -4358,9 +4369,9 @@ dependencies = [ [[package]] name = "libsecp256k1" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" dependencies = [ "arrayref", "base64", @@ -4406,9 +4417,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.8" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e" dependencies = [ "cc", "pkg-config", @@ -4417,9 +4428,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.6" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "linked_hash_set" @@ -4483,11 +4494,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.8" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +checksum = "c84e6fe5655adc6ce00787cf7dcaf8dc4f998a0565d23eafc207a8b08ca3349a" dependencies = [ - "hashbrown 0.12.3", + "hashbrown 0.11.2", ] [[package]] @@ -4528,6 +4539,12 @@ dependencies = [ "libc", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "mashnet-node" version = "1.7.1" @@ -4666,9 +4683,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memfd" @@ -4690,9 +4707,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.5" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" +checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" dependencies = [ "libc", ] @@ -4713,7 +4730,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" dependencies = [ "hash-db", - "hashbrown 0.12.3", + "hashbrown 0.12.0", "parity-util-mem", ] @@ -4763,23 +4780,34 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", + "miow", + "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", ] [[package]] @@ -4830,7 +4858,7 @@ dependencies = [ "digest 0.10.3", "multihash-derive", "sha2 0.10.2", - "sha3 0.10.2", + "sha3 0.10.1", "unsigned-varint", ] @@ -4878,7 +4906,7 @@ dependencies = [ "matrixmultiply", "nalgebra-macros", "num-complex", - "num-rational 0.4.1", + "num-rational 0.4.0", "num-traits", "rand 0.8.5", "rand_distr", @@ -4926,9 +4954,9 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.12.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +checksum = "733ea73609acfd7fa7ddadfb7bf709b0471668c456ad9513685af543a06342b2" dependencies = [ "anyhow", "bitflags", @@ -4952,24 +4980,23 @@ dependencies = [ [[package]] name = "netlink-proto" -version = "0.10.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +checksum = "ef8785b8141e8432aa45fceb922a7e876d7da3fad37fa7e7ec702ace3aa0826b" dependencies = [ "bytes", "futures 0.3.21", "log", "netlink-packet-core", "netlink-sys", - "thiserror", "tokio", ] [[package]] name = "netlink-sys" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b654097027250401127914afb37cb1f311df6610a9891ff07a757e94199027" +checksum = "3e4c9f9547a08241bee7b6558b9b98e1f290d187de8b7cfca2bbb4937bcaa8f8" dependencies = [ "async-io", "bytes", @@ -4980,13 +5007,15 @@ dependencies = [ [[package]] name = "nix" -version = "0.24.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" +checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" dependencies = [ "bitflags", + "cc", "cfg-if 1.0.0", "libc", + "memoffset", ] [[package]] @@ -5011,6 +5040,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + [[package]] name = "num-bigint" version = "0.2.6" @@ -5024,9 +5062,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" dependencies = [ "num-traits", ] @@ -5043,9 +5081,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg", "num-traits", @@ -5065,9 +5103,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ "autocfg", "num-integer", @@ -5076,9 +5114,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", "libm", @@ -5096,9 +5134,9 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456" dependencies = [ "crc32fast", "hashbrown 0.11.2", @@ -5106,15 +5144,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.13.0" @@ -5180,9 +5209,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.2.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" [[package]] name = "owning_ref" @@ -5445,7 +5474,7 @@ dependencies = [ "rand 0.8.5", "scale-info", "serde", - "sha3 0.10.2", + "sha3 0.10.1", "sp-core", "sp-io", "sp-keystore", @@ -6226,7 +6255,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.12.3", + "hashbrown 0.12.0", "impl-trait-for-tuples", "parity-util-mem-derive", "parking_lot 0.12.1", @@ -6285,7 +6314,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.2", ] [[package]] @@ -6304,22 +6333,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.34.0", ] [[package]] name = "paste" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] name = "pbkdf2" @@ -6433,19 +6462,18 @@ dependencies = [ [[package]] name = "pest" -version = "2.2.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" dependencies = [ - "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.2.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" dependencies = [ "pest", "pest_generator", @@ -6453,9 +6481,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.2.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", @@ -6466,20 +6494,20 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.2.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" dependencies = [ - "once_cell", + "maplit", "pest", - "sha-1 0.10.0", + "sha-1 0.8.2", ] [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" dependencies = [ "fixedbitset", "indexmap", @@ -6487,18 +6515,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -6572,7 +6600,7 @@ dependencies = [ "derive_more", "fatality", "futures 0.3.21", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6594,7 +6622,7 @@ source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.27#b017 dependencies = [ "fatality", "futures 0.3.21", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6716,7 +6744,7 @@ dependencies = [ "derive_more", "fatality", "futures 0.3.21", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6816,7 +6844,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "kvdb", - "lru 0.7.8", + "lru 0.7.7", "merlin", "parity-scale-codec", "polkadot-node-jaeger", @@ -6947,7 +6975,7 @@ dependencies = [ "fatality", "futures 0.3.21", "kvdb", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -7181,7 +7209,7 @@ dependencies = [ "futures 0.3.21", "itertools", "kvdb", - "lru 0.7.8", + "lru 0.7.7", "parity-db", "parity-scale-codec", "parity-util-mem", @@ -7211,7 +7239,7 @@ dependencies = [ "async-trait", "futures 0.3.21", "futures-timer", - "lru 0.7.8", + "lru 0.7.7", "orchestra", "parity-util-mem", "parking_lot 0.12.1", @@ -7533,7 +7561,7 @@ dependencies = [ "kusama-runtime", "kvdb", "kvdb-rocksdb", - "lru 0.7.8", + "lru 0.7.7", "pallet-babe", "pallet-im-online", "pallet-staking", @@ -7725,11 +7753,10 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.2.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d50bfb8c23f23915855a00d98b5a35ef2e0b871bb52937bacadb798fbb66c8" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ - "once_cell", "thiserror", "toml", ] @@ -7769,15 +7796,15 @@ dependencies = [ [[package]] name = "prometheus" -version = "0.13.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cface98dfa6d645ea4c789839f176e4b072265d085bfcc48eaa8d137f58d3c39" +checksum = "b7f64969ffd5dd8f39bd57a68ac53c163a095ed9d0fb707146da1b27025a3504" dependencies = [ "cfg-if 1.0.0", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot 0.11.2", "thiserror", ] @@ -7788,7 +7815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1abe0255c04d15f571427a2d1e00099016506cf3297b53853acd2b7eb87825" dependencies = [ "dtoa", - "itoa 1.0.3", + "itoa 1.0.1", "owning_ref", "prometheus-client-derive-text-encode", ] @@ -7874,9 +7901,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.20" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f446d0a6efba22928558c4fb4ce0b3fd6c89b0061343e390bf01a703742b8125" +checksum = "871372391786ccec00d3c5d3d6608905b3d4db263639cfe075d3b60a736d115a" dependencies = [ "cc", ] @@ -7887,6 +7914,12 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quicksink" version = "0.1.2" @@ -7900,9 +7933,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ "proc-macro2", ] @@ -7973,7 +8006,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", ] [[package]] @@ -8021,9 +8054,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.5.3" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" dependencies = [ "autocfg", "crossbeam-deque", @@ -8033,9 +8066,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -8045,9 +8078,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] @@ -8058,7 +8091,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", "redox_syscall", "thiserror", ] @@ -8078,18 +8111,18 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed13bcd201494ab44900a96490291651d200730904221832b9547d24a87d332b" +checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5234cd6063258a5e32903b53b1b6ac043a0541c8adc1f610f67b0326c7a578fa" +checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" dependencies = [ "proc-macro2", "quote", @@ -8110,9 +8143,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -8130,9 +8163,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "region" @@ -8179,14 +8212,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ "hostname", - "quick-error", + "quick-error 1.2.3", ] [[package]] name = "retain_mut" -version = "0.1.9" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" +checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086" [[package]] name = "rfc6979" @@ -8317,9 +8350,9 @@ dependencies = [ [[package]] name = "rtnetlink" -version = "0.10.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +checksum = "6f54290e54521dac3de4149d83ddf9f62a359b3cc93bcb494a794a41e6f4744b" dependencies = [ "async-global-executor", "futures 0.3.21", @@ -8391,7 +8424,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.13", + "semver 1.0.7", ] [[package]] @@ -8419,14 +8452,14 @@ dependencies = [ "io-lifetimes 0.7.2", "libc", "linux-raw-sys 0.0.46", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] name = "rustls" -version = "0.20.6" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" dependencies = [ "log", "ring", @@ -8448,18 +8481,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" dependencies = [ "base64", ] [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "rw-stream-sink" @@ -8474,9 +8507,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "safe-mix" @@ -8588,7 +8621,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#8eff668a42325aeb4433eace1604f4d286a6ec05" dependencies = [ "impl-trait-for-tuples", - "memmap2 0.5.5", + "memmap2 0.5.3", "parity-scale-codec", "sc-chain-spec-derive", "sc-network", @@ -8875,7 +8908,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#8eff668a42325aeb4433eace1604f4d286a6ec05" dependencies = [ "lazy_static", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "parking_lot 0.12.1", "sc-executor-common", @@ -9063,7 +9096,7 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "parking_lot 0.12.1", "pin-project", @@ -9119,7 +9152,7 @@ dependencies = [ "futures-timer", "libp2p", "log", - "lru 0.7.8", + "lru 0.7.7", "sc-network", "sp-runtime", "substrate-prometheus-endpoint", @@ -9155,7 +9188,7 @@ dependencies = [ "futures 0.3.21", "libp2p", "log", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "prost", "prost-build", @@ -9549,12 +9582,12 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "windows-sys", + "winapi", ] [[package]] @@ -9598,7 +9631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ "der", - "generic-array 0.14.6", + "generic-array 0.14.5", "subtle", "zeroize", ] @@ -9673,9 +9706,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" dependencies = [ "serde", ] @@ -9688,18 +9721,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" +checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e" +checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" dependencies = [ "proc-macro2", "quote", @@ -9712,7 +9745,7 @@ version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" dependencies = [ - "itoa 1.0.3", + "itoa 1.0.1", "ryu", "serde", ] @@ -9728,26 +9761,27 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.8" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.0", + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", ] [[package]] name = "sha-1" -version = "0.10.0" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -9800,9 +9834,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a31480366ec990f395a61b7c08122d99bd40544fdb5abcfc1b06bb29994312c" +checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86" dependencies = [ "digest 0.10.3", "keccak", @@ -9825,9 +9859,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" dependencies = [ "libc", "signal-hook-registry", @@ -9866,12 +9900,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" -dependencies = [ - "autocfg", -] +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "slice-group-by" @@ -9902,9 +9933,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "snap" @@ -10056,7 +10087,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#8e dependencies = [ "futures 0.3.21", "log", - "lru 0.7.8", + "lru 0.7.7", "parity-scale-codec", "parking_lot 0.12.1", "sp-api", @@ -10209,7 +10240,7 @@ dependencies = [ "byteorder", "digest 0.10.3", "sha2 0.10.2", - "sha3 0.10.2", + "sha3 0.10.1", "sp-std", "twox-hash", ] @@ -10757,9 +10788,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.25.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a039906277e0d8db996cd9d1ef19278c10209d994ecfc1025ced16342873a17c" +checksum = "5d804c8d48aeab838be31570866fce1130d275b563d49af08b4927a0bd561e7c" dependencies = [ "Inflector", "num-format", @@ -10837,9 +10868,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.24.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b" +checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" dependencies = [ "heck", "proc-macro2", @@ -10949,9 +10980,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ "proc-macro2", "quote", @@ -10999,9 +11030,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.4" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" [[package]] name = "tempfile" @@ -11034,18 +11065,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", @@ -11168,9 +11199,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -11179,9 +11210,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" dependencies = [ "rustls", "tokio", @@ -11201,9 +11232,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" dependencies = [ "bytes", "futures-core", @@ -11225,15 +11256,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if 1.0.0", "pin-project-lite 0.2.9", @@ -11243,9 +11274,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", "quote", @@ -11346,7 +11377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" dependencies = [ "hash-db", - "hashbrown 0.12.3", + "hashbrown 0.12.0", "log", "rustc-hex", "smallvec", @@ -11461,9 +11492,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.4" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "uint" @@ -11494,15 +11525,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] @@ -11515,9 +11546,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "universal-hash" @@ -11525,7 +11556,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.5", "subtle", ] @@ -11640,9 +11671,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -11650,13 +11681,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", + "lazy_static", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -11665,9 +11696,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -11677,9 +11708,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11687,9 +11718,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", "quote", @@ -11700,9 +11731,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "wasm-gc-api" @@ -11775,9 +11806,9 @@ dependencies = [ [[package]] name = "wasmtime" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f50eadf868ab6a04b7b511460233377d0bfbb92e417b2f6a98b98fef2e098f5" +checksum = "e76e2b2833bb0ece666ccdbed7b71b617d447da11f1bb61f4f2bab2648f745ee" dependencies = [ "anyhow", "backtrace", @@ -11787,7 +11818,7 @@ dependencies = [ "lazy_static", "libc", "log", - "object 0.28.4", + "object", "once_cell", "paste", "psm", @@ -11806,9 +11837,9 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1df23c642e1376892f3b72f311596976979cbf8b85469680cdd3a8a063d12a2" +checksum = "743a9f142d93318262d7e1fe329394ff2e8f86a1df45ae5e4f0eedba215ca5ce" dependencies = [ "anyhow", "base64", @@ -11826,9 +11857,9 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f264ff6b4df247d15584f2f53d009fbc90032cfdc2605b52b961bffc71b6eccd" +checksum = "5dc0f80afa1ce97083a7168e6b6948d015d6237369e9f4a511d38c9c4ac8fbb9" dependencies = [ "anyhow", "cranelift-codegen", @@ -11839,7 +11870,7 @@ dependencies = [ "gimli", "log", "more-asserts", - "object 0.28.4", + "object", "target-lexicon", "thiserror", "wasmparser", @@ -11848,9 +11879,9 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839d2820e4b830f4b9e7aa08d4c0acabf4a5036105d639f6dfa1c6891c73bdc6" +checksum = "0816d9365196f1f447060087e0f87239ccded830bd54970a1168b0c9c8e824c9" dependencies = [ "anyhow", "cranelift-entity", @@ -11858,7 +11889,7 @@ dependencies = [ "indexmap", "log", "more-asserts", - "object 0.28.4", + "object", "serde", "target-lexicon", "thiserror", @@ -11868,9 +11899,9 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0a0bcbfa18b946d890078ba0e1bc76bcc53eccfb40806c0020ec29dcd1bd49" +checksum = "5c687f33cfa0f89ec1646929d0ff102087052cf9f0d15533de56526b0da0d1b3" dependencies = [ "addr2line", "anyhow", @@ -11879,7 +11910,7 @@ dependencies = [ "cpp_demangle", "gimli", "log", - "object 0.28.4", + "object", "region", "rustc-demangle", "rustix 0.33.7", @@ -11894,20 +11925,20 @@ dependencies = [ [[package]] name = "wasmtime-jit-debug" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4779d976206c458edd643d1ac622b6c37e4a0800a8b1d25dfbf245ac2f2cac" +checksum = "b252d1d025f94f3954ba2111f12f3a22826a0764a11c150c2d46623115a69e27" dependencies = [ "lazy_static", - "object 0.28.4", + "object", "rustix 0.33.7", ] [[package]] name = "wasmtime-runtime" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7eb6ffa169eb5dcd18ac9473c817358cd57bc62c244622210566d473397954a" +checksum = "ace251693103c9facbbd7df87a29a75e68016e48bc83c09133f2fda6b575e0ab" dependencies = [ "anyhow", "backtrace", @@ -11931,9 +11962,9 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "0.38.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d932b0ac5336f7308d869703dd225610a6a3aeaa8e968c52b43eed96cefb1c2" +checksum = "d129b0487a95986692af8708ffde9c50b0568dcefd79200941d475713b4f40bb" dependencies = [ "cranelift-entity", "serde", @@ -11943,9 +11974,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", @@ -11963,9 +11994,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.4" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" dependencies = [ "webpki", ] @@ -12130,9 +12161,22 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac7fef12f4b59cd0a29339406cc9203ab44e440ddff6b3f5a41455349fa9cf3" +dependencies = [ + "windows_aarch64_msvc 0.29.0", + "windows_i686_gnu 0.29.0", + "windows_i686_msvc 0.29.0", + "windows_x86_64_gnu 0.29.0", + "windows_x86_64_msvc 0.29.0", +] + +[[package]] +name = "windows-sys" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" dependencies = [ "windows_aarch64_msvc 0.34.0", "windows_i686_gnu 0.34.0", @@ -12154,6 +12198,12 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows_aarch64_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d027175d00b01e0cbeb97d6ab6ebe03b12330a35786cbaca5252b1c4bf5d9b" + [[package]] name = "windows_aarch64_msvc" version = "0.34.0" @@ -12166,6 +12216,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_i686_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8793f59f7b8e8b01eda1a652b2697d87b93097198ae85f823b969ca5b89bba58" + [[package]] name = "windows_i686_gnu" version = "0.34.0" @@ -12178,6 +12234,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8602f6c418b67024be2996c512f5f995de3ba417f4c75af68401ab8756796ae4" + [[package]] name = "windows_i686_msvc" version = "0.34.0" @@ -12190,6 +12252,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_x86_64_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d615f419543e0bd7d2b3323af0d86ff19cbc4f816e6453f36a2c2ce889c354" + [[package]] name = "windows_x86_64_gnu" version = "0.34.0" @@ -12202,6 +12270,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d95421d9ed3672c280884da53201a5c46b7b2765ca6faf34b0d71cf34a3561" + [[package]] name = "windows_x86_64_msvc" version = "0.34.0" @@ -12308,9 +12382,9 @@ dependencies = [ [[package]] name = "yamux" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" +checksum = "0c0608f53c1dc0bad505d03a34bbd49fbf2ad7b51eb036123e896365532745a1" dependencies = [ "futures 0.3.21", "log", @@ -12322,9 +12396,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.7" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" dependencies = [ "zeroize_derive", ] diff --git a/Dockerfile b/Dockerfile index db98a52b8b..e7b2593d64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ # pinned the version to avoid build cache invalidation # Corresponds to paritytech/ci-linux:production at the time of this PR -# https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6?context=explore -FROM paritytech/ci-linux@sha256:3e13ead5d3a2aaca0ea5ffc8fedeef05f0ac9efe325c77b8b06d208d3c7e8ee6 as builder +# https://hub.docker.com/layers/ci-linux/paritytech/ci-linux/production/images/sha256-4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e?context=explore +FROM paritytech/ci-linux@sha256:4e8c072ea12bc17d99cb531adb58dea5a4c7d4880a8a86525052d24d1454e89e as builder WORKDIR /build From e70c044c02fb3c591c4cda5580dc4156920d83e0 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 8 Sep 2022 10:58:29 +0200 Subject: [PATCH 17/34] feat: add staking rewards runtime api --- Cargo.lock | 1 + pallets/parachain-staking/Cargo.toml | 2 ++ pallets/parachain-staking/src/runtime_api.rs | 30 ++++++++++++++++++++ runtimes/peregrine/src/lib.rs | 6 ++++ runtimes/spiritnet/src/lib.rs | 6 ++++ 5 files changed, 45 insertions(+) create mode 100644 pallets/parachain-staking/src/runtime_api.rs diff --git a/Cargo.lock b/Cargo.lock index 13e2925ab2..5794800a4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6261,6 +6261,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", + "sp-api", "sp-consensus-aura", "sp-core", "sp-io", diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml index 73aff71aaa..7d61bc5d02 100644 --- a/pallets/parachain-staking/Cargo.toml +++ b/pallets/parachain-staking/Cargo.toml @@ -17,6 +17,7 @@ log = "0.4.17" parity-scale-codec = {version = "3.1.5", default-features = false, features = ["derive"]} scale-info = {version = "2.1.1", default-features = false, features = ["derive"]} serde = {version = "1.0.142", optional = true} +sp-api = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false} frame-support = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false} frame-system = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false} @@ -47,6 +48,7 @@ std = [ "parity-scale-codec/std", "scale-info/std", "serde", + "sp-api/std", "sp-runtime/std", "sp-staking/std", "sp-std/std", diff --git a/pallets/parachain-staking/src/runtime_api.rs b/pallets/parachain-staking/src/runtime_api.rs new file mode 100644 index 0000000000..fcee95a35f --- /dev/null +++ b/pallets/parachain-staking/src/runtime_api.rs @@ -0,0 +1,30 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2022 BOTLabs GmbH + +// The KILT Blockchain is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The KILT Blockchain is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +use frame_support::dispatch::fmt::Debug; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; + +sp_api::decl_runtime_apis! { + pub trait GetStakingRewards + where + AccountId: Eq + PartialEq + Debug + Encode + Decode + Clone, + Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq + { + fn get_staking_rewards(account: &AccountId) -> Balance; + } +} diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index 9ac359a6e9..c3ed25ce03 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -1234,6 +1234,12 @@ impl_runtime_apis! { } } + impl parachain_staking::runtime_api::GetStakingRewards for Runtime { + fn get_staking_rewards(account: &AccountId) -> Balance { + ParachainStaking::get_staking_rewards(account) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index 75805f589c..e667537209 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -1226,6 +1226,12 @@ impl_runtime_apis! { } } + impl parachain_staking::runtime_api::GetStakingRewards for Runtime { + fn get_staking_rewards(account: &AccountId) -> Balance { + ParachainStaking::get_staking_rewards(account) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( From b1de42aba1e56d6247d5c0576ccf096f16bbcd99 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 8 Sep 2022 10:58:57 +0200 Subject: [PATCH 18/34] docs: add new extrinsics to staking header --- pallets/parachain-staking/src/lib.rs | 39 +++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 8bbb760bdf..3c120ec4dc 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -139,12 +139,21 @@ //! - `unlock_unstaked` - Attempt to unlock previously unstaked balance from any //! account. Succeeds if at least one unstake call happened at least //! `StakeDuration` blocks ago. +//! - `claim_rewards_for` - Claim block authoring rewards for the target +//! address. +//! - `increment_collator_rewards` - Actively increment the rewards of a +//! collator and their delegators. +//! - `increment_delegator_rewards`- Actively increment the rewards of a +//! delegator for all their delegations. +//! - `execute_scheduled_reward_change` - Executes the annual reduction of the +//! reward rates for collators anddelegators. Moreover, sets rewards for all +//! collators and delegators before adjusting the inflation. //! //! ## Genesis config //! //! The ParachainStaking pallet depends on the [`GenesisConfig`]. //! -//! ## Assumptions+ +//! ## Assumptions //! //! - At the start of session s(i), the set of session ids for session s(i+1) //! are chosen. These equal the set of selected candidates. Thus, we cannot @@ -156,6 +165,7 @@ #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; pub mod default_weights; +pub mod runtime_api; #[cfg(test)] pub(crate) mod mock; @@ -2426,6 +2436,33 @@ pub mod pallet { .compute_reward::(stake, staking_rate, multiplier) } + /// Calculates the staking rewards for a given account address. + /// + /// At least used in Runtime API. + pub fn get_staking_rewards(acc: &T::AccountId) -> BalanceOf { + let r_count = RewardCount::::get(acc); + let rewards = Rewards::::get(acc); + + // exit early + if r_count.is_zero() && rewards.is_zero() { + return BalanceOf::::zero(); + } + + if Self::is_active_candidate(acc).is_some() { + let stake = CandidatePool::::get(acc) + .map(|state| state.stake) + .unwrap_or(BalanceOf::::zero()); + rewards.saturating_add(Self::calc_block_rewards_collator(stake, r_count.into())) + } else if Self::is_delegator(acc) { + let stake = DelegatorState::::get(acc) + .map(|state| state.amount) + .unwrap_or(BalanceOf::::zero()); + rewards.saturating_add(Self::calc_block_rewards_collator(stake, r_count.into())) + } else { + BalanceOf::::zero() + } + } + /// Increment the accumulated rewards of a collator by consuming their /// current rewards counter. /// From 6f732963fabdce3408d75bd73fb5394fd3e3a8cc Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 8 Sep 2022 18:24:24 +0200 Subject: [PATCH 19/34] feat: add staking rates api --- pallets/parachain-staking/src/lib.rs | 60 ++++++++++++++------ pallets/parachain-staking/src/runtime_api.rs | 16 +++++- runtimes/peregrine/src/lib.rs | 10 +++- runtimes/spiritnet/src/lib.rs | 10 +++- 4 files changed, 74 insertions(+), 22 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 3c120ec4dc..45545a54a9 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -551,7 +551,7 @@ pub mod pallet { // check for network reward and mint // on success, mint each block if now > T::NetworkRewardStart::get() { - T::NetworkRewardBeneficiary::on_unbalanced(Self::get_network_reward()); + T::NetworkRewardBeneficiary::on_unbalanced(Self::issue_network_reward()); post_weight = post_weight.saturating_add(::WeightInfo::on_initialize_network_rewards()); } post_weight @@ -2390,7 +2390,7 @@ pub mod pallet { /// /// `col_reward_rate_per_block * col_max_stake * max_num_of_collators * /// NetworkRewardRate` - fn get_network_reward() -> NegativeImbalanceOf { + fn issue_network_reward() -> NegativeImbalanceOf { // Multiplication with Perquintill cannot overflow let max_col_rewards = InflationConfig::::get().collator.reward_rate.per_block * MaxCollatorCandidateStake::::get() @@ -2439,25 +2439,24 @@ pub mod pallet { /// Calculates the staking rewards for a given account address. /// /// At least used in Runtime API. - pub fn get_staking_rewards(acc: &T::AccountId) -> BalanceOf { - let r_count = RewardCount::::get(acc); + pub fn get_unclaimed_staking_rewards(acc: &T::AccountId) -> BalanceOf { + let mut reward_count = RewardCount::::get(acc); let rewards = Rewards::::get(acc); - // exit early - if r_count.is_zero() && rewards.is_zero() { - return BalanceOf::::zero(); - } - - if Self::is_active_candidate(acc).is_some() { - let stake = CandidatePool::::get(acc) - .map(|state| state.stake) - .unwrap_or(BalanceOf::::zero()); - rewards.saturating_add(Self::calc_block_rewards_collator(stake, r_count.into())) - } else if Self::is_delegator(acc) { + if let Some(delegator_state) = DelegatorState::::get(acc) { + // delegator reward count does not automatically inrement in order to be + // scalable + reward_count = + reward_count.saturating_add(delegator_state.owner.map(RewardCount::::get).unwrap_or(0u32)); let stake = DelegatorState::::get(acc) .map(|state| state.amount) - .unwrap_or(BalanceOf::::zero()); - rewards.saturating_add(Self::calc_block_rewards_collator(stake, r_count.into())) + .unwrap_or_else(BalanceOf::::zero); + rewards.saturating_add(Self::calc_block_rewards_delegator(stake, reward_count.into())) + } else if Self::is_active_candidate(acc).is_some() { + let stake = CandidatePool::::get(acc) + .map(|state| state.stake) + .unwrap_or_else(BalanceOf::::zero); + rewards.saturating_add(Self::calc_block_rewards_collator(stake, reward_count.into())) } else { BalanceOf::::zero() } @@ -2523,6 +2522,33 @@ pub mod pallet { T::DbWeight::get().reads(2) } } + + /// Calculates the current staking and reward rates for collators and + /// delegators. + /// + /// At least used in Runtime API. + pub fn get_staking_rates() -> runtime_api::StakingRates { + let total_issuance = T::Currency::total_issuance(); + let total_stake = >::get(); + let inflation_config = InflationConfig::::get(); + let collator_staking_rate = Perquintill::from_rational(total_stake.collators, total_issuance); + let delegator_staking_rate = Perquintill::from_rational(total_stake.delegators, total_issuance); + let collator_reward_rate = Perquintill::from_rational( + inflation_config.collator.max_rate.deconstruct(), + collator_staking_rate.deconstruct(), + ) * inflation_config.collator.reward_rate.annual; + let delegator_reward_rate = Perquintill::from_rational( + inflation_config.delegator.max_rate.deconstruct(), + delegator_staking_rate.deconstruct(), + ) * inflation_config.delegator.reward_rate.annual; + + runtime_api::StakingRates { + collator_staking_rate, + collator_reward_rate, + delegator_staking_rate, + delegator_reward_rate, + } + } } impl pallet_authorship::EventHandler for Pallet diff --git a/pallets/parachain-staking/src/runtime_api.rs b/pallets/parachain-staking/src/runtime_api.rs index fcee95a35f..62ac3b341d 100644 --- a/pallets/parachain-staking/src/runtime_api.rs +++ b/pallets/parachain-staking/src/runtime_api.rs @@ -18,6 +18,16 @@ use frame_support::dispatch::fmt::Debug; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::Perquintill; + +#[derive(Decode, Encode, TypeInfo, MaxEncodedLen, PartialEq, Eq, Debug)] +pub struct StakingRates { + pub collator_staking_rate: Perquintill, + pub collator_reward_rate: Perquintill, + pub delegator_staking_rate: Perquintill, + pub delegator_reward_rate: Perquintill, +} sp_api::decl_runtime_apis! { pub trait GetStakingRewards @@ -25,6 +35,10 @@ sp_api::decl_runtime_apis! { AccountId: Eq + PartialEq + Debug + Encode + Decode + Clone, Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq { - fn get_staking_rewards(account: &AccountId) -> Balance; + fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance; + } + + pub trait GetStakingRates { + fn get_staking_rates() -> StakingRates; } } diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index c3ed25ce03..c783d067fd 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -1235,8 +1235,14 @@ impl_runtime_apis! { } impl parachain_staking::runtime_api::GetStakingRewards for Runtime { - fn get_staking_rewards(account: &AccountId) -> Balance { - ParachainStaking::get_staking_rewards(account) + fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance { + ParachainStaking::get_unclaimed_staking_rewards(account) + } + } + + impl parachain_staking::runtime_api::GetStakingRates for Runtime { + fn get_staking_rates() -> parachain_staking::runtime_api::StakingRates { + ParachainStaking::get_staking_rates() } } diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index e667537209..be5e2cbb81 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -1227,8 +1227,14 @@ impl_runtime_apis! { } impl parachain_staking::runtime_api::GetStakingRewards for Runtime { - fn get_staking_rewards(account: &AccountId) -> Balance { - ParachainStaking::get_staking_rewards(account) + fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance { + ParachainStaking::get_unclaimed_staking_rewards(account) + } + } + + impl parachain_staking::runtime_api::GetStakingRates for Runtime { + fn get_staking_rates() -> parachain_staking::runtime_api::StakingRates { + ParachainStaking::get_staking_rates() } } From 20fd5231ff1a6bffd260aef53b9d06f43176c225 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 8 Sep 2022 18:24:32 +0200 Subject: [PATCH 20/34] tests: add api --- pallets/parachain-staking/src/tests.rs | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 1103914d65..273d29368c 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -35,6 +35,7 @@ use crate::{ Event as MetaEvent, ExtBuilder, Origin, Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, TREASURY_ACC, }, + runtime_api::StakingRates, set::OrderedSet, types::{ BalanceOf, Candidate, CandidateStatus, DelegationCounter, Delegator, RoundInfo, Stake, StakeOf, TotalStake, @@ -4267,3 +4268,72 @@ fn rewards_incrementing_and_claiming() { ); }); } + +#[test] +fn api_get_unclaimed_staking_rewards() { + let stake = 100_000 * DECIMALS; + ExtBuilder::default() + .with_balances(vec![(1, stake), (2, stake), (3, 100 * stake)]) + .with_collators(vec![(1, stake), (3, 2 * stake)]) + .with_delegators(vec![(2, 1, stake)]) + .build() + .execute_with(|| { + let inflation_config = StakePallet::inflation_config(); + + // Increment rewards of 1 and 2 + roll_to(2, vec![None, Some(1)]); + assert_eq!( + StakePallet::get_unclaimed_staking_rewards(&1), + // Multiplying with 2 because there are two authors + inflation_config.collator.reward_rate.per_block * stake * 2 + ); + assert_eq!( + StakePallet::get_unclaimed_staking_rewards(&2), + inflation_config.delegator.reward_rate.per_block * stake * 2 + ); + assert!(StakePallet::get_unclaimed_staking_rewards(&3).is_zero()); + + // Should only increment rewards of 3 + roll_to(3, vec![None, None, Some(3)]); + assert_eq!( + 2 * StakePallet::get_unclaimed_staking_rewards(&1), + StakePallet::get_unclaimed_staking_rewards(&3), + ); + assert_eq!( + StakePallet::get_unclaimed_staking_rewards(&2), + inflation_config.delegator.reward_rate.per_block * stake * 2 + ); + }); +} + +#[test] +fn api_get_staking_rates() { + let stake = 100_000 * DECIMALS; + ExtBuilder::default() + .with_balances(vec![(1, stake), (2, stake), (3, 2 * stake)]) + .with_collators(vec![(1, stake), (2, stake)]) + .with_delegators(vec![(3, 1, stake)]) + .with_inflation(25, 10, 25, 8, ::BLOCKS_PER_YEAR) + .build() + .execute_with(|| { + let mut rates = StakingRates { + collator_staking_rate: Perquintill::from_percent(50), + collator_reward_rate: Perquintill::from_percent(5), + delegator_staking_rate: Perquintill::from_percent(25), + delegator_reward_rate: Perquintill::from_percent(8), + }; + // collators exceed max staking rate + assert_eq!(rates, StakePallet::get_staking_rates()); + + // candidates stake less to not exceed max staking rate + assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), stake / 2)); + assert_ok!(StakePallet::candidate_stake_less(Origin::signed(2), stake / 2)); + // delegator stakes more to exceed + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, stake)); + rates.collator_staking_rate = Perquintill::from_percent(25); + rates.collator_reward_rate = Perquintill::from_percent(10); + rates.delegator_staking_rate = Perquintill::from_percent(50); + rates.delegator_reward_rate = Perquintill::from_percent(4); + assert_eq!(rates, StakePallet::get_staking_rates()); + }); +} From 0f8160b18cb3a205824a805cc08cee2a339e69d1 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Fri, 9 Sep 2022 16:21:58 +0200 Subject: [PATCH 21/34] fix: unify staking runtime api --- pallets/parachain-staking/src/runtime_api.rs | 6 ++---- runtimes/peregrine/src/lib.rs | 4 +--- runtimes/spiritnet/src/lib.rs | 4 +--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/pallets/parachain-staking/src/runtime_api.rs b/pallets/parachain-staking/src/runtime_api.rs index 62ac3b341d..ca4b2b305e 100644 --- a/pallets/parachain-staking/src/runtime_api.rs +++ b/pallets/parachain-staking/src/runtime_api.rs @@ -15,6 +15,7 @@ // along with this program. If not, see . // If you feel like getting in touch with us, you can do so at info@botlabs.org +#![cfg_attr(not(feature = "std"), no_std)] use frame_support::dispatch::fmt::Debug; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -30,15 +31,12 @@ pub struct StakingRates { } sp_api::decl_runtime_apis! { - pub trait GetStakingRewards + pub trait ParachainStakingApi where AccountId: Eq + PartialEq + Debug + Encode + Decode + Clone, Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq { fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance; - } - - pub trait GetStakingRates { fn get_staking_rates() -> StakingRates; } } diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index c783d067fd..74856ad8d4 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -1234,13 +1234,11 @@ impl_runtime_apis! { } } - impl parachain_staking::runtime_api::GetStakingRewards for Runtime { + impl parachain_staking::runtime_api::ParachainStakingApi for Runtime { fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance { ParachainStaking::get_unclaimed_staking_rewards(account) } - } - impl parachain_staking::runtime_api::GetStakingRates for Runtime { fn get_staking_rates() -> parachain_staking::runtime_api::StakingRates { ParachainStaking::get_staking_rates() } diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index be5e2cbb81..f416e19238 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -1226,13 +1226,11 @@ impl_runtime_apis! { } } - impl parachain_staking::runtime_api::GetStakingRewards for Runtime { + impl parachain_staking::runtime_api::ParachainStakingApi for Runtime { fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance { ParachainStaking::get_unclaimed_staking_rewards(account) } - } - impl parachain_staking::runtime_api::GetStakingRates for Runtime { fn get_staking_rates() -> parachain_staking::runtime_api::StakingRates { ParachainStaking::get_staking_rates() } From 420170d387972e64c0e0c50997f8ca1110cac9f4 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 15 Sep 2022 11:16:53 +0200 Subject: [PATCH 22/34] refactor: stricter claiming --- pallets/parachain-staking/src/benchmarking.rs | 12 +++++++----- pallets/parachain-staking/src/default_weights.rs | 6 +++--- pallets/parachain-staking/src/lib.rs | 10 ++++------ pallets/parachain-staking/src/mock.rs | 4 ++-- pallets/parachain-staking/src/tests.rs | 8 ++++---- runtimes/peregrine/src/weights/parachain_staking.rs | 2 +- runtimes/spiritnet/src/weights/parachain_staking.rs | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 39014ff98e..b407ce0dcb 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -558,7 +558,8 @@ benchmarks! { RewardCount::::insert(&collator, u32::MAX); assert!(Rewards::::get(&delegator).is_zero()); - }: _(RawOrigin::Signed(delegator.clone())) + let origin = RawOrigin::Signed(delegator.clone()); + }: _(origin) verify { assert!(!Rewards::::get(&delegator).is_zero()); } @@ -572,19 +573,20 @@ benchmarks! { // mock high counter to compensate for tiny amounts in unit test env RewardCount::::insert(&collator, u32::MAX); assert!(Rewards::::get(&collator).is_zero(), "reward {:?}", Rewards::::get(&collator)); - }: _(RawOrigin::Signed(collator.clone())) + let origin = RawOrigin::Signed(collator.clone()); + }: _(origin) verify { assert!(!Rewards::::get(&collator).is_zero()); } - claim_rewards_for { + claim_rewards { let beneficiary = account("beneficiary", 0, 0); let amount = T::MinCollatorCandidateStake::get(); T::Currency::make_free_balance_be(&beneficiary, amount); Rewards::::insert(&beneficiary, amount); assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), amount.into()); - let unlookup_beneficiary = T::Lookup::unlookup(beneficiary.clone()); - }: _(RawOrigin::Signed(beneficiary.clone()), unlookup_beneficiary) + let origin = RawOrigin::Signed(beneficiary.clone()); + }: _(origin) verify { assert!(Rewards::::get(&beneficiary).is_zero()); assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), (amount + amount).into()); diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs index f458dc9586..b78dc2e517 100644 --- a/pallets/parachain-staking/src/default_weights.rs +++ b/pallets/parachain-staking/src/default_weights.rs @@ -68,7 +68,7 @@ pub trait WeightInfo { fn set_max_candidate_stake() -> Weight; fn increment_delegator_rewards() -> Weight; fn increment_collator_rewards(_m: u32, ) -> Weight; - fn claim_rewards_for() -> Weight; + fn claim_rewards() -> Weight; fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight; } @@ -407,7 +407,7 @@ impl WeightInfo for SubstrateWeight { } // Storage: ParachainStaking Rewards (r:1 w:1) // Storage: System Account (r:1 w:1) - fn claim_rewards_for() -> Weight { + fn claim_rewards() -> Weight { (29_833_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -768,7 +768,7 @@ impl WeightInfo for () { } // Storage: ParachainStaking Rewards (r:1 w:1) // Storage: System Account (r:1 w:1) - fn claim_rewards_for() -> Weight { + fn claim_rewards() -> Weight { (29_833_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 45545a54a9..ff05d95f38 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -139,8 +139,7 @@ //! - `unlock_unstaked` - Attempt to unlock previously unstaked balance from any //! account. Succeeds if at least one unstake call happened at least //! `StakeDuration` blocks ago. -//! - `claim_rewards_for` - Claim block authoring rewards for the target -//! address. +//! - `claim_rewards` - Claim block authoring rewards for the calling origin. //! - `increment_collator_rewards` - Actively increment the rewards of a //! collator and their delegators. //! - `increment_delegator_rewards`- Actively increment the rewards of a @@ -1730,10 +1729,9 @@ pub mod pallet { /// for anyone. /// /// Emits `Rewarded`. - #[pallet::weight(::WeightInfo::claim_rewards_for())] - pub fn claim_rewards_for(origin: OriginFor, target: ::Source) -> DispatchResult { - ensure_signed(origin)?; - let target = T::Lookup::lookup(target)?; + #[pallet::weight(::WeightInfo::claim_rewards())] + pub fn claim_rewards(origin: OriginFor) -> DispatchResult { + let target = ensure_signed(origin)?; // we could kill the storage entry but let's be safe in case the deposit fails let rewards = Rewards::::get(&target); diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index eaab0cd281..3b8f88cb08 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -391,14 +391,14 @@ pub(crate) fn roll_to_claim_rewards(n: BlockNumber, authors: Vec>::on_finalize(System::block_number()); diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 273d29368c..c708e16356 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -4203,7 +4203,7 @@ fn rewards_incrementing_and_claiming() { ); (1..=3).for_each(|id| { assert_noop!( - StakePallet::claim_rewards_for(Origin::signed(id), id), + StakePallet::claim_rewards(Origin::signed(id)), Error::::RewardsNotFound, ); }); @@ -4216,7 +4216,7 @@ fn rewards_incrementing_and_claiming() { // claiming should not be possible before incrementing rewards (1..=3).for_each(|id| { assert_noop!( - StakePallet::claim_rewards_for(Origin::signed(id), id), + StakePallet::claim_rewards(Origin::signed(id)), Error::::RewardsNotFound ); }); @@ -4242,7 +4242,7 @@ fn rewards_incrementing_and_claiming() { assert!(!StakePallet::rewards(3).is_zero()); // claim for 1 to move rewards into balance - assert_ok!(StakePallet::claim_rewards_for(Origin::signed(3), 1)); + assert_ok!(StakePallet::claim_rewards(Origin::signed(1))); assert!(StakePallet::reward_count(1).is_zero()); assert!(StakePallet::rewards(1).is_zero()); // delegator situation should be unchanged @@ -4251,7 +4251,7 @@ fn rewards_incrementing_and_claiming() { assert_eq!(Balances::free_balance(&3), DECIMALS); // claim for 2 to move rewards into balance - assert_ok!(StakePallet::claim_rewards_for(Origin::signed(1), 2)); + assert_ok!(StakePallet::claim_rewards(Origin::signed(2))); assert!(Balances::free_balance(&2) > DECIMALS); assert!(StakePallet::reward_count(2).is_zero()); assert!(StakePallet::rewards(2).is_zero()); diff --git a/runtimes/peregrine/src/weights/parachain_staking.rs b/runtimes/peregrine/src/weights/parachain_staking.rs index 080f3ca309..0206a12eea 100644 --- a/runtimes/peregrine/src/weights/parachain_staking.rs +++ b/runtimes/peregrine/src/weights/parachain_staking.rs @@ -380,7 +380,7 @@ impl parachain_staking::WeightInfo for WeightInfo { } // Storage: ParachainStaking Rewards (r:1 w:1) // Storage: System Account (r:1 w:1) - fn claim_rewards_for() -> Weight { + fn claim_rewards() -> Weight { (29_833_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) diff --git a/runtimes/spiritnet/src/weights/parachain_staking.rs b/runtimes/spiritnet/src/weights/parachain_staking.rs index ece13ab308..d16bb0b3cd 100644 --- a/runtimes/spiritnet/src/weights/parachain_staking.rs +++ b/runtimes/spiritnet/src/weights/parachain_staking.rs @@ -380,7 +380,7 @@ impl parachain_staking::WeightInfo for WeightInfo { } // Storage: ParachainStaking Rewards (r:1 w:1) // Storage: System Account (r:1 w:1) - fn claim_rewards_for() -> Weight { + fn claim_rewards() -> Weight { (29_833_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) From a3b263163aa3ee4772e51d9e460e914873a83386 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Fri, 16 Sep 2022 15:12:03 +0200 Subject: [PATCH 23/34] fix: easy suggestions from code review --- pallets/parachain-staking/src/lib.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 273f962119..803e0defba 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -2395,19 +2395,22 @@ pub mod pallet { let mut reward_count = RewardCount::::get(acc); let rewards = Rewards::::get(acc); + // delegators and collators need to be handled differently if let Some(delegator_state) = DelegatorState::::get(acc) { - // delegator reward count does not automatically inrement in order to be - // scalable + // delegator reward counts do not automatically increment in order to be + // scalable, see [increment_delegator_rewards] for details + // therefore, we need to query the counter of the collator + // (`delegator_stare.owner`) reward_count = reward_count.saturating_add(delegator_state.owner.map(RewardCount::::get).unwrap_or(0u32)); - let stake = DelegatorState::::get(acc) - .map(|state| state.amount) - .unwrap_or_else(BalanceOf::::zero); + let stake = delegator_state.amount; + // rewards += stake * (self_count + collator_count) * delegator_reward_rate rewards.saturating_add(Self::calc_block_rewards_delegator(stake, reward_count.into())) } else if Self::is_active_candidate(acc).is_some() { let stake = CandidatePool::::get(acc) .map(|state| state.stake) .unwrap_or_else(BalanceOf::::zero); + // rewards += stake * self_count * collator_reward_rate rewards.saturating_add(Self::calc_block_rewards_collator(stake, reward_count.into())) } else { BalanceOf::::zero() @@ -2481,7 +2484,7 @@ pub mod pallet { /// At least used in Runtime API. pub fn get_staking_rates() -> runtime_api::StakingRates { let total_issuance = T::Currency::total_issuance(); - let total_stake = >::get(); + let total_stake = TotalCollatorStake::::get(); let inflation_config = InflationConfig::::get(); let collator_staking_rate = Perquintill::from_rational(total_stake.collators, total_issuance); let delegator_staking_rate = Perquintill::from_rational(total_stake.delegators, total_issuance); From e703493c668c3eb2af734920ac05abca615de5c6 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 19 Sep 2022 09:27:52 +0200 Subject: [PATCH 24/34] tests: comp api claim with claiming --- pallets/parachain-staking/src/tests.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index c708e16356..411fb0b74d 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -4295,14 +4295,28 @@ fn api_get_unclaimed_staking_rewards() { // Should only increment rewards of 3 roll_to(3, vec![None, None, Some(3)]); + let rewards_1 = StakePallet::get_unclaimed_staking_rewards(&1); + let rewards_2 = StakePallet::get_unclaimed_staking_rewards(&2); + let rewards_3 = StakePallet::get_unclaimed_staking_rewards(&3); assert_eq!( - 2 * StakePallet::get_unclaimed_staking_rewards(&1), - StakePallet::get_unclaimed_staking_rewards(&3), + 2 * rewards_1, + rewards_3, ); assert_eq!( - StakePallet::get_unclaimed_staking_rewards(&2), + rewards_2, inflation_config.delegator.reward_rate.per_block * stake * 2 ); + + // API and actual claiming should match + assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(1))); + assert_ok!(StakePallet::claim_rewards(Origin::signed(1))); + assert_eq!(rewards_1, Balances::usable_balance(&1)); + assert_ok!(StakePallet::increment_delegator_rewards(Origin::signed(2))); + assert_ok!(StakePallet::claim_rewards(Origin::signed(2))); + assert_eq!(rewards_2, Balances::usable_balance(&2)); + assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(3))); + assert_ok!(StakePallet::claim_rewards(Origin::signed(3))); + assert_eq!(rewards_3 + 98 * stake, Balances::usable_balance(&3)); }); } From 02eb40733520f5b4a5d18378e2bcbcfd3c79ff43 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 19 Sep 2022 10:22:13 +0200 Subject: [PATCH 25/34] stlye: fmt --- pallets/parachain-staking/src/tests.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 411fb0b74d..0b714dd2e7 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -4298,14 +4298,8 @@ fn api_get_unclaimed_staking_rewards() { let rewards_1 = StakePallet::get_unclaimed_staking_rewards(&1); let rewards_2 = StakePallet::get_unclaimed_staking_rewards(&2); let rewards_3 = StakePallet::get_unclaimed_staking_rewards(&3); - assert_eq!( - 2 * rewards_1, - rewards_3, - ); - assert_eq!( - rewards_2, - inflation_config.delegator.reward_rate.per_block * stake * 2 - ); + assert_eq!(2 * rewards_1, rewards_3,); + assert_eq!(rewards_2, inflation_config.delegator.reward_rate.per_block * stake * 2); // API and actual claiming should match assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(1))); From 36e4abdcaa419635695809d8776178edd6f22abb Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 31 Oct 2022 10:34:43 +0100 Subject: [PATCH 26/34] tests: add safety check to API rewards --- pallets/parachain-staking/src/tests.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 0b714dd2e7..d4ea43e227 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -4305,12 +4305,17 @@ fn api_get_unclaimed_staking_rewards() { assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(1))); assert_ok!(StakePallet::claim_rewards(Origin::signed(1))); assert_eq!(rewards_1, Balances::usable_balance(&1)); + assert!(StakePallet::get_unclaimed_staking_rewards(&1).is_zero()); + assert_ok!(StakePallet::increment_delegator_rewards(Origin::signed(2))); assert_ok!(StakePallet::claim_rewards(Origin::signed(2))); assert_eq!(rewards_2, Balances::usable_balance(&2)); + assert!(StakePallet::get_unclaimed_staking_rewards(&2).is_zero()); + assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(3))); assert_ok!(StakePallet::claim_rewards(Origin::signed(3))); assert_eq!(rewards_3 + 98 * stake, Balances::usable_balance(&3)); + assert!(StakePallet::get_unclaimed_staking_rewards(&3).is_zero()); }); } From 56a55390cbc60d90ef7c2542f34a57093ca600ae Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 31 Oct 2022 14:53:28 +0100 Subject: [PATCH 27/34] style: fmt --- pallets/parachain-staking/src/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index d4ea43e227..dcf0659e3c 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -4306,12 +4306,12 @@ fn api_get_unclaimed_staking_rewards() { assert_ok!(StakePallet::claim_rewards(Origin::signed(1))); assert_eq!(rewards_1, Balances::usable_balance(&1)); assert!(StakePallet::get_unclaimed_staking_rewards(&1).is_zero()); - + assert_ok!(StakePallet::increment_delegator_rewards(Origin::signed(2))); assert_ok!(StakePallet::claim_rewards(Origin::signed(2))); assert_eq!(rewards_2, Balances::usable_balance(&2)); assert!(StakePallet::get_unclaimed_staking_rewards(&2).is_zero()); - + assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(3))); assert_ok!(StakePallet::claim_rewards(Origin::signed(3))); assert_eq!(rewards_3 + 98 * stake, Balances::usable_balance(&3)); From 30044dd1e31e38c25e796373e436db378742b77a Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Fri, 16 Sep 2022 16:28:05 +0200 Subject: [PATCH 28/34] feat: write delegator state migration --- pallets/parachain-staking/src/lib.rs | 3 +- pallets/parachain-staking/src/migration.rs | 135 +++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 pallets/parachain-staking/src/migration.rs diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 803e0defba..2bc058b3f3 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -120,6 +120,7 @@ pub mod benchmarking; pub mod default_weights; pub mod runtime_api; +pub mod migration; #[cfg(test)] pub(crate) mod mock; #[cfg(test)] @@ -172,7 +173,7 @@ pub mod pallet { pub(crate) const STAKING_ID: LockIdentifier = *b"kiltpstk"; /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(7); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(8); /// Pallet for parachain staking. #[pallet::pallet] diff --git a/pallets/parachain-staking/src/migration.rs b/pallets/parachain-staking/src/migration.rs new file mode 100644 index 0000000000..db9b715da1 --- /dev/null +++ b/pallets/parachain-staking/src/migration.rs @@ -0,0 +1,135 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2022 BOTLabs GmbH + +// The KILT Blockchain is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The KILT Blockchain is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +#![cfg_attr(not(feature = "std"), no_std)] + +use crate::{ + set::OrderedSet, + types::{BalanceOf, Delegator, Stake}, +}; + +use super::*; +use core::marker::PhantomData; +use frame_support::{ + dispatch::GetStorageVersion, + pallet_prelude::ValueQuery, + parameter_types, storage_alias, + traits::{Get, OnRuntimeUpgrade}, + weights::Weight, + RuntimeDebug, +}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +#[cfg(feature = "try-runtime")] +use sp_runtime::SaturatedConversion; + +// Old types +#[derive(Encode, Decode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] +#[scale_info(skip_type_params(MaxCollatorsPerDelegator))] +#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] +pub struct DelegatorOld> { + pub delegations: OrderedSet, MaxCollatorsPerDelegator>, + pub total: Balance, +} +parameter_types! { + const MaxCollatorsPerDelegator: u32 = 1; +} + +/// Number of delegators post migration +#[storage_alias] +type CounterForDelegators = StorageValue, u32, ValueQuery>; + +pub struct StakingPayoutRefactor(PhantomData); +impl OnRuntimeUpgrade for StakingPayoutRefactor { + fn on_runtime_upgrade() -> Weight { + let current = Pallet::::current_storage_version(); + let onchain = Pallet::::on_chain_storage_version(); + + log::info!( + "Running migration with current storage version {:?} / onchain {:?}", + current, + onchain + ); + + if current == 8 && onchain == 7 { + let num_delegators = migrate_delegators::(); + T::DbWeight::get().reads_writes(num_delegators, num_delegators) + } else { + log::info!("StakingPayoutRefactor did not execute. This probably should be removed"); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + use sp_runtime::traits::Zero; + + let current = Pallet::::current_storage_version(); + + assert_eq!( + current, 7, + "ParachainStaking StorageVersion is {:?} instead of 7", + current + ); + assert!( + CounterForDelegators::::get().is_zero(), + "CounterForDelegators already set." + ); + // store number of delegators before migration + CounterForDelegators::::put(DelegatorState::::iter_keys().count().saturated_into::()); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + // new version must be set. + let onchain = Pallet::::on_chain_storage_version(); + + assert_eq!( + onchain, 8, + "ParachainStaking StorageVersion post-migration is not 8, but {:?} instead.", + onchain + ); + + let old_num_delegators: u32 = CounterForDelegators::::get(); + let new_num_delegators: u32 = DelegatorState::::iter_keys().count().saturated_into::(); + assert_eq!( + old_num_delegators, new_num_delegators, + "Number of delegators changed during migration! Before {:?} vs. now {:?}", + old_num_delegators, new_num_delegators + ); + Ok(()) + } +} + +fn migrate_delegators() -> u64 { + let mut counter = 0; + DelegatorState::::translate_values::< + Option, MaxCollatorsPerDelegator>>, + _, + >(|maybe_old| { + counter += 1; + maybe_old.map(|old| Delegator { + amount: old.total, + owner: old.delegations.get(0).map(|stake| stake.owner.clone()), + }) + }); + + counter +} From 30be731402178ef7ce10519459d1d228b8d5fec6 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 1 Nov 2022 13:25:52 +0100 Subject: [PATCH 29/34] refactor: Delegator interface functions --- pallets/parachain-staking/src/lib.rs | 6 +++--- pallets/parachain-staking/src/types.rs | 19 +++---------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 2bc058b3f3..ea64f3b19e 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1517,7 +1517,7 @@ pub mod pallet { let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); let stake_after = delegation - .inc_delegation(candidate.clone(), more) + .try_increment(candidate.clone(), more) .map_err(|_| Error::::DelegationNotFound)?; // *** No Fail except during increase_lock beyond this point *** @@ -1595,7 +1595,7 @@ pub mod pallet { let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); let stake_after = delegations - .dec_delegation(candidate.clone(), less) + .try_decrement(candidate.clone(), less) .map_err(|_| Error::::DelegationNotFound)? .ok_or(Error::::Underflow)?; @@ -2223,7 +2223,7 @@ pub mod pallet { // remove delegation from delegator state if let Some(mut delegator) = DelegatorState::::get(&stake.owner) { delegator - .rm_delegation(collator.clone()) + .try_clear(collator.clone()) .map_err(|_| Error::::DelegationNotFound)?; DelegatorState::::remove(&stake.owner); } diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index fdde733ac5..125ca67827 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -215,22 +215,9 @@ where AccountId: Eq + Ord + Clone + Debug, Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default + CheckedSub, { - /// Adds a new delegation. - /// - /// If already delegating to someone, this call will fail. - pub fn add_delegation(&mut self, stake: Stake) -> Result<(), ()> { - if self.owner.is_none() && self.amount.is_zero() { - self.owner = Some(stake.owner); - self.amount = stake.amount; - Ok(()) - } else { - Err(()) - } - } - /// Returns Ok if the delegation for the /// collator exists and `Err` otherwise. - pub fn rm_delegation(&mut self, collator: AccountId) -> Result<(), ()> { + pub fn try_clear(&mut self, collator: AccountId) -> Result<(), ()> { if self.owner == Some(collator) { self.amount = Balance::zero(); self.owner = None; @@ -242,7 +229,7 @@ where /// Returns Ok(delegated_amount) if successful, `Err` if delegation was /// not found. - pub fn inc_delegation(&mut self, collator: AccountId, more: Balance) -> Result { + pub fn try_increment(&mut self, collator: AccountId, more: Balance) -> Result { if self.owner == Some(collator) { self.amount = self.amount.saturating_add(more); Ok(self.amount) @@ -253,7 +240,7 @@ where /// Returns Ok(Some(delegated_amount)) if successful, `Err` if delegation /// was not found and Ok(None) if delegated stake would underflow. - pub fn dec_delegation(&mut self, collator: AccountId, less: Balance) -> Result, ()> { + pub fn try_decrement(&mut self, collator: AccountId, less: Balance) -> Result, ()> { if self.owner == Some(collator) { Ok(self.amount.checked_sub(&less).map(|new| { self.amount = new; From 55c6ac30dd1771e0cd36ee6fa80e01475d912870 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 1 Nov 2022 13:54:53 +0100 Subject: [PATCH 30/34] refactor: rm Option for Delegator.owner --- pallets/parachain-staking/src/benchmarking.rs | 2 +- pallets/parachain-staking/src/lib.rs | 11 ++--- pallets/parachain-staking/src/migration.rs | 14 ++++--- pallets/parachain-staking/src/tests.rs | 40 ++++--------------- pallets/parachain-staking/src/types.rs | 9 ++--- 5 files changed, 25 insertions(+), 51 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 1f3926f606..0679bed3f5 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -567,7 +567,7 @@ benchmarks! { // mock high values to compensate for tiny values in unit test env let stake = T::CurrencyBalance::from(1_000_000_000_000_000_000u128); - DelegatorState::::insert(&delegator, crate::types::Delegator { owner: Some(collator.clone()), amount: stake}); + DelegatorState::::insert(&delegator, crate::types::Delegator { owner: collator.clone(), amount: stake}); RewardCount::::insert(&collator, u32::MAX); assert!(Rewards::::get(&delegator).is_zero()); diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index ea64f3b19e..bfe3c7a9ea 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1401,7 +1401,7 @@ pub mod pallet { let delegator_state = Delegator { amount, - owner: Some(collator.clone()), + owner: collator.clone(), }; let CandidateOf:: { stake: old_stake, @@ -1477,8 +1477,7 @@ pub mod pallet { pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { let acc = ensure_signed(origin)?; let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; - // should never throw - let collator = delegator.owner.ok_or(Error::::DelegationNotFound)?; + let collator = delegator.owner; Self::delegator_leaves_collator(acc.clone(), collator)?; // *** No Fail beyond this point *** @@ -1734,8 +1733,7 @@ pub mod pallet { pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { let delegator = ensure_signed(origin)?; let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; - // should never throw - let collator = delegation.owner.ok_or(Error::::DelegationNotFound)?; + let collator = delegation.owner; Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); ensure!(!Rewards::::get(&delegator).is_zero(), Error::::RewardsNotFound); @@ -2402,8 +2400,7 @@ pub mod pallet { // scalable, see [increment_delegator_rewards] for details // therefore, we need to query the counter of the collator // (`delegator_stare.owner`) - reward_count = - reward_count.saturating_add(delegator_state.owner.map(RewardCount::::get).unwrap_or(0u32)); + reward_count = reward_count.saturating_add(RewardCount::::get(&delegator_state.owner)); let stake = delegator_state.amount; // rewards += stake * (self_count + collator_count) * delegator_reward_rate rewards.saturating_add(Self::calc_block_rewards_delegator(stake, reward_count.into())) diff --git a/pallets/parachain-staking/src/migration.rs b/pallets/parachain-staking/src/migration.rs index db9b715da1..11761a32b6 100644 --- a/pallets/parachain-staking/src/migration.rs +++ b/pallets/parachain-staking/src/migration.rs @@ -16,8 +16,6 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -#![cfg_attr(not(feature = "std"), no_std)] - use crate::{ set::OrderedSet, types::{BalanceOf, Delegator, Stake}, @@ -125,10 +123,14 @@ fn migrate_delegators() -> u64 { _, >(|maybe_old| { counter += 1; - maybe_old.map(|old| Delegator { - amount: old.total, - owner: old.delegations.get(0).map(|stake| stake.owner.clone()), - }) + maybe_old + .map(|old| { + old.delegations.get(0).map(|stake| Delegator { + amount: old.total, + owner: stake.owner.clone(), + }) + }) + .unwrap_or(None) }); counter diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index dcf0659e3c..b3f43a5bc0 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -715,31 +715,19 @@ fn execute_leave_candidates_with_delay() { } assert_eq!( StakePallet::delegator_state(11), - Some(Delegator:: { - owner: Some(1), - amount: 110, - }) + Some(Delegator:: { owner: 1, amount: 110 }) ); assert_eq!( StakePallet::delegator_state(12), - Some(Delegator:: { - owner: Some(1), - amount: 120 - }) + Some(Delegator:: { owner: 1, amount: 120 }) ); assert_eq!( StakePallet::delegator_state(13), - Some(Delegator:: { - owner: Some(2), - amount: 130 - }) + Some(Delegator:: { owner: 2, amount: 130 }) ); assert_eq!( StakePallet::delegator_state(14), - Some(Delegator:: { - owner: Some(2), - amount: 140 - }) + Some(Delegator:: { owner: 2, amount: 140 }) ); for delegator in 11u64..=14u64 { assert!(StakePallet::is_delegator(&delegator)); @@ -816,31 +804,19 @@ fn execute_leave_candidates_with_delay() { } assert_eq!( StakePallet::delegator_state(11), - Some(Delegator:: { - owner: Some(1), - amount: 110 - }) + Some(Delegator:: { owner: 1, amount: 110 }) ); assert_eq!( StakePallet::delegator_state(12), - Some(Delegator:: { - owner: Some(1), - amount: 120 - }) + Some(Delegator:: { owner: 1, amount: 120 }) ); assert_eq!( StakePallet::delegator_state(13), - Some(Delegator:: { - owner: Some(2), - amount: 130 - }) + Some(Delegator:: { owner: 2, amount: 130 }) ); assert_eq!( StakePallet::delegator_state(14), - Some(Delegator:: { - owner: Some(2), - amount: 140 - }) + Some(Delegator:: { owner: 2, amount: 140 }) ); for delegator in 11u64..=14u64 { assert!(StakePallet::is_delegator(&delegator)); diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index 125ca67827..d5f5841ee8 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -209,7 +209,7 @@ where } } -pub type Delegator = Stake, Balance>; +pub type Delegator = Stake; impl Delegator where AccountId: Eq + Ord + Clone + Debug, @@ -218,9 +218,8 @@ where /// Returns Ok if the delegation for the /// collator exists and `Err` otherwise. pub fn try_clear(&mut self, collator: AccountId) -> Result<(), ()> { - if self.owner == Some(collator) { + if self.owner == collator { self.amount = Balance::zero(); - self.owner = None; Ok(()) } else { Err(()) @@ -230,7 +229,7 @@ where /// Returns Ok(delegated_amount) if successful, `Err` if delegation was /// not found. pub fn try_increment(&mut self, collator: AccountId, more: Balance) -> Result { - if self.owner == Some(collator) { + if self.owner == collator { self.amount = self.amount.saturating_add(more); Ok(self.amount) } else { @@ -241,7 +240,7 @@ where /// Returns Ok(Some(delegated_amount)) if successful, `Err` if delegation /// was not found and Ok(None) if delegated stake would underflow. pub fn try_decrement(&mut self, collator: AccountId, less: Balance) -> Result, ()> { - if self.owner == Some(collator) { + if self.owner == collator { Ok(self.amount.checked_sub(&less).map(|new| { self.amount = new; self.amount From cd9684e99508da4889354eb6d5db86c360c44311 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 1 Nov 2022 16:15:35 +0100 Subject: [PATCH 31/34] style: apply turbofish to staking --- pallets/parachain-staking/src/benchmarking.rs | 140 +++++++++--------- pallets/parachain-staking/src/lib.rs | 71 +++++---- 2 files changed, 105 insertions(+), 106 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 0679bed3f5..fd5346e521 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -48,11 +48,11 @@ fn setup_collator_candidates( for acc in collators.iter() { T::Currency::make_free_balance_be(acc, amount); - assert_ok!(>::join_candidates( + assert_ok!(Pallet::::join_candidates( T::Origin::from(Some(acc.clone()).into()), amount, )); - assert_eq!(>::get(acc).unwrap().stake, amount); + assert_eq!(CandidatePool::::get(acc).unwrap().stake, amount); } TopCandidates::::get() @@ -64,7 +64,7 @@ fn setup_collator_candidates( } fn fill_delegators(num_delegators: u32, collator: T::AccountId, collator_seed: u32) -> Vec { - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); let current_delegators = state.delegators.len().saturated_into::(); let delegators: Vec = (current_delegators..num_delegators) @@ -79,7 +79,7 @@ fn fill_delegators(num_delegators: u32, collator: T::AccountId, colla for acc in delegators.iter() { T::Currency::make_free_balance_be(acc, T::MinDelegatorStake::get()); - assert_ok!(>::join_delegators( + assert_ok!(Pallet::::join_delegators( T::Origin::from(Some(acc.clone()).into()), T::Lookup::unlookup(collator.clone()), T::MinDelegatorStake::get(), @@ -95,43 +95,43 @@ where u64: Into<::BlockNumber>, { let who = delegator.unwrap_or(collator); - assert_eq!(>::get(who).len(), 0); + assert_eq!(Unstaking::::get(who).len(), 0); while System::::block_number() < unstaked.into() { if let Some(delegator) = delegator { - assert_ok!(>::delegator_stake_less( + assert_ok!(Pallet::::delegator_stake_less( RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::one() )); } else { - assert_ok!(>::candidate_stake_less( + assert_ok!(Pallet::::candidate_stake_less( RawOrigin::Signed(collator.clone()).into(), T::CurrencyBalance::one() )); } System::::set_block_number(System::::block_number() + T::BlockNumber::one()); } - assert_eq!(>::get(who).len() as u64, unstaked); - assert!(>::get(who).len() <= T::MaxUnstakeRequests::get().try_into().unwrap()); + assert_eq!(Unstaking::::get(who).len() as u64, unstaked); + assert!(Unstaking::::get(who).len() <= T::MaxUnstakeRequests::get().try_into().unwrap()); } benchmarks! { where_clause { where u64: Into<::BlockNumber> } on_initialize_no_action { - assert_eq!(>::get().current, 0u32); + assert_eq!(Round::::get().current, 0u32); let block = T::BlockNumber::one(); }: { Pallet::::on_initialize(block) } verify { - assert_eq!(>::get().current, 0u32); + assert_eq!(Round::::get().current, 0u32); } on_initialize_round_update { - let round = >::get(); + let round = Round::::get(); assert_eq!(round.current, 0u32); }: { Pallet::::on_initialize(round.length) } verify { - assert_eq!(>::get().current, 1u32); + assert_eq!(Round::::get().current, 1u32); } on_initialize_network_rewards { @@ -148,14 +148,14 @@ benchmarks! { } force_new_round { - let round = >::get(); + let round = Round::::get(); let now = System::::block_number(); assert_eq!(round.current, 0); assert_eq!(Session::::current_index(), 0); - assert!(!>::get()); + assert!(!ForceNewRound::::get()); }: _(RawOrigin::Root) verify { - assert!(>::get()); + assert!(ForceNewRound::::get()); assert_eq!(Session::::current_index(), 0); // jump to next block to trigger new round @@ -163,12 +163,12 @@ benchmarks! { System::::set_block_number(now); Session::::on_initialize(now); assert_eq!(Session::::current_index(), 1); - assert_eq!(>::get(), RoundInfo { + assert_eq!(Round::::get(), RoundInfo { current: 1, first: now, length: round.length, }); - assert!(!>::get()); + assert!(!ForceNewRound::::get()); } set_inflation { @@ -207,14 +207,14 @@ benchmarks! { let old_candidate = candidates[0].clone(); }: _(RawOrigin::Root, n) verify { - assert_eq!(>::get(), n); + assert_eq!(MaxSelectedCandidates::::get(), n); } set_blocks_per_round { let bpr: T::BlockNumber = T::MinBlocksPerRound::get() + T::BlockNumber::one(); }: _(RawOrigin::Root, bpr) verify { - assert_eq!(>::get().length, bpr); + assert_eq!(Round::::get().length, bpr); } force_remove_candidate { @@ -262,7 +262,7 @@ benchmarks! { fill_delegators::(m, c.clone(), i.saturated_into::()); } - let now = >::get().current; + let now = Round::::get().current; let candidate = candidates[0].clone(); let origin = RawOrigin::Signed(candidate.clone()); @@ -271,7 +271,7 @@ benchmarks! { let candidates = TopCandidates::::get(); assert!(!candidates.into_iter().any(|other| other.owner == candidate)); let unlocking_at = now.saturating_add(T::ExitQueueDelay::get()); - assert!(>::get(candidate).unwrap().can_exit(unlocking_at)); + assert!(CandidatePool::::get(candidate).unwrap().can_exit(unlocking_at)); } cancel_leave_candidates { @@ -284,7 +284,7 @@ benchmarks! { } let candidate = candidates[0].clone(); - assert_ok!(>::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); + assert_ok!(Pallet::::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); let origin = RawOrigin::Signed(candidate.clone()); }: _(origin) @@ -307,16 +307,16 @@ benchmarks! { // increase stake so we can unstake, because current stake is minimum let more_stake = T::MinCollatorCandidateStake::get(); T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); + assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&candidate, None, u as u64); // go to block in which we can exit - assert_ok!(>::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); + assert_ok!(Pallet::::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); for i in 1..=T::ExitQueueDelay::get() { - let round = >::get(); + let round = Round::::get(); let now = round.first + round.length; System::::set_block_number(now); Pallet::::on_initialize(now); @@ -327,7 +327,7 @@ benchmarks! { }: _(origin, unlookup_candidate) verify { // should have one more entry in Unstaking - assert_eq!(>::get(&candidate).len().saturated_into::(), u.saturating_add(1u32)); + assert_eq!(Unstaking::::get(&candidate).len().saturated_into::(), u.saturating_add(1u32)); } candidate_stake_more { @@ -341,12 +341,12 @@ benchmarks! { } let candidate = candidates[0].clone(); - let old_stake = >::get(&candidate).unwrap().stake; + let old_stake = CandidatePool::::get(&candidate).unwrap().stake; let more_stake = T::MinCollatorCandidateStake::get(); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); + assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&candidate, None, u as u64); @@ -354,8 +354,8 @@ benchmarks! { let origin = RawOrigin::Signed(candidate.clone()); }: _(origin, more_stake) verify { - let new_stake = >::get(&candidate).unwrap().stake; - assert!(>::get(candidate).is_empty()); + let new_stake = CandidatePool::::get(&candidate).unwrap().stake; + assert!(Unstaking::::get(candidate).is_empty()); assert_eq!(new_stake, old_stake + more_stake + more_stake - T::CurrencyBalance::from(u as u64)); } @@ -370,19 +370,19 @@ benchmarks! { let candidate = candidates[0].clone(); // increase stake of candidate to later decrease it again - let old_stake = >::get(&candidate).unwrap().stake; + let old_stake = CandidatePool::::get(&candidate).unwrap().stake; let more_stake = T::MinCollatorCandidateStake::get(); T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake).expect("should increase stake"); - let new_stake = >::get(&candidate).unwrap().stake; + let new_stake = CandidatePool::::get(&candidate).unwrap().stake; assert_eq!(new_stake, old_stake + more_stake); let origin = RawOrigin::Signed(candidate.clone()); }: _(origin, more_stake) verify { - let new_stake = >::get(&candidate).unwrap().stake; + let new_stake = CandidatePool::::get(&candidate).unwrap().stake; assert_eq!(new_stake, old_stake); } @@ -404,7 +404,7 @@ benchmarks! { let origin = RawOrigin::Signed(delegator.clone()); }: _(origin, unlookup_collator, amount) verify { - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); } @@ -423,27 +423,27 @@ benchmarks! { let amount = T::MinDelegatorStake::get(); // make sure delegator collated to collator - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().amount, amount); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::from(u as u64))); - assert_eq!(>::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::from(u as u64))); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&collator, Some(&delegator), u as u64); - assert_eq!(>::get(&delegator).unwrap().amount, amount); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); let unlookup_collator = T::Lookup::unlookup(collator.clone()); let origin = RawOrigin::Signed(delegator.clone()); }: _(origin, unlookup_collator, amount) verify { - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(>::get(&delegator).unwrap().amount, amount + amount); - assert!(>::get(&delegator).is_empty()); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + amount); + assert!(Unstaking::::get(&delegator).is_empty()); } delegator_stake_less { @@ -460,28 +460,28 @@ benchmarks! { let amount = T::CurrencyBalance::one(); // make sure delegator collated to collator - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block - assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); - assert_eq!(>::get(&delegator).len(), 1); + assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); + assert_eq!(Unstaking::::get(&delegator).len(), 1); let unlookup_collator = T::Lookup::unlookup(collator.clone()); let origin = RawOrigin::Signed(delegator.clone()); }: _(origin, unlookup_collator, amount) verify { - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); - assert_eq!(>::get(&delegator).len(), 2); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); + assert_eq!(Unstaking::::get(&delegator).len(), 2); } leave_delegators { @@ -498,27 +498,27 @@ benchmarks! { let amount = T::CurrencyBalance::one(); // make sure delegator collated to collator - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(>::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block - assert_ok!(>::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); - assert_eq!(>::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); - assert_eq!(>::get(&delegator).len(), 1); + assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); + assert_eq!(Unstaking::::get(&delegator).len(), 1); let origin = RawOrigin::Signed(delegator.clone()); }: _(origin) verify { - let state = >::get(&collator).unwrap(); + let state = CandidatePool::::get(&collator).unwrap(); assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); - assert!(>::get(&delegator).is_none()); - assert_eq!(>::get(&delegator).len(), 2); + assert!(DelegatorState::::get(&delegator).is_none()); + assert_eq!(Unstaking::::get(&delegator).len(), 2); } unlock_unstaked { @@ -528,18 +528,18 @@ benchmarks! { let free_balance = T::CurrencyBalance::from(u128::MAX); let stake = T::MinCollatorCandidateStake::get(); T::Currency::make_free_balance_be(&candidate, free_balance); - assert_ok!(>::join_candidates( + assert_ok!(Pallet::::join_candidates( T::Origin::from(Some(candidate.clone()).into()), stake, )); assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - T::MinCollatorCandidateStake::get()).into()); // increase stake so we can unstake, because current stake is minimum - assert_ok!(>::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), stake)); + assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), stake)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&candidate, None, u as u64); - assert_eq!(>::get(&candidate).unwrap().stake, stake + stake - T::CurrencyBalance::from(u as u64)); + assert_eq!(CandidatePool::::get(&candidate).unwrap().stake, stake + stake - T::CurrencyBalance::from(u as u64)); // roll to block in which first unstake can be unlocked System::::set_block_number(T::StakeDuration::get()); @@ -549,16 +549,16 @@ benchmarks! { let origin = RawOrigin::Signed(candidate.clone()); }: _(origin, unlookup_candidate) verify { - assert_eq!(>::get(&candidate).len().saturated_into::(), u.saturating_sub(1u32)); + assert_eq!(Unstaking::::get(&candidate).len().saturated_into::(), u.saturating_sub(1u32)); assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - stake - stake + T::CurrencyBalance::one()).into()); } set_max_candidate_stake { - let old = >::get(); - let new = >::get() + T::CurrencyBalance::from(10u128); + let old = MaxCollatorCandidateStake::::get(); + let new = MaxCollatorCandidateStake::::get() + T::CurrencyBalance::from(10u128); }: _(RawOrigin::Root, new) verify { - assert_eq!(>::get(), new); + assert_eq!(MaxCollatorCandidateStake::::get(), new); } increment_delegator_rewards { diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index bfe3c7a9ea..435537c41c 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -490,14 +490,14 @@ pub mod pallet { impl Hooks> for Pallet { fn on_initialize(now: T::BlockNumber) -> frame_support::weights::Weight { let mut post_weight = ::WeightInfo::on_initialize_no_action(); - let mut round = >::get(); + let mut round = Round::::get(); // check for round update if round.should_update(now) { // mutate round round.update(now); // start next round - >::put(round); + Round::::put(round); Self::deposit_event(Event::NewRound(round.first, round.current)); post_weight = ::WeightInfo::on_initialize_round_update(); @@ -680,13 +680,13 @@ pub mod pallet { "Account does not have enough balance to stake." ); if let Some(delegated_val) = opt_val { - assert_ok!(>::join_delegators( + assert_ok!(Pallet::::join_delegators( T::Origin::from(Some(actor.clone()).into()), T::Lookup::unlookup(delegated_val.clone()), balance, )); } else { - assert_ok!(>::join_candidates( + assert_ok!(Pallet::::join_candidates( T::Origin::from(Some(actor.clone()).into()), balance )); @@ -695,11 +695,11 @@ pub mod pallet { // Set total selected candidates to minimum config MaxSelectedCandidates::::put(T::MinCollators::get()); - >::update_total_stake(); + Pallet::::update_total_stake(); // Start Round 0 at Block 0 let round: RoundInfo = RoundInfo::new(0u32, 0u32.into(), T::DefaultBlocksPerRound::get()); - >::put(round); + Round::::put(round); } } @@ -718,7 +718,7 @@ pub mod pallet { // set force_new_round handle which, at the start of the next block, will // trigger `should_end_session` in `Session::on_initialize` and update the // current round - >::put(true); + ForceNewRound::::put(true); Ok(()) } @@ -865,11 +865,11 @@ pub mod pallet { ensure_root(origin)?; ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); - let old_round = >::get(); + let old_round = Round::::get(); // *** No Fail beyond this point *** - >::put(RoundInfo { + Round::::put(RoundInfo { length: new, ..old_round }); @@ -1069,7 +1069,7 @@ pub mod pallet { Error::::TooFewCollatorCandidates ); - let now = >::get().current; + let now = Round::::get().current; let when = now.saturating_add(T::ExitQueueDelay::get()); state.leave_candidates(when); @@ -1129,7 +1129,7 @@ pub mod pallet { let collator = T::Lookup::lookup(collator)?; let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; ensure!(state.is_leaving(), Error::::NotLeaving); - ensure!(state.can_exit(>::get().current), Error::::CannotLeaveYet); + ensure!(state.can_exit(Round::::get().current), Error::::CannotLeaveYet); let num_delegators = state.delegators.len().saturated_into::(); let total_amount = state.total; @@ -1441,7 +1441,7 @@ pub mod pallet { // update states CandidatePool::::insert(&collator, state); DelegatorState::::insert(&acc, delegator_state); - >::insert(&acc, delegation_counter); + LastDelegation::::insert(&acc, delegation_counter); // initiate reward counter to match the current state of the candidate RewardCount::::insert(&acc, RewardCount::::get(&collator)); @@ -1687,13 +1687,12 @@ pub mod pallet { pub fn claim_rewards(origin: OriginFor) -> DispatchResult { let target = ensure_signed(origin)?; - // we could kill the storage entry but let's be safe in case the deposit fails - let rewards = Rewards::::get(&target); + // reset rewards + let rewards = Rewards::::take(&target); ensure!(!rewards.is_zero(), Error::::RewardsNotFound); - // mint into target and reset rewards + // mint into target let rewards = T::Currency::deposit_into_existing(&target, rewards)?; - Rewards::::remove(&target); Self::deposit_event(Event::Rewarded(target, rewards.peek())); @@ -2136,7 +2135,7 @@ pub mod pallet { // *** No Fail except during Unstaking mutation beyond this point *** // update Unstaking by consuming up to {amount | more} - >::try_mutate(who, |unstaking| -> DispatchResult { + Unstaking::::try_mutate(who, |unstaking| -> DispatchResult { // reduce {amount | more} by unstaking until either {amount | more} is zero or // no unstaking is left // if more is set, we only want to reduce by more to achieve 100 - 40 + 30 = 90 @@ -2181,9 +2180,9 @@ pub mod pallet { // should never occur but let's be safe ensure!(!amount.is_zero(), Error::::StakeNotFound); - let now = >::block_number(); + let now = frame_system::Pallet::::block_number(); let unlock_block = now.saturating_add(T::StakeDuration::get()); - let mut unstaking = >::get(who); + let mut unstaking = Unstaking::::get(who); let allowed_unstakings = if is_removal { // the account was forcedly removed and we allow to fill all unstake requests @@ -2203,7 +2202,7 @@ pub mod pallet { unstaking .try_insert(unlock_block, amount) .map_err(|_| Error::::NoMoreUnstaking)?; - >::insert(who, unstaking); + Unstaking::::insert(who, unstaking); Ok(()) } @@ -2256,8 +2255,8 @@ pub mod pallet { /// Withdraw all staked currency which was unstaked at least /// `StakeDuration` blocks ago. fn do_unlock(who: &T::AccountId) -> Result { - let now = >::block_number(); - let mut unstaking = >::get(who); + let now = frame_system::Pallet::::block_number(); + let mut unstaking = Unstaking::::get(who); let unstaking_len = unstaking.len().saturated_into::(); ensure!(!unstaking.is_empty(), Error::::UnstakingIsEmpty); @@ -2290,10 +2289,10 @@ pub mod pallet { if total_locked.is_zero() { T::Currency::remove_lock(STAKING_ID, who); - >::remove(who); + Unstaking::::remove(who); } else { T::Currency::set_lock(STAKING_ID, who, total_locked, WithdrawReasons::all()); - >::insert(who, unstaking); + Unstaking::::insert(who, unstaking); } Ok(unstaking_len) @@ -2303,8 +2302,8 @@ pub mod pallet { /// if they have not delegated MaxDelegationsPerRound many times /// already in this round. fn get_delegation_counter(delegator: &T::AccountId) -> Result { - let last_delegation = >::get(delegator); - let round = >::get(); + let last_delegation = LastDelegation::::get(delegator); + let round = Round::::get(); // reset counter if the round advanced since last delegation let counter = if last_delegation.round < round.current { @@ -2361,7 +2360,7 @@ pub mod pallet { let TotalStake { collators: total_collators, .. - } = >::get(); + } = TotalCollatorStake::::get(); let staking_rate = Perquintill::from_rational(total_collators, total_issuance); InflationConfig::::get() @@ -2379,7 +2378,7 @@ pub mod pallet { let TotalStake { delegators: total_delegators, .. - } = >::get(); + } = TotalCollatorStake::::get(); let staking_rate = Perquintill::from_rational(total_delegators, total_issuance); InflationConfig::::get() @@ -2544,7 +2543,7 @@ pub mod pallet { log::debug!( "assembling new collators for new session {} at #{:?}", new_index, - >::block_number(), + frame_system::Pallet::::block_number(), ); frame_system::Pallet::::register_extra_weight_unchecked( @@ -2578,19 +2577,19 @@ pub mod pallet { DispatchClass::Mandatory, ); - let mut round = >::get(); + let mut round = Round::::get(); // always update when a new round should start if round.should_update(now) { true - } else if >::get() { + } else if ForceNewRound::::get() { frame_system::Pallet::::register_extra_weight_unchecked( T::DbWeight::get().writes(2), DispatchClass::Mandatory, ); // check for forced new round - >::put(false); + ForceNewRound::::put(false); round.update(now); - >::put(round); + Round::::put(round); Self::deposit_event(Event::NewRound(round.first, round.current)); true } else { @@ -2601,11 +2600,11 @@ pub mod pallet { impl EstimateNextSessionRotation for Pallet { fn average_session_length() -> T::BlockNumber { - >::get().length + Round::::get().length } fn estimate_current_session_progress(now: T::BlockNumber) -> (Option, Weight) { - let round = >::get(); + let round = Round::::get(); let passed_blocks = now.saturating_sub(round.first); ( @@ -2616,7 +2615,7 @@ pub mod pallet { } fn estimate_next_session_rotation(_now: T::BlockNumber) -> (Option, Weight) { - let round = >::get(); + let round = Round::::get(); ( Some(round.first + round.length), From f459050e76ebed0c6d142a70d13a9f66730d60e5 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 2 Nov 2022 11:57:15 +0100 Subject: [PATCH 32/34] fix: replace RewardCount with two counters --- pallets/parachain-staking/src/benchmarking.rs | 9 +- .../parachain-staking/src/default_weights.rs | 6 +- pallets/parachain-staking/src/lib.rs | 335 +++++++++--------- pallets/parachain-staking/src/mock.rs | 4 +- pallets/parachain-staking/src/runtime_api.rs | 1 - pallets/parachain-staking/src/tests.rs | 215 ++++++----- .../src/weights/parachain_staking.rs | 2 +- .../src/weights/parachain_staking.rs | 2 +- 8 files changed, 321 insertions(+), 253 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index fd5346e521..7346be7029 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -568,28 +568,27 @@ benchmarks! { // mock high values to compensate for tiny values in unit test env let stake = T::CurrencyBalance::from(1_000_000_000_000_000_000u128); DelegatorState::::insert(&delegator, crate::types::Delegator { owner: collator.clone(), amount: stake}); - RewardCount::::insert(&collator, u32::MAX); + BlocksAuthored::::insert(&collator, u64::MAX.into()); assert!(Rewards::::get(&delegator).is_zero()); let origin = RawOrigin::Signed(delegator.clone()); }: _(origin) verify { assert!(!Rewards::::get(&delegator).is_zero()); + assert_eq!(BlocksRewarded::::get(&delegator), u64::MAX.into()); } increment_collator_rewards { - let m in 1 .. T::MaxDelegatorsPerCollator::get(); - let collator = setup_collator_candidates::(1, None)[0].clone(); - let delegators = fill_delegators::(m, collator.clone(), COLLATOR_ACCOUNT_SEED); // mock high counter to compensate for tiny amounts in unit test env - RewardCount::::insert(&collator, u32::MAX); + BlocksAuthored::::insert(&collator, u64::MAX.into()); assert!(Rewards::::get(&collator).is_zero(), "reward {:?}", Rewards::::get(&collator)); let origin = RawOrigin::Signed(collator.clone()); }: _(origin) verify { assert!(!Rewards::::get(&collator).is_zero()); + assert_eq!(BlocksRewarded::::get(&collator), u64::MAX.into()); } claim_rewards { diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs index bcf6987ff3..3aeb2e585d 100644 --- a/pallets/parachain-staking/src/default_weights.rs +++ b/pallets/parachain-staking/src/default_weights.rs @@ -67,7 +67,7 @@ pub trait WeightInfo { fn unlock_unstaked(u: u32, ) -> Weight; fn set_max_candidate_stake() -> Weight; fn increment_delegator_rewards() -> Weight; - fn increment_collator_rewards(_m: u32, ) -> Weight; + fn increment_collator_rewards() -> Weight; fn claim_rewards() -> Weight; fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight; } @@ -382,7 +382,7 @@ impl WeightInfo for SubstrateWeight {// KILT Blockch // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) // Storage: ParachainStaking InflationConfig (r:1 w:0) /// The range of component `m` is `[0, 35]`. - fn increment_collator_rewards(_m: u32, ) -> Weight { + fn increment_collator_rewards() -> Weight { Weight::from_ref_time(366_611_000 as u64) .saturating_add(T::DbWeight::get().reads(75 as u64)) .saturating_add(T::DbWeight::get().writes(72 as u64)) @@ -725,7 +725,7 @@ impl WeightInfo for () { // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) // Storage: ParachainStaking InflationConfig (r:1 w:0) /// The range of component `m` is `[0, 35]`. - fn increment_collator_rewards(_m: u32, ) -> Weight { + fn increment_collator_rewards() -> Weight { Weight::from_ref_time(366_611_000 as u64) .saturating_add(RocksDbWeight::get().reads(75 as u64)) .saturating_add(RocksDbWeight::get().writes(72 as u64)) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 435537c41c..c0561ab16e 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -209,6 +209,7 @@ pub mod pallet { + From + Into<::Balance> + From<::Balance> + + From + TypeInfo + MaxEncodedLen; @@ -611,21 +612,24 @@ pub mod pallet { #[pallet::getter(fn last_reward_reduction)] pub(crate) type LastRewardReduction = StorageValue<_, T::BlockNumber, ValueQuery>; - /// The counter of accumulated rewards for an account. + /// The number of authored blocks for collators. It is updated via the + /// `note_author` hook when authoring a block . + #[pallet::storage] + #[pallet::getter(fn blocks_authored)] + pub(crate) type BlocksAuthored = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>; + + /// The number of blocks for which rewards have been claimed by an address. /// - /// For collators, it reflects the number of authored blocks since the last - /// reward raise. Thus, everytime a collator authors a block, the - /// counter is increased. It is reset, when the collator increments their - /// rewards. + /// For collators, this can be at most BlocksAuthored. It is updated when + /// incrementing collator rewards, either when calling + /// `inc_collator_rewards` or updating the `InflationInfo`. /// - /// For delegators, it is used to determine the difference between the - /// delegator and corresponding collator when incrementing the delegator's - /// rewards. In this case, the counter is never incremented but reset to the - /// collator one when the delegator reward increment happens. - // TODO: Maybe rather use u64. Assuming 30 validators, u32 would suffice for 27 years of constant 12s blocktime. + /// For delegators, this can be at most BlocksAuthored of the collator.It is + /// updated when incrementing delegator rewards, either when calling + /// `inc_delegator_rewards` or updating the `InflationInfo`. #[pallet::storage] - #[pallet::getter(fn reward_count)] - pub(crate) type RewardCount = StorageMap<_, Twox64Concat, T::AccountId, u32, ValueQuery>; + #[pallet::getter(fn blocks_rewarded)] + pub(crate) type BlocksRewarded = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>; /// The accumulated rewards for collator candidates and delegators. /// @@ -731,9 +735,9 @@ pub mod pallet { /// /// The estimated average block time is twelve seconds. /// - /// NOTE: Iterates over CandidatePool for each candidate over their - /// delegators to set rewards. Needs to be improved when scaling up - /// `MaxTopCandidates`. + /// NOTE: Iterates over CandidatePool and for each candidate over their + /// delegators to update their rewards before the reward rates change. + /// Needs to be improved when scaling up `MaxTopCandidates`. /// /// The dispatch origin must be Root. /// @@ -748,37 +752,16 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { ensure_root(origin)?; - let inflation = InflationInfo::new( - T::BLOCKS_PER_YEAR.saturated_into(), + // Update inflation and increment rewards + let (num_col, num_del) = Self::do_set_inflation( + T::BLOCKS_PER_YEAR, collator_max_rate_percentage, collator_annual_reward_rate_percentage, delegator_max_rate_percentage, delegator_annual_reward_rate_percentage, - ); - - ensure!( - inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), - Error::::InvalidSchedule - ); - - // set rewards for all collators and delegators due - let mut num_delegators = 0; - CandidatePool::::iter().for_each(|(id, state)| { - num_delegators = num_delegators.max(Self::do_inc_collator_reward(&id, state.stake)); - }); + )?; - Self::deposit_event(Event::RoundInflationSet( - inflation.collator.max_rate, - inflation.collator.reward_rate.per_block, - inflation.delegator.max_rate, - inflation.delegator.reward_rate.per_block, - )); - InflationConfig::::put(inflation); - Ok(Some(::WeightInfo::set_inflation( - CandidatePool::::count(), - num_delegators.saturated_into(), - )) - .into()) + Ok(Some(::WeightInfo::set_inflation(num_col, num_del)).into()) } /// Set the maximum number of collator candidates that can be selected @@ -1245,7 +1228,7 @@ pub mod pallet { }; CandidatePool::::insert(&collator, state); - // increment rewards for origin + their delegators and reset reward counter + // increment rewards for collator and update number of rewarded blocks Self::do_inc_collator_reward(&collator, before_stake); Self::deposit_event(Event::CollatorStakedMore(collator, before_stake, after_stake)); @@ -1313,7 +1296,7 @@ pub mod pallet { }; CandidatePool::::insert(&collator, state); - // increment rewards for origin + their delegators and reset reward counter + // increment rewards and update number of rewarded blocks Self::do_inc_collator_reward(&collator, before_stake); Self::deposit_event(Event::CollatorStakedLess(collator, before_stake, after)); @@ -1443,8 +1426,9 @@ pub mod pallet { DelegatorState::::insert(&acc, delegator_state); LastDelegation::::insert(&acc, delegation_counter); - // initiate reward counter to match the current state of the candidate - RewardCount::::insert(&acc, RewardCount::::get(&collator)); + // initiate rewarded counter to match the current autored counter of the + // candidate + BlocksRewarded::::insert(&acc, BlocksAuthored::::get(&collator)); Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); Ok(Some(::WeightInfo::join_delegators( @@ -1546,7 +1530,7 @@ pub mod pallet { 0u32 }; - // set rewards and reset reward counter + // increment rewards and update number of rewarded blocks Self::do_inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); CandidatePool::::insert(&candidate, collator); @@ -1629,7 +1613,7 @@ pub mod pallet { 0u32 }; - // set rewards and reset reward counter + // increment rewards and update number of rewarded blocks Self::do_inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); CandidatePool::::insert(&candidate, collator); @@ -1699,30 +1683,24 @@ pub mod pallet { Ok(()) } - /// Actively increment the rewards of a collator and their delegators. + /// Actively increment the rewards of a collator. /// /// The same effect is triggered by changing the stake or leaving the /// network. /// /// The dispatch origin must be a collator. - #[pallet::weight(::WeightInfo::increment_collator_rewards(T::MaxDelegatorsPerCollator::get()))] - pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResultWithPostInfo { + #[pallet::weight(::WeightInfo::increment_collator_rewards())] + pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResult { let collator = ensure_signed(origin)?; let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - // early exit - let reward_count = RewardCount::::get(&collator); - ensure!(!reward_count.is_zero(), Error::::RewardsNotFound); + // increment rewards and update number of rewarded blocks + Self::do_inc_collator_reward(&collator, state.stake); - let num_delegators = Self::do_inc_collator_reward(&collator, state.stake); - Ok(Some(::WeightInfo::increment_collator_rewards( - num_delegators.saturated_into(), - )) - .into()) + Ok(()) } - /// Actively increment the rewards of a delegator for all their - /// delegations. + /// Actively increment the rewards of a delegator. /// /// The same effect is triggered by changing the stake or revoking /// delegations. @@ -1734,16 +1712,21 @@ pub mod pallet { let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; let collator = delegation.owner; + // increment rewards and update number of rewarded blocks Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); - ensure!(!Rewards::::get(&delegator).is_zero(), Error::::RewardsNotFound); Ok(()) } /// Executes the annual reduction of the reward rates for collators and - /// delegators. Moreover, sets rewards for all collators and delegators + /// delegators. + /// + /// Moreover, sets rewards for all collators and delegators /// before adjusting the inflation. /// + /// The dispatch origin can be any signed one because we bail if called + /// too early. + /// /// Emits `RoundInflationSet`. #[pallet::weight(::WeightInfo::execute_scheduled_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] pub fn execute_scheduled_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { @@ -1751,54 +1734,40 @@ pub mod pallet { let now = frame_system::Pallet::::block_number(); let year = now / T::BLOCKS_PER_YEAR; - let last_update = LastRewardReduction::::get(); + // We can already mutate thanks to extrinsics being transactional + let last_update = LastRewardReduction::::mutate(|last_year| { + let old = *last_year; + *last_year = old.saturating_add(T::BlockNumber::one()); + old + }); + // Bail if less than a year (in terms of number of blocks) has passed since the + // last update ensure!(year > last_update, Error::::TooEarly); // Calculate new inflation based on last year let inflation = InflationConfig::::get(); + // collator reward rate decreases by 2% p.a. of the previous one let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); + // delegator reward rate should be 6% in 2nd year and 0% afterwards let d_reward_rate = if year == T::BlockNumber::one() { Perquintill::from_percent(6) } else { Perquintill::zero() }; - let new_inflation = InflationInfo::new( - T::BLOCKS_PER_YEAR.saturated_into(), + + // Update inflation and increment rewards + let (num_col, num_del) = Self::do_set_inflation( + T::BLOCKS_PER_YEAR, inflation.collator.max_rate, c_reward_rate, inflation.delegator.max_rate, d_reward_rate, - ); - // should never fail - ensure!( - new_inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), - Error::::InvalidSchedule - ); - - // set rewards for all collators and delegators before updating reward rates - let mut max_num_delegators = 0; - CandidatePool::::iter().for_each(|(id, state)| { - max_num_delegators = max_num_delegators.max(Self::do_inc_collator_reward(&id, state.stake)); - }); - - // update inflation config - InflationConfig::::put(new_inflation.clone()); - LastRewardReduction::::put(year); - Self::deposit_event(Event::RoundInflationSet( - new_inflation.collator.max_rate, - new_inflation.collator.reward_rate.per_block, - new_inflation.delegator.max_rate, - new_inflation.delegator.reward_rate.per_block, - )); + )?; - Ok(Some(::WeightInfo::execute_scheduled_reward_change( - CandidatePool::::count(), - max_num_delegators.saturated_into(), - )) - .into()) + Ok(Some(::WeightInfo::set_inflation(num_col, num_del)).into()) } } @@ -1819,6 +1788,63 @@ pub mod pallet { None } } + /// Set the annual inflation rate to derive per-round inflation. + /// + /// The inflation details are considered valid if the annual reward rate + /// is approximately the per-block reward rate multiplied by the + /// estimated* total number of blocks per year. + /// + /// The estimated average block time is twelve seconds. + /// + /// NOTE: Iterates over CandidatePool and for each candidate over their + /// delegators to update their rewards before the reward rates change. + /// Needs to be improved when scaling up `MaxTopCandidates`. + /// + /// Emits `RoundInflationSet`. + fn do_set_inflation( + blocks_per_year: T::BlockNumber, + col_max_rate: Perquintill, + col_reward_rate: Perquintill, + del_max_rate: Perquintill, + del_reward_rate: Perquintill, + ) -> Result<(u32, u32), DispatchError> { + // Check validity of new inflation + let inflation = InflationInfo::new( + blocks_per_year.saturated_into(), + col_max_rate, + col_reward_rate, + del_max_rate, + del_reward_rate, + ); + ensure!( + inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), + Error::::InvalidSchedule + ); + + // Increment rewards for all collators and delegators due to change of reward + // rates + let mut num_delegators = 0u32; + CandidatePool::::iter().for_each(|(id, state)| { + // increment collator rewards + Self::do_inc_collator_reward(&id, state.stake); + // increment delegator rewards + state.delegators.into_iter().for_each(|delegator_state| { + Self::do_inc_delegator_reward(&delegator_state.owner, delegator_state.amount, &id); + num_delegators = num_delegators.saturating_add(1u32); + }); + }); + + // Update inflation + InflationConfig::::put(inflation); + Self::deposit_event(Event::RoundInflationSet( + col_max_rate, + col_reward_rate, + del_max_rate, + del_reward_rate, + )); + + Ok((CandidatePool::::count(), num_delegators)) + } /// Update the top candidates and total amount at stake after mutating /// an active candidate's stake. @@ -2009,8 +2035,9 @@ pub mod pallet { state.total = state.total.saturating_sub(delegator_stake); let new_total = state.total; - // set rewards + // increment rewards and kill storage for number of rewarded blocks Self::do_inc_delegator_reward(&delegator, delegator_stake, &collator); + BlocksRewarded::::remove(&delegator); // we don't unlock immediately Self::prep_unstake(&delegator, delegator_stake, false)?; @@ -2099,7 +2126,7 @@ pub mod pallet { // update total stake state.total = state.total.saturating_sub(stake_to_remove.amount); - // set rewards for kicked delegator + // update rewards for kicked delegator Self::do_inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); // prepare unstaking for kicked delegator Self::prep_unstake(&stake_to_remove.owner, stake_to_remove.amount, true)?; @@ -2215,6 +2242,8 @@ pub mod pallet { ) -> DispatchResult { // iterate over delegators for stake in &state.delegators[..] { + // increment rewards + Self::do_inc_delegator_reward(&stake.owner, stake.amount, collator); // prepare unstaking of delegator Self::prep_unstake(&stake.owner, stake.amount, true)?; // remove delegation from delegator state @@ -2230,7 +2259,7 @@ pub mod pallet { // *** No Fail beyond this point *** - // increment rewards of collator and their delegators + // increment rewards of collator Self::do_inc_collator_reward(collator, state.stake); // disable validator for next session if they were in the set of validators @@ -2248,6 +2277,9 @@ pub mod pallet { // FIXME: Does not prevent the collator from being able to author a block in this (or potentially the next) session. See https://github.com/paritytech/substrate/issues/8004 .map(pallet_session::Pallet::::disable_index); + // Kill storage + BlocksAuthored::::remove(&collator); + BlocksRewarded::::remove(&collator); CandidatePool::::remove(&collator); Ok(()) } @@ -2388,91 +2420,74 @@ pub mod pallet { /// Calculates the staking rewards for a given account address. /// + /// Subtracts the number of rewarded blocks from the number of authored + /// blocks by the collator and multiplies that with the current stake + /// as well as reward rate. + /// /// At least used in Runtime API. pub fn get_unclaimed_staking_rewards(acc: &T::AccountId) -> BalanceOf { - let mut reward_count = RewardCount::::get(acc); + let count_rewarded = BlocksRewarded::::get(acc); let rewards = Rewards::::get(acc); // delegators and collators need to be handled differently if let Some(delegator_state) = DelegatorState::::get(acc) { - // delegator reward counts do not automatically increment in order to be - // scalable, see [increment_delegator_rewards] for details - // therefore, we need to query the counter of the collator - // (`delegator_stare.owner`) - reward_count = reward_count.saturating_add(RewardCount::::get(&delegator_state.owner)); + // #blocks for unclaimed staking rewards equals + // #blocks_authored_by_collator - #blocks_claimed_by_delegator + let count_unclaimed = BlocksAuthored::::get(&delegator_state.owner).saturating_sub(count_rewarded); let stake = delegator_state.amount; - // rewards += stake * (self_count + collator_count) * delegator_reward_rate - rewards.saturating_add(Self::calc_block_rewards_delegator(stake, reward_count.into())) + // rewards += stake * reward_count * delegator_reward_rate + rewards.saturating_add(Self::calc_block_rewards_delegator(stake, count_unclaimed.into())) } else if Self::is_active_candidate(acc).is_some() { + // #blocks for unclaimed staking rewards equals + // #blocks_authored_by_collator - #blocks_claimed_by_collator + let count_unclaimed = BlocksAuthored::::get(acc).saturating_sub(count_rewarded); let stake = CandidatePool::::get(acc) .map(|state| state.stake) .unwrap_or_else(BalanceOf::::zero); // rewards += stake * self_count * collator_reward_rate - rewards.saturating_add(Self::calc_block_rewards_collator(stake, reward_count.into())) + rewards.saturating_add(Self::calc_block_rewards_collator(stake, count_unclaimed.into())) } else { BalanceOf::::zero() } } - /// Increment the accumulated rewards of a collator by consuming their - /// current rewards counter. - /// - /// Moreover, automatically increments all associated delegators since - /// their reward increment is dependend on the collator reward counter. - /// - /// Resets all reward counters of the collator and their delegators to - /// zero. - fn do_inc_collator_reward(collator: &T::AccountId, stake: BalanceOf) -> usize { - // get reward counters - let col_reward_count = RewardCount::::get(collator); - - // set reward data for collator - Rewards::::mutate(collator, |reward| { - *reward = reward.saturating_add(Self::calc_block_rewards_collator(stake, col_reward_count.into())); + /// Increment the accumulated rewards of a collator. + /// + /// Updates Rewarded(col) and sets BlocksRewarded(col) to equal + /// BlocksAuthored(col). + fn do_inc_collator_reward(acc: &T::AccountId, stake: BalanceOf) { + let count_authored = BlocksAuthored::::get(acc); + // We can already mutate thanks to extrinsics being transactional + let count_rewarded = BlocksRewarded::::mutate(acc, |rewarded| { + let old = *rewarded; + *rewarded = count_authored; + old }); + let unclaimed_blocks = count_authored.saturating_sub(count_rewarded); - // set reward data for delegators - let num_delegators = if let Some(state) = CandidatePool::::get(collator.clone()) { - let num_delegators = state.delegators.len(); - for Stake { owner, amount } in state.delegators { - Self::do_inc_delegator_reward(&owner, amount, collator); - // Reset delegator counter since collator counter will be reset - RewardCount::::insert(owner, 0); - } - num_delegators - } else { - 0usize - }; - - // Reset collator reward count - RewardCount::::insert(collator, 0); - - num_delegators + Rewards::::mutate(acc, |reward| { + *reward = reward.saturating_add(Self::calc_block_rewards_collator(stake, unclaimed_blocks.into())); + }); } - /// Increment the accumulated rewards of a delegator by consuming their - /// current rewards counter. The counter will be reset to the collator - /// counter. - fn do_inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) -> Weight { - // get reward counters - let del_reward_count = RewardCount::::get(acc); - let col_reward_count = RewardCount::::get(col); - let diff = col_reward_count.saturating_sub(del_reward_count); - - // only update if collator has higher reward count - if diff > 0 { - Rewards::::mutate(acc, |reward| { - *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, diff.into())); - }); - // align with collator counter such that incrementing would - // lead to 0 rewards until the collator counter increases - RewardCount::::insert(acc, col_reward_count); + /// Increment the accumulated rewards of a delegator by checking the + /// number of authored blocks by the collator. + /// + /// Updates Rewarded(del) and sets BlocksRewarded(del) to equal + /// BlocksAuthored(col). + fn do_inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) { + let count_authored = BlocksAuthored::::get(col); + // We can already mutate thanks to extrinsics being transactional + let count_rewarded = BlocksRewarded::::mutate(acc, |rewarded| { + let old = *rewarded; + *rewarded = count_authored; + old + }); + let unclaimed_blocks = count_authored.saturating_sub(count_rewarded); - // 4 reads from reward calc - T::DbWeight::get().reads_writes(6, 2) - } else { - T::DbWeight::get().reads(2) - } + Rewards::::mutate(acc, |reward| { + *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, unclaimed_blocks.into())) + }); } /// Calculates the current staking and reward rates for collators and @@ -2515,8 +2530,8 @@ pub mod pallet { if CandidatePool::::get(&author).is_some() { // necessary to compensate for a potentially fluctuating number of collators let authors = pallet_session::Pallet::::validators(); - RewardCount::::mutate(&author, |count| { - *count = count.saturating_add(authors.len().saturated_into::()); + BlocksAuthored::::mutate(&author, |count| { + *count = count.saturating_add(authors.len().saturated_into::()); }); } diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index d7d482fe8f..1a5281dbd1 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -386,7 +386,7 @@ pub(crate) fn roll_to_claim_rewards(n: BlockNumber, authors: Vec. // If you feel like getting in touch with us, you can do so at info@botlabs.org -#![cfg_attr(not(feature = "std"), no_std)] use frame_support::dispatch::fmt::Debug; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index b3f43a5bc0..286d634801 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -946,8 +946,9 @@ fn multiple_delegations() { assert!(StakePallet::unstaking(9).is_empty()); assert!(StakePallet::rewards(9).is_zero()); assert_ok!(StakePallet::join_delegators(Origin::signed(11), 2, 11)); - // 11 should be initiated with the same reward counter as their collator 2 - assert_eq!(StakePallet::reward_count(2), StakePallet::reward_count(11)); + // 11 should be initiated with the same rewarded counter as the authored counter + // by their collator 2 + assert_eq!(StakePallet::blocks_rewarded(2), StakePallet::blocks_authored(11)); assert!(StakePallet::delegator_state(9).is_none()); assert_eq!(StakePallet::unstaking(9).get(&23), Some(&10u128)); @@ -2781,11 +2782,12 @@ fn adjust_reward_rates() { .saturating_sub(10_000_000 * DECIMALS) .saturating_sub(c_rewards_0) .saturating_sub(c_rewards_1); + assert!(c_rewards_1 > c_rewards_2); + // should be zero because we set reward rate to zero let d_rewards_2 = Balances::free_balance(&2) .saturating_sub(90_000_000 * DECIMALS) .saturating_sub(d_rewards_0) .saturating_sub(d_rewards_1); - assert!(c_rewards_1 > c_rewards_2); assert!(d_rewards_2.is_zero()); }); } @@ -3823,18 +3825,30 @@ fn rewards_candidate_stake_more() { .execute_with(|| { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_authored(2).is_zero()); + assert!(StakePallet::blocks_authored(3).is_zero()); (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::blocks_rewarded(id).is_zero()); + assert!(StakePallet::rewards(id).is_zero()); }); - // stake more to trigger reward incrementing + // stake less to trigger reward incrementing for collator assert_ok!(StakePallet::candidate_stake_more(Origin::signed(1), DECIMALS)); - (1..=3).for_each(|id| { - assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::rewards(1).is_zero()); + assert!(!StakePallet::blocks_rewarded(1).is_zero()); + // delegator reward storage should be untouched + (2..=3).for_each(|id| { + assert!( + StakePallet::rewards(id).is_zero(), + "Rewards not zero for acc_id {:?}", + id + ); + assert!( + StakePallet::blocks_rewarded(id).is_zero(), + "BlocksRewaeded not zero for acc_id {:?}", + id + ); }); }); } @@ -3849,18 +3863,30 @@ fn rewards_candidate_stake_less() { .execute_with(|| { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_authored(2).is_zero()); + assert!(StakePallet::blocks_authored(3).is_zero()); (1..=3).for_each(|id| { + assert!(StakePallet::blocks_rewarded(id).is_zero()); assert!(StakePallet::rewards(id).is_zero()); }); - // stake less to trigger reward incrementing + // stake less to trigger reward incrementing for collator assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), DECIMALS)); - (1..=3).for_each(|id| { - assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::rewards(1).is_zero()); + assert!(!StakePallet::blocks_rewarded(1).is_zero()); + // delegator reward storage should be untouched + (2..=3).for_each(|id| { + assert!( + StakePallet::rewards(id).is_zero(), + "Rewards not zero for acc_id {:?}", + id + ); + assert!( + StakePallet::blocks_rewarded(id).is_zero(), + "BlocksRewaeded not zero for acc_id {:?}", + id + ); }); }); } @@ -3898,22 +3924,37 @@ fn rewards_candidate_leave_network() { Some(2), ], ); - assert_eq!(StakePallet::reward_count(1), 4 * 2); + // Only authored should be bumped for collator, not rewarded + assert_eq!(StakePallet::blocks_authored(1), 4 * 2); + assert!(StakePallet::blocks_rewarded(1).is_zero()); // count for delegators should not be incremented - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); // rewards should not be incremented (1..=3).for_each(|id| { assert!(StakePallet::rewards(id).is_zero()); }); - // execute leave intent to trigger reward incrementing + // execute leave intent to trigger reward incrementing for collator and + // delegators assert_ok!(StakePallet::execute_leave_candidates(Origin::signed(1), 1)); - (1..=3).for_each(|id| { - assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + + // reward counting storages should be killed for collator + assert!(StakePallet::blocks_authored(1).is_zero()); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + assert!(!StakePallet::rewards(1).is_zero()); + + // reward counting storages should NOT be killed for delegators + (2..=3).for_each(|id| { + assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards acc_id {:?}", id); + assert_eq!( + StakePallet::blocks_rewarded(id), + 4 * 2, + "Rewarded blocks Delegator {:?} do not match up with exited collator", + id + ); }); }); } @@ -3938,19 +3979,29 @@ fn rewards_force_remove_candidate() { // removing triggers reward increment for collator 1 and delegators 4, 5 assert_ok!(StakePallet::force_remove_candidate(Origin::root(), 1)); + // rewarded counter storage should be killed for collator + assert!(StakePallet::blocks_authored(1).is_zero()); + assert!(StakePallet::blocks_rewarded(1).is_zero()); (1..=3).for_each(|id| { - assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards for acc_id {:?}", id); + if id > 1 { + assert_eq!( + StakePallet::blocks_rewarded(id), + 2, + "Rewarded counter does not match for delegator {:?}", + id + ); + } }); (4..=5).for_each(|id| { assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::blocks_rewarded(id).is_zero(), "acc_id {:?}", id); }); }); } #[test] -fn reward_count_join_delegators() { +fn blocks_rewarded_join_delegators() { ExtBuilder::default() .with_balances(vec![(1, 100), (2, 100)]) .with_collators(vec![(1, 100)]) @@ -3958,10 +4009,12 @@ fn reward_count_join_delegators() { .execute_with(|| { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); assert_ok!(StakePallet::join_delegators(Origin::signed(2), 1, 100)); - // delegator should have same counter as collator upon joining - assert_eq!(StakePallet::reward_count(2), 1); + // delegator's rewarded counter should equal of collator's authored counter upon + // joining + assert_eq!(StakePallet::blocks_rewarded(2), StakePallet::blocks_authored(1)); }); } @@ -3975,23 +4028,24 @@ fn rewards_delegator_stake_more() { .execute_with(|| { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); (1..=3).for_each(|id| { assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); }); - // stake more to trigger reward incrementing just for 3 + // stake less to trigger reward incrementing just for 3 assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, DECIMALS)); // 1 should still have counter 1 but no rewards - assert_eq!(StakePallet::reward_count(1), 1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); assert!(StakePallet::rewards(1).is_zero()); // 2 should still have neither rewards nor counter - assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::blocks_rewarded(2).is_zero()); assert!(StakePallet::rewards(2).is_zero()); // 3 should have rewards and the same counter as 1 - assert_eq!(StakePallet::reward_count(3), 1); + assert_eq!(StakePallet::blocks_rewarded(3), 1); assert!(!StakePallet::rewards(3).is_zero()); }); } @@ -4006,9 +4060,9 @@ fn rewards_delegator_stake_less() { .execute_with(|| { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); (1..=3).for_each(|id| { assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); }); @@ -4016,13 +4070,14 @@ fn rewards_delegator_stake_less() { // stake less to trigger reward incrementing just for 3 assert_ok!(StakePallet::delegator_stake_less(Origin::signed(3), 1, DECIMALS)); // 1 should still have counter 1 but no rewards - assert_eq!(StakePallet::reward_count(1), 1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); assert!(StakePallet::rewards(1).is_zero()); // 2 should still have neither rewards nor counter - assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::blocks_rewarded(2).is_zero()); assert!(StakePallet::rewards(2).is_zero()); // 3 should have rewards and the same counter as 1 - assert_eq!(StakePallet::reward_count(3), 1); + assert_eq!(StakePallet::blocks_rewarded(3), 1); assert!(!StakePallet::rewards(3).is_zero()); }); } @@ -4049,16 +4104,16 @@ fn rewards_delegator_replaced() { .execute_with(|| { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); + assert_eq!(StakePallet::blocks_authored(1), 1); // 6 kicks 5 assert_ok!(StakePallet::join_delegators(Origin::signed(6), 1, 2 * DECIMALS)); // 5 should have rewards and counter updated assert!(!StakePallet::rewards(5).is_zero()); - assert_eq!(StakePallet::reward_count(5), 1); + assert_eq!(StakePallet::blocks_rewarded(5), 1); // 6 should not have rewards but same counter as former collator assert!(StakePallet::rewards(6).is_zero()); - assert_eq!(StakePallet::reward_count(6), 1); + assert_eq!(StakePallet::blocks_rewarded(6), 1); }); } @@ -4072,21 +4127,22 @@ fn rewards_delegator_leaves() { .execute_with(|| { // note collator once to set their counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); (1..=3).for_each(|id| { assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); }); - // only 3 should have non-zero rewards and their counter reset + // only 3 should have non-zero rewards assert_ok!(StakePallet::leave_delegators(Origin::signed(3))); - assert_eq!(StakePallet::reward_count(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); assert!(StakePallet::rewards(1).is_zero()); - assert!(StakePallet::reward_count(2).is_zero()); + assert!(StakePallet::blocks_rewarded(2).is_zero()); assert!(StakePallet::rewards(2).is_zero()); assert!(!StakePallet::rewards(3).is_zero()); - assert_eq!(StakePallet::reward_count(3), 1); + // counter should be reset due to leaving + assert!(StakePallet::blocks_rewarded(3).is_zero()); }); } @@ -4118,9 +4174,9 @@ fn rewards_set_inflation() { hundred, hundred )); - // rewards should be set and counter reset + // rewards and counters should be set (1..=5).for_each(|id| { - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::blocks_rewarded(id).is_zero(), "acc_id {:?}", id); assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); }); }); @@ -4145,6 +4201,8 @@ fn rewards_yearly_inflation_adjustment() { StakePallet::note_author(2); System::set_block_number(::BLOCKS_PER_YEAR - 1); roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); + assert!(!StakePallet::blocks_authored(1).is_zero()); + assert!(!StakePallet::blocks_authored(2).is_zero()); // rewards should not be triggered before executing pending adjustment (1..=5).for_each(|id| { @@ -4154,8 +4212,12 @@ fn rewards_yearly_inflation_adjustment() { // execute to trigger reward increment assert_ok!(StakePallet::execute_scheduled_reward_change(Origin::signed(1))); (1..=5).for_each(|id| { - assert!(StakePallet::reward_count(id).is_zero(), "acc_id {:?}", id); - assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!( + !StakePallet::blocks_rewarded(id).is_zero(), + "Zero rewarded blocks for acc_id {:?}", + id + ); + assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards for acc_id {:?}", id); }); }); } @@ -4168,15 +4230,7 @@ fn rewards_incrementing_and_claiming() { .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) .build() .execute_with(|| { - // claiming or incrementing should not be possible with zero counter - assert_noop!( - StakePallet::increment_collator_rewards(Origin::signed(1)), - Error::::RewardsNotFound - ); - assert_noop!( - StakePallet::increment_delegator_rewards(Origin::signed(2)), - Error::::RewardsNotFound - ); + // claiming should not be possible with zero counters (1..=3).for_each(|id| { assert_noop!( StakePallet::claim_rewards(Origin::signed(id)), @@ -4186,8 +4240,8 @@ fn rewards_incrementing_and_claiming() { // note once to set counter to 1 StakePallet::note_author(1); - assert_eq!(StakePallet::reward_count(1), 1); - assert!(StakePallet::reward_count(2).is_zero()); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); // claiming should not be possible before incrementing rewards (1..=3).for_each(|id| { @@ -4199,37 +4253,36 @@ fn rewards_incrementing_and_claiming() { // increment rewards for 2 and match counter to collator assert_ok!(StakePallet::increment_delegator_rewards(Origin::signed(2))); - assert_eq!(StakePallet::reward_count(2), 1); + assert_eq!(StakePallet::blocks_rewarded(2), 1); let rewards_2 = StakePallet::rewards(2); assert!(!rewards_2.is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); assert!(StakePallet::rewards(3).is_zero()); - // should set rewards for delegator 3 as well + // should only update rewards for collator as well assert_ok!(StakePallet::increment_collator_rewards(Origin::signed(1))); - assert!(StakePallet::reward_count(1).is_zero()); + assert_eq!(StakePallet::blocks_rewarded(1), StakePallet::blocks_authored(1)); assert!(!StakePallet::rewards(1).is_zero()); - // counter of delegators should be reset to 0 (= cols counter) - assert!(StakePallet::reward_count(2).is_zero()); - assert!(StakePallet::reward_count(3).is_zero()); // rewards of 2 should not be changed assert_eq!(StakePallet::rewards(2), rewards_2); - // 3 should have rewards now (passively) - assert!(!StakePallet::rewards(3).is_zero()); + // 3 should still not have blocks rewarded bumped + assert!(StakePallet::blocks_rewarded(3).is_zero()); // claim for 1 to move rewards into balance assert_ok!(StakePallet::claim_rewards(Origin::signed(1))); - assert!(StakePallet::reward_count(1).is_zero()); assert!(StakePallet::rewards(1).is_zero()); // delegator situation should be unchanged assert!(Balances::free_balance(&1) > DECIMALS); assert_eq!(Balances::free_balance(&2), DECIMALS); assert_eq!(Balances::free_balance(&3), DECIMALS); + // incrementing again should not change anything because collator has not + // authored blocks since last inc + assert_ok!(StakePallet::increment_delegator_rewards(Origin::signed(2))); + assert_eq!(StakePallet::blocks_rewarded(2), 1); // claim for 2 to move rewards into balance assert_ok!(StakePallet::claim_rewards(Origin::signed(2))); assert!(Balances::free_balance(&2) > DECIMALS); - assert!(StakePallet::reward_count(2).is_zero()); assert!(StakePallet::rewards(2).is_zero()); assert_eq!(Balances::free_balance(&3), DECIMALS); diff --git a/runtimes/peregrine/src/weights/parachain_staking.rs b/runtimes/peregrine/src/weights/parachain_staking.rs index 4c9ffae8c7..9ff79ed390 100644 --- a/runtimes/peregrine/src/weights/parachain_staking.rs +++ b/runtimes/peregrine/src/weights/parachain_staking.rs @@ -355,7 +355,7 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) // Storage: ParachainStaking InflationConfig (r:1 w:0) /// The range of component `m` is `[0, 35]`. - fn increment_collator_rewards(_m: u32, ) -> Weight { + fn increment_collator_rewards() -> Weight { Weight::from_ref_time(366_611_000 as u64) .saturating_add(T::DbWeight::get().reads(75 as u64)) .saturating_add(T::DbWeight::get().writes(72 as u64)) diff --git a/runtimes/spiritnet/src/weights/parachain_staking.rs b/runtimes/spiritnet/src/weights/parachain_staking.rs index 4c9ffae8c7..9ff79ed390 100644 --- a/runtimes/spiritnet/src/weights/parachain_staking.rs +++ b/runtimes/spiritnet/src/weights/parachain_staking.rs @@ -355,7 +355,7 @@ impl parachain_staking::WeightInfo for WeightInfo { // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) // Storage: ParachainStaking InflationConfig (r:1 w:0) /// The range of component `m` is `[0, 35]`. - fn increment_collator_rewards(_m: u32, ) -> Weight { + fn increment_collator_rewards() -> Weight { Weight::from_ref_time(366_611_000 as u64) .saturating_add(T::DbWeight::get().reads(75 as u64)) .saturating_add(T::DbWeight::get().writes(72 as u64)) From 39e3716d372deaf1c3c17ab26e3dcfb21e86f319 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 2 Nov 2022 12:12:09 +0100 Subject: [PATCH 33/34] refactor: rm col input for del stake adjustment --- pallets/parachain-staking/src/benchmarking.rs | 17 ++-- pallets/parachain-staking/src/lib.rs | 22 ++--- pallets/parachain-staking/src/tests.rs | 98 ++++++++----------- 3 files changed, 55 insertions(+), 82 deletions(-) diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs index 7346be7029..1a6c10f763 100644 --- a/pallets/parachain-staking/src/benchmarking.rs +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -100,7 +100,6 @@ where if let Some(delegator) = delegator { assert_ok!(Pallet::::delegator_stake_less( RawOrigin::Signed(delegator.clone()).into(), - T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::one() )); } else { @@ -429,16 +428,15 @@ benchmarks! { // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), T::CurrencyBalance::from(u as u64))); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::CurrencyBalance::from(u as u64))); assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); // fill unstake BTreeMap by unstaked many entries of 1 fill_unstaking::(&collator, Some(&delegator), u as u64); assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); - let unlookup_collator = T::Lookup::unlookup(collator.clone()); let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin, unlookup_collator, amount) + }: _(origin, amount) verify { let state = CandidatePool::::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); @@ -466,17 +464,16 @@ benchmarks! { // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), amount + amount)); assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block - assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); + assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), amount)); assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); assert_eq!(Unstaking::::get(&delegator).len(), 1); - let unlookup_collator = T::Lookup::unlookup(collator.clone()); let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin, unlookup_collator, amount) + }: _(origin, amount) verify { let state = CandidatePool::::get(&collator).unwrap(); assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); @@ -504,11 +501,11 @@ benchmarks! { // increase stake so we can unstake, because current stake is minimum T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount + amount)); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), amount + amount)); assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); // decrease stake once so we have an unstaking entry for this block - assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), T::Lookup::unlookup(collator.clone()), amount)); + assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), amount)); assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); assert_eq!(Unstaking::::get(&delegator).len(), 1); diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index c0561ab16e..3e168b7449 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1487,16 +1487,12 @@ pub mod pallet { T::MaxDelegatorsPerCollator::get(), T::MaxUnstakeRequests::get().saturated_into::()) )] - pub fn delegator_stake_more( - origin: OriginFor, - candidate: ::Source, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { + pub fn delegator_stake_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; ensure!(!more.is_zero(), Error::::ValStakeZero); - let candidate = T::Lookup::lookup(candidate)?; let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let candidate = delegation.owner.clone(); let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); let stake_after = delegation @@ -1565,19 +1561,15 @@ pub mod pallet { T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get() ))] - pub fn delegator_stake_less( - origin: OriginFor, - candidate: ::Source, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { + pub fn delegator_stake_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; ensure!(!less.is_zero(), Error::::ValStakeZero); - let candidate = T::Lookup::lookup(candidate)?; - let mut delegations = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let candidate = delegation.owner.clone(); let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let stake_after = delegations + let stake_after = delegation .try_decrement(candidate.clone(), less) .map_err(|_| Error::::DelegationNotFound)? .ok_or(Error::::Underflow)?; @@ -1617,7 +1609,7 @@ pub mod pallet { Self::do_inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); CandidatePool::::insert(&candidate, collator); - DelegatorState::::insert(&delegator, delegations); + DelegatorState::::insert(&delegator, delegation); Self::deposit_event(Event::DelegatorStakedLess(delegator, candidate, before_total, after)); Ok(Some(::WeightInfo::delegator_stake_less( diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs index 286d634801..a08805d1a4 100644 --- a/pallets/parachain-staking/src/tests.rs +++ b/pallets/parachain-staking/src/tests.rs @@ -1086,13 +1086,13 @@ fn should_update_total_stake() { ); old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(7), 1, 50)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(7), 50)); assert_noop!( - StakePallet::delegator_stake_more(Origin::signed(7), 1, 0), + StakePallet::delegator_stake_more(Origin::signed(7), 0), Error::::ValStakeZero ); assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(7), 1, 0), + StakePallet::delegator_stake_less(Origin::signed(7), 0), Error::::ValStakeZero ); assert_eq!( @@ -1104,7 +1104,7 @@ fn should_update_total_stake() { ); old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(7), 1, 50)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(7), 50)); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -1287,40 +1287,24 @@ fn delegators_bond() { Error::::AlreadyDelegating ); assert_noop!( - StakePallet::delegator_stake_more(Origin::signed(1), 2, 50), + StakePallet::delegator_stake_more(Origin::signed(1), 50), Error::::DelegatorNotFound ); assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(1), 2, 50), + StakePallet::delegator_stake_less(Origin::signed(1), 50), Error::::DelegatorNotFound ); assert_noop!( - StakePallet::delegator_stake_more(Origin::signed(6), 2, 50), - Error::::DelegationNotFound - ); - assert_noop!( - StakePallet::delegator_stake_more(Origin::signed(7), 6, 50), - Error::::CandidateNotFound - ); - assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(7), 6, 50), - Error::::CandidateNotFound - ); - assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(6), 1, 11), + StakePallet::delegator_stake_less(Origin::signed(6), 11), Error::::Underflow ); assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(6), 1, 8), + StakePallet::delegator_stake_less(Origin::signed(6), 8), Error::::DelegationBelowMin ); - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 1, 10)); - assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(6), 2, 5), - Error::::DelegationNotFound - ); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 10)); assert_noop!( - StakePallet::delegator_stake_more(Origin::signed(6), 1, 81), + StakePallet::delegator_stake_more(Origin::signed(6), 81), BalancesError::::InsufficientBalance ); assert_noop!( @@ -2362,12 +2346,12 @@ fn unlock_unstaked() { assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10)); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10)); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10),); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10),); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10),); let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = BoundedBTreeMap::new(); assert_ok!(unstaking.try_insert(3, 60)); @@ -2390,7 +2374,7 @@ fn unlock_unstaked() { roll_to(2, vec![]); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10),); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10),); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10),); assert_ok!(unstaking.try_insert(4, 10)); assert_eq!(Balances::locks(1), vec![lock.clone()]); assert_eq!(Balances::locks(2), vec![lock.clone()]); @@ -2406,7 +2390,7 @@ fn unlock_unstaked() { roll_to(3, vec![]); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10),); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10),); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10),); assert_ok!(unstaking.try_insert(5, 10)); assert_ok!(unstaking.try_insert(5, 10)); assert_eq!(Balances::locks(1), vec![lock.clone()]); @@ -2426,13 +2410,13 @@ fn unlock_unstaked() { // reach MaxUnstakeRequests roll_to(4, vec![]); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); roll_to(5, vec![]); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); roll_to(6, vec![]); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 10)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 10)); assert_ok!(unstaking.try_insert(6, 10)); assert_ok!(unstaking.try_insert(7, 10)); assert_ok!(unstaking.try_insert(8, 10)); @@ -2447,7 +2431,7 @@ fn unlock_unstaked() { Error::::NoMoreUnstaking ); assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(2), 1, 10), + StakePallet::delegator_stake_less(Origin::signed(2), 10), Error::::NoMoreUnstaking ); assert_ok!(StakePallet::unlock_unstaked(Origin::signed(1), 1)); @@ -2462,10 +2446,10 @@ fn unlock_unstaked() { assert_eq!(Balances::locks(1), vec![lock.clone()]); assert_eq!(Balances::locks(2), vec![lock.clone()]); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), 40)); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 1, 40)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(2), 40)); assert_ok!(unstaking.try_insert(9, 40)); assert_ok!(StakePallet::candidate_stake_more(Origin::signed(1), 30)); - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 1, 30)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(2), 30)); unstaking.remove(&8); assert_ok!(unstaking.try_insert(9, 20)); assert_eq!(StakePallet::unstaking(1), unstaking); @@ -2526,14 +2510,14 @@ fn kick_delegator_with_full_unstaking() { // Fill unstake requests for block in 1u64..1u64.saturating_add(max_unstake_reqs as u64) { System::set_block_number(block); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(5), 1, 1)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(5), 1)); } assert_eq!(StakePallet::unstaking(5).into_inner().len(), max_unstake_reqs); // Additional unstake should fail System::set_block_number(100); assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(5), 1, 1), + StakePallet::delegator_stake_less(Origin::signed(5), 1), Error::::NoMoreUnstaking ); @@ -2601,11 +2585,11 @@ fn candidate_leaves() { Error::::CannotDelegateIfLeaving ); assert_noop!( - StakePallet::delegator_stake_more(Origin::signed(12), 1, 1), + StakePallet::delegator_stake_more(Origin::signed(12), 1), Error::::CannotDelegateIfLeaving ); assert_noop!( - StakePallet::delegator_stake_less(Origin::signed(12), 1, 1), + StakePallet::delegator_stake_less(Origin::signed(12), 1), Error::::CannotDelegateIfLeaving ); assert_noop!( @@ -3149,7 +3133,7 @@ fn prioritize_collators() { ); // 7 decreases delegation - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(7), 5, 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(7), 10)); assert_eq!(StakePallet::selected_candidates().into_inner(), vec![5, 3]); assert_eq!( StakePallet::top_candidates(), @@ -3231,7 +3215,7 @@ fn prioritize_delegators() { ); // delegate_less - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(5), 2, 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(5), 10)); assert_eq!( StakePallet::candidate_pool(2).unwrap().delegators, OrderedSet::from_sorted_set( @@ -3247,7 +3231,7 @@ fn prioritize_delegators() { ); // delegate_more - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 2, 10)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(6), 10)); assert_eq!( StakePallet::candidate_pool(2).unwrap().delegators, OrderedSet::from_sorted_set( @@ -3261,7 +3245,7 @@ fn prioritize_delegators() { .unwrap() ) ); - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(7), 2, 10)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(7), 10)); assert_eq!( StakePallet::candidate_pool(2).unwrap().delegators, OrderedSet::from_sorted_set( @@ -3635,7 +3619,7 @@ fn update_total_stake_collators_stay() { delegators: 150 } ); - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, 10)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 10)); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -3643,7 +3627,7 @@ fn update_total_stake_collators_stay() { delegators: 160 } ); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(4), 2, 5)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(4), 5)); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -3689,10 +3673,10 @@ fn update_total_stake_displace_collators() { delegators: 105 } ); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(8), 4, 45)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(8), 45)); // 3 is pushed out by delegator staking less - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(7), 3, 45)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(7), 45)); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -3788,7 +3772,7 @@ fn update_total_stake_no_collator_changes() { delegators: 110 } ); - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(5), 1, 10)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(5), 10)); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -3804,7 +3788,7 @@ fn update_total_stake_no_collator_changes() { delegators: 110 } ); - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(6), 2, 10)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(6), 10)); assert_eq!( StakePallet::total_collator_stake(), TotalStake { @@ -4036,7 +4020,7 @@ fn rewards_delegator_stake_more() { }); // stake less to trigger reward incrementing just for 3 - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, DECIMALS)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), DECIMALS)); // 1 should still have counter 1 but no rewards assert_eq!(StakePallet::blocks_authored(1), 1); assert!(StakePallet::blocks_rewarded(1).is_zero()); @@ -4068,7 +4052,7 @@ fn rewards_delegator_stake_less() { }); // stake less to trigger reward incrementing just for 3 - assert_ok!(StakePallet::delegator_stake_less(Origin::signed(3), 1, DECIMALS)); + assert_ok!(StakePallet::delegator_stake_less(Origin::signed(3), DECIMALS)); // 1 should still have counter 1 but no rewards assert_eq!(StakePallet::blocks_authored(1), 1); assert!(StakePallet::blocks_rewarded(1).is_zero()); @@ -4371,7 +4355,7 @@ fn api_get_staking_rates() { assert_ok!(StakePallet::candidate_stake_less(Origin::signed(1), stake / 2)); assert_ok!(StakePallet::candidate_stake_less(Origin::signed(2), stake / 2)); // delegator stakes more to exceed - assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, stake)); + assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), stake)); rates.collator_staking_rate = Perquintill::from_percent(25); rates.collator_reward_rate = Perquintill::from_percent(10); rates.delegator_staking_rate = Perquintill::from_percent(50); From 9102cfb194d2d3105303adb49f2c487c8ce909c7 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 3 Nov 2022 07:51:27 +0100 Subject: [PATCH 34/34] Update pallets/parachain-staking/src/lib.rs Co-authored-by: Albrecht --- pallets/parachain-staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 3e168b7449..f8b82500ae 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -1426,7 +1426,7 @@ pub mod pallet { DelegatorState::::insert(&acc, delegator_state); LastDelegation::::insert(&acc, delegation_counter); - // initiate rewarded counter to match the current autored counter of the + // initiate rewarded counter to match the current authored counter of the // candidate BlocksRewarded::::insert(&acc, BlocksAuthored::::get(&collator));