From 7429f0b89c79332fea25cd22e29d501139527f18 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 13:59:26 +0200 Subject: [PATCH 001/103] make total reward payout counter never decrease --- substrate/frame/nomination-pools/src/lib.rs | 10 ++- substrate/frame/nomination-pools/src/mock.rs | 55 +++++++++++++ substrate/frame/nomination-pools/src/tests.rs | 81 ++++++++++++++++++- 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index c4bebc5a1d03..58acaf95e844 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1303,10 +1303,17 @@ impl RewardPool { // Store the total payouts at the time of this update. Total payouts are essentially the // entire historical balance of the reward pool, equating to the current balance + the total // rewards that have left the pool + the total commission that has left the pool. - self.last_recorded_total_payouts = balance + let last_recorded_total_payouts = balance .checked_add(&self.total_rewards_claimed.saturating_add(self.total_commission_claimed)) .ok_or(Error::::OverflowRisk)?; + // An increase in ED could cause `last_recorded_total_payouts` to decrease but we should not + // allow that to happen since an already paid out reward cannot decrease. The reward account + // might go in deficit temporarily if this happens but it will be corrected once new rewards + // are added to the pool. + self.last_recorded_total_payouts = + self.last_recorded_total_payouts.max(last_recorded_total_payouts); + Ok(()) } @@ -1487,6 +1494,7 @@ impl SubPools { /// `no_era` pool. This is guaranteed to at least be equal to the staking `UnbondingDuration`. For /// improved UX [`Config::PostUnbondingPoolsWindow`] should be configured to a non-zero value. pub struct TotalUnbondingPools(PhantomData); + impl Get for TotalUnbondingPools { fn get() -> u32 { // NOTE: this may be dangerous in the scenario bonding_duration gets decreased because diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 7d0d729a40d4..11ce5bbf0c8c 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -423,6 +423,61 @@ pub fn fully_unbond_permissioned(member: AccountId) -> DispatchResult { Pools::unbond(RuntimeOrigin::signed(member), member, points) } +pub fn pending_rewards_for_pool(pool: PoolId) -> Balance { + let bonded_pool = BondedPools::::get(pool).unwrap(); + let reward_pool = RewardPools::::get(pool).unwrap(); + + let current_rc = if !bonded_pool.points.is_zero() { + let commission = bonded_pool.commission.current(); + reward_pool + .current_reward_counter(pool, bonded_pool.points, commission) + .unwrap() + .0 + } else { + Default::default() + }; + + PoolMembers::::iter() + .filter(|(_, d)| d.pool_id == pool) + .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) + .sum() +} + +pub fn pending_rewards_for_delegator(delegator: AccountId) -> Balance { + let member = PoolMembers::::get(delegator).unwrap(); + let bonded_pool = BondedPools::::get(member.pool_id).unwrap(); + let reward_pool = RewardPools::::get(member.pool_id).unwrap(); + + assert!(!bonded_pool.points.is_zero()); + + let commission = bonded_pool.commission.current(); + let current_rc = reward_pool + .current_reward_counter(member.pool_id, bonded_pool.points, commission) + .unwrap() + .0; + + member.pending_rewards(current_rc).unwrap_or_default() +} + +#[derive(PartialEq, Debug)] +pub enum RewardImbalance { + // There is no reward deficit. + Surplus(Balance), + // There is a reward deficit. + Deficit(Balance), +} + +pub fn reward_imbalance(pool: PoolId) -> RewardImbalance { + let pending_rewards = pending_rewards_for_pool(pool); + let current_balance = RewardPool::::current_balance(pool); + + if pending_rewards > current_balance { + RewardImbalance::Deficit(pending_rewards - current_balance) + } else { + RewardImbalance::Surplus(current_balance - pending_rewards) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index d0fe4e40a18b..2bc3d7611630 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -298,10 +298,11 @@ mod bonded_pool { } mod reward_pool { + use super::*; + use crate::mock::RewardImbalance::{Deficit, Surplus}; + #[test] fn current_balance_only_counts_balance_over_existential_deposit() { - use super::*; - ExtBuilder::default().build_and_execute(|| { let reward_account = Pools::create_reward_account(2); @@ -324,6 +325,82 @@ mod reward_pool { assert_eq!(RewardPool::::current_balance(2), 1); }); } + + #[test] + fn ed_change_causes_reward_deficit() { + ExtBuilder::default() + .max_members_per_pool(Some(200)) + .max_members(Some(200)) + .build_and_execute(|| { + // original ED + ExistentialDeposit::set(5); + + // 11 joins the pool + Balances::make_free_balance_be(&11, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); + + // new delegator does not have any pending rewards + assert_eq!(pending_rewards_for_delegator(11), 0); + + // give the pool some rewards + deposit_rewards(100); + + // all existing delegator has pending rewards + assert_eq!(pending_rewards_for_delegator(11), 90); + assert_eq!(pending_rewards_for_delegator(10), 10); + assert_eq!(reward_imbalance(1), Surplus(0)); + + // 12 joins the pool. + Balances::make_free_balance_be(&12, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(12), 100, 1)); + + // Current reward balance is committed to last recorded reward counter of + // the pool before the increase in ED. + let bonded_pool = BondedPools::::get(1).unwrap(); + let reward_pool = RewardPools::::get(1).unwrap(); + assert_eq!( + reward_pool.last_recorded_reward_counter, + reward_pool + .current_reward_counter(1, bonded_pool.points, Perbill::zero()) + .unwrap() + .0 + ); + + // reward pool before ED increase and reward counter getting committed. + let reward_pool_1 = RewardPools::::get(1).unwrap(); + + // increase ED from 5 to 50 + ExistentialDeposit::set(50); + + // There is now an expected deficit of ed_diff + assert_eq!(reward_imbalance(1), Deficit(45)); + + // 13 joins the pool which commits the reward counter to reward pool. + Balances::make_free_balance_be(&13, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(13), 100, 1)); + + // still a deficit + assert_eq!(reward_imbalance(1), Deficit(45)); + + // reward pool after ED increase + let reward_pool_2 = RewardPools::::get(1).unwrap(); + + // last recorded total payout does not decrease even as ED increases. + assert_eq!( + reward_pool_1.last_recorded_total_payouts, + reward_pool_2.last_recorded_total_payouts + ); + + // Topping up pool decreases deficit + deposit_rewards(10); + assert_eq!(reward_imbalance(1), Deficit(35)); + + // top up the pool to remove the deficit + deposit_rewards(35); + // No deficit anymore + assert_eq!(reward_imbalance(1), Surplus(0)); + }); + } } mod unbond_pool { From fc135d7b34f8d9e937fe6ea17b5e147b70c2cdf7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 14:04:30 +0200 Subject: [PATCH 002/103] improve comments --- substrate/frame/nomination-pools/src/lib.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 58acaf95e844..f19187ccce11 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1300,17 +1300,19 @@ impl RewardPool { self.total_commission_pending = self.total_commission_pending.saturating_add(new_pending_commission); - // Store the total payouts at the time of this update. Total payouts are essentially the - // entire historical balance of the reward pool, equating to the current balance + the total - // rewards that have left the pool + the total commission that has left the pool. + // Total payouts are essentially the entire historical balance of the reward pool, equating + // to the current balance + the total rewards that have left the pool + the total commission + // that has left the pool. let last_recorded_total_payouts = balance .checked_add(&self.total_rewards_claimed.saturating_add(self.total_commission_claimed)) .ok_or(Error::::OverflowRisk)?; + // Store the total payouts at the time of this update. + // // An increase in ED could cause `last_recorded_total_payouts` to decrease but we should not // allow that to happen since an already paid out reward cannot decrease. The reward account - // might go in deficit temporarily if this happens but it will be corrected once new rewards - // are added to the pool. + // might go in deficit temporarily in this exceptional case but it will be corrected once + // new rewards are added to the pool. self.last_recorded_total_payouts = self.last_recorded_total_payouts.max(last_recorded_total_payouts); From a580bc103224a66a099e25ca7d94faf6346c242a Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 17:20:34 +0200 Subject: [PATCH 003/103] new call to top up the pool --- substrate/frame/nomination-pools/src/lib.rs | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index f19187ccce11..9185d11554d5 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1780,6 +1780,8 @@ pub mod pallet { }, /// Pool commission has been claimed. PoolCommissionClaimed { pool_id: PoolId, commission: BalanceOf }, + /// Pool topped up in case of a reward deficit. + PoolToppedUp { pool_id: PoolId, top_up_value: BalanceOf, deficit: BalanceOf }, } #[pallet::error] @@ -1855,6 +1857,8 @@ pub mod pallet { InvalidPoolId, /// Bonding extra is restricted to the exact pending reward amount. BondExtraRestricted, + /// No reward deficit to top up. + NoRewardDeficit, } #[derive(Encode, Decode, PartialEq, TypeInfo, PalletError, RuntimeDebug)] @@ -2641,6 +2645,19 @@ pub mod pallet { let who = ensure_signed(origin)?; Self::do_claim_commission(who, pool_id) } + + /// Top up the reward deficit of a pool permissionlessly. + /// + /// This can happen in situations where ED has increased from the time the pool was created. + /// The increased ED eats up from the available rewards of the pool, and the pool can end up + /// with a net deficit. + #[pallet::call_index(21)] + // FIXME(ank4n): bench + tests + #[pallet::weight(T::WeightInfo::claim_commission())] + pub fn top_up_reward_deficit(origin: OriginFor, pool_id: PoolId, #[pallet::compact] max_transfer: BalanceOf,) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_top_up_reward_deficit(who, pool_id, max_transfer) + } } #[pallet::hooks] @@ -3039,6 +3056,50 @@ impl Pallet { Ok(()) } + fn pool_pending_rewards(pool: PoolId) -> Result, sp_runtime::DispatchError> { + let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; + let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; + + let current_rc = if !bonded_pool.points.is_zero() { + let commission = bonded_pool.commission.current(); + reward_pool + .current_reward_counter(pool, bonded_pool.points, commission)?.0 + } else { + Default::default() + }; + + Ok(PoolMembers::::iter() + .filter(|(_, d)| d.pool_id == pool) + .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) + .fold(0u32.into(), |acc: BalanceOf, x| acc.saturating_add(x))) + } + + fn do_top_up_reward_deficit(who: T::AccountId, pool: PoolId, max_transfer: BalanceOf) -> DispatchResult { + let pool_pending_rewards = Self::pool_pending_rewards(pool)?; + let reward_balance = RewardPool::::current_balance(pool); + let deficit = pool_pending_rewards.saturating_sub(reward_balance); + + ensure!(!deficit.is_zero(), Error::::NoRewardDeficit); + + // do not top up beyond the max transfer amount desired by the caller. + let top_up_amount = deficit.min(max_transfer); + T::Currency::transfer( + &who, + &Self::create_reward_account(pool), + top_up_amount, + ExistenceRequirement::KeepAlive, + )?; + + Self::deposit_event(Event::::PoolToppedUp { + pool_id: pool, + top_up_value: top_up_amount, + deficit: deficit.saturating_sub(top_up_amount), + }); + + Ok(()) + } + + /// Ensure the correctness of the state of this pallet. /// /// This should be valid before or after each state transition of this pallet. From aace388fed78d3399c107ac161eefc7a4a1d3c60 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 17:21:04 +0200 Subject: [PATCH 004/103] format --- substrate/frame/nomination-pools/src/lib.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 9185d11554d5..0349a45e4972 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2654,7 +2654,11 @@ pub mod pallet { #[pallet::call_index(21)] // FIXME(ank4n): bench + tests #[pallet::weight(T::WeightInfo::claim_commission())] - pub fn top_up_reward_deficit(origin: OriginFor, pool_id: PoolId, #[pallet::compact] max_transfer: BalanceOf,) -> DispatchResult { + pub fn top_up_reward_deficit( + origin: OriginFor, + pool_id: PoolId, + #[pallet::compact] max_transfer: BalanceOf, + ) -> DispatchResult { let who = ensure_signed(origin)?; Self::do_top_up_reward_deficit(who, pool_id, max_transfer) } @@ -3062,8 +3066,7 @@ impl Pallet { let current_rc = if !bonded_pool.points.is_zero() { let commission = bonded_pool.commission.current(); - reward_pool - .current_reward_counter(pool, bonded_pool.points, commission)?.0 + reward_pool.current_reward_counter(pool, bonded_pool.points, commission)?.0 } else { Default::default() }; @@ -3074,7 +3077,11 @@ impl Pallet { .fold(0u32.into(), |acc: BalanceOf, x| acc.saturating_add(x))) } - fn do_top_up_reward_deficit(who: T::AccountId, pool: PoolId, max_transfer: BalanceOf) -> DispatchResult { + fn do_top_up_reward_deficit( + who: T::AccountId, + pool: PoolId, + max_transfer: BalanceOf, + ) -> DispatchResult { let pool_pending_rewards = Self::pool_pending_rewards(pool)?; let reward_balance = RewardPool::::current_balance(pool); let deficit = pool_pending_rewards.saturating_sub(reward_balance); @@ -3099,7 +3106,6 @@ impl Pallet { Ok(()) } - /// Ensure the correctness of the state of this pallet. /// /// This should be valid before or after each state transition of this pallet. From 66b593dbfbfff3b29435d2d708f068d940aa6645 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 17:41:24 +0200 Subject: [PATCH 005/103] topped up funds are not rewardeable to delegators --- substrate/frame/nomination-pools/src/lib.rs | 10 ++++++++++ substrate/frame/nomination-pools/src/mock.rs | 18 +----------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 0349a45e4972..5c9ebe6eb1d6 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3097,6 +3097,16 @@ impl Pallet { ExistenceRequirement::KeepAlive, )?; + // The topped up amount should not be claimable by delegators. + RewardPools::::mutate(pool, |maybe_reward_pool| { + if let Some(pool) = maybe_reward_pool { + pool.total_rewards_claimed.saturating_accrue(top_up_amount); + Ok(()) + } else { + Err(Error::::PoolNotFound) + } + })?; + Self::deposit_event(Event::::PoolToppedUp { pool_id: pool, top_up_value: top_up_amount, diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 11ce5bbf0c8c..13c739af3943 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -424,23 +424,7 @@ pub fn fully_unbond_permissioned(member: AccountId) -> DispatchResult { } pub fn pending_rewards_for_pool(pool: PoolId) -> Balance { - let bonded_pool = BondedPools::::get(pool).unwrap(); - let reward_pool = RewardPools::::get(pool).unwrap(); - - let current_rc = if !bonded_pool.points.is_zero() { - let commission = bonded_pool.commission.current(); - reward_pool - .current_reward_counter(pool, bonded_pool.points, commission) - .unwrap() - .0 - } else { - Default::default() - }; - - PoolMembers::::iter() - .filter(|(_, d)| d.pool_id == pool) - .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) - .sum() + Pools::pool_pending_rewards(pool).expect("pool should exist") } pub fn pending_rewards_for_delegator(delegator: AccountId) -> Balance { From 56cafc4ec40fdd5a00e74bcb7e50993edf4b6cc7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 18:24:35 +0200 Subject: [PATCH 006/103] test for top up function --- substrate/frame/nomination-pools/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/tests.rs | 190 ++++++++++++------ 2 files changed, 134 insertions(+), 58 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 5c9ebe6eb1d6..2b7efada2ed8 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3100,7 +3100,7 @@ impl Pallet { // The topped up amount should not be claimable by delegators. RewardPools::::mutate(pool, |maybe_reward_pool| { if let Some(pool) = maybe_reward_pool { - pool.total_rewards_claimed.saturating_accrue(top_up_amount); + pool.last_recorded_total_payouts.saturating_accrue(top_up_amount); Ok(()) } else { Err(Error::::PoolNotFound) diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 2bc3d7611630..8f56a2d8d4e5 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -328,78 +328,154 @@ mod reward_pool { #[test] fn ed_change_causes_reward_deficit() { - ExtBuilder::default() - .max_members_per_pool(Some(200)) - .max_members(Some(200)) - .build_and_execute(|| { - // original ED - ExistentialDeposit::set(5); + ExtBuilder::default().max_members_per_pool(Some(5)).build_and_execute(|| { + // original ED + ExistentialDeposit::set(5); - // 11 joins the pool - Balances::make_free_balance_be(&11, 500); - assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); + // 11 joins the pool + Balances::make_free_balance_be(&11, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); - // new delegator does not have any pending rewards - assert_eq!(pending_rewards_for_delegator(11), 0); + // new delegator does not have any pending rewards + assert_eq!(pending_rewards_for_delegator(11), 0); - // give the pool some rewards - deposit_rewards(100); + // give the pool some rewards + deposit_rewards(100); - // all existing delegator has pending rewards - assert_eq!(pending_rewards_for_delegator(11), 90); - assert_eq!(pending_rewards_for_delegator(10), 10); - assert_eq!(reward_imbalance(1), Surplus(0)); + // all existing delegator has pending rewards + assert_eq!(pending_rewards_for_delegator(11), 90); + assert_eq!(pending_rewards_for_delegator(10), 10); + assert_eq!(reward_imbalance(1), Surplus(0)); - // 12 joins the pool. - Balances::make_free_balance_be(&12, 500); - assert_ok!(Pools::join(RuntimeOrigin::signed(12), 100, 1)); + // 12 joins the pool. + Balances::make_free_balance_be(&12, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(12), 100, 1)); - // Current reward balance is committed to last recorded reward counter of - // the pool before the increase in ED. - let bonded_pool = BondedPools::::get(1).unwrap(); - let reward_pool = RewardPools::::get(1).unwrap(); - assert_eq!( - reward_pool.last_recorded_reward_counter, - reward_pool - .current_reward_counter(1, bonded_pool.points, Perbill::zero()) - .unwrap() - .0 - ); + // Current reward balance is committed to last recorded reward counter of + // the pool before the increase in ED. + let bonded_pool = BondedPools::::get(1).unwrap(); + let reward_pool = RewardPools::::get(1).unwrap(); + assert_eq!( + reward_pool.last_recorded_reward_counter, + reward_pool + .current_reward_counter(1, bonded_pool.points, Perbill::zero()) + .unwrap() + .0 + ); - // reward pool before ED increase and reward counter getting committed. - let reward_pool_1 = RewardPools::::get(1).unwrap(); + // reward pool before ED increase and reward counter getting committed. + let reward_pool_1 = RewardPools::::get(1).unwrap(); - // increase ED from 5 to 50 - ExistentialDeposit::set(50); + // increase ED from 5 to 50 + ExistentialDeposit::set(50); - // There is now an expected deficit of ed_diff - assert_eq!(reward_imbalance(1), Deficit(45)); + // There is now an expected deficit of ed_diff + assert_eq!(reward_imbalance(1), Deficit(45)); - // 13 joins the pool which commits the reward counter to reward pool. - Balances::make_free_balance_be(&13, 500); - assert_ok!(Pools::join(RuntimeOrigin::signed(13), 100, 1)); + // 13 joins the pool which commits the reward counter to reward pool. + Balances::make_free_balance_be(&13, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(13), 100, 1)); - // still a deficit - assert_eq!(reward_imbalance(1), Deficit(45)); + // still a deficit + assert_eq!(reward_imbalance(1), Deficit(45)); - // reward pool after ED increase - let reward_pool_2 = RewardPools::::get(1).unwrap(); + // reward pool after ED increase + let reward_pool_2 = RewardPools::::get(1).unwrap(); - // last recorded total payout does not decrease even as ED increases. - assert_eq!( - reward_pool_1.last_recorded_total_payouts, - reward_pool_2.last_recorded_total_payouts - ); + // last recorded total payout does not decrease even as ED increases. + assert_eq!( + reward_pool_1.last_recorded_total_payouts, + reward_pool_2.last_recorded_total_payouts + ); - // Topping up pool decreases deficit - deposit_rewards(10); - assert_eq!(reward_imbalance(1), Deficit(35)); + // Topping up pool decreases deficit + deposit_rewards(10); + assert_eq!(reward_imbalance(1), Deficit(35)); - // top up the pool to remove the deficit - deposit_rewards(35); - // No deficit anymore - assert_eq!(reward_imbalance(1), Surplus(0)); - }); + // top up the pool to remove the deficit + deposit_rewards(35); + // No deficit anymore + assert_eq!(reward_imbalance(1), Surplus(0)); + }); + } + + #[test] + fn top_up_fixes_reward_deficit() { + ExtBuilder::default().max_members_per_pool(Some(5)).build_and_execute(|| { + // Given: pool has a reward deficit + + // original ED + ExistentialDeposit::set(5); + + // 11 joins the pool + Balances::make_free_balance_be(&11, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); + + // Pool some rewards + deposit_rewards(100); + + // 12 joins the pool. + Balances::make_free_balance_be(&12, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(12), 10, 1)); + + // When: pool ends up in reward deficit + + // increase ED + ExistentialDeposit::set(50); + assert_eq!(reward_imbalance(1), Deficit(45)); + + // clear events + pool_events_since_last_call(); + + // Then: top up reduces the deficit + Balances::make_free_balance_be(&99, 1000); + // caller can set safe ceiling for top up. + let max_top_up: Balance = 20; + assert_ok!(Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, max_top_up)); + // only upto max_transfer is topped up. + assert_eq!( + pool_events_since_last_call(), + vec![Event::PoolToppedUp { + pool_id: 1, + top_up_value: max_top_up, + deficit: 45 - max_top_up + },] + ); + assert_eq!(reward_imbalance(1), Deficit(25)); + + // Top up the remaining deficit + assert_ok!(Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, 1000)); + assert_eq!( + pool_events_since_last_call(), + vec![Event::PoolToppedUp { pool_id: 1, top_up_value: 25, deficit: 0 },] + ); + assert_eq!(reward_imbalance(1), Surplus(0)); + + // Trying to top up again does not work + assert_err!( + Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, 1000), + Error::::NoRewardDeficit + ); + }); + } + + #[test] + fn topping_up_does_not_work_for_pools_with_no_deficit() { + ExtBuilder::default().max_members_per_pool(Some(5)).build_and_execute(|| { + // 11 joins the pool + Balances::make_free_balance_be(&11, 500); + assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); + + // Pool some rewards + deposit_rewards(100); + assert_eq!(reward_imbalance(1), Surplus(0)); + + // Topping up fails + assert_err!( + Pools::top_up_reward_deficit(RuntimeOrigin::signed(11), 1, 100), + Error::::NoRewardDeficit + ); + }); } } From 767cc3adcec410488d7e4ac9ecc0f87a67e84c30 Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 29 Aug 2023 18:39:02 +0200 Subject: [PATCH 007/103] check user has enough balance and limit max transfer to their free balance --- substrate/frame/nomination-pools/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 2b7efada2ed8..44e8b0c422ca 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2660,7 +2660,8 @@ pub mod pallet { #[pallet::compact] max_transfer: BalanceOf, ) -> DispatchResult { let who = ensure_signed(origin)?; - Self::do_top_up_reward_deficit(who, pool_id, max_transfer) + let caller_balance = T::Currency::free_balance(&who); + Self::do_top_up_reward_deficit(who, pool_id, max_transfer.min(caller_balance)) } } From c4c7e96ba2ac72e15e45dae8ca4ae77ad86f99b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Sat, 2 Sep 2023 14:41:33 +0200 Subject: [PATCH 008/103] contracts: Update to wasmi 0.31 (#1350) * contracts: Update to wasmi 0.31 * ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_contracts --------- Co-authored-by: command-bot <> --- Cargo.lock | 38 +- substrate/frame/contracts/Cargo.toml | 2 +- substrate/frame/contracts/src/weights.rs | 1734 +++++++++++----------- 3 files changed, 869 insertions(+), 905 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13bc2327daef..f3bbc2faf296 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6471,12 +6471,6 @@ dependencies = [ "webrtc-util", ] -[[package]] -name = "intx" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f38a50a899dc47a6d0ed5508e7f601a2e34c3a85303514b5d137f3c10a0c75" - [[package]] name = "io-lifetimes" version = "1.0.11" @@ -9387,7 +9381,7 @@ dependencies = [ "sp-runtime", "sp-std", "wasm-instrument 0.4.0", - "wasmi 0.30.0", + "wasmi", "wat", ] @@ -16574,7 +16568,7 @@ dependencies = [ "smallvec", "soketto", "twox-hash", - "wasmi 0.31.0", + "wasmi", "x25519-dalek 2.0.0", "zeroize", ] @@ -19811,20 +19805,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmi" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51fb5c61993e71158abf5bb863df2674ca3ec39ed6471c64f07aeaf751d67b4" -dependencies = [ - "intx", - "smallvec", - "spin 0.9.8", - "wasmi_arena", - "wasmi_core 0.12.0", - "wasmparser-nostd", -] - [[package]] name = "wasmi" version = "0.31.0" @@ -19834,7 +19814,7 @@ dependencies = [ "smallvec", "spin 0.9.8", "wasmi_arena", - "wasmi_core 0.13.0", + "wasmi_core", "wasmparser-nostd", ] @@ -19844,18 +19824,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "401c1f35e413fac1846d4843745589d9ec678977ab35a384db8ae7830525d468" -[[package]] -name = "wasmi_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624e6333e861ef49095d2d678b76ebf30b06bf37effca845be7e5b87c90071b7" -dependencies = [ - "downcast-rs", - "libm", - "num-traits", - "paste", -] - [[package]] name = "wasmi_core" version = "0.13.0" diff --git a/substrate/frame/contracts/Cargo.toml b/substrate/frame/contracts/Cargo.toml index 8d6a9fd9cdb3..237ab9303e25 100644 --- a/substrate/frame/contracts/Cargo.toml +++ b/substrate/frame/contracts/Cargo.toml @@ -26,7 +26,7 @@ serde = { version = "1", optional = true, features = ["derive"] } smallvec = { version = "1", default-features = false, features = [ "const_generics", ] } -wasmi = { version = "0.30", default-features = false } +wasmi = { version = "0.31", default-features = false } impl-trait-for-tuples = "0.2" # Only used in benchmarking to generate contract code diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs index 34bea8ff0a30..22e4f749313d 100644 --- a/substrate/frame/contracts/src/weights.rs +++ b/substrate/frame/contracts/src/weights.rs @@ -18,10 +18,10 @@ //! Autogenerated weights for `pallet_contracts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-09-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-pzhd7p6z-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: // target/production/substrate-node @@ -32,12 +32,12 @@ // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=pallet_contracts // --chain=dev -// --header=./HEADER-APACHE2 -// --output=./frame/contracts/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/contracts/src/weights.rs +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -141,8 +141,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_410_000 picoseconds. - Weight::from_parts(2_581_000, 1627) + // Minimum execution time: 2_548_000 picoseconds. + Weight::from_parts(2_670_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -152,10 +152,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `451 + k * (69 ±0)` // Estimated: `441 + k * (70 ±0)` - // Minimum execution time: 13_278_000 picoseconds. - Weight::from_parts(13_944_000, 441) - // Standard Error: 1_643 - .saturating_add(Weight::from_parts(1_194_404, 0).saturating_mul(k.into())) + // Minimum execution time: 13_526_000 picoseconds. + Weight::from_parts(13_902_000, 441) + // Standard Error: 1_058 + .saturating_add(Weight::from_parts(1_274_724, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -169,10 +169,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_533_000 picoseconds. - Weight::from_parts(9_141_899, 6149) + // Minimum execution time: 8_426_000 picoseconds. + Weight::from_parts(8_591_621, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_327, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_203, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -185,8 +185,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_998_000 picoseconds. - Weight::from_parts(17_776_000, 6450) + // Minimum execution time: 17_008_000 picoseconds. + Weight::from_parts(17_742_000, 6450) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -199,10 +199,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_919_000 picoseconds. - Weight::from_parts(4_057_153, 3635) - // Standard Error: 1_252 - .saturating_add(Weight::from_parts(1_151_419, 0).saturating_mul(k.into())) + // Minimum execution time: 3_949_000 picoseconds. + Weight::from_parts(4_062_000, 3635) + // Standard Error: 1_983 + .saturating_add(Weight::from_parts(1_173_197, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -221,10 +221,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `325 + c * (1 ±0)` // Estimated: `6263 + c * (1 ±0)` - // Minimum execution time: 17_730_000 picoseconds. - Weight::from_parts(17_540_884, 6263) + // Minimum execution time: 17_094_000 picoseconds. + Weight::from_parts(17_338_591, 6263) // Standard Error: 1 - .saturating_add(Weight::from_parts(417, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(436, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -235,8 +235,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 13_089_000 picoseconds. - Weight::from_parts(13_727_000, 6380) + // Minimum execution time: 12_704_000 picoseconds. + Weight::from_parts(13_147_000, 6380) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -250,8 +250,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `360` // Estimated: `6300` - // Minimum execution time: 49_083_000 picoseconds. - Weight::from_parts(50_462_000, 6300) + // Minimum execution time: 48_387_000 picoseconds. + Weight::from_parts(50_024_000, 6300) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -263,8 +263,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 49_299_000 picoseconds. - Weight::from_parts(50_805_000, 6534) + // Minimum execution time: 59_300_000 picoseconds. + Weight::from_parts(61_805_000, 6534) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -274,8 +274,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 3_305_000 picoseconds. - Weight::from_parts(3_489_000, 1627) + // Minimum execution time: 3_327_000 picoseconds. + Weight::from_parts(3_502_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -287,8 +287,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 12_657_000 picoseconds. - Weight::from_parts(13_100_000, 3631) + // Minimum execution time: 12_759_000 picoseconds. + Weight::from_parts(13_134_000, 3631) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -298,8 +298,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_784_000 picoseconds. - Weight::from_parts(4_994_000, 3607) + // Minimum execution time: 4_775_000 picoseconds. + Weight::from_parts(5_084_000, 3607) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -310,8 +310,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 6_762_000 picoseconds. - Weight::from_parts(6_945_000, 3632) + // Minimum execution time: 6_663_000 picoseconds. + Weight::from_parts(6_855_000, 3632) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -322,8 +322,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_999_000 picoseconds. - Weight::from_parts(7_372_000, 3607) + // Minimum execution time: 7_212_000 picoseconds. + Weight::from_parts(7_426_000, 3607) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -344,12 +344,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 125952]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `759` - // Estimated: `6710 + c * (1 ±0)` - // Minimum execution time: 304_121_000 picoseconds. - Weight::from_parts(288_627_840, 6710) - // Standard Error: 83 - .saturating_add(Weight::from_parts(37_343, 0).saturating_mul(c.into())) + // Measured: `792` + // Estimated: `6743 + c * (1 ±0)` + // Minimum execution time: 289_557_000 picoseconds. + Weight::from_parts(272_895_652, 6743) + // Standard Error: 80 + .saturating_add(Weight::from_parts(39_917, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -377,16 +377,16 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 1048576]`. fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `290` - // Estimated: `8714` - // Minimum execution time: 4_101_589_000 picoseconds. - Weight::from_parts(694_193_047, 8714) - // Standard Error: 334 - .saturating_add(Weight::from_parts(108_847, 0).saturating_mul(c.into())) - // Standard Error: 40 - .saturating_add(Weight::from_parts(1_677, 0).saturating_mul(i.into())) - // Standard Error: 40 - .saturating_add(Weight::from_parts(1_783, 0).saturating_mul(s.into())) + // Measured: `323` + // Estimated: `8747` + // Minimum execution time: 4_671_359_000 picoseconds. + Weight::from_parts(586_523_882, 8747) + // Standard Error: 206 + .saturating_add(Weight::from_parts(115_402, 0).saturating_mul(c.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(1_797, 0).saturating_mul(i.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(2_046, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } @@ -404,22 +404,22 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `527` - // Estimated: `6471` - // Minimum execution time: 2_011_580_000 picoseconds. - Weight::from_parts(397_415_227, 6471) - // Standard Error: 10 - .saturating_add(Weight::from_parts(1_689, 0).saturating_mul(i.into())) - // Standard Error: 10 - .saturating_add(Weight::from_parts(1_679, 0).saturating_mul(s.into())) + // Measured: `560` + // Estimated: `6504` + // Minimum execution time: 2_170_657_000 picoseconds. + Weight::from_parts(369_331_405, 6504) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_940, 0).saturating_mul(i.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_858, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -439,10 +439,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `793` - // Estimated: `6733` - // Minimum execution time: 204_975_000 picoseconds. - Weight::from_parts(214_770_000, 6733) + // Measured: `826` + // Estimated: `6766` + // Minimum execution time: 204_287_000 picoseconds. + Weight::from_parts(213_239_000, 6766) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -461,10 +461,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 269_545_000 picoseconds. - Weight::from_parts(256_054_650, 3607) - // Standard Error: 91 - .saturating_add(Weight::from_parts(72_743, 0).saturating_mul(c.into())) + // Minimum execution time: 285_434_000 picoseconds. + Weight::from_parts(242_697_648, 3607) + // Standard Error: 128 + .saturating_add(Weight::from_parts(76_087, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -482,8 +482,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 47_880_000 picoseconds. - Weight::from_parts(49_427_000, 3780) + // Minimum execution time: 46_486_000 picoseconds. + Weight::from_parts(48_422_000, 3780) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -499,8 +499,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 37_898_000 picoseconds. - Weight::from_parts(39_826_000, 8967) + // Minimum execution time: 37_568_000 picoseconds. + Weight::from_parts(38_589_000, 8967) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -521,12 +521,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_caller(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `833 + r * (6 ±0)` - // Estimated: `6773 + r * (6 ±0)` - // Minimum execution time: 260_916_000 picoseconds. - Weight::from_parts(295_521_846, 6773) - // Standard Error: 1_126 - .saturating_add(Weight::from_parts(348_317, 0).saturating_mul(r.into())) + // Measured: `866 + r * (6 ±0)` + // Estimated: `6806 + r * (6 ±0)` + // Minimum execution time: 274_513_000 picoseconds. + Weight::from_parts(288_793_403, 6806) + // Standard Error: 650 + .saturating_add(Weight::from_parts(339_309, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -548,12 +548,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_is_contract(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `889 + r * (209 ±0)` - // Estimated: `6793 + r * (2684 ±0)` - // Minimum execution time: 274_335_000 picoseconds. - Weight::from_parts(132_998_512, 6793) - // Standard Error: 7_396 - .saturating_add(Weight::from_parts(3_602_287, 0).saturating_mul(r.into())) + // Measured: `922 + r * (209 ±0)` + // Estimated: `6826 + r * (2684 ±0)` + // Minimum execution time: 260_096_000 picoseconds. + Weight::from_parts(149_954_322, 6826) + // Standard Error: 5_713 + .saturating_add(Weight::from_parts(3_788_924, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -576,12 +576,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `888 + r * (213 ±0)` - // Estimated: `6797 + r * (2688 ±0)` - // Minimum execution time: 272_514_000 picoseconds. - Weight::from_parts(104_825_618, 6797) - // Standard Error: 10_038 - .saturating_add(Weight::from_parts(4_520_258, 0).saturating_mul(r.into())) + // Measured: `921 + r * (213 ±0)` + // Estimated: `6830 + r * (2688 ±0)` + // Minimum execution time: 277_496_000 picoseconds. + Weight::from_parts(285_839_000, 6830) + // Standard Error: 10_076 + .saturating_add(Weight::from_parts(4_720_110, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -604,12 +604,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_own_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `840 + r * (6 ±0)` - // Estimated: `6782 + r * (6 ±0)` - // Minimum execution time: 264_593_000 picoseconds. - Weight::from_parts(294_139_363, 6782) - // Standard Error: 907 - .saturating_add(Weight::from_parts(432_964, 0).saturating_mul(r.into())) + // Measured: `873 + r * (6 ±0)` + // Estimated: `6815 + r * (6 ±0)` + // Minimum execution time: 275_655_000 picoseconds. + Weight::from_parts(291_386_528, 6815) + // Standard Error: 898 + .saturating_add(Weight::from_parts(428_765, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -631,12 +631,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_origin(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (3 ±0)` - // Estimated: `6771 + r * (3 ±0)` - // Minimum execution time: 260_412_000 picoseconds. - Weight::from_parts(284_371_703, 6771) - // Standard Error: 433 - .saturating_add(Weight::from_parts(182_952, 0).saturating_mul(r.into())) + // Measured: `863 + r * (3 ±0)` + // Estimated: `6804 + r * (3 ±0)` + // Minimum execution time: 260_323_000 picoseconds. + Weight::from_parts(286_371_403, 6804) + // Standard Error: 451 + .saturating_add(Weight::from_parts(183_053, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -656,12 +656,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_root(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `720 + r * (3 ±0)` - // Estimated: `6660 + r * (3 ±0)` - // Minimum execution time: 255_112_000 picoseconds. - Weight::from_parts(273_052_488, 6660) - // Standard Error: 376 - .saturating_add(Weight::from_parts(166_644, 0).saturating_mul(r.into())) + // Measured: `753 + r * (3 ±0)` + // Estimated: `6693 + r * (3 ±0)` + // Minimum execution time: 262_974_000 picoseconds. + Weight::from_parts(276_571_502, 6693) + // Standard Error: 527 + .saturating_add(Weight::from_parts(165_364, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -683,12 +683,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `834 + r * (6 ±0)` - // Estimated: `6774 + r * (6 ±0)` - // Minimum execution time: 270_426_000 picoseconds. - Weight::from_parts(289_240_775, 6774) - // Standard Error: 748 - .saturating_add(Weight::from_parts(344_791, 0).saturating_mul(r.into())) + // Measured: `867 + r * (6 ±0)` + // Estimated: `6807 + r * (6 ±0)` + // Minimum execution time: 272_826_000 picoseconds. + Weight::from_parts(290_963_001, 6807) + // Standard Error: 810 + .saturating_add(Weight::from_parts(343_762, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -710,12 +710,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_gas_left(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (6 ±0)` - // Estimated: `6773 + r * (6 ±0)` - // Minimum execution time: 260_217_000 picoseconds. - Weight::from_parts(288_660_978, 6773) - // Standard Error: 1_199 - .saturating_add(Weight::from_parts(550_304, 0).saturating_mul(r.into())) + // Measured: `863 + r * (6 ±0)` + // Estimated: `6806 + r * (6 ±0)` + // Minimum execution time: 277_324_000 picoseconds. + Weight::from_parts(290_872_814, 6806) + // Standard Error: 766 + .saturating_add(Weight::from_parts(371_542, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -737,12 +737,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `974 + r * (6 ±0)` - // Estimated: `6898 + r * (6 ±0)` - // Minimum execution time: 273_473_000 picoseconds. - Weight::from_parts(298_889_279, 6898) - // Standard Error: 4_604 - .saturating_add(Weight::from_parts(1_630_175, 0).saturating_mul(r.into())) + // Measured: `1007 + r * (6 ±0)` + // Estimated: `6931 + r * (6 ±0)` + // Minimum execution time: 274_460_000 picoseconds. + Weight::from_parts(285_748_025, 6931) + // Standard Error: 1_570 + .saturating_add(Weight::from_parts(1_656_237, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -764,12 +764,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_value_transferred(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `844 + r * (6 ±0)` - // Estimated: `6790 + r * (6 ±0)` - // Minimum execution time: 262_033_000 picoseconds. - Weight::from_parts(284_293_851, 6790) - // Standard Error: 591 - .saturating_add(Weight::from_parts(369_240, 0).saturating_mul(r.into())) + // Measured: `877 + r * (6 ±0)` + // Estimated: `6823 + r * (6 ±0)` + // Minimum execution time: 278_254_000 picoseconds. + Weight::from_parts(283_893_525, 6823) + // Standard Error: 726 + .saturating_add(Weight::from_parts(347_368, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -791,12 +791,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_minimum_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `842 + r * (6 ±0)` - // Estimated: `6783 + r * (6 ±0)` - // Minimum execution time: 274_568_000 picoseconds. - Weight::from_parts(294_688_466, 6783) - // Standard Error: 768 - .saturating_add(Weight::from_parts(349_584, 0).saturating_mul(r.into())) + // Measured: `875 + r * (6 ±0)` + // Estimated: `6816 + r * (6 ±0)` + // Minimum execution time: 279_646_000 picoseconds. + Weight::from_parts(292_505_446, 6816) + // Standard Error: 867 + .saturating_add(Weight::from_parts(337_202, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -818,12 +818,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_block_number(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839 + r * (6 ±0)` - // Estimated: `6786 + r * (6 ±0)` - // Minimum execution time: 264_061_000 picoseconds. - Weight::from_parts(287_964_188, 6786) - // Standard Error: 490 - .saturating_add(Weight::from_parts(356_273, 0).saturating_mul(r.into())) + // Measured: `872 + r * (6 ±0)` + // Estimated: `6819 + r * (6 ±0)` + // Minimum execution time: 274_522_000 picoseconds. + Weight::from_parts(295_135_659, 6819) + // Standard Error: 1_052 + .saturating_add(Weight::from_parts(330_788, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -845,12 +845,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_now(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (6 ±0)` - // Estimated: `6771 + r * (6 ±0)` - // Minimum execution time: 275_707_000 picoseconds. - Weight::from_parts(290_797_828, 6771) - // Standard Error: 967 - .saturating_add(Weight::from_parts(352_839, 0).saturating_mul(r.into())) + // Measured: `863 + r * (6 ±0)` + // Estimated: `6804 + r * (6 ±0)` + // Minimum execution time: 274_228_000 picoseconds. + Weight::from_parts(289_201_593, 6804) + // Standard Error: 752 + .saturating_add(Weight::from_parts(337_860, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -874,12 +874,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_weight_to_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `904 + r * (14 ±0)` - // Estimated: `6839 + r * (14 ±0)` - // Minimum execution time: 272_492_000 picoseconds. - Weight::from_parts(295_010_878, 6839) - // Standard Error: 2_549 - .saturating_add(Weight::from_parts(1_426_715, 0).saturating_mul(r.into())) + // Measured: `937 + r * (14 ±0)` + // Estimated: `6872 + r * (14 ±0)` + // Minimum execution time: 277_142_000 picoseconds. + Weight::from_parts(296_736_114, 6872) + // Standard Error: 1_502 + .saturating_add(Weight::from_parts(1_446_663, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) @@ -901,12 +901,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_input(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `832 + r * (6 ±0)` - // Estimated: `6774 + r * (6 ±0)` - // Minimum execution time: 257_981_000 picoseconds. - Weight::from_parts(285_824_773, 6774) - // Standard Error: 704 - .saturating_add(Weight::from_parts(301_327, 0).saturating_mul(r.into())) + // Measured: `865 + r * (6 ±0)` + // Estimated: `6807 + r * (6 ±0)` + // Minimum execution time: 276_087_000 picoseconds. + Weight::from_parts(287_863_377, 6807) + // Standard Error: 495 + .saturating_add(Weight::from_parts(282_718, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -928,12 +928,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_input_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `836` - // Estimated: `6776` - // Minimum execution time: 259_470_000 picoseconds. - Weight::from_parts(232_759_442, 6776) - // Standard Error: 24 - .saturating_add(Weight::from_parts(981, 0).saturating_mul(n.into())) + // Measured: `869` + // Estimated: `6809` + // Minimum execution time: 277_128_000 picoseconds. + Weight::from_parts(234_478_674, 6809) + // Standard Error: 23 + .saturating_add(Weight::from_parts(1_052, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -954,12 +954,10 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1]`. fn seal_return(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `820 + r * (45 ±0)` - // Estimated: `6760 + r * (45 ±0)` - // Minimum execution time: 252_740_000 picoseconds. - Weight::from_parts(278_155_436, 6760) - // Standard Error: 882_420 - .saturating_add(Weight::from_parts(755_063, 0).saturating_mul(r.into())) + // Measured: `853 + r * (45 ±0)` + // Estimated: `6793 + r * (45 ±0)` + // Minimum execution time: 251_983_000 picoseconds. + Weight::from_parts(277_986_885, 6793) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) @@ -981,12 +979,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_return_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830` - // Estimated: `6777` - // Minimum execution time: 257_318_000 picoseconds. - Weight::from_parts(285_765_697, 6777) - // Standard Error: 1 - .saturating_add(Weight::from_parts(322, 0).saturating_mul(n.into())) + // Measured: `863` + // Estimated: `6810` + // Minimum execution time: 275_108_000 picoseconds. + Weight::from_parts(284_552_708, 6810) + // Standard Error: 0 + .saturating_add(Weight::from_parts(391, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1013,12 +1011,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2939 + r * (316 ±0)` - // Estimated: `8879 + r * (5266 ±0)` - // Minimum execution time: 280_392_000 picoseconds. - Weight::from_parts(310_023_381, 8879) - // Standard Error: 1_008_026 - .saturating_add(Weight::from_parts(130_208_818, 0).saturating_mul(r.into())) + // Measured: `2972 + r * (316 ±0)` + // Estimated: `8912 + r * (5266 ±0)` + // Minimum execution time: 281_278_000 picoseconds. + Weight::from_parts(306_800_667, 8912) + // Standard Error: 855_257 + .saturating_add(Weight::from_parts(126_508_132, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1044,12 +1042,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_random(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `911 + r * (10 ±0)` - // Estimated: `6852 + r * (10 ±0)` - // Minimum execution time: 270_547_000 picoseconds. - Weight::from_parts(295_931_189, 6852) - // Standard Error: 3_280 - .saturating_add(Weight::from_parts(1_941_248, 0).saturating_mul(r.into())) + // Measured: `944 + r * (10 ±0)` + // Estimated: `6885 + r * (10 ±0)` + // Minimum execution time: 260_609_000 picoseconds. + Weight::from_parts(287_385_076, 6885) + // Standard Error: 2_754 + .saturating_add(Weight::from_parts(2_057_388, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -1071,12 +1069,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_deposit_event(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (10 ±0)` - // Estimated: `6772 + r * (10 ±0)` - // Minimum execution time: 255_730_000 picoseconds. - Weight::from_parts(301_859_471, 6772) - // Standard Error: 5_401 - .saturating_add(Weight::from_parts(3_887_632, 0).saturating_mul(r.into())) + // Measured: `863 + r * (10 ±0)` + // Estimated: `6805 + r * (10 ±0)` + // Minimum execution time: 254_770_000 picoseconds. + Weight::from_parts(255_105_647, 6805) + // Standard Error: 5_707 + .saturating_add(Weight::from_parts(3_808_788, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -1099,14 +1097,14 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `847 + t * (32 ±0)` - // Estimated: `6792 + t * (2508 ±0)` - // Minimum execution time: 276_643_000 picoseconds. - Weight::from_parts(294_275_838, 6792) - // Standard Error: 106_745 - .saturating_add(Weight::from_parts(2_831_489, 0).saturating_mul(t.into())) - // Standard Error: 29 - .saturating_add(Weight::from_parts(624, 0).saturating_mul(n.into())) + // Measured: `880 + t * (32 ±0)` + // Estimated: `6825 + t * (2508 ±0)` + // Minimum execution time: 278_200_000 picoseconds. + Weight::from_parts(288_081_493, 6825) + // Standard Error: 97_535 + .saturating_add(Weight::from_parts(3_683_455, 0).saturating_mul(t.into())) + // Standard Error: 27 + .saturating_add(Weight::from_parts(731, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1130,12 +1128,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_debug_message(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `829 + r * (7 ±0)` - // Estimated: `6774 + r * (7 ±0)` - // Minimum execution time: 169_012_000 picoseconds. - Weight::from_parts(179_567_029, 6774) - // Standard Error: 534 - .saturating_add(Weight::from_parts(249_500, 0).saturating_mul(r.into())) + // Measured: `862 + r * (7 ±0)` + // Estimated: `6807 + r * (7 ±0)` + // Minimum execution time: 167_181_000 picoseconds. + Weight::from_parts(178_433_475, 6807) + // Standard Error: 374 + .saturating_add(Weight::from_parts(241_240, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) @@ -1157,12 +1155,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 1048576]`. fn seal_debug_message_per_byte(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `125780` - // Estimated: `131722` - // Minimum execution time: 408_647_000 picoseconds. - Weight::from_parts(387_678_006, 131722) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_045, 0).saturating_mul(i.into())) + // Measured: `125813` + // Estimated: `131755` + // Minimum execution time: 434_456_000 picoseconds. + Weight::from_parts(400_940_450, 131755) + // Standard Error: 13 + .saturating_add(Weight::from_parts(1_102, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1171,12 +1169,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_set_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `891 + r * (292 ±0)` - // Estimated: `892 + r * (293 ±0)` - // Minimum execution time: 279_315_000 picoseconds. - Weight::from_parts(171_270_899, 892) - // Standard Error: 15_492 - .saturating_add(Weight::from_parts(6_776_878, 0).saturating_mul(r.into())) + // Measured: `924 + r * (292 ±0)` + // Estimated: `925 + r * (293 ±0)` + // Minimum execution time: 277_825_000 picoseconds. + Weight::from_parts(159_688_263, 925) + // Standard Error: 13_610 + .saturating_add(Weight::from_parts(7_145_641, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1188,12 +1186,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_new_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1413` - // Estimated: `1396` - // Minimum execution time: 289_666_000 picoseconds. - Weight::from_parts(348_062_625, 1396) - // Standard Error: 79 - .saturating_add(Weight::from_parts(532, 0).saturating_mul(n.into())) + // Measured: `1446` + // Estimated: `1429` + // Minimum execution time: 284_745_000 picoseconds. + Weight::from_parts(345_928_316, 1429) + // Standard Error: 70 + .saturating_add(Weight::from_parts(547, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -1202,12 +1200,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_old_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1219 + n * (1 ±0)` - // Estimated: `1219 + n * (1 ±0)` - // Minimum execution time: 273_840_000 picoseconds. - Weight::from_parts(297_024_621, 1219) - // Standard Error: 55 - .saturating_add(Weight::from_parts(945, 0).saturating_mul(n.into())) + // Measured: `1252 + n * (1 ±0)` + // Estimated: `1252 + n * (1 ±0)` + // Minimum execution time: 275_328_000 picoseconds. + Weight::from_parts(300_037_010, 1252) + // Standard Error: 32 + .saturating_add(Weight::from_parts(558, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1217,12 +1215,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_clear_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `887 + r * (288 ±0)` - // Estimated: `893 + r * (289 ±0)` - // Minimum execution time: 279_110_000 picoseconds. - Weight::from_parts(177_898_012, 893) - // Standard Error: 16_287 - .saturating_add(Weight::from_parts(6_640_103, 0).saturating_mul(r.into())) + // Measured: `920 + r * (288 ±0)` + // Estimated: `926 + r * (289 ±0)` + // Minimum execution time: 273_742_000 picoseconds. + Weight::from_parts(169_430_806, 926) + // Standard Error: 11_821 + .saturating_add(Weight::from_parts(6_927_074, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1234,10 +1232,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_clear_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1215 + n * (1 ±0)` - // Estimated: `1215 + n * (1 ±0)` - // Minimum execution time: 276_566_000 picoseconds. - Weight::from_parts(304_992_376, 1215) + // Measured: `1248 + n * (1 ±0)` + // Estimated: `1248 + n * (1 ±0)` + // Minimum execution time: 275_167_000 picoseconds. + Weight::from_parts(301_883_655, 1248) + // Standard Error: 35 + .saturating_add(Weight::from_parts(4, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1247,12 +1247,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_get_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `887 + r * (296 ±0)` - // Estimated: `889 + r * (297 ±0)` - // Minimum execution time: 266_285_000 picoseconds. - Weight::from_parts(200_488_939, 889) - // Standard Error: 11_193 - .saturating_add(Weight::from_parts(5_467_725, 0).saturating_mul(r.into())) + // Measured: `920 + r * (296 ±0)` + // Estimated: `922 + r * (297 ±0)` + // Minimum execution time: 274_628_000 picoseconds. + Weight::from_parts(195_255_092, 922) + // Standard Error: 9_109 + .saturating_add(Weight::from_parts(5_707_060, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1263,12 +1263,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_get_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1231 + n * (1 ±0)` - // Estimated: `1231 + n * (1 ±0)` - // Minimum execution time: 278_625_000 picoseconds. - Weight::from_parts(304_319_493, 1231) - // Standard Error: 39 - .saturating_add(Weight::from_parts(415, 0).saturating_mul(n.into())) + // Measured: `1264 + n * (1 ±0)` + // Estimated: `1264 + n * (1 ±0)` + // Minimum execution time: 274_202_000 picoseconds. + Weight::from_parts(296_440_752, 1264) + // Standard Error: 38 + .saturating_add(Weight::from_parts(1_010, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1278,12 +1278,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_contains_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `898 + r * (288 ±0)` - // Estimated: `895 + r * (289 ±0)` - // Minimum execution time: 271_851_000 picoseconds. - Weight::from_parts(202_164_395, 895) - // Standard Error: 11_115 - .saturating_add(Weight::from_parts(5_273_320, 0).saturating_mul(r.into())) + // Measured: `931 + r * (288 ±0)` + // Estimated: `928 + r * (289 ±0)` + // Minimum execution time: 274_123_000 picoseconds. + Weight::from_parts(193_280_535, 928) + // Standard Error: 9_264 + .saturating_add(Weight::from_parts(5_548_039, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1294,12 +1294,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_contains_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1218 + n * (1 ±0)` - // Estimated: `1218 + n * (1 ±0)` - // Minimum execution time: 274_200_000 picoseconds. - Weight::from_parts(299_524_586, 1218) - // Standard Error: 33 - .saturating_add(Weight::from_parts(272, 0).saturating_mul(n.into())) + // Measured: `1251 + n * (1 ±0)` + // Estimated: `1251 + n * (1 ±0)` + // Minimum execution time: 276_425_000 picoseconds. + Weight::from_parts(300_521_806, 1251) + // Standard Error: 36 + .saturating_add(Weight::from_parts(83, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1309,12 +1309,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_take_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `880 + r * (296 ±0)` - // Estimated: `885 + r * (297 ±0)` - // Minimum execution time: 258_535_000 picoseconds. - Weight::from_parts(190_468_808, 885) - // Standard Error: 11_940 - .saturating_add(Weight::from_parts(6_737_079, 0).saturating_mul(r.into())) + // Measured: `913 + r * (296 ±0)` + // Estimated: `918 + r * (297 ±0)` + // Minimum execution time: 264_860_000 picoseconds. + Weight::from_parts(191_561_777, 918) + // Standard Error: 10_678 + .saturating_add(Weight::from_parts(6_895_457, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1326,12 +1326,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_take_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1232 + n * (1 ±0)` - // Estimated: `1232 + n * (1 ±0)` - // Minimum execution time: 280_536_000 picoseconds. - Weight::from_parts(304_479_477, 1232) + // Measured: `1265 + n * (1 ±0)` + // Estimated: `1265 + n * (1 ±0)` + // Minimum execution time: 282_501_000 picoseconds. + Weight::from_parts(303_351_919, 1265) // Standard Error: 37 - .saturating_add(Weight::from_parts(534, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(643, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1353,12 +1353,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_transfer(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1382 + r * (45 ±0)` - // Estimated: `7274 + r * (2520 ±0)` - // Minimum execution time: 260_373_000 picoseconds. - Weight::from_parts(278_290_000, 7274) - // Standard Error: 25_683 - .saturating_add(Weight::from_parts(39_264_864, 0).saturating_mul(r.into())) + // Measured: `1415 + r * (45 ±0)` + // Estimated: `7307 + r * (2520 ±0)` + // Minimum execution time: 273_198_000 picoseconds. + Weight::from_parts(179_673_238, 7307) + // Standard Error: 34_990 + .saturating_add(Weight::from_parts(38_468_091, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -1382,12 +1382,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_call(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1227 + r * (245 ±0)` - // Estimated: `9407 + r * (2721 ±0)` - // Minimum execution time: 277_621_000 picoseconds. - Weight::from_parts(281_775_000, 9407) - // Standard Error: 110_802 - .saturating_add(Weight::from_parts(245_363_533, 0).saturating_mul(r.into())) + // Measured: `1260 + r * (245 ±0)` + // Estimated: `9440 + r * (2721 ±0)` + // Minimum execution time: 283_869_000 picoseconds. + Weight::from_parts(288_374_000, 9440) + // Standard Error: 137_512 + .saturating_add(Weight::from_parts(248_206_665, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -1412,11 +1412,11 @@ impl WeightInfo for SubstrateWeight { fn seal_delegate_call(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` - // Estimated: `6779 + r * (2637 ±3)` - // Minimum execution time: 267_314_000 picoseconds. - Weight::from_parts(279_888_000, 6779) - // Standard Error: 144_378 - .saturating_add(Weight::from_parts(244_606_414, 0).saturating_mul(r.into())) + // Estimated: `6812 + r * (2637 ±3)` + // Minimum execution time: 257_577_000 picoseconds. + Weight::from_parts(277_310_000, 6812) + // Standard Error: 150_204 + .saturating_add(Weight::from_parts(249_943_483, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1441,14 +1441,14 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 1048576]`. fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1274 + t * (277 ±0)` - // Estimated: `12164 + t * (5227 ±0)` - // Minimum execution time: 477_589_000 picoseconds. - Weight::from_parts(70_712_793, 12164) - // Standard Error: 11_713_135 - .saturating_add(Weight::from_parts(375_371_698, 0).saturating_mul(t.into())) + // Measured: `1307 + t * (277 ±0)` + // Estimated: `12197 + t * (5227 ±0)` + // Minimum execution time: 471_081_000 picoseconds. + Weight::from_parts(79_081_122, 12197) + // Standard Error: 11_777_790 + .saturating_add(Weight::from_parts(357_425_411, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(991, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_111, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) @@ -1469,19 +1469,19 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Holds` (r:800 w:800) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1245 + r * (255 ±0)` - // Estimated: `9587 + r * (2731 ±0)` - // Minimum execution time: 662_502_000 picoseconds. - Weight::from_parts(671_726_000, 9587) - // Standard Error: 351_643 - .saturating_add(Weight::from_parts(390_457_971, 0).saturating_mul(r.into())) + // Measured: `1278 + r * (255 ±0)` + // Estimated: `9620 + r * (2731 ±0)` + // Minimum execution time: 672_742_000 picoseconds. + Weight::from_parts(680_025_000, 9620) + // Standard Error: 313_642 + .saturating_add(Weight::from_parts(388_311_259, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -1502,25 +1502,23 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1270 + t * (104 ±0)` - // Estimated: `12178 + t * (2549 ±1)` - // Minimum execution time: 2_675_525_000 picoseconds. - Weight::from_parts(851_421_242, 12178) - // Standard Error: 7_094_722 - .saturating_add(Weight::from_parts(112_457_697, 0).saturating_mul(t.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(1_867, 0).saturating_mul(i.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(1_931, 0).saturating_mul(s.into())) + // Measured: `1303 + t * (104 ±0)` + // Estimated: `12211 + t * (2549 ±1)` + // Minimum execution time: 2_733_870_000 picoseconds. + Weight::from_parts(1_001_793_458, 12211) + // Standard Error: 12 + .saturating_add(Weight::from_parts(1_963, 0).saturating_mul(i.into())) + // Standard Error: 12 + .saturating_add(Weight::from_parts(2_060, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(16_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(11_u64)) @@ -1544,12 +1542,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_sha2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `829 + r * (8 ±0)` - // Estimated: `6768 + r * (8 ±0)` - // Minimum execution time: 270_818_000 picoseconds. - Weight::from_parts(286_520_166, 6768) - // Standard Error: 575 - .saturating_add(Weight::from_parts(402_286, 0).saturating_mul(r.into())) + // Measured: `862 + r * (8 ±0)` + // Estimated: `6801 + r * (8 ±0)` + // Minimum execution time: 272_658_000 picoseconds. + Weight::from_parts(282_717_645, 6801) + // Standard Error: 517 + .saturating_add(Weight::from_parts(400_604, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1571,12 +1569,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `837` - // Estimated: `6775` - // Minimum execution time: 257_134_000 picoseconds. - Weight::from_parts(268_214_648, 6775) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_098, 0).saturating_mul(n.into())) + // Measured: `870` + // Estimated: `6808` + // Minimum execution time: 260_969_000 picoseconds. + Weight::from_parts(265_206_847, 6808) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_134, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1597,12 +1595,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_keccak_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + r * (8 ±0)` - // Estimated: `6773 + r * (8 ±0)` - // Minimum execution time: 259_222_000 picoseconds. - Weight::from_parts(283_273_283, 6773) - // Standard Error: 967 - .saturating_add(Weight::from_parts(817_596, 0).saturating_mul(r.into())) + // Measured: `864 + r * (8 ±0)` + // Estimated: `6806 + r * (8 ±0)` + // Minimum execution time: 262_351_000 picoseconds. + Weight::from_parts(286_974_296, 6806) + // Standard Error: 514 + .saturating_add(Weight::from_parts(802_363, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1624,12 +1622,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839` - // Estimated: `6781` - // Minimum execution time: 260_040_000 picoseconds. - Weight::from_parts(283_869_860, 6781) + // Measured: `872` + // Estimated: `6814` + // Minimum execution time: 276_907_000 picoseconds. + Weight::from_parts(277_928_418, 6814) // Standard Error: 1 - .saturating_add(Weight::from_parts(3_349, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_410, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1650,12 +1648,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + r * (8 ±0)` - // Estimated: `6775 + r * (8 ±0)` - // Minimum execution time: 260_698_000 picoseconds. - Weight::from_parts(282_900_345, 6775) - // Standard Error: 805 - .saturating_add(Weight::from_parts(469_457, 0).saturating_mul(r.into())) + // Measured: `864 + r * (8 ±0)` + // Estimated: `6808 + r * (8 ±0)` + // Minimum execution time: 263_660_000 picoseconds. + Weight::from_parts(285_665_916, 6808) + // Standard Error: 527 + .saturating_add(Weight::from_parts(480_457, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1677,12 +1675,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839` - // Estimated: `6780` - // Minimum execution time: 256_967_000 picoseconds. - Weight::from_parts(273_024_512, 6780) + // Measured: `872` + // Estimated: `6813` + // Minimum execution time: 262_071_000 picoseconds. + Weight::from_parts(270_115_341, 6813) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_254, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1703,12 +1701,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_128(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + r * (8 ±0)` - // Estimated: `6772 + r * (8 ±0)` - // Minimum execution time: 272_039_000 picoseconds. - Weight::from_parts(289_853_116, 6772) + // Measured: `864 + r * (8 ±0)` + // Estimated: `6805 + r * (8 ±0)` + // Minimum execution time: 265_568_000 picoseconds. + Weight::from_parts(285_791_811, 6805) // Standard Error: 559 - .saturating_add(Weight::from_parts(459_383, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(505_330, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1730,12 +1728,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839` - // Estimated: `6778` - // Minimum execution time: 253_913_000 picoseconds. - Weight::from_parts(274_682_010, 6778) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(n.into())) + // Measured: `872` + // Estimated: `6811` + // Minimum execution time: 271_336_000 picoseconds. + Weight::from_parts(272_829_313, 6811) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_252, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1756,12 +1754,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 125697]`. fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `964 + n * (1 ±0)` - // Estimated: `6901 + n * (1 ±0)` - // Minimum execution time: 343_955_000 picoseconds. - Weight::from_parts(350_777_388, 6901) + // Measured: `997 + n * (1 ±0)` + // Estimated: `6934 + n * (1 ±0)` + // Minimum execution time: 351_146_000 picoseconds. + Weight::from_parts(355_368_323, 6934) // Standard Error: 14 - .saturating_add(Weight::from_parts(5_915, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(6_155, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1783,12 +1781,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_sr25519_verify(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `774 + r * (112 ±0)` - // Estimated: `6715 + r * (112 ±0)` - // Minimum execution time: 268_698_000 picoseconds. - Weight::from_parts(336_398_814, 6715) - // Standard Error: 16_627 - .saturating_add(Weight::from_parts(56_155_384, 0).saturating_mul(r.into())) + // Measured: `807 + r * (112 ±0)` + // Estimated: `6748 + r * (112 ±0)` + // Minimum execution time: 277_250_000 picoseconds. + Weight::from_parts(346_490_114, 6748) + // Standard Error: 14_654 + .saturating_add(Weight::from_parts(56_127_492, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) @@ -1810,12 +1808,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_recover(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `874 + r * (76 ±0)` - // Estimated: `6768 + r * (77 ±0)` - // Minimum execution time: 258_906_000 picoseconds. - Weight::from_parts(340_672_829, 6768) - // Standard Error: 18_295 - .saturating_add(Weight::from_parts(46_106_884, 0).saturating_mul(r.into())) + // Measured: `907 + r * (76 ±0)` + // Estimated: `6801 + r * (77 ±0)` + // Minimum execution time: 272_697_000 picoseconds. + Weight::from_parts(345_385_667, 6801) + // Standard Error: 14_226 + .saturating_add(Weight::from_parts(46_037_637, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) @@ -1837,12 +1835,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `844 + r * (42 ±0)` - // Estimated: `6783 + r * (42 ±0)` - // Minimum execution time: 275_105_000 picoseconds. - Weight::from_parts(313_700_348, 6783) - // Standard Error: 11_960 - .saturating_add(Weight::from_parts(12_050_300, 0).saturating_mul(r.into())) + // Measured: `877 + r * (42 ±0)` + // Estimated: `6816 + r * (42 ±0)` + // Minimum execution time: 271_800_000 picoseconds. + Weight::from_parts(314_891_136, 6816) + // Standard Error: 9_762 + .saturating_add(Weight::from_parts(11_949_979, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) @@ -1865,11 +1863,11 @@ impl WeightInfo for SubstrateWeight { fn seal_set_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` - // Estimated: `6774 + r * (3090 ±7)` - // Minimum execution time: 259_178_000 picoseconds. - Weight::from_parts(275_643_000, 6774) - // Standard Error: 54_044 - .saturating_add(Weight::from_parts(26_026_930, 0).saturating_mul(r.into())) + // Estimated: `6807 + r * (3090 ±10)` + // Minimum execution time: 274_238_000 picoseconds. + Weight::from_parts(278_034_000, 6807) + // Standard Error: 77_011 + .saturating_add(Weight::from_parts(27_627_005, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1893,12 +1891,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 32]`. fn add_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `895 + r * (131 ±0)` - // Estimated: `6845 + r * (2606 ±0)` - // Minimum execution time: 263_386_000 picoseconds. - Weight::from_parts(295_443_439, 6845) - // Standard Error: 24_422 - .saturating_add(Weight::from_parts(6_429_537, 0).saturating_mul(r.into())) + // Measured: `928 + r * (131 ±0)` + // Estimated: `6878 + r * (2606 ±0)` + // Minimum execution time: 271_519_000 picoseconds. + Weight::from_parts(292_726_476, 6878) + // Standard Error: 23_870 + .saturating_add(Weight::from_parts(6_695_172, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1922,12 +1920,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 32]`. fn remove_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `936 + r * (183 ±0)` + // Measured: `969 + r * (183 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 261_371_000 picoseconds. - Weight::from_parts(297_493_194, 129453) - // Standard Error: 23_734 - .saturating_add(Weight::from_parts(5_673_169, 0).saturating_mul(r.into())) + // Minimum execution time: 274_675_000 picoseconds. + Weight::from_parts(293_727_489, 129453) + // Standard Error: 23_160 + .saturating_add(Weight::from_parts(5_895_043, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1951,12 +1949,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `825 + r * (3 ±0)` - // Estimated: `6771 + r * (3 ±0)` - // Minimum execution time: 275_558_000 picoseconds. - Weight::from_parts(287_220_765, 6771) - // Standard Error: 437 - .saturating_add(Weight::from_parts(184_125, 0).saturating_mul(r.into())) + // Measured: `858 + r * (3 ±0)` + // Estimated: `6804 + r * (3 ±0)` + // Minimum execution time: 253_330_000 picoseconds. + Weight::from_parts(281_079_564, 6804) + // Standard Error: 378 + .saturating_add(Weight::from_parts(180_655, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -1978,12 +1976,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_account_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2076 + r * (39 ±0)` - // Estimated: `7866 + r * (40 ±0)` - // Minimum execution time: 265_752_000 picoseconds. - Weight::from_parts(331_187_665, 7866) - // Standard Error: 1_950 - .saturating_add(Weight::from_parts(312_262, 0).saturating_mul(r.into())) + // Measured: `2109 + r * (39 ±0)` + // Estimated: `7899 + r * (40 ±0)` + // Minimum execution time: 276_552_000 picoseconds. + Weight::from_parts(368_521_088, 7899) + // Standard Error: 2_310 + .saturating_add(Weight::from_parts(318_129, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) @@ -2007,12 +2005,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_instantiation_nonce(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `828 + r * (3 ±0)` - // Estimated: `6768 + r * (3 ±0)` - // Minimum execution time: 257_114_000 picoseconds. - Weight::from_parts(286_686_654, 6768) - // Standard Error: 426 - .saturating_add(Weight::from_parts(162_295, 0).saturating_mul(r.into())) + // Measured: `861 + r * (3 ±0)` + // Estimated: `6801 + r * (3 ±0)` + // Minimum execution time: 258_953_000 picoseconds. + Weight::from_parts(288_222_836, 6801) + // Standard Error: 367 + .saturating_add(Weight::from_parts(152_842, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2022,10 +2020,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_388_000 picoseconds. - Weight::from_parts(1_680_408, 0) - // Standard Error: 21 - .saturating_add(Weight::from_parts(10_564, 0).saturating_mul(r.into())) + // Minimum execution time: 1_476_000 picoseconds. + Weight::from_parts(2_119_717, 0) + // Standard Error: 28 + .saturating_add(Weight::from_parts(9_805, 0).saturating_mul(r.into())) } } @@ -2037,8 +2035,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_410_000 picoseconds. - Weight::from_parts(2_581_000, 1627) + // Minimum execution time: 2_548_000 picoseconds. + Weight::from_parts(2_670_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2048,10 +2046,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `451 + k * (69 ±0)` // Estimated: `441 + k * (70 ±0)` - // Minimum execution time: 13_278_000 picoseconds. - Weight::from_parts(13_944_000, 441) - // Standard Error: 1_643 - .saturating_add(Weight::from_parts(1_194_404, 0).saturating_mul(k.into())) + // Minimum execution time: 13_526_000 picoseconds. + Weight::from_parts(13_902_000, 441) + // Standard Error: 1_058 + .saturating_add(Weight::from_parts(1_274_724, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -2065,10 +2063,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_533_000 picoseconds. - Weight::from_parts(9_141_899, 6149) + // Minimum execution time: 8_426_000 picoseconds. + Weight::from_parts(8_591_621, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_327, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_203, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2081,8 +2079,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_998_000 picoseconds. - Weight::from_parts(17_776_000, 6450) + // Minimum execution time: 17_008_000 picoseconds. + Weight::from_parts(17_742_000, 6450) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2095,10 +2093,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_919_000 picoseconds. - Weight::from_parts(4_057_153, 3635) - // Standard Error: 1_252 - .saturating_add(Weight::from_parts(1_151_419, 0).saturating_mul(k.into())) + // Minimum execution time: 3_949_000 picoseconds. + Weight::from_parts(4_062_000, 3635) + // Standard Error: 1_983 + .saturating_add(Weight::from_parts(1_173_197, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -2117,10 +2115,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `325 + c * (1 ±0)` // Estimated: `6263 + c * (1 ±0)` - // Minimum execution time: 17_730_000 picoseconds. - Weight::from_parts(17_540_884, 6263) + // Minimum execution time: 17_094_000 picoseconds. + Weight::from_parts(17_338_591, 6263) // Standard Error: 1 - .saturating_add(Weight::from_parts(417, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(436, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2131,8 +2129,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 13_089_000 picoseconds. - Weight::from_parts(13_727_000, 6380) + // Minimum execution time: 12_704_000 picoseconds. + Weight::from_parts(13_147_000, 6380) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2146,8 +2144,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `360` // Estimated: `6300` - // Minimum execution time: 49_083_000 picoseconds. - Weight::from_parts(50_462_000, 6300) + // Minimum execution time: 48_387_000 picoseconds. + Weight::from_parts(50_024_000, 6300) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2159,8 +2157,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 49_299_000 picoseconds. - Weight::from_parts(50_805_000, 6534) + // Minimum execution time: 59_300_000 picoseconds. + Weight::from_parts(61_805_000, 6534) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2170,8 +2168,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 3_305_000 picoseconds. - Weight::from_parts(3_489_000, 1627) + // Minimum execution time: 3_327_000 picoseconds. + Weight::from_parts(3_502_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2183,8 +2181,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 12_657_000 picoseconds. - Weight::from_parts(13_100_000, 3631) + // Minimum execution time: 12_759_000 picoseconds. + Weight::from_parts(13_134_000, 3631) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2194,8 +2192,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_784_000 picoseconds. - Weight::from_parts(4_994_000, 3607) + // Minimum execution time: 4_775_000 picoseconds. + Weight::from_parts(5_084_000, 3607) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2206,8 +2204,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 6_762_000 picoseconds. - Weight::from_parts(6_945_000, 3632) + // Minimum execution time: 6_663_000 picoseconds. + Weight::from_parts(6_855_000, 3632) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2218,8 +2216,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_999_000 picoseconds. - Weight::from_parts(7_372_000, 3607) + // Minimum execution time: 7_212_000 picoseconds. + Weight::from_parts(7_426_000, 3607) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2240,12 +2238,12 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 125952]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `759` - // Estimated: `6710 + c * (1 ±0)` - // Minimum execution time: 304_121_000 picoseconds. - Weight::from_parts(288_627_840, 6710) - // Standard Error: 83 - .saturating_add(Weight::from_parts(37_343, 0).saturating_mul(c.into())) + // Measured: `792` + // Estimated: `6743 + c * (1 ±0)` + // Minimum execution time: 289_557_000 picoseconds. + Weight::from_parts(272_895_652, 6743) + // Standard Error: 80 + .saturating_add(Weight::from_parts(39_917, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2273,16 +2271,16 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 1048576]`. fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `290` - // Estimated: `8714` - // Minimum execution time: 4_101_589_000 picoseconds. - Weight::from_parts(694_193_047, 8714) - // Standard Error: 334 - .saturating_add(Weight::from_parts(108_847, 0).saturating_mul(c.into())) - // Standard Error: 40 - .saturating_add(Weight::from_parts(1_677, 0).saturating_mul(i.into())) - // Standard Error: 40 - .saturating_add(Weight::from_parts(1_783, 0).saturating_mul(s.into())) + // Measured: `323` + // Estimated: `8747` + // Minimum execution time: 4_671_359_000 picoseconds. + Weight::from_parts(586_523_882, 8747) + // Standard Error: 206 + .saturating_add(Weight::from_parts(115_402, 0).saturating_mul(c.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(1_797, 0).saturating_mul(i.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(2_046, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } @@ -2300,22 +2298,22 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `527` - // Estimated: `6471` - // Minimum execution time: 2_011_580_000 picoseconds. - Weight::from_parts(397_415_227, 6471) - // Standard Error: 10 - .saturating_add(Weight::from_parts(1_689, 0).saturating_mul(i.into())) - // Standard Error: 10 - .saturating_add(Weight::from_parts(1_679, 0).saturating_mul(s.into())) + // Measured: `560` + // Estimated: `6504` + // Minimum execution time: 2_170_657_000 picoseconds. + Weight::from_parts(369_331_405, 6504) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_940, 0).saturating_mul(i.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_858, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -2335,10 +2333,10 @@ impl WeightInfo for () { /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `793` - // Estimated: `6733` - // Minimum execution time: 204_975_000 picoseconds. - Weight::from_parts(214_770_000, 6733) + // Measured: `826` + // Estimated: `6766` + // Minimum execution time: 204_287_000 picoseconds. + Weight::from_parts(213_239_000, 6766) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2357,10 +2355,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 269_545_000 picoseconds. - Weight::from_parts(256_054_650, 3607) - // Standard Error: 91 - .saturating_add(Weight::from_parts(72_743, 0).saturating_mul(c.into())) + // Minimum execution time: 285_434_000 picoseconds. + Weight::from_parts(242_697_648, 3607) + // Standard Error: 128 + .saturating_add(Weight::from_parts(76_087, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2378,8 +2376,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 47_880_000 picoseconds. - Weight::from_parts(49_427_000, 3780) + // Minimum execution time: 46_486_000 picoseconds. + Weight::from_parts(48_422_000, 3780) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2395,8 +2393,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 37_898_000 picoseconds. - Weight::from_parts(39_826_000, 8967) + // Minimum execution time: 37_568_000 picoseconds. + Weight::from_parts(38_589_000, 8967) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -2417,12 +2415,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_caller(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `833 + r * (6 ±0)` - // Estimated: `6773 + r * (6 ±0)` - // Minimum execution time: 260_916_000 picoseconds. - Weight::from_parts(295_521_846, 6773) - // Standard Error: 1_126 - .saturating_add(Weight::from_parts(348_317, 0).saturating_mul(r.into())) + // Measured: `866 + r * (6 ±0)` + // Estimated: `6806 + r * (6 ±0)` + // Minimum execution time: 274_513_000 picoseconds. + Weight::from_parts(288_793_403, 6806) + // Standard Error: 650 + .saturating_add(Weight::from_parts(339_309, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2444,12 +2442,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_is_contract(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `889 + r * (209 ±0)` - // Estimated: `6793 + r * (2684 ±0)` - // Minimum execution time: 274_335_000 picoseconds. - Weight::from_parts(132_998_512, 6793) - // Standard Error: 7_396 - .saturating_add(Weight::from_parts(3_602_287, 0).saturating_mul(r.into())) + // Measured: `922 + r * (209 ±0)` + // Estimated: `6826 + r * (2684 ±0)` + // Minimum execution time: 260_096_000 picoseconds. + Weight::from_parts(149_954_322, 6826) + // Standard Error: 5_713 + .saturating_add(Weight::from_parts(3_788_924, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2472,12 +2470,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `888 + r * (213 ±0)` - // Estimated: `6797 + r * (2688 ±0)` - // Minimum execution time: 272_514_000 picoseconds. - Weight::from_parts(104_825_618, 6797) - // Standard Error: 10_038 - .saturating_add(Weight::from_parts(4_520_258, 0).saturating_mul(r.into())) + // Measured: `921 + r * (213 ±0)` + // Estimated: `6830 + r * (2688 ±0)` + // Minimum execution time: 277_496_000 picoseconds. + Weight::from_parts(285_839_000, 6830) + // Standard Error: 10_076 + .saturating_add(Weight::from_parts(4_720_110, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2500,12 +2498,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_own_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `840 + r * (6 ±0)` - // Estimated: `6782 + r * (6 ±0)` - // Minimum execution time: 264_593_000 picoseconds. - Weight::from_parts(294_139_363, 6782) - // Standard Error: 907 - .saturating_add(Weight::from_parts(432_964, 0).saturating_mul(r.into())) + // Measured: `873 + r * (6 ±0)` + // Estimated: `6815 + r * (6 ±0)` + // Minimum execution time: 275_655_000 picoseconds. + Weight::from_parts(291_386_528, 6815) + // Standard Error: 898 + .saturating_add(Weight::from_parts(428_765, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2527,12 +2525,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_origin(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (3 ±0)` - // Estimated: `6771 + r * (3 ±0)` - // Minimum execution time: 260_412_000 picoseconds. - Weight::from_parts(284_371_703, 6771) - // Standard Error: 433 - .saturating_add(Weight::from_parts(182_952, 0).saturating_mul(r.into())) + // Measured: `863 + r * (3 ±0)` + // Estimated: `6804 + r * (3 ±0)` + // Minimum execution time: 260_323_000 picoseconds. + Weight::from_parts(286_371_403, 6804) + // Standard Error: 451 + .saturating_add(Weight::from_parts(183_053, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2552,12 +2550,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_root(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `720 + r * (3 ±0)` - // Estimated: `6660 + r * (3 ±0)` - // Minimum execution time: 255_112_000 picoseconds. - Weight::from_parts(273_052_488, 6660) - // Standard Error: 376 - .saturating_add(Weight::from_parts(166_644, 0).saturating_mul(r.into())) + // Measured: `753 + r * (3 ±0)` + // Estimated: `6693 + r * (3 ±0)` + // Minimum execution time: 262_974_000 picoseconds. + Weight::from_parts(276_571_502, 6693) + // Standard Error: 527 + .saturating_add(Weight::from_parts(165_364, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2579,12 +2577,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `834 + r * (6 ±0)` - // Estimated: `6774 + r * (6 ±0)` - // Minimum execution time: 270_426_000 picoseconds. - Weight::from_parts(289_240_775, 6774) - // Standard Error: 748 - .saturating_add(Weight::from_parts(344_791, 0).saturating_mul(r.into())) + // Measured: `867 + r * (6 ±0)` + // Estimated: `6807 + r * (6 ±0)` + // Minimum execution time: 272_826_000 picoseconds. + Weight::from_parts(290_963_001, 6807) + // Standard Error: 810 + .saturating_add(Weight::from_parts(343_762, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2606,12 +2604,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_gas_left(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (6 ±0)` - // Estimated: `6773 + r * (6 ±0)` - // Minimum execution time: 260_217_000 picoseconds. - Weight::from_parts(288_660_978, 6773) - // Standard Error: 1_199 - .saturating_add(Weight::from_parts(550_304, 0).saturating_mul(r.into())) + // Measured: `863 + r * (6 ±0)` + // Estimated: `6806 + r * (6 ±0)` + // Minimum execution time: 277_324_000 picoseconds. + Weight::from_parts(290_872_814, 6806) + // Standard Error: 766 + .saturating_add(Weight::from_parts(371_542, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2633,12 +2631,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `974 + r * (6 ±0)` - // Estimated: `6898 + r * (6 ±0)` - // Minimum execution time: 273_473_000 picoseconds. - Weight::from_parts(298_889_279, 6898) - // Standard Error: 4_604 - .saturating_add(Weight::from_parts(1_630_175, 0).saturating_mul(r.into())) + // Measured: `1007 + r * (6 ±0)` + // Estimated: `6931 + r * (6 ±0)` + // Minimum execution time: 274_460_000 picoseconds. + Weight::from_parts(285_748_025, 6931) + // Standard Error: 1_570 + .saturating_add(Weight::from_parts(1_656_237, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2660,12 +2658,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_value_transferred(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `844 + r * (6 ±0)` - // Estimated: `6790 + r * (6 ±0)` - // Minimum execution time: 262_033_000 picoseconds. - Weight::from_parts(284_293_851, 6790) - // Standard Error: 591 - .saturating_add(Weight::from_parts(369_240, 0).saturating_mul(r.into())) + // Measured: `877 + r * (6 ±0)` + // Estimated: `6823 + r * (6 ±0)` + // Minimum execution time: 278_254_000 picoseconds. + Weight::from_parts(283_893_525, 6823) + // Standard Error: 726 + .saturating_add(Weight::from_parts(347_368, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2687,12 +2685,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_minimum_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `842 + r * (6 ±0)` - // Estimated: `6783 + r * (6 ±0)` - // Minimum execution time: 274_568_000 picoseconds. - Weight::from_parts(294_688_466, 6783) - // Standard Error: 768 - .saturating_add(Weight::from_parts(349_584, 0).saturating_mul(r.into())) + // Measured: `875 + r * (6 ±0)` + // Estimated: `6816 + r * (6 ±0)` + // Minimum execution time: 279_646_000 picoseconds. + Weight::from_parts(292_505_446, 6816) + // Standard Error: 867 + .saturating_add(Weight::from_parts(337_202, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2714,12 +2712,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_block_number(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839 + r * (6 ±0)` - // Estimated: `6786 + r * (6 ±0)` - // Minimum execution time: 264_061_000 picoseconds. - Weight::from_parts(287_964_188, 6786) - // Standard Error: 490 - .saturating_add(Weight::from_parts(356_273, 0).saturating_mul(r.into())) + // Measured: `872 + r * (6 ±0)` + // Estimated: `6819 + r * (6 ±0)` + // Minimum execution time: 274_522_000 picoseconds. + Weight::from_parts(295_135_659, 6819) + // Standard Error: 1_052 + .saturating_add(Weight::from_parts(330_788, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2741,12 +2739,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_now(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (6 ±0)` - // Estimated: `6771 + r * (6 ±0)` - // Minimum execution time: 275_707_000 picoseconds. - Weight::from_parts(290_797_828, 6771) - // Standard Error: 967 - .saturating_add(Weight::from_parts(352_839, 0).saturating_mul(r.into())) + // Measured: `863 + r * (6 ±0)` + // Estimated: `6804 + r * (6 ±0)` + // Minimum execution time: 274_228_000 picoseconds. + Weight::from_parts(289_201_593, 6804) + // Standard Error: 752 + .saturating_add(Weight::from_parts(337_860, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2770,12 +2768,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_weight_to_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `904 + r * (14 ±0)` - // Estimated: `6839 + r * (14 ±0)` - // Minimum execution time: 272_492_000 picoseconds. - Weight::from_parts(295_010_878, 6839) - // Standard Error: 2_549 - .saturating_add(Weight::from_parts(1_426_715, 0).saturating_mul(r.into())) + // Measured: `937 + r * (14 ±0)` + // Estimated: `6872 + r * (14 ±0)` + // Minimum execution time: 277_142_000 picoseconds. + Weight::from_parts(296_736_114, 6872) + // Standard Error: 1_502 + .saturating_add(Weight::from_parts(1_446_663, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) @@ -2797,12 +2795,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_input(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `832 + r * (6 ±0)` - // Estimated: `6774 + r * (6 ±0)` - // Minimum execution time: 257_981_000 picoseconds. - Weight::from_parts(285_824_773, 6774) - // Standard Error: 704 - .saturating_add(Weight::from_parts(301_327, 0).saturating_mul(r.into())) + // Measured: `865 + r * (6 ±0)` + // Estimated: `6807 + r * (6 ±0)` + // Minimum execution time: 276_087_000 picoseconds. + Weight::from_parts(287_863_377, 6807) + // Standard Error: 495 + .saturating_add(Weight::from_parts(282_718, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2824,12 +2822,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_input_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `836` - // Estimated: `6776` - // Minimum execution time: 259_470_000 picoseconds. - Weight::from_parts(232_759_442, 6776) - // Standard Error: 24 - .saturating_add(Weight::from_parts(981, 0).saturating_mul(n.into())) + // Measured: `869` + // Estimated: `6809` + // Minimum execution time: 277_128_000 picoseconds. + Weight::from_parts(234_478_674, 6809) + // Standard Error: 23 + .saturating_add(Weight::from_parts(1_052, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -2850,12 +2848,10 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1]`. fn seal_return(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `820 + r * (45 ±0)` - // Estimated: `6760 + r * (45 ±0)` - // Minimum execution time: 252_740_000 picoseconds. - Weight::from_parts(278_155_436, 6760) - // Standard Error: 882_420 - .saturating_add(Weight::from_parts(755_063, 0).saturating_mul(r.into())) + // Measured: `853 + r * (45 ±0)` + // Estimated: `6793 + r * (45 ±0)` + // Minimum execution time: 251_983_000 picoseconds. + Weight::from_parts(277_986_885, 6793) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) @@ -2877,12 +2873,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_return_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830` - // Estimated: `6777` - // Minimum execution time: 257_318_000 picoseconds. - Weight::from_parts(285_765_697, 6777) - // Standard Error: 1 - .saturating_add(Weight::from_parts(322, 0).saturating_mul(n.into())) + // Measured: `863` + // Estimated: `6810` + // Minimum execution time: 275_108_000 picoseconds. + Weight::from_parts(284_552_708, 6810) + // Standard Error: 0 + .saturating_add(Weight::from_parts(391, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -2909,12 +2905,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2939 + r * (316 ±0)` - // Estimated: `8879 + r * (5266 ±0)` - // Minimum execution time: 280_392_000 picoseconds. - Weight::from_parts(310_023_381, 8879) - // Standard Error: 1_008_026 - .saturating_add(Weight::from_parts(130_208_818, 0).saturating_mul(r.into())) + // Measured: `2972 + r * (316 ±0)` + // Estimated: `8912 + r * (5266 ±0)` + // Minimum execution time: 281_278_000 picoseconds. + Weight::from_parts(306_800_667, 8912) + // Standard Error: 855_257 + .saturating_add(Weight::from_parts(126_508_132, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2940,12 +2936,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_random(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `911 + r * (10 ±0)` - // Estimated: `6852 + r * (10 ±0)` - // Minimum execution time: 270_547_000 picoseconds. - Weight::from_parts(295_931_189, 6852) - // Standard Error: 3_280 - .saturating_add(Weight::from_parts(1_941_248, 0).saturating_mul(r.into())) + // Measured: `944 + r * (10 ±0)` + // Estimated: `6885 + r * (10 ±0)` + // Minimum execution time: 260_609_000 picoseconds. + Weight::from_parts(287_385_076, 6885) + // Standard Error: 2_754 + .saturating_add(Weight::from_parts(2_057_388, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -2967,12 +2963,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_deposit_event(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (10 ±0)` - // Estimated: `6772 + r * (10 ±0)` - // Minimum execution time: 255_730_000 picoseconds. - Weight::from_parts(301_859_471, 6772) - // Standard Error: 5_401 - .saturating_add(Weight::from_parts(3_887_632, 0).saturating_mul(r.into())) + // Measured: `863 + r * (10 ±0)` + // Estimated: `6805 + r * (10 ±0)` + // Minimum execution time: 254_770_000 picoseconds. + Weight::from_parts(255_105_647, 6805) + // Standard Error: 5_707 + .saturating_add(Weight::from_parts(3_808_788, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -2995,14 +2991,14 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `847 + t * (32 ±0)` - // Estimated: `6792 + t * (2508 ±0)` - // Minimum execution time: 276_643_000 picoseconds. - Weight::from_parts(294_275_838, 6792) - // Standard Error: 106_745 - .saturating_add(Weight::from_parts(2_831_489, 0).saturating_mul(t.into())) - // Standard Error: 29 - .saturating_add(Weight::from_parts(624, 0).saturating_mul(n.into())) + // Measured: `880 + t * (32 ±0)` + // Estimated: `6825 + t * (2508 ±0)` + // Minimum execution time: 278_200_000 picoseconds. + Weight::from_parts(288_081_493, 6825) + // Standard Error: 97_535 + .saturating_add(Weight::from_parts(3_683_455, 0).saturating_mul(t.into())) + // Standard Error: 27 + .saturating_add(Weight::from_parts(731, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3026,12 +3022,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_debug_message(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `829 + r * (7 ±0)` - // Estimated: `6774 + r * (7 ±0)` - // Minimum execution time: 169_012_000 picoseconds. - Weight::from_parts(179_567_029, 6774) - // Standard Error: 534 - .saturating_add(Weight::from_parts(249_500, 0).saturating_mul(r.into())) + // Measured: `862 + r * (7 ±0)` + // Estimated: `6807 + r * (7 ±0)` + // Minimum execution time: 167_181_000 picoseconds. + Weight::from_parts(178_433_475, 6807) + // Standard Error: 374 + .saturating_add(Weight::from_parts(241_240, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) @@ -3053,12 +3049,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 1048576]`. fn seal_debug_message_per_byte(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `125780` - // Estimated: `131722` - // Minimum execution time: 408_647_000 picoseconds. - Weight::from_parts(387_678_006, 131722) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_045, 0).saturating_mul(i.into())) + // Measured: `125813` + // Estimated: `131755` + // Minimum execution time: 434_456_000 picoseconds. + Weight::from_parts(400_940_450, 131755) + // Standard Error: 13 + .saturating_add(Weight::from_parts(1_102, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3067,12 +3063,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_set_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `891 + r * (292 ±0)` - // Estimated: `892 + r * (293 ±0)` - // Minimum execution time: 279_315_000 picoseconds. - Weight::from_parts(171_270_899, 892) - // Standard Error: 15_492 - .saturating_add(Weight::from_parts(6_776_878, 0).saturating_mul(r.into())) + // Measured: `924 + r * (292 ±0)` + // Estimated: `925 + r * (293 ±0)` + // Minimum execution time: 277_825_000 picoseconds. + Weight::from_parts(159_688_263, 925) + // Standard Error: 13_610 + .saturating_add(Weight::from_parts(7_145_641, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3084,12 +3080,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_new_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1413` - // Estimated: `1396` - // Minimum execution time: 289_666_000 picoseconds. - Weight::from_parts(348_062_625, 1396) - // Standard Error: 79 - .saturating_add(Weight::from_parts(532, 0).saturating_mul(n.into())) + // Measured: `1446` + // Estimated: `1429` + // Minimum execution time: 284_745_000 picoseconds. + Weight::from_parts(345_928_316, 1429) + // Standard Error: 70 + .saturating_add(Weight::from_parts(547, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -3098,12 +3094,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_old_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1219 + n * (1 ±0)` - // Estimated: `1219 + n * (1 ±0)` - // Minimum execution time: 273_840_000 picoseconds. - Weight::from_parts(297_024_621, 1219) - // Standard Error: 55 - .saturating_add(Weight::from_parts(945, 0).saturating_mul(n.into())) + // Measured: `1252 + n * (1 ±0)` + // Estimated: `1252 + n * (1 ±0)` + // Minimum execution time: 275_328_000 picoseconds. + Weight::from_parts(300_037_010, 1252) + // Standard Error: 32 + .saturating_add(Weight::from_parts(558, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3113,12 +3109,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_clear_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `887 + r * (288 ±0)` - // Estimated: `893 + r * (289 ±0)` - // Minimum execution time: 279_110_000 picoseconds. - Weight::from_parts(177_898_012, 893) - // Standard Error: 16_287 - .saturating_add(Weight::from_parts(6_640_103, 0).saturating_mul(r.into())) + // Measured: `920 + r * (288 ±0)` + // Estimated: `926 + r * (289 ±0)` + // Minimum execution time: 273_742_000 picoseconds. + Weight::from_parts(169_430_806, 926) + // Standard Error: 11_821 + .saturating_add(Weight::from_parts(6_927_074, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3130,10 +3126,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_clear_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1215 + n * (1 ±0)` - // Estimated: `1215 + n * (1 ±0)` - // Minimum execution time: 276_566_000 picoseconds. - Weight::from_parts(304_992_376, 1215) + // Measured: `1248 + n * (1 ±0)` + // Estimated: `1248 + n * (1 ±0)` + // Minimum execution time: 275_167_000 picoseconds. + Weight::from_parts(301_883_655, 1248) + // Standard Error: 35 + .saturating_add(Weight::from_parts(4, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3143,12 +3141,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_get_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `887 + r * (296 ±0)` - // Estimated: `889 + r * (297 ±0)` - // Minimum execution time: 266_285_000 picoseconds. - Weight::from_parts(200_488_939, 889) - // Standard Error: 11_193 - .saturating_add(Weight::from_parts(5_467_725, 0).saturating_mul(r.into())) + // Measured: `920 + r * (296 ±0)` + // Estimated: `922 + r * (297 ±0)` + // Minimum execution time: 274_628_000 picoseconds. + Weight::from_parts(195_255_092, 922) + // Standard Error: 9_109 + .saturating_add(Weight::from_parts(5_707_060, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3159,12 +3157,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_get_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1231 + n * (1 ±0)` - // Estimated: `1231 + n * (1 ±0)` - // Minimum execution time: 278_625_000 picoseconds. - Weight::from_parts(304_319_493, 1231) - // Standard Error: 39 - .saturating_add(Weight::from_parts(415, 0).saturating_mul(n.into())) + // Measured: `1264 + n * (1 ±0)` + // Estimated: `1264 + n * (1 ±0)` + // Minimum execution time: 274_202_000 picoseconds. + Weight::from_parts(296_440_752, 1264) + // Standard Error: 38 + .saturating_add(Weight::from_parts(1_010, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3174,12 +3172,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_contains_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `898 + r * (288 ±0)` - // Estimated: `895 + r * (289 ±0)` - // Minimum execution time: 271_851_000 picoseconds. - Weight::from_parts(202_164_395, 895) - // Standard Error: 11_115 - .saturating_add(Weight::from_parts(5_273_320, 0).saturating_mul(r.into())) + // Measured: `931 + r * (288 ±0)` + // Estimated: `928 + r * (289 ±0)` + // Minimum execution time: 274_123_000 picoseconds. + Weight::from_parts(193_280_535, 928) + // Standard Error: 9_264 + .saturating_add(Weight::from_parts(5_548_039, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3190,12 +3188,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_contains_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1218 + n * (1 ±0)` - // Estimated: `1218 + n * (1 ±0)` - // Minimum execution time: 274_200_000 picoseconds. - Weight::from_parts(299_524_586, 1218) - // Standard Error: 33 - .saturating_add(Weight::from_parts(272, 0).saturating_mul(n.into())) + // Measured: `1251 + n * (1 ±0)` + // Estimated: `1251 + n * (1 ±0)` + // Minimum execution time: 276_425_000 picoseconds. + Weight::from_parts(300_521_806, 1251) + // Standard Error: 36 + .saturating_add(Weight::from_parts(83, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3205,12 +3203,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_take_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `880 + r * (296 ±0)` - // Estimated: `885 + r * (297 ±0)` - // Minimum execution time: 258_535_000 picoseconds. - Weight::from_parts(190_468_808, 885) - // Standard Error: 11_940 - .saturating_add(Weight::from_parts(6_737_079, 0).saturating_mul(r.into())) + // Measured: `913 + r * (296 ±0)` + // Estimated: `918 + r * (297 ±0)` + // Minimum execution time: 264_860_000 picoseconds. + Weight::from_parts(191_561_777, 918) + // Standard Error: 10_678 + .saturating_add(Weight::from_parts(6_895_457, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3222,12 +3220,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_take_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1232 + n * (1 ±0)` - // Estimated: `1232 + n * (1 ±0)` - // Minimum execution time: 280_536_000 picoseconds. - Weight::from_parts(304_479_477, 1232) + // Measured: `1265 + n * (1 ±0)` + // Estimated: `1265 + n * (1 ±0)` + // Minimum execution time: 282_501_000 picoseconds. + Weight::from_parts(303_351_919, 1265) // Standard Error: 37 - .saturating_add(Weight::from_parts(534, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(643, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3249,12 +3247,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_transfer(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1382 + r * (45 ±0)` - // Estimated: `7274 + r * (2520 ±0)` - // Minimum execution time: 260_373_000 picoseconds. - Weight::from_parts(278_290_000, 7274) - // Standard Error: 25_683 - .saturating_add(Weight::from_parts(39_264_864, 0).saturating_mul(r.into())) + // Measured: `1415 + r * (45 ±0)` + // Estimated: `7307 + r * (2520 ±0)` + // Minimum execution time: 273_198_000 picoseconds. + Weight::from_parts(179_673_238, 7307) + // Standard Error: 34_990 + .saturating_add(Weight::from_parts(38_468_091, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -3278,12 +3276,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_call(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1227 + r * (245 ±0)` - // Estimated: `9407 + r * (2721 ±0)` - // Minimum execution time: 277_621_000 picoseconds. - Weight::from_parts(281_775_000, 9407) - // Standard Error: 110_802 - .saturating_add(Weight::from_parts(245_363_533, 0).saturating_mul(r.into())) + // Measured: `1260 + r * (245 ±0)` + // Estimated: `9440 + r * (2721 ±0)` + // Minimum execution time: 283_869_000 picoseconds. + Weight::from_parts(288_374_000, 9440) + // Standard Error: 137_512 + .saturating_add(Weight::from_parts(248_206_665, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -3308,11 +3306,11 @@ impl WeightInfo for () { fn seal_delegate_call(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` - // Estimated: `6779 + r * (2637 ±3)` - // Minimum execution time: 267_314_000 picoseconds. - Weight::from_parts(279_888_000, 6779) - // Standard Error: 144_378 - .saturating_add(Weight::from_parts(244_606_414, 0).saturating_mul(r.into())) + // Estimated: `6812 + r * (2637 ±3)` + // Minimum execution time: 257_577_000 picoseconds. + Weight::from_parts(277_310_000, 6812) + // Standard Error: 150_204 + .saturating_add(Weight::from_parts(249_943_483, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3337,14 +3335,14 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 1048576]`. fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1274 + t * (277 ±0)` - // Estimated: `12164 + t * (5227 ±0)` - // Minimum execution time: 477_589_000 picoseconds. - Weight::from_parts(70_712_793, 12164) - // Standard Error: 11_713_135 - .saturating_add(Weight::from_parts(375_371_698, 0).saturating_mul(t.into())) + // Measured: `1307 + t * (277 ±0)` + // Estimated: `12197 + t * (5227 ±0)` + // Minimum execution time: 471_081_000 picoseconds. + Weight::from_parts(79_081_122, 12197) + // Standard Error: 11_777_790 + .saturating_add(Weight::from_parts(357_425_411, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(991, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_111, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) @@ -3365,19 +3363,19 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Holds` (r:800 w:800) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1245 + r * (255 ±0)` - // Estimated: `9587 + r * (2731 ±0)` - // Minimum execution time: 662_502_000 picoseconds. - Weight::from_parts(671_726_000, 9587) - // Standard Error: 351_643 - .saturating_add(Weight::from_parts(390_457_971, 0).saturating_mul(r.into())) + // Measured: `1278 + r * (255 ±0)` + // Estimated: `9620 + r * (2731 ±0)` + // Minimum execution time: 672_742_000 picoseconds. + Weight::from_parts(680_025_000, 9620) + // Standard Error: 313_642 + .saturating_add(Weight::from_parts(388_311_259, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -3398,25 +3396,23 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1270 + t * (104 ±0)` - // Estimated: `12178 + t * (2549 ±1)` - // Minimum execution time: 2_675_525_000 picoseconds. - Weight::from_parts(851_421_242, 12178) - // Standard Error: 7_094_722 - .saturating_add(Weight::from_parts(112_457_697, 0).saturating_mul(t.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(1_867, 0).saturating_mul(i.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(1_931, 0).saturating_mul(s.into())) + // Measured: `1303 + t * (104 ±0)` + // Estimated: `12211 + t * (2549 ±1)` + // Minimum execution time: 2_733_870_000 picoseconds. + Weight::from_parts(1_001_793_458, 12211) + // Standard Error: 12 + .saturating_add(Weight::from_parts(1_963, 0).saturating_mul(i.into())) + // Standard Error: 12 + .saturating_add(Weight::from_parts(2_060, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(16_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(11_u64)) @@ -3440,12 +3436,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_sha2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `829 + r * (8 ±0)` - // Estimated: `6768 + r * (8 ±0)` - // Minimum execution time: 270_818_000 picoseconds. - Weight::from_parts(286_520_166, 6768) - // Standard Error: 575 - .saturating_add(Weight::from_parts(402_286, 0).saturating_mul(r.into())) + // Measured: `862 + r * (8 ±0)` + // Estimated: `6801 + r * (8 ±0)` + // Minimum execution time: 272_658_000 picoseconds. + Weight::from_parts(282_717_645, 6801) + // Standard Error: 517 + .saturating_add(Weight::from_parts(400_604, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3467,12 +3463,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `837` - // Estimated: `6775` - // Minimum execution time: 257_134_000 picoseconds. - Weight::from_parts(268_214_648, 6775) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_098, 0).saturating_mul(n.into())) + // Measured: `870` + // Estimated: `6808` + // Minimum execution time: 260_969_000 picoseconds. + Weight::from_parts(265_206_847, 6808) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_134, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3493,12 +3489,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_keccak_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + r * (8 ±0)` - // Estimated: `6773 + r * (8 ±0)` - // Minimum execution time: 259_222_000 picoseconds. - Weight::from_parts(283_273_283, 6773) - // Standard Error: 967 - .saturating_add(Weight::from_parts(817_596, 0).saturating_mul(r.into())) + // Measured: `864 + r * (8 ±0)` + // Estimated: `6806 + r * (8 ±0)` + // Minimum execution time: 262_351_000 picoseconds. + Weight::from_parts(286_974_296, 6806) + // Standard Error: 514 + .saturating_add(Weight::from_parts(802_363, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3520,12 +3516,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839` - // Estimated: `6781` - // Minimum execution time: 260_040_000 picoseconds. - Weight::from_parts(283_869_860, 6781) + // Measured: `872` + // Estimated: `6814` + // Minimum execution time: 276_907_000 picoseconds. + Weight::from_parts(277_928_418, 6814) // Standard Error: 1 - .saturating_add(Weight::from_parts(3_349, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_410, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3546,12 +3542,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + r * (8 ±0)` - // Estimated: `6775 + r * (8 ±0)` - // Minimum execution time: 260_698_000 picoseconds. - Weight::from_parts(282_900_345, 6775) - // Standard Error: 805 - .saturating_add(Weight::from_parts(469_457, 0).saturating_mul(r.into())) + // Measured: `864 + r * (8 ±0)` + // Estimated: `6808 + r * (8 ±0)` + // Minimum execution time: 263_660_000 picoseconds. + Weight::from_parts(285_665_916, 6808) + // Standard Error: 527 + .saturating_add(Weight::from_parts(480_457, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3573,12 +3569,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839` - // Estimated: `6780` - // Minimum execution time: 256_967_000 picoseconds. - Weight::from_parts(273_024_512, 6780) + // Measured: `872` + // Estimated: `6813` + // Minimum execution time: 262_071_000 picoseconds. + Weight::from_parts(270_115_341, 6813) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_254, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3599,12 +3595,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_128(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + r * (8 ±0)` - // Estimated: `6772 + r * (8 ±0)` - // Minimum execution time: 272_039_000 picoseconds. - Weight::from_parts(289_853_116, 6772) + // Measured: `864 + r * (8 ±0)` + // Estimated: `6805 + r * (8 ±0)` + // Minimum execution time: 265_568_000 picoseconds. + Weight::from_parts(285_791_811, 6805) // Standard Error: 559 - .saturating_add(Weight::from_parts(459_383, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(505_330, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3626,12 +3622,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `839` - // Estimated: `6778` - // Minimum execution time: 253_913_000 picoseconds. - Weight::from_parts(274_682_010, 6778) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(n.into())) + // Measured: `872` + // Estimated: `6811` + // Minimum execution time: 271_336_000 picoseconds. + Weight::from_parts(272_829_313, 6811) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_252, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3652,12 +3648,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 125697]`. fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `964 + n * (1 ±0)` - // Estimated: `6901 + n * (1 ±0)` - // Minimum execution time: 343_955_000 picoseconds. - Weight::from_parts(350_777_388, 6901) + // Measured: `997 + n * (1 ±0)` + // Estimated: `6934 + n * (1 ±0)` + // Minimum execution time: 351_146_000 picoseconds. + Weight::from_parts(355_368_323, 6934) // Standard Error: 14 - .saturating_add(Weight::from_parts(5_915, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(6_155, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3679,12 +3675,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_sr25519_verify(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `774 + r * (112 ±0)` - // Estimated: `6715 + r * (112 ±0)` - // Minimum execution time: 268_698_000 picoseconds. - Weight::from_parts(336_398_814, 6715) - // Standard Error: 16_627 - .saturating_add(Weight::from_parts(56_155_384, 0).saturating_mul(r.into())) + // Measured: `807 + r * (112 ±0)` + // Estimated: `6748 + r * (112 ±0)` + // Minimum execution time: 277_250_000 picoseconds. + Weight::from_parts(346_490_114, 6748) + // Standard Error: 14_654 + .saturating_add(Weight::from_parts(56_127_492, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) @@ -3706,12 +3702,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_recover(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `874 + r * (76 ±0)` - // Estimated: `6768 + r * (77 ±0)` - // Minimum execution time: 258_906_000 picoseconds. - Weight::from_parts(340_672_829, 6768) - // Standard Error: 18_295 - .saturating_add(Weight::from_parts(46_106_884, 0).saturating_mul(r.into())) + // Measured: `907 + r * (76 ±0)` + // Estimated: `6801 + r * (77 ±0)` + // Minimum execution time: 272_697_000 picoseconds. + Weight::from_parts(345_385_667, 6801) + // Standard Error: 14_226 + .saturating_add(Weight::from_parts(46_037_637, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) @@ -3733,12 +3729,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `844 + r * (42 ±0)` - // Estimated: `6783 + r * (42 ±0)` - // Minimum execution time: 275_105_000 picoseconds. - Weight::from_parts(313_700_348, 6783) - // Standard Error: 11_960 - .saturating_add(Weight::from_parts(12_050_300, 0).saturating_mul(r.into())) + // Measured: `877 + r * (42 ±0)` + // Estimated: `6816 + r * (42 ±0)` + // Minimum execution time: 271_800_000 picoseconds. + Weight::from_parts(314_891_136, 6816) + // Standard Error: 9_762 + .saturating_add(Weight::from_parts(11_949_979, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) @@ -3761,11 +3757,11 @@ impl WeightInfo for () { fn seal_set_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` - // Estimated: `6774 + r * (3090 ±7)` - // Minimum execution time: 259_178_000 picoseconds. - Weight::from_parts(275_643_000, 6774) - // Standard Error: 54_044 - .saturating_add(Weight::from_parts(26_026_930, 0).saturating_mul(r.into())) + // Estimated: `6807 + r * (3090 ±10)` + // Minimum execution time: 274_238_000 picoseconds. + Weight::from_parts(278_034_000, 6807) + // Standard Error: 77_011 + .saturating_add(Weight::from_parts(27_627_005, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3789,12 +3785,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 32]`. fn add_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `895 + r * (131 ±0)` - // Estimated: `6845 + r * (2606 ±0)` - // Minimum execution time: 263_386_000 picoseconds. - Weight::from_parts(295_443_439, 6845) - // Standard Error: 24_422 - .saturating_add(Weight::from_parts(6_429_537, 0).saturating_mul(r.into())) + // Measured: `928 + r * (131 ±0)` + // Estimated: `6878 + r * (2606 ±0)` + // Minimum execution time: 271_519_000 picoseconds. + Weight::from_parts(292_726_476, 6878) + // Standard Error: 23_870 + .saturating_add(Weight::from_parts(6_695_172, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3818,12 +3814,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 32]`. fn remove_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `936 + r * (183 ±0)` + // Measured: `969 + r * (183 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 261_371_000 picoseconds. - Weight::from_parts(297_493_194, 129453) - // Standard Error: 23_734 - .saturating_add(Weight::from_parts(5_673_169, 0).saturating_mul(r.into())) + // Minimum execution time: 274_675_000 picoseconds. + Weight::from_parts(293_727_489, 129453) + // Standard Error: 23_160 + .saturating_add(Weight::from_parts(5_895_043, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3847,12 +3843,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `825 + r * (3 ±0)` - // Estimated: `6771 + r * (3 ±0)` - // Minimum execution time: 275_558_000 picoseconds. - Weight::from_parts(287_220_765, 6771) - // Standard Error: 437 - .saturating_add(Weight::from_parts(184_125, 0).saturating_mul(r.into())) + // Measured: `858 + r * (3 ±0)` + // Estimated: `6804 + r * (3 ±0)` + // Minimum execution time: 253_330_000 picoseconds. + Weight::from_parts(281_079_564, 6804) + // Standard Error: 378 + .saturating_add(Weight::from_parts(180_655, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -3874,12 +3870,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_account_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2076 + r * (39 ±0)` - // Estimated: `7866 + r * (40 ±0)` - // Minimum execution time: 265_752_000 picoseconds. - Weight::from_parts(331_187_665, 7866) - // Standard Error: 1_950 - .saturating_add(Weight::from_parts(312_262, 0).saturating_mul(r.into())) + // Measured: `2109 + r * (39 ±0)` + // Estimated: `7899 + r * (40 ±0)` + // Minimum execution time: 276_552_000 picoseconds. + Weight::from_parts(368_521_088, 7899) + // Standard Error: 2_310 + .saturating_add(Weight::from_parts(318_129, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) @@ -3903,12 +3899,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_instantiation_nonce(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `828 + r * (3 ±0)` - // Estimated: `6768 + r * (3 ±0)` - // Minimum execution time: 257_114_000 picoseconds. - Weight::from_parts(286_686_654, 6768) - // Standard Error: 426 - .saturating_add(Weight::from_parts(162_295, 0).saturating_mul(r.into())) + // Measured: `861 + r * (3 ±0)` + // Estimated: `6801 + r * (3 ±0)` + // Minimum execution time: 258_953_000 picoseconds. + Weight::from_parts(288_222_836, 6801) + // Standard Error: 367 + .saturating_add(Weight::from_parts(152_842, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -3918,9 +3914,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_388_000 picoseconds. - Weight::from_parts(1_680_408, 0) - // Standard Error: 21 - .saturating_add(Weight::from_parts(10_564, 0).saturating_mul(r.into())) + // Minimum execution time: 1_476_000 picoseconds. + Weight::from_parts(2_119_717, 0) + // Standard Error: 28 + .saturating_add(Weight::from_parts(9_805, 0).saturating_mul(r.into())) } } From a1a6d3e7c35068129f6fdcfd1064e48cd9f91693 Mon Sep 17 00:00:00 2001 From: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Date: Sat, 2 Sep 2023 21:25:43 +0200 Subject: [PATCH 009/103] substrate: chain-spec paths corrected in zombienet tests (#1362) * substrate: chain-spec paths corrected in zombienet tests * fix chain-spec path in cumulus test * disable beefy on validator --------- Co-authored-by: Javier Viola --- cumulus/zombienet/tests/0007-full_node_warp_sync.toml | 6 +++--- .../zombienet/0001-basic-warp-sync/test-warp-sync.toml | 2 +- .../test-validators-warp-sync.toml | 2 +- .../test-block-building-warp-sync.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cumulus/zombienet/tests/0007-full_node_warp_sync.toml b/cumulus/zombienet/tests/0007-full_node_warp_sync.toml index 42d1de7148d6..524ce6643ce1 100644 --- a/cumulus/zombienet/tests/0007-full_node_warp_sync.toml +++ b/cumulus/zombienet/tests/0007-full_node_warp_sync.toml @@ -3,7 +3,7 @@ default_image = "{{RELAY_IMAGE}}" default_command = "polkadot" default_args = [ "-lparachain=debug" ] chain = "rococo-local" -chain_spec_path = "cumulus/zombienet/tests/0007-warp-sync-relaychain-spec.json" +chain_spec_path = "0007-warp-sync-relaychain-spec.json" [[relaychain.nodes]] name = "alice" @@ -23,12 +23,12 @@ chain_spec_path = "cumulus/zombienet/tests/0007-warp-sync-relaychain-spec.json" [[relaychain.nodes]] name = "dave" validator = true - args = ["--sync warp", "--reserved-only", "--reserved-nodes {{'alice'|zombie('multiAddress')}} {{'bob'|zombie('multiAddress')}} {{'charlie'|zombie('multiAddress')}}"] + args = ["--no-beefy", "--sync warp", "--reserved-only", "--reserved-nodes {{'alice'|zombie('multiAddress')}} {{'bob'|zombie('multiAddress')}} {{'charlie'|zombie('multiAddress')}}"] [[parachains]] id = 2000 cumulus_based = true -chain_spec_path = "cumulus/zombienet/tests/0007-warp-sync-parachain-spec.json" +chain_spec_path = "0007-warp-sync-parachain-spec.json" add_to_genesis = false # Run 'dave' as parachain collator. diff --git a/substrate/zombienet/0001-basic-warp-sync/test-warp-sync.toml b/substrate/zombienet/0001-basic-warp-sync/test-warp-sync.toml index d14d77cfe621..773f5020bc3a 100644 --- a/substrate/zombienet/0001-basic-warp-sync/test-warp-sync.toml +++ b/substrate/zombienet/0001-basic-warp-sync/test-warp-sync.toml @@ -6,7 +6,7 @@ default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" default_command = "substrate" chain = "gen-db" -chain_spec_path = "substrate/zombienet/0001-basic-warp-sync/chain-spec.json" +chain_spec_path = "chain-spec.json" [[relaychain.nodes]] name = "alice" diff --git a/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.toml b/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.toml index 8336672ad497..12951575f4a4 100644 --- a/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.toml +++ b/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.toml @@ -6,7 +6,7 @@ default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" default_command = "substrate" chain = "gen-db" -chain_spec_path = "substrate/zombienet/0002-validators-warp-sync/chain-spec.json" +chain_spec_path = "chain-spec.json" [[relaychain.nodes]] name = "alice" diff --git a/substrate/zombienet/0003-block-building-warp-sync/test-block-building-warp-sync.toml b/substrate/zombienet/0003-block-building-warp-sync/test-block-building-warp-sync.toml index 6642ba8fea3c..7fe9b0f065da 100644 --- a/substrate/zombienet/0003-block-building-warp-sync/test-block-building-warp-sync.toml +++ b/substrate/zombienet/0003-block-building-warp-sync/test-block-building-warp-sync.toml @@ -6,7 +6,7 @@ default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" default_command = "substrate" chain = "gen-db" -chain_spec_path = "substrate/zombienet/0003-block-building-warp-sync/chain-spec.json" +chain_spec_path = "chain-spec.json" #we need at least 3 nodes for warp sync [[relaychain.nodes]] From bda10a8d8c7944b2c05e487f35c0133c26804e10 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Sun, 3 Sep 2023 15:11:26 +0200 Subject: [PATCH 010/103] Ensure cumulus/bridges is ignored by formatter and run it (#1369) --- .rustfmt.toml | 4 ++-- substrate/client/network/src/service.rs | 14 ++++++++------ .../rpc-spec-v2/src/chain_head/chain_head.rs | 6 ++++-- .../src/chain_head/chain_head_storage.rs | 4 +--- substrate/frame/broker/src/dispatchable_impls.rs | 4 ++-- substrate/frame/broker/src/tick_impls.rs | 4 ++-- substrate/frame/safe-mode/src/lib.rs | 2 +- 7 files changed, 20 insertions(+), 18 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index 10568e496801..0dc11bdb8a3a 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -19,9 +19,9 @@ trailing_comma = "Vertical" trailing_semicolon = false use_field_init_shorthand = true ignore = [ - "bridges", + "cumulus/bridges", ] edition = "2021" # Format comments comment_width = 100 -wrap_comments = true \ No newline at end of file +wrap_comments = true diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index aca0072a31de..c1df48ad7858 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -943,9 +943,10 @@ where peers: HashSet, ) -> Result<(), String> { let Some(set_id) = self.notification_protocol_ids.get(&protocol) else { - return Err( - format!("Cannot add peers to reserved set of unknown protocol: {}", protocol) - ) + return Err(format!( + "Cannot add peers to reserved set of unknown protocol: {}", + protocol + )) }; let peers = self.split_multiaddr_and_peer_id(peers)?; @@ -974,9 +975,10 @@ where peers: Vec, ) -> Result<(), String> { let Some(set_id) = self.notification_protocol_ids.get(&protocol) else { - return Err( - format!("Cannot remove peers from reserved set of unknown protocol: {}", protocol) - ) + return Err(format!( + "Cannot remove peers from reserved set of unknown protocol: {}", + protocol + )) }; for peer_id in peers.into_iter() { diff --git a/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs b/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs index bae7c84df0ed..14364c331e6c 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs @@ -462,7 +462,8 @@ where follow_subscription: String, operation_id: String, ) -> RpcResult<()> { - let Some(operation) = self.subscriptions.get_operation(&follow_subscription, &operation_id) else { + let Some(operation) = self.subscriptions.get_operation(&follow_subscription, &operation_id) + else { return Ok(()) }; @@ -479,7 +480,8 @@ where follow_subscription: String, operation_id: String, ) -> RpcResult<()> { - let Some(operation) = self.subscriptions.get_operation(&follow_subscription, &operation_id) else { + let Some(operation) = self.subscriptions.get_operation(&follow_subscription, &operation_id) + else { return Ok(()) }; diff --git a/substrate/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs b/substrate/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs index 5e1f38f9a997..48a673f47e3b 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs @@ -166,9 +166,7 @@ where let mut ret = Vec::with_capacity(self.operation_max_storage_items); for _ in 0..self.operation_max_storage_items { - let Some(key) = keys_iter.next() else { - break - }; + let Some(key) = keys_iter.next() else { break }; let result = match ty { IterQueryType::Value => self.query_storage_value(hash, &key, child_key), diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs index 7c1d5a786b7c..8dc0c9de393e 100644 --- a/substrate/frame/broker/src/dispatchable_impls.rs +++ b/substrate/frame/broker/src/dispatchable_impls.rs @@ -334,10 +334,10 @@ impl Pallet { contribution.length.saturating_dec(); let Some(mut pool_record) = InstaPoolHistory::::get(r) else { - continue; + continue }; let Some(total_payout) = pool_record.maybe_payout else { - break; + break }; let p = total_payout .saturating_mul(contributed_parts.into()) diff --git a/substrate/frame/broker/src/tick_impls.rs b/substrate/frame/broker/src/tick_impls.rs index d65b8968f3cf..909af6caf734 100644 --- a/substrate/frame/broker/src/tick_impls.rs +++ b/substrate/frame/broker/src/tick_impls.rs @@ -96,7 +96,7 @@ impl Pallet { pub(crate) fn process_revenue() -> bool { let Some((until, amount)) = T::Coretime::check_notify_revenue_info() else { - return false; + return false }; let when: Timeslice = (until / T::TimeslicePeriod::get()).saturating_sub(One::one()).saturated_into(); @@ -290,7 +290,7 @@ impl Pallet { core: CoreIndex, ) { let Some(workplan) = Workplan::::take((timeslice, core)) else { - return; + return }; let workload = Workload::::get(core); let parts_used = workplan.iter().map(|i| i.mask).fold(CoreMask::void(), |a, i| a | i); diff --git a/substrate/frame/safe-mode/src/lib.rs b/substrate/frame/safe-mode/src/lib.rs index ff045b964afb..b8e8378fa9e7 100644 --- a/substrate/frame/safe-mode/src/lib.rs +++ b/substrate/frame/safe-mode/src/lib.rs @@ -398,7 +398,7 @@ pub mod pallet { /// [`EnteredUntil`]. fn on_initialize(current: BlockNumberFor) -> Weight { let Some(limit) = EnteredUntil::::get() else { - return T::WeightInfo::on_initialize_noop(); + return T::WeightInfo::on_initialize_noop() }; if current > limit { From 60895d0b0923a426bda85749a8b28709a3d75454 Mon Sep 17 00:00:00 2001 From: yjh Date: Mon, 4 Sep 2023 03:52:20 +0800 Subject: [PATCH 011/103] feat: add futures api to `TransactionPool` (#1348) * feat: add futures api to `TransactionPool` * fix clippy --- substrate/bin/node/bench/src/construct.rs | 4 ++++ substrate/client/transaction-pool/api/src/lib.rs | 3 +++ substrate/client/transaction-pool/src/graph/base_pool.rs | 3 +-- .../client/transaction-pool/src/graph/validated_pool.rs | 2 +- substrate/client/transaction-pool/src/lib.rs | 6 ++++++ 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/substrate/bin/node/bench/src/construct.rs b/substrate/bin/node/bench/src/construct.rs index 4f3ca07f86b9..f14f89fcd3ab 100644 --- a/substrate/bin/node/bench/src/construct.rs +++ b/substrate/bin/node/bench/src/construct.rs @@ -282,6 +282,10 @@ impl sc_transaction_pool_api::TransactionPool for Transactions { Default::default() } + fn futures(&self) -> Vec { + unimplemented!() + } + fn status(&self) -> PoolStatus { unimplemented!() } diff --git a/substrate/client/transaction-pool/api/src/lib.rs b/substrate/client/transaction-pool/api/src/lib.rs index 32fe30f4584f..a132cbc46e9b 100644 --- a/substrate/client/transaction-pool/api/src/lib.rs +++ b/substrate/client/transaction-pool/api/src/lib.rs @@ -247,6 +247,9 @@ pub trait TransactionPool: Send + Sync { fn remove_invalid(&self, hashes: &[TxHash]) -> Vec>; // *** logging + /// Get futures transaction list. + fn futures(&self) -> Vec; + /// Returns pool status. fn status(&self) -> PoolStatus; diff --git a/substrate/client/transaction-pool/src/graph/base_pool.rs b/substrate/client/transaction-pool/src/graph/base_pool.rs index a9d2d6c825f6..32885622da42 100644 --- a/substrate/client/transaction-pool/src/graph/base_pool.rs +++ b/substrate/client/transaction-pool/src/graph/base_pool.rs @@ -84,8 +84,7 @@ pub struct PruneStatus { } /// Immutable transaction -#[cfg_attr(test, derive(Clone))] -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Clone)] pub struct Transaction { /// Raw extrinsic representing that transaction. pub data: Extrinsic, diff --git a/substrate/client/transaction-pool/src/graph/validated_pool.rs b/substrate/client/transaction-pool/src/graph/validated_pool.rs index ed76d439ae71..3d7cfeb46b04 100644 --- a/substrate/client/transaction-pool/src/graph/validated_pool.rs +++ b/substrate/client/transaction-pool/src/graph/validated_pool.rs @@ -106,7 +106,7 @@ pub struct ValidatedPool { is_validator: IsValidator, options: Options, listener: RwLock, B>>, - pool: RwLock, ExtrinsicFor>>, + pub(crate) pool: RwLock, ExtrinsicFor>>, import_notification_sinks: Mutex>>>, rotator: PoolRotator>, } diff --git a/substrate/client/transaction-pool/src/lib.rs b/substrate/client/transaction-pool/src/lib.rs index 80e5925194c6..ffaab89d9823 100644 --- a/substrate/client/transaction-pool/src/lib.rs +++ b/substrate/client/transaction-pool/src/lib.rs @@ -358,6 +358,12 @@ where fn ready(&self) -> ReadyIteratorFor { Box::new(self.pool.validated_pool().ready()) } + + fn futures(&self) -> Vec { + let pool = self.pool.validated_pool().pool.read(); + + pool.futures().cloned().collect::>() + } } impl FullPool From 86f0cc1e57288c1f5a1e0e90efb75879f8b22f7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 08:48:15 +0300 Subject: [PATCH 012/103] Bump proc-macro-warning from 0.4.1 to 0.4.2 (#1376) Bumps [proc-macro-warning](https://github.com/ggwpez/proc-macro-warning) from 0.4.1 to 0.4.2. - [Release notes](https://github.com/ggwpez/proc-macro-warning/releases) - [Commits](https://github.com/ggwpez/proc-macro-warning/compare/v0.4.1...v0.4.2) --- updated-dependencies: - dependency-name: proc-macro-warning dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 6 +++--- substrate/frame/support/procedural/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3bbc2faf296..62652542fe04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13423,9 +13423,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-warning" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70550716265d1ec349c41f70dd4f964b4fd88394efe4405f0c1da679c4799a07" +checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", @@ -19379,7 +19379,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index a25216ea9aa1..ad28eed959eb 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -23,7 +23,7 @@ proc-macro2 = "1.0.56" quote = "1.0.28" syn = { version = "2.0.16", features = ["full"] } frame-support-procedural-tools = { path = "tools" } -proc-macro-warning = { version = "0.4.1", default-features = false } +proc-macro-warning = { version = "0.4.2", default-features = false } macro_magic = { version = "0.4.2", features = ["proc_support"] } expander = "2.0.0" From 0423b0d9d653a70ae890cfc4c6971a241f1c733b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 08:48:36 +0300 Subject: [PATCH 013/103] Bump the known_good_semver group with 1 update (#1375) Bumps the known_good_semver group with 1 update: [syn](https://github.com/dtolnay/syn). - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.29...2.0.31) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: known_good_semver ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 100 +++++++++--------- .../parachain-system/proc-macro/Cargo.toml | 2 +- polkadot/node/gum/proc-macro/Cargo.toml | 2 +- polkadot/xcm/procedural/Cargo.toml | 2 +- substrate/client/chain-spec/derive/Cargo.toml | 2 +- .../client/tracing/proc-macro/Cargo.toml | 2 +- .../frame/contracts/proc-macro/Cargo.toml | 2 +- .../solution-type/Cargo.toml | 2 +- .../frame/staking/reward-curve/Cargo.toml | 2 +- substrate/frame/support/procedural/Cargo.toml | 2 +- .../frame/support/procedural/tools/Cargo.toml | 2 +- .../procedural/tools/derive/Cargo.toml | 2 +- .../primitives/api/proc-macro/Cargo.toml | 2 +- .../core/hashing/proc-macro/Cargo.toml | 2 +- substrate/primitives/debug-derive/Cargo.toml | 2 +- .../runtime-interface/proc-macro/Cargo.toml | 2 +- .../primitives/version/proc-macro/Cargo.toml | 2 +- 17 files changed, 66 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62652542fe04..8af7f4f87217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1138,7 +1138,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1160,7 +1160,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1177,7 +1177,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1352,7 +1352,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2516,7 +2516,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -3575,7 +3575,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4067,7 +4067,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4107,7 +4107,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4124,7 +4124,7 @@ checksum = "50c49547d73ba8dcfd4ad7325d64c6d5391ff4224d498fc39a6f3f49825a530d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4422,7 +4422,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4484,7 +4484,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.29", + "syn 2.0.31", "termcolor", "toml 0.7.6", "walkdir", @@ -4728,7 +4728,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4739,7 +4739,7 @@ checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -4902,7 +4902,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -5258,7 +5258,7 @@ dependencies = [ "quote", "scale-info", "sp-arithmetic", - "syn 2.0.29", + "syn 2.0.31", "trybuild", ] @@ -5410,7 +5410,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -5421,7 +5421,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -5430,7 +5430,7 @@ version = "3.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -5653,7 +5653,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -7660,7 +7660,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -7674,7 +7674,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -7685,7 +7685,7 @@ checksum = "c12469fc165526520dff2807c2975310ab47cf7190a45b99b49a7dc8befab17b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -7696,7 +7696,7 @@ checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -9403,7 +9403,7 @@ version = "4.0.0-dev" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -10474,7 +10474,7 @@ dependencies = [ "proc-macro2", "quote", "sp-runtime", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -11333,7 +11333,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -11374,7 +11374,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -13347,7 +13347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -13429,7 +13429,7 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -13475,7 +13475,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -13866,7 +13866,7 @@ checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -14628,7 +14628,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -15841,7 +15841,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -16195,7 +16195,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -16261,7 +16261,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -16701,7 +16701,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -17102,7 +17102,7 @@ version = "9.0.0" dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -17146,7 +17146,7 @@ version = "8.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -17377,7 +17377,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -17617,7 +17617,7 @@ dependencies = [ "proc-macro2", "quote", "sp-version", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -18441,9 +18441,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -18690,7 +18690,7 @@ checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -18881,7 +18881,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -19062,7 +19062,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -19105,7 +19105,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -19678,7 +19678,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", "wasm-bindgen-shared", ] @@ -19712,7 +19712,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -20848,7 +20848,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -20967,7 +20967,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] diff --git a/cumulus/pallets/parachain-system/proc-macro/Cargo.toml b/cumulus/pallets/parachain-system/proc-macro/Cargo.toml index 58a4a97e0492..e5e7da81d2ae 100644 --- a/cumulus/pallets/parachain-system/proc-macro/Cargo.toml +++ b/cumulus/pallets/parachain-system/proc-macro/Cargo.toml @@ -9,7 +9,7 @@ description = "Proc macros provided by the parachain-system pallet" proc-macro = true [dependencies] -syn = "2.0.29" +syn = "2.0.31" proc-macro2 = "1.0.64" quote = "1.0.33" proc-macro-crate = "1.3.1" diff --git a/polkadot/node/gum/proc-macro/Cargo.toml b/polkadot/node/gum/proc-macro/Cargo.toml index fc057c769752..ec6b817476a9 100644 --- a/polkadot/node/gum/proc-macro/Cargo.toml +++ b/polkadot/node/gum/proc-macro/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "2.0.15", features = ["full", "extra-traits"] } +syn = { version = "2.0.31", features = ["full", "extra-traits"] } quote = "1.0.28" proc-macro2 = "1.0.56" proc-macro-crate = "1.1.3" diff --git a/polkadot/xcm/procedural/Cargo.toml b/polkadot/xcm/procedural/Cargo.toml index a5c50a48007f..6545fb68764d 100644 --- a/polkadot/xcm/procedural/Cargo.toml +++ b/polkadot/xcm/procedural/Cargo.toml @@ -11,5 +11,5 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.56" quote = "1.0.28" -syn = "2.0.15" +syn = "2.0.31" Inflector = "0.11.4" diff --git a/substrate/client/chain-spec/derive/Cargo.toml b/substrate/client/chain-spec/derive/Cargo.toml index 8b8210fe04fe..b5ecc6107b94 100644 --- a/substrate/client/chain-spec/derive/Cargo.toml +++ b/substrate/client/chain-spec/derive/Cargo.toml @@ -18,4 +18,4 @@ proc-macro = true proc-macro-crate = "1.1.3" proc-macro2 = "1.0.56" quote = "1.0.28" -syn = "2.0.16" +syn = "2.0.31" diff --git a/substrate/client/tracing/proc-macro/Cargo.toml b/substrate/client/tracing/proc-macro/Cargo.toml index 23dc9557a4bc..8c444ffb606b 100644 --- a/substrate/client/tracing/proc-macro/Cargo.toml +++ b/substrate/client/tracing/proc-macro/Cargo.toml @@ -18,4 +18,4 @@ proc-macro = true proc-macro-crate = "1.1.3" proc-macro2 = "1.0.56" quote = { version = "1.0.28", features = ["proc-macro"] } -syn = { version = "2.0.16", features = ["proc-macro", "full", "extra-traits", "parsing"] } +syn = { version = "2.0.31", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/substrate/frame/contracts/proc-macro/Cargo.toml b/substrate/frame/contracts/proc-macro/Cargo.toml index afc6ce281bb4..ecc5bc627b70 100644 --- a/substrate/frame/contracts/proc-macro/Cargo.toml +++ b/substrate/frame/contracts/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.56" quote = "1.0.28" -syn = { version = "2.0.16", features = ["full"] } +syn = { version = "2.0.31", features = ["full"] } [dev-dependencies] diff --git a/substrate/frame/election-provider-support/solution-type/Cargo.toml b/substrate/frame/election-provider-support/solution-type/Cargo.toml index bc0127e91bad..7693da0372d9 100644 --- a/substrate/frame/election-provider-support/solution-type/Cargo.toml +++ b/substrate/frame/election-provider-support/solution-type/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "2.0.16", features = ["full", "visit"] } +syn = { version = "2.0.31", features = ["full", "visit"] } quote = "1.0.28" proc-macro2 = "1.0.56" proc-macro-crate = "1.1.3" diff --git a/substrate/frame/staking/reward-curve/Cargo.toml b/substrate/frame/staking/reward-curve/Cargo.toml index dc8458481619..e1b97d278da1 100644 --- a/substrate/frame/staking/reward-curve/Cargo.toml +++ b/substrate/frame/staking/reward-curve/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true proc-macro-crate = "1.1.3" proc-macro2 = "1.0.56" quote = "1.0.28" -syn = { version = "2.0.16", features = ["full", "visit"] } +syn = { version = "2.0.31", features = ["full", "visit"] } [dev-dependencies] sp-runtime = { path = "../../../primitives/runtime" } diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index ad28eed959eb..9ca86b9fccb1 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -21,7 +21,7 @@ cfg-expr = "0.15.4" itertools = "0.10.3" proc-macro2 = "1.0.56" quote = "1.0.28" -syn = { version = "2.0.16", features = ["full"] } +syn = { version = "2.0.31", features = ["full"] } frame-support-procedural-tools = { path = "tools" } proc-macro-warning = { version = "0.4.2", default-features = false } macro_magic = { version = "0.4.2", features = ["proc_support"] } diff --git a/substrate/frame/support/procedural/tools/Cargo.toml b/substrate/frame/support/procedural/tools/Cargo.toml index 3a56f29eb190..46c264256513 100644 --- a/substrate/frame/support/procedural/tools/Cargo.toml +++ b/substrate/frame/support/procedural/tools/Cargo.toml @@ -15,5 +15,5 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro-crate = "1.1.3" proc-macro2 = "1.0.56" quote = "1.0.28" -syn = { version = "2.0.16", features = ["full", "visit", "extra-traits"] } +syn = { version = "2.0.31", features = ["full", "visit", "extra-traits"] } frame-support-procedural-tools-derive = { path = "derive" } diff --git a/substrate/frame/support/procedural/tools/derive/Cargo.toml b/substrate/frame/support/procedural/tools/derive/Cargo.toml index 68e85a2060d9..da01e6f4f6af 100644 --- a/substrate/frame/support/procedural/tools/derive/Cargo.toml +++ b/substrate/frame/support/procedural/tools/derive/Cargo.toml @@ -17,4 +17,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.56" quote = { version = "1.0.28", features = ["proc-macro"] } -syn = { version = "2.0.16", features = ["proc-macro", "full", "extra-traits", "parsing"] } +syn = { version = "2.0.31", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/substrate/primitives/api/proc-macro/Cargo.toml b/substrate/primitives/api/proc-macro/Cargo.toml index c415813b978f..6819d139f450 100644 --- a/substrate/primitives/api/proc-macro/Cargo.toml +++ b/substrate/primitives/api/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.28" -syn = { version = "2.0.16", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "2.0.31", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.56" blake2 = { version = "0.10.4", default-features = false } proc-macro-crate = "1.1.3" diff --git a/substrate/primitives/core/hashing/proc-macro/Cargo.toml b/substrate/primitives/core/hashing/proc-macro/Cargo.toml index d3a74d4bb814..ef17473a6f39 100644 --- a/substrate/primitives/core/hashing/proc-macro/Cargo.toml +++ b/substrate/primitives/core/hashing/proc-macro/Cargo.toml @@ -17,5 +17,5 @@ proc-macro = true [dependencies] quote = "1.0.28" -syn = { version = "2.0.16", features = ["full", "parsing"] } +syn = { version = "2.0.31", features = ["full", "parsing"] } sp-core-hashing = { path = "..", default-features = false} diff --git a/substrate/primitives/debug-derive/Cargo.toml b/substrate/primitives/debug-derive/Cargo.toml index bd35939a8b9e..292c07e092f9 100644 --- a/substrate/primitives/debug-derive/Cargo.toml +++ b/substrate/primitives/debug-derive/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true [dependencies] quote = "1.0.28" -syn = "2.0.16" +syn = "2.0.31" proc-macro2 = "1.0.56" [features] diff --git a/substrate/primitives/runtime-interface/proc-macro/Cargo.toml b/substrate/primitives/runtime-interface/proc-macro/Cargo.toml index 3488e4f50bf3..e01343d6dc0a 100644 --- a/substrate/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/substrate/primitives/runtime-interface/proc-macro/Cargo.toml @@ -20,4 +20,4 @@ Inflector = "0.11.4" proc-macro-crate = "1.1.3" proc-macro2 = "1.0.56" quote = "1.0.28" -syn = { version = "2.0.16", features = ["full", "visit", "fold", "extra-traits"] } +syn = { version = "2.0.31", features = ["full", "visit", "fold", "extra-traits"] } diff --git a/substrate/primitives/version/proc-macro/Cargo.toml b/substrate/primitives/version/proc-macro/Cargo.toml index e7cec134ed55..25b5e7906f62 100644 --- a/substrate/primitives/version/proc-macro/Cargo.toml +++ b/substrate/primitives/version/proc-macro/Cargo.toml @@ -19,7 +19,7 @@ proc-macro = true codec = { package = "parity-scale-codec", version = "3.6.1", features = [ "derive" ] } proc-macro2 = "1.0.56" quote = "1.0.28" -syn = { version = "2.0.16", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "2.0.31", features = ["full", "fold", "extra-traits", "visit"] } [dev-dependencies] sp-version = { path = ".." } From 2b89df647811dcd7a56e52cc03bc46dc17c348fe Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 4 Sep 2023 09:19:41 +0200 Subject: [PATCH 014/103] Update `fmt` file and some authors (#1379) * Include bridges into fmt Signed-off-by: Oliver Tale-Yazdi * Fix some authors Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi --- .rustfmt.toml | 5 +---- polkadot/roadmap/implementers-guide/book.toml | 2 +- substrate/frame/asset-rate/Cargo.toml | 2 +- substrate/primitives/consensus/sassafras/Cargo.toml | 2 +- substrate/utils/frame/rpc/support/Cargo.toml | 5 +---- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index 0dc11bdb8a3a..c34215391239 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,4 +1,5 @@ # Basic +edition = "2021" hard_tabs = true max_width = 100 use_small_heuristics = "Max" @@ -18,10 +19,6 @@ match_block_trailing_comma = true trailing_comma = "Vertical" trailing_semicolon = false use_field_init_shorthand = true -ignore = [ - "cumulus/bridges", -] -edition = "2021" # Format comments comment_width = 100 wrap_comments = true diff --git a/polkadot/roadmap/implementers-guide/book.toml b/polkadot/roadmap/implementers-guide/book.toml index 0ced0e26f9a0..1e6680f6f4b7 100644 --- a/polkadot/roadmap/implementers-guide/book.toml +++ b/polkadot/roadmap/implementers-guide/book.toml @@ -1,5 +1,5 @@ [book] -authors = ["Rob Habermeier", "Peter Goodspeed-Niklaus"] +authors = ["Parity Technologies "] language = "en" multilingual = false src = "src" diff --git a/substrate/frame/asset-rate/Cargo.toml b/substrate/frame/asset-rate/Cargo.toml index 479631e7dd12..2338e8711eda 100644 --- a/substrate/frame/asset-rate/Cargo.toml +++ b/substrate/frame/asset-rate/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-asset-rate" version = "4.0.0-dev" description = "Whitelist non-native assets for treasury spending and provide conversion to native balance" -authors = ["William Freudenberger "] +authors.workspace = true homepage = "https://substrate.io" edition.workspace = true license = "Apache-2.0" diff --git a/substrate/primitives/consensus/sassafras/Cargo.toml b/substrate/primitives/consensus/sassafras/Cargo.toml index 56ae0087099e..e848f280f5d8 100644 --- a/substrate/primitives/consensus/sassafras/Cargo.toml +++ b/substrate/primitives/consensus/sassafras/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sp-consensus-sassafras" version = "0.3.4-dev" -authors = ["Parity Technologies "] +authors.workspace = true description = "Primitives for Sassafras consensus" edition = "2021" license = "Apache-2.0" diff --git a/substrate/utils/frame/rpc/support/Cargo.toml b/substrate/utils/frame/rpc/support/Cargo.toml index 5cc4f6cbc099..b0a00e1207a6 100644 --- a/substrate/utils/frame/rpc/support/Cargo.toml +++ b/substrate/utils/frame/rpc/support/Cargo.toml @@ -1,10 +1,7 @@ [package] name = "substrate-frame-rpc-support" version = "3.0.0" -authors = [ - "Parity Technologies ", - "Andrew Dirksen ", -] +authors.workspace = true edition.workspace = true license = "Apache-2.0" homepage = "https://substrate.io" From d3ba197d9105530531bc71848a6d7ec41edd2969 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Mon, 4 Sep 2023 11:02:32 +0200 Subject: [PATCH 015/103] Markdown linter (#1309) * Add markdown linting - add linter default rules - adapt rules to current code - fix the code for linting to pass - add CI check fix #1243 * Fix markdown for Substrate * Fix tooling install * Fix workflow * Add documentation * Remove trailing spaces * Update .github/.markdownlint.yaml Co-authored-by: Oliver Tale-Yazdi * Fix mangled markdown/lists * Fix captalization issues on known words --- .github/.markdownlint.yaml | 210 ++++ .github/workflows/check-markdown.yml | 33 + README.md | 50 +- cumulus/BRIDGES.md | 34 +- cumulus/README.md | 162 ++- cumulus/bridges/CODE_OF_CONDUCT.md | 4 +- cumulus/bridges/README.md | 118 ++- cumulus/bridges/SECURITY.md | 12 +- cumulus/bridges/docs/high-level-overview.md | 209 ++-- .../docs/polkadot-kusama-bridge-overview.md | 111 +- cumulus/bridges/modules/messages/README.md | 339 +++---- cumulus/bridges/modules/parachains/README.md | 2 +- cumulus/docs/container.md | 30 +- cumulus/docs/release.md | 55 +- cumulus/pallets/collator-selection/README.md | 2 +- cumulus/parachain-template/README.md | 2 +- .../e2e/collectives/README.md | 16 +- .../parachains/runtimes/bridge-hubs/README.md | 67 +- .../contracts/contracts-rococo/README.md | 4 +- cumulus/scripts/ci/changelog/README.md | 77 ++ cumulus/xcm/xcm-emulator/README.md | 4 +- .../0007-prepare-warp-sync-db-snapshot.md | 15 +- docs/CONTRIBUTING.md | 18 +- docs/DOCUMENTATION_GUIDELINE.md | 245 +++-- docs/PULL_REQUEST_TEMPLATE.md | 26 +- docs/STYLE_GUIDE.md | 40 +- docs/markdown_linting.md | 20 + polkadot/README.md | 8 +- polkadot/RELEASE.md | 93 +- polkadot/doc/docker.md | 50 +- polkadot/doc/release-checklist.md | 111 +- polkadot/doc/shell-completion.md | 6 +- polkadot/doc/testing.md | 108 +- polkadot/erasure-coding/benches/README.md | 8 +- polkadot/grafana/README.md | 52 +- polkadot/node/gum/README.md | 2 +- polkadot/node/malus/README.md | 4 +- polkadot/node/metrics/README.md | 2 +- polkadot/node/test/service/README.md | 2 +- polkadot/parachain/test-parachains/README.md | 3 +- .../test-parachains/adder/collator/README.md | 2 +- .../roadmap/implementers-guide/src/README.md | 10 +- .../roadmap/implementers-guide/src/SUMMARY.md | 20 +- .../implementers-guide/src/architecture.md | 58 +- .../implementers-guide/src/disputes-flow.md | 40 +- .../implementers-guide/src/glossary.md | 74 +- .../implementers-guide/src/messaging.md | 90 +- .../implementers-guide/src/node/README.md | 43 +- .../src/node/approval/README.md | 7 +- .../node/approval/approval-distribution.md | 200 ++-- .../src/node/approval/approval-voting.md | 294 ++++-- .../src/node/availability/README.md | 6 +- .../availability/availability-distribution.md | 96 +- .../availability/availability-recovery.md | 56 +- .../availability/bitfield-distribution.md | 34 +- .../src/node/availability/bitfield-signing.md | 24 +- .../src/node/backing/README.md | 13 +- .../src/node/backing/candidate-backing.md | 100 +- .../backing/statement-distribution-legacy.md | 152 ++- .../node/backing/statement-distribution.md | 460 ++++----- .../src/node/collators/README.md | 8 +- .../node/collators/collation-generation.md | 40 +- .../src/node/collators/collator-protocol.md | 118 ++- .../src/node/disputes/README.md | 12 +- .../src/node/disputes/dispute-coordinator.md | 960 ++++++++---------- .../src/node/disputes/dispute-distribution.md | 12 +- .../src/node/grandpa-voting-rule.md | 25 +- .../implementers-guide/src/node/overseer.md | 99 +- .../src/node/subsystems-and-jobs.md | 172 ++-- .../src/node/utility/availability-store.md | 72 +- .../src/node/utility/candidate-validation.md | 43 +- .../src/node/utility/chain-api.md | 6 +- .../src/node/utility/chain-selection.md | 53 +- .../src/node/utility/network-bridge.md | 98 +- .../src/node/utility/provisioner.md | 198 ++-- .../src/node/utility/pvf-prechecker.md | 55 +- .../src/node/utility/runtime-api.md | 10 +- .../src/protocol-approval.md | 336 ++++-- .../src/protocol-chain-selection.md | 45 +- .../src/protocol-disputes.md | 126 ++- .../src/protocol-overview.md | 127 ++- .../implementers-guide/src/pvf-prechecking.md | 69 +- .../src/runtime-api/README.md | 39 +- .../src/runtime-api/availability-cores.md | 18 +- .../candidate-pending-availability.md | 3 +- .../src/runtime-api/disputes-info.md | 5 +- .../runtime-api/persisted-validation-data.md | 6 +- .../src/runtime-api/pvf-prechecking.md | 14 +- .../src/runtime-api/session-index.md | 3 +- .../src/runtime-api/validator-groups.md | 3 +- .../src/runtime-api/validators.md | 3 +- .../implementers-guide/src/runtime/README.md | 89 +- .../src/runtime/configuration.md | 26 +- .../src/runtime/disputes.md | 103 +- .../implementers-guide/src/runtime/dmp.md | 13 +- .../implementers-guide/src/runtime/hrmp.md | 95 +- .../src/runtime/inclusion.md | 122 ++- .../src/runtime/initializer.md | 21 +- .../src/runtime/parainherent.md | 61 +- .../implementers-guide/src/runtime/paras.md | 97 +- .../src/runtime/scheduler.md | 147 ++- .../src/runtime/session_info.md | 14 +- .../implementers-guide/src/runtime/shared.md | 32 +- .../implementers-guide/src/types/approval.md | 19 +- .../src/types/availability.md | 24 +- .../implementers-guide/src/types/backing.md | 29 +- .../implementers-guide/src/types/candidate.md | 60 +- .../implementers-guide/src/types/disputes.md | 3 +- .../implementers-guide/src/types/network.md | 3 +- .../src/types/overseer-protocol.md | 51 +- .../src/whence-parachains.md | 39 +- polkadot/roadmap/parachains.md | 182 ++-- polkadot/runtime/rococo/README.md | 6 +- polkadot/utils/staking-miner/README.md | 37 +- polkadot/xcm/xcm-simulator/fuzzer/README.md | 6 +- polkadot/zombienet_tests/README.md | 44 +- substrate/README.md | 46 +- substrate/bin/node-template/README.md | 179 ++-- .../bin/node-template/docs/rust-setup.md | 103 +- .../node-template/pallets/template/README.md | 2 +- substrate/bin/utils/subkey/README.md | 67 +- substrate/bin/utils/subkey/SECURITY.md | 23 +- substrate/client/allocator/README.md | 2 +- substrate/client/api/README.md | 2 +- substrate/client/block-builder/README.md | 2 +- substrate/client/chain-spec/README.md | 2 +- substrate/client/cli/README.md | 2 +- substrate/client/consensus/aura/README.md | 4 +- substrate/client/consensus/babe/README.md | 2 +- substrate/client/consensus/babe/rpc/README.md | 2 +- substrate/client/consensus/common/README.md | 2 +- substrate/client/consensus/epochs/README.md | 2 +- substrate/client/consensus/grandpa/README.md | 4 +- .../client/consensus/grandpa/rpc/README.md | 2 +- .../client/consensus/manual-seal/README.md | 2 +- substrate/client/consensus/slots/README.md | 2 +- substrate/client/db/README.md | 2 +- substrate/client/executor/README.md | 2 +- substrate/client/executor/common/README.md | 2 +- substrate/client/executor/wasmtime/README.md | 2 +- substrate/client/informant/README.md | 2 +- substrate/client/keystore/README.md | 2 +- substrate/client/network-gossip/README.md | 2 +- substrate/client/network/README.md | 10 +- substrate/client/offchain/README.md | 2 +- substrate/client/proposer-metrics/README.md | 2 +- substrate/client/rpc-api/README.md | 4 +- substrate/client/rpc-servers/README.md | 2 +- substrate/client/rpc-spec-v2/README.md | 4 +- substrate/client/rpc/README.md | 2 +- substrate/client/service/README.md | 2 +- substrate/client/state-db/README.md | 6 +- substrate/client/telemetry/README.md | 6 +- substrate/client/tracing/README.md | 4 +- substrate/client/transaction-pool/README.md | 8 +- substrate/docker/README.md | 30 +- substrate/docs/CHANGELOG.md | 144 ++- substrate/docs/SECURITY.md | 40 +- substrate/docs/STYLE_GUIDE.md | 70 +- substrate/docs/Upgrade.md | 8 +- substrate/docs/Upgrading-2.0-to-3.0.md | 140 ++- substrate/docs/node-template-release.md | 96 +- substrate/frame/README.md | 7 +- substrate/frame/assets/README.md | 35 +- substrate/frame/atomic-swap/README.md | 6 +- substrate/frame/aura/README.md | 3 +- substrate/frame/authority-discovery/README.md | 4 +- substrate/frame/authorship/README.md | 2 +- substrate/frame/babe/README.md | 2 +- substrate/frame/balances/README.md | 62 +- substrate/frame/benchmarking/README.md | 181 ++-- substrate/frame/child-bounties/README.md | 2 +- substrate/frame/contracts/CHANGELOG.md | 2 +- substrate/frame/contracts/README.md | 130 +-- .../frame/contracts/benchmarks/README.md | 11 +- .../frame/contracts/primitives/README.md | 2 +- substrate/frame/core-fellowship/README.md | 2 +- substrate/frame/elections-phragmen/README.md | 110 +- substrate/frame/examples/basic/README.md | 2 +- substrate/frame/examples/split/README.md | 2 +- substrate/frame/executive/README.md | 18 +- substrate/frame/glutton/README.md | 7 +- substrate/frame/grandpa/README.md | 2 +- substrate/frame/identity/README.md | 28 +- substrate/frame/indices/README.md | 2 +- .../README.md | 20 +- substrate/frame/multisig/README.md | 6 +- .../frame/nft-fractionalization/README.md | 8 +- substrate/frame/nfts/README.md | 24 +- substrate/frame/nicks/README.md | 6 +- substrate/frame/nis/README.md | 2 +- .../nomination-pools/runtime-api/README.md | 2 +- substrate/frame/offences/README.md | 2 +- .../frame/offences/benchmarking/README.md | 2 +- substrate/frame/ranked-collective/README.md | 2 +- substrate/frame/recovery/README.md | 28 +- substrate/frame/remark/README.md | 2 +- substrate/frame/root-offences/README.md | 2 +- substrate/frame/root-testing/README.md | 2 +- substrate/frame/salary/README.md | 2 +- substrate/frame/scheduler/README.md | 8 +- substrate/frame/session/README.md | 64 +- .../frame/session/benchmarking/README.md | 2 +- substrate/frame/society/README.md | 38 +- substrate/frame/staking/README.md | 193 ++-- substrate/frame/sudo/README.md | 6 +- substrate/frame/support/README.md | 2 +- substrate/frame/support/test/tests/pallet.rs | 6 +- substrate/frame/system/README.md | 36 +- substrate/frame/system/benchmarking/README.md | 2 +- .../frame/system/benchmarking/res/README.md | 3 +- .../frame/system/rpc/runtime-api/README.md | 2 +- substrate/frame/timestamp/README.md | 8 +- substrate/frame/tips/README.md | 4 +- substrate/frame/transaction-storage/README.md | 24 +- substrate/frame/uniques/README.md | 16 +- substrate/frame/utility/README.md | 4 +- substrate/primitives/api/README.md | 2 +- .../primitives/application-crypto/README.md | 2 +- substrate/primitives/arithmetic/README.md | 2 +- .../primitives/authority-discovery/README.md | 2 +- substrate/primitives/block-builder/README.md | 2 +- substrate/primitives/blockchain/README.md | 2 +- substrate/primitives/consensus/aura/README.md | 2 +- substrate/primitives/consensus/babe/README.md | 2 +- .../primitives/consensus/common/README.md | 4 +- .../primitives/consensus/grandpa/README.md | 2 +- substrate/primitives/consensus/pow/README.md | 2 +- .../primitives/consensus/slots/README.md | 2 +- substrate/primitives/database/README.md | 2 +- substrate/primitives/externalities/README.md | 2 +- substrate/primitives/inherents/README.md | 2 +- substrate/primitives/io/README.md | 4 +- substrate/primitives/keyring/README.md | 2 +- substrate/primitives/npos-elections/README.md | 55 +- substrate/primitives/offchain/README.md | 2 +- substrate/primitives/panic-handler/README.md | 2 +- substrate/primitives/rpc/README.md | 2 +- .../primitives/runtime-interface/README.md | 50 +- substrate/primitives/runtime/README.md | 2 +- substrate/primitives/session/README.md | 2 +- substrate/primitives/staking/README.md | 2 +- substrate/primitives/state-machine/README.md | 2 +- .../primitives/statement-store/README.md | 35 +- substrate/primitives/std/README.md | 2 +- substrate/primitives/storage/README.md | 2 +- substrate/primitives/timestamp/README.md | 2 +- substrate/primitives/tracing/README.md | 2 +- .../primitives/transaction-pool/README.md | 2 +- substrate/primitives/trie/README.md | 2 +- substrate/primitives/version/README.md | 2 +- substrate/primitives/wasm-interface/README.md | 2 +- .../ci/docker/subkey.Dockerfile.README.md | 7 +- .../ci/docker/substrate.Dockerfile.README.md | 2 +- .../grafana-dashboards/README_dashboard.md | 2 +- substrate/utils/build-script-utils/README.md | 2 +- substrate/utils/fork-tree/README.md | 2 +- .../utils/frame/benchmarking-cli/README.md | 17 +- .../benchmarking-cli/src/block/README.md | 81 +- .../benchmarking-cli/src/machine/README.md | 48 +- .../benchmarking-cli/src/overhead/README.md | 62 +- .../benchmarking-cli/src/shared/README.md | 7 +- .../benchmarking-cli/src/storage/README.md | 43 +- .../utils/frame/frame-utilities-cli/README.md | 2 +- substrate/utils/frame/rpc/support/README.md | 2 +- substrate/utils/frame/rpc/system/README.md | 2 +- substrate/utils/prometheus/README.md | 12 +- substrate/utils/wasm-builder/README.md | 61 +- .../zombienet/0001-basic-warp-sync/README.md | 9 +- .../0002-validators-warp-sync/README.md | 7 +- .../0003-block-building-warp-sync/README.md | 5 +- 271 files changed, 6425 insertions(+), 4586 deletions(-) create mode 100644 .github/.markdownlint.yaml create mode 100644 .github/workflows/check-markdown.yml create mode 100644 cumulus/scripts/ci/changelog/README.md create mode 100644 docs/markdown_linting.md diff --git a/.github/.markdownlint.yaml b/.github/.markdownlint.yaml new file mode 100644 index 000000000000..6a93d89c46ad --- /dev/null +++ b/.github/.markdownlint.yaml @@ -0,0 +1,210 @@ +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time +MD001: true + +# MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading +MD002: + # Heading level + level: 1 + +# MD003/heading-style/header-style - Heading style +MD003: + # Heading style + style: "consistent" + +# MD004/ul-style - Unordered list style +MD004: + # List style + style: "consistent" + +# MD005/list-indent - Inconsistent indentation for list items at the same level +MD005: false + +# MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line +MD006: false + +# MD007/ul-indent - Unordered list indentation +MD007: false + +# MD009/no-trailing-spaces - Trailing spaces +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs - Hard tabs +MD010: false + +# MD011/no-reversed-links - Reversed link syntax +MD011: true + +# MD012/no-multiple-blanks - Multiple consecutive blank lines +MD012: + # Consecutive blank lines + maximum: 2 + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 120 + # Number of characters for headings + heading_line_length: 120 + # Number of characters for code blocks + code_block_line_length: 150 + # Include code blocks + code_blocks: true + # Include tables + tables: true + # Include headings + headings: true + # Include headings + headers: true + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD014/commands-show-output - Dollar signs used before commands without showing output +MD014: true + +# MD018/no-missing-space-atx - No space after hash on atx style heading +MD018: true + +# MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading +MD019: true + +# MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading +MD020: true + +# MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading +MD021: true + +# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines +MD022: false + +# MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line +MD023: true + +# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content +MD024: false + +# MD025/single-title/single-h1 - Multiple top-level headings in the same document +MD025: false + +# MD026/no-trailing-punctuation - Trailing punctuation in heading +MD026: + # Punctuation characters + punctuation: ".,;:!。,;:!" + +# MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol +MD027: true + +# MD028/no-blanks-blockquote - Blank line inside blockquote +MD028: true + +# MD029/ol-prefix - Ordered list item prefix +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space - Spaces after list markers +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines +MD031: false + +# MD032/blanks-around-lists - Lists should be surrounded by blank lines +MD032: false + +# MD033/no-inline-html - Inline HTML +MD033: false + +# MD034/no-bare-urls - Bare URL used +MD034: false + +# MD035/hr-style - Horizontal rule style +MD035: + # Horizontal rule style + style: "consistent" + +# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD036: false + +# MD037/no-space-in-emphasis - Spaces inside emphasis markers +MD037: true + +# MD038/no-space-in-code - Spaces inside code span elements +MD038: true + +# MD039/no-space-in-links - Spaces inside link text +MD039: true + +# MD040/fenced-code-language - Fenced code blocks should have a language specified +MD040: false + +# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading +MD041: false + +# MD042/no-empty-links - No empty links +MD042: true + +# MD043/required-headings/required-headers - Required heading structure +MD043: false + +# MD044/proper-names - Proper names should have the correct capitalization +MD044: + # List of proper names + names: ["Polkadot", "Substrate", "Cumulus", "Parity"] + # Include code blocks + code_blocks: false + # Include HTML elements + html_elements: false + +# MD045/no-alt-text - Images should have alternate text (alt text) +MD045: false + +# MD046/code-block-style - Code block style +MD046: + # Block style + style: "consistent" + +# MD047/single-trailing-newline - Files should end with a single newline character +MD047: true + +# MD048/code-fence-style - Code fence style +MD048: + # Code fence style + style: "consistent" + +# MD049/emphasis-style - Emphasis style should be consistent +MD049: false + +# MD050/strong-style - Strong style should be consistent +MD050: + # Strong style + style: "consistent" + +# MD051/link-fragments - Link fragments should be valid +MD051: false + +# MD052/reference-links-images - Reference links and images should use a label that is defined +MD052: false + +# MD053/link-image-reference-definitions - Link and image reference definitions should be needed +MD053: false diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml new file mode 100644 index 000000000000..b386fd6d1b1e --- /dev/null +++ b/.github/workflows/check-markdown.yml @@ -0,0 +1,33 @@ +name: Check Markdown + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +permissions: + packages: read + +jobs: + lint-markdown: + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - uses: actions/setup-node@v3.8.1 + with: + node-version: "18.x" + registry-url: "https://npm.pkg.github.com" + scope: "@paritytech" + + - name: Install tooling + run: | + npm install -g markdownlint-cli + markdownlint --version + + - name: Check Markdown + env: + CONFIG: .github/.markdownlint.yaml + run: | + markdownlint --config "$CONFIG" --ignore target . diff --git a/README.md b/README.md index a0ef18182798..56b3481bafc0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -> NOTE: We have recently made significant changes to our repository structure. In order to -streamline our development process and foster better contributions, we have merged three separate -repositories Cumulus, Substrate and Polkadot into this repository. Read more about the changes [ +> NOTE: We have recently made significant changes to our repository structure. In order to streamline our development +process and foster better contributions, we have merged three separate repositories Cumulus, Substrate and Polkadot into +this repository. Read more about the changes [ here](https://polkadot-public.notion.site/Polkadot-SDK-FAQ-fbc4cecc2c46443fb37b9eeec2f0d85f). # Polkadot SDK @@ -9,27 +9,29 @@ here](https://polkadot-public.notion.site/Polkadot-SDK-FAQ-fbc4cecc2c46443fb37b9 [![StackExchange](https://img.shields.io/badge/StackExchange-Community%20&%20Support-222222?logo=stackexchange)](https://substrate.stackexchange.com/) -The Polkadot SDK repository provides all the resources needed to start building on the Polkadot -network, a multi-chain blockchain platform that enables different blockchains to interoperate and -share information in a secure and scalable way. The Polkadot SDK comprises three main pieces of -software: +The Polkadot SDK repository provides all the resources needed to start building on the Polkadot network, a multi-chain +blockchain platform that enables different blockchains to interoperate and share information in a secure and scalable +way. The Polkadot SDK comprises three main pieces of software: ## [Polkadot](./polkadot/) -[![PolkadotForum](https://img.shields.io/badge/Polkadot_Forum-e6007a?logo=polkadot)](https://forum.polkadot.network/) [![Polkadot-license](https://img.shields.io/badge/License-GPL3-blue)](./polkadot/LICENSE) +[![PolkadotForum](https://img.shields.io/badge/Polkadot_Forum-e6007a?logo=polkadot)](https://forum.polkadot.network/) +[![Polkadot-license](https://img.shields.io/badge/License-GPL3-blue)](./polkadot/LICENSE) -Implementation of a node for the https://polkadot.network in Rust, using the Substrate framework. -This directory currently contains runtimes for the Polkadot, Kusama, Westend, and Rococo networks. -In the future, these will be relocated to the [`runtimes`](https://github.com/polkadot-fellows/runtimes/) repository. +Implementation of a node for the https://polkadot.network in Rust, using the Substrate framework. This directory +currently contains runtimes for the Polkadot, Kusama, Westend, and Rococo networks. In the future, these will be +relocated to the [`runtimes`](https://github.com/polkadot-fellows/runtimes/) repository. ## [Substrate](./substrate/) - [![SubstrateRustDocs](https://img.shields.io/badge/Rust_Docs-Substrate-24CC85?logo=rust)](https://paritytech.github.io/substrate/master/substrate/index.html) [![Substrate-license](https://img.shields.io/badge/License-GPL3%2FApache2.0-blue)](./substrate/README.md#LICENSE) + [![SubstrateRustDocs](https://img.shields.io/badge/Rust_Docs-Substrate-24CC85?logo=rust)](https://paritytech.github.io/substrate/master/substrate/index.html) + [![Substrate-license](https://img.shields.io/badge/License-GPL3%2FApache2.0-blue)](./substrate/README.md#LICENSE) -Substrate is the primary blockchain SDK used by developers to create the parachains that make up -the Polkadot network. Additionally, it allows for the development of self-sovereign blockchains -that operate completely independently of Polkadot. +Substrate is the primary blockchain SDK used by developers to create the parachains that make up the Polkadot network. +Additionally, it allows for the development of self-sovereign blockchains that operate completely independently of +Polkadot. ## [Cumulus](./cumulus/) -[![CumulusRustDocs](https://img.shields.io/badge/Rust_Docs-Cumulus-222222?logo=rust)](https://paritytech.github.io/cumulus/cumulus_client_collator/index.html) [![Cumulus-license](https://img.shields.io/badge/License-GPL3-blue)](./cumulus/LICENSE) +[![CumulusRustDocs](https://img.shields.io/badge/Rust_Docs-Cumulus-222222?logo=rust)](https://paritytech.github.io/cumulus/cumulus_client_collator/index.html) +[![Cumulus-license](https://img.shields.io/badge/License-GPL3-blue)](./cumulus/LICENSE) Cumulus is a set of tools for writing Substrate-based Polkadot parachains. @@ -37,10 +39,10 @@ Cumulus is a set of tools for writing Substrate-based Polkadot parachains. Below are the primary upstream dependencies utilized in this project: -- [parity-scale-codec](https://crates.io/crates/parity-scale-codec) -- [parity-db](https://crates.io/crates/parity-db) -- [parity-common](https://github.com/paritytech/parity-common) -- [trie](https://github.com/paritytech/trie) +- [`parity-scale-codec`](https://crates.io/crates/parity-scale-codec) +- [`parity-db`](https://crates.io/crates/parity-db) +- [`parity-common`](https://github.com/paritytech/parity-common) +- [`trie`](https://github.com/paritytech/trie) ## Security @@ -48,9 +50,11 @@ The security policy and procedures can be found in [docs/SECURITY.md](./docs/SEC ## Contributing & Code of Conduct -Ensure you follow our [contribution guidelines](./docs/CONTRIBUTING.md). In every interaction and contribution, this project adheres to the [Contributor Covenant Code of Conduct](./docs/CODE_OF_CONDUCT.md). +Ensure you follow our [contribution guidelines](./docs/CONTRIBUTING.md). In every interaction and contribution, this +project adheres to the [Contributor Covenant Code of Conduct](./docs/CODE_OF_CONDUCT.md). ## Additional Resources -- For monitoring upcoming changes and current proposals related to the technical implementation of the Polkadot network, visit the [`Requests for Comment (RFC)`](https://github.com/polkadot-fellows/RFCs) repository. While it's maintained by the Polkadot Fellowship, the RFC process welcomes contributions from everyone. - +- For monitoring upcoming changes and current proposals related to the technical implementation of the Polkadot network, + visit the [`Requests for Comment (RFC)`](https://github.com/polkadot-fellows/RFCs) repository. While it's maintained + by the Polkadot Fellowship, the RFC process welcomes contributions from everyone. diff --git a/cumulus/BRIDGES.md b/cumulus/BRIDGES.md index 8766de92c17e..a6f00aec0928 100644 --- a/cumulus/BRIDGES.md +++ b/cumulus/BRIDGES.md @@ -1,13 +1,13 @@ -# Using Parity Bridges Common dependency (`git subtree`). +# Using Parity Bridges Common dependency (`git subtree`) In `./bridges` sub-directory you can find a `git subtree` imported version of: -[parity-bridges-common](https://github.com/paritytech/parity-bridges-common/) repository. +[`parity-bridges-common`](https://github.com/paritytech/parity-bridges-common/) repository. (For regular Cumulus contributor 1. is relevant) \ (For Cumulus maintainer 1. and 2. are relevant) \ (For Bridges team 1. and 2. and 3. are relevant) -# 1. How to fix broken Bridges code? +## How to fix broken Bridges code? To fix Bridges code simply create a commit in current (`Cumulus`) repo. Best if the commit is isolated to changes in `./bridges` sub-directory, because it makes @@ -16,7 +16,7 @@ it easier to import that change back to upstream repo. (Any changes to `bridges` subtree require Bridges team approve and they should manage backport to Bridges repo) -# 2. How to pull latest Bridges code to the `bridges` subtree +## How to pull latest Bridges code to the `bridges` subtree (in practice) The `bridges` repo has a stabilized branch `polkadot-staging` dedicated for releasing. @@ -25,7 +25,7 @@ The `bridges` repo has a stabilized branch `polkadot-staging` dedicated for rele cd # this will update new git branches from bridges repo -# there could be unresolved conflicts, but dont worry, +# there could be unresolved conflicts, but don't worry, # lots of them are caused because of removed unneeded files with patch step, BRANCH=polkadot-staging ./scripts/bridges_update_subtree.sh fetch @@ -45,9 +45,9 @@ BRANCH=polkadot-staging ./scripts/bridges_update_subtree.sh fetch # so after all conflicts are solved and patch passes and compiles, # then we need to finish merge with: git merge --continue -```` +``` -# 3. How to pull latest Bridges code or contribute back? +## How to pull latest Bridges code or contribute back? (in theory) Note that it's totally fine to ping the **Bridges Team** to do that for you. The point @@ -58,34 +58,34 @@ If you still would like to either update the code to match latest code from the or create an upstream PR read below. The following commands should be run in the current (`polkadot`) repo. -1. Add Bridges repo as a local remote: +### Add Bridges repo as a local remote ``` -$ git remote add -f bridges git@github.com:paritytech/parity-bridges-common.git +git remote add -f bridges git@github.com:paritytech/parity-bridges-common.git ``` If you plan to contribute back, consider forking the repository on Github and adding your personal fork as a remote as well. ``` -$ git remote add -f my-bridges git@github.com:tomusdrw/parity-bridges-common.git +git remote add -f my-bridges git@github.com:tomusdrw/parity-bridges-common.git ``` -2. To update Bridges: +### To update Bridges +``` +git fetch bridges polkadot-staging +git subtree pull --prefix=bridges bridges polkadot-staging --squash ``` -$ git fetch bridges polkadot-staging -$ git subtree pull --prefix=bridges bridges polkadot-staging --squash -```` We use `--squash` to avoid adding individual commits and rather squashing them all into one. -3. Clean unneeded files here: +### Clean unneeded files here ``` ./bridges/scripts/verify-pallets-build.sh --ignore-git-state --no-revert ``` -4. Contributing back to Bridges (creating upstream PR) +### Contributing back to Bridges (creating upstream PR) ``` -$ git subtree push --prefix=bridges my-bridges polkadot-staging +git subtree push --prefix=bridges my-bridges polkadot-staging ``` This command will push changes to your personal fork of Bridges repo, from where you can simply create a PR to the main repo. diff --git a/cumulus/README.md b/cumulus/README.md index 419e293a0abd..19f9f3f113dd 100644 --- a/cumulus/README.md +++ b/cumulus/README.md @@ -2,59 +2,53 @@ [![Doc](https://img.shields.io/badge/cumulus%20docs-master-brightgreen)](https://paritytech.github.io/cumulus/) -This repository contains both the Cumulus SDK and also specific chains implemented on top of this -SDK. +This repository contains both the Cumulus SDK and also specific chains implemented on top of this SDK. -If you only want to run a **Polkadot Parachain Node**, check out our [container -section](./docs/container.md). +If you only want to run a **Polkadot Parachain Node**, check out our [container section](./docs/container.md). ## Cumulus SDK -A set of tools for writing [Substrate](https://substrate.io/)-based -[Polkadot](https://wiki.polkadot.network/en/) -[parachains](https://wiki.polkadot.network/docs/en/learn-parachains). Refer to the included -[overview](docs/overview.md) for architectural details, and the [Connect to a relay chain how-to -guide](https://docs.substrate.io/reference/how-to-guides/parachains/connect-to-a-relay-chain/) for a -guided walk-through of using these tools. +A set of tools for writing [Substrate](https://substrate.io/)-based [Polkadot](https://wiki.polkadot.network/en/) +[parachains](https://wiki.polkadot.network/docs/en/learn-parachains). Refer to the included [overview](docs/overview.md) +for architectural details, and the [Connect to a relay chain how-to +guide](https://docs.substrate.io/reference/how-to-guides/parachains/connect-to-a-relay-chain/) for a guided walk-through +of using these tools. -It's easy to write blockchains using Substrate, and the overhead of writing parachains' -distribution, p2p, database, and synchronization layers should be just as low. This project aims to -make it easy to write parachains for Polkadot by leveraging the power of Substrate. +It's easy to write blockchains using Substrate, and the overhead of writing parachains' distribution, p2p, database, and +synchronization layers should be just as low. This project aims to make it easy to write parachains for Polkadot by +leveraging the power of Substrate. -Cumulus clouds are shaped sort of like dots; together they form a system that is intricate, -beautiful and functional. +Cumulus clouds are shaped sort of like dots; together they form a system that is intricate, beautiful and functional. ### Consensus [`parachain-consensus`](https://github.com/paritytech/polkadot-sdk/blob/master/cumulus/client/consensus/common/src/parachain_consensus.rs) -is a [consensus engine](https://docs.substrate.io/v3/advanced/consensus) for Substrate that follows -a Polkadot [relay chain](https://wiki.polkadot.network/docs/en/learn-architecture#relay-chain). This -will run a Polkadot node internally, and dictate to the client and synchronization algorithms which -chain to follow, -[finalize](https://wiki.polkadot.network/docs/en/learn-consensus#probabilistic-vs-provable-finality), -and treat as best. +is a [consensus engine](https://docs.substrate.io/v3/advanced/consensus) for Substrate that follows a Polkadot [relay +chain](https://wiki.polkadot.network/docs/en/learn-architecture#relay-chain). This will run a Polkadot node internally, +and dictate to the client and synchronization algorithms which chain to follow, +[finalize](https://wiki.polkadot.network/docs/en/learn-consensus#probabilistic-vs-provable-finality), and treat as best. ### Collator -A Polkadot [collator](https://wiki.polkadot.network/docs/en/learn-collator) for the parachain is -implemented by the `polkadot-parachain` binary (previously called `polkadot-collator`). +A Polkadot [collator](https://wiki.polkadot.network/docs/en/learn-collator) for the parachain is implemented by the +`polkadot-parachain` binary (previously called `polkadot-collator`). -You may run `polkadot-parachain` locally after building it or using one of the container option -described [here](./docs/container.md). +You may run `polkadot-parachain` locally after building it or using one of the container option described +[here](./docs/container.md). -### Relay Chain Interaction -To operate a parachain node, a connection to the corresponding relay -chain is necessary. This can be achieved in one of three ways: -1. Run a full relay chain node within the parachain node (default) -2. Connect to an external relay chain node via WebSocket RPC +### Relay Chain Interaction +To operate a parachain node, a connection to the corresponding relay chain is necessary. This can be achieved in one of +three ways: +1. Run a full relay chain node within the parachain node (default) +2. Connect to an external relay chain node via WebSocket RPC 3. Run a light client for the relay chain #### In-process Relay Chain Node -If an external relay chain node is not specified (default behavior), then a full relay chain node is -spawned within the same process. +If an external relay chain node is not specified (default behavior), then a full relay chain node is spawned within the +same process. -This node has all of the typical components of a regular Polkadot node and will have to fully sync -with the relay chain to work. +This node has all of the typical components of a regular Polkadot node and will have to fully sync with the relay chain +to work. ##### Example command ```bash @@ -66,19 +60,16 @@ polkadot-parachain \ ``` #### External Relay Chain Node -An external relay chain node is connected via WebsSocket RPC by using the -`--relay-chain-rpc-urls` command line argument. This option accepts one or more -space-separated WebSocket URLs to a full relay chain node. By default, only the -first URL will be used, with the rest as a backup in case the connection to the -first node is lost. +An external relay chain node is connected via WebsSocket RPC by using the `--relay-chain-rpc-urls` command line +argument. This option accepts one or more space-separated WebSocket URLs to a full relay chain node. By default, only +the first URL will be used, with the rest as a backup in case the connection to the first node is lost. -Parachain nodes using this feature won't have to fully sync with the relay chain -to work, so in general they will use fewer system resources. +Parachain nodes using this feature won't have to fully sync with the relay chain to work, so in general they will use +fewer system resources. -**Note:** At this time, any parachain nodes using this feature will still spawn a -significantly cut-down relay chain node in-process. Even though they lack the -majority of normal Polkadot subsystems, they will still need to connect directly -to the relay chain network. +**Note:** At this time, any parachain nodes using this feature will still spawn a significantly cut-down relay chain +node in-process. Even though they lack the majority of normal Polkadot subsystems, they will still need to connect +directly to the relay chain network. ##### Example command @@ -94,17 +85,15 @@ polkadot-parachain \ ``` #### Relay Chain Light Client -An internal relay chain light client provides a fast and lightweight approach -for connecting to the relay chain network. It provides relay chain notifications -and facilitates runtime calls. +An internal relay chain light client provides a fast and lightweight approach for connecting to the relay chain network. +It provides relay chain notifications and facilitates runtime calls. -To specify which chain the light client should connect to, users need to supply -a relay chain chain-spec as part of the relay chain arguments. +To specify which chain the light client should connect to, users need to supply a relay chain chain-spec as part of the +relay chain arguments. -**Note:** At this time, any parachain nodes using this feature will still spawn -a significantly cut-down relay chain node in-process. Even though they lack the -majority of normal Polkadot subsystems, they will still need to connect directly -to the relay chain network. +**Note:** At this time, any parachain nodes using this feature will still spawn a significantly cut-down relay chain +node in-process. Even though they lack the majority of normal Polkadot subsystems, they will still need to connect +directly to the relay chain network. ##### Example command @@ -118,23 +107,22 @@ polkadot-parachain \ ``` ## Installation and Setup -Before building Cumulus SDK based nodes / runtimes prepare your environment by -following Substrate [installation instructions](https://docs.substrate.io/main-docs/install/). +Before building Cumulus SDK based nodes / runtimes prepare your environment by following Substrate [installation +instructions](https://docs.substrate.io/main-docs/install/). -To launch a local network, you can use [zombienet](https://github.com/paritytech/zombienet) -for quick setup and experimentation or follow the [manual setup](#manual-setup). +To launch a local network, you can use [zombienet](https://github.com/paritytech/zombienet) for quick setup and +experimentation or follow the [manual setup](#manual-setup). ### Zombienet -We use Zombienet to spin up networks for integration tests and local networks. -Follow [these installation steps](https://github.com/paritytech/zombienet#requirements-by-provider) -to set it up on your machine. A simple network specification with two relay chain -nodes and one collator is located at [zombienet/examples/small_network.toml](zombienet/examples/small_network.toml). +We use Zombienet to spin up networks for integration tests and local networks. Follow [these installation +steps](https://github.com/paritytech/zombienet#requirements-by-provider) to set it up on your machine. A simple network +specification with two relay chain nodes and one collator is located at +[zombienet/examples/small_network.toml](zombienet/examples/small_network.toml). #### Which provider should I use? Zombienet offers multiple providers to run networks. Choose the one that best fits your needs: - **Podman:** Choose this if you want to spin up a network quick and easy. -- **Native:** Choose this if you want to develop and deploy your changes. Requires compilation -of the binaries. +- **Native:** Choose this if you want to develop and deploy your changes. Requires compilation of the binaries. - **Kubernetes:** Choose this for advanced use-cases or running on cloud-infrastructure. #### How to run @@ -183,13 +171,16 @@ cargo build --release --bin polkadot-parachain ./target/release/polkadot-parachain export-genesis-wasm > genesis-wasm # Collator1 -./target/release/polkadot-parachain --collator --alice --force-authoring --tmp --port 40335 --rpc-port 9946 -- --chain ../polkadot/rococo-local-cfde.json --port 30335 +./target/release/polkadot-parachain --collator --alice --force-authoring \ + --tmp --port 40335 --rpc-port 9946 -- --chain ../polkadot/rococo-local-cfde.json --port 30335 # Collator2 -./target/release/polkadot-parachain --collator --bob --force-authoring --tmp --port 40336 --rpc-port 9947 -- --chain ../polkadot/rococo-local-cfde.json --port 30336 +./target/release/polkadot-parachain --collator --bob --force-authoring \ + --tmp --port 40336 --rpc-port 9947 -- --chain ../polkadot/rococo-local-cfde.json --port 30336 # Parachain Full Node 1 -./target/release/polkadot-parachain --tmp --port 40337 --rpc-port 9948 -- --chain ../polkadot/rococo-local-cfde.json --port 30337 +./target/release/polkadot-parachain --tmp --port 40337 --rpc-port 9948 -- \ + --chain ../polkadot/rococo-local-cfde.json --port 30337 ``` #### Register the parachain @@ -199,8 +190,8 @@ cargo build --release --bin polkadot-parachain ## Asset Hub 🪙 -This repository also contains the Asset Hub runtimes. Asset Hub is a system parachain -providing an asset store for the Polkadot ecosystem. +This repository also contains the Asset Hub runtimes. Asset Hub is a system parachain providing an asset store for the +Polkadot ecosystem. ### Build & Launch a Node @@ -228,20 +219,18 @@ See [the `contracts-rococo` readme](parachains/runtimes/contracts/contracts-roco See [the `bridge-hubs` readme](parachains/runtimes/bridge-hubs/README.md) for details. ## Rococo 👑 -[Rococo](https://polkadot.js.org/apps/?rpc=wss://rococo-rpc.polkadot.io) is becoming a -[Community Parachain Testbed](https://polkadot.network/blog/rococo-revamp-becoming-a-community-parachain-testbed/) -for parachain teams in the Polkadot ecosystem. It supports multiple parachains with the -differentiation of long-term connections and recurring short-term connections, to see -which parachains are currently connected and how long they will be connected for -[see here](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-rpc.polkadot.io#/parachains). +[Rococo](https://polkadot.js.org/apps/?rpc=wss://rococo-rpc.polkadot.io) is becoming a [Community Parachain +Testbed](https://polkadot.network/blog/rococo-revamp-becoming-a-community-parachain-testbed/) for parachain teams in the +Polkadot ecosystem. It supports multiple parachains with the differentiation of long-term connections and recurring +short-term connections, to see which parachains are currently connected and how long they will be connected for [see +here](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-rpc.polkadot.io#/parachains). -Rococo is an elaborate style of design and the name describes the painstaking effort that -has gone into this project. +Rococo is an elaborate style of design and the name describes the painstaking effort that has gone into this project. ### Build & Launch Rococo Collators -Collators are similar to validators in the relay chain. These nodes build the blocks that -will eventually be included by the relay chain for a parachain. +Collators are similar to validators in the relay chain. These nodes build the blocks that will eventually be included by +the relay chain for a parachain. To run a Rococo collator you will need to compile the following binary: @@ -250,8 +239,7 @@ To run a Rococo collator you will need to compile the following binary: cargo build --release --locked --bin polkadot-parachain ``` -Once the executable is built, launch collators for each parachain (repeat once each for chain -`tick`, `trick`, `track`): +Once the executable is built, launch collators for each parachain (repeat once each for chain `tick`, `trick`, `track`): ```bash ./target/release/polkadot-parachain --chain $CHAIN --validator @@ -261,10 +249,10 @@ You can also build [using a container](./docs/container.md). ### Parachains -* [Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-statemint-rpc.polkadot.io#/explorer) -* [Contracts on Rococo](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-contracts-rpc.polkadot.io#/explorer) -* [RILT](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo.kilt.io#/explorer) +- [Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-statemint-rpc.polkadot.io#/explorer) +- [Contracts on Rococo](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-contracts-rpc.polkadot.io#/explorer) +- [RILT](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo.kilt.io#/explorer) -The network uses horizontal message passing (HRMP) to enable communication between -parachains and the relay chain and, in turn, between parachains. This means that every -message is sent to the relay chain, and from the relay chain to its destination parachain. +The network uses horizontal message passing (HRMP) to enable communication between parachains and the relay chain and, +in turn, between parachains. This means that every message is sent to the relay chain, and from the relay chain to its +destination parachain. diff --git a/cumulus/bridges/CODE_OF_CONDUCT.md b/cumulus/bridges/CODE_OF_CONDUCT.md index 70541fb72fa2..23411da2e048 100644 --- a/cumulus/bridges/CODE_OF_CONDUCT.md +++ b/cumulus/bridges/CODE_OF_CONDUCT.md @@ -34,9 +34,9 @@ of preference. We see that blockchains are naturally community platforms with u ultimate decision makers. We assert that good software will maximise user agency by facilitate user-expression on the network. As such: -- This project will strive to give users as much choice as is both reasonable and possible over what +* This project will strive to give users as much choice as is both reasonable and possible over what protocol they adhere to; but -- use of the project's technical forums, commenting systems, pull requests and issue trackers as a +* use of the project's technical forums, commenting systems, pull requests and issue trackers as a means to express individual protocol preferences is forbidden. ## Our Responsibilities diff --git a/cumulus/bridges/README.md b/cumulus/bridges/README.md index 2f8c5ca9abb2..da46fe67d924 100644 --- a/cumulus/bridges/README.md +++ b/cumulus/bridges/README.md @@ -2,11 +2,10 @@ This is a collection of components for building bridges. -These components include Substrate pallets for syncing headers, passing arbitrary messages, as well -as libraries for building relayers to provide cross-chain communication capabilities. +These components include Substrate pallets for syncing headers, passing arbitrary messages, as well as libraries for +building relayers to provide cross-chain communication capabilities. -Three bridge nodes are also available. The nodes can be used to run test networks which bridge other -Substrate chains. +Three bridge nodes are also available. The nodes can be used to run test networks which bridge other Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 @@ -21,8 +20,8 @@ Substrate chains. ## Installation -To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web -Assembly (WASM) runtime for the node. You can configure the WASM support as so: +To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web Assembly (WASM) +runtime for the node. You can configure the WASM support as so: ```bash rustup install nightly @@ -38,8 +37,8 @@ cargo build --all cargo test --all ``` -Also you can build the repo with -[Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): +Also you can build the repo with [Parity CI Docker +image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): ```bash docker pull paritytech/bridges-ci:production @@ -57,16 +56,14 @@ docker run --rm -it -w /shellhere/parity-bridges-common \ If you want to reproduce other steps of CI process you can use the following [guide](https://github.com/paritytech/scripts#reproduce-ci-locally). -If you need more information about setting up your development environment [Substrate's -Installation page](https://docs.substrate.io/main-docs/install/) is a good -resource. +If you need more information about setting up your development environment [Substrate's Installation +page](https://docs.substrate.io/main-docs/install/) is a good resource. ## High-Level Architecture -This repo has support for bridging foreign chains together using a combination of Substrate pallets -and external processes called relayers. A bridge chain is one that is able to follow the consensus -of a foreign chain independently. For example, consider the case below where we want to bridge two -Substrate based chains. +This repo has support for bridging foreign chains together using a combination of Substrate pallets and external +processes called relayers. A bridge chain is one that is able to follow the consensus of a foreign chain independently. +For example, consider the case below where we want to bridge two Substrate based chains. ``` +---------------+ +---------------+ @@ -82,19 +79,19 @@ Substrate based chains. +---------------+ ``` -The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by -using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact -directly they need an external service, called a relayer, to communicate. The relayer will subscribe -to new Rialto headers via RPC and submit them to the Millau chain for verification. +The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by using a runtime +module designed to track GRANDPA finality. Since two blockchains can't interact directly they need an external service, +called a relayer, to communicate. The relayer will subscribe to new Rialto headers via RPC and submit them to the Millau +chain for verification. -Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth -description of the bridge interaction. +Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth description of the +bridge interaction. ## Project Layout -Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual -"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and -the `relays` which are used to pass messages between chains. +Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual "blockchain", the +`modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass +messages between chains. ``` ├── bin // Node and Runtime for the various Substrate chains @@ -117,16 +114,16 @@ the `relays` which are used to pass messages between chains. ## Running the Bridge -To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes -on each side of the bridge (source and target chain). +To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes on each side of the +bridge (source and target chain). There are 2 ways to run the bridge, described below: -- building & running from source: with this option, you'll be able to run the bridge between two standalone -chains that are running GRANDPA finality gadget to achieve finality; +- building & running from source: with this option, you'll be able to run the bridge between two standalone chains that +are running GRANDPA finality gadget to achieve finality; -- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, -complex relays and more. +- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, complex relays +and more. ### Using the Source @@ -141,16 +138,15 @@ cargo build -p substrate-relay ### Running a Dev network -We will launch a dev network to demonstrate how to relay a message between two Substrate based -chains (named Rialto and Millau). +We will launch a dev network to demonstrate how to relay a message between two Substrate based chains (named Rialto and +Millau). -To do this we will need two nodes, two relayers which will relay headers, and two relayers which -will relay messages. +To do this we will need two nodes, two relayers which will relay headers, and two relayers which will relay messages. #### Running from local scripts -To run a simple dev network you can use the scripts located in the -[`deployments/local-scripts` folder](./deployments/local-scripts). +To run a simple dev network you can use the scripts located in the [`deployments/local-scripts` +folder](./deployments/local-scripts). First, we must run the two Substrate nodes. @@ -167,8 +163,8 @@ After the nodes are up we can run the header relayers. ./deployments/local-scripts/relay-rialto-to-millau.sh ``` -At this point you should see the relayer submitting headers from the Millau Substrate chain to the -Rialto Substrate chain. +At this point you should see the relayer submitting headers from the Millau Substrate chain to the Rialto Substrate +chain. ``` # Header Relayer Logs @@ -192,20 +188,23 @@ You will also see the message lane relayers listening for new messages. [Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces [...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race [...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces -[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } +[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { + latest_nonce: 0, nonces_data: () } [...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces -[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } +[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { + latest_nonce: 0, nonces_data: () } [...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) } [...] [date] DEBUG bridge Asking Millau node about its state -[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) } +[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: + HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) } ``` To send a message see the ["How to send a message" section](#how-to-send-a-message). ### How to send a message -In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM -`Trap(43)` message. +In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM `Trap(43)` +message. ```bash # In `parity-bridges-common` folder @@ -222,20 +221,20 @@ TRACE bridge Sent transaction to Millau node: 0x5e68... And at the Rialto node logs you'll something like this: ``` -... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: 48559)/Weight(ref_time: 1215065371, proof_size: 54703). -``` +... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: + 48559)/Weight(ref_time: 1215065371, proof_size: 54703). +``` -It means that the message has been delivered and dispatched. Message may be dispatched with an -error, though - the goal of our test bridge is to ensure that messages are successfully delivered -and all involved components are working. +It means that the message has been delivered and dispatched. Message may be dispatched with an error, though - the goal +of our test bridge is to ensure that messages are successfully delivered and all involved components are working. ## Full Network Docker Compose Setup -For a more sophisticated deployment which includes bidirectional header sync, message passing, -monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). +For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards, +etc. see the [Deployments README](./deployments/README.md). -You should note that you can find images for all the bridge components published on -[Docker Hub](https://hub.docker.com/u/paritytech). +You should note that you can find images for all the bridge components published on [Docker +Hub](https://hub.docker.com/u/paritytech). To run a Rialto node for example, you can use the following command: @@ -247,13 +246,12 @@ docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ ## Community -Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat -server like, for example, Discord. Most discussions around Polkadot and Substrate happen -in various Element "rooms" (channels). So, joining Element might be a good idea, anyway. +Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat server like, for +example, Discord. Most discussions around Polkadot and Substrate happen in various Element "rooms" (channels). So, +joining Element might be a good idea, anyway. -If you are interested in information exchange and development of Polkadot related bridges please -feel free to join the [Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) -Element channel. +If you are interested in information exchange and development of Polkadot related bridges please feel free to join the +[Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) Element channel. -The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element -channel is most suited for discussions regarding Substrate itself. +The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element channel is most suited +for discussions regarding Substrate itself. diff --git a/cumulus/bridges/SECURITY.md b/cumulus/bridges/SECURITY.md index 65f2f3bff05d..9f215c887654 100644 --- a/cumulus/bridges/SECURITY.md +++ b/cumulus/bridges/SECURITY.md @@ -4,11 +4,15 @@ Thanks for helping make the Parity ecosystem more secure. Security is one of our ## Reporting a vulnerability -If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it in the public forum as it can cause more damage, rather than giving real help to the ecosystem. +If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it +in the public forum as it can cause more damage, rather than giving real help to the ecosystem. Security vulnerabilities should be reported by the [contact form](https://security-submission.parity.io/). -If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information about our Bug Bounty Program. - -**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for information. +If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. +Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information +about our Bug Bounty Program. +**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not +mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for +information. diff --git a/cumulus/bridges/docs/high-level-overview.md b/cumulus/bridges/docs/high-level-overview.md index 449224124afd..42efc8100bd0 100644 --- a/cumulus/bridges/docs/high-level-overview.md +++ b/cumulus/bridges/docs/high-level-overview.md @@ -1,83 +1,85 @@ # High-Level Bridge Documentation -This document gives a brief, abstract description of main components that may be found in this repository. -If you want to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please -refer to the [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md). +This document gives a brief, abstract description of main components that may be found in this repository. If you want +to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please refer to the [Polkadot <> +Kusama Bridge](./polkadot-kusama-bridge-overview.md). ## Purpose -This repo contains all components required to build a trustless connection between standalone Substrate chains, -that are using GRANDPA finality, their parachains or any combination of those. On top of this connection, we -offer a messaging pallet that provides means to organize messages exchange. +This repo contains all components required to build a trustless connection between standalone Substrate chains, that are +using GRANDPA finality, their parachains or any combination of those. On top of this connection, we offer a messaging +pallet that provides means to organize messages exchange. -On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM messaging](./polkadot-kusama-bridge-overview.md), -[encoded calls messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on. +On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM +messaging](./polkadot-kusama-bridge-overview.md), [encoded calls +messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on. ## Terminology -Even though we support (and require) two-way bridging, the documentation will generally talk about -a one-sided interaction. That's to say, we will only talk about syncing finality proofs and messages -from a _source_ chain to a _target_ chain. This is because the two-sided interaction is really just the -one-sided interaction with the source and target chains switched. +Even though we support (and require) two-way bridging, the documentation will generally talk about a one-sided +interaction. That's to say, we will only talk about syncing finality proofs and messages from a _source_ chain to a +_target_ chain. This is because the two-sided interaction is really just the one-sided interaction with the source and +target chains switched. The bridge has both on-chain (pallets) and offchain (relayers) components. ## On-chain components -On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require -deployment at the target chain, while messages pallet needs to be deployed at both, source -and target chains. +On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require deployment at +the target chain, while messages pallet needs to be deployed at both, source and target chains. ### Bridge GRANDPA Finality Pallet -A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth" -about the source chain headers which have been finalized. This is useful for higher level applications. +A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth" about +the source chain headers which have been finalized. This is useful for higher level applications. -The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), -generated by the current authorities set. The GRANDPA protocol itself requires current authorities set to -generate explicit justification for the header that enacts next authorities set. Such headers and their finality -proofs are called mandatory in the pallet and relayer pays no fee for such headers submission. +The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), generated +by the current authorities set. The GRANDPA protocol itself requires current authorities set to generate explicit +justification for the header that enacts next authorities set. Such headers and their finality proofs are called +mandatory in the pallet and relayer pays no fee for such headers submission. -The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers -he wants to submit (with the exception of mandatory headers). +The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers he wants to +submit (with the exception of mandatory headers). More: [pallet level documentation and code](../modules/grandpa/). ### Bridge Parachains Finality Pallet -Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their -finality proofs. Instead, they rely on their relay chain finality. The parachain header is considered final, -when it is accepted by the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) -at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay -chain GRANDPA gadget. +Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their finality +proofs. Instead, they rely on their relay chain finality. The parachain header is considered final, when it is accepted +by the [`paras` +pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) +at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay chain +GRANDPA gadget. That said, the bridge parachains pallet accepts storage proof of one or several parachain heads, inserted to the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) -map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras). +map of the [`paras` +pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras). To verify this storage proof, the pallet uses relay chain header, imported earlier by the bridge GRANDPA pallet. -The pallet may track multiple parachains at once and those parachains may use different primitives. So the -parachain header decoding never happens at the pallet level. For maintaining the headers order, the pallet -uses relay chain header number. +The pallet may track multiple parachains at once and those parachains may use different primitives. So the parachain +header decoding never happens at the pallet level. For maintaining the headers order, the pallet uses relay chain header +number. More: [pallet level documentation and code](../modules/parachains/). ### Bridge Messages Pallet -The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the -target chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the -same order they are sent. The pallet supports many lanes. +The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the target +chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the same order they +are sent. The pallet supports many lanes. -The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of -messages that have been received. Inbound lane end stores the number of messages that have been received and -also a map that maps messages to relayers that have delivered those messages to the target chain. +The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of messages +that have been received. Inbound lane end stores the number of messages that have been received and also a map that maps +messages to relayers that have delivered those messages to the target chain. The pallet has three main entrypoints: - the `send_message` may be used by the other runtime pallets to send the messages; -- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the -dispatch code; -- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding -relayers that have delivered the message. +- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the dispatch +code; +- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding relayers +that have delivered the message. Many things are abstracted by the pallet: - the message itself may mean anything, the pallet doesn't care about its content; @@ -85,97 +87,98 @@ Many things are abstracted by the pallet: - the messages proof and messages delivery proof are verified outside of the pallet; - the relayers incentivization scheme is defined outside of the pallet. -Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular -storage proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages -pallet, in this case, depends on one of the finality pallets. The messages are XCM messages and we are using -XCM executor to dispatch them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) -document. +Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular storage +proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages pallet, in this +case, depends on one of the finality pallets. The messages are XCM messages and we are using XCM executor to dispatch +them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) document. More: [pallet level documentation and code](../modules/messages/). ### Bridge Relayers Pallet -The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When -the rewards are registered and the reward amount is configured outside of the pallet. +The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When the rewards +are registered and the reward amount is configured outside of the pallet. More: [pallet level documentation and code](../modules/relayers/). ## Offchain Components -Offchain bridge components are separate processes, called relayers. Relayers are connected both to the -source chain and target chain nodes. Relayers are reading state of the source chain, compare it to the -state of the target chain and, if state at target chain needs to be updated, submits target chain -transaction. +Offchain bridge components are separate processes, called relayers. Relayers are connected both to the source chain and +target chain nodes. Relayers are reading state of the source chain, compare it to the state of the target chain and, if +state at target chain needs to be updated, submits target chain transaction. ### GRANDPA Finality Relay -The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to -the Bridge GRANDPA Finality Pallet, deployed at the target chain. For that, the relay subscribes to -the source chain GRANDPA justifications stream and submits every new justification it sees to the -target chain GRANDPA light client. In addition, relay is searching for mandatory headers and -submits their justifications - without that the pallet will be unable to move forward. +The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to the Bridge GRANDPA +Finality Pallet, deployed at the target chain. For that, the relay subscribes to the source chain GRANDPA justifications +stream and submits every new justification it sees to the target chain GRANDPA light client. In addition, relay is +searching for mandatory headers and submits their justifications - without that the pallet will be unable to move +forward. -More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and code](../relays/finality/). +More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and +code](../relays/finality/). ### Parachains Finality Relay -The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the -tracked parachain nodes. The relay looks at the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) -map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) -in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at -the target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** -until header `B` or one of its ancestors appears at the target chain. Once it is available, the storage -proof of the map entry is generated and is submitted to the target chain. +The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the tracked +parachain nodes. The relay looks at the +[`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) +map of the [`paras` +pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) +in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at the +target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** until header `B` +or one of its ancestors appears at the target chain. Once it is available, the storage proof of the map entry is +generated and is submitted to the target chain. -As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains -finality relay requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or -any of its children's finality at source won't be relayed at target, and target chain -won't be able to verify generated storage proof. +As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains finality relay +requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or any of its children's finality +at source won't be relayed at target, and target chain won't be able to verify generated storage proof. More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/). ### Messages Relay -Messages relay is actually two relays that are running in a single process: messages delivery relay and -delivery confirmation relay. Even though they are more complex and have many caveats, the overall algorithm -is the same as in other relays. +Messages relay is actually two relays that are running in a single process: messages delivery relay and delivery +confirmation relay. Even though they are more complex and have many caveats, the overall algorithm is the same as in +other relays. -Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new -messages are queued there. Once they appear at the source block `B`, the relay start waiting for the block -`B` or its descendant appear at the target chain. Then the messages storage proof is generated and submitted -to the bridge messages pallet at the target chain. In addition, the transaction may include the storage proof -of the outbound lane state - that proves that relayer rewards have been paid and this data (map of relay -accounts to the delivered messages) may be pruned from the inbound lane state at the target chain. +Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new messages are +queued there. Once they appear at the source block `B`, the relay start waiting for the block `B` or its descendant +appear at the target chain. Then the messages storage proof is generated and submitted to the bridge messages pallet at +the target chain. In addition, the transaction may include the storage proof of the outbound lane state - that proves +that relayer rewards have been paid and this data (map of relay accounts to the delivered messages) may be pruned from +the inbound lane state at the target chain. -Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new -messages are delivered to the target chain, the corresponding _source chain account_ is inserted to the -map in the inbound lane data. Relay detects that, say, at the target chain block `B` and waits until that -block or its descendant appears at the source chain. Once that happens, the relay crafts a storage proof of -that data and sends it to the messages pallet, deployed at the source chain. +Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new messages are +delivered to the target chain, the corresponding _source chain account_ is inserted to the map in the inbound lane data. +Relay detects that, say, at the target chain block `B` and waits until that block or its descendant appears at the +source chain. Once that happens, the relay crafts a storage proof of that data and sends it to the messages pallet, +deployed at the source chain. -As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages -relay submits transactions to both source and target chains, it requires both _source-to-target_ and -_target-to-source_ finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, -depending on the type of connected chain. +As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages relay +submits transactions to both source and target chains, it requires both _source-to-target_ and _target-to-source_ +finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, depending on the type of +connected chain. -More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and code](../relays/messages/). +More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and +code](../relays/messages/). ### Complex Relay -Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory -GRANDPA header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it -sees, will have to pay a (quite large) cost. And if no messages are sent through the bridge, that is just -waste of money. +Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory GRANDPA +header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it sees, will have to +pay a (quite large) cost. And if no messages are sent through the bridge, that is just waste of money. -We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions -that are required for the messages/confirmations delivery. This mode starts two message relays (in both -directions). All required finality relays are also started in a special _on-demand_ mode. In this mode they -do not submit any headers without special request. As always, the only exception is when GRANDPA finality -relay sees the mandatory header - it is submitted without such request. +We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions that are +required for the messages/confirmations delivery. This mode starts two message relays (in both directions). All required +finality relays are also started in a special _on-demand_ mode. In this mode they do not submit any headers without +special request. As always, the only exception is when GRANDPA finality relay sees the mandatory header - it is +submitted without such request. -The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations -to be delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and -then message relay may perform its job. If on-demand relay is a parachain finality relay, it also runs its -own on-demand GRANDPA relay, which is used to relay required relay chain headers. +The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations to be +delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and then message relay +may perform its job. If on-demand relay is a parachain finality relay, it also runs its own on-demand GRANDPA relay, +which is used to relay required relay chain headers. -More: [Complex Relay Sequence Diagram](./complex-relay.html), [code](../relays/bin-substrate/src/cli/relay_headers_and_messages/). +More: [Complex Relay Sequence Diagram](./complex-relay.html), +[code](../relays/bin-substrate/src/cli/relay_headers_and_messages/). diff --git a/cumulus/bridges/docs/polkadot-kusama-bridge-overview.md b/cumulus/bridges/docs/polkadot-kusama-bridge-overview.md index b469720f65b2..08036f0b0722 100644 --- a/cumulus/bridges/docs/polkadot-kusama-bridge-overview.md +++ b/cumulus/bridges/docs/polkadot-kusama-bridge-overview.md @@ -1,35 +1,35 @@ # Polkadot <> Kusama Bridge Overview -This document describes how we use all components, described in the [High-Level Bridge Documentation](./high-level-overview.md), -to build the XCM bridge between Kusama and Polkadot. In this case, our components merely work as a XCM transport -(like XCMP/UMP/HRMP), between chains that are not a part of the same consensus system. +This document describes how we use all components, described in the [High-Level Bridge +Documentation](./high-level-overview.md), to build the XCM bridge between Kusama and Polkadot. In this case, our +components merely work as a XCM transport (like XCMP/UMP/HRMP), between chains that are not a part of the same consensus +system. The overall architecture may be seen in [this diagram](./polkadot-kusama-bridge.html). ## Bridge Hubs -All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains. -That's why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama -Bridge Hub under Kusama consensus. +All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains. That's +why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama Bridge Hub under +Kusama consensus. -The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to -use our bridge hubs too and have their pallets there. +The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to use +our bridge hubs too and have their pallets there. -The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub. -The runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs. +The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub. The +runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs. ## Connecting Parachains -You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need -to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will -just queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. +You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need to +use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will just +queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. -Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two -parachains would allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama -accounts to hold wrapped DOT tokens. +Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two parachains would +allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama accounts to hold wrapped DOT tokens. -For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, -when other parachains will join the bridge, they will be using other lanes for their messages. +For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, when +other parachains will join the bridge, they will be using other lanes for their messages. ## Running Relayers @@ -38,9 +38,9 @@ justifications to the bridge hubs at the other side. It'll also relay finalized Hub heads. This will only happen when messages will be queued at hubs. So most of time relayer will be idle. There's no any active relayer sets, or something like that. Anyone may start its own relayer and relay queued messages. -We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost. -Apart from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have -a mechanism for rewarding relayers. +We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost. Apart +from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have a mechanism +for rewarding relayers. ### Compensating the Cost of Message Delivery Transactions @@ -56,51 +56,49 @@ is the relayer, which is following our rules: - we compensate the cost of message delivery transactions that have actually delivered the messages. So if your transaction has claimed to deliver messages `[42, 43, 44]`, but, because of some reasons, has actually delivered - messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then - the relayer pays the full cost of the transaction; + messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then the relayer + pays the full cost of the transaction; - we compensate the cost of message delivery and all required finality calls, if they are part of the same [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326) - transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used - to prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they - are not linked together, the relayer pays the full transaction cost. + transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used to + prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they are not + linked together, the relayer pays the full transaction cost. Please keep in mind that the fee of "zero-cost" transactions is still withdrawn from the relayer account. But the -compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer -may later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call. +compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer may +later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call. *A side note*: why we don't simply set the cost of useful transactions to zero? That's because the bridge has its cost. If we won't take any fees, it would mean that the sender is not obliged to pay for its messages. And Bridge Hub -collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later, -in the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section. +collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later, in +the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section. ### Message Delivery Confirmation Rewards In addition to the "zero-cost" message delivery transactions, the relayer is also rewarded for: -- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge - Hub.; +- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge Hub.; -- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms - delivery of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It - receives some fee for confirming messages, delivered by other relayers. +- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms delivery + of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It receives some fee + for confirming messages, delivered by other relayers. Both rewards may be claimed using the `pallet_bridge_relayers::claim_rewards` call at the Source Bridge Hub. ### Who is Rewarding Relayers Obviously, there should be someone who is paying relayer rewards. We want bridge transactions to have a cost, so we -can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides -of the bridge to cover relayer rewards. +can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides of the bridge +to cover relayer rewards. -Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will -have an account at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama -Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the -`pallet_bridge_relayers::claim_rewards`. +Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will have an account +at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama Bridge Hub. The sovereign accounts +are used as a source of funds when the relayer is calling the `pallet_bridge_relayers::claim_rewards`. -Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. -Kusama Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign account -is not used to cover rewards of bridging with some other Polkadot Parachain. +Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. Kusama +Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign +account is not used to cover rewards of bridging with some other Polkadot Parachain. ### Multiple Relayers and Rewards @@ -108,25 +106,24 @@ Our goal is to incentivize running honest relayers. But we have no relayers sets message delivery transaction, hoping that the cost of this transaction will be compensated. So what if some message is currently queued and two relayers are submitting two identical message delivery transactions at once? Without any special means, the cost of first included transaction will be compensated and the cost of the other one won't. A honest, -but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which -may be used by other useful transactions. +but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which may be +used by other useful transactions. -To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages! {}](../bin/runtime-common/src/lib.rs) -and [RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are -preventing bridge transactions with obsolete data from including into the block. We are rejecting following -transactions: +To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages! +{}](../bin/runtime-common/src/lib.rs) and +[RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are preventing +bridge transactions with obsolete data from including into the block. We are rejecting following transactions: - transactions, that are submitting the GRANDPA justification for the best finalized header, or one of its ancestors; - transactions, that are submitting the proof of the current best parachain head, or one of its ancestors; -- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered, - the transaction is not rejected; +- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered, the + transaction is not rejected; -- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new, - the transaction is not rejected; +- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new, the + transaction is not rejected; - [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326) - transactions, that have both finality and message delivery calls. All restrictions from the - [Compensating the Cost of Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions) - are applied. + transactions, that have both finality and message delivery calls. All restrictions from the [Compensating the Cost of + Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions) are applied. diff --git a/cumulus/bridges/modules/messages/README.md b/cumulus/bridges/modules/messages/README.md index b5250d0dca0b..457d5f5facfa 100644 --- a/cumulus/bridges/modules/messages/README.md +++ b/cumulus/bridges/modules/messages/README.md @@ -1,8 +1,7 @@ # Bridge Messages Pallet -The messages pallet is used to deliver messages from source chain to target chain. Message is -(almost) opaque to the module and the final goal is to hand message to the message dispatch -mechanism. +The messages pallet is used to deliver messages from source chain to target chain. Message is (almost) opaque to the +module and the final goal is to hand message to the message dispatch mechanism. ## Contents @@ -14,229 +13,203 @@ mechanism. ## Overview -Message lane is an unidirectional channel, where messages are sent from source chain to the target -chain. At the same time, a single instance of messages module supports both outbound lanes and -inbound lanes. So the chain where the module is deployed (this chain), may act as a source chain for -outbound messages (heading to a bridged chain) and as a target chain for inbound messages (coming -from a bridged chain). +Message lane is an unidirectional channel, where messages are sent from source chain to the target chain. At the same +time, a single instance of messages module supports both outbound lanes and inbound lanes. So the chain where the module +is deployed (this chain), may act as a source chain for outbound messages (heading to a bridged chain) and as a target +chain for inbound messages (coming from a bridged chain). -Messages module supports multiple message lanes. Every message lane is identified with a 4-byte -identifier. Messages sent through the lane are assigned unique (for this lane) increasing integer -value that is known as nonce ("number that can only be used once"). Messages that are sent over the -same lane are guaranteed to be delivered to the target chain in the same order they're sent from -the source chain. In other words, message with nonce `N` will be delivered right before delivering a -message with nonce `N+1`. +Messages module supports multiple message lanes. Every message lane is identified with a 4-byte identifier. Messages +sent through the lane are assigned unique (for this lane) increasing integer value that is known as nonce ("number that +can only be used once"). Messages that are sent over the same lane are guaranteed to be delivered to the target chain in +the same order they're sent from the source chain. In other words, message with nonce `N` will be delivered right before +delivering a message with nonce `N+1`. -Single message lane may be seen as a transport channel for single application (onchain, offchain or -mixed). At the same time the module itself never dictates any lane or message rules. In the end, it -is the runtime developer who defines what message lane and message mean for this runtime. +Single message lane may be seen as a transport channel for single application (onchain, offchain or mixed). At the same +time the module itself never dictates any lane or message rules. In the end, it is the runtime developer who defines +what message lane and message mean for this runtime. -In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane -as a channel of communication between two parachains of different relay chains. For example, lane -`[0, 0, 0, 0]` is used for Polkadot <> Kusama Asset Hub communications. Other lanes may be used to -bridge other parachains. +In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane as a channel of +communication between two parachains of different relay chains. For example, lane `[0, 0, 0, 0]` is used for Polkadot <> +Kusama Asset Hub communications. Other lanes may be used to bridge other parachains. ## Message Workflow -The pallet is not intended to be used by end users and provides no public calls to send the message. -Instead, it provides runtime-internal method that allows other pallets (or other runtime code) to queue -outbound messages. - -The message "appears" when some runtime code calls the `send_message()` method of the pallet. -The submitter specifies the lane that they're willing to use and the message itself. If some fee must -be paid for sending the message, it must be paid outside of the pallet. If a message passes all checks -(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and -the message is stored in the module storage. The message is in an "undelivered" state now. - -We assume that there are external, offchain actors, called relayers, that are submitting module -related transactions to both target and source chains. The pallet itself has no assumptions about -relayers incentivization scheme, but it has some callbacks for paying rewards. See -[Integrating Messages Module into runtime](#Integrating-Messages-Module-into-runtime) -for details. - -Eventually, some relayer would notice this message in the "undelivered" state and it would decide to -deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery -transaction) for the messages module instance, deployed at the target chain. Relayer provides -its account id at the source chain, the proof of message (or several messages), the number of -messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the -message is considered "delivered". - -Once a message is delivered, the relayer may want to confirm delivery back to the source chain. -There are two reasons why it would want to do that. The first is that we intentionally limit number -of "delivered", but not yet "confirmed" messages at inbound lanes -(see [What about other Constants in the Messages Module Configuration Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). -So at some point, the target chain may stop accepting new messages until relayers confirm some of -these. The second is that if the relayer wants to be rewarded for delivery, it must prove the fact -that it has actually delivered the message. And this proof may only be generated after the delivery -transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka -confirmation transaction) for the messages module instance, deployed at the source chain. Once -this transaction is mined, the message is considered "confirmed". - -The "confirmed" state is the final state of the message. But there's one last thing related to the -message - the fact that it is now "confirmed" and reward has been paid to the relayer (or at least -callback for this has been called), must be confirmed to the target chain. Otherwise, we may reach -the limit of "unconfirmed" messages at the target chain and it will stop accepting new messages. So -relayer sometimes includes a nonce of the latest "confirmed" message in the next +The pallet is not intended to be used by end users and provides no public calls to send the message. Instead, it +provides runtime-internal method that allows other pallets (or other runtime code) to queue outbound messages. + +The message "appears" when some runtime code calls the `send_message()` method of the pallet. The submitter specifies +the lane that they're willing to use and the message itself. If some fee must be paid for sending the message, it must +be paid outside of the pallet. If a message passes all checks (that include, for example, message size check, disabled +lane check, ...), the nonce is assigned and the message is stored in the module storage. The message is in an +"undelivered" state now. + +We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to +both target and source chains. The pallet itself has no assumptions about relayers incentivization scheme, but it has +some callbacks for paying rewards. See [Integrating Messages Module into +runtime](#Integrating-Messages-Module-into-runtime) for details. + +Eventually, some relayer would notice this message in the "undelivered" state and it would decide to deliver this +message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery transaction) for the messages module +instance, deployed at the target chain. Relayer provides its account id at the source chain, the proof of message (or +several messages), the number of messages in the transaction and their cumulative dispatch weight. Once a transaction is +mined, the message is considered "delivered". + +Once a message is delivered, the relayer may want to confirm delivery back to the source chain. There are two reasons +why it would want to do that. The first is that we intentionally limit number of "delivered", but not yet "confirmed" +messages at inbound lanes (see [What about other Constants in the Messages Module Configuration +Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). So at some point, the +target chain may stop accepting new messages until relayers confirm some of these. The second is that if the relayer +wants to be rewarded for delivery, it must prove the fact that it has actually delivered the message. And this proof may +only be generated after the delivery transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` +transaction (aka confirmation transaction) for the messages module instance, deployed at the source chain. Once this +transaction is mined, the message is considered "confirmed". + +The "confirmed" state is the final state of the message. But there's one last thing related to the message - the fact +that it is now "confirmed" and reward has been paid to the relayer (or at least callback for this has been called), must +be confirmed to the target chain. Otherwise, we may reach the limit of "unconfirmed" messages at the target chain and it +will stop accepting new messages. So relayer sometimes includes a nonce of the latest "confirmed" message in the next `receive_messages_proof()` transaction, proving that some messages have been confirmed. ## Integrating Messages Module into Runtime -As it has been said above, the messages module supports both outbound and inbound message lanes. -So if we will integrate a module in some runtime, it may act as the source chain runtime for -outbound messages and as the target chain runtime for inbound messages. In this section, we'll -sometimes refer to the chain we're currently integrating with, as "this chain" and the other -chain as "bridged chain". - -Messages module doesn't simply accept transactions that are claiming that the bridged chain has -some updated data for us. Instead of this, the module assumes that the bridged chain is able to -prove that updated data in some way. The proof is abstracted from the module and may be of any kind. -In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other bridges may use -transaction proofs, Substrate header digests or anything else that may be proved. - -**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module -configuration. But if you're interested in well-probed and relatively easy integration of two -Substrate-based chains, you may want to look at the -[bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of -helpers for integration, which may be directly used from within your runtime. Then if you'll decide -to change something in this scheme, get back here for detailed information. +As it has been said above, the messages module supports both outbound and inbound message lanes. So if we will integrate +a module in some runtime, it may act as the source chain runtime for outbound messages and as the target chain runtime +for inbound messages. In this section, we'll sometimes refer to the chain we're currently integrating with, as "this +chain" and the other chain as "bridged chain". + +Messages module doesn't simply accept transactions that are claiming that the bridged chain has some updated data for +us. Instead of this, the module assumes that the bridged chain is able to prove that updated data in some way. The proof +is abstracted from the module and may be of any kind. In our Substrate-to-Substrate bridge we're using runtime storage +proofs. Other bridges may use transaction proofs, Substrate header digests or anything else that may be proved. + +**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module configuration. But if +you're interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at +the [bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of helpers for integration, +which may be directly used from within your runtime. Then if you'll decide to change something in this scheme, get back +here for detailed information. ### General Information -The messages module supports instances. Every module instance is supposed to bridge this chain -and some bridged chain. To bridge with another chain, using another instance is suggested (this -isn't forced anywhere in the code, though). Keep in mind, that the pallet may be used to build -virtual channels between multiple chains, as we do in our [Polkadot <> Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). -There, the pallet actually bridges only two parachains - Kusama Bridge Hub and Polkadot -Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages to their -Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper +The messages module supports instances. Every module instance is supposed to bridge this chain and some bridged chain. +To bridge with another chain, using another instance is suggested (this isn't forced anywhere in the code, though). Keep +in mind, that the pallet may be used to build virtual channels between multiple chains, as we do in our [Polkadot <> +Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). There, the pallet actually bridges only two parachains - +Kusama Bridge Hub and Polkadot Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages +to their Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper destination parachain within the bridged chain consensus. -Message submitters may track message progress by inspecting module events. When Message is accepted, -the `MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that -has been assigned to the message. When a message is delivered to the target chain, the `MessagesDelivered` -event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains -the message lane identifier and inclusive range of delivered message nonces. +Message submitters may track message progress by inspecting module events. When Message is accepted, the +`MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that has been assigned to +the message. When a message is delivered to the target chain, the `MessagesDelivered` event is emitted from the +`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane identifier and +inclusive range of delivered message nonces. -The pallet provides no means to get the result of message dispatch at the target chain. If that is -required, it must be done outside of the pallet. For example, XCM messages, when dispatched, have -special instructions to send some data back to the sender. Other dispatchers may use similar -mechanism for that. +The pallet provides no means to get the result of message dispatch at the target chain. If that is required, it must be +done outside of the pallet. For example, XCM messages, when dispatched, have special instructions to send some data back +to the sender. Other dispatchers may use similar mechanism for that. ### How to plug-in Messages Module to Send Messages to the Bridged Chain? -The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with -outbound messages. The `pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the -bridged chain as the target for our outbound messages. It must be able to check that the bridged -chain may accept our message - like that the message has size below maximal possible transaction -size of the chain and so on. And when the relayer sends us a confirmation transaction, this -implementation must be able to parse and verify the proof of messages delivery. Normally, you would -reuse the same (configurable) type on all chains that are sending messages to the same bridged -chain. - -The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound -messages. The simplest callback may just accept all messages. But in this case you'll need to answer -many questions first. Who will pay for the delivery and confirmation transaction? Are we sure that -someone will ever deliver this message to the bridged chain? Are we sure that we don't bloat our -runtime storage by accepting this message? What if the message is improperly encoded or has some -fields set to invalid values? Answering all those (and similar) questions would lead to correct -implementation. +The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with outbound messages. The +`pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the bridged chain as the target for our outbound +messages. It must be able to check that the bridged chain may accept our message - like that the message has size below +maximal possible transaction size of the chain and so on. And when the relayer sends us a confirmation transaction, this +implementation must be able to parse and verify the proof of messages delivery. Normally, you would reuse the same +(configurable) type on all chains that are sending messages to the same bridged chain. + +The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The +simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will +pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the +bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is +improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to +correct implementation. There's another thing to consider when implementing type for use in -`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes -identically, or they'll have different sets of verification rules? For example, you may reserve -lane#1 for messages coming from some 'wrapped-token' pallet - then you may verify in your -implementation that the origin is associated with this pallet. Lane#2 may be reserved for 'system' -messages and you may charge zero fee for such messages. You may have some rate limiting for messages -sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is +`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll +have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some +'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet. +Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate +limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation. -The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation -transaction is received, we call the `pay_reward()` method, passing the range of delivered messages. -You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its -[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible -implementation. It allows you to pay fixed reward for relaying the message and some of its portion -for confirming delivery. +The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation transaction is +received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the +[`pallet-bridge-relayers`](../relayers/) pallet and its +[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible implementation. It +allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery. ### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? You should be looking at the `bp_messages::source_chain::ForbidOutboundMessages` structure -[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements -all required traits and will simply reject all transactions, related to outbound messages. +[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements all required traits and will +simply reject all transactions, related to outbound messages. ### How to plug-in Messages Module to Receive Messages from the Bridged Chain? -The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with -inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the -bridged chain as the source of our inbound messages. When relayer sends us a delivery transaction, -this implementation must be able to parse and verify the proof of messages wrapped in this -transaction. Normally, you would reuse the same (configurable) type on all chains that are sending -messages to the same bridged chain. +The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with inbound messages. The +`pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the bridged chain as the source of our inbound +messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof +of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are +sending messages to the same bridged chain. -The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered -messages. Apart from actually dispatching the message, the implementation must return the correct -dispatch weight of the message before dispatch is called. +The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered messages. Apart from +actually dispatching the message, the implementation must return the correct dispatch weight of the message before +dispatch is called. ### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do? -You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from -the [`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It -implements all required traits and will simply reject all transactions, related to inbound messages. +You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from the +[`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It implements all required traits +and will simply reject all transactions, related to inbound messages. ### What about other Constants in the Messages Module Configuration Trait? Two settings that are used to check messages in the `send_message()` function. The -`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that -may be used to send messages. All messages sent using other lanes are rejected. All messages that have -size above `pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected. - -To be able to reward the relayer for delivering messages, we store a map of message nonces range => -identifier of the relayer that has delivered this range at the target chain runtime storage. If a -relayer delivers multiple consequent ranges, they're merged into single entry. So there may be more -than one entry for the same relayer. Eventually, this whole map must be delivered back to the source -chain to confirm delivery and pay rewards. So to make sure we are able to craft this confirmation -transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure that -the weight of processing this map is below a certain limit. Both size and processing weight mostly -depend on the number of entries. The number of entries is limited with the -`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight -also depends on the total number of messages that are being confirmed, because every confirmed -message needs to be read. So there's another -`pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. - -When choosing values for these parameters, you must also keep in mind that if proof in your scheme -is based on finality of headers (and it is the most obvious option for Substrate-based chains with -finality notion), then choosing too small values for these parameters may cause significant delays -in message delivery. That's because there are too many actors involved in this scheme: 1) authorities -that are finalizing headers of the target chain need to finalize header with non-empty map; 2) the -headers relayer then needs to submit this header and its finality proof to the source chain; 3) the -messages relayer must then send confirmation transaction (storage proof of this map) to the source -chain; 4) when the confirmation transaction will be mined at some header, source chain authorities -must finalize this header; 5) the headers relay then needs to submit this header and its finality -proof to the target chain; 6) only now the messages relayer may submit new messages from the source -to target chain and prune the entry from the map. - -Delivery transaction requires the relayer to provide both number of entries and total number of -messages in the map. This means that the module never charges an extra cost for delivering a map - -the relayer would need to pay exactly for the number of entries+messages it has delivered. So the -best guess for values of these parameters would be the pair that would occupy `N` percent of the -maximal transaction size and weight of the source chain. The `N` should be large enough to process -large maps, at the same time keeping reserve for future source chain upgrades. +`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that may be used to send +messages. All messages sent using other lanes are rejected. All messages that have size above +`pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected. + +To be able to reward the relayer for delivering messages, we store a map of message nonces range => identifier of the +relayer that has delivered this range at the target chain runtime storage. If a relayer delivers multiple consequent +ranges, they're merged into single entry. So there may be more than one entry for the same relayer. Eventually, this +whole map must be delivered back to the source chain to confirm delivery and pay rewards. So to make sure we are able to +craft this confirmation transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure +that the weight of processing this map is below a certain limit. Both size and processing weight mostly depend on the +number of entries. The number of entries is limited with the +`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight also depends on +the total number of messages that are being confirmed, because every confirmed message needs to be read. So there's +another `pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. + +When choosing values for these parameters, you must also keep in mind that if proof in your scheme is based on finality +of headers (and it is the most obvious option for Substrate-based chains with finality notion), then choosing too small +values for these parameters may cause significant delays in message delivery. That's because there are too many actors +involved in this scheme: 1) authorities that are finalizing headers of the target chain need to finalize header with +non-empty map; 2) the headers relayer then needs to submit this header and its finality proof to the source chain; 3) +the messages relayer must then send confirmation transaction (storage proof of this map) to the source chain; 4) when +the confirmation transaction will be mined at some header, source chain authorities must finalize this header; 5) the +headers relay then needs to submit this header and its finality proof to the target chain; 6) only now the messages +relayer may submit new messages from the source to target chain and prune the entry from the map. + +Delivery transaction requires the relayer to provide both number of entries and total number of messages in the map. +This means that the module never charges an extra cost for delivering a map - the relayer would need to pay exactly for +the number of entries+messages it has delivered. So the best guess for values of these parameters would be the pair that +would occupy `N` percent of the maximal transaction size and weight of the source chain. The `N` should be large enough +to process large maps, at the same time keeping reserve for future source chain upgrades. ## Non-Essential Functionality -There may be a special account in every runtime where the messages module is deployed. This -account, named 'module owner', is like a module-level sudo account - he's able to halt and -resume all module operations without requiring runtime upgrade. Calls that are related to this -account are: +There may be a special account in every runtime where the messages module is deployed. This account, named 'module +owner', is like a module-level sudo account - he's able to halt and resume all module operations without requiring +runtime upgrade. Calls that are related to this account are: - `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; -- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all - module operations. After this call, all message-related transactions will be rejected until - further `resume_operations` call'. This call may be used when something extraordinary happens with - the bridge; -- `fn resume_operations()`: module owner may call this function to resume bridge operations. The - module will resume its regular operations after this call. +- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all module operations. After + this call, all message-related transactions will be rejected until further `resume_operations` call'. This call may be + used when something extraordinary happens with the bridge; +- `fn resume_operations()`: module owner may call this function to resume bridge operations. The module will resume its + regular operations after this call. If pallet owner is not defined, the governance may be used to make those calls. ## Messages Relay -We have an offchain actor, who is watching for new messages and submits them to the bridged chain. -It is the messages relay - you may look at the [crate level documentation and the code](../../relays/messages/). +We have an offchain actor, who is watching for new messages and submits them to the bridged chain. It is the messages +relay - you may look at the [crate level documentation and the code](../../relays/messages/). diff --git a/cumulus/bridges/modules/parachains/README.md b/cumulus/bridges/modules/parachains/README.md index 5982c65ad316..d3f52c791ab5 100644 --- a/cumulus/bridges/modules/parachains/README.md +++ b/cumulus/bridges/modules/parachains/README.md @@ -19,7 +19,7 @@ validators. Validators validate the block and register the new parachain head in [`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645) of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet, deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet, -even though the names are similar. +even though the names are similar. And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that `Heads` map. It does that using relay chain header, that has been previously imported by the diff --git a/cumulus/docs/container.md b/cumulus/docs/container.md index 63575f37a59b..ef7c52a44fab 100644 --- a/cumulus/docs/container.md +++ b/cumulus/docs/container.md @@ -1,19 +1,22 @@ -## Using Containers +# Using Containers -Using containers via **Podman** or **Docker** brings benefit, whether it is to build a container image or -run a node while keeping a minimum footprint on your local system. +Using containers via **Podman** or **Docker** brings benefit, whether it is to build a container image or run a node +while keeping a minimum footprint on your local system. -This document mentions using `podman` or `docker`. Those are usually interchangeable and it is encouraged using preferably **Podman**. If you have podman installed and want to use all the commands mentioned below, you can simply create an alias with `alias docker=podman`. +This document mentions using `podman` or `docker`. Those are usually interchangeable and it is encouraged using +preferably **Podman**. If you have podman installed and want to use all the commands mentioned below, you can simply +create an alias with `alias docker=podman`. There are a few options to build a node within a container and inject a binary inside an image. -### Parity built container image +## Parity built container image Parity builds and publishes a container image that can be found as `docker.io/parity/polkadot-parachain`. -### Parity CI image +## Parity CI image -Parity maintains and uses internally a generic "CI" image that can be used as a base to build binaries: [Parity CI container image](https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-linux): +Parity maintains and uses internally a generic "CI" image that can be used as a base to build binaries: [Parity CI +container image](https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-linux): The command below allows building a Linux binary without having to even install Rust or any dependency locally: @@ -29,19 +32,22 @@ sudo chown -R $(id -u):$(id -g) target/ If you want to reproduce other steps of CI process you can use the following [guide](https://github.com/paritytech/scripts#gitlab-ci-for-building-docker-images). -### Injected image +## Injected image -Injecting a binary inside a base image is the quickest option to get a working container image. This only works if you were able to build a Linux binary, either locally, or using a container as described above. +Injecting a binary inside a base image is the quickest option to get a working container image. This only works if you +were able to build a Linux binary, either locally, or using a container as described above. -After building a Linux binary ()`polkadot-parachain`) with cargo or with Parity CI image as documented above, the following command allows producing a new container image where the compiled binary is injected: +After building a Linux binary ()`polkadot-parachain`) with cargo or with Parity CI image as documented above, the +following command allows producing a new container image where the compiled binary is injected: ```bash ./docker/scripts/build-injected-image.sh ``` -### Container build +## Container build -Alternatively, you can build an image with a builder pattern. This options takes a while but offers a simple method for anyone to get a working container image without requiring any of the Rust toolchain installed locally. +Alternatively, you can build an image with a builder pattern. This options takes a while but offers a simple method for +anyone to get a working container image without requiring any of the Rust toolchain installed locally. ```bash docker build \ diff --git a/cumulus/docs/release.md b/cumulus/docs/release.md index b04c4e844c4e..38d1915013b0 100644 --- a/cumulus/docs/release.md +++ b/cumulus/docs/release.md @@ -37,8 +37,8 @@ performed during the release process. ### Burn In -Ensure that Parity DevOps has run the new release on Westend and Kusama Asset Hub collators for 12h -prior to publishing the release. +Ensure that Parity DevOps has run the new release on Westend and Kusama Asset Hub collators for 12h prior to publishing +the release. ### Build Artifacts @@ -75,56 +75,61 @@ function of the appropriate pallets. ### Extrinsic Ordering & Storage -Offline signing libraries depend on a consistent ordering of call indices and -functions. Compare the metadata of the current and new runtimes and ensure that -the `module index, call index` tuples map to the same set of functions. It also checks if there have been any changes in `storage`. In case of a breaking change, increase `transaction_version`. +Offline signing libraries depend on a consistent ordering of call indices and functions. Compare the metadata of the +current and new runtimes and ensure that the `module index, call index` tuples map to the same set of functions. It also +checks if there have been any changes in `storage`. In case of a breaking change, increase `transaction_version`. -To verify the order has not changed, manually start the following [Github Action](https://github.com/paritytech/cumulus/actions/workflows/extrinsic-ordering-check-from-bin.yml). It takes around a minute to run and will produce the report as artifact you need to manually check. +To verify the order has not changed, manually start the following [Github +Action](https://github.com/paritytech/cumulus/actions/workflows/extrinsic-ordering-check-from-bin.yml). It takes around +a minute to run and will produce the report as artifact you need to manually check. To run it, in the _Run Workflow_ dropdown: 1. **Use workflow from**: to ignore, leave `master` as default -2. **The WebSocket url of the reference node**: - - Asset Hub Polkadot: `wss://statemint-rpc.polkadot.io` +2. **The WebSocket url of the reference node**: - Asset Hub Polkadot: `wss://statemint-rpc.polkadot.io` - Asset Hub Kusama: `wss://statemine-rpc.polkadot.io` - Asset Hub Westend: `wss://westmint-rpc.polkadot.io` -3. **A url to a Linux binary for the node containing the runtime to test**: Paste the URL of the latest release-candidate binary from the draft-release on Github. The binary has to previously be uploaded to S3 (Github url link to the binary is constantly changing) +3. **A url to a Linux binary for the node containing the runtime to test**: Paste the URL of the latest + release-candidate binary from the draft-release on Github. The binary has to previously be uploaded to S3 (Github url + link to the binary is constantly changing) - E.g: https://releases.parity.io/cumulus/v0.9.270-rc3/polkadot-parachain -4. **The name of the chain under test. Usually, you would pass a local chain**: - - Asset Hub Polkadot: `asset-hub-polkadot-local` +4. **The name of the chain under test. Usually, you would pass a local chain**: - Asset Hub Polkadot: + `asset-hub-polkadot-local` - Asset Hub Kusama: `asset-hub-kusama-local` - Asset Hub Westend: `asset-hub-westend-local` 5. Click **Run workflow** -When the workflow is done, click on it and download the zip artifact, inside you'll find an `output.txt` file. The things to look for in the output are lines like: +When the workflow is done, click on it and download the zip artifact, inside you'll find an `output.txt` file. The +things to look for in the output are lines like: - `[Identity] idx 28 -> 25 (calls 15)` - indicates the index for Identity has changed - `[+] Society, Recovery` - indicates the new version includes 2 additional modules/pallets. - If no indices have changed, every modules line should look something like `[Identity] idx 25 (calls 15)` -**Note**: Adding new functions to the runtime does not constitute a breaking change -as long as the indexes did not change. +**Note**: Adding new functions to the runtime does not constitute a breaking change as long as the indexes did not +change. -**Note**: Extrinsic function signatures changes (adding/removing & ordering arguments) are not caught by the job, so those changes should be reviewed "manually" +**Note**: Extrinsic function signatures changes (adding/removing & ordering arguments) are not caught by the job, so +those changes should be reviewed "manually" ### Benchmarks -The Benchmarks can now be started from the CI. First find the CI pipeline from [here](https://gitlab.parity.io/parity/mirrors/cumulus/-/pipelines?page=1&scope=all&ref=release-parachains-v9220) and pick the latest. -[Guide](https://github.com/paritytech/ci_cd/wiki/Benchmarks:-cumulus) +The Benchmarks can now be started from the CI. First find the CI pipeline from +[here](https://gitlab.parity.io/parity/mirrors/cumulus/-/pipelines?page=1&scope=all&ref=release-parachains-v9220) and +pick the latest. [Guide](https://github.com/paritytech/ci_cd/wiki/Benchmarks:-cumulus) ### Integration Tests Until https://github.com/paritytech/ci_cd/issues/499 is done, tests will have to be run manually. -1. Go to https://github.com/paritytech/parachains-integration-tests and check out the release branch. -E.g. https://github.com/paritytech/parachains-integration-tests/tree/release-v9270-v0.9.27 -for `release-parachains-v0.9.270` +1. Go to https://github.com/paritytech/parachains-integration-tests and check out the release branch. E.g. +https://github.com/paritytech/parachains-integration-tests/tree/release-v9270-v0.9.27 for `release-parachains-v0.9.270` 2. Clone `release-parachains-` branch from Cumulus 3. `cargo build --release` 4. Copy `./target/polkadot-parachain` to `./bin` -5. Clone `it/release--fast-sudo` from Polkadot -In case the branch does not exists (it is a manual process): cherry pick paritytech/polkadot@791c8b8 and run -`find . -type f -name "*.toml" -print0 | xargs -0 sed -i '' -e 's/polkadot-vX.X.X/polkadot-v/g'` +5. Clone `it/release--fast-sudo` from Polkadot In case the branch does not exists (it is a manual process): + cherry pick `paritytech/polkadot@791c8b8` and run: + `find . -type f -name "*.toml" -print0 | xargs -0 sed -i '' -e 's/polkadot-vX.X.X/polkadot-v/g'` 6. `cargo build --release --features fast-runtime` 7. Copy `./target/polkadot` into `./bin` (in Cumulus) 8. Run the tests: - - Asset Hub Polkadot: `yarn zombienet-test -c ./examples/statemint/config.toml -t ./examples/statemint` - - Asset Hub Kusama: `yarn zombienet-test -c ./examples/statemine/config.toml -t ./examples/statemine` + - Asset Hub Polkadot: `yarn zombienet-test -c ./examples/statemint/config.toml -t ./examples/statemint` + - Asset Hub Kusama: `yarn zombienet-test -c ./examples/statemine/config.toml -t ./examples/statemine` diff --git a/cumulus/pallets/collator-selection/README.md b/cumulus/pallets/collator-selection/README.md index 9718db58b37e..811207fd8c0f 100644 --- a/cumulus/pallets/collator-selection/README.md +++ b/cumulus/pallets/collator-selection/README.md @@ -1 +1 @@ -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/cumulus/parachain-template/README.md b/cumulus/parachain-template/README.md index 6dcc70c53829..2d71bbd71f36 100644 --- a/cumulus/parachain-template/README.md +++ b/cumulus/parachain-template/README.md @@ -19,4 +19,4 @@ parathreads [here](https://wiki.polkadot.network/docs/learn-parathreads). 🧙 Learn about how to use this template and run your own parachain testnet for it in the -[Devhub Cumulus Tutorial](https://docs.substrate.io/tutorials/v3/cumulus/start-relay/). \ No newline at end of file +[Devhub Cumulus Tutorial](https://docs.substrate.io/tutorials/v3/cumulus/start-relay/). diff --git a/cumulus/parachains/integration-tests/e2e/collectives/README.md b/cumulus/parachains/integration-tests/e2e/collectives/README.md index 98ea77aac606..9c4efe7c9504 100644 --- a/cumulus/parachains/integration-tests/e2e/collectives/README.md +++ b/cumulus/parachains/integration-tests/e2e/collectives/README.md @@ -1,19 +1,23 @@ -E2E tests concerning Polkadot Governance and the Collectives Parachain. The tests run by the Parachain Integration Tests [tool](https://github.com/paritytech/parachains-integration-tests/). +E2E tests concerning Polkadot Governance and the Collectives Parachain. The tests run by the Parachain Integration Tests +[tool](https://github.com/paritytech/parachains-integration-tests/). -## Requirements +# Requirements The tests require some changes to the regular production runtime builds: -RelayChain runtime: +## RelayChain runtime 1. Alice has SUDO -2. Public Referenda `StakingAdmin`, `FellowshipAdmin` tracks settings (see the corresponding keys of the `TRACKS_DATA` constant in the `governance::tracks` module of the Relay Chain runtime crate): +2. Public Referenda `StakingAdmin`, `FellowshipAdmin` tracks settings (see the corresponding keys of the `TRACKS_DATA` + constant in the `governance::tracks` module of the Relay Chain runtime crate): ``` yaml prepare_period: 5 Block, decision_period: 1 Block, confirm_period: 1 Block, min_enactment_period: 1 Block, ``` -Collectives runtime: -1. Fellowship Referenda `Fellows` track settings (see the corresponding key of the `TRACKS_DATA` constant in the `fellowship::tracks` module of the Collectives runtime crate): + +## Collectives runtime +1. Fellowship Referenda `Fellows` track settings (see the corresponding key of the `TRACKS_DATA` constant in the + `fellowship::tracks` module of the Collectives runtime crate): ``` yaml prepare_period: 5 Block, decision_period: 1 Block, diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index 1520065b7e3a..487c601ef840 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -1,26 +1,26 @@ - [Bridge-hub Parachains](#bridge-hub-parachains) - * [Requirements for local run/testing](#requirements-for-local-runtesting) - * [How to test local Rococo <-> Wococo bridge](#how-to-test-local-rococo---wococo-bridge) - + [Run chains (Rococo + BridgeHub, Wococo + BridgeHub) with zombienet](#run-chains-rococo--bridgehub-wococo--bridgehub-with-zombienet) - + [Run relayer (BridgeHubRococo, BridgeHubWococo)](#run-relayer-bridgehubrococo-bridgehubwococo) + - [Requirements for local run/testing](#requirements-for-local-runtesting) + - [How to test local Rococo <-> Wococo bridge](#how-to-test-local-rococo---wococo-bridge) + - [Run chains (Rococo + BridgeHub, Wococo + BridgeHub) with + zombienet](#run-chains-rococo--bridgehub-wococo--bridgehub-with-zombienet) + - [Run relayer (BridgeHubRococo, BridgeHubWococo)](#run-relayer-bridgehubrococo-bridgehubwococo) - [Run with script (alternative 1)](#run-with-script-alternative-1) - [Run with binary (alternative 2)](#run-with-binary-alternative-2) - + [Send messages - transfer asset over bridge](#send-messages---transfer-asset-over-bridge) - * [How to test live BridgeHubRococo/BridgeHubWococo](#how-to-test-live-bridgehubrococobridgehubwococo) - * [How to test local BridgeHubKusama/BridgeHubPolkadot](#how-to-test-local-bridgehubkusamabridgehubpolkadot) + - [Send messages - transfer asset over bridge](#send-messages---transfer-asset-over-bridge) + - [How to test live BridgeHubRococo/BridgeHubWococo](#how-to-test-live-bridgehubrococobridgehubwococo) + - [How to test local BridgeHubKusama/BridgeHubPolkadot](#how-to-test-local-bridgehubkusamabridgehubpolkadot) # Bridge-hub Parachains -_BridgeHub(s)_ are **_system parachains_** that will house trustless bridges from the local -ecosystem to others. -The current trustless bridges planned for the BridgeHub(s) are: +_BridgeHub(s)_ are **_system parachains_** that will house trustless bridges from the local ecosystem to others. The +current trustless bridges planned for the BridgeHub(s) are: - `BridgeHubPolkadot` system parachain: 1. Polkadot <-> Kusama bridge 2. Polkadot <-> Ethereum bridge (Snowbridge) - `BridgeHubKusama` system parachain: 1. Kusama <-> Polkadot bridge - 2. Kusama <-> Ethereum bridge - The high-level responsibilities of each bridge living on BridgeHub: + 2. Kusama <-> Ethereum bridge The high-level + responsibilities of each bridge living on BridgeHub: - sync finality proofs between relay chains (or equivalent) - sync finality proofs between BridgeHub parachains - pass (XCM) messages between different BridgeHub parachains @@ -192,43 +192,40 @@ RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ ``` **Check relay-chain headers relaying:** -- Rococo parachain: - - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8943#/chainstate - - Pallet: **bridgeWococoGrandpa** - - Keys: **bestFinalized()** -- Wococo parachain: - - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8945#/chainstate - - Pallet: **bridgeRococoGrandpa** - - Keys: **bestFinalized()** +- Rococo parachain: - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8943#/chainstate - Pallet: + **bridgeWococoGrandpa** - Keys: **bestFinalized()** +- Wococo parachain: - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8945#/chainstate - Pallet: + **bridgeRococoGrandpa** - Keys: **bestFinalized()** **Check parachain headers relaying:** -- Rococo parachain: - - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8943#/chainstate - - Pallet: **bridgeWococoParachain** - - Keys: **bestParaHeads()** -- Wococo parachain: - - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8945#/chainstate - - Pallet: **bridgeRococoParachain** - - Keys: **bestParaHeads()** +- Rococo parachain: - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8943#/chainstate - Pallet: + **bridgeWococoParachain** - Keys: **bestParaHeads()** +- Wococo parachain: - https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A8945#/chainstate - Pallet: + **bridgeRococoParachain** - Keys: **bestParaHeads()** ### Send messages - transfer asset over bridge TODO: see `# !!! READ HERE` above ## How to test live BridgeHubRococo/BridgeHubWococo -(here is still deployed older PoC from branch `origin/bko-transfer-asset-via-bridge`, which uses custom extrinsic, which is going to be replaced by `pallet_xcm` usage) +(here is still deployed older PoC from branch `origin/bko-transfer-asset-via-bridge`, which uses custom extrinsic, which +is going to be replaced by `pallet_xcm` usage) - uses account seed on Live Rococo:Rockmine2 ``` cd ./scripts/bridges_rococo_wococo.sh transfer-asset-from-asset-hub-rococo ``` -- open explorers: - - Rockmine2 (see events `xcmpQueue.XcmpMessageSent`, `bridgeTransfer.ReserveAssetsDeposited`, `bridgeTransfer.TransferInitiated`) https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fws-rococo-rockmine2-collator-node-0.parity-testnet.parity.io#/explorer - - BridgeHubRococo (see `bridgeWococoMessages.MessageAccepted`) https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-bridge-hub-rpc.polkadot.io#/explorer - - BridgeHubWococo (see `bridgeRococoMessages.MessagesReceived`) https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwococo-bridge-hub-rpc.polkadot.io#/explorer - - Wockmint (see `xcmpQueue.Success` for `transfer-asset` and `xcmpQueue.Fail` for `ping-via-bridge`) https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwococo-wockmint-rpc.polkadot.io#/explorer - - BridgeHubRococo (see `bridgeWococoMessages.MessagesDelivered`) +- open explorers: - Rockmine2 (see events `xcmpQueue.XcmpMessageSent`, `bridgeTransfer.ReserveAssetsDeposited`, + `bridgeTransfer.TransferInitiated`) + https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fws-rococo-rockmine2-collator-node-0.parity-testnet.parity.io#/explorer + - BridgeHubRococo (see `bridgeWococoMessages.MessageAccepted`) + https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-bridge-hub-rpc.polkadot.io#/explorer - BridgeHubWococo (see + `bridgeRococoMessages.MessagesReceived`) + https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwococo-bridge-hub-rpc.polkadot.io#/explorer - Wockmint (see + `xcmpQueue.Success` for `transfer-asset` and `xcmpQueue.Fail` for `ping-via-bridge`) + https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwococo-wockmint-rpc.polkadot.io#/explorer - BridgeHubRococo (see + `bridgeWococoMessages.MessagesDelivered`) ## How to test local BridgeHubKusama/BridgeHubPolkadot diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/README.md b/cumulus/parachains/runtimes/contracts/contracts-rococo/README.md index e4f15ccf92d6..387bb24bb0e0 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/README.md +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/README.md @@ -33,8 +33,8 @@ There are also different user interfaces and command-line tools you can use to d or interact with contracts: * [Contracts UI](https://paritytech.github.io/contracts-ui/) ‒ a beginner-friendly UI for smart contract developers. -* [polkadot-js](https://polkadot.js.org/apps/) ‒ the go-to expert UI for smart contract developers. -* [cargo-contract](https://github.com/paritytech/cargo-contract) ‒ a CLI tool, ideal for scripting or your terminal workflow. +* [`polkadot-js`](https://polkadot.js.org/apps/) ‒ the go-to expert UI for smart contract developers. +* [`cargo-contract`](https://github.com/paritytech/cargo-contract) ‒ a CLI tool, ideal for scripting or your terminal workflow. If you are looking for a quickstart, we can recommend [ink!'s Guided Tutorial for Beginners](https://docs.substrate.io/tutorials/v3/ink-workshop/pt1/). diff --git a/cumulus/scripts/ci/changelog/README.md b/cumulus/scripts/ci/changelog/README.md new file mode 100644 index 000000000000..e274b4919473 --- /dev/null +++ b/cumulus/scripts/ci/changelog/README.md @@ -0,0 +1,77 @@ +# Changelog + +Currently, the changelog is built locally. It will be moved to CI once labels stabilize. + +For now, a bit of preparation is required before you can run the script: +- fetch the srtool digests +- store them under the `digests` folder as `-srtool-digest.json` +- ensure the `.env` file is up to date with correct information + +The content of the release notes is generated from the template files under the `scripts/ci/changelog/templates` folder. +For readability and maintenance, the template is split into several small snippets. + +Run: +``` +./bin/changelog [=HEAD] +``` + +For instance: +``` +./bin/changelog parachains-v7.0.0-rc8 +``` + +A file called `release-notes.md` will be generated and can be used for the release. + +## ENV + +You may use the following ENV for testing: + +``` +RUSTC_STABLE="rustc 1.56.1 (59eed8a2a 2021-11-01)" +RUSTC_NIGHTLY="rustc 1.57.0-nightly (51e514c0f 2021-09-12)" +PRE_RELEASE=true +HIDE_SRTOOL_ROCOCO=true +HIDE_SRTOOL_SHELL=true +REF1=statemine-v5.0.0 +REF2=HEAD +DEBUG=1 +NO_CACHE=1 +``` + +By default, the template will include all the information, including the runtime data. For clients releases, we don't +need those and they can be skipped by setting the following env: +``` +RELEASE_TYPE=client +``` + +## Considered labels + +The following list will likely evolve over time and it will be hard to keep it in sync. In any case, if you want to find +all the labels that are used, search for `meta` in the templates. Currently, the considered labels are: + +- Priority: C labels +- Audit: D labels +- E4 => new host function +- B0 => silent, not showing up +- B1-releasenotes (misc unless other labels) +- B5-client (client changes) +- B7-runtimenoteworthy (runtime changes) +- T6-XCM + +Note that labels with the same letter are mutually exclusive. A PR should not have both `B0` and `B5`, or both `C1` and +`C9`. In case of conflicts, the template will decide which label will be considered. + +## Dev and debuggin + +### Hot Reload + +The following command allows **Hot Reload**: +``` +fswatch templates -e ".*\.md$" | xargs -n1 -I{} ./bin/changelog statemine-v5.0.0 +``` +### Caching + +By default, if the changelog data from Github is already present, the calls to the Github API will be skipped and the +local version of the data will be used. This is much faster. If you know that some labels have changed in Github, you +probably want to refresh the data. You can then either delete manually the `cumulus.json` file or `export NO_CACHE=1` to +force refreshing the data. diff --git a/cumulus/xcm/xcm-emulator/README.md b/cumulus/xcm/xcm-emulator/README.md index d188c99eecfc..2a861a9d269b 100644 --- a/cumulus/xcm/xcm-emulator/README.md +++ b/cumulus/xcm/xcm-emulator/README.md @@ -13,11 +13,11 @@ As the messages do not physically go through the same messaging infrastructure there is some code that is not being tested compared to using slower E2E tests. In future it may be possible to run these XCM emulated tests as E2E tests (without changes). -As well as the XCM message transport being mocked out, so too are areas around consensus, +As well as the XCM message transport being mocked out, so too are areas around consensus, in particular things like disputes, staking and iamonline events can't be tested. ## Alternatives If you just wish to test execution of various XCM instructions -against the XCM VM then the `xcm-simulator` (in the polkadot +against the XCM VM then the `xcm-simulator` (in the Polkadot repo) is the perfect tool for this. diff --git a/cumulus/zombienet/tests/0007-prepare-warp-sync-db-snapshot.md b/cumulus/zombienet/tests/0007-prepare-warp-sync-db-snapshot.md index 7885dd0c0269..373e48072380 100644 --- a/cumulus/zombienet/tests/0007-prepare-warp-sync-db-snapshot.md +++ b/cumulus/zombienet/tests/0007-prepare-warp-sync-db-snapshot.md @@ -1,22 +1,24 @@ # Database snapshot guide -For this guide we will be taking a snapshot of a parachain and relay chain. Please note we are using a local chain here `rococo_local_testnet` and `local_testnet`. Live chains will have different values +For this guide we will be taking a snapshot of a parachain and relay chain. Please note we are using a local chain here +`rococo_local_testnet` and `local_testnet`. Live chains will have different values *Please ensure that the database is not in current use, i.e no nodes are writing to it* # How to prepare database for a relaychain -To prepare snapshot for a relay chain we need to copy the database. +To prepare snapshot for a relay chain we need to copy the database. ``` mkdir -p relaychain-snapshot/alice/data/chains/rococo_local_testnet/db/ -cp -r chain-data/alice/data/chains/rococo_local_testnet/db/. relaychain-snapshot/alice/data/chains/rococo_local_testnet/db/ +cp -r chain-data/alice/data/chains/rococo_local_testnet/db/. relaychain-snapshot/alice/data/chains/rococo_local_testnet/db/ tar -C relaychain-snapshot/alice/ -czf relaychain.tgz data ``` # How to prepare database for a parachain -To prepare snapshot for a parachain we need to copy the database for both the collator node (parachain data) and validator (relay data) +To prepare snapshot for a parachain we need to copy the database for both the collator node (parachain data) and +validator (relay data) ``` #Parachain data @@ -33,5 +35,6 @@ tar -C parachain-snapshot/charlie/ -czf parachain.tgz data relay-data ``` # Restoring a snapshot -Zombienet will automatically download the `*.tgz` file to the respective folder for a run. However you can also download it manually, just ensure you extract the tar file in the correct directory, i.e. the root directory -`chain-data/charlie/` \ No newline at end of file +Zombienet will automatically download the `*.tgz` file to the respective folder for a run. However you can also download +it manually, just ensure you extract the tar file in the correct directory, i.e. the root directory +`chain-data/charlie/` diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 5e892625fb77..20fa1d3a768b 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -32,11 +32,11 @@ If it is an urgent fix with no large change to logic, then it may be merged afte contributor has reviewed it well and approved the review once CI is complete. No PR should be merged until all reviews' comments are addressed. -### Labels: +### Labels The set of labels and their description can be found [here](https://paritytech.github.io/labels/doc_polkadot-sdk.html). -### Process: +### Process 1. Please use our [Pull Request Template](./PULL_REQUEST_TEMPLATE.md) and make sure all relevant information is reflected in your PR. @@ -50,12 +50,12 @@ The set of labels and their description can be found [here](https://paritytech.g `T13-documentation`. The docs team will get in touch. 5. If your PR changes files in these paths: - `polkadot` : '^runtime/polkadot' - `polkadot` : '^runtime/kusama' - `polkadot` : '^primitives/src/' - `polkadot` : '^runtime/common' - `substrate` : '^frame/' - `substrate` : '^primitives/' + `polkadot` : `^runtime/polkadot` + `polkadot` : `^runtime/kusama` + `polkadot` : `^primitives/src/` + `polkadot` : `^runtime/common` + `substrate` : `^frame/` + `substrate` : `^primitives/` It should be added to the [security audit board](https://github.com/orgs/paritytech/projects/103) and will need to undergo an audit before merge. @@ -67,7 +67,7 @@ to change the code to make it work/compile. It should also mention potential storage migrations and if they require some special setup aside adding it to the list of migrations in the runtime. -## Reviewing pull requests: +## Reviewing pull requests When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews should finish with approval unless there are issues that would result in: diff --git a/docs/DOCUMENTATION_GUIDELINE.md b/docs/DOCUMENTATION_GUIDELINE.md index 823617329590..f6c8cac7cd2a 100644 --- a/docs/DOCUMENTATION_GUIDELINE.md +++ b/docs/DOCUMENTATION_GUIDELINE.md @@ -1,11 +1,10 @@ # Substrate Documentation Guidelines -This document is focused on documenting parts of substrate that relate to its -external API. The list of such crates can be found in [CODEOWNERS](./CODEOWNERS). -Search for the crates auto-assigned to the `docs-audit` team. +This document is focused on documenting parts of Substrate that relate to its external API. The list of such crates can +be found in [CODEOWNERS](./CODEOWNERS). Search for the crates auto-assigned to the `docs-audit` team. -These crates are used by external developers and need thorough documentation. -They are the most concerned with FRAME development. +These crates are used by external developers and need thorough documentation. They are the most concerned with FRAME +development. - [Substrate Documentation Guidelines](#substrate-documentation-guidelines) - [General/Non-Pallet Crates](#generalnon-pallet-crates) @@ -35,22 +34,19 @@ First, consider the case for all such crates, except for those that are pallets. The first question is, what should you document? Use this filter: 1. In the crates assigned to `docs-audit` in [CODEOWNERS](./CODEOWNERS), -2. All `pub` items need to be documented. If not `pub`, it doesn't appear in the -rust-docs, and is not public facing. +2. All `pub` items need to be documented. If not `pub`, it doesn't appear in the rust-docs, and is not public facing. - * Within `pub` items, sometimes they are only `pub` to be used by another - internal crate, and you can foresee that this won't be used by anyone else. - These need **not** be documented thoroughly. + - Within `pub` items, sometimes they are only `pub` to be used by another internal crate, and you can foresee that + this won't be used by anyone else. These need **not** be documented thoroughly. - * Reminder: `trait` items are public by definition if the trait is public. + - Reminder: `trait` items are public by definition if the trait is public. 3. All public modules (`mod`) should have reasonable module-level documentation (`//!`). #### Rust Docs vs. Code Comments -Note that anything starting with `///` is an external rust-doc, and everything -starting with `//` does not appear in the rust-docs. -It's important to not confuse the two in your documentation. +Note that anything starting with `///` is an external rust-doc, and everything starting with `//` does not appear in the +rust-docs. It's important to not confuse the two in your documentation. ```rust /// Computes the square root of the input, returning `Ok(_)` if successful. @@ -73,100 +69,88 @@ pub fn sqrt(x: u32) -> Result { There are good sources to look into: - [Rust Documentation Guide](https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html) -- [Documentation in Rust Book](https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments) -- [Guide on Writing Documentation for a Rust Crate](https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate) - -As mentioned [here](https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/documentation.html#writing-documentation-comments) and [here](https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate), -always start with a **single sentence** demonstrating what is documented. All additional -documentation should be added *after a newline*. Strive to make the first sentence succinct -and short.The reason for this is the first paragraph of docs about an item (everything -before the first newline) is used as the excerpt that rust doc displays about -this item when it appears in tables, such as the table listing all functions in -a module. If this excerpt is too long, the module docs will be very difficult -to read. - -About [special sections](https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/documentation.html#special-sections), we will most likely not need to think about panic and safety in any runtime related code. Our code is never `unsafe`, and will (almost) never panic. - -Use `# Examples as much as possible. These are great ways to further -demonstrate what your APIs are doing, and add free test coverage. As an -additional benefit, any code in rust-docs is treated as an "integration tests", -not unit tests, which tests your crate in a different way than unit tests. So, -it is both a win for "more documentation" and a win for "more test coverage". - -You can also consider having an `# Error` section optionally. Of course, this -only applies if there is a `Result` being returned, and if the `Error` variants -are overly complicated. - -Strive to include correct links to other items in your written docs as much as -possible. In other words, avoid \`some_func\` and instead use \[\`some_fund\`\]. -Read more about how to correctly use links in your rust-docs -[here](https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html#valid-links) -and [here](https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html#additions-to-the-documentation-syntax). -Strive to include correct links to other items in your written docs as much as -possible. In other words, avoid `` `some_func` `` and instead use -``[`some_func`]``. - -> While you are linking, you might become conscious of the fact that you are -in need of linking to (too many) foreign items in order to explain your API. -This is leaning more towards API-Design rather than documentation, but it is a -warning that the subject API might be slightly wrong. For example, most "glue" -traits[^1] in `frame/support` should be designed and documented without making -hard assumptions about particular pallets that implement them. +- [Documentation in Rust + Book](https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments) +- [Guide on Writing Documentation for a Rust + Crate](https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate) + +As mentioned +[here](https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/documentation.html#writing-documentation-comments) +and [here](https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate), +always start with a **single sentence** demonstrating what is documented. All additional documentation should be added +*after a newline*. Strive to make the first sentence succinct and short.The reason for this is the first paragraph of +docs about an item (everything before the first newline) is used as the excerpt that rust doc displays about this item +when it appears in tables, such as the table listing all functions in a module. If this excerpt is too long, the module +docs will be very difficult to read. + +About [special +sections](https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/documentation.html#special-sections), +we will most likely not need to think about panic and safety in any runtime related code. Our code is never `unsafe`, +and will (almost) never panic. + +Use `# Examples as much as possible. These are great ways to further demonstrate what your APIs are doing, and add free +test coverage. As an additional benefit, any code in rust-docs is treated as an "integration tests", not unit tests, +which tests your crate in a different way than unit tests. So, it is both a win for "more documentation" and a win for +"more test coverage". + +You can also consider having an `# Error` section optionally. Of course, this only applies if there is a `Result` being +returned, and if the `Error` variants are overly complicated. + +Strive to include correct links to other items in your written docs as much as possible. In other words, avoid +\`some_func\` and instead use \[\`some_fund\`\]. Read more about how to correctly use links in your rust-docs +[here](https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html#valid-links) and +[here](https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html#additions-to-the-documentation-syntax). Strive to +include correct links to other items in your written docs as much as possible. In other words, avoid `` `some_func` `` +and instead use ``[`some_func`]``. + +> While you are linking, you might become conscious of the fact that you are in need of linking to (too many) foreign +items in order to explain your API. This is leaning more towards API-Design rather than documentation, but it is a +warning that the subject API might be slightly wrong. For example, most "glue" traits[^1] in `frame/support` should be +designed and documented without making hard assumptions about particular pallets that implement them. --- #### TLDR -0. Have the goal of enforcing `#![deny(missing_docs)]` mentally, even if it is -not enforced by the compiler 🙈. -1. Start with a single, clear and concise sentence. Follow up with more context, -after a newline, if needed. +0. Have the goal of enforcing `#![deny(missing_docs)]` mentally, even if it is not enforced by the compiler 🙈. +1. Start with a single, clear and concise sentence. Follow up with more context, after a newline, if needed. 2. Use examples as much as reasonably possible. 3. Use links as much as possible. -4. Think about context. If you are explaining a lot of foreign topics while -documenting a trait that should not explicitly depend on them, you have likely -not designed it properly. +4. Think about context. If you are explaining a lot of foreign topics while documenting a trait that should not +explicitly depend on them, you have likely not designed it properly. --- #### Proc-Macros -Note that there are special considerations when documenting proc macros. Doc -links will appear to function _within_ your proc macro crate, but often will no -longer function when these proc macros are re-exported elsewhere in your -project. The exception is doc links to _other proc macros_ which will function -just fine if they are also being re-exported. It is also often necessary to -disambiguate between a proc macro and a function of the same name, which can be -done using the `macro@my_macro_name` syntax in your link. Read more about how to -correctly use links in your rust-docs [here](https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html#valid-links) -and [here](https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html#additions-to-the-documentation-syntax). +Note that there are special considerations when documenting proc macros. Doc links will appear to function _within_ your +proc macro crate, but often will no longer function when these proc macros are re-exported elsewhere in your project. +The exception is doc links to _other proc macros_ which will function just fine if they are also being re-exported. It +is also often necessary to disambiguate between a proc macro and a function of the same name, which can be done using +the `macro@my_macro_name` syntax in your link. Read more about how to correctly use links in your rust-docs +[here](https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html#valid-links) and +[here](https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html#additions-to-the-documentation-syntax). --- ### Other Guidelines -The above five guidelines must always be reasonably respected in the -documentation. +The above five guidelines must always be reasonably respected in the documentation. -The following are a set of notes that may not necessarily hold in all -circumstances: +The following are a set of notes that may not necessarily hold in all circumstances: --- #### Document Through Code -You should make sure that your code is properly-named and well-organized so that -your code functions as a form of documentation. However, within the complexity -of our projects in Polkadot/Substrate that is not enough. Particularly, things -like examples, errors and panics cannot be documented only through properly- -named and well-organized code. +You should make sure that your code is properly-named and well-organized so that your code functions as a form of +documentation. However, within the complexity of our projects in Polkadot/Substrate that is not enough. Particularly, +things like examples, errors and panics cannot be documented only through properly- named and well-organized code. -> Our north star is self-documenting code that also happens to be well-documented -and littered with examples. +> Our north star is self-documenting code that also happens to be well-documented and littered with examples. -* Your written documents should *complement* the code, not *repeat* it. As an -example, a documentation on top of a code example should never look like the -following: +- Your written documents should *complement* the code, not *repeat* it. As an example, a documentation on top of a code +example should never look like the following: ```rust /// Sends request and handles the response. @@ -175,15 +159,14 @@ following: } ``` -In the above example, the documentation has added no useful information not -already contained within the properly-named trait and is redundant. +In the above example, the documentation has added no useful information not already contained within the properly-named +trait and is redundant. --- #### Formatting Matters -The way you format your documents (newlines, heading and so on) makes a -difference. Consider the below examples: +The way you format your documents (newlines, heading and so on) makes a difference. Consider the below examples: ```rust /// This function works with input u32 x and multiplies it by two. If @@ -206,16 +189,15 @@ fn multiply_by_2(x: u32) -> u32 { .. } // More efficiency can be achieved if we improve this via such and such. fn multiply_by_2(x: u32) -> u32 { .. } ``` -They are both roughly conveying the same set of facts, but one is easier to -follow because it was formatted cleanly. Especially for traits and types that -you can foresee will be seen and used a lot, try and write a well formatted +They are both roughly conveying the same set of facts, but one is easier to follow because it was formatted cleanly. +Especially for traits and types that you can foresee will be seen and used a lot, try and write a well formatted version. -Similarly, make sure your comments are wrapped at 100 characters line-width (as -defined by our [`rustfmt.toml`](../rustfmt.toml)), no **more and no less**! The -more is fixed by `rustfmt` and our CI, but if you (for some unknown reason) -wrap your lines at 59 characters, it will pass the CI, and it will not look good -🫣. Consider using a plugin like [rewrap](https://marketplace.visualstudio.com/items?itemName=stkb.rewrap) (for Visual Studio Code) to properly do this. +Similarly, make sure your comments are wrapped at 100 characters line-width (as defined by our +[`rustfmt.toml`](../rustfmt.toml)), no **more and no less**! The more is fixed by `rustfmt` and our CI, but if you (for +some unknown reason) wrap your lines at 59 characters, it will pass the CI, and it will not look good 🫣. Consider using +a plugin like [rewrap](https://marketplace.visualstudio.com/items?itemName=stkb.rewrap) (for Visual Studio Code) to +properly do this. [^1]: Those that help two pallets talk to each other. @@ -224,12 +206,11 @@ wrap your lines at 59 characters, it will pass the CI, and it will not look good ## Pallet Crates -The guidelines so far have been general in nature, and are applicable to crates -that are pallets and crates that're not pallets. +The guidelines so far have been general in nature, and are applicable to crates that are pallets and crates that're not +pallets. -The following is relevant to how to document parts of a crate that is a pallet. -See [`pallet-fast-unstake`](../frame/fast-unstake/src/lib.rs) as one example of -adhering these guidelines. +The following is relevant to how to document parts of a crate that is a pallet. See +[`pallet-fast-unstake`](../frame/fast-unstake/src/lib.rs) as one example of adhering these guidelines. --- @@ -252,15 +233,20 @@ For the top-level pallet docs, consider the following template: //! //! ### Example //! -//! . +//! . //! //! ## Pallet API //! -//! +//! //! -//! See the [`pallet`] module for more information about the interfaces this pallet exposes, including its configuration trait, dispatchables, storage items, events and errors. +//! See the [`pallet`] module for more information about the interfaces this pallet exposes, including its configuration +//! trait, dispatchables, storage items, events and errors. //! -//! +//! //! //! This section can most often be left as-is. //! @@ -268,7 +254,8 @@ For the top-level pallet docs, consider the following template: //! //! //! -//! +//! //! //! ### Design Goals (optional) //! @@ -276,31 +263,31 @@ For the top-level pallet docs, consider the following template: //! //! ### Design (optional) //! -//! +//! //! //! ### Terminology (optional) //! -//! +//! ``` -This template's details (heading 3s and beyond) are left flexible, and at the -discretion of the developer to make the best final choice about. For example, -you might want to include `### Terminology` or not. Moreover, you might find it +This template's details (heading 3s and beyond) are left flexible, and at the discretion of the developer to make the +best final choice about. For example, you might want to include `### Terminology` or not. Moreover, you might find it more useful to include it in `## Overview`. -Nonetheless, the high level flow of going from the most high level explanation -to the most low level explanation is important to follow. +Nonetheless, the high level flow of going from the most high level explanation to the most low level explanation is +important to follow. -As a rule of thumb, the Heading 2s (`##`) in this template can be considered a -strict rule, while the Heading 3s (`###`) and beyond are flexible. +As a rule of thumb, the Heading 2s (`##`) in this template can be considered a strict rule, while the Heading 3s (`###`) +and beyond are flexible. --- #### Polkadot and Substrate -Optionally, in order to demonstrate the relation between the two, you can start -the pallet documentation with: +Optionally, in order to demonstrate the relation between the two, you can start the pallet documentation with: ``` //! > Made with *Substrate*, for *Polkadot*. @@ -331,7 +318,8 @@ For each dispatchable (`fn` item inside `#[pallet::call]`), consider the followi /// /// ## Errors (optional) /// -/// +/// /// /// ## Events (optional) /// @@ -339,29 +327,26 @@ For each dispatchable (`fn` item inside `#[pallet::call]`), consider the followi pub fn name_of_dispatchable(origin: OriginFor, ...) -> DispatchResult {} ``` -Consider the fact that these docs will be part of the metadata of the associated dispatchable, and might be used by wallets and explorers. +Consider the fact that these docs will be part of the metadata of the associated dispatchable, and might be used by +wallets and explorers. --- ### Storage Items -1. If a map-like type is being used, always note the choice of your hashers as -private code docs (`// Hasher X chosen because ...`). Recall that this is not -relevant information to external people, so it must be documented as `//`. +1. If a map-like type is being used, always note the choice of your hashers as private code docs (`// Hasher X chosen +because ...`). Recall that this is not relevant information to external people, so it must be documented as `//`. -2. Consider explaining the crypto-economics of how a deposit is being taken in -return of the storage being used. +2. Consider explaining the crypto-economics of how a deposit is being taken in return of the storage being used. -3. Consider explaining why it is safe for the storage item to be unbounded, if -`#[pallet::unbounded]` or `#[pallet::without_storage_info]` is being used. +3. Consider explaining why it is safe for the storage item to be unbounded, if `#[pallet::unbounded]` or +`#[pallet::without_storage_info]` is being used. --- ### Errors and Events -Consider the fact that, similar to dispatchables, these docs will be part of -the metadata of the associated event/error, and might be used by wallets and -explorers. +Consider the fact that, similar to dispatchables, these docs will be part of the metadata of the associated event/error, +and might be used by wallets and explorers. -Specifically for `error`, explain why the error has happened, and what can be -done in order to avoid it. +Specifically for `error`, explain why the error has happened, and what can be done in order to avoid it. diff --git a/docs/PULL_REQUEST_TEMPLATE.md b/docs/PULL_REQUEST_TEMPLATE.md index 1d0ef338c10b..284ad15afc9e 100644 --- a/docs/PULL_REQUEST_TEMPLATE.md +++ b/docs/PULL_REQUEST_TEMPLATE.md @@ -2,25 +2,27 @@ ✄ ----------------------------------------------------------------------------- -Thank you for your Pull Request! 🙏 Please make sure it follows the contribution -guidelines outlined in [this document](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CONTRIBUTING.md) and fill out the -sections below. Once you're ready to submit your PR for review, please delete -this section and leave only the text under the "Description" heading. - +Thank you for your Pull Request! 🙏 Please make sure it follows the contribution guidelines outlined in +[this document](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CONTRIBUTING.md) and fill +out the sections below. Once you're ready to submit your PR for review, please +delete this section and leave only the text under the "Description" heading. # Description -*Please include a summary of the changes and the related issue. Please also include relevant motivation and context, including:* +*Please include a summary of the changes and the related issue. Please also include relevant motivation and context, +including:* - What does this PR do? - Why are these changes needed? - How were these changes implemented and what do they affect? -*Use [Github semantic linking](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) to address any open issues this PR relates to or closes.* +*Use [Github semantic +linking](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) +to address any open issues this PR relates to or closes.* -Fixes # (issue number, *if applicable*) +Fixes # (issue number, *if applicable*) -Closes # (issue number, *if applicable*) +Closes # (issue number, *if applicable*) Polkadot companion: (*if applicable*) @@ -29,10 +31,12 @@ Cumulus companion: (*if applicable*) # Checklist - [ ] My PR includes a detailed description as outlined in the "Description" section above -- [ ] My PR follows the [labeling requirements](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CONTRIBUTING.md#process) of this project (at minimum one label for `T` required) +- [ ] My PR follows the [labeling requirements](CONTRIBUTING.md#Process) of this project (at minimum one label for `T` + required) - [ ] I have made corresponding changes to the documentation (if applicable) - [ ] I have added tests that prove my fix is effective or that my feature works (if applicable) -- [ ] If this PR alters any external APIs or interfaces used by Polkadot, the corresponding Polkadot PR is ready as well as the corresponding Cumulus PR (optional) +- [ ] If this PR alters any external APIs or interfaces used by Polkadot, the corresponding Polkadot PR is ready as well + as the corresponding Cumulus PR (optional) You can remove the "Checklist" section once all have been checked. Thank you for your contribution! diff --git a/docs/STYLE_GUIDE.md b/docs/STYLE_GUIDE.md index eb3399880f53..a9ac4a5910b3 100644 --- a/docs/STYLE_GUIDE.md +++ b/docs/STYLE_GUIDE.md @@ -2,19 +2,19 @@ title: Style Guide for Rust in the Polkadot-SDK --- -Where possible these styles are enforced by settings in `rustfmt.toml` so if you run `cargo fmt` +Where possible these styles are enforced by settings in `rustfmt.toml` so if you run `cargo fmt` then you will adhere to most of these style guidelines automatically. # Formatting -- Indent using tabs. -- Lines should be longer than 100 characters long only in exceptional circumstances and certainly +- Indent using tabs. +- Lines should be longer than 100 characters long only in exceptional circumstances and certainly no longer than 120. For this purpose, tabs are considered 4 characters wide. -- Indent levels should be greater than 5 only in exceptional circumstances and certainly no +- Indent levels should be greater than 5 only in exceptional circumstances and certainly no greater than 8. If they are greater than 5, then consider using `let` or auxiliary functions in order to strip out complex inline expressions. -- Never have spaces on a line prior to a non-whitespace character -- Follow-on lines are only ever a single indent from the original line. +- Never have spaces on a line prior to a non-whitespace character +- Follow-on lines are only ever a single indent from the original line. ```rust fn calculation(some_long_variable_a: i8, some_long_variable_b: i8) -> bool { @@ -25,7 +25,7 @@ fn calculation(some_long_variable_a: i8, some_long_variable_b: i8) -> bool { } ``` -- Indent level should follow open parens/brackets, but should be collapsed to the smallest number +- Indent level should follow open parens/brackets, but should be collapsed to the smallest number of levels actually used: ```rust @@ -45,8 +45,8 @@ fn calculate( } ``` -- `where` is indented, and its items are indented one further. -- Argument lists or function invocations that are too long to fit on one line are indented +- `where` is indented, and its items are indented one further. +- Argument lists or function invocations that are too long to fit on one line are indented similarly to code blocks, and once one param is indented in such a way, all others should be, too. Run-on parameter lists are also acceptable for single-line run-ons of basic function calls. @@ -92,7 +92,7 @@ fn foo(really_long_parameter_name_1: SomeLongTypeName, really_long_parameter_nam } ``` -- Always end last item of a multi-line comma-delimited set with `,` when legal: +- Always end last item of a multi-line comma-delimited set with `,` when legal: ```rust struct Point { @@ -104,7 +104,7 @@ struct Point { enum Meal { Breakfast, Lunch, Dinner }; ``` -- Avoid trailing `;`s where unneeded. +- Avoid trailing `;`s where unneeded. ```rust if condition { @@ -112,8 +112,8 @@ if condition { } ``` -- `match` arms may be either blocks or have a trailing `,` but not both. -- Blocks should not be used unnecessarily. +- `match` arms may be either blocks or have a trailing `,` but not both. +- Blocks should not be used unnecessarily. ```rust match meal { @@ -126,7 +126,7 @@ match meal { # Style -- Panickers require explicit proofs they don't trigger. Calling `unwrap` is discouraged. The +- Panickers require explicit proofs they don't trigger. Calling `unwrap` is discouraged. The exception to this rule is test code. Avoiding panickers by restructuring code is preferred if feasible. @@ -139,14 +139,14 @@ let mut target_path = ); ``` -- Unsafe code requires explicit proofs just as panickers do. When introducing unsafe code, +- Unsafe code requires explicit proofs just as panickers do. When introducing unsafe code, consider trade-offs between efficiency on one hand and reliability, maintenance costs, and security on the other. Here is a list of questions that may help evaluating the trade-off while preparing or reviewing a PR: - - how much more performant or compact the resulting code will be using unsafe code, - - how likely is it that invariants could be violated, - - are issues stemming from the use of unsafe code caught by existing tests/tooling, - - what are the consequences if the problems slip into production. + - how much more performant or compact the resulting code will be using unsafe code, + - how likely is it that invariants could be violated, + - are issues stemming from the use of unsafe code caught by existing tests/tooling, + - what are the consequences if the problems slip into production. # Manifest Formatting @@ -177,4 +177,4 @@ default = [ # Comments go here as well ;) "std", ] -``` \ No newline at end of file +``` diff --git a/docs/markdown_linting.md b/docs/markdown_linting.md new file mode 100644 index 000000000000..d916b86ba544 --- /dev/null +++ b/docs/markdown_linting.md @@ -0,0 +1,20 @@ +# Markdown linting + +Since the introduction of [PR #1309](https://github.com/paritytech/polkadot-sdk/pull/1309), the markdown +files in this repository are checked by a linter for formatting and consistency. + +The linter used is [`markdownlint`](https://github.com/DavidAnson/markdownlint) and can be installed locally on your +machine. It can also be setup as [pre-commit hook](https://github.com/igorshubovych/markdownlint-cli#use-with-pre-commit) +to ensure that your markdown is passing all the tests. + +The rules in place are defined +[here](https://github.com/paritytech/polkadot-sdk/blob/master/.github/.markdownlint.yaml). + +You may run `markdownlint` locally using: +``` +markdownlint --config .github/.markdownlint.yaml --ignore target . +``` + +There are also plugins for your favorite editor, that can ensure that most +of the rules will pass and fix typical issues (such as trailing spaces, +missing eof new line, long lines, etc...) diff --git a/polkadot/README.md b/polkadot/README.md index 8f0809c9fc7a..93e93cfba0ee 100644 --- a/polkadot/README.md +++ b/polkadot/README.md @@ -22,7 +22,7 @@ Installation from the Debian repository will create a `systemd` service that can Polkadot node. This is disabled by default, and can be started by running `systemctl start polkadot` on demand (use `systemctl enable polkadot` to make it auto-start after reboot). By default, it will run as the `polkadot` user. Command-line flags passed to the binary can be customized by editing -`/etc/default/polkadot`. This file will not be overwritten on updating polkadot. You may also just +`/etc/default/polkadot`. This file will not be overwritten on updating Polkadot. You may also just run the node directly from the command-line. ### Debian-based (Debian, Ubuntu) @@ -128,7 +128,7 @@ Connect to the global Polkadot Mainnet network by running: You can see your node on [telemetry] (set a custom name with `--name "my custom name"`). -[telemetry]: https://telemetry.polkadot.io/#list/Polkadot +[telemetry](https://telemetry.polkadot.io/#list/Polkadot): https://telemetry.polkadot.io/#list/Polkadot ### Connect to the "Kusama" Canary Network @@ -140,7 +140,7 @@ Connect to the global Kusama canary network by running: You can see your node on [telemetry] (set a custom name with `--name "my custom name"`). -[telemetry]: https://telemetry.polkadot.io/#list/Kusama +[telemetry](https://telemetry.polkadot.io/#list/Kusama): https://telemetry.polkadot.io/#list/Kusama ### Connect to the Westend Testnet @@ -152,7 +152,7 @@ Connect to the global Westend testnet by running: You can see your node on [telemetry] (set a custom name with `--name "my custom name"`). -[telemetry]: https://telemetry.polkadot.io/#list/Westend +[telemetry](https://telemetry.polkadot.io/#list/Westend): https://telemetry.polkadot.io/#list/Westend ### Obtaining DOTs diff --git a/polkadot/RELEASE.md b/polkadot/RELEASE.md index 937c1e6e515f..196f27e595d6 100644 --- a/polkadot/RELEASE.md +++ b/polkadot/RELEASE.md @@ -1,57 +1,52 @@ -Polkadot Release Process ------------------------- +# Polkadot Release Process -### Branches -* release-candidate branch: The branch used for staging of the next release. - Named like `release-v0.8.26` - -### Notes -* The release-candidate branch *must* be made in the paritytech/polkadot repo in -order for release automation to work correctly -* Any new pushes/merges to the release-candidate branch (for example, -refs/heads/release-v0.8.26) will result in the rc index being bumped (e.g., v0.8.26-rc1 -to v0.8.26-rc2) and new wasms built. +## Branches +* release-candidate branch: The branch used for staging of the next release. Named like `release-v0.8.26` -### Release workflow +## Notes +* The release-candidate branch *must* be made in the `paritytech/polkadot` repo in order for release automation to work +correctly +* Any new pushes/merges to the release-candidate branch (for example, refs/heads/release-v0.8.26) will result in the rc +index being bumped (e.g., v0.8.26-rc1 to v0.8.26-rc2) and new wasm built. -Below are the steps of the release workflow. Steps prefixed with NOACTION are -automated and require no human action. +## Release workflow + +Below are the steps of the release workflow. Steps prefixed with NOACTION are automated and require no human action. 1. To initiate the release process: - 1. branch master off to a release candidate branch: - - `git checkout master; git pull; git checkout -b release-v0.8.26` - 2. In the [substrate](https://github.com/paritytech/substrate) repo, check out the commit used by polkadot (this can be found using the following command in the *polkadot* repo: `grep 'paritytech/substrate' Cargo.lock | grep -E '[0-9a-f]{40}' | sort | uniq ` - 3. Branch off this **substrate** commit into its own branch: `git branch -b polkadot-v0.8.26; git push origin refs/heads/polkadot-v0.8.26` - 4. In the **polkadot** repository, use [diener](https://github.com/bkchr/diener/) to switch to this branch: `diener update --branch "polkadot-v0.8.26" --substrate`. Update Cargo.lock (to do this, you can run `cargo build` and then ctrl+c once it finishes fetching and begins compiling) - 5. Push the **polkadot** `release-v0.8.26` branch to Github: `git push origin refs/heads/release-v0.8.26` -2. NOACTION: The current HEAD of the release-candidate branch is tagged `v0.8.26-rc1` -3. NOACTION: A draft release and runtime WASMs are created for this - release-candidate automatically. A link to the draft release will be linked in - the internal polkadot matrix channel. -4. NOACTION: A new Github issue is created containing a checklist of manual - steps to be completed before we are confident with the release. This will be - linked in Matrix. -5. Complete the steps in the issue created in step 4, signing them off as - completed -6. (optional) If a fix is required to the release-candidate: + 1. branch master off to a release candidate branch: - `git checkout master; git pull; git checkout -b release-v0.8.26` + 1. In the [Substrate](https://github.com/paritytech/substrate) repo, check out the commit used by Polkadot (this can + be found using the following command in the *Polkadot* repo: `grep 'paritytech/substrate' Cargo.lock | grep -E + '[0-9a-f]{40}' | sort | uniq` + 1. Branch off this **Substrate** commit into its own branch: `git branch -b polkadot-v0.8.26; git push origin + refs/heads/polkadot-v0.8.26` + 1. In the **Polkadot** repository, use [diener](https://github.com/bkchr/diener/) to switch to this branch: `diener + update --branch "polkadot-v0.8.26" --substrate`. Update Cargo.lock (to do this, you can run `cargo build` and then + ctrl+c once it finishes fetching and begins compiling) + 1. Push the **Polkadot** `release-v0.8.26` branch to Github: `git push origin refs/heads/release-v0.8.26` +1. NOACTION: The current HEAD of the release-candidate branch is tagged `v0.8.26-rc1` +1. NOACTION: A draft release and runtime WASMs are created for this release-candidate automatically. A link to the draft + release will be linked in the internal Polkadot matrix channel. +1. NOACTION: A new Github issue is created containing a checklist of manual steps to be completed before we are + confident with the release. This will be linked in Matrix. +1. Complete the steps in the issue created in step 4, signing them off as completed +1. (optional) If a fix is required to the release-candidate: 1. Merge the fix with `master` first - 2. Cherry-pick the commit from `master` to `release-v0.8.26`, fixing any - merge conflicts. Try to avoid unnecessarily bumping crates. - 3. Push the release-candidate branch to Github - this is now the new release- - candidate - 4. Depending on the cherry-picked changes, it may be necessary to perform some - or all of the manual tests again. - 5. If there are **substrate** changes required, these should be cherry-picked to the substrate `polkadot-v0.8.26` branch and pushed, and the version of substrate used in **polkadot** updated using `cargo update -p sp-io` -7. Once happy with the release-candidate, tag the current top commit in the release candidate branch and push to Github: `git tag -s -m 'v0.8.26' v0.8.26; git push --tags` -9. NOACTION: The HEAD of the `release` branch will be tagged with `v0.8.26`, - and a final draft release will be created on Github. + 1. Cherry-pick the commit from `master` to `release-v0.8.26`, fixing any merge conflicts. Try to avoid unnecessarily + bumping crates. + 1. Push the release-candidate branch to Github - this is now the new release- candidate + 1. Depending on the cherry-picked changes, it may be necessary to perform some or all of the manual tests again. + 1. If there are **Substrate** changes required, these should be cherry-picked to the Substrate `polkadot-v0.8.26` + branch and pushed, and the version of Substrate used in **Polkadot** updated using `cargo update -p sp-io` +1. Once happy with the release-candidate, tag the current top commit in the release candidate branch and push to Github: + `git tag -s -m 'v0.8.26' v0.8.26; git push --tags` +1. NOACTION: The HEAD of the `release` branch will be tagged with `v0.8.26`, and a final draft release will be created + on Github. -### Security releases +## Security releases -Occasionally there may be changes that need to be made to the most recently -released version of Polkadot, without taking *every* change to `master` since -the last release. For example, in the event of a security vulnerability being -found, where releasing a fixed version is a matter of some expediency. In cases -like this, the fix should first be merged with master, cherry-picked to a branch -forked from `release`, tested, and then finally merged with `release`. A -sensible versioning scheme for changes like this is `vX.Y.Z-1`. +Occasionally there may be changes that need to be made to the most recently released version of Polkadot, without taking +*every* change to `master` since the last release. For example, in the event of a security vulnerability being found, +where releasing a fixed version is a matter of some expediency. In cases like this, the fix should first be merged with +master, cherry-picked to a branch forked from `release`, tested, and then finally merged with `release`. A sensible +versioning scheme for changes like this is `vX.Y.Z-1`. diff --git a/polkadot/doc/docker.md b/polkadot/doc/docker.md index f20c2d001edd..dc679908ec61 100644 --- a/polkadot/doc/docker.md +++ b/polkadot/doc/docker.md @@ -1,6 +1,8 @@ # Using Containers -The following commands should work no matter if you use Docker or Podman. In general, Podman is recommended. All commands are "engine neutral" so you can use the container engine of your choice while still being able to copy/paste the commands below. +The following commands should work no matter if you use Docker or Podman. In general, Podman is recommended. All +commands are "engine neutral" so you can use the container engine of your choice while still being able to copy/paste +the commands below. Let's start defining Podman as our engine: ``` @@ -14,11 +16,15 @@ ENGINE=docker ## The easiest way -The easiest/faster option to run Polkadot in Docker is to use the latest release images. These are small images that use the latest official release of the Polkadot binary, pulled from our Debian package. +The easiest/faster option to run Polkadot in Docker is to use the latest release images. These are small images that use +the latest official release of the Polkadot binary, pulled from our Debian package. -**_The following examples are running on westend chain and without SSL. They can be used to quick start and learn how Polkadot needs to be configured. Please find out how to secure your node, if you want to operate it on the internet. Do not expose RPC and WS ports, if they are not correctly configured._** +**_The following examples are running on westend chain and without SSL. They can be used to quick start and learn how +Polkadot needs to be configured. Please find out how to secure your node, if you want to operate it on the internet. Do +not expose RPC and WS ports, if they are not correctly configured._** -Let's first check the version we have. The first time you run this command, the Polkadot docker image will be downloaded. This takes a bit of time and bandwidth, be patient: +Let's first check the version we have. The first time you run this command, the Polkadot docker image will be +downloaded. This takes a bit of time and bandwidth, be patient: ```bash $ENGINE run --rm -it parity/polkadot:latest --version @@ -32,11 +38,14 @@ $ENGINE run --rm -it parity/polkadot:latest --chain westend --name "PolkaDocker" ## Examples -Once you are done experimenting and picking the best node name :) you can start Polkadot as daemon, exposes the Polkadot ports and mount a volume that will keep your blockchain data locally. Make sure that you set the ownership of your local directory to the Polkadot user that is used by the container. +Once you are done experimenting and picking the best node name :) you can start Polkadot as daemon, exposes the Polkadot +ports and mount a volume that will keep your blockchain data locally. Make sure that you set the ownership of your local +directory to the Polkadot user that is used by the container. Set user id 1000 and group id 1000, by running `chown 1000.1000 /my/local/folder -R` if you use a bind mount. -To start a Polkadot node on default rpc port 9933 and default p2p port 30333 use the following command. If you want to connect to rpc port 9933, then must add Polkadot startup parameter: `--rpc-external`. +To start a Polkadot node on default rpc port 9933 and default p2p port 30333 use the following command. If you want to +connect to rpc port 9933, then must add Polkadot startup parameter: `--rpc-external`. ```bash $ENGINE run -d -p 30333:30333 -p 9933:9933 \ @@ -82,7 +91,8 @@ services: ] ``` -With following `docker-compose.yml` you can set up a node and use polkadot-js-apps as the front end on port 80. After starting the node use a browser and enter your Docker host IP in the URL field: __ +With following `docker-compose.yml` you can set up a node and use `polkadot-js-apps` as the front end on port 80. After +starting the node use a browser and enter your Docker host IP in the URL field: __ ```bash version: '2' @@ -117,12 +127,14 @@ services: Chain syncing will utilize all available memory and CPU power your server has to offer, which can lead to crashing. -If running on a low resource VPS, use `--memory` and `--cpus` to limit the resources used. E.g. To allow a maximum of 512MB memory and 50% of 1 CPU, use `--cpus=".5" --memory="512m"`. Read more about limiting a container's resources [here](https://docs.docker.com/config/containers/resource_constraints). +If running on a low resource VPS, use `--memory` and `--cpus` to limit the resources used. E.g. To allow a maximum of +512MB memory and 50% of 1 CPU, use `--cpus=".5" --memory="512m"`. Read more about limiting a container's resources +[here](https://docs.docker.com/config/containers/resource_constraints). ## Build your own image -There are 3 options to build a polkadot container image: +There are 3 options to build a Polkadot container image: - using the builder image - using the injected "Debian" image - using the generic injected image @@ -131,27 +143,31 @@ There are 3 options to build a polkadot container image: To get up and running with the smallest footprint on your system, you may use an existing Polkadot Container image. -You may also build a polkadot container image yourself (it takes a while...) using the container specs `scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile`. +You may also build a Polkadot container image yourself (it takes a while...) using the container specs +`scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile`. ### Debian injected -The Debian injected image is how the official polkadot container image is produced. It relies on the Debian package that is published upon each release. The Debian injected image is usually available a few minutes after a new release is published. -It has the benefit of relying on the GPG signatures embedded in the Debian package. +The Debian injected image is how the official Polkadot container image is produced. It relies on the Debian package that +is published upon each release. The Debian injected image is usually available a few minutes after a new release is +published. It has the benefit of relying on the GPG signatures embedded in the Debian package. ### Generic injected -For simple testing purposes, the easiest option for polkadot and also random binaries, is to use the `binary_injected.Dockerfile` container spec. This option is less secure since the injected binary is not checked at all but it has the benefit to be simple. This option requires to already have a valid `polkadot` binary, compiled for Linux. +For simple testing purposes, the easiest option for Polkadot and also random binaries, is to use the +`binary_injected.Dockerfile` container spec. This option is less secure since the injected binary is not checked at all +but it has the benefit to be simple. This option requires to already have a valid `polkadot` binary, compiled for Linux. This binary is then simply copied inside the `parity/base-bin` image. ## Reporting issues -If you run into issues with Polkadot when using docker, please run the following command -(replace the tag with the appropriate one if you do not use latest): +If you run into issues with Polkadot when using docker, please run the following command (replace the tag with the +appropriate one if you do not use latest): ```bash $ENGINE run --rm -it parity/polkadot:latest --version ``` -This will show you the Polkadot version as well as the git commit ref that was used to build your container. -You can now paste the version information in a [new issue](https://github.com/paritytech/polkadot/issues/new/choose). +This will show you the Polkadot version as well as the git commit ref that was used to build your container. You can now +paste the version information in a [new issue](https://github.com/paritytech/polkadot/issues/new/choose). diff --git a/polkadot/doc/release-checklist.md b/polkadot/doc/release-checklist.md index 4be7c9bcd5df..8c57791fed1d 100644 --- a/polkadot/doc/release-checklist.md +++ b/polkadot/doc/release-checklist.md @@ -1,98 +1,91 @@ -## Notes +# Notes -### Burn In +## Burn In -Ensure that Parity DevOps has run the new release on Westend, Kusama, and -Polkadot validators for at least 12 hours prior to publishing the release. +Ensure that Parity DevOps has run the new release on Westend, Kusama, and Polkadot validators for at least 12 hours +prior to publishing the release. -### Build Artifacts +## Build Artifacts Add any necessary assets to the release. They should include: -- Linux binary -- GPG signature of the Linux binary -- SHA256 of binary -- Source code -- Wasm binaries of any runtimes +* Linux binary +* GPG signature of the Linux binary +* SHA256 of binary +* Source code +* Wasm binaries of any runtimes -### Release notes +## Release notes The release notes should list: -- The priority of the release (i.e., how quickly users should upgrade) - this is - based on the max priority of any *client* changes. -- Which native runtimes and their versions are included -- The proposal hashes of the runtimes as built with - [srtool](https://gitlab.com/chevdor/srtool) -- Any changes in this release that are still awaiting audit +* The priority of the release (i.e., how quickly users should upgrade) - this is based on the max priority of any + *client* changes. +* Which native runtimes and their versions are included +* The proposal hashes of the runtimes as built with [srtool](https://gitlab.com/chevdor/srtool) +* Any changes in this release that are still awaiting audit The release notes may also list: -- Free text at the beginning of the notes mentioning anything important - regarding this release -- Notable changes (those labelled with B[1-9]-* labels) separated into sections +* Free text at the beginning of the notes mentioning anything important regarding this release +* Notable changes (those labelled with B[1-9]-* labels) separated into sections -### Spec Version +## Spec Version -A runtime upgrade must bump the spec number. This may follow a pattern with the -client release (e.g. runtime v12 corresponds to v0.8.12, even if the current -runtime is not v11). +A runtime upgrade must bump the spec number. This may follow a pattern with the client release (e.g. runtime v12 +corresponds to v0.8.12, even if the current runtime is not v11). -### Old Migrations Removed +## Old Migrations Removed -Any previous `on_runtime_upgrade` functions from old upgrades must be removed -to prevent them from executing a second time. The `on_runtime_upgrade` function -can be found in `runtime//src/lib.rs`. +Any previous `on_runtime_upgrade` functions from old upgrades must be removed to prevent them from executing a second +time. The `on_runtime_upgrade` function can be found in `runtime//src/lib.rs`. -### New Migrations +## New Migrations -Ensure that any migrations that are required due to storage or logic changes -are included in the `on_runtime_upgrade` function of the appropriate pallets. +Ensure that any migrations that are required due to storage or logic changes are included in the `on_runtime_upgrade` +function of the appropriate pallets. -### Extrinsic Ordering +## Extrinsic Ordering -Offline signing libraries depend on a consistent ordering of call indices and -functions. Compare the metadata of the current and new runtimes and ensure that -the `module index, call index` tuples map to the same set of functions. In case +Offline signing libraries depend on a consistent ordering of call indices and functions. Compare the metadata of the +current and new runtimes and ensure that the `module index, call index` tuples map to the same set of functions. In case of a breaking change, increase `transaction_version`. -To verify the order has not changed, you may manually start the following [Github Action](https://github.com/paritytech/polkadot/actions/workflows/extrinsic-ordering-check-from-bin.yml). It takes around a minute to run and will produce the report as artifact you need to manually check. +To verify the order has not changed, you may manually start the following [Github +Action](https://github.com/paritytech/polkadot/actions/workflows/extrinsic-ordering-check-from-bin.yml). It takes around +a minute to run and will produce the report as artifact you need to manually check. The things to look for in the output are lines like: - - `[Identity] idx 28 -> 25 (calls 15)` - indicates the index for `Identity` has changed - - `[+] Society, Recovery` - indicates the new version includes 2 additional modules/pallets. - - If no indices have changed, every modules line should look something like `[Identity] idx 25 (calls 15)` + * `[Identity] idx 28 -> 25 (calls 15)` - indicates the index for `Identity` has changed + * `[+] Society, Recovery` - indicates the new version includes 2 additional modules/pallets. + * If no indices have changed, every modules line should look something like `[Identity] idx 25 (calls 15)` -Note: Adding new functions to the runtime does not constitute a breaking change -as long as the indexes did not change. +Note: Adding new functions to the runtime does not constitute a breaking change as long as the indexes did not change. -### Proxy Filtering +## Proxy Filtering -The runtime contains proxy filters that map proxy types to allowable calls. If -the new runtime contains any new calls, verify that the proxy filters are up to -date to include them. +The runtime contains proxy filters that map proxy types to allowable calls. If the new runtime contains any new calls, +verify that the proxy filters are up to date to include them. -### Benchmarks +## Benchmarks -There are three benchmarking machines reserved for updating the weights at -release-time. To initialise a benchmark run for each production runtime -(westend, kusama, polkadot): +There are three benchmarking machines reserved for updating the weights at release-time. To initialise a benchmark run +for each production runtime (`westend`, `kusama`, `polkadot`): * Go to https://gitlab.parity.io/parity/polkadot/-/pipelines?page=1&scope=branches&ref=master * Click the link to the last pipeline run for master * Start each of the manual jobs: - * 'update_westend_weights' - * 'update_polkadot_weights' - * 'update_kusama_weights' -* When these jobs have completed (it takes a few hours), a git PATCH file will - be available to download as an artifact. + * `update_westend_weights` + * `update_polkadot_weights` + * `update_kusama_weights` +* When these jobs have completed (it takes a few hours), a git PATCH file will be available to download as an artifact. * On your local machine, branch off master * Download the patch file and apply it to your branch with `git patch patchfile.patch` * Commit the changes to your branch and submit a PR against master -* The weights should be (Currently manually) checked to make sure there are no - big outliers (i.e., twice or half the weight). +* The weights should be (Currently manually) checked to make sure there are no big outliers (i.e., twice or half the + weight). -### Polkadot JS +## Polkadot JS -Ensure that a release of [Polkadot JS API]() contains any new types or -interfaces necessary to interact with the new runtime. +Ensure that a release of [Polkadot JS API](https://github.com/polkadot-js/api) contains any new types or interfaces +necessary to interact with the new runtime. diff --git a/polkadot/doc/shell-completion.md b/polkadot/doc/shell-completion.md index 9c53cf43a10f..9761c153d5be 100644 --- a/polkadot/doc/shell-completion.md +++ b/polkadot/doc/shell-completion.md @@ -1,6 +1,7 @@ # Shell completion -The Polkadot CLI command supports shell auto-completion. For this to work, you will need to run the completion script matching you build and system. +The Polkadot CLI command supports shell auto-completion. For this to work, you will need to run the completion script +matching you build and system. Assuming you built a release version using `cargo build --release` and use `bash` run the following: @@ -30,7 +31,8 @@ source $HOME/.bash_profile ## Update -When you build a new version of Polkadot, the following will ensure you auto-completion script matches the current binary: +When you build a new version of Polkadot, the following will ensure you auto-completion script matches the current +binary: ```bash COMPL_DIR=$HOME/.completion diff --git a/polkadot/doc/testing.md b/polkadot/doc/testing.md index 78ad77e0e0fd..1045303baf0d 100644 --- a/polkadot/doc/testing.md +++ b/polkadot/doc/testing.md @@ -4,7 +4,7 @@ Automated testing is an essential tool to assure correctness. ## Scopes -The testing strategy for polkadot is 4-fold: +The testing strategy for Polkadot is 4-fold: ### Unit testing (1) @@ -16,18 +16,15 @@ There are two variants of integration tests: #### Subsystem tests (2) -One particular subsystem (subsystem under test) interacts with a -mocked overseer that is made to assert incoming and outgoing messages -of the subsystem under test. -This is largely present today, but has some fragmentation in the evolved -integration test implementation. A `proc-macro`/`macro_rules` would allow -for more consistent implementation and structure. +One particular subsystem (subsystem under test) interacts with a mocked overseer that is made to assert incoming and +outgoing messages of the subsystem under test. This is largely present today, but has some fragmentation in the evolved +integration test implementation. A `proc-macro`/`macro_rules` would allow for more consistent implementation and +structure. #### Behavior tests (3) -Launching small scale networks, with multiple adversarial nodes without any further tooling required. -This should include tests around the thresholds in order to evaluate the error handling once certain -assumed invariants fail. +Launching small scale networks, with multiple adversarial nodes without any further tooling required. This should +include tests around the thresholds in order to evaluate the error handling once certain assumed invariants fail. For this purpose based on `AllSubsystems` and `proc-macro` `AllSubsystemsGen`. @@ -35,18 +32,14 @@ This assumes a simplistic test runtime. #### Testing at scale (4) -Launching many nodes with configurable network speed and node features in a cluster of nodes. -At this scale the [Simnet][simnet] comes into play which launches a full cluster of nodes. -The scale is handled by spawning a kubernetes cluster and the meta description -is covered by [Gurke][Gurke]. -Asserts are made using Grafana rules, based on the existing prometheus metrics. This can -be extended by adding an additional service translating `jaeger` spans into addition -prometheus avoiding additional polkadot source changes. +Launching many nodes with configurable network speed and node features in a cluster of nodes. At this scale the +[Simnet][simnet] comes into play which launches a full cluster of nodes. The scale is handled by spawning a kubernetes +cluster and the meta description is covered by [Gurke][Gurke]. Asserts are made using Grafana rules, based on the +existing prometheus metrics. This can be extended by adding an additional service translating `jaeger` spans into +addition prometheus avoiding additional Polkadot source changes. -_Behavior tests_ and _testing at scale_ have naturally soft boundary. -The most significant difference is the presence of a real network and -the number of nodes, since a single host often not capable to run -multiple nodes at once. +_Behavior tests_ and _testing at scale_ have naturally soft boundary. The most significant difference is the presence of +a real network and the number of nodes, since a single host often not capable to run multiple nodes at once. --- @@ -54,8 +47,8 @@ multiple nodes at once. Coverage gives a _hint_ of the actually covered source lines by tests and test applications. -The state of the art is currently [tarpaulin][tarpaulin] which unfortunately yields a -lot of false negatives. Lines that are in fact covered, marked as uncovered due to a mere linebreak in a statement can cause these artifacts. This leads to +The state of the art is currently [tarpaulin][tarpaulin] which unfortunately yields a lot of false negatives. Lines that +are in fact covered, marked as uncovered due to a mere linebreak in a statement can cause these artifacts. This leads to lower coverage percentages than there actually is. Since late 2020 rust has gained [MIR based coverage tooling]( @@ -97,9 +90,11 @@ The test coverage in `lcov` can the be published to . bash <(curl -s https://codecov.io/bash) -f lcov.info ``` -or just printed as part of the PR using a github action i.e. [`jest-lcov-reporter`](https://github.com/marketplace/actions/jest-lcov-reporter). +or just printed as part of the PR using a github action i.e. +[`jest-lcov-reporter`](https://github.com/marketplace/actions/jest-lcov-reporter). -For full examples on how to use [`grcov` /w polkadot specifics see the github repo](https://github.com/mozilla/grcov#coverallscodecov-output). +For full examples on how to use [`grcov` /w Polkadot specifics see the github +repo](https://github.com/mozilla/grcov#coverallscodecov-output). ## Fuzzing @@ -109,11 +104,12 @@ Currently implemented fuzzing targets: * `erasure-coding` -The tooling of choice here is `honggfuzz-rs` as it allows _fastest_ coverage according to "some paper" which is a positive feature when run as part of PRs. +The tooling of choice here is `honggfuzz-rs` as it allows _fastest_ coverage according to "some paper" which is a +positive feature when run as part of PRs. -Fuzzing is generally not applicable for data secured by cryptographic hashes or signatures. Either the input has to be specifically crafted, such that the discarded input -percentage stays in an acceptable range. -System level fuzzing is hence simply not feasible due to the amount of state that is required. +Fuzzing is generally not applicable for data secured by cryptographic hashes or signatures. Either the input has to be +specifically crafted, such that the discarded input percentage stays in an acceptable range. System level fuzzing is +hence simply not feasible due to the amount of state that is required. Other candidates to implement fuzzing are: @@ -128,14 +124,17 @@ There are various ways of performance metrics. * cache hits/misses w/ `iai` harness or `criterion-perf` * `coz` a performance based compiler -Most of them are standard tools to aid in the creation of statistical tests regarding change in time of certain unit tests. +Most of them are standard tools to aid in the creation of statistical tests regarding change in time of certain unit +tests. -`coz` is meant for runtime. In our case, the system is far too large to yield a sufficient number of measurements in finite time. -An alternative approach could be to record incoming package streams per subsystem and store dumps of them, which in return could be replayed repeatedly at an -accelerated speed, with which enough metrics could be obtained to yield -information on which areas would improve the metrics. -This unfortunately will not yield much information, since most if not all of the subsystem code is linear based on the input to generate one or multiple output messages, it is unlikely to get any useful metrics without mocking a sufficiently large part of the other subsystem which overlaps with [#Integration tests] which is unfortunately not repeatable as of now. -As such the effort gain seems low and this is not pursued at the current time. +`coz` is meant for runtime. In our case, the system is far too large to yield a sufficient number of measurements in +finite time. An alternative approach could be to record incoming package streams per subsystem and store dumps of them, +which in return could be replayed repeatedly at an accelerated speed, with which enough metrics could be obtained to +yield information on which areas would improve the metrics. This unfortunately will not yield much information, since +most if not all of the subsystem code is linear based on the input to generate one or multiple output messages, it is +unlikely to get any useful metrics without mocking a sufficiently large part of the other subsystem which overlaps with +[#Integration tests] which is unfortunately not repeatable as of now. As such the effort gain seems low and this is not +pursued at the current time. ## Writing small scope integration tests with preconfigured workers @@ -152,29 +151,25 @@ Requirements: ### Goals -The main goals are is to allow creating a test node which -exhibits a certain behavior by utilizing a subset of _wrapped_ or _replaced_ subsystems easily. -The runtime must not matter at all for these tests and should be simplistic. -The execution must be fast, this mostly means to assure a close to zero network latency as -well as shorting the block time and epoch times down to a few `100ms` and a few dozend blocks per epoch. +The main goals are is to allow creating a test node which exhibits a certain behavior by utilizing a subset of _wrapped_ +or _replaced_ subsystems easily. The runtime must not matter at all for these tests and should be simplistic. The +execution must be fast, this mostly means to assure a close to zero network latency as well as shorting the block time +and epoch times down to a few `100ms` and a few dozend blocks per epoch. ### Approach #### MVP -A simple small scale builder pattern would suffice for stage one implementation of allowing to -replace individual subsystems. -An alternative would be to harness the existing `AllSubsystems` type -and replace the subsystems as needed. +A simple small scale builder pattern would suffice for stage one implementation of allowing to replace individual +subsystems. An alternative would be to harness the existing `AllSubsystems` type and replace the subsystems as needed. #### Full `proc-macro` implementation -`Overseer` is a common pattern. -It could be extracted as `proc` macro and generative `proc-macro`. -This would replace the `AllSubsystems` type as well as implicitly create -the `AllMessages` enum as `AllSubsystemsGen` does today. +`Overseer` is a common pattern. It could be extracted as `proc` macro and generative `proc-macro`. This would replace +the `AllSubsystems` type as well as implicitly create the `AllMessages` enum as `AllSubsystemsGen` does today. -The implementation is yet to be completed, see the [implementation PR](https://github.com/paritytech/polkadot/pull/2962) for details. +The implementation is yet to be completed, see the [implementation PR](https://github.com/paritytech/polkadot/pull/2962) +for details. ##### Declare an overseer implementation @@ -233,19 +228,16 @@ fn main() -> eyre::Result<()> { #### Simnet -Spawn a kubernetes cluster based on a meta description using [Gurke] with the -[Simnet] scripts. +Spawn a kubernetes cluster based on a meta description using [Gurke] with the [Simnet] scripts. -Coordinated attacks of multiple nodes or subsystems must be made possible via -a side-channel, that is out of scope for this document. +Coordinated attacks of multiple nodes or subsystems must be made possible via a side-channel, that is out of scope for +this document. -The individual node configurations are done as targets with a particular -builder configuration. +The individual node configurations are done as targets with a particular builder configuration. #### Behavior tests w/o Simnet -Commonly this will require multiple nodes, and most machines are limited to -running two or three nodes concurrently. +Commonly this will require multiple nodes, and most machines are limited to running two or three nodes concurrently. Hence, this is not the common case and is just an implementation _idea_. ```rust diff --git a/polkadot/erasure-coding/benches/README.md b/polkadot/erasure-coding/benches/README.md index e643643229e8..94fca5400c61 100644 --- a/polkadot/erasure-coding/benches/README.md +++ b/polkadot/erasure-coding/benches/README.md @@ -1,10 +1,10 @@ -### Run benches +# Run benches ``` -$ cd erasure-coding # ensure you are in the right directory -$ cargo bench +cd erasure-coding # ensure you are in the right directory +cargo bench ``` -### `scaling_with_validators` +## `scaling_with_validators` This benchmark evaluates the performance of constructing the chunks and the erasure root from PoV and reconstructing the PoV from chunks. You can see the results of running this bench on 5950x below. diff --git a/polkadot/grafana/README.md b/polkadot/grafana/README.md index 73c5b6feacf2..7350001bfa1f 100644 --- a/polkadot/grafana/README.md +++ b/polkadot/grafana/README.md @@ -1,35 +1,35 @@ # Do I need this ? -Polkadot nodes collect and produce Prometheus metrics and logs. These include health, performance and debug -information such as last finalized block, height of the chain, and many other deeper implementation details -of the Polkadot/Substrate node subsystems. These are crucial pieces of information that one needs to successfully +Polkadot nodes collect and produce Prometheus metrics and logs. These include health, performance and debug +information such as last finalized block, height of the chain, and many other deeper implementation details +of the Polkadot/Substrate node subsystems. These are crucial pieces of information that one needs to successfully monitor the liveliness and performance of a network and its validators. # How does it work ? -Just import the dashboard JSON files from this folder in your Grafana installation. All dashboards are grouped in +Just import the dashboard JSON files from this folder in your Grafana installation. All dashboards are grouped in folder percategory (like for example `parachains`). The files have been created by Grafana export functionality and follow the data model specified [here](https://grafana.com/docs/grafana/latest/dashboards/json-model/). -We aim to keep the dashboards here in sync with the implementation, except dashboards for development and +We aim to keep the dashboards here in sync with the implementation, except dashboards for development and testing. # Contributing -**Your contributions are most welcome!** +**Your contributions are most welcome!** Please make sure to follow the following design guidelines: - Add a new entry in this file and describe the usecase and key metrics -- Ensure proper names and descriptions for dashboard panels and add relevant documentation when needed. -This is very important as not all users have similar depth of understanding of the implementation +- Ensure proper names and descriptions for dashboard panels and add relevant documentation when needed. +This is very important as not all users have similar depth of understanding of the implementation - Have labels for axis - All values have proper units of measurement - A crisp and clear color scheme is used # Prerequisites -Before you continue make sure you have Grafana set up, or otherwise follow this -[guide](https://wiki.polkadot.network/docs/maintain-guides-how-to-monitor-your-node). +Before you continue make sure you have Grafana set up, or otherwise follow this +[guide](https://wiki.polkadot.network/docs/maintain-guides-how-to-monitor-your-node). You might also need to [setup Loki](https://grafana.com/go/webinar/loki-getting-started/). @@ -44,7 +44,7 @@ This section is a list of dashboards, their use case as well as the key metrics ## Node Versions -Useful for monitoring versions and logs of validator nodes. Includes time series panels that +Useful for monitoring versions and logs of validator nodes. Includes time series panels that track node warning and error log rates. These can be further investigated in Grafana Loki. Requires Loki for log aggregation and querying. @@ -64,30 +64,30 @@ It includes panels covering key subsystems of the parachain node side implementa - Disputes coordinator - Chain selection -It is important to note that this dashboard applies only for validator nodes. The prometheus -queries assume the `instance` label value contains the string `validator` only for validator nodes. +It is important to note that this dashboard applies only for validator nodes. The prometheus +queries assume the `instance` label value contains the string `validator` only for validator nodes. [Dashboard JSON](parachains/status.json) ### Key liveliness indicators - **Relay chain finality lag**. How far behind finality is compared to the current best block. By design, GRANDPA never finalizes past last 2 blocks, so this value is always >=2 blocks. -- **Approval checking finality lag**. The distance (in blocks) between the chain head and the last block -on which Approval voting is happening. The block is generally the highest approved ancestor of the head +- **Approval checking finality lag**. The distance (in blocks) between the chain head and the last block +on which Approval voting is happening. The block is generally the highest approved ancestor of the head block and the metric is computed during relay chain selection. -- **Disputes finality lag**. How far behind the chain head is the last approved and non disputed block. -This value is always higher than approval checking lag as it further restricts finality to only undisputed +- **Disputes finality lag**. How far behind the chain head is the last approved and non disputed block. +This value is always higher than approval checking lag as it further restricts finality to only undisputed chains. -- **PVF preparation and execution time**. Each parachain has it's own PVF (parachain validation function): -a wasm blob that is executed by validators during backing, approval checking and disputing. The PVF -preparation time refers to the time it takes for the PVF wasm to be compiled. This step is done once and -then result cached. PVF execution will use the resulting artifact to execute the PVF for a given candidate. -PVFs are expected to have a limited execution time to ensure there is enough time left for the parachain +- **PVF preparation and execution time**. Each parachain has it's own PVF (parachain validation function): +a wasm blob that is executed by validators during backing, approval checking and disputing. The PVF +preparation time refers to the time it takes for the PVF wasm to be compiled. This step is done once and +then result cached. PVF execution will use the resulting artifact to execute the PVF for a given candidate. +PVFs are expected to have a limited execution time to ensure there is enough time left for the parachain block to be included in the relay block. -- **Time to recover and check candidate**. This is part of approval voting and covers the time it takes +- **Time to recover and check candidate**. This is part of approval voting and covers the time it takes to recover the candidate block available data from other validators, check it (includes PVF execution time) and issue statement or initiate dispute. -- **Assignment delay tranches**. Approval voting is designed such that validators assigned to check a specific -candidate are split up into equal delay tranches (0.5 seconds each). All validators checks are ordered by the delay -tranche index. Early tranches of validators have the opportunity to check the candidate first before later tranches +- **Assignment delay tranches**. Approval voting is designed such that validators assigned to check a specific +candidate are split up into equal delay tranches (0.5 seconds each). All validators checks are ordered by the delay +tranche index. Early tranches of validators have the opportunity to check the candidate first before later tranches that act as as backups in case of no shows. diff --git a/polkadot/node/gum/README.md b/polkadot/node/gum/README.md index 739ce3066ecb..aed576351326 100644 --- a/polkadot/node/gum/README.md +++ b/polkadot/node/gum/README.md @@ -52,6 +52,6 @@ when providing to any of the log macros (`warn!`, `info!`, etc.). The crate has to be used throughout the entire codebase to work consistently, to disambiguate, the prefix `gum::` is used. -Feature parity with `tracing::{warn!,..}` is not desired. We want consistency +Feature Parity with `tracing::{warn!,..}` is not desired. We want consistency more than anything. All currently used features _are_ supported with _gum_ as well. diff --git a/polkadot/node/malus/README.md b/polkadot/node/malus/README.md index fb4bb0cd272f..e0c7893a7531 100644 --- a/polkadot/node/malus/README.md +++ b/polkadot/node/malus/README.md @@ -18,7 +18,7 @@ defined in the [(DSL[(**D**omain **S**pecific **L**anguage)]) doc](https://parit ## Usage -> Assumes you already gained permissiones, ping in element @javier:matrix.parity.io to get access. +> Assumes you already gained permissiones, ping in element `@javier:matrix.parity.io` to get access. > and you have cloned the [zombienet][zombienet] repo. To launch a test case in the development cluster use (e.g. for the ./node/malus/integrationtests/0001-dispute-valid-block.toml): @@ -48,7 +48,7 @@ This will also teardown the namespace after completion. ## Container Image Building Note In order to build the container image you need to have the latest changes from -polkadot and substrate master branches. +Polkadot and Substrate master branches. ```sh pwd # run this from the current dir diff --git a/polkadot/node/metrics/README.md b/polkadot/node/metrics/README.md index cc88884f2142..0cf57006f67a 100644 --- a/polkadot/node/metrics/README.md +++ b/polkadot/node/metrics/README.md @@ -1,4 +1,4 @@ -# polkadot-node-metrics +# `polkadot-node-metrics` ## Testing diff --git a/polkadot/node/test/service/README.md b/polkadot/node/test/service/README.md index 2fdee46a7f93..b0240588c44c 100644 --- a/polkadot/node/test/service/README.md +++ b/polkadot/node/test/service/README.md @@ -1,4 +1,4 @@ -# polkadot-test-service +# `polkadot-test-service` ## Testing diff --git a/polkadot/parachain/test-parachains/README.md b/polkadot/parachain/test-parachains/README.md index 2c708bd54318..e679d40591b3 100644 --- a/polkadot/parachain/test-parachains/README.md +++ b/polkadot/parachain/test-parachains/README.md @@ -1,3 +1,4 @@ # Test Parachains -Each parachain consists of three parts: a `#![no_std]` library with the main execution logic, a WASM crate which wraps this logic, and a collator node. +Each parachain consists of three parts: a `#![no_std]` library with the main execution logic, a WASM crate which wraps +this logic, and a collator node. diff --git a/polkadot/parachain/test-parachains/adder/collator/README.md b/polkadot/parachain/test-parachains/adder/collator/README.md index a1378544c386..dd737627c9ad 100644 --- a/polkadot/parachain/test-parachains/adder/collator/README.md +++ b/polkadot/parachain/test-parachains/adder/collator/README.md @@ -19,7 +19,7 @@ Next start the collator that will collate for the adder parachain: cargo run --release -p test-parachain-adder-collator -- --tmp --chain rococo-local --port 50553 ``` -The last step is to register the parachain using polkadot-js. The parachain id is +The last step is to register the parachain using `polkadot-js`. The parachain id is 100. The genesis state and the validation code are printed at startup by the collator. To do this automatically, run `scripts/adder-collator.sh`. diff --git a/polkadot/roadmap/implementers-guide/src/README.md b/polkadot/roadmap/implementers-guide/src/README.md index 9b6189992773..6673c533ece4 100644 --- a/polkadot/roadmap/implementers-guide/src/README.md +++ b/polkadot/roadmap/implementers-guide/src/README.md @@ -1,5 +1,11 @@ # Preamble -This document aims to describe the purpose, functionality, and implementation of the host for Polkadot's _parachains_ functionality - that is, the software which provides security and advancement for constituent parachains. It is not for the implementer of a specific parachain but rather for the implementer of the Parachain Host. In practice, this is for the implementers of Polkadot in general. +This document aims to describe the purpose, functionality, and implementation of the host for Polkadot's _parachains_ +functionality - that is, the software which provides security and advancement for constituent parachains. It is not for +the implementer of a specific parachain but rather for the implementer of the Parachain Host. In practice, this is for +the implementers of Polkadot in general. -There are a number of other documents describing the research in more detail. All referenced documents will be linked here and should be read alongside this document for the best understanding of the full picture. However, this is the only document which aims to describe key aspects of Polkadot's particular instantiation of much of that research down to low-level technical details and software architecture. +There are a number of other documents describing the research in more detail. All referenced documents will be linked +here and should be read alongside this document for the best understanding of the full picture. However, this is the +only document which aims to describe key aspects of Polkadot's particular instantiation of much of that research down to +low-level technical details and software architecture. diff --git a/polkadot/roadmap/implementers-guide/src/SUMMARY.md b/polkadot/roadmap/implementers-guide/src/SUMMARY.md index e997d4d77ad1..bb19390c7af4 100644 --- a/polkadot/roadmap/implementers-guide/src/SUMMARY.md +++ b/polkadot/roadmap/implementers-guide/src/SUMMARY.md @@ -71,16 +71,16 @@ - [Chain Selection Request](node/utility/chain-selection.md) - [PVF Pre-Checking](node/utility/pvf-prechecker.md) - [Data Structures and Types](types/README.md) - - [Candidate](types/candidate.md) - - [Backing](types/backing.md) - - [Availability](types/availability.md) - - [Overseer and Subsystem Protocol](types/overseer-protocol.md) - - [Runtime](types/runtime.md) - - [Messages](types/messages.md) - - [Network](types/network.md) - - [Approvals](types/approval.md) - - [Disputes](types/disputes.md) - - [PVF Pre-checking](types/pvf-prechecking.md) + - [Candidate](types/candidate.md) + - [Backing](types/backing.md) + - [Availability](types/availability.md) + - [Overseer and Subsystem Protocol](types/overseer-protocol.md) + - [Runtime](types/runtime.md) + - [Messages](types/messages.md) + - [Network](types/network.md) + - [Approvals](types/approval.md) + - [Disputes](types/disputes.md) + - [PVF Pre-checking](types/pvf-prechecking.md) [Glossary](glossary.md) [Further Reading](further-reading.md) diff --git a/polkadot/roadmap/implementers-guide/src/architecture.md b/polkadot/roadmap/implementers-guide/src/architecture.md index 0c192a5b980d..b75270662005 100644 --- a/polkadot/roadmap/implementers-guide/src/architecture.md +++ b/polkadot/roadmap/implementers-guide/src/architecture.md @@ -1,8 +1,13 @@ # Architecture Overview -This section aims to describe, at a high level, the code architecture and subsystems involved in the implementation of an individual Parachain Host. It also illuminates certain subtleties and challenges faced in the design and implementation of those subsystems. +This section aims to describe, at a high level, the code architecture and subsystems involved in the implementation of +an individual Parachain Host. It also illuminates certain subtleties and challenges faced in the design and +implementation of those subsystems. -To recap, Polkadot includes a blockchain known as the relay-chain. A blockchain is a Directed Acyclic Graph (DAG) of state transitions, where every block can be considered to be the head of a linked-list (known as a "chain" or "fork") with a cumulative state which is determined by applying the state transition of each block in turn. All paths through the DAG terminate at the Genesis Block. In fact, the blockchain is a tree, since each block can have only one parent. +To recap, Polkadot includes a blockchain known as the relay-chain. A blockchain is a Directed Acyclic Graph (DAG) of +state transitions, where every block can be considered to be the head of a linked-list (known as a "chain" or "fork") +with a cumulative state which is determined by applying the state transition of each block in turn. All paths through +the DAG terminate at the Genesis Block. In fact, the blockchain is a tree, since each block can have only one parent. ```dot process digraph { @@ -22,16 +27,25 @@ digraph { } ``` -A blockchain network is comprised of nodes. These nodes each have a view of many different forks of a blockchain and must decide which forks to follow and what actions to take based on the forks of the chain that they are aware of. +A blockchain network is comprised of nodes. These nodes each have a view of many different forks of a blockchain and +must decide which forks to follow and what actions to take based on the forks of the chain that they are aware of. -So in specifying an architecture to carry out the functionality of a Parachain Host, we have to answer two categories of questions: +So in specifying an architecture to carry out the functionality of a Parachain Host, we have to answer two categories of +questions: -1. What is the state-transition function of the blockchain? What is necessary for a transition to be considered valid, and what information is carried within the implicit state of a block? -1. Being aware of various forks of the blockchain as well as global private state such as a view of the current time, what behaviors should a node undertake? What information should a node extract from the state of which forks, and how should that information be used? +1. What is the state-transition function of the blockchain? What is necessary for a transition to be considered valid, + and what information is carried within the implicit state of a block? +1. Being aware of various forks of the blockchain as well as global private state such as a view of the current time, + what behaviors should a node undertake? What information should a node extract from the state of which forks, and how + should that information be used? -The first category of questions will be addressed by the Runtime, which defines the state-transition logic of the chain. Runtime logic only has to focus on the perspective of one chain, as each state has only a single parent state. +The first category of questions will be addressed by the Runtime, which defines the state-transition logic of the chain. +Runtime logic only has to focus on the perspective of one chain, as each state has only a single parent state. -The second category of questions addressed by Node-side behavior. Node-side behavior defines all activities that a node undertakes, given its view of the blockchain/block-DAG. Node-side behavior can take into account all or many of the forks of the blockchain, and only conditionally undertake certain activities based on which forks it is aware of, as well as the state of the head of those forks. +The second category of questions addressed by Node-side behavior. Node-side behavior defines all activities that a node +undertakes, given its view of the blockchain/block-DAG. Node-side behavior can take into account all or many of the +forks of the blockchain, and only conditionally undertake certain activities based on which forks it is aware of, as +well as the state of the head of those forks. ```dot process digraph G { @@ -46,7 +60,13 @@ digraph G { ``` -It is also helpful to divide Node-side behavior into two further categories: Networking and Core. Networking behaviors relate to how information is distributed between nodes. Core behaviors relate to internal work that a specific node does. These two categories of behavior often interact, but can be heavily abstracted from each other. Core behaviors care that information is distributed and received, but not the internal details of how distribution and receipt function. Networking behaviors act on requests for distribution or fetching of information, but are not concerned with how the information is used afterwards. This allows us to create clean boundaries between Core and Networking activities, improving the modularity of the code. +It is also helpful to divide Node-side behavior into two further categories: Networking and Core. Networking behaviors +relate to how information is distributed between nodes. Core behaviors relate to internal work that a specific node +does. These two categories of behavior often interact, but can be heavily abstracted from each other. Core behaviors +care that information is distributed and received, but not the internal details of how distribution and receipt +function. Networking behaviors act on requests for distribution or fetching of information, but are not concerned with +how the information is used afterwards. This allows us to create clean boundaries between Core and Networking +activities, improving the modularity of the code. ```text ___________________ ____________________ @@ -65,8 +85,18 @@ It is also helpful to divide Node-side behavior into two further categories: Net ``` -Node-side behavior is split up into various subsystems. Subsystems are long-lived workers that perform a particular category of work. Subsystems can communicate with each other, and do so via an [Overseer](node/overseer.md) that prevents race conditions. - -Runtime logic is divided up into Modules and APIs. Modules encapsulate particular behavior of the system. Modules consist of storage, routines, and entry-points. Routines are invoked by entry points, by other modules, upon block initialization or closing. Routines can read and alter the storage of the module. Entry-points are the means by which new information is introduced to a module and can limit the origins (user, root, parachain) that they accept being called by. Each block in the blockchain contains a set of Extrinsics. Each extrinsic targets a a specific entry point to trigger and which data should be passed to it. Runtime APIs provide a means for Node-side behavior to extract meaningful information from the state of a single fork. - -These two aspects of the implementation are heavily dependent on each other. The Runtime depends on Node-side behavior to author blocks, and to include Extrinsics which trigger the correct entry points. The Node-side behavior relies on Runtime APIs to extract information necessary to determine which actions to take. +Node-side behavior is split up into various subsystems. Subsystems are long-lived workers that perform a particular +category of work. Subsystems can communicate with each other, and do so via an [Overseer](node/overseer.md) that +prevents race conditions. + +Runtime logic is divided up into Modules and APIs. Modules encapsulate particular behavior of the system. Modules +consist of storage, routines, and entry-points. Routines are invoked by entry points, by other modules, upon block +initialization or closing. Routines can read and alter the storage of the module. Entry-points are the means by which +new information is introduced to a module and can limit the origins (user, root, parachain) that they accept being +called by. Each block in the blockchain contains a set of Extrinsics. Each extrinsic targets a a specific entry point to +trigger and which data should be passed to it. Runtime APIs provide a means for Node-side behavior to extract meaningful +information from the state of a single fork. + +These two aspects of the implementation are heavily dependent on each other. The Runtime depends on Node-side behavior +to author blocks, and to include Extrinsics which trigger the correct entry points. The Node-side behavior relies on +Runtime APIs to extract information necessary to determine which actions to take. diff --git a/polkadot/roadmap/implementers-guide/src/disputes-flow.md b/polkadot/roadmap/implementers-guide/src/disputes-flow.md index a325b2ce7272..f9fd8dcce351 100644 --- a/polkadot/roadmap/implementers-guide/src/disputes-flow.md +++ b/polkadot/roadmap/implementers-guide/src/disputes-flow.md @@ -70,10 +70,12 @@ stateDiagram-v2 ## Conditional formulation -The set of validators eligible to vote consists of -the validators that had duty at the time of backing, plus backing votes by the backing validators. +The set of validators eligible to vote consists of the validators that had duty at the time of backing, plus backing +votes by the backing validators. -If a validator receives an initial dispute message (a set of votes where there are at least two opposing votes contained), and the PoV or Code are hence not reconstructable from local storage, that validator must request the required data from its peers. +If a validator receives an initial dispute message (a set of votes where there are at least two opposing votes +contained), and the PoV or Code are hence not reconstructable from local storage, that validator must request the +required data from its peers. The dispute availability message must contain code, persisted validation data, and the proof of validity. @@ -81,9 +83,11 @@ Only peers that already voted shall be queried for the dispute availability data The peer to be queried for disputes data, must be picked at random. -A validator must retain code, persisted validation data and PoV until a block, that contains the dispute resolution, is finalized - plus an additional 24 hours. +A validator must retain code, persisted validation data and PoV until a block, that contains the dispute resolution, is +finalized - plus an additional 24 hours. -Dispute availability gossip must continue beyond the dispute resolution, until the post resolution timeout expired (equiv to the timeout until which additional late votes are accepted). +Dispute availability gossip must continue beyond the dispute resolution, until the post resolution timeout expired +(equiv to the timeout until which additional late votes are accepted). Remote disputes are disputes that are in relation to a chain that is not part of the local validators active heads. @@ -93,32 +97,42 @@ Persisted votes stay persisted for `N` sessions, and are cleaned up on a per ses Votes must be queryable by a particular validator, identified by its signing key. -Votes must be queryable by a particular validator, identified by a session index and the validator index valid in that session. +Votes must be queryable by a particular validator, identified by a session index and the validator index valid in that +session. If there exists a negative and a positive vote for a particular block, a dispute is detected. If a dispute is detected, all currently available votes for that block must be gossiped. -If an incoming dispute vote is detected, a validator must cast their own vote. The vote is determined by validating the PoV with the Code at the time of backing the block in question. +If an incoming dispute vote is detected, a validator must cast their own vote. The vote is determined by validating the +PoV with the Code at the time of backing the block in question. If the validator was also a backer of the block, validation and casting an additional vote should be skipped. -If the count of votes pro or cons regarding the disputed block, reaches the required ⅔ supermajority (including the backing votes), the conclusion must be recorded on chain and the voters on the loosing and no-shows being slashed appropriately. +If the count of votes pro or cons regarding the disputed block, reaches the required ⅔ supermajority (including the +backing votes), the conclusion must be recorded on chain and the voters on the loosing and no-shows being slashed +appropriately. -If a block is found invalid by a dispute resolution, it must be blacklisted to avoid resync or further build on that chain if other chains are available (to be detailed in the grandpa fork choice rule). +If a block is found invalid by a dispute resolution, it must be blacklisted to avoid resync or further build on that +chain if other chains are available (to be detailed in the grandpa fork choice rule). A dispute accepts Votes after the dispute is resolved, for 1 day. -If a vote is received, after the dispute is resolved, the vote shall still be recorded in the state root, albeit yielding less reward. +If a vote is received, after the dispute is resolved, the vote shall still be recorded in the state root, albeit +yielding less reward. Recording in the state root might happen batched, at timeout expiry. -If a new active head/chain appears, and the dispute resolution was not recorded on that chain yet, the dispute resolution or open dispute must be recorded / transplanted to that chain as well, since the disputes must be present on all chains to make sure the offender is punished. +If a new active head/chain appears, and the dispute resolution was not recorded on that chain yet, the dispute +resolution or open dispute must be recorded / transplanted to that chain as well, since the disputes must be present on +all chains to make sure the offender is punished. -If a validator votes in two opposing ways, this composes of a double vote like in other cases (backing, approval voting). +If a validator votes in two opposing ways, this composes of a double vote like in other cases (backing, approval +voting). If a dispute is not resolved within due time, all validators are to be slashed for a small amount. If a dispute is not resolved within due time, governance mode shall be entered for manual resolution. -If a validator unexpectedly restarts, the dispute shall be continued with the state based on votes being cast and being present in persistent storage. +If a validator unexpectedly restarts, the dispute shall be continued with the state based on votes being cast and being +present in persistent storage. diff --git a/polkadot/roadmap/implementers-guide/src/glossary.md b/polkadot/roadmap/implementers-guide/src/glossary.md index a036ccdd668c..b2365ba51c5c 100644 --- a/polkadot/roadmap/implementers-guide/src/glossary.md +++ b/polkadot/roadmap/implementers-guide/src/glossary.md @@ -2,46 +2,72 @@ Here you can find definitions of a bunch of jargon, usually specific to the Polkadot project. -- **Approval Checker:** A validator who randomly self-selects so to perform validity checks on a parablock which is pending approval. -- **BABE:** (Blind Assignment for Blockchain Extension). The algorithm validators use to safely extend the Relay Chain. See [the Polkadot wiki][0] for more information. -- **Backable Candidate:** A Parachain Candidate which is backed by a majority of validators assigned to a given parachain. +- **Approval Checker:** A validator who randomly self-selects so to perform validity checks on a parablock which is + pending approval. +- **BABE:** (Blind Assignment for Blockchain Extension). The algorithm validators use to safely extend the Relay Chain. + See [the Polkadot wiki][0] for more information. +- **Backable Candidate:** A Parachain Candidate which is backed by a majority of validators assigned to a given + parachain. - **Backed Candidate:** A Backable Candidate noted in a relay-chain block - **Backing:** A set of statements proving that a Parachain Candidate is backable. - **Collator:** A node who generates Proofs-of-Validity (PoV) for blocks of a specific parachain. -- **DMP:** (Downward Message Passing). Message passing from the relay-chain to a parachain. Also there is a runtime parachains module with the same name. -- **DMQ:** (Downward Message Queue). A message queue for messages from the relay-chain down to a parachain. A parachain has -exactly one downward message queue. -- **Extrinsic:** An element of a relay-chain block which triggers a specific entry-point of a runtime module with given arguments. -- **GRANDPA:** (Ghost-based Recursive ANcestor Deriving Prefix Agreement). The algorithm validators use to guarantee finality of the Relay Chain. -- **HRMP:** (Horizontally Relay-routed Message Passing). A mechanism for message passing between parachains (hence horizontal) that leverages the relay-chain storage. Predates XCMP. Also there is a runtime parachains module with the same name. -- **Inclusion Pipeline:** The set of steps taken to carry a Parachain Candidate from authoring, to backing, to availability and full inclusion in an active fork of its parachain. +- **DMP:** (Downward Message Passing). Message passing from the relay-chain to a parachain. Also there is a runtime + parachains module with the same name. +- **DMQ:** (Downward Message Queue). A message queue for messages from the relay-chain down to a parachain. A parachain +has exactly one downward message queue. +- **Extrinsic:** An element of a relay-chain block which triggers a specific entry-point of a runtime module with given + arguments. +- **GRANDPA:** (Ghost-based Recursive ANcestor Deriving Prefix Agreement). The algorithm validators use to guarantee + finality of the Relay Chain. +- **HRMP:** (Horizontally Relay-routed Message Passing). A mechanism for message passing between parachains (hence + horizontal) that leverages the relay-chain storage. Predates XCMP. Also there is a runtime parachains module with the + same name. +- **Inclusion Pipeline:** The set of steps taken to carry a Parachain Candidate from authoring, to backing, to + availability and full inclusion in an active fork of its parachain. - **Module:** A component of the Runtime logic, encapsulating storage, routines, and entry-points. - **Module Entry Point:** A recipient of new information presented to the Runtime. This may trigger routines. -- **Module Routine:** A piece of code executed within a module by block initialization, closing, or upon an entry point being triggered. This may execute computation, and read or write storage. -- **MQC:** (Message Queue Chain). A cryptographic data structure that resembles an append-only linked list which doesn't store original values but only their hashes. The whole structure is described by a single hash, referred as a "head". When a value is appended, it's contents hashed with the previous head creating a hash that becomes a new head. -- **Node:** A participant in the Polkadot network, who follows the protocols of communication and connection to other nodes. Nodes form a peer-to-peer network topology without a central authority. +- **Module Routine:** A piece of code executed within a module by block initialization, closing, or upon an entry point + being triggered. This may execute computation, and read or write storage. +- **MQC:** (Message Queue Chain). A cryptographic data structure that resembles an append-only linked list which doesn't + store original values but only their hashes. The whole structure is described by a single hash, referred as a "head". + When a value is appended, it's contents hashed with the previous head creating a hash that becomes a new head. +- **Node:** A participant in the Polkadot network, who follows the protocols of communication and connection to other + nodes. Nodes form a peer-to-peer network topology without a central authority. - **Parachain Candidate, or Candidate:** A proposed block for inclusion into a parachain. - **Parablock:** A block in a parachain. - **Parachain:** A constituent chain secured by the Relay Chain's validators. -- **Parachain Validators:** A subset of validators assigned during a period of time to back candidates for a specific parachain +- **Parachain Validators:** A subset of validators assigned during a period of time to back candidates for a specific + parachain - **On-demand parachain:** A parachain which is scheduled on a pay-as-you-go basis. -- **Lease holding parachain:** A parachain possessing an active slot lease. The lease holder is assigned a single availability core for the duration of the lease, granting consistent blockspace scheduling at the rate 1 parablock per relay block. +- **Lease holding parachain:** A parachain possessing an active slot lease. The lease holder is assigned a single + availability core for the duration of the lease, granting consistent blockspace scheduling at the rate 1 parablock per + relay block. - **PDK (Parachain Development Kit):** A toolset that allows one to develop a parachain. Cumulus is a PDK. -- **Preimage:** In our context, if `H(X) = Y` where `H` is a hash function and `Y` is the hash, then `X` is the hash preimage. -- **Proof-of-Validity (PoV):** A stateless-client proof that a parachain candidate is valid, with respect to some validation function. +- **Preimage:** In our context, if `H(X) = Y` where `H` is a hash function and `Y` is the hash, then `X` is the hash + preimage. +- **Proof-of-Validity (PoV):** A stateless-client proof that a parachain candidate is valid, with respect to some + validation function. - **PVF:** Parachain Validation Function. The validation code that is run by validators on parachains. -- **PVF Prechecking:** This is the process of initially checking the PVF when it is first added. We attempt preparation of the PVF and make sure it succeeds within a given timeout, plus some additional checks. -- **PVF Preparation:** This is the process of preparing the WASM blob and includes both prevalidation and compilation. As there is no prevalidation right now, preparation just consists of compilation. -- **Relay Parent:** A block in the relay chain, referred to in a context where work is being done in the context of the state at this block. +- **PVF Prechecking:** This is the process of initially checking the PVF when it is first added. We attempt preparation + of the PVF and make sure it succeeds within a given timeout, plus some additional checks. +- **PVF Preparation:** This is the process of preparing the WASM blob and includes both prevalidation and compilation. + As there is no prevalidation right now, preparation just consists of compilation. +- **Relay Parent:** A block in the relay chain, referred to in a context where work is being done in the context of the + state at this block. - **Runtime:** The relay-chain state machine. - **Runtime Module:** See Module. -- **Runtime API:** A means for the node-side behavior to access structured information based on the state of a fork of the blockchain. +- **Runtime API:** A means for the node-side behavior to access structured information based on the state of a fork of + the blockchain. - **Subsystem:** A long-running task which is responsible for carrying out a particular category of work. - **UMP:** (Upward Message Passing) A vertical message passing mechanism from a parachain to the relay chain. -- **Validator:** Specially-selected node in the network who is responsible for validating parachain blocks and issuing attestations about their validity. +- **Validator:** Specially-selected node in the network who is responsible for validating parachain blocks and issuing + attestations about their validity. - **Validation Function:** A piece of Wasm code that describes the state-transition function of a parachain. -- **VMP:** (Vertical Message Passing) A family of mechanisms that are responsible for message exchange between the relay chain and parachains. -- **XCMP:** (Cross-Chain Message Passing) A type of horizontal message passing (i.e. between parachains) that allows secure message passing directly between parachains and has minimal resource requirements from the relay chain, thus highly scalable. +- **VMP:** (Vertical Message Passing) A family of mechanisms that are responsible for message exchange between the relay + chain and parachains. +- **XCMP:** (Cross-Chain Message Passing) A type of horizontal message passing (i.e. between parachains) that allows + secure message passing directly between parachains and has minimal resource requirements from the relay chain, thus + highly scalable. ## See Also diff --git a/polkadot/roadmap/implementers-guide/src/messaging.md b/polkadot/roadmap/implementers-guide/src/messaging.md index edc810e03415..11cd3565e8ed 100644 --- a/polkadot/roadmap/implementers-guide/src/messaging.md +++ b/polkadot/roadmap/implementers-guide/src/messaging.md @@ -1,9 +1,9 @@ # Messaging Overview -The Polkadot Host has a few mechanisms that are responsible for message passing. They can be generally divided -on two categories: Horizontal and Vertical. Horizontal Message Passing (HMP) refers to mechanisms -that are responsible for exchanging messages between parachains. Vertical Message Passing (VMP) is -used for communication between the relay chain and parachains. +The Polkadot Host has a few mechanisms that are responsible for message passing. They can be generally divided on two +categories: Horizontal and Vertical. Horizontal Message Passing (HMP) refers to mechanisms that are responsible for +exchanging messages between parachains. Vertical Message Passing (VMP) is used for communication between the relay chain +and parachains. ## Vertical Message Passing @@ -19,35 +19,34 @@ digraph { Downward Message Passing (DMP) is a mechanism for delivering messages to parachains from the relay chain. -Each parachain has its own queue that stores all pending inbound downward messages. A parachain -doesn't have to process all messages at once, however, there are rules as to how the downward message queue -should be processed. Currently, at least one message must be consumed per candidate if the queue is not empty. -The downward message queue doesn't have a cap on its size and it is up to the relay-chain to put mechanisms -that prevent spamming in place. +Each parachain has its own queue that stores all pending inbound downward messages. A parachain doesn't have to process +all messages at once, however, there are rules as to how the downward message queue should be processed. Currently, at +least one message must be consumed per candidate if the queue is not empty. The downward message queue doesn't have a +cap on its size and it is up to the relay-chain to put mechanisms that prevent spamming in place. -Upward Message Passing (UMP) is a mechanism responsible for delivering messages in the opposite direction: -from a parachain up to the relay chain. Upward messages are essentially byte blobs. However, they are interpreted -by the relay-chain according to the XCM standard. +Upward Message Passing (UMP) is a mechanism responsible for delivering messages in the opposite direction: from a +parachain up to the relay chain. Upward messages are essentially byte blobs. However, they are interpreted by the +relay-chain according to the XCM standard. -The XCM standard is a common vocabulary of messages. The XCM standard doesn't require a particular interpretation of -a message. However, the parachains host (e.g. Polkadot) guarantees certain semantics for those. +The XCM standard is a common vocabulary of messages. The XCM standard doesn't require a particular interpretation of a +message. However, the parachains host (e.g. Polkadot) guarantees certain semantics for those. -Moreover, while most XCM messages are handled by the on-chain XCM interpreter, some of the messages are special -cased. Specifically, those messages can be checked during the acceptance criteria and thus invalid -messages would lead to rejecting the candidate itself. +Moreover, while most XCM messages are handled by the on-chain XCM interpreter, some of the messages are special cased. +Specifically, those messages can be checked during the acceptance criteria and thus invalid messages would lead to +rejecting the candidate itself. -One kind of such a message is `Xcm::Transact`. This upward message can be seen as a way for a parachain -to execute arbitrary entrypoints on the relay-chain. `Xcm::Transact` messages resemble regular extrinsics with the exception that they -originate from a parachain. +One kind of such a message is `Xcm::Transact`. This upward message can be seen as a way for a parachain to execute +arbitrary entrypoints on the relay-chain. `Xcm::Transact` messages resemble regular extrinsics with the exception that +they originate from a parachain. -The payload of `Xcm::Transact` messages is referred as to `Dispatchable`. When a candidate with such a message is enacted -the dispatchables are put into a queue corresponding to the parachain. There can be only so many dispatchables in that queue at once. -The weight that processing of the dispatchables can consume is limited by a preconfigured value. Therefore, it is possible -that some dispatchables will be left for later blocks. To make the dispatching more fair, the queues are processed turn-by-turn -in a round robin fashion. +The payload of `Xcm::Transact` messages is referred as to `Dispatchable`. When a candidate with such a message is +enacted the dispatchables are put into a queue corresponding to the parachain. There can be only so many dispatchables +in that queue at once. The weight that processing of the dispatchables can consume is limited by a preconfigured value. +Therefore, it is possible that some dispatchables will be left for later blocks. To make the dispatching more fair, the +queues are processed turn-by-turn in a round robin fashion. -The second category of special cased XCM messages are for horizontal messaging channel management, -namely messages meant to request opening and closing HRMP channels (HRMP will be described below). +The second category of special cased XCM messages are for horizontal messaging channel management, namely messages meant +to request opening and closing HRMP channels (HRMP will be described below). ## Horizontal Message Passing @@ -77,29 +76,28 @@ The most important member of this family is XCMP. > ℹ️ XCMP is currently under construction and details are subject for change. -XCMP is a message passing mechanism between parachains that require minimal involvement of the relay chain. -The relay chain provides means for sending parachains to authenticate messages sent to recipient parachains. +XCMP is a message passing mechanism between parachains that require minimal involvement of the relay chain. The relay +chain provides means for sending parachains to authenticate messages sent to recipient parachains. -Semantically communication occurs through so called channels. A channel is unidirectional and it has -two endpoints, for sender and for recipient. A channel can be opened only if the both parties agree -and closed unilaterally. +Semantically communication occurs through so called channels. A channel is unidirectional and it has two endpoints, for +sender and for recipient. A channel can be opened only if the both parties agree and closed unilaterally. -Only the channel metadata is stored on the relay-chain in a very compact form: all messages and their -contents sent by the sender parachain are encoded using only one root hash. This root is referred as -MQC head. +Only the channel metadata is stored on the relay-chain in a very compact form: all messages and their contents sent by +the sender parachain are encoded using only one root hash. This root is referred as MQC head. -The authenticity of the messages must be proven using that root hash to the receiving party at the -candidate authoring time. The proof stems from the relay parent storage that contains the root hash of the channel. -Since not all messages are required to be processed by the receiver's candidate, only the processed -messages are supplied (i.e. preimages), rest are provided as hashes. +The authenticity of the messages must be proven using that root hash to the receiving party at the candidate authoring +time. The proof stems from the relay parent storage that contains the root hash of the channel. Since not all messages +are required to be processed by the receiver's candidate, only the processed messages are supplied (i.e. preimages), +rest are provided as hashes. -Further details can be found at the official repository for the -[Cross-Consensus Message Format (XCM)](https://github.com/paritytech/xcm-format/blob/master/README.md), as well as -at the [W3F research website](https://research.web3.foundation/en/latest/polkadot/XCMP.html) and -[this blogpost](https://medium.com/web3foundation/polkadots-messaging-scheme-b1ec560908b7). +Further details can be found at the official repository for the [Cross-Consensus Message Format +(XCM)](https://github.com/paritytech/xcm-format/blob/master/README.md), as well as at the [W3F research +website](https://research.web3.foundation/en/latest/polkadot/XCMP.html) and [this +blogpost](https://medium.com/web3foundation/polkadots-messaging-scheme-b1ec560908b7). -HRMP (Horizontally Relay-routed Message Passing) is a stop gap that predates XCMP. Semantically, it mimics XCMP's interface. -The crucial difference from XCMP though is that all the messages are stored in the relay-chain storage. That makes -things simple but at the same time that makes HRMP more demanding in terms of resources thus making it more expensive. +HRMP (Horizontally Relay-routed Message Passing) is a stop gap that predates XCMP. Semantically, it mimics XCMP's +interface. The crucial difference from XCMP though is that all the messages are stored in the relay-chain storage. That +makes things simple but at the same time that makes HRMP more demanding in terms of resources thus making it more +expensive. Once XCMP is available we expect to retire HRMP. diff --git a/polkadot/roadmap/implementers-guide/src/node/README.md b/polkadot/roadmap/implementers-guide/src/node/README.md index edd72d2335b5..c67f2b0b82ee 100644 --- a/polkadot/roadmap/implementers-guide/src/node/README.md +++ b/polkadot/roadmap/implementers-guide/src/node/README.md @@ -2,30 +2,49 @@ ## Design Goals -* Modularity: Components of the system should be as self-contained as possible. Communication boundaries between components should be well-defined and mockable. This is key to creating testable, easily reviewable code. -* Minimizing side effects: Components of the system should aim to minimize side effects and to communicate with other components via message-passing. -* Operational Safety: The software will be managing signing keys where conflicting messages can lead to large amounts of value to be slashed. Care should be taken to ensure that no messages are signed incorrectly or in conflict with each other. +* Modularity: Components of the system should be as self-contained as possible. Communication boundaries between + components should be well-defined and mockable. This is key to creating testable, easily reviewable code. +* Minimizing side effects: Components of the system should aim to minimize side effects and to communicate with other + components via message-passing. +* Operational Safety: The software will be managing signing keys where conflicting messages can lead to large amounts of + value to be slashed. Care should be taken to ensure that no messages are signed incorrectly or in conflict with each + other. -The architecture of the node-side behavior aims to embody the Rust principles of ownership and message-passing to create clean, isolatable code. Each resource should have a single owner, with minimal sharing where unavoidable. +The architecture of the node-side behavior aims to embody the Rust principles of ownership and message-passing to create +clean, isolatable code. Each resource should have a single owner, with minimal sharing where unavoidable. -Many operations that need to be carried out involve the network, which is asynchronous. This asynchrony affects all core subsystems that rely on the network as well. The approach of hierarchical state machines is well-suited to this kind of environment. +Many operations that need to be carried out involve the network, which is asynchronous. This asynchrony affects all core +subsystems that rely on the network as well. The approach of hierarchical state machines is well-suited to this kind of +environment. We introduce ## Components The node architecture consists of the following components: - * The Overseer (and subsystems): A hierarchy of state machines where an overseer supervises subsystems. Subsystems can contain their own internal hierarchy of jobs. This is elaborated on in the next section on Subsystems. + * The Overseer (and subsystems): A hierarchy of state machines where an overseer supervises subsystems. Subsystems can + contain their own internal hierarchy of jobs. This is elaborated on in the next section on Subsystems. * A block proposer: Logic triggered by the consensus algorithm of the chain when the node should author a block. - * A GRANDPA voting rule: A strategy for selecting chains to vote on in the GRANDPA algorithm to ensure that only valid parachain candidates appear in finalized relay-chain blocks. + * A GRANDPA voting rule: A strategy for selecting chains to vote on in the GRANDPA algorithm to ensure that only valid + parachain candidates appear in finalized relay-chain blocks. ## Assumptions -The Node-side code comes with a set of assumptions that we build upon. These assumptions encompass most of the fundamental blockchain functionality. +The Node-side code comes with a set of assumptions that we build upon. These assumptions encompass most of the +fundamental blockchain functionality. We assume the following constraints regarding provided basic functionality: * The underlying **consensus** algorithm, whether it is BABE or SASSAFRAS is implemented. - * There is a **chain synchronization** protocol which will search for and download the longest available chains at all times. - * The **state** of all blocks at the head of the chain is available. There may be **state pruning** such that state of the last `k` blocks behind the last finalized block are available, as well as the state of all their descendants. This assumption implies that the state of all active leaves and their last `k` ancestors are all available. The underlying implementation is expected to support `k` of a few hundred blocks, but we reduce this to a very conservative `k=5` for our purposes. - * There is an underlying **networking** framework which provides **peer discovery** services which will provide us with peers and will not create "loopback" connections to our own node. The number of peers we will have is assumed to be bounded at 1000. - * There is a **transaction pool** and a **transaction propagation** mechanism which maintains a set of current transactions and distributes to connected peers. Current transactions are those which are not outdated relative to some "best" fork of the chain, which is part of the active heads, and have not been included in the best fork. + * There is a **chain synchronization** protocol which will search for and download the longest available chains at all + times. + * The **state** of all blocks at the head of the chain is available. There may be **state pruning** such that state of + the last `k` blocks behind the last finalized block are available, as well as the state of all their descendants. + This assumption implies that the state of all active leaves and their last `k` ancestors are all available. The + underlying implementation is expected to support `k` of a few hundred blocks, but we reduce this to a very + conservative `k=5` for our purposes. + * There is an underlying **networking** framework which provides **peer discovery** services which will provide us + with peers and will not create "loopback" connections to our own node. The number of peers we will have is assumed + to be bounded at 1000. + * There is a **transaction pool** and a **transaction propagation** mechanism which maintains a set of current + transactions and distributes to connected peers. Current transactions are those which are not outdated relative to + some "best" fork of the chain, which is part of the active heads, and have not been included in the best fork. diff --git a/polkadot/roadmap/implementers-guide/src/node/approval/README.md b/polkadot/roadmap/implementers-guide/src/node/approval/README.md index 1f65173e16bb..ae9f46674e54 100644 --- a/polkadot/roadmap/implementers-guide/src/node/approval/README.md +++ b/polkadot/roadmap/implementers-guide/src/node/approval/README.md @@ -2,6 +2,9 @@ The approval subsystems implement the node-side of the [Approval Protocol](../../protocol-approval.md). -We make a divide between the [assignment/voting logic](approval-voting.md) and the [distribution logic](approval-distribution.md) that distributes assignment certifications and approval votes. The logic in the assignment and voting also informs the GRANDPA voting rule on how to vote. +We make a divide between the [assignment/voting logic](approval-voting.md) and the [distribution +logic](approval-distribution.md) that distributes assignment certifications and approval votes. The logic in the +assignment and voting also informs the GRANDPA voting rule on how to vote. -These subsystems are intended to flag issues and begin participating in live disputes. Dispute subsystems also track all observed votes (backing, approval, and dispute-specific) by all validators on all candidates. +These subsystems are intended to flag issues and begin participating in live disputes. Dispute subsystems also track all +observed votes (backing, approval, and dispute-specific) by all validators on all candidates. diff --git a/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md b/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md index 81c98afa16bf..ce71de6f76b8 100644 --- a/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md @@ -2,50 +2,73 @@ A subsystem for the distribution of assignments and approvals for approval checks on candidates over the network. -The [Approval Voting](approval-voting.md) subsystem is responsible for active participation in a protocol designed to select a sufficient number of validators to check each and every candidate which appears in the relay chain. Statements of participation in this checking process are divided into two kinds: - - **Assignments** indicate that validators have been selected to do checking - - **Approvals** indicate that validators have checked and found the candidate satisfactory. - -The [Approval Voting](approval-voting.md) subsystem handles all the issuing and tallying of this protocol, but this subsystem is responsible for the disbursal of statements among the validator-set. - -The inclusion pipeline of candidates concludes after availability, and only after inclusion do candidates actually get pushed into the approval checking pipeline. As such, this protocol deals with the candidates _made available by_ particular blocks, as opposed to the candidates which actually appear within those blocks, which are the candidates _backed by_ those blocks. Unless stated otherwise, whenever we reference a candidate partially by block hash, we are referring to the set of candidates _made available by_ those blocks. - -We implement this protocol as a gossip protocol, and like other parachain-related gossip protocols our primary concerns are about ensuring fast message propagation while maintaining an upper bound on the number of messages any given node must store at any time. - -Approval messages should always follow assignments, so we need to be able to discern two pieces of information based on our [View](../../types/network.md#universal-types): +The [Approval Voting](approval-voting.md) subsystem is responsible for active participation in a protocol designed to +select a sufficient number of validators to check each and every candidate which appears in the relay chain. Statements +of participation in this checking process are divided into two kinds: + * **Assignments** indicate that validators have been selected to do checking + * **Approvals** indicate that validators have checked and found the candidate satisfactory. + +The [Approval Voting](approval-voting.md) subsystem handles all the issuing and tallying of this protocol, but this +subsystem is responsible for the disbursal of statements among the validator-set. + +The inclusion pipeline of candidates concludes after availability, and only after inclusion do candidates actually get +pushed into the approval checking pipeline. As such, this protocol deals with the candidates _made available by_ +particular blocks, as opposed to the candidates which actually appear within those blocks, which are the candidates +_backed by_ those blocks. Unless stated otherwise, whenever we reference a candidate partially by block hash, we are +referring to the set of candidates _made available by_ those blocks. + +We implement this protocol as a gossip protocol, and like other parachain-related gossip protocols our primary concerns +are about ensuring fast message propagation while maintaining an upper bound on the number of messages any given node +must store at any time. + +Approval messages should always follow assignments, so we need to be able to discern two pieces of information based on +our [View](../../types/network.md#universal-types): 1. Is a particular assignment relevant under a given `View`? 2. Is a particular approval relevant to any assignment in a set? -For our own local view, these two queries must not yield false negatives. When applied to our peers' views, it is acceptable for them to yield false negatives. The reason for that is that our peers' views may be beyond ours, and we are not capable of fully evaluating them. Once we have caught up, we can check again for false negatives to continue distributing. +For our own local view, these two queries must not yield false negatives. When applied to our peers' views, it is +acceptable for them to yield false negatives. The reason for that is that our peers' views may be beyond ours, and we +are not capable of fully evaluating them. Once we have caught up, we can check again for false negatives to continue +distributing. -For assignments, what we need to be checking is whether we are aware of the (block, candidate) pair that the assignment references. For approvals, we need to be aware of an assignment by the same validator which references the candidate being approved. +For assignments, what we need to be checking is whether we are aware of the (block, candidate) pair that the assignment +references. For approvals, we need to be aware of an assignment by the same validator which references the candidate +being approved. -However, awareness on its own of a (block, candidate) pair would imply that even ancient candidates all the way back to the genesis are relevant. We are actually not interested in anything before finality. +However, awareness on its own of a (block, candidate) pair would imply that even ancient candidates all the way back to +the genesis are relevant. We are actually not interested in anything before finality. -We gossip assignments along a grid topology produced by the [Gossip Support Subsystem](../utility/gossip-support.md) and also to a few random peers. The first time we accept an assignment or approval, regardless of the source, which originates from a validator peer in a shared dimension of the grid, we propagate the message to validator peers in the unshared dimension as well as a few random peers. +We gossip assignments along a grid topology produced by the [Gossip Support Subsystem](../utility/gossip-support.md) and +also to a few random peers. The first time we accept an assignment or approval, regardless of the source, which +originates from a validator peer in a shared dimension of the grid, we propagate the message to validator peers in the +unshared dimension as well as a few random peers. -But, in case these mechanisms don't work on their own, we need to trade bandwidth for protocol liveness by introducing aggression. +But, in case these mechanisms don't work on their own, we need to trade bandwidth for protocol liveness by introducing +aggression. Aggression has 3 levels: - Aggression Level 0: The basic behaviors described above. - Aggression Level 1: The originator of a message sends to all peers. Other peers follow the rules above. - Aggression Level 2: All peers send all messages to all their row and column neighbors. This means that each validator will, on average, receive each message approximately 2*sqrt(n) times. +* Aggression Level 0: The basic behaviors described above. +* Aggression Level 1: The originator of a message sends to all peers. Other peers follow the rules above. +* Aggression Level 2: All peers send all messages to all their row and column neighbors. This means that each validator + will, on average, receive each message approximately 2*sqrt(n) times. -These aggression levels are chosen based on how long a block has taken to finalize: assignments and approvals related to the unfinalized block will be propagated with more aggression. In particular, it's only the earliest unfinalized blocks that aggression should be applied to, because descendants may be unfinalized only by virtue of being descendants. +These aggression levels are chosen based on how long a block has taken to finalize: assignments and approvals related to +the unfinalized block will be propagated with more aggression. In particular, it's only the earliest unfinalized blocks +that aggression should be applied to, because descendants may be unfinalized only by virtue of being descendants. ## Protocol Input: - - `ApprovalDistributionMessage::NewBlocks` - - `ApprovalDistributionMessage::DistributeAssignment` - - `ApprovalDistributionMessage::DistributeApproval` - - `ApprovalDistributionMessage::NetworkBridgeUpdate` - - `OverseerSignal::BlockFinalized` + * `ApprovalDistributionMessage::NewBlocks` + * `ApprovalDistributionMessage::DistributeAssignment` + * `ApprovalDistributionMessage::DistributeApproval` + * `ApprovalDistributionMessage::NetworkBridgeUpdate` + * `OverseerSignal::BlockFinalized` Output: - - `ApprovalVotingMessage::CheckAndImportAssignment` - - `ApprovalVotingMessage::CheckAndImportApproval` - - `NetworkBridgeMessage::SendValidationMessage::ApprovalDistribution` + * `ApprovalVotingMessage::CheckAndImportAssignment` + * `ApprovalVotingMessage::CheckAndImportApproval` + * `NetworkBridgeMessage::SendValidationMessage::ApprovalDistribution` ## Functionality @@ -134,28 +157,37 @@ Iterate over every `BlockEntry` and remove `PeerId` from it. #### `NetworkBridgeEvent::OurViewChange` -Remove entries in `pending_known` for all hashes not present in the view. -Ensure a vector is present in `pending_known` for each hash in the view that does not have an entry in `blocks`. +Remove entries in `pending_known` for all hashes not present in the view. Ensure a vector is present in `pending_known` +for each hash in the view that does not have an entry in `blocks`. #### `NetworkBridgeEvent::PeerViewChange` Invoke `unify_with_peer(peer, view)` to catch them up to messages we have. -We also need to use the `view.finalized_number` to remove the `PeerId` from any blocks that it won't be wanting information about anymore. Note that we have to be on guard for peers doing crazy stuff like jumping their `finalized_number` forward 10 trillion blocks to try and get us stuck in a loop for ages. +We also need to use the `view.finalized_number` to remove the `PeerId` from any blocks that it won't be wanting +information about anymore. Note that we have to be on guard for peers doing crazy stuff like jumping their +`finalized_number` forward 10 trillion blocks to try and get us stuck in a loop for ages. -One of the safeguards we can implement is to reject view updates from peers where the new `finalized_number` is less than the previous. +One of the safeguards we can implement is to reject view updates from peers where the new `finalized_number` is less +than the previous. -We augment that by defining `constrain(x)` to output the x bounded by the first and last numbers in `state.blocks_by_number`. +We augment that by defining `constrain(x)` to output the x bounded by the first and last numbers in +`state.blocks_by_number`. -From there, we can loop backwards from `constrain(view.finalized_number)` until `constrain(last_view.finalized_number)` is reached, removing the `PeerId` from all `BlockEntry`s referenced at that height. We can break the loop early if we ever exit the bound supplied by the first block in `state.blocks_by_number`. +From there, we can loop backwards from `constrain(view.finalized_number)` until `constrain(last_view.finalized_number)` +is reached, removing the `PeerId` from all `BlockEntry`s referenced at that height. We can break the loop early if we +ever exit the bound supplied by the first block in `state.blocks_by_number`. #### `NetworkBridgeEvent::PeerMessage` -If the block hash referenced by the message exists in `pending_known`, add it to the vector of pending messages and return. +If the block hash referenced by the message exists in `pending_known`, add it to the vector of pending messages and +return. -If the message is of type `ApprovalDistributionV1Message::Assignment(assignment_cert, claimed_index)`, then call `import_and_circulate_assignment(MessageSource::Peer(sender), assignment_cert, claimed_index)` +If the message is of type `ApprovalDistributionV1Message::Assignment(assignment_cert, claimed_index)`, then call +`import_and_circulate_assignment(MessageSource::Peer(sender), assignment_cert, claimed_index)` -If the message is of type `ApprovalDistributionV1Message::Approval(approval_vote)`, then call `import_and_circulate_approval(MessageSource::Peer(sender), approval_vote)` +If the message is of type `ApprovalDistributionV1Message::Approval(approval_vote)`, then call +`import_and_circulate_approval(MessageSource::Peer(sender), approval_vote)` ### Subsystem Updates @@ -164,7 +196,8 @@ If the message is of type `ApprovalDistributionV1Message::Approval(approval_vote Create `BlockEntry` and `CandidateEntries` for all blocks. For all entries in `pending_known`: - * If there is now an entry under `blocks` for the block hash, drain all messages and import with `import_and_circulate_assignment` and `import_and_circulate_approval`. + * If there is now an entry under `blocks` for the block hash, drain all messages and import with + `import_and_circulate_assignment` and `import_and_circulate_approval`. For all peers: * Compute `view_intersection` as the intersection of the peer's view blocks with the hashes of the new blocks. @@ -180,7 +213,8 @@ Call `import_and_circulate_approval` with `MessageSource::Local`. #### `OverseerSignal::BlockFinalized` -Prune all lists from `blocks_by_number` with number less than or equal to `finalized_number`. Prune all the `BlockEntry`s referenced by those lists. +Prune all lists from `blocks_by_number` with number less than or equal to `finalized_number`. Prune all the +`BlockEntry`s referenced by those lists. ### Utility @@ -192,9 +226,14 @@ enum MessageSource { } ``` -#### `import_and_circulate_assignment(source: MessageSource, assignment: IndirectAssignmentCert, claimed_candidate_index: CandidateIndex)` +#### `import_and_circulate_assignment(...)` -Imports an assignment cert referenced by block hash and candidate index. As a postcondition, if the cert is valid, it will have distributed the cert to all peers who have the block in their view, with the exclusion of the peer referenced by the `MessageSource`. +`import_and_circulate_assignment(source: MessageSource, assignment: IndirectAssignmentCert, claimed_candidate_index: +CandidateIndex)` + +Imports an assignment cert referenced by block hash and candidate index. As a postcondition, if the cert is valid, it +will have distributed the cert to all peers who have the block in their view, with the exclusion of the peer referenced +by the `MessageSource`. We maintain a few invariants: * we only send an assignment to a peer after we add its fingerprint to our knowledge @@ -202,61 +241,84 @@ We maintain a few invariants: The algorithm is the following: - * Load the `BlockEntry` using `assignment.block_hash`. If it does not exist, report the source if it is `MessageSource::Peer` and return. + * Load the `BlockEntry` using `assignment.block_hash`. If it does not exist, report the source if it is + `MessageSource::Peer` and return. * Compute a fingerprint for the `assignment` using `claimed_candidate_index`. * If the source is `MessageSource::Peer(sender)`: - * check if `peer` appears under `known_by` and whether the fingerprint is in the knowledge of the peer. If the peer does not know the block, report for providing data out-of-view and proceed. If the peer does know the block and the `sent` knowledge contains the fingerprint, report for providing replicate data and return, otherwise, insert into the `received` knowledge and return. - * If the message fingerprint appears under the `BlockEntry`'s `Knowledge`, give the peer a small positive reputation boost, - add the fingerprint to the peer's knowledge only if it knows about the block and return. - Note that we must do this after checking for out-of-view and if the peers knows about the block to avoid being spammed. - If we did this check earlier, a peer could provide data out-of-view repeatedly and be rewarded for it. + * check if `peer` appears under `known_by` and whether the fingerprint is in the knowledge of the peer. If the peer + does not know the block, report for providing data out-of-view and proceed. If the peer does know the block and + the `sent` knowledge contains the fingerprint, report for providing replicate data and return, otherwise, insert + into the `received` knowledge and return. + * If the message fingerprint appears under the `BlockEntry`'s `Knowledge`, give the peer a small positive reputation + boost, add the fingerprint to the peer's knowledge only if it knows about the block and return. Note that we must do + this after checking for out-of-view and if the peers knows about the block to avoid being spammed. If we did this + check earlier, a peer could provide data out-of-view repeatedly and be rewarded for it. * Dispatch `ApprovalVotingMessage::CheckAndImportAssignment(assignment)` and wait for the response. * If the result is `AssignmentCheckResult::Accepted` * If the vote was accepted but not duplicate, give the peer a positive reputation boost - * add the fingerprint to both our and the peer's knowledge in the `BlockEntry`. Note that we only doing this after making sure we have the right fingerprint. - * If the result is `AssignmentCheckResult::AcceptedDuplicate`, add the fingerprint to the peer's knowledge if it knows about the block and return. + * add the fingerprint to both our and the peer's knowledge in the `BlockEntry`. Note that we only doing this after + making sure we have the right fingerprint. + * If the result is `AssignmentCheckResult::AcceptedDuplicate`, add the fingerprint to the peer's knowledge if it + knows about the block and return. * If the result is `AssignmentCheckResult::TooFarInFuture`, mildly punish the peer and return. * If the result is `AssignmentCheckResult::Bad`, punish the peer and return. * If the source is `MessageSource::Local(CandidateIndex)` * check if the fingerprint appears under the `BlockEntry's` knowledge. If not, add it. - * Load the candidate entry for the given candidate index. It should exist unless there is a logic error in the approval voting subsystem. - * Set the approval state for the validator index to `ApprovalState::Assigned` unless the approval state is set already. This should not happen as long as the approval voting subsystem instructs us to ignore duplicate assignments. - * Dispatch a `ApprovalDistributionV1Message::Assignment(assignment, candidate_index)` to all peers in the `BlockEntry`'s `known_by` set, excluding the peer in the `source`, if `source` has kind `MessageSource::Peer`. Add the fingerprint of the assignment to the knowledge of each peer. + * Load the candidate entry for the given candidate index. It should exist unless there is a logic error in the + approval voting subsystem. + * Set the approval state for the validator index to `ApprovalState::Assigned` unless the approval state is set + already. This should not happen as long as the approval voting subsystem instructs us to ignore duplicate + assignments. + * Dispatch a `ApprovalDistributionV1Message::Assignment(assignment, candidate_index)` to all peers in the + `BlockEntry`'s `known_by` set, excluding the peer in the `source`, if `source` has kind `MessageSource::Peer`. Add + the fingerprint of the assignment to the knowledge of each peer. #### `import_and_circulate_approval(source: MessageSource, approval: IndirectSignedApprovalVote)` Imports an approval signature referenced by block hash and candidate index: - * Load the `BlockEntry` using `approval.block_hash` and the candidate entry using `approval.candidate_entry`. If either does not exist, report the source if it is `MessageSource::Peer` and return. + * Load the `BlockEntry` using `approval.block_hash` and the candidate entry using `approval.candidate_entry`. If + either does not exist, report the source if it is `MessageSource::Peer` and return. * Compute a fingerprint for the approval. - * Compute a fingerprint for the corresponding assignment. If the `BlockEntry`'s knowledge does not contain that fingerprint, then report the source if it is `MessageSource::Peer` and return. All references to a fingerprint after this refer to the approval's, not the assignment's. + * Compute a fingerprint for the corresponding assignment. If the `BlockEntry`'s knowledge does not contain that + fingerprint, then report the source if it is `MessageSource::Peer` and return. All references to a fingerprint after + this refer to the approval's, not the assignment's. * If the source is `MessageSource::Peer(sender)`: - * check if `peer` appears under `known_by` and whether the fingerprint is in the knowledge of the peer. If the peer does not know the block, report for providing data out-of-view and proceed. If the peer does know the block and the `sent` knowledge contains the fingerprint, report for providing replicate data and return, otherwise, insert into the `received` knowledge and return. - * If the message fingerprint appears under the `BlockEntry`'s `Knowledge`, give the peer a small positive reputation boost, - add the fingerprint to the peer's knowledge only if it knows about the block and return. - Note that we must do this after checking for out-of-view to avoid being spammed. If we did this check earlier, a peer could provide data out-of-view repeatedly and be rewarded for it. + * check if `peer` appears under `known_by` and whether the fingerprint is in the knowledge of the peer. If the peer + does not know the block, report for providing data out-of-view and proceed. If the peer does know the block and + the `sent` knowledge contains the fingerprint, report for providing replicate data and return, otherwise, insert + into the `received` knowledge and return. + * If the message fingerprint appears under the `BlockEntry`'s `Knowledge`, give the peer a small positive reputation + boost, add the fingerprint to the peer's knowledge only if it knows about the block and return. Note that we must do + this after checking for out-of-view to avoid being spammed. If we did this check earlier, a peer could provide data + out-of-view repeatedly and be rewarded for it. * Dispatch `ApprovalVotingMessage::CheckAndImportApproval(approval)` and wait for the response. * If the result is `VoteCheckResult::Accepted(())`: * Give the peer a positive reputation boost and add the fingerprint to both our and the peer's knowledge. * If the result is `VoteCheckResult::Bad`: * Report the peer and return. - * Load the candidate entry for the given candidate index. It should exist unless there is a logic error in the approval voting subsystem. - * Set the approval state for the validator index to `ApprovalState::Approved`. It should already be in the `Assigned` state as our `BlockEntry` knowledge contains a fingerprint for the assignment. - * Dispatch a `ApprovalDistributionV1Message::Approval(approval)` to all peers in the `BlockEntry`'s `known_by` set, excluding the peer in the `source`, if `source` has kind `MessageSource::Peer`. Add the fingerprint of the assignment to the knowledge of each peer. Note that this obeys the politeness conditions: + * Load the candidate entry for the given candidate index. It should exist unless there is a logic error in the + approval voting subsystem. + * Set the approval state for the validator index to `ApprovalState::Approved`. It should already be in the `Assigned` + state as our `BlockEntry` knowledge contains a fingerprint for the assignment. + * Dispatch a `ApprovalDistributionV1Message::Approval(approval)` to all peers in the `BlockEntry`'s `known_by` set, + excluding the peer in the `source`, if `source` has kind `MessageSource::Peer`. Add the fingerprint of the + assignment to the knowledge of each peer. Note that this obeys the politeness conditions: * We guarantee elsewhere that all peers within `known_by` are aware of all assignments relative to the block. * We've checked that this specific approval has a corresponding assignment within the `BlockEntry`. * Thus, all peers are aware of the assignment or have a message to them in-flight which will make them so. - -#### `unify_with_peer(peer: PeerId, view)`: +#### `unify_with_peer(peer: PeerId, view)` 1. Initialize a set `missing_knowledge = {}` For each block in the view: - 2. Load the `BlockEntry` for the block. If the block is unknown, or the number is less than or equal to the view's finalized number go to step 6. - 3. Inspect the `known_by` set of the `BlockEntry`. If the peer already knows all assignments/approvals, go to step 6. - 4. Add the peer to `known_by` and add the hash and missing knowledge of the block to `missing_knowledge`. - 5. Return to step 2 with the ancestor of the block. - -6. For each block in `missing_knowledge`, send all assignments and approvals for all candidates in those blocks to the peer. + 1. Load the `BlockEntry` for the block. If the block is unknown, or the number is less than or equal to the view's + finalized number go to step 6. + 1. Inspect the `known_by` set of the `BlockEntry`. If the peer already knows all assignments/approvals, go to step 6. + 1. Add the peer to `known_by` and add the hash and missing knowledge of the block to `missing_knowledge`. + 1. Return to step 2 with the ancestor of the block. + +1. For each block in `missing_knowledge`, send all assignments and approvals for all candidates in those blocks to the + peer. diff --git a/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md b/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md index 88744e50cf79..6da2f5d9b883 100644 --- a/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md +++ b/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md @@ -1,35 +1,61 @@ # Approval Voting -Reading the [section on the approval protocol](../../protocol-approval.md) will likely be necessary to understand the aims of this subsystem. - -Approval votes are split into two parts: Assignments and Approvals. Validators first broadcast their assignment to indicate intent to check a candidate. Upon successfully checking, they broadcast an approval vote. If a validator doesn't broadcast their approval vote shortly after issuing an assignment, this is an indication that they are being prevented from recovering or validating the block data and that more validators should self-select to check the candidate. This is known as a "no-show". - -The core of this subsystem is a Tick-based timer loop, where Ticks are 500ms. We also reason about time in terms of `DelayTranche`s, which measure the number of ticks elapsed since a block was produced. We track metadata for all un-finalized but included candidates. We compute our local assignments to check each candidate, as well as which `DelayTranche` those assignments may be minimally triggered at. As the same candidate may appear in more than one block, we must produce our potential assignments for each (Block, Candidate) pair. The timing loop is based on waiting for assignments to become no-shows or waiting to broadcast and begin our own assignment to check. - -Another main component of this subsystem is the logic for determining when a (Block, Candidate) pair has been approved and when to broadcast and trigger our own assignment. Once a (Block, Candidate) pair has been approved, we mark a corresponding bit in the `BlockEntry` that indicates the candidate has been approved under the block. When we trigger our own assignment, we broadcast it via Approval Distribution, begin fetching the data from Availability Recovery, and then pass it through to the Candidate Validation. Once these steps are successful, we issue our approval vote. If any of these steps fail, we don't issue any vote and will "no-show" from the perspective of other validators in addition a dispute is raised via the dispute-coordinator, by sending `IssueLocalStatement`. - -Where this all fits into Polkadot is via block finality. Our goal is to not finalize any block containing a candidate that is not approved. We provide a hook for a custom GRANDPA voting rule - GRANDPA makes requests of the form (target, minimum) consisting of a target block (i.e. longest chain) that it would like to finalize, and a minimum block which, due to the rules of GRANDPA, must be voted on. The minimum is typically the last finalized block, but may be beyond it, in the case of having a last-round-estimate beyond the last finalized. Thus, our goal is to inform GRANDPA of some block between target and minimum which we believe can be finalized safely. We do this by iterating backwards from the target to the minimum and finding the longest continuous chain from minimum where all candidates included by those blocks have been approved. +Reading the [section on the approval protocol](../../protocol-approval.md) will likely be necessary to understand the +aims of this subsystem. + +Approval votes are split into two parts: Assignments and Approvals. Validators first broadcast their assignment to +indicate intent to check a candidate. Upon successfully checking, they broadcast an approval vote. If a validator +doesn't broadcast their approval vote shortly after issuing an assignment, this is an indication that they are being +prevented from recovering or validating the block data and that more validators should self-select to check the +candidate. This is known as a "no-show". + +The core of this subsystem is a Tick-based timer loop, where Ticks are 500ms. We also reason about time in terms of +`DelayTranche`s, which measure the number of ticks elapsed since a block was produced. We track metadata for all +un-finalized but included candidates. We compute our local assignments to check each candidate, as well as which +`DelayTranche` those assignments may be minimally triggered at. As the same candidate may appear in more than one block, +we must produce our potential assignments for each (Block, Candidate) pair. The timing loop is based on waiting for +assignments to become no-shows or waiting to broadcast and begin our own assignment to check. + +Another main component of this subsystem is the logic for determining when a (Block, Candidate) pair has been approved +and when to broadcast and trigger our own assignment. Once a (Block, Candidate) pair has been approved, we mark a +corresponding bit in the `BlockEntry` that indicates the candidate has been approved under the block. When we trigger +our own assignment, we broadcast it via Approval Distribution, begin fetching the data from Availability Recovery, and +then pass it through to the Candidate Validation. Once these steps are successful, we issue our approval vote. If any of +these steps fail, we don't issue any vote and will "no-show" from the perspective of other validators in addition a +dispute is raised via the dispute-coordinator, by sending `IssueLocalStatement`. + +Where this all fits into Polkadot is via block finality. Our goal is to not finalize any block containing a candidate +that is not approved. We provide a hook for a custom GRANDPA voting rule - GRANDPA makes requests of the form (target, +minimum) consisting of a target block (i.e. longest chain) that it would like to finalize, and a minimum block which, +due to the rules of GRANDPA, must be voted on. The minimum is typically the last finalized block, but may be beyond it, +in the case of having a last-round-estimate beyond the last finalized. Thus, our goal is to inform GRANDPA of some block +between target and minimum which we believe can be finalized safely. We do this by iterating backwards from the target +to the minimum and finding the longest continuous chain from minimum where all candidates included by those blocks have +been approved. ## Protocol Input: - - `ApprovalVotingMessage::CheckAndImportAssignment` - - `ApprovalVotingMessage::CheckAndImportApproval` - - `ApprovalVotingMessage::ApprovedAncestor` + * `ApprovalVotingMessage::CheckAndImportAssignment` + * `ApprovalVotingMessage::CheckAndImportApproval` + * `ApprovalVotingMessage::ApprovedAncestor` Output: - - `ApprovalDistributionMessage::DistributeAssignment` - - `ApprovalDistributionMessage::DistributeApproval` - - `RuntimeApiMessage::Request` - - `ChainApiMessage` - - `AvailabilityRecoveryMessage::Recover` - - `CandidateExecutionMessage::ValidateFromExhaustive` + * `ApprovalDistributionMessage::DistributeAssignment` + * `ApprovalDistributionMessage::DistributeApproval` + * `RuntimeApiMessage::Request` + * `ChainApiMessage` + * `AvailabilityRecoveryMessage::Recover` + * `CandidateExecutionMessage::ValidateFromExhaustive` ## Functionality -The approval voting subsystem is responsible for casting votes and determining approval of candidates and as a result, blocks. +The approval voting subsystem is responsible for casting votes and determining approval of candidates and as a result, +blocks. -This subsystem wraps a database which is used to store metadata about unfinalized blocks and the candidates within them. Candidates may appear in multiple blocks, and assignment criteria are chosen differently based on the hash of the block they appear in. +This subsystem wraps a database which is used to store metadata about unfinalized blocks and the candidates within them. +Candidates may appear in multiple blocks, and assignment criteria are chosen differently based on the hash of the block +they appear in. ## Database Schema @@ -150,16 +176,22 @@ struct State { } ``` -This guide section makes no explicit references to writes to or reads from disk. Instead, it handles them implicitly, with the understanding that updates to block, candidate, and approval entries are persisted to disk. +This guide section makes no explicit references to writes to or reads from disk. Instead, it handles them implicitly, +with the understanding that updates to block, candidate, and approval entries are persisted to disk. [`SessionInfo`](../../runtime/session_info.md) -On start-up, we clear everything currently stored by the database. This is done by loading the `StoredBlockRange`, iterating through each block number, iterating through each block hash, and iterating through each candidate referenced by each block. Although this is `O(o*n*p)`, we don't expect to have more than a few unfinalized blocks at any time and in extreme cases, a few thousand. The clearing operation should be relatively fast as a result. +On start-up, we clear everything currently stored by the database. This is done by loading the `StoredBlockRange`, +iterating through each block number, iterating through each block hash, and iterating through each candidate referenced +by each block. Although this is `O(o*n*p)`, we don't expect to have more than a few unfinalized blocks at any time and +in extreme cases, a few thousand. The clearing operation should be relatively fast as a result. Main loop: * Each iteration, select over all of - * The next `Tick` in `wakeups`: trigger `wakeup_process` for each `(Hash, Hash)` pair scheduled under the `Tick` and then remove all entries under the `Tick`. - * The next message from the overseer: handle the message as described in the [Incoming Messages section](#incoming-messages) + * The next `Tick` in `wakeups`: trigger `wakeup_process` for each `(Hash, Hash)` pair scheduled under the `Tick` and + then remove all entries under the `Tick`. + * The next message from the overseer: handle the message as described in the [Incoming Messages + section](#incoming-messages) * The next approval vote request from `background_rx` * If this is an `ApprovalVoteRequest`, [Issue an approval vote](#issue-approval-vote). @@ -167,41 +199,84 @@ Main loop: #### `OverseerSignal::BlockFinalized` -On receiving an `OverseerSignal::BlockFinalized(h)`, we fetch the block number `b` of that block from the `ChainApi` subsystem. We update our `StoredBlockRange` to begin at `b+1`. Additionally, we remove all block entries and candidates referenced by them up to and including `b`. Lastly, we prune out all descendants of `h` transitively: when we remove a `BlockEntry` with number `b` that is not equal to `h`, we recursively delete all the `BlockEntry`s referenced as children. We remove the `block_assignments` entry for the block hash and if `block_assignments` is now empty, remove the `CandidateEntry`. We also update each of the `BlockNumber -> Vec` keys in the database to reflect the blocks at that height, clearing if empty. +On receiving an `OverseerSignal::BlockFinalized(h)`, we fetch the block number `b` of that block from the `ChainApi` +subsystem. We update our `StoredBlockRange` to begin at `b+1`. Additionally, we remove all block entries and candidates +referenced by them up to and including `b`. Lastly, we prune out all descendants of `h` transitively: when we remove a +`BlockEntry` with number `b` that is not equal to `h`, we recursively delete all the `BlockEntry`s referenced as +children. We remove the `block_assignments` entry for the block hash and if `block_assignments` is now empty, remove the +`CandidateEntry`. We also update each of the `BlockNumber -> Vec` keys in the database to reflect the blocks at +that height, clearing if empty. #### `OverseerSignal::ActiveLeavesUpdate` On receiving an `OverseerSignal::ActiveLeavesUpdate(update)`: - * We determine the set of new blocks that were not in our previous view. This is done by querying the ancestry of all new items in the view and contrasting against the stored `BlockNumber`s. Typically, there will be only one new block. We fetch the headers and information on these blocks from the `ChainApi` subsystem. Stale leaves in the update can be ignored. + * We determine the set of new blocks that were not in our previous view. This is done by querying the ancestry of all + new items in the view and contrasting against the stored `BlockNumber`s. Typically, there will be only one new + block. We fetch the headers and information on these blocks from the `ChainApi` subsystem. Stale leaves in the + update can be ignored. * We update the `StoredBlockRange` and the `BlockNumber` maps. - * We use the `RuntimeApiSubsystem` to determine information about these blocks. It is generally safe to assume that runtime state is available for recent, unfinalized blocks. In the case that it isn't, it means that we are catching up to the head of the chain and needn't worry about assignments to those blocks anyway, as the security assumption of the protocol tolerates nodes being temporarily offline or out-of-date. - * We fetch the set of candidates included by each block by dispatching a `RuntimeApiRequest::CandidateEvents` and checking the `CandidateIncluded` events. - * We fetch the session of the block by dispatching a `session_index_for_child` request with the parent-hash of the block. - * If the `session index - APPROVAL_SESSIONS > state.earliest_session`, then bump `state.earliest_sessions` to that amount and prune earlier sessions. - * If the session isn't in our `state.session_info`, load the session info for it and for all sessions since the earliest-session, including the earliest-session, if that is missing. And it can be, just after pruning, if we've done a big jump forward, as is the case when we've just finished chain synchronization. + * We use the `RuntimeApiSubsystem` to determine information about these blocks. It is generally safe to assume that + runtime state is available for recent, unfinalized blocks. In the case that it isn't, it means that we are catching + up to the head of the chain and needn't worry about assignments to those blocks anyway, as the security assumption + of the protocol tolerates nodes being temporarily offline or out-of-date. + * We fetch the set of candidates included by each block by dispatching a `RuntimeApiRequest::CandidateEvents` and + checking the `CandidateIncluded` events. + * We fetch the session of the block by dispatching a `session_index_for_child` request with the parent-hash of the + block. + * If the `session index - APPROVAL_SESSIONS > state.earliest_session`, then bump `state.earliest_sessions` to that + amount and prune earlier sessions. + * If the session isn't in our `state.session_info`, load the session info for it and for all sessions since the + earliest-session, including the earliest-session, if that is missing. And it can be, just after pruning, if we've + done a big jump forward, as is the case when we've just finished chain synchronization. * If any of the runtime API calls fail, we just warn and skip the block. - * We use the `RuntimeApiSubsystem` to determine the set of candidates included in these blocks and use BABE logic to determine the slot number and VRF of the blocks. - * We also note how late we appear to have received the block. We create a `BlockEntry` for each block and a `CandidateEntry` for each candidate obtained from `CandidateIncluded` events after making a `RuntimeApiRequest::CandidateEvents` request. - * For each candidate, if the amount of needed approvals is more than the validators remaining after the backing group of the candidate is subtracted, then the candidate is insta-approved as approval would be impossible otherwise. If all candidates in the block are insta-approved, or there are no candidates in the block, then the block is insta-approved. If the block is insta-approved, a [`ChainSelectionMessage::Approved`][CSM] should be sent for the block. - * Ensure that the `CandidateEntry` contains a `block_assignments` entry for the block, with the correct backing group set. + * We use the `RuntimeApiSubsystem` to determine the set of candidates included in these blocks and use BABE logic to + determine the slot number and VRF of the blocks. + * We also note how late we appear to have received the block. We create a `BlockEntry` for each block and a + `CandidateEntry` for each candidate obtained from `CandidateIncluded` events after making a + `RuntimeApiRequest::CandidateEvents` request. + * For each candidate, if the amount of needed approvals is more than the validators remaining after the backing group + of the candidate is subtracted, then the candidate is insta-approved as approval would be impossible otherwise. If + all candidates in the block are insta-approved, or there are no candidates in the block, then the block is + insta-approved. If the block is insta-approved, a [`ChainSelectionMessage::Approved`][CSM] should be sent for the + block. + * Ensure that the `CandidateEntry` contains a `block_assignments` entry for the block, with the correct backing group + set. * If a validator in this session, compute and assign `our_assignment` for the `block_assignments` * Only if not a member of the backing group. - * Run `RelayVRFModulo` and `RelayVRFDelay` according to the [the approvals protocol section](../../protocol-approval.md#assignment-criteria). Ensure that the assigned core derived from the output is covered by the auxiliary signature aggregated in the `VRFPRoof`. - * [Handle Wakeup](#handle-wakeup) for each new candidate in each new block - this will automatically broadcast a 0-tranche assignment, kick off approval work, and schedule the next delay. + * Run `RelayVRFModulo` and `RelayVRFDelay` according to the [the approvals protocol + section](../../protocol-approval.md#assignment-criteria). Ensure that the assigned core derived from the output is + covered by the auxiliary signature aggregated in the `VRFPRoof`. + * [Handle Wakeup](#handle-wakeup) for each new candidate in each new block - this will automatically broadcast a + 0-tranche assignment, kick off approval work, and schedule the next delay. * Dispatch an `ApprovalDistributionMessage::NewBlocks` with the meta information filled out for each new block. #### `ApprovalVotingMessage::CheckAndImportAssignment` -On receiving a `ApprovalVotingMessage::CheckAndImportAssignment` message, we check the assignment cert against the block entry. The cert itself contains information necessary to determine the candidate that is being assigned-to. In detail: - * Load the `BlockEntry` for the relay-parent referenced by the message. If there is none, return `AssignmentCheckResult::Bad`. +On receiving a `ApprovalVotingMessage::CheckAndImportAssignment` message, we check the assignment cert against the block +entry. The cert itself contains information necessary to determine the candidate that is being assigned-to. In detail: + * Load the `BlockEntry` for the relay-parent referenced by the message. If there is none, return + `AssignmentCheckResult::Bad`. * Fetch the `SessionInfo` for the session of the block * Determine the assignment key of the validator based on that. - * Determine the claimed core index by looking up the candidate with given index in `block_entry.candidates`. Return `AssignmentCheckResult::Bad` if missing. + * Determine the claimed core index by looking up the candidate with given index in `block_entry.candidates`. Return + `AssignmentCheckResult::Bad` if missing. * Check the assignment cert - * If the cert kind is `RelayVRFModulo`, then the certificate is valid as long as `sample < session_info.relay_vrf_samples` and the VRF is valid for the validator's key with the input `block_entry.relay_vrf_story ++ sample.encode()` as described with [the approvals protocol section](../../protocol-approval.md#assignment-criteria). We set `core_index = vrf.make_bytes().to_u32() % session_info.n_cores`. If the `BlockEntry` causes inclusion of a candidate at `core_index`, then this is a valid assignment for the candidate at `core_index` and has delay tranche 0. Otherwise, it can be ignored. - * If the cert kind is `RelayVRFDelay`, then we check if the VRF is valid for the validator's key with the input `block_entry.relay_vrf_story ++ cert.core_index.encode()` as described in [the approvals protocol section](../../protocol-approval.md#assignment-criteria). The cert can be ignored if the block did not cause inclusion of a candidate on that core index. Otherwise, this is a valid assignment for the included candidate. The delay tranche for the assignment is determined by reducing `(vrf.make_bytes().to_u64() % (session_info.n_delay_tranches + session_info.zeroth_delay_tranche_width)).saturating_sub(session_info.zeroth_delay_tranche_width)`. - * We also check that the core index derived by the output is covered by the `VRFProof` by means of an auxiliary signature. + * If the cert kind is `RelayVRFModulo`, then the certificate is valid as long as `sample < + session_info.relay_vrf_samples` and the VRF is valid for the validator's key with the input + `block_entry.relay_vrf_story ++ sample.encode()` as described with [the approvals protocol + section](../../protocol-approval.md#assignment-criteria). We set `core_index = vrf.make_bytes().to_u32() % + session_info.n_cores`. If the `BlockEntry` causes inclusion of a candidate at `core_index`, then this is a valid + assignment for the candidate at `core_index` and has delay tranche 0. Otherwise, it can be ignored. + * If the cert kind is `RelayVRFDelay`, then we check if the VRF is valid for the validator's key with the input + `block_entry.relay_vrf_story ++ cert.core_index.encode()` as described in [the approvals protocol + section](../../protocol-approval.md#assignment-criteria). The cert can be ignored if the block did not cause + inclusion of a candidate on that core index. Otherwise, this is a valid assignment for the included candidate. The + delay tranche for the assignment is determined by reducing `(vrf.make_bytes().to_u64() % + (session_info.n_delay_tranches + + session_info.zeroth_delay_tranche_width)).saturating_sub(session_info.zeroth_delay_tranche_width)`. + * We also check that the core index derived by the output is covered by the `VRFProof` by means of an auxiliary + signature. * If the delay tranche is too far in the future, return `AssignmentCheckResult::TooFarInFuture`. * Import the assignment. * Load the candidate in question and access the `approval_entry` for the block hash the cert references. @@ -217,32 +292,41 @@ On receiving a `ApprovalVotingMessage::CheckAndImportAssignment` message, we che On receiving a `CheckAndImportApproval(indirect_approval_vote, response_channel)` message: * Fetch the `BlockEntry` from the indirect approval vote's `block_hash`. If none, return `ApprovalCheckResult::Bad`. - * Fetch the `CandidateEntry` from the indirect approval vote's `candidate_index`. If the block did not trigger inclusion of enough candidates, return `ApprovalCheckResult::Bad`. - * Construct a `SignedApprovalVote` using the candidate hash and check against the validator's approval key, based on the session info of the block. If invalid or no such validator, return `ApprovalCheckResult::Bad`. + * Fetch the `CandidateEntry` from the indirect approval vote's `candidate_index`. If the block did not trigger + inclusion of enough candidates, return `ApprovalCheckResult::Bad`. + * Construct a `SignedApprovalVote` using the candidate hash and check against the validator's approval key, based on + the session info of the block. If invalid or no such validator, return `ApprovalCheckResult::Bad`. * Send `ApprovalCheckResult::Accepted` * [Import the checked approval vote](#import-checked-approval) #### `ApprovalVotingMessage::ApprovedAncestor` On receiving an `ApprovedAncestor(Hash, BlockNumber, response_channel)`: - * Iterate over the ancestry of the hash all the way back to block number given, starting from the provided block hash. Load the `CandidateHash`es from each block entry. + * Iterate over the ancestry of the hash all the way back to block number given, starting from the provided block hash. + Load the `CandidateHash`es from each block entry. * Keep track of an `all_approved_max: Option<(Hash, BlockNumber, Vec<(Hash, Vec))>`. - * For each block hash encountered, load the `BlockEntry` associated. If any are not found, return `None` on the response channel and conclude. - * If the block entry's `approval_bitfield` has all bits set to 1 and `all_approved_max == None`, set `all_approved_max = Some((current_hash, current_number))`. + * For each block hash encountered, load the `BlockEntry` associated. If any are not found, return `None` on the + response channel and conclude. + * If the block entry's `approval_bitfield` has all bits set to 1 and `all_approved_max == None`, set `all_approved_max + = Some((current_hash, current_number))`. * If the block entry's `approval_bitfield` has any 0 bits, set `all_approved_max = None`. - * If `all_approved_max` is `Some`, push the current block hash and candidate hashes onto the list of blocks and candidates `all_approved_max`. + * If `all_approved_max` is `Some`, push the current block hash and candidate hashes onto the list of blocks and + candidates `all_approved_max`. * After iterating all ancestry, return `all_approved_max`. ### Updates and Auxiliary Logic #### Import Checked Approval - * Import an approval vote which we can assume to have passed signature checks and correspond to an imported assignment. + * Import an approval vote which we can assume to have passed signature checks and correspond to an imported + assignment. * Requires `(BlockEntry, CandidateEntry, ValidatorIndex)` * Set the corresponding bit of the `approvals` bitfield in the `CandidateEntry` to `1`. If already `1`, return. - * Checks the approval state of a candidate under a specific block, and updates the block and candidate entries accordingly. + * Checks the approval state of a candidate under a specific block, and updates the block and candidate entries + accordingly. * Checks the `ApprovalEntry` for the block. * [determine the tranches to inspect](#determine-required-tranches) of the candidate, - * [the candidate is approved under the block](#check-approval), set the corresponding bit in the `block_entry.approved_bitfield`. + * [the candidate is approved under the block](#check-approval), set the corresponding bit in the + `block_entry.approved_bitfield`. * If the block is now fully approved and was not before, send a [`ChainSelectionMessage::Approved`][CSM]. * Otherwise, [schedule a wakeup of the candidate](#schedule-wakeup) * If the approval vote originates locally, set the `our_approval_sig` in the candidate entry. @@ -250,13 +334,19 @@ On receiving an `ApprovedAncestor(Hash, BlockNumber, response_channel)`: #### Handling Wakeup * Handle a previously-scheduled wakeup of a candidate under a specific block. * Requires `(relay_block, candidate_hash)` - * Load the `BlockEntry` and `CandidateEntry` from disk. If either is not present, this may have lost a race with finality and can be ignored. Also load the `ApprovalEntry` for the block and candidate. + * Load the `BlockEntry` and `CandidateEntry` from disk. If either is not present, this may have lost a race with + finality and can be ignored. Also load the `ApprovalEntry` for the block and candidate. * [determine the `RequiredTranches` of the candidate](#determine-required-tranches). * Determine if we should trigger our assignment. * If we've already triggered or `OurAssignment` is `None`, we do not trigger. - * If we have `RequiredTranches::All`, then we trigger if the candidate is [not approved](#check-approval). We have no next wakeup as we assume that other validators are doing the same and we will be implicitly woken up by handling new votes. - * If we have `RequiredTranches::Pending { considered, next_no_show, uncovered, maximum_broadcast, clock_drift }`, then we trigger if our assignment's tranche is less than or equal to `maximum_broadcast` and the current tick, with `clock_drift` applied, is at least the tick of our tranche. - * If we have `RequiredTranches::Exact { .. }` then we do not trigger, because this value indicates that no new assignments are needed at the moment. + * If we have `RequiredTranches::All`, then we trigger if the candidate is [not approved](#check-approval). We have + no next wakeup as we assume that other validators are doing the same and we will be implicitly woken up by + handling new votes. + * If we have `RequiredTranches::Pending { considered, next_no_show, uncovered, maximum_broadcast, clock_drift }`, + then we trigger if our assignment's tranche is less than or equal to `maximum_broadcast` and the current tick, + with `clock_drift` applied, is at least the tick of our tranche. + * If we have `RequiredTranches::Exact { .. }` then we do not trigger, because this value indicates that no new + assignments are needed at the moment. * If we should trigger our assignment * Import the assignment to the `ApprovalEntry` * Broadcast on network with an `ApprovalDistributionMessage::DistributeAssignment`. @@ -265,26 +355,39 @@ On receiving an `ApprovedAncestor(Hash, BlockNumber, response_channel)`: #### Schedule Wakeup - * Requires `(approval_entry, candidate_entry)` which effectively denotes a `(Block Hash, Candidate Hash)` pair - the candidate, along with the block it appears in. + * Requires `(approval_entry, candidate_entry)` which effectively denotes a `(Block Hash, Candidate Hash)` pair - the + candidate, along with the block it appears in. * Also requires `RequiredTranches` * If the `approval_entry` is approved, this doesn't need to be woken up again. - * If `RequiredTranches::All` - no wakeup. We assume other incoming votes will trigger wakeup and potentially re-schedule. - * If `RequiredTranches::Pending { considered, next_no_show, uncovered, maximum_broadcast, clock_drift }` - schedule at the lesser of the next no-show tick, or the tick, offset positively by `clock_drift` of the next non-empty tranche we are aware of after `considered`, including any tranche containing our own unbroadcast assignment. This can lead to no wakeup in the case that we have already broadcast our assignment and there are no pending no-shows; that is, we have approval votes for every assignment we've received that is not already a no-show. In this case, we will be re-triggered by other validators broadcasting their assignments. - * If `RequiredTranches::Exact { next_no_show, latest_assignment_tick, .. }` - set a wakeup for the earlier of the next no-show tick or the latest assignment tick + `APPROVAL_DELAY`. + * If `RequiredTranches::All` - no wakeup. We assume other incoming votes will trigger wakeup and potentially + re-schedule. + * If `RequiredTranches::Pending { considered, next_no_show, uncovered, maximum_broadcast, clock_drift }` - schedule at + the lesser of the next no-show tick, or the tick, offset positively by `clock_drift` of the next non-empty tranche + we are aware of after `considered`, including any tranche containing our own unbroadcast assignment. This can lead + to no wakeup in the case that we have already broadcast our assignment and there are no pending no-shows; that is, + we have approval votes for every assignment we've received that is not already a no-show. In this case, we will be + re-triggered by other validators broadcasting their assignments. + * If `RequiredTranches::Exact { next_no_show, latest_assignment_tick, .. }` - set a wakeup for the earlier of the next + no-show tick or the latest assignment tick + `APPROVAL_DELAY`. #### Launch Approval Work * Requires `(SessionIndex, SessionInfo, CandidateReceipt, ValidatorIndex, backing_group, block_hash, candidate_index)` * Extract the public key of the `ValidatorIndex` from the `SessionInfo` for the session. -* Issue an `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session_index, Some(backing_group), response_sender)` -* Load the historical validation code of the parachain by dispatching a `RuntimeApiRequest::ValidationCodeByHash(descriptor.validation_code_hash)` against the state of `block_hash`. +* Issue an `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session_index, Some(backing_group), + response_sender)` +* Load the historical validation code of the parachain by dispatching a + `RuntimeApiRequest::ValidationCodeByHash(descriptor.validation_code_hash)` against the state of `block_hash`. * Spawn a background task with a clone of `background_tx` * Wait for the available data - * Issue a `CandidateValidationMessage::ValidateFromExhaustive` message with `APPROVAL_EXECUTION_TIMEOUT` as the timeout parameter. + * Issue a `CandidateValidationMessage::ValidateFromExhaustive` message with `APPROVAL_EXECUTION_TIMEOUT` as the + timeout parameter. * Wait for the result of validation * Check that the result of validation, if valid, matches the commitments in the receipt. * If valid, issue a message on `background_tx` detailing the request. - * If any of the data, the candidate, or the commitments are invalid, issue on `background_tx` a [`DisputeCoordinatorMessage::IssueLocalStatement`](../../types/overseer-protocol.md#dispute-coordinator-message) with `valid = false` to initiate a dispute. + * If any of the data, the candidate, or the commitments are invalid, issue on `background_tx` a + [`DisputeCoordinatorMessage::IssueLocalStatement`](../../types/overseer-protocol.md#dispute-coordinator-message) + with `valid = false` to initiate a dispute. #### Issue Approval Vote * Fetch the block entry and candidate entry. Ignore if `None` - we've probably just lost a race with finality. @@ -297,14 +400,22 @@ On receiving an `ApprovedAncestor(Hash, BlockNumber, response_channel)`: #### Determine Required Tranches -This logic is for inspecting an approval entry that tracks the assignments received, along with information on which assignments have corresponding approval votes. Inspection also involves the current time and expected requirements and is used to help the higher-level code determine the following: +This logic is for inspecting an approval entry that tracks the assignments received, along with information on which +assignments have corresponding approval votes. Inspection also involves the current time and expected requirements and +is used to help the higher-level code determine the following: * Whether to broadcast the local assignment * Whether to check that the candidate entry has been completely approved. - * If the candidate is waiting on approval, when to schedule the next wakeup of the `(candidate, block)` pair at a point where the state machine could be advanced. + * If the candidate is waiting on approval, when to schedule the next wakeup of the `(candidate, block)` pair at a + point where the state machine could be advanced. -These routines are pure functions which only depend on the environmental state. The expectation is that this determination is re-run every time we attempt to update an approval entry: either when we trigger a wakeup to advance the state machine based on a no-show or our own broadcast, or when we receive further assignments or approvals from the network. +These routines are pure functions which only depend on the environmental state. The expectation is that this +determination is re-run every time we attempt to update an approval entry: either when we trigger a wakeup to advance +the state machine based on a no-show or our own broadcast, or when we receive further assignments or approvals from the +network. -Thus it may be that at some point in time, we consider that tranches 0..X is required to be considered, but as we receive more information, we might require fewer tranches. Or votes that we perceived to be missing and require replacement are filled in and change our view. +Thus it may be that at some point in time, we consider that tranches 0..X is required to be considered, but as we +receive more information, we might require fewer tranches. Or votes that we perceived to be missing and require +replacement are filled in and change our view. Requires `(approval_entry, approvals_received, tranche_now, block_tick, no_show_duration, needed_approvals)` @@ -327,7 +438,8 @@ enum RequiredTranches { /// as though it is `clock_drift` ticks earlier. clock_drift: Tick, }, - // An exact number of required tranches and a number of no-shows. This indicates that the amount of `needed_approvals` are assigned and additionally all no-shows are covered. + // An exact number of required tranches and a number of no-shows. This indicates that the amount of `needed_approvals` + // are assigned and additionally all no-shows are covered. Exact { /// The tranche to inspect up to. needed: DelayTranche, @@ -345,13 +457,21 @@ enum RequiredTranches { **Clock-drift and Tranche-taking** -Our vote-counting procedure depends heavily on how we interpret time based on the presence of no-shows - assignments which have no corresponding approval after some time. +Our vote-counting procedure depends heavily on how we interpret time based on the presence of no-shows - assignments +which have no corresponding approval after some time. We have this is because of how we handle no-shows: we keep track of the depth of no-shows we are covering. -As an example: there may be initial no-shows in tranche 0. It'll take `no_show_duration` ticks before those are considered no-shows. Then, we don't want to immediately take `no_show_duration` more tranches. Instead, we want to take one tranche for each uncovered no-show. However, as we take those tranches, there may be further no-shows. Since these depth-1 no-shows should have only been triggered after the depth-0 no-shows were already known to be no-shows, we need to discount the local clock by `no_show_duration` to see whether these should be considered no-shows or not. There may be malicious parties who broadcast their assignment earlier than they were meant to, who shouldn't be counted as instant no-shows. We continue onwards to cover all depth-1 no-shows which may lead to depth-2 no-shows and so on. +As an example: there may be initial no-shows in tranche 0. It'll take `no_show_duration` ticks before those are +considered no-shows. Then, we don't want to immediately take `no_show_duration` more tranches. Instead, we want to take +one tranche for each uncovered no-show. However, as we take those tranches, there may be further no-shows. Since these +depth-1 no-shows should have only been triggered after the depth-0 no-shows were already known to be no-shows, we need +to discount the local clock by `no_show_duration` to see whether these should be considered no-shows or not. There may +be malicious parties who broadcast their assignment earlier than they were meant to, who shouldn't be counted as instant +no-shows. We continue onwards to cover all depth-1 no-shows which may lead to depth-2 no-shows and so on. -Likewise, when considering how many tranches to take, the no-show depth should be used to apply a depth-discount or clock drift to the `tranche_now`. +Likewise, when considering how many tranches to take, the no-show depth should be used to apply a depth-discount or +clock drift to the `tranche_now`. **Procedure** @@ -360,21 +480,35 @@ Likewise, when considering how many tranches to take, the no-show depth should b * Take tranches up to `tranche_now - clock_drift` until all needed assignments are met. * Keep track of the `next_no_show` according to the clock drift, as we go. * Keep track of the `last_assignment_tick` as we go. - * If running out of tranches before then, return `Pending { considered, next_no_show, maximum_broadcast, clock_drift }` + * If running out of tranches before then, return `Pending { considered, next_no_show, maximum_broadcast, clock_drift + }` * If there are no no-shows, return `Exact { needed, tolerated_missing, next_no_show, last_assignment_tick }` - * `maximum_broadcast` is either `DelayTranche::max_value()` at tranche 0 or otherwise by the last considered tranche + the number of uncovered no-shows at this point. - * If there are no-shows, return to the beginning, incrementing `depth` and attempting to cover the number of no-shows. Each no-show must be covered by a non-empty tranche, which are tranches that have at least one assignment. Each non-empty tranche covers exactly one no-show. - * If at any point, it seems that all validators are required, do an early return with `RequiredTranches::All` which indicates that everyone should broadcast. + * `maximum_broadcast` is either `DelayTranche::max_value()` at tranche 0 or otherwise by the last considered tranche + + the number of uncovered no-shows at this point. + * If there are no-shows, return to the beginning, incrementing `depth` and attempting to cover the number of no-shows. + Each no-show must be covered by a non-empty tranche, which are tranches that have at least one assignment. Each + non-empty tranche covers exactly one no-show. + * If at any point, it seems that all validators are required, do an early return with `RequiredTranches::All` which + indicates that everyone should broadcast. #### Check Approval * Check whether a candidate is approved under a particular block. * Requires `(block_entry, candidate_entry, approval_entry, n_tranches)` - * If we have `3 * n_approvals > n_validators`, return true. This is because any set with f+1 validators must have at least one honest validator, who has approved the candidate. + * If we have `3 * n_approvals > n_validators`, return true. This is because any set with f+1 validators must have at + least one honest validator, who has approved the candidate. * If `n_tranches` is `RequiredTranches::Pending`, return false * If `n_tranches` is `RequiredTranches::All`, return false. - * If `n_tranches` is `RequiredTranches::Exact { tranche, tolerated_missing, latest_assignment_tick, .. }`, then we return whether all assigned validators up to `tranche` less `tolerated_missing` have approved and `latest_assignment_tick + APPROVAL_DELAY >= tick_now`. - * e.g. if we had 5 tranches and 1 tolerated missing, we would accept only if all but 1 of assigned validators in tranches 0..=5 have approved. In that example, we also accept all validators in tranches 0..=5 having approved, but that would indicate that the `RequiredTranches` value was incorrectly constructed, so it is not realistic. `tolerated_missing` actually represents covered no-shows. If there are more missing approvals than there are tolerated missing, that indicates that there are some assignments which are not yet no-shows, but may become no-shows, and we should wait for the validators to either approve or become no-shows. - * e.g. If the above passes and the `latest_assignment_tick` was 5 and the current tick was 6, then we'd return false. + * If `n_tranches` is `RequiredTranches::Exact { tranche, tolerated_missing, latest_assignment_tick, .. }`, then we + return whether all assigned validators up to `tranche` less `tolerated_missing` have approved and + `latest_assignment_tick + APPROVAL_DELAY >= tick_now`. + * e.g. if we had 5 tranches and 1 tolerated missing, we would accept only if all but 1 of assigned validators in + tranches 0..=5 have approved. In that example, we also accept all validators in tranches 0..=5 having approved, + but that would indicate that the `RequiredTranches` value was incorrectly constructed, so it is not realistic. + `tolerated_missing` actually represents covered no-shows. If there are more missing approvals than there are + tolerated missing, that indicates that there are some assignments which are not yet no-shows, but may become + no-shows, and we should wait for the validators to either approve or become no-shows. + * e.g. If the above passes and the `latest_assignment_tick` was 5 and the current tick was 6, then we'd return + false. ### Time diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/README.md b/polkadot/roadmap/implementers-guide/src/node/availability/README.md index 76bd6467e178..2fcfd58de9e8 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/README.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/README.md @@ -1,3 +1,7 @@ # Availability Subsystems -The availability subsystems are responsible for ensuring that Proofs of Validity of backed candidates are widely available within the validator set, without requiring every node to retain a full copy. They accomplish this by broadly distributing erasure-coded chunks of the PoV, keeping track of which validator has which chunk by means of signed bitfields. They are also responsible for reassembling a complete PoV when required, e.g. when an approval checker needs to validate a parachain block. +The availability subsystems are responsible for ensuring that Proofs of Validity of backed candidates are widely +available within the validator set, without requiring every node to retain a full copy. They accomplish this by broadly +distributing erasure-coded chunks of the PoV, keeping track of which validator has which chunk by means of signed +bitfields. They are also responsible for reassembling a complete PoV when required, e.g. when an approval checker needs +to validate a parachain block. diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/availability-distribution.md b/polkadot/roadmap/implementers-guide/src/node/availability/availability-distribution.md index 1760a2ee7df4..931d82d529b9 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/availability-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/availability-distribution.md @@ -1,31 +1,26 @@ # Availability Distribution -This subsystem is responsible for distribution availability data to peers. -Availability data are chunks, `PoV`s and `AvailableData` (which is `PoV` + -`PersistedValidationData`). It does so via request response protocols. +This subsystem is responsible for distribution availability data to peers. Availability data are chunks, `PoV`s and +`AvailableData` (which is `PoV` + `PersistedValidationData`). It does so via request response protocols. In particular this subsystem is responsible for: -- Respond to network requests requesting availability data by querying the - [Availability Store](../utility/availability-store.md). -- Request chunks from backing validators to put them in the local `Availability - Store` whenever we find an occupied core on any fresh leaf, - this is to ensure availability by at least 2/3+ of all validators, this - happens after a candidate is backed. -- Fetch `PoV` from validators, when requested via `FetchPoV` message from - backing (`pov_requester` module). +- Respond to network requests requesting availability data by querying the [Availability + Store](../utility/availability-store.md). +- Request chunks from backing validators to put them in the local `Availability Store` whenever we find an occupied core + on any fresh leaf, this is to ensure availability by at least 2/3+ of all validators, this happens after a candidate + is backed. +- Fetch `PoV` from validators, when requested via `FetchPoV` message from backing (`pov_requester` module). -The backing subsystem is responsible of making available data available in the -local `Availability Store` upon validation. This subsystem will serve any -network requests by querying that store. +The backing subsystem is responsible of making available data available in the local `Availability Store` upon +validation. This subsystem will serve any network requests by querying that store. ## Protocol -This subsystem does not handle any peer set messages, but the `pov_requester` -does connect to validators of the same backing group on the validation peer -set, to ensure fast propagation of statements between those validators and for -ensuring already established connections for requesting `PoV`s. Other than that -this subsystem drives request/response protocols. +This subsystem does not handle any peer set messages, but the `pov_requester` does connect to validators of the same +backing group on the validation peer set, to ensure fast propagation of statements between those validators and for +ensuring already established connections for requesting `PoV`s. Other than that this subsystem drives request/response +protocols. Input: @@ -48,51 +43,42 @@ Output: ### PoV Requester -The PoV requester in the `pov_requester` module takes care of staying connected -to validators of the current backing group of this very validator on the `Validation` -peer set and it will handle `FetchPoV` requests by issuing network requests to -those validators. It will check the hash of the received `PoV`, but will not do any -further validation. That needs to be done by the original `FetchPoV` sender -(backing subsystem). +The PoV requester in the `pov_requester` module takes care of staying connected to validators of the current backing +group of this very validator on the `Validation` peer set and it will handle `FetchPoV` requests by issuing network +requests to those validators. It will check the hash of the received `PoV`, but will not do any further validation. That +needs to be done by the original `FetchPoV` sender (backing subsystem). ### Chunk Requester -After a candidate is backed, the availability of the PoV block must be confirmed -by 2/3+ of all validators. The chunk requester is responsible of making that -availability a reality. +After a candidate is backed, the availability of the PoV block must be confirmed by 2/3+ of all validators. The chunk +requester is responsible of making that availability a reality. -It does that by querying checking occupied cores for all active leaves. For each -occupied core it will spawn a task fetching the erasure chunk which has the -`ValidatorIndex` of the node. For this an `ChunkFetchingRequest` is issued, via -substrate's generic request/response protocol. +It does that by querying checking occupied cores for all active leaves. For each occupied core it will spawn a task +fetching the erasure chunk which has the `ValidatorIndex` of the node. For this an `ChunkFetchingRequest` is issued, via +Substrate's generic request/response protocol. -The spawned task will start trying to fetch the chunk from validators in -responsible group of the occupied core, in a random order. For ensuring that we -use already open TCP connections wherever possible, the requester maintains a -cache and preserves that random order for the entire session. +The spawned task will start trying to fetch the chunk from validators in responsible group of the occupied core, in a +random order. For ensuring that we use already open TCP connections wherever possible, the requester maintains a cache +and preserves that random order for the entire session. -Note however that, because not all validators in a group have to be actual -backers, not all of them are required to have the needed chunk. This in turn -could lead to low throughput, as we have to wait for fetches to fail, -before reaching a validator finally having our chunk. We do rank back validators -not delivering our chunk, but as backers could vary from block to block on a -perfectly legitimate basis, this is still not ideal. See issues [2509](https://github.com/paritytech/polkadot/issues/2509) and [2512](https://github.com/paritytech/polkadot/issues/2512) -for more information. +Note however that, because not all validators in a group have to be actual backers, not all of them are required to have +the needed chunk. This in turn could lead to low throughput, as we have to wait for fetches to fail, before reaching a +validator finally having our chunk. We do rank back validators not delivering our chunk, but as backers could vary from +block to block on a perfectly legitimate basis, this is still not ideal. See issues +[2509](https://github.com/paritytech/polkadot/issues/2509) and +[2512](https://github.com/paritytech/polkadot/issues/2512) for more information. -The current implementation also only fetches chunks for occupied cores in blocks -in active leaves. This means though, if active leaves skips a block or we are -particularly slow in fetching our chunk, we might not fetch our chunk if -availability reached 2/3 fast enough (slot becomes free). This is not desirable -as we would like as many validators as possible to have their chunk. See this -[issue](https://github.com/paritytech/polkadot/issues/2513) for more details. +The current implementation also only fetches chunks for occupied cores in blocks in active leaves. This means though, if +active leaves skips a block or we are particularly slow in fetching our chunk, we might not fetch our chunk if +availability reached 2/3 fast enough (slot becomes free). This is not desirable as we would like as many validators as +possible to have their chunk. See this [issue](https://github.com/paritytech/polkadot/issues/2513) for more details. ### Serving -On the other side the subsystem will listen for incoming `ChunkFetchingRequest`s -and `PoVFetchingRequest`s from the network bridge and will respond to queries, -by looking the requested chunks and `PoV`s up in the availability store, this -happens in the `responder` module. +On the other side the subsystem will listen for incoming `ChunkFetchingRequest`s and `PoVFetchingRequest`s from the +network bridge and will respond to queries, by looking the requested chunks and `PoV`s up in the availability store, +this happens in the `responder` module. -We rely on the backing subsystem to make available data available locally in the -`Availability Store` after it has validated it. +We rely on the backing subsystem to make available data available locally in the `Availability Store` after it has +validated it. diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md b/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md index ac733c1ce918..e3bb14db3a55 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md @@ -1,8 +1,13 @@ # Availability Recovery -This subsystem is the inverse of the [Availability Distribution](availability-distribution.md) subsystem: validators will serve the availability chunks kept in the availability store to nodes who connect to them. And the subsystem will also implement the other side: the logic for nodes to connect to validators, request availability pieces, and reconstruct the `AvailableData`. +This subsystem is the inverse of the [Availability Distribution](availability-distribution.md) subsystem: validators +will serve the availability chunks kept in the availability store to nodes who connect to them. And the subsystem will +also implement the other side: the logic for nodes to connect to validators, request availability pieces, and +reconstruct the `AvailableData`. -This version of the availability recovery subsystem is based off of direct connections to validators. In order to recover any given `AvailableData`, we must recover at least `f + 1` pieces from validators of the session. Thus, we will connect to and query randomly chosen validators until we have received `f + 1` pieces. +This version of the availability recovery subsystem is based off of direct connections to validators. In order to +recover any given `AvailableData`, we must recover at least `f + 1` pieces from validators of the session. Thus, we will +connect to and query randomly chosen validators until we have received `f + 1` pieces. ## Protocol @@ -10,18 +15,20 @@ This version of the availability recovery subsystem is based off of direct conne Input: -- `NetworkBridgeUpdate(update)` -- `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session, backing_group, response)` +* `NetworkBridgeUpdate(update)` +* `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session, backing_group, response)` Output: -- `NetworkBridge::SendValidationMessage` -- `NetworkBridge::ReportPeer` -- `AvailabilityStore::QueryChunk` +* `NetworkBridge::SendValidationMessage` +* `NetworkBridge::ReportPeer` +* `AvailabilityStore::QueryChunk` ## Functionality -We hold a state which tracks the currently ongoing recovery tasks, as well as which request IDs correspond to which task. A recovery task is a structure encapsulating all recovery tasks with the network necessary to recover the available data in respect to one candidate. +We hold a state which tracks the currently ongoing recovery tasks, as well as which request IDs correspond to which +task. A recovery task is a structure encapsulating all recovery tasks with the network necessary to recover the +available data in respect to one candidate. ```rust struct State { @@ -87,17 +94,22 @@ On `Conclude`, shut down the subsystem. 1. Check the `availability_lru` for the candidate and return the data if so. 1. Check if there is already an recovery handle for the request. If so, add the response handle to it. -1. Otherwise, load the session info for the given session under the state of `live_block_hash`, and initiate a recovery task with *`launch_recovery_task`*. Add a recovery handle to the state and add the response channel to it. +1. Otherwise, load the session info for the given session under the state of `live_block_hash`, and initiate a recovery + task with *`launch_recovery_task`*. Add a recovery handle to the state and add the response channel to it. 1. If the session info is not available, return `RecoveryError::Unavailable` on the response channel. ### Recovery logic #### `launch_recovery_task(session_index, session_info, candidate_receipt, candidate_hash, Option)` -1. Compute the threshold from the session info. It should be `f + 1`, where `n = 3f + k`, where `k in {1, 2, 3}`, and `n` is the number of validators. -1. Set the various fields of `RecoveryParams` based on the validator lists in `session_info` and information about the candidate. -1. If the `backing_group_index` is `Some`, start in the `RequestFromBackers` phase with a shuffling of the backing group validator indices and a `None` requesting value. -1. Otherwise, start in the `RequestChunksFromValidators` source with `received_chunks`,`requesting_chunks`, and `next_shuffling` all empty. +1. Compute the threshold from the session info. It should be `f + 1`, where `n = 3f + k`, where `k in {1, 2, 3}`, and + `n` is the number of validators. +1. Set the various fields of `RecoveryParams` based on the validator lists in `session_info` and information about the + candidate. +1. If the `backing_group_index` is `Some`, start in the `RequestFromBackers` phase with a shuffling of the backing group + validator indices and a `None` requesting value. +1. Otherwise, start in the `RequestChunksFromValidators` source with `received_chunks`,`requesting_chunks`, and + `next_shuffling` all empty. 1. Set the `to_subsystems` sender to be equal to a clone of the `SubsystemContext`'s sender. 1. Initialize `received_chunks` to an empty set, as well as `requesting_chunks`. @@ -115,19 +127,24 @@ const N_PARALLEL: usize = 50; * Loop: * If the `requesting_pov` is `Some`, poll for updates on it. If it concludes, set `requesting_pov` to `None`. * If the `requesting_pov` is `None`, take the next backer off the `shuffled_backers`. - * If the backer is `Some`, issue a `NetworkBridgeMessage::Requests` with a network request for the `AvailableData` and wait for the response. + * If the backer is `Some`, issue a `NetworkBridgeMessage::Requests` with a network request for the + `AvailableData` and wait for the response. * If it concludes with a `None` result, return to beginning. * If it concludes with available data, attempt a re-encoding. * If it has the correct erasure-root, break and issue a `Ok(available_data)`. * If it has an incorrect erasure-root, return to beginning. * Send the result to each member of `awaiting`. - * If the backer is `None`, set the source to `RequestChunksFromValidators` with a random shuffling of validators and empty `received_chunks`, and `requesting_chunks` and break the loop. + * If the backer is `None`, set the source to `RequestChunksFromValidators` with a random shuffling of validators + and empty `received_chunks`, and `requesting_chunks` and break the loop. * If the task contains `RequestChunksFromValidators`: - * Request `AvailabilityStoreMessage::QueryAllChunks`. For each chunk that exists, add it to `received_chunks` and remote the validator from `shuffling`. + * Request `AvailabilityStoreMessage::QueryAllChunks`. For each chunk that exists, add it to `received_chunks` and + remote the validator from `shuffling`. * Loop: - * If `received_chunks + requesting_chunks + shuffling` lengths are less than the threshold, break and return `Err(Unavailable)`. - * Poll for new updates from `requesting_chunks`. Check merkle proofs of any received chunks. If the request simply fails due to network issues, insert into the front of `shuffling` to be retried. + * If `received_chunks + requesting_chunks + shuffling` lengths are less than the threshold, break and return + `Err(Unavailable)`. + * Poll for new updates from `requesting_chunks`. Check merkle proofs of any received chunks. If the request simply + fails due to network issues, insert into the front of `shuffling` to be retried. * If `received_chunks` has more than `threshold` entries, attempt to recover the data. * If that fails, return `Err(RecoveryError::Invalid)` * If correct: @@ -135,5 +152,6 @@ const N_PARALLEL: usize = 50; * break and issue `Ok(available_data)` * Send the result to each member of `awaiting`. * While there are fewer than `N_PARALLEL` entries in `requesting_chunks`, - * Pop the next item from `shuffling`. If it's empty and `requesting_chunks` is empty, return `Err(RecoveryError::Unavailable)`. + * Pop the next item from `shuffling`. If it's empty and `requesting_chunks` is empty, return + `Err(RecoveryError::Unavailable)`. * Issue a `NetworkBridgeMessage::Requests` and wait for the response in `requesting_chunks`. diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-distribution.md b/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-distribution.md index 53bd8a1bced6..097f2e635384 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-distribution.md @@ -1,34 +1,40 @@ # Bitfield Distribution -Validators vote on the availability of a backed candidate by issuing signed bitfields, where each bit corresponds to a single candidate. These bitfields can be used to compactly determine which backed candidates are available or not based on a 2/3+ quorum. +Validators vote on the availability of a backed candidate by issuing signed bitfields, where each bit corresponds to a +single candidate. These bitfields can be used to compactly determine which backed candidates are available or not based +on a 2/3+ quorum. ## Protocol `PeerSet`: `Validation` -Input: -[`BitfieldDistributionMessage`](../../types/overseer-protocol.md#bitfield-distribution-message) which are gossiped to all peers, no matter if validator or not. +Input: [`BitfieldDistributionMessage`](../../types/overseer-protocol.md#bitfield-distribution-message) which are +gossiped to all peers, no matter if validator or not. Output: -- `NetworkBridge::SendValidationMessage([PeerId], message)` gossip a verified incoming bitfield on to interested subsystems within this validator node. -- `NetworkBridge::ReportPeer(PeerId, cost_or_benefit)` improve or penalize the reputation of peers based on the messages that are received relative to the current view. -- `ProvisionerMessage::ProvisionableData(ProvisionableData::Bitfield(relay_parent, SignedAvailabilityBitfield))` pass - on the bitfield to the other submodules via the overseer. +- `NetworkBridge::SendValidationMessage([PeerId], message)` gossip a verified incoming bitfield on to interested + subsystems within this validator node. +- `NetworkBridge::ReportPeer(PeerId, cost_or_benefit)` improve or penalize the reputation of peers based on the messages + that are received relative to the current view. +- `ProvisionerMessage::ProvisionableData(ProvisionableData::Bitfield(relay_parent, SignedAvailabilityBitfield))` pass on + the bitfield to the other submodules via the overseer. ## Functionality This is implemented as a gossip system. -It is necessary to track peer connection, view change, and disconnection events, in order to maintain an index of which peers are interested in which relay parent bitfields. +It is necessary to track peer connection, view change, and disconnection events, in order to maintain an index of which +peers are interested in which relay parent bitfields. -Before gossiping incoming bitfields, they must be checked to be signed by one of the validators -of the validator set relevant to the current relay parent. -Only accept bitfields relevant to our current view and only distribute bitfields to other peers when relevant to their most recent view. -Accept and distribute only one bitfield per validator. +Before gossiping incoming bitfields, they must be checked to be signed by one of the validators of the validator set +relevant to the current relay parent. Only accept bitfields relevant to our current view and only distribute bitfields +to other peers when relevant to their most recent view. Accept and distribute only one bitfield per validator. -When receiving a bitfield either from the network or from a `DistributeBitfield` message, forward it along to the block authorship (provisioning) subsystem for potential inclusion in a block. +When receiving a bitfield either from the network or from a `DistributeBitfield` message, forward it along to the block +authorship (provisioning) subsystem for potential inclusion in a block. -Peers connecting after a set of valid bitfield gossip messages was received, those messages must be cached and sent upon connection of new peers or re-connecting peers. +Peers connecting after a set of valid bitfield gossip messages was received, those messages must be cached and sent upon +connection of new peers or re-connecting peers. diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-signing.md b/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-signing.md index 08cbe528473e..a5875e0a8055 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-signing.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/bitfield-signing.md @@ -1,12 +1,15 @@ # Bitfield Signing -Validators vote on the availability of a backed candidate by issuing signed bitfields, where each bit corresponds to a single candidate. These bitfields can be used to compactly determine which backed candidates are available or not based on a 2/3+ quorum. +Validators vote on the availability of a backed candidate by issuing signed bitfields, where each bit corresponds to a +single candidate. These bitfields can be used to compactly determine which backed candidates are available or not based +on a 2/3+ quorum. ## Protocol Input: -There is no dedicated input mechanism for bitfield signing. Instead, Bitfield Signing produces a bitfield representing the current state of availability on `StartWork`. +There is no dedicated input mechanism for bitfield signing. Instead, Bitfield Signing produces a bitfield representing +the current state of availability on `StartWork`. Output: @@ -15,15 +18,20 @@ Output: ## Functionality -Upon receipt of an `ActiveLeavesUpdate`, launch bitfield signing job for each `activated` head referring to a fresh leaf. Stop the job for each `deactivated` head. +Upon receipt of an `ActiveLeavesUpdate`, launch bitfield signing job for each `activated` head referring to a fresh +leaf. Stop the job for each `deactivated` head. ## Bitfield Signing Job -Localized to a specific relay-parent `r` -If not running as a validator, do nothing. +Localized to a specific relay-parent `r` If not running as a validator, do nothing. -- For each fresh leaf, begin by waiting a fixed period of time so availability distribution has the chance to make candidates available. -- Determine our validator index `i`, the set of backed candidates pending availability in `r`, and which bit of the bitfield each corresponds to. -- Start with an empty bitfield. For each bit in the bitfield, if there is a candidate pending availability, query the [Availability Store](../utility/availability-store.md) for whether we have the availability chunk for our validator index. The `OccupiedCore` struct contains the candidate hash so the full candidate does not need to be fetched from runtime. +- For each fresh leaf, begin by waiting a fixed period of time so availability distribution has the chance to make + candidates available. +- Determine our validator index `i`, the set of backed candidates pending availability in `r`, and which bit of the + bitfield each corresponds to. +- Start with an empty bitfield. For each bit in the bitfield, if there is a candidate pending availability, query the + [Availability Store](../utility/availability-store.md) for whether we have the availability chunk for our validator + index. The `OccupiedCore` struct contains the candidate hash so the full candidate does not need to be fetched from + runtime. - For all chunks we have, set the corresponding bit in the bitfield. - Sign the bitfield and dispatch a `BitfieldDistribution::DistributeBitfield` message. diff --git a/polkadot/roadmap/implementers-guide/src/node/backing/README.md b/polkadot/roadmap/implementers-guide/src/node/backing/README.md index ac47abefb0d0..d2a77ded6b76 100644 --- a/polkadot/roadmap/implementers-guide/src/node/backing/README.md +++ b/polkadot/roadmap/implementers-guide/src/node/backing/README.md @@ -1,10 +1,15 @@ # Backing Subsystems -The backing subsystems, when conceived as a black box, receive an arbitrary quantity of parablock candidates and associated proofs of validity from arbitrary untrusted collators. From these, they produce a bounded quantity of backable candidates which relay chain block authors may choose to include in a subsequent block. +The backing subsystems, when conceived as a black box, receive an arbitrary quantity of parablock candidates and +associated proofs of validity from arbitrary untrusted collators. From these, they produce a bounded quantity of +backable candidates which relay chain block authors may choose to include in a subsequent block. In broad strokes, the flow operates like this: - **Candidate Selection** winnows the field of parablock candidates, selecting up to one of them to second. -- **Candidate Backing** ensures that a seconding candidate is valid, then generates the appropriate `Statement`. It also keeps track of which candidates have received the backing of a quorum of other validators. -- **Statement Distribution** is the networking component which ensures that all validators receive each others' statements. -- **PoV Distribution** is the networking component which ensures that validators considering a candidate can get the appropriate PoV. +- **Candidate Backing** ensures that a seconding candidate is valid, then generates the appropriate `Statement`. It also + keeps track of which candidates have received the backing of a quorum of other validators. +- **Statement Distribution** is the networking component which ensures that all validators receive each others' + statements. +- **PoV Distribution** is the networking component which ensures that validators considering a candidate can get the + appropriate PoV. diff --git a/polkadot/roadmap/implementers-guide/src/node/backing/candidate-backing.md b/polkadot/roadmap/implementers-guide/src/node/backing/candidate-backing.md index 0eee0cc532ef..31f8423fe27b 100644 --- a/polkadot/roadmap/implementers-guide/src/node/backing/candidate-backing.md +++ b/polkadot/roadmap/implementers-guide/src/node/backing/candidate-backing.md @@ -1,12 +1,20 @@ # Candidate Backing -The Candidate Backing subsystem ensures every parablock considered for relay block inclusion has been seconded by at least one validator, and approved by a quorum. Parablocks for which not enough validators will assert correctness are discarded. If the block later proves invalid, the initial backers are slashable; this gives polkadot a rational threat model during subsequent stages. +The Candidate Backing subsystem ensures every parablock considered for relay block inclusion has been seconded by at +least one validator, and approved by a quorum. Parablocks for which not enough validators will assert correctness are +discarded. If the block later proves invalid, the initial backers are slashable; this gives Polkadot a rational threat +model during subsequent stages. -Its role is to produce backable candidates for inclusion in new relay-chain blocks. It does so by issuing signed [`Statement`s][Statement] and tracking received statements signed by other validators. Once enough statements are received, they can be combined into backing for specific candidates. +Its role is to produce backable candidates for inclusion in new relay-chain blocks. It does so by issuing signed +[`Statement`s][Statement] and tracking received statements signed by other validators. Once enough statements are +received, they can be combined into backing for specific candidates. -Note that though the candidate backing subsystem attempts to produce as many backable candidates as possible, it does _not_ attempt to choose a single authoritative one. The choice of which actually gets included is ultimately up to the block author, by whatever metrics it may use; those are opaque to this subsystem. +Note that though the candidate backing subsystem attempts to produce as many backable candidates as possible, it does +_not_ attempt to choose a single authoritative one. The choice of which actually gets included is ultimately up to the +block author, by whatever metrics it may use; those are opaque to this subsystem. -Once a sufficient quorum has agreed that a candidate is valid, this subsystem notifies the [Provisioner][PV], which in turn engages block production mechanisms to include the parablock. +Once a sufficient quorum has agreed that a candidate is valid, this subsystem notifies the [Provisioner][PV], which in +turn engages block production mechanisms to include the parablock. ## Protocol @@ -14,33 +22,49 @@ Input: [`CandidateBackingMessage`][CBM] Output: -- [`CandidateValidationMessage`][CVM] -- [`RuntimeApiMessage`][RAM] -- [`CollatorProtocolMessage`][CPM] -- [`ProvisionerMessage`][PM] -- [`AvailabilityDistributionMessage`][ADM] -- [`StatementDistributionMessage`][SDM] +* [`CandidateValidationMessage`][CVM] +* [`RuntimeApiMessage`][RAM] +* [`CollatorProtocolMessage`][CPM] +* [`ProvisionerMessage`][PM] +* [`AvailabilityDistributionMessage`][ADM] +* [`StatementDistributionMessage`][SDM] ## Functionality -The [Collator Protocol][CP] subsystem is the primary source of non-overseer messages into this subsystem. That subsystem generates appropriate [`CandidateBackingMessage`s][CBM] and passes them to this subsystem. +The [Collator Protocol][CP] subsystem is the primary source of non-overseer messages into this subsystem. That subsystem +generates appropriate [`CandidateBackingMessage`s][CBM] and passes them to this subsystem. -This subsystem requests validation from the [Candidate Validation][CV] and generates an appropriate [`Statement`][Statement]. All `Statement`s are then passed on to the [Statement Distribution][SD] subsystem to be gossiped to peers. When [Candidate Validation][CV] decides that a candidate is invalid, and it was recommended to us to second by our own [Collator Protocol][CP] subsystem, a message is sent to the [Collator Protocol][CP] subsystem with the candidate's hash so that the collator which recommended it can be penalized. +This subsystem requests validation from the [Candidate Validation][CV] and generates an appropriate +[`Statement`][Statement]. All `Statement`s are then passed on to the [Statement Distribution][SD] subsystem to be +gossiped to peers. When [Candidate Validation][CV] decides that a candidate is invalid, and it was recommended to us to +second by our own [Collator Protocol][CP] subsystem, a message is sent to the [Collator Protocol][CP] subsystem with the +candidate's hash so that the collator which recommended it can be penalized. -The subsystem should maintain a set of handles to Candidate Backing Jobs that are currently live, as well as the relay-parent to which they correspond. +The subsystem should maintain a set of handles to Candidate Backing Jobs that are currently live, as well as the +relay-parent to which they correspond. ### On Overseer Signal * If the signal is an [`OverseerSignal`][OverseerSignal]`::ActiveLeavesUpdate`: - * spawn a Candidate Backing Job for each `activated` head referring to a fresh leaf, storing a bidirectional channel with the Candidate Backing Job in the set of handles. + * spawn a Candidate Backing Job for each `activated` head referring to a fresh leaf, storing a bidirectional channel + with the Candidate Backing Job in the set of handles. * cease the Candidate Backing Job for each `deactivated` head, if any. -* If the signal is an [`OverseerSignal`][OverseerSignal]`::Conclude`: Forward conclude messages to all jobs, wait a small amount of time for them to join, and then exit. +* If the signal is an [`OverseerSignal`][OverseerSignal]`::Conclude`: Forward conclude messages to all jobs, wait a + small amount of time for them to join, and then exit. ### On Receiving `CandidateBackingMessage` -* If the message is a [`CandidateBackingMessage`][CBM]`::GetBackedCandidates`, get all backable candidates from the statement table and send them back. -* If the message is a [`CandidateBackingMessage`][CBM]`::Second`, sign and dispatch a `Seconded` statement only if we have not seconded any other candidate and have not signed a `Valid` statement for the requested candidate. Signing both a `Seconded` and `Valid` message is a double-voting misbehavior with a heavy penalty, and this could occur if another validator has seconded the same candidate and we've received their message before the internal seconding request. -* If the message is a [`CandidateBackingMessage`][CBM]`::Statement`, count the statement to the quorum. If the statement in the message is `Seconded` and it contains a candidate that belongs to our assignment, request the corresponding `PoV` from the backing node via `AvailabilityDistribution` and launch validation. Issue our own `Valid` or `Invalid` statement as a result. +* If the message is a [`CandidateBackingMessage`][CBM]`::GetBackedCandidates`, get all backable candidates from the + statement table and send them back. +* If the message is a [`CandidateBackingMessage`][CBM]`::Second`, sign and dispatch a `Seconded` statement only if we + have not seconded any other candidate and have not signed a `Valid` statement for the requested candidate. Signing + both a `Seconded` and `Valid` message is a double-voting misbehavior with a heavy penalty, and this could occur if + another validator has seconded the same candidate and we've received their message before the internal seconding + request. +* If the message is a [`CandidateBackingMessage`][CBM]`::Statement`, count the statement to the quorum. If the statement + in the message is `Seconded` and it contains a candidate that belongs to our assignment, request the corresponding + `PoV` from the backing node via `AvailabilityDistribution` and launch validation. Issue our own `Valid` or `Invalid` + statement as a result. If the seconding node did not provide us with the `PoV` we will retry fetching from other backing validators. @@ -51,19 +75,25 @@ If the seconding node did not provide us with the `PoV` we will retry fetching f > * Allow inclusion of _old_ parachain candidates validated by _current_ validators. > * Allow inclusion of _old_ parachain candidates validated by _old_ validators. > -> This will probably blur the lines between jobs, will probably require inter-job communication and a short-term memory of recently backable, but not backed candidates. +> This will probably blur the lines between jobs, will probably require inter-job communication and a short-term memory +> of recently backable, but not backed candidates. ## Candidate Backing Job -The Candidate Backing Job represents the work a node does for backing candidates with respect to a particular relay-parent. +The Candidate Backing Job represents the work a node does for backing candidates with respect to a particular +relay-parent. -The goal of a Candidate Backing Job is to produce as many backable candidates as possible. This is done via signed [`Statement`s][STMT] by validators. If a candidate receives a majority of supporting Statements from the Parachain Validators currently assigned, then that candidate is considered backable. +The goal of a Candidate Backing Job is to produce as many backable candidates as possible. This is done via signed +[`Statement`s][STMT] by validators. If a candidate receives a majority of supporting Statements from the Parachain +Validators currently assigned, then that candidate is considered backable. ### On Startup -* Fetch current validator set, validator -> parachain assignments from [`Runtime API`][RA] subsystem using [`RuntimeApiRequest::Validators`][RAM] and [`RuntimeApiRequest::ValidatorGroups`][RAM] +* Fetch current validator set, validator -> parachain assignments from [`Runtime API`][RA] subsystem using + [`RuntimeApiRequest::Validators`][RAM] and [`RuntimeApiRequest::ValidatorGroups`][RAM] * Determine if the node controls a key in the current validator set. Call this the local key if so. -* If the local key exists, extract the parachain head and validation function from the [`Runtime API`][RA] for the parachain the local key is assigned to by issuing a [`RuntimeApiRequest::Validators`][RAM] +* If the local key exists, extract the parachain head and validation function from the [`Runtime API`][RA] for the + parachain the local key is assigned to by issuing a [`RuntimeApiRequest::Validators`][RAM] * Issue a [`RuntimeApiRequest::SigningContext`][RAM] message to get a context that will later be used upon signing. ### On Receiving New Candidate Backing Message @@ -91,15 +121,17 @@ match msg { } ``` -Add `Seconded` statements and `Valid` statements to a quorum. If the quorum reaches a pre-defined threshold, send a [`ProvisionerMessage`][PM]`::ProvisionableData(ProvisionableData::BackedCandidate(CandidateReceipt))` message. -`Invalid` statements that conflict with already witnessed `Seconded` and `Valid` statements for the given candidate, statements that are double-votes, self-contradictions and so on, should result in issuing a [`ProvisionerMessage`][PM]`::MisbehaviorReport` message for each newly detected case of this kind. +Add `Seconded` statements and `Valid` statements to a quorum. If the quorum reaches a pre-defined threshold, send a +[`ProvisionerMessage`][PM]`::ProvisionableData(ProvisionableData::BackedCandidate(CandidateReceipt))` message. `Invalid` +statements that conflict with already witnessed `Seconded` and `Valid` statements for the given candidate, statements +that are double-votes, self-contradictions and so on, should result in issuing a +[`ProvisionerMessage`][PM]`::MisbehaviorReport` message for each newly detected case of this kind. -Backing does not need to concern itself with providing statements to the dispute -coordinator as the dispute coordinator scrapes them from chain. This way the -import is batched and contains only statements that actually made it on some +Backing does not need to concern itself with providing statements to the dispute coordinator as the dispute coordinator +scrapes them from chain. This way the import is batched and contains only statements that actually made it on some chain. -### Validating Candidates. +### Validating Candidates ```rust fn spawn_validation_work(candidate, parachain head, validation function) { @@ -119,14 +151,16 @@ fn spawn_validation_work(candidate, parachain head, validation function) { ### Fetch PoV Block -Create a `(sender, receiver)` pair. -Dispatch a [`AvailabilityDistributionMessage`][ADM]`::FetchPoV{ validator_index, pov_hash, candidate_hash, tx, } and listen on the passed receiver for a response. Availability distribution will send the request to the validator specified by `validator_index`, which might not be serving it for whatever reasons, therefore we need to retry with other backing validators in that case. +Create a `(sender, receiver)` pair. Dispatch a [`AvailabilityDistributionMessage`][ADM]`::FetchPoV{ validator_index, +pov_hash, candidate_hash, tx, }` and listen on the passed receiver for a response. Availability distribution will send +the request to the validator specified by `validator_index`, which might not be serving it for whatever reasons, +therefore we need to retry with other backing validators in that case. ### Validate PoV Block -Create a `(sender, receiver)` pair. -Dispatch a `CandidateValidationMessage::Validate(validation function, candidate, pov, BACKING_EXECUTION_TIMEOUT, sender)` and listen on the receiver for a response. +Create a `(sender, receiver)` pair. Dispatch a `CandidateValidationMessage::Validate(validation function, candidate, +pov, BACKING_EXECUTION_TIMEOUT, sender)` and listen on the receiver for a response. ### Distribute Signed Statement diff --git a/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md b/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md index 5cbc875d8a73..e10a55010b91 100644 --- a/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md +++ b/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md @@ -1,18 +1,16 @@ # Statement Distribution (Legacy) -This describes the legacy, backwards-compatible version of the Statement -Distribution subsystem. +This describes the legacy, backwards-compatible version of the Statement Distribution subsystem. -**Note:** All the V1 (legacy) code was extracted out to a `legacy_v1` module of -the `statement-distribution` crate, which doesn't alter any logic. V2 (new -protocol) peers also run `legacy_v1` and communicate with V1 peers using V1 -messages and with V2 peers using V2 messages. Once the runtime upgrade goes -through on all networks, this `legacy_v1` code will no longer be triggered and -will be vestigial and can be removed. +**Note:** All the V1 (legacy) code was extracted out to a `legacy_v1` module of the `statement-distribution` crate, +which doesn't alter any logic. V2 (new protocol) peers also run `legacy_v1` and communicate with V1 peers using V1 +messages and with V2 peers using V2 messages. Once the runtime upgrade goes through on all networks, this `legacy_v1` +code will no longer be triggered and will be vestigial and can be removed. ## Overview -The Statement Distribution Subsystem is responsible for distributing statements about seconded candidates between validators. +The Statement Distribution Subsystem is responsible for distributing statements about seconded candidates between +validators. ## Protocol @@ -31,89 +29,133 @@ Output: ## Functionality -Implemented as a gossip protocol. Handles updates to our view and peers' views. Neighbor packets are used to inform peers which chain heads we are interested in data for. +Implemented as a gossip protocol. Handles updates to our view and peers' views. Neighbor packets are used to inform +peers which chain heads we are interested in data for. -The Statement Distribution Subsystem is responsible for distributing signed statements that we have generated and for forwarding statements generated by other validators. It also detects a variety of Validator misbehaviors for reporting to the [Provisioner Subsystem](../utility/provisioner.md). During the Backing stage of the inclusion pipeline, Statement Distribution is the main point of contact with peer nodes. On receiving a signed statement from a peer in the same backing group, assuming the peer receipt state machine is in an appropriate state, it sends the Candidate Receipt to the [Candidate Backing subsystem](candidate-backing.md) to handle the validator's statement. On receiving `StatementDistributionMessage::Share` we make sure to send messages to our backing group in addition to random other peers, to ensure a fast backing process and getting all statements quickly for distribution. +The Statement Distribution Subsystem is responsible for distributing signed statements that we have generated and for +forwarding statements generated by other validators. It also detects a variety of Validator misbehaviors for reporting +to the [Provisioner Subsystem](../utility/provisioner.md). During the Backing stage of the inclusion pipeline, Statement +Distribution is the main point of contact with peer nodes. On receiving a signed statement from a peer in the same +backing group, assuming the peer receipt state machine is in an appropriate state, it sends the Candidate Receipt to the +[Candidate Backing subsystem](candidate-backing.md) to handle the validator's statement. On receiving +`StatementDistributionMessage::Share` we make sure to send messages to our backing group in addition to random other +peers, to ensure a fast backing process and getting all statements quickly for distribution. -This subsystem tracks equivocating validators and stops accepting information from them. It establishes a data-dependency order: +This subsystem tracks equivocating validators and stops accepting information from them. It establishes a +data-dependency order: - In order to receive a `Seconded` message we have the corresponding chain head in our view - In order to receive a `Valid` message we must have received the corresponding `Seconded` message. -And respect this data-dependency order from our peers by respecting their views. This subsystem is responsible for checking message signatures. +And respect this data-dependency order from our peers by respecting their views. This subsystem is responsible for +checking message signatures. The Statement Distribution subsystem sends statements to peer nodes. ## Peer Receipt State Machine -There is a very simple state machine which governs which messages we are willing to receive from peers. Not depicted in the state machine: on initial receipt of any [`SignedFullStatement`](../../types/backing.md#signed-statement-type), validate that the provided signature does in fact sign the included data. Note that each individual parablock candidate gets its own instance of this state machine; it is perfectly legal to receive a `Valid(X)` before a `Seconded(Y)`, as long as a `Seconded(X)` has been received. +There is a very simple state machine which governs which messages we are willing to receive from peers. Not depicted in +the state machine: on initial receipt of any [`SignedFullStatement`](../../types/backing.md#signed-statement-type), +validate that the provided signature does in fact sign the included data. Note that each individual parablock candidate +gets its own instance of this state machine; it is perfectly legal to receive a `Valid(X)` before a `Seconded(Y)`, as +long as a `Seconded(X)` has been received. -A: Initial State. Receive `SignedFullStatement(Statement::Second)`: extract `Statement`, forward to Candidate Backing, proceed to B. Receive any other `SignedFullStatement` variant: drop it. +A: Initial State. Receive `SignedFullStatement(Statement::Second)`: extract `Statement`, forward to Candidate Backing, +proceed to B. Receive any other `SignedFullStatement` variant: drop it. -B: Receive any `SignedFullStatement`: check signature and determine whether the statement is new to us. if new, forward to Candidate Backing and circulate to other peers. Receive `OverseerMessage::StopWork`: proceed to C. +B: Receive any `SignedFullStatement`: check signature and determine whether the statement is new to us. if new, forward +to Candidate Backing and circulate to other peers. Receive `OverseerMessage::StopWork`: proceed to C. C: Receive any message for this block: drop it. -For large statements (see below), we also keep track of the total received large -statements per peer and have a hard limit on that number for flood protection. -This is necessary as in the current code we only forward statements once we have -all the data, therefore flood protection for large statement is a bit more -subtle. This will become an obsolete problem once [off chain code -upgrades](https://github.com/paritytech/polkadot/issues/2979) are implemented. +For large statements (see below), we also keep track of the total received large statements per peer and have a hard +limit on that number for flood protection. This is necessary as in the current code we only forward statements once we +have all the data, therefore flood protection for large statement is a bit more subtle. This will become an obsolete +problem once [off chain code upgrades](https://github.com/paritytech/polkadot/issues/2979) are implemented. ## Peer Knowledge Tracking -The peer receipt state machine implies that for parsimony of network resources, we should model the knowledge of our peers, and help them out. For example, let's consider a case with peers A, B, and C, validators X and Y, and candidate M. A sends us a `Statement::Second(M)` signed by X. We've double-checked it, and it's valid. While we're checking it, we receive a copy of X's `Statement::Second(M)` from `B`, along with a `Statement::Valid(M)` signed by Y. +The peer receipt state machine implies that for parsimony of network resources, we should model the knowledge of our +peers, and help them out. For example, let's consider a case with peers A, B, and C, validators X and Y, and candidate +M. A sends us a `Statement::Second(M)` signed by X. We've double-checked it, and it's valid. While we're checking it, we +receive a copy of X's `Statement::Second(M)` from `B`, along with a `Statement::Valid(M)` signed by Y. -Our response to A is just the `Statement::Valid(M)` signed by Y. However, we haven't heard anything about this from C. Therefore, we send it everything we have: first a copy of X's `Statement::Second`, then Y's `Statement::Valid`. +Our response to A is just the `Statement::Valid(M)` signed by Y. However, we haven't heard anything about this from C. +Therefore, we send it everything we have: first a copy of X's `Statement::Second`, then Y's `Statement::Valid`. -This system implies a certain level of duplication of messages--we received X's `Statement::Second` from both our peers, and C may experience the same--but it minimizes the degree to which messages are simply dropped. +This system implies a certain level of duplication of messages--we received X's `Statement::Second` from both our peers, +and C may experience the same--but it minimizes the degree to which messages are simply dropped. And respect this data-dependency order from our peers. This subsystem is responsible for checking message signatures. -No jobs. We follow view changes from the [`NetworkBridge`](../utility/network-bridge.md), which in turn is updated by the overseer. +No jobs. We follow view changes from the [`NetworkBridge`](../utility/network-bridge.md), which in turn is updated by +the overseer. ## Equivocations and Flood Protection -An equivocation is a double-vote by a validator. The [Candidate Backing](candidate-backing.md) Subsystem is better-suited than this one to detect equivocations as it adds votes to quorum trackers. +An equivocation is a double-vote by a validator. The [Candidate Backing](candidate-backing.md) Subsystem is +better-suited than this one to detect equivocations as it adds votes to quorum trackers. -At this level, we are primarily concerned about flood-protection, and to some extent, detecting equivocations is a part of that. In particular, we are interested in detecting equivocations of `Seconded` statements. Since every other statement is dependent on `Seconded` statements, ensuring that we only ever hold a bounded number of `Seconded` statements is sufficient for flood-protection. +At this level, we are primarily concerned about flood-protection, and to some extent, detecting equivocations is a part +of that. In particular, we are interested in detecting equivocations of `Seconded` statements. Since every other +statement is dependent on `Seconded` statements, ensuring that we only ever hold a bounded number of `Seconded` +statements is sufficient for flood-protection. -The simple approach is to say that we only receive up to two `Seconded` statements per validator per chain head. However, the marginal cost of equivocation, conditional on having already equivocated, is close to 0, since a single double-vote offence is counted as all double-vote offences for a particular chain-head. Even if it were not, there is some amount of equivocations that can be done such that the marginal cost of issuing further equivocations is close to 0, as there would be an amount of equivocations necessary to be completely and totally obliterated by the slashing algorithm. We fear the validator with nothing left to lose. +The simple approach is to say that we only receive up to two `Seconded` statements per validator per chain head. +However, the marginal cost of equivocation, conditional on having already equivocated, is close to 0, since a single +double-vote offence is counted as all double-vote offences for a particular chain-head. Even if it were not, there is +some amount of equivocations that can be done such that the marginal cost of issuing further equivocations is close to +0, as there would be an amount of equivocations necessary to be completely and totally obliterated by the slashing +algorithm. We fear the validator with nothing left to lose. With that in mind, this simple approach has a caveat worth digging deeper into. -First: We may be aware of two equivocated `Seconded` statements issued by a validator. A totally honest peer of ours can also be aware of one or two different `Seconded` statements issued by the same validator. And yet another peer may be aware of one or two _more_ `Seconded` statements. And so on. This interacts badly with pre-emptive sending logic. Upon sending a `Seconded` statement to a peer, we will want to pre-emptively follow up with all statements relative to that candidate. Waiting for acknowledgment introduces latency at every hop, so that is best avoided. What can happen is that upon receipt of the `Seconded` statement, the peer will discard it as it falls beyond the bound of 2 that it is allowed to store. It cannot store anything in memory about discarded candidates as that would introduce a DoS vector. Then, the peer would receive from us all of the statements pertaining to that candidate, which, from its perspective, would be undesired - they are data-dependent on the `Seconded` statement we sent them, but they have erased all record of that from their memory. Upon receiving a potential flood of undesired statements, this 100% honest peer may choose to disconnect from us. In this way, an adversary may be able to partition the network with careful distribution of equivocated `Seconded` statements. - -The fix is to track, per-peer, the hashes of up to 4 candidates per validator (per relay-parent) that the peer is aware of. It is 4 because we may send them 2 and they may send us 2 different ones. We track the data that they are aware of as the union of things we have sent them and things they have sent us. If we receive a 1st or 2nd `Seconded` statement from a peer, we note it in the peer's known candidates even if we do disregard the data locally. And then, upon receipt of any data dependent on that statement, we do not reduce that peer's standing in our eyes, as the data was not undesired. - -There is another caveat to the fix: we don't want to allow the peer to flood us because it has set things up in a way that it knows we will drop all of its traffic. -We also track how many statements we have received per peer, per candidate, and per chain-head. This is any statement concerning a particular candidate: `Seconded`, `Valid`, or `Invalid`. If we ever receive a statement from a peer which would push any of these counters beyond twice the amount of validators at the chain-head, we begin to lower the peer's standing and eventually disconnect. This bound is a massive overestimate and could be reduced to twice the number of validators in the corresponding validator group. It is worth noting that the goal at the time of writing is to ensure any finite bound on the amount of stored data, as any equivocation results in a large slash. +First: We may be aware of two equivocated `Seconded` statements issued by a validator. A totally honest peer of ours can +also be aware of one or two different `Seconded` statements issued by the same validator. And yet another peer may be +aware of one or two _more_ `Seconded` statements. And so on. This interacts badly with pre-emptive sending logic. Upon +sending a `Seconded` statement to a peer, we will want to pre-emptively follow up with all statements relative to that +candidate. Waiting for acknowledgment introduces latency at every hop, so that is best avoided. What can happen is that +upon receipt of the `Seconded` statement, the peer will discard it as it falls beyond the bound of 2 that it is allowed +to store. It cannot store anything in memory about discarded candidates as that would introduce a DoS vector. Then, the +peer would receive from us all of the statements pertaining to that candidate, which, from its perspective, would be +undesired - they are data-dependent on the `Seconded` statement we sent them, but they have erased all record of that +from their memory. Upon receiving a potential flood of undesired statements, this 100% honest peer may choose to +disconnect from us. In this way, an adversary may be able to partition the network with careful distribution of +equivocated `Seconded` statements. + +The fix is to track, per-peer, the hashes of up to 4 candidates per validator (per relay-parent) that the peer is aware +of. It is 4 because we may send them 2 and they may send us 2 different ones. We track the data that they are aware of +as the union of things we have sent them and things they have sent us. If we receive a 1st or 2nd `Seconded` statement +from a peer, we note it in the peer's known candidates even if we do disregard the data locally. And then, upon receipt +of any data dependent on that statement, we do not reduce that peer's standing in our eyes, as the data was not +undesired. + +There is another caveat to the fix: we don't want to allow the peer to flood us because it has set things up in a way +that it knows we will drop all of its traffic. We also track how many statements we have received per peer, per +candidate, and per chain-head. This is any statement concerning a particular candidate: `Seconded`, `Valid`, or +`Invalid`. If we ever receive a statement from a peer which would push any of these counters beyond twice the amount of +validators at the chain-head, we begin to lower the peer's standing and eventually disconnect. This bound is a massive +overestimate and could be reduced to twice the number of validators in the corresponding validator group. It is worth +noting that the goal at the time of writing is to ensure any finite bound on the amount of stored data, as any +equivocation results in a large slash. ## Large statements -Seconded statements can become quite large on parachain runtime upgrades for -example. For this reason, there exists a `LargeStatement` constructor for the -`StatementDistributionMessage` wire message, which only contains light metadata -of a statement. The actual candidate data is not included. This message type is -used whenever a message is deemed large. The receiver of such a message needs to -request the actual payload via request/response by means of a +Seconded statements can become quite large on parachain runtime upgrades for example. For this reason, there exists a +`LargeStatement` constructor for the `StatementDistributionMessage` wire message, which only contains light metadata of +a statement. The actual candidate data is not included. This message type is used whenever a message is deemed large. +The receiver of such a message needs to request the actual payload via request/response by means of a `StatementFetchingV1` request. -This is necessary as distribution of a large payload (mega bytes) via gossip -would make the network collapse and timely distribution of statements would no -longer be possible. By using request/response it is ensured that each peer only -transferes large data once. We only take good care to detect an overloaded -peer early and immediately move on to a different peer for fetching the data. -This mechanism should result in a good load distribution and therefore a rather +This is necessary as distribution of a large payload (mega bytes) via gossip would make the network collapse and timely +distribution of statements would no longer be possible. By using request/response it is ensured that each peer only +transferes large data once. We only take good care to detect an overloaded peer early and immediately move on to a +different peer for fetching the data. This mechanism should result in a good load distribution and therefore a rather optimal distribution path. -With these optimizations, distribution of payloads in the size of up to 3 to 4 -MB should work with Kusama validator specifications. For scaling up even more, -runtime upgrades and message passing should be done off chain at some point. +With these optimizations, distribution of payloads in the size of up to 3 to 4 MB should work with Kusama validator +specifications. For scaling up even more, runtime upgrades and message passing should be done off chain at some point. -Flood protection considerations: For making DoS attacks slightly harder on this -subsystem, nodes will only respond to large statement requests, when they -previously notified that peer via gossip about that statement. So, it is not -possible to DoS nodes at scale, by requesting candidate data over and over -again. +Flood protection considerations: For making DoS attacks slightly harder on this subsystem, nodes will only respond to +large statement requests, when they previously notified that peer via gossip about that statement. So, it is not +possible to DoS nodes at scale, by requesting candidate data over and over again. diff --git a/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md b/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md index 2e0142848210..24f2785f8294 100644 --- a/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md @@ -1,158 +1,127 @@ # Statement Distribution -This subsystem is responsible for distributing signed statements that we have generated and forwarding statements generated by our peers. Received candidate receipts and statements are passed to the [Candidate Backing subsystem](candidate-backing.md) to handle producing local statements. On receiving `StatementDistributionMessage::Share`, this subsystem distributes the message across the network with redundency to ensure a fast backing process. +This subsystem is responsible for distributing signed statements that we have generated and forwarding statements +generated by our peers. Received candidate receipts and statements are passed to the [Candidate Backing +subsystem](candidate-backing.md) to handle producing local statements. On receiving +`StatementDistributionMessage::Share`, this subsystem distributes the message across the network with redundency to +ensure a fast backing process. ## Overview -**Goal:** every well-connected node is aware of every next potential parachain -block. +**Goal:** every well-connected node is aware of every next potential parachain block. Validators can either: - receive parachain block from collator, check block, and gossip statement. -- receive statements from other validators, check the parachain block if it - originated within their own group, gossip forward statement if valid. - -Validators must have statements, candidates, and persisted validation from all -other validators. This is because we need to store statements from validators -who've checked the candidate on the relay chain, so we know who to hold -accountable in case of disputes. Any validator can be selected as the next -relay-chain block author, and this is not revealed in advance for security -reasons. As a result, all validators must have a up to date view of all possible -parachain candidates + backing statements that could be placed on-chain in the -next block. - -[This blog post](https://polkadot.network/blog/polkadot-v1-0-sharding-and-economic-security) -puts it another way: "Validators who aren't assigned to the parachain still -listen for the attestations [statements] because whichever validator ends up -being the author of the relay-chain block needs to bundle up attested parachain -blocks for several parachains and place them into the relay-chain block." - -Backing-group quorum (that is, enough backing group votes) must be reached -before the block author will consider the candidate. Therefore, validators need -to consider _all_ seconded candidates within their own group, because that's -what they're assigned to work on. Validators only need to consider _backable_ -candidates from other groups. This informs the design of the statement -distribution protocol to have separate phases for in-group and out-group -distribution, respectively called "cluster" and "grid" mode (see below). +- receive statements from other validators, check the parachain block if it originated within their own group, gossip + forward statement if valid. + +Validators must have statements, candidates, and persisted validation from all other validators. This is because we need +to store statements from validators who've checked the candidate on the relay chain, so we know who to hold accountable +in case of disputes. Any validator can be selected as the next relay-chain block author, and this is not revealed in +advance for security reasons. As a result, all validators must have a up to date view of all possible parachain +candidates + backing statements that could be placed on-chain in the next block. + +[This blog post](https://polkadot.network/blog/polkadot-v1-0-sharding-and-economic-security) puts it another way: +"Validators who aren't assigned to the parachain still listen for the attestations [statements] because whichever +validator ends up being the author of the relay-chain block needs to bundle up attested parachain blocks for several +parachains and place them into the relay-chain block." + +Backing-group quorum (that is, enough backing group votes) must be reached before the block author will consider the +candidate. Therefore, validators need to consider _all_ seconded candidates within their own group, because that's what +they're assigned to work on. Validators only need to consider _backable_ candidates from other groups. This informs the +design of the statement distribution protocol to have separate phases for in-group and out-group distribution, +respectively called "cluster" and "grid" mode (see below). ### With Async Backing -Asynchronous backing changes the runtime to accept parachain candidates from a -certain allowed range of historic relay-parents. These candidates must be backed -by the group assigned to the parachain as-of their corresponding relay parents. +Asynchronous backing changes the runtime to accept parachain candidates from a certain allowed range of historic +relay-parents. These candidates must be backed by the group assigned to the parachain as-of their corresponding relay +parents. ## Protocol -To address the concern of dealing with large numbers of spam candidates or -statements, the overall design approach is to combine a focused "clustering" -protocol for legitimate fresh candidates with a broad-distribution "grid" -protocol to quickly get backed candidates into the hands of many validators. -Validators do not eagerly send each other heavy `CommittedCandidateReceipt`, -but instead request these lazily through request/response protocols. +To address the concern of dealing with large numbers of spam candidates or statements, the overall design approach is to +combine a focused "clustering" protocol for legitimate fresh candidates with a broad-distribution "grid" protocol to +quickly get backed candidates into the hands of many validators. Validators do not eagerly send each other heavy +`CommittedCandidateReceipt`, but instead request these lazily through request/response protocols. A high-level description of the protocol follows: ### Messages -Nodes can send each other a few kinds of messages: `Statement`, -`BackedCandidateManifest`, `BackedCandidateAcknowledgement`. +Nodes can send each other a few kinds of messages: `Statement`, `BackedCandidateManifest`, +`BackedCandidateAcknowledgement`. -- `Statement` messages contain only a signed compact statement, without full - candidate info. -- `BackedCandidateManifest` messages advertise a description of a backed - candidate and stored statements. -- `BackedCandidateAcknowledgement` messages acknowledge that a backed candidate - is fully known. +- `Statement` messages contain only a signed compact statement, without full candidate info. +- `BackedCandidateManifest` messages advertise a description of a backed candidate and stored statements. +- `BackedCandidateAcknowledgement` messages acknowledge that a backed candidate is fully known. ### Request/response protocol -Nodes can request the full `CommittedCandidateReceipt` and -`PersistedValidationData`, along with statements, over a request/response -protocol. This is the `AttestedCandidateRequest`; the response is -`AttestedCandidateResponse`. +Nodes can request the full `CommittedCandidateReceipt` and `PersistedValidationData`, along with statements, over a +request/response protocol. This is the `AttestedCandidateRequest`; the response is `AttestedCandidateResponse`. ### Importability and the Hypothetical Frontier -The **prospective parachains** subsystem maintains prospective "fragment trees" -which can be used to determine whether a particular parachain candidate could -possibly be included in the future. Candidates which either are within a -fragment tree or _would be_ part of a fragment tree if accepted are said to be -in the "hypothetical frontier". +The **prospective parachains** subsystem maintains prospective "fragment trees" which can be used to determine whether a +particular parachain candidate could possibly be included in the future. Candidates which either are within a fragment +tree or _would be_ part of a fragment tree if accepted are said to be in the "hypothetical frontier". -The **statement-distribution** subsystem keeps track of all candidates, and -updates its knowledge of the hypothetical frontier based on events such as new -relay parents, new confirmed candidates, and newly backed candidates. +The **statement-distribution** subsystem keeps track of all candidates, and updates its knowledge of the hypothetical +frontier based on events such as new relay parents, new confirmed candidates, and newly backed candidates. -We only consider statements as "importable" when the corresponding candidate is -part of the hypothetical frontier, and only send "importable" statements to the -backing subsystem itself. +We only consider statements as "importable" when the corresponding candidate is part of the hypothetical frontier, and +only send "importable" statements to the backing subsystem itself. ### Cluster Mode -- Validator nodes are partitioned into groups (with some exceptions), and - validators within a group at a relay-parent can send each other `Statement` - messages for any candidates within that group and based on that relay-parent. +- Validator nodes are partitioned into groups (with some exceptions), and validators within a group at a relay-parent + can send each other `Statement` messages for any candidates within that group and based on that relay-parent. - This is referred to as the "cluster" mode. - - Right now these are the same as backing groups, though "cluster" - specifically refers to the set of nodes communicating with each other in the - first phase of distribution. + - Right now these are the same as backing groups, though "cluster" specifically refers to the set of nodes + communicating with each other in the first phase of distribution. - `Seconded` statements must be sent before `Valid` statements. -- `Seconded` statements may only be sent to other members of the group when the - candidate is fully known by the local validator. - - "Fully known" means the validator has the full `CommittedCandidateReceipt` - and `PersistedValidationData`, which it receives on request from other - validators or from a collator. - - The reason for this is that sending a statement (which is always a - `CompactStatement` carrying nothing but a hash and signature) to the - cluster, is also a signal that the sending node is available to request the - candidate from. - - This makes the protocol easier to reason about, while also reducing network - messages about candidates that don't really exist. -- Validators in a cluster receiving messages about unknown candidates request - the candidate (and statements) from other cluster members which have it. +- `Seconded` statements may only be sent to other members of the group when the candidate is fully known by the local + validator. + - "Fully known" means the validator has the full `CommittedCandidateReceipt` and `PersistedValidationData`, which it + receives on request from other validators or from a collator. + - The reason for this is that sending a statement (which is always a `CompactStatement` carrying nothing but a hash + and signature) to the cluster, is also a signal that the sending node is available to request the candidate from. + - This makes the protocol easier to reason about, while also reducing network messages about candidates that don't + really exist. +- Validators in a cluster receiving messages about unknown candidates request the candidate (and statements) from other + cluster members which have it. - Spam considerations - - The maximum depth of candidates allowed in asynchronous backing determines - the maximum amount of `Seconded` statements originating from a validator V - which each validator in a cluster may send to others. This bounds the number - of candidates. - - There is a small number of validators in each group, which further limits - the amount of candidates. -- We accept candidates which don't fit in the fragment trees of any relay - parents. - - "Accept" means "attempt to request and store in memory until useful or - expired". - - We listen to prospective parachains subsystem to learn of new additions to - the fragment trees. + - The maximum depth of candidates allowed in asynchronous backing determines the maximum amount of `Seconded` + statements originating from a validator V which each validator in a cluster may send to others. This bounds the + number of candidates. + - There is a small number of validators in each group, which further limits the amount of candidates. +- We accept candidates which don't fit in the fragment trees of any relay parents. + - "Accept" means "attempt to request and store in memory until useful or expired". + - We listen to prospective parachains subsystem to learn of new additions to the fragment trees. - Use this to attempt to import the candidate later. ### Grid Mode -- Every consensus session provides randomness and a fixed validator set, which - is used to build a redundant grid topology. - - It's redundant in the sense that there are 2 paths from every node to every - other node. See "Grid Topology" section for more details. -- This grid topology is used to create a sending path from each validator group - to every validator. -- When a node observes a candidate as backed, it sends a - `BackedCandidateManifest` to their "receiving" nodes. +- Every consensus session provides randomness and a fixed validator set, which is used to build a redundant grid + topology. + - It's redundant in the sense that there are 2 paths from every node to every other node. See "Grid Topology" section + for more details. +- This grid topology is used to create a sending path from each validator group to every validator. +- When a node observes a candidate as backed, it sends a `BackedCandidateManifest` to their "receiving" nodes. - If receiving nodes don't yet know the candidate, they request it. -- Once they know the candidate, they respond with a - `BackedCandidateAcknowledgement`. -- Once two nodes perform a manifest/acknowledgement exchange, they can send - `Statement` messages directly to each other for any new statements they might - need. - - This limits the amount of statements we'd have to deal with w.r.t. - candidates that don't really exist. See "Manifest Exchange" section. -- There are limitations on the number of candidates that can be advertised by - each peer, similar to those in the cluster. Validators do not request - candidates which exceed these limitations. -- Validators request candidates as soon as they are advertised, but do not - import the statements until the candidate is part of the hypothetical - frontier, and do not re-advertise or acknowledge until the candidate is - considered both backable and part of the hypothetical frontier. -- Note that requesting is not an implicit acknowledgement, and an explicit - acknowledgement must be sent upon receipt. +- Once they know the candidate, they respond with a `BackedCandidateAcknowledgement`. +- Once two nodes perform a manifest/acknowledgement exchange, they can send `Statement` messages directly to each other + for any new statements they might need. + - This limits the amount of statements we'd have to deal with w.r.t. candidates that don't really exist. See "Manifest + Exchange" section. +- There are limitations on the number of candidates that can be advertised by each peer, similar to those in the + cluster. Validators do not request candidates which exceed these limitations. +- Validators request candidates as soon as they are advertised, but do not import the statements until the candidate is + part of the hypothetical frontier, and do not re-advertise or acknowledge until the candidate is considered both + backable and part of the hypothetical frontier. +- Note that requesting is not an implicit acknowledgement, and an explicit acknowledgement must be sent upon receipt. ## Messages @@ -161,27 +130,23 @@ backing subsystem itself. - `ActiveLeaves` - Notification of a change in the set of active leaves. - `StatementDistributionMessage::Share` - - Notification of a locally-originating statement. That is, this statement - comes from our node and should be distributed to other nodes. - - Sent by the Backing Subsystem after it successfully imports a - locally-originating statement. + - Notification of a locally-originating statement. That is, this statement comes from our node and should be + distributed to other nodes. + - Sent by the Backing Subsystem after it successfully imports a locally-originating statement. - `StatementDistributionMessage::Backed` - - Notification of a candidate being backed (received enough validity votes - from the backing group). - - Sent by the Backing Subsystem after it successfully imports a statement for - the first time and after sending ~Share~. + - Notification of a candidate being backed (received enough validity votes from the backing group). + - Sent by the Backing Subsystem after it successfully imports a statement for the first time and after sending + ~Share~. - `StatementDistributionMessage::NetworkBridgeUpdate` - See next section. #### Network bridge events - v1 compatibility - - Messages for the v1 protocol are routed to the legacy statement - distribution. + - Messages for the v1 protocol are routed to the legacy statement distribution. - `Statement` - Notification of a signed statement. - - Sent by a peer's Statement Distribution subsystem when circulating - statements. + - Sent by a peer's Statement Distribution subsystem when circulating statements. - `BackedCandidateManifest` - Notification of a backed candidate being known by the sending node. - For the candidate being requested by the receiving node if needed. @@ -196,26 +161,23 @@ backing subsystem itself. ### Outgoing - `NetworkBridgeTxMessage::SendValidationMessages` - - Sends a peer all pending messages / acknowledgements / statements for a - relay parent, either through the cluster or the grid. + - Sends a peer all pending messages / acknowledgements / statements for a relay parent, either through the cluster or + the grid. - `NetworkBridgeTxMessage::SendValidationMessage` - - Circulates a compact statement to all peers who need it, either through the - cluster or the grid. + - Circulates a compact statement to all peers who need it, either through the cluster or the grid. - `NetworkBridgeTxMessage::ReportPeer` - Reports a peer (either good or bad). - `CandidateBackingMessage::Statement` - Note a validator's statement about a particular candidate. - `ProspectiveParachainsMessage::GetHypotheticalFrontier` - - Gets the hypothetical frontier membership of candidates under active leaves' - fragment trees. + - Gets the hypothetical frontier membership of candidates under active leaves' fragment trees. - `NetworkBridgeTxMessage::SendRequests` - Sends requests, initiating the request/response protocol. ## Request/Response -We also have a request/response protocol because validators do not eagerly send -each other heavy `CommittedCandidateReceipt`, but instead need to request these -lazily. +We also have a request/response protocol because validators do not eagerly send each other heavy +`CommittedCandidateReceipt`, but instead need to request these lazily. ### Protocol @@ -225,16 +187,13 @@ lazily. - Done as needed, when handling incoming manifests/statements. - `RequestManager::dispatch_requests` sends any queued-up requests. - Calls `RequestManager::next_request` to completion. - - Creates the `OutgoingRequest`, saves the receiver in - `RequestManager::pending_responses`. - - Does nothing if we have more responses pending than the limit of parallel - requests. + - Creates the `OutgoingRequest`, saves the receiver in `RequestManager::pending_responses`. + - Does nothing if we have more responses pending than the limit of parallel requests. 2. Peer - Requests come in on a peer on the `IncomingRequestReceiver`. - - Runs in a background responder task which feeds requests to `answer_request` - through `MuxedMessage`. + - Runs in a background responder task which feeds requests to `answer_request` through `MuxedMessage`. - This responder task has a limit on the number of parallel requests. - `answer_request` on the peer takes the request and sends a response. - Does this using the response sender on the request. @@ -243,8 +202,7 @@ lazily. - `receive_response` on the original validator yields a response. - Response was sent on the request's response sender. - - Uses `RequestManager::await_incoming` to await on pending responses in an - unordered fashion. + - Uses `RequestManager::await_incoming` to await on pending responses in an unordered fashion. - Runs on the `MuxedMessage` receiver. - `handle_response` handles the response. @@ -265,25 +223,23 @@ lazily. ## Manifests -A manifest is a message about a known backed candidate, along with a description -of the statements backing it. It can be one of two kinds: +A manifest is a message about a known backed candidate, along with a description of the statements backing it. It can be +one of two kinds: -- `Full`: Contains information about the candidate and should be sent to peers - who may not have the candidate yet. This is also called an `Announcement`. -- `Acknowledgement`: Omits information implicit in the candidate, and should be - sent to peers which are guaranteed to have the candidate already. +- `Full`: Contains information about the candidate and should be sent to peers who may not have the candidate yet. This + is also called an `Announcement`. +- `Acknowledgement`: Omits information implicit in the candidate, and should be sent to peers which are guaranteed to + have the candidate already. ### Manifest Exchange -Manifest exchange is when a receiving node received a `Full` manifest and -replied with an `Acknowledgement`. It indicates that both nodes know the -candidate as valid and backed. This allows the nodes to send `Statement` -messages directly to each other for any new statements. +Manifest exchange is when a receiving node received a `Full` manifest and replied with an `Acknowledgement`. It +indicates that both nodes know the candidate as valid and backed. This allows the nodes to send `Statement` messages +directly to each other for any new statements. -Why? This limits the amount of statements we'd have to deal with w.r.t. -candidates that don't really exist. Limiting out-of-group statement distribution -between peers to only candidates that both peers agree are backed and exist -ensures we only have to store statements about real candidates. +Why? This limits the amount of statements we'd have to deal with w.r.t. candidates that don't really exist. Limiting +out-of-group statement distribution between peers to only candidates that both peers agree are backed and exist ensures +we only have to store statements about real candidates. In practice, manifest exchange means that one of three things have happened: @@ -291,36 +247,31 @@ In practice, manifest exchange means that one of three things have happened: - We announced, they acknowledged. - We announced, they announced. -Concerning the last case, note that it is possible for two nodes to have each -other in their sending set. Consider: +Concerning the last case, note that it is possible for two nodes to have each other in their sending set. Consider: ``` 1 2 3 4 ``` -If validators 2 and 4 are in group B, then there is a path `2->1->3` and -`4->3->1`. Therefore, 1 and 3 might send each other manifests for the same -candidate at the same time, without having seen the other's yet. This also -counts as a manifest exchange, but is only allowed to occur in this way. +If validators 2 and 4 are in group B, then there is a path `2->1->3` and `4->3->1`. Therefore, 1 and 3 might send each +other manifests for the same candidate at the same time, without having seen the other's yet. This also counts as a +manifest exchange, but is only allowed to occur in this way. -After the exchange is complete, we update pending statements. Pending statements -are those we know locally that the remote node does not. +After the exchange is complete, we update pending statements. Pending statements are those we know locally that the +remote node does not. #### Alternative Paths Through The Topology -Nodes should send a `BackedCandidateAcknowledgement(CandidateHash, -StatementFilter)` notification to any peer which has sent a manifest, and the -candidate has been acquired by other means. This keeps alternative paths through -the topology open, which allows nodes to receive additional statements that come -later, but not after the candidate has been posted on-chain. +Nodes should send a `BackedCandidateAcknowledgement(CandidateHash, StatementFilter)` notification to any peer which has +sent a manifest, and the candidate has been acquired by other means. This keeps alternative paths through the topology +open, which allows nodes to receive additional statements that come later, but not after the candidate has been posted +on-chain. -This is mostly about the limitation that the runtime has no way for block -authors to post statements that come after the parablock is posted on-chain and -ensure those validators still get rewarded. Technically, we only need enough -statements to back the candidate and the manifest + request will provide that. -But more statements might come shortly afterwards, and we want those to end up -on-chain as well to ensure all validators in the group are rewarded. +This is mostly about the limitation that the runtime has no way for block authors to post statements that come after the +parablock is posted on-chain and ensure those validators still get rewarded. Technically, we only need enough statements +to back the candidate and the manifest + request will provide that. But more statements might come shortly afterwards, +and we want those to end up on-chain as well to ensure all validators in the group are rewarded. For clarity, here is the full timeline: @@ -333,52 +284,42 @@ For clarity, here is the full timeline: ## Cluster Module -The cluster module provides direct distribution of unbacked candidates within a -group. By utilizing this initial phase of propagating only within -clusters/groups, we bound the number of `Seconded` messages per validator per -relay-parent, helping us prevent spam. Validators can try to circumvent this, -but they would only consume a few KB of memory and it is trivially slashable on -chain. +The cluster module provides direct distribution of unbacked candidates within a group. By utilizing this initial phase +of propagating only within clusters/groups, we bound the number of `Seconded` messages per validator per relay-parent, +helping us prevent spam. Validators can try to circumvent this, but they would only consume a few KB of memory and it is +trivially slashable on chain. -The cluster module determines whether to accept/reject messages from other -validators in the same group. It keeps track of what we have sent to other -validators in the group, and pending statements. For the full protocol, see -"Protocol". +The cluster module determines whether to accept/reject messages from other validators in the same group. It keeps track +of what we have sent to other validators in the group, and pending statements. For the full protocol, see "Protocol". ## Grid Module -The grid module provides distribution of backed candidates and late statements -outside the backing group. For the full protocol, see the "Protocol" section. +The grid module provides distribution of backed candidates and late statements outside the backing group. For the full +protocol, see the "Protocol" section. ### Grid Topology -For distributing outside our cluster (aka backing group) we use a 2D grid -topology. This limits the amount of peers we send messages to, and handles -view updates. +For distributing outside our cluster (aka backing group) we use a 2D grid topology. This limits the amount of peers we +send messages to, and handles view updates. The basic operation of the grid topology is that: -- A validator producing a message sends it to its row-neighbors and its - column-neighbors. -- A validator receiving a message originating from one of its row-neighbors - sends it to its column-neighbors. -- A validator receiving a message originating from one of its column-neighbors - sends it to its row-neighbors. +- A validator producing a message sends it to its row-neighbors and its column-neighbors. +- A validator receiving a message originating from one of its row-neighbors sends it to its column-neighbors. +- A validator receiving a message originating from one of its column-neighbors sends it to its row-neighbors. -This grid approach defines 2 unique paths for every validator to reach every -other validator in at most 2 hops, providing redundancy. +This grid approach defines 2 unique paths for every validator to reach every other validator in at most 2 hops, +providing redundancy. Propagation follows these rules: -- Each node has a receiving set and a sending set. These are different for each - group. That is, if a node receives a candidate from group A, it checks if it - is allowed to receive from that node for candidates from group A. +- Each node has a receiving set and a sending set. These are different for each group. That is, if a node receives a + candidate from group A, it checks if it is allowed to receive from that node for candidates from group A. - For groups that we are in, receive from nobody and send to our X/Y peers. - For groups that we are not part of: - - We receive from any validator in the group we share a slice with and send to - the corresponding X/Y slice in the other dimension. - - For any validators we don't share a slice with, we receive from the nodes - which share a slice with them. + - We receive from any validator in the group we share a slice with and send to the corresponding X/Y slice in the + other dimension. + - For any validators we don't share a slice with, we receive from the nodes which share a slice with them. ### Example @@ -391,81 +332,63 @@ For size 11, the matrix would be: 9 10 ``` -e.g. for index 10, the neighbors would be 1, 4, 7, 9 -- these are the nodes we -could directly communicate with (e.g. either send to or receive from). - -Now, which of these neighbors can 10 receive from? Recall that the -sending/receiving sets for 10 would be different for different groups. Here are -some hypothetical scenarios: - -- **Scenario 1:** 9 belongs to group A but not 10. Here, 10 can directly receive - candidates from group A from 9. 10 would propagate them to the nodes in {1, 4, - 7} that are not in A. -- **Scenario 2:** 6 is in group A instead of 9, and 7 is not in group A. 10 can - receive group A messages from 7 or 9. 10 will try to relay these messages, but - 7 and 9 together should have already propagated the message to all x/y - peers of 10. If so, then 10 will just receive acknowledgements in reply rather - than requests. -- **Scenario 3:** 10 itself is in group A. 10 would not receive candidates from - this group from any other nodes through the grid. It would itself send such - candidates to all its neighbors that are not in A. +e.g. for index 10, the neighbors would be 1, 4, 7, 9 -- these are the nodes we could directly communicate with (e.g. +either send to or receive from). + +Now, which of these neighbors can 10 receive from? Recall that the sending/receiving sets for 10 would be different for +different groups. Here are some hypothetical scenarios: + +- **Scenario 1:** 9 belongs to group A but not 10. Here, 10 can directly receive candidates from group A from 9. 10 + would propagate them to the nodes in {1, 4, 7} that are not in A. +- **Scenario 2:** 6 is in group A instead of 9, and 7 is not in group A. 10 can receive group A messages from 7 or 9. 10 + will try to relay these messages, but 7 and 9 together should have already propagated the message to all x/y peers of + 10. If so, then 10 will just receive acknowledgements in reply rather than requests. +- **Scenario 3:** 10 itself is in group A. 10 would not receive candidates from this group from any other nodes through + the grid. It would itself send such candidates to all its neighbors that are not in A. ### Seconding Limit -The seconding limit is a per-validator limit. Before asynchronous backing, we -had a rule that every validator was only allowed to second one candidate per -relay parent. With asynchronous backing, we have a 'maximum depth' which makes -it possible to second multiple candidates per relay parent. The seconding limit -is set to `max depth + 1` to set an upper bound on candidates entering the -system. +The seconding limit is a per-validator limit. Before asynchronous backing, we had a rule that every validator was only +allowed to second one candidate per relay parent. With asynchronous backing, we have a 'maximum depth' which makes it +possible to second multiple candidates per relay parent. The seconding limit is set to `max depth + 1` to set an upper +bound on candidates entering the system. ## Candidates Module -The candidates module provides a tracker for all known candidates in the view, -whether they are confirmed or not, and how peers have advertised the candidates. -What is a confirmed candidate? It is a candidate for which we have the full -receipt and the persisted validation data. This module gets confirmed candidates -from two sources: +The candidates module provides a tracker for all known candidates in the view, whether they are confirmed or not, and +how peers have advertised the candidates. What is a confirmed candidate? It is a candidate for which we have the full +receipt and the persisted validation data. This module gets confirmed candidates from two sources: -- It can be that a validator fetched a collation directly from the collator and - validated it. -- The first time a validator gets an announcement for an unknown candidate, it - will send a request for the candidate. Upon receiving a response and - validating it (see `UnhandledResponse::validate_response`), it will mark the - candidate as confirmed. +- It can be that a validator fetched a collation directly from the collator and validated it. +- The first time a validator gets an announcement for an unknown candidate, it will send a request for the candidate. + Upon receiving a response and validating it (see `UnhandledResponse::validate_response`), it will mark the candidate + as confirmed. ## Requests Module -The requests module provides a manager for pending requests for candidate data, -as well as pending responses. See "Request/Response Protocol" for a high-level -description of the flow. See module-docs for full details. +The requests module provides a manager for pending requests for candidate data, as well as pending responses. See +"Request/Response Protocol" for a high-level description of the flow. See module-docs for full details. ## Glossary -- **Acknowledgement:** A partial manifest sent to a validator that already has the - candidate to inform them that the sending node also knows the candidate. - Concludes a manifest exchange. -- **Announcement:** A full manifest indicating that a backed candidate is known by - the sending node. Initiates a manifest exchange. +- **Acknowledgement:** A partial manifest sent to a validator that already has the candidate to inform them that the + sending node also knows the candidate. Concludes a manifest exchange. +- **Announcement:** A full manifest indicating that a backed candidate is known by the sending node. Initiates a + manifest exchange. - **Attestation:** See "Statement". - **Backable vs. Backed:** - - Note that we sometimes use "backed" to refer to candidates that are - "backable", but not yet backed on chain. - - **Backed** should technically mean that the parablock candidate and its - backing statements have been added to a relay chain block. - - **Backable** is when the necessary backing statements have been acquired but - those statements and the parablock candidate haven't been backed in a relay - chain block yet. -- **Fragment tree:** A parachain fragment not referenced by the relay-chain. - It is a tree of prospective parachain blocks. -- **Manifest:** A message about a known backed candidate, along with a - description of the statements backing it. There are two kinds of manifest, - `Acknowledgement` and `Announcement`. See "Manifests" section. + - Note that we sometimes use "backed" to refer to candidates that are "backable", but not yet backed on chain. + - **Backed** should technically mean that the parablock candidate and its backing statements have been added to a + relay chain block. + - **Backable** is when the necessary backing statements have been acquired but those statements and the parablock + candidate haven't been backed in a relay chain block yet. +- **Fragment tree:** A parachain fragment not referenced by the relay-chain. It is a tree of prospective parachain + blocks. +- **Manifest:** A message about a known backed candidate, along with a description of the statements backing it. There + are two kinds of manifest, `Acknowledgement` and `Announcement`. See "Manifests" section. - **Peer:** Another validator that a validator is connected to. -- **Request/response:** A protocol used to lazily request and receive heavy - candidate data when needed. -- **Reputation:** Tracks reputation of peers. Applies annoyance cost and good - behavior benefits. +- **Request/response:** A protocol used to lazily request and receive heavy candidate data when needed. +- **Reputation:** Tracks reputation of peers. Applies annoyance cost and good behavior benefits. - **Statement:** Signed statements that can be made about parachain candidates. - **Seconded:** Proposal of a parachain candidate. Implicit validity vote. - **Valid:** States that a parachain candidate is valid. @@ -474,6 +397,5 @@ description of the flow. See module-docs for full details. - **Explicit view** / **immediate view** - The view a peer has of the relay chain heads and highest finalized block. - **Implicit view** - - Derived from the immediate view. Composed of active leaves and minimum - relay-parents allowed for candidates of various parachains at those - leaves. + - Derived from the immediate view. Composed of active leaves and minimum relay-parents allowed for candidates of + various parachains at those leaves. diff --git a/polkadot/roadmap/implementers-guide/src/node/collators/README.md b/polkadot/roadmap/implementers-guide/src/node/collators/README.md index 3642e415efab..09edd0c119f3 100644 --- a/polkadot/roadmap/implementers-guide/src/node/collators/README.md +++ b/polkadot/roadmap/implementers-guide/src/node/collators/README.md @@ -1,6 +1,8 @@ # Collators -Collators are special nodes which bridge a parachain to the relay chain. They are simultaneously full nodes of the parachain, and at least light clients of the relay chain. Their overall contribution to the system is the generation of Proofs of Validity for parachain candidates. +Collators are special nodes which bridge a parachain to the relay chain. They are simultaneously full nodes of the +parachain, and at least light clients of the relay chain. Their overall contribution to the system is the generation of +Proofs of Validity for parachain candidates. -The **Collation Generation** subsystem triggers collators to produce collations -and then forwards them to **Collator Protocol** to circulate to validators. +The **Collation Generation** subsystem triggers collators to produce collations and then forwards them to **Collator +Protocol** to circulate to validators. diff --git a/polkadot/roadmap/implementers-guide/src/node/collators/collation-generation.md b/polkadot/roadmap/implementers-guide/src/node/collators/collation-generation.md index 9053ea40f89e..05148357f753 100644 --- a/polkadot/roadmap/implementers-guide/src/node/collators/collation-generation.md +++ b/polkadot/roadmap/implementers-guide/src/node/collators/collation-generation.md @@ -1,17 +1,18 @@ # Collation Generation -The collation generation subsystem is executed on collator nodes and produces candidates to be distributed to validators. If configured to produce collations for a para, it produces collations and then feeds them to the [Collator Protocol][CP] subsystem, which handles the networking. +The collation generation subsystem is executed on collator nodes and produces candidates to be distributed to +validators. If configured to produce collations for a para, it produces collations and then feeds them to the [Collator +Protocol][CP] subsystem, which handles the networking. ## Protocol Collation generation for Parachains currently works in the following way: -1. A new relay chain block is imported. -2. The collation generation subsystem checks if the core associated to - the parachain is free and if yes, continues. -3. Collation generation calls our collator callback, if present, to generate a PoV. If none exists, do nothing. -4. Authoring logic determines if the current node should build a PoV. -5. Build new PoV and give it back to collation generation. +1. A new relay chain block is imported. +2. The collation generation subsystem checks if the core associated to the parachain is free and if yes, continues. +3. Collation generation calls our collator callback, if present, to generate a PoV. If none exists, do nothing. +4. Authoring logic determines if the current node should build a PoV. +5. Build new PoV and give it back to collation generation. ## Messages @@ -22,8 +23,7 @@ Collation generation for Parachains currently works in the following way: - Triggers collation generation procedure outlined in "Protocol" section. - `CollationGenerationMessage::Initialize` - Initializes the subsystem. Carries a config. - - No more than one initialization message should ever be sent to the collation - generation subsystem. + - No more than one initialization message should ever be sent to the collation generation subsystem. - Sent by a collator to initialize this subsystem. - `CollationGenerationMessage::SubmitCollation` - If the subsystem isn't initialized or the relay-parent is too old to be relevant, ignore the message. @@ -37,7 +37,9 @@ Collation generation for Parachains currently works in the following way: ## Functionality -The process of generating a collation for a parachain is very parachain-specific. As such, the details of how to do so are left beyond the scope of this description. The subsystem should be implemented as an abstract wrapper, which is aware of this configuration: +The process of generating a collation for a parachain is very parachain-specific. As such, the details of how to do so +are left beyond the scope of this description. The subsystem should be implemented as an abstract wrapper, which is +aware of this configuration: ```rust /// The output of a collator. @@ -117,30 +119,24 @@ The configuration should be optional, to allow for the case where the node is no - **Collation (output of a collator)** - - Contains the PoV (proof to verify the state transition of the - parachain) and other data. + - Contains the PoV (proof to verify the state transition of the parachain) and other data. - **Collation result** - - Contains the collation, and an optional result sender for a - collation-seconded signal. + - Contains the collation, and an optional result sender for a collation-seconded signal. - **Collation seconded signal** - - The signal that is returned when a collation was seconded by a - validator. + - The signal that is returned when a collation was seconded by a validator. - **Collation function** - - Called with the relay chain block the parablock will be built on top - of. + - Called with the relay chain block the parablock will be built on top of. - Called with the validation data. - - Provides information about the state of the parachain on the relay - chain. + - Provides information about the state of the parachain on the relay chain. - **Collation generation config** - - Contains collator's authentication key, optional collator function, and - parachain ID. + - Contains collator's authentication key, optional collator function, and parachain ID. [CP]: collator-protocol.md diff --git a/polkadot/roadmap/implementers-guide/src/node/collators/collator-protocol.md b/polkadot/roadmap/implementers-guide/src/node/collators/collator-protocol.md index 09265a534847..1fed671170c7 100644 --- a/polkadot/roadmap/implementers-guide/src/node/collators/collator-protocol.md +++ b/polkadot/roadmap/implementers-guide/src/node/collators/collator-protocol.md @@ -1,16 +1,25 @@ # Collator Protocol -The Collator Protocol implements the network protocol by which collators and validators communicate. It is used by collators to distribute collations to validators and used by validators to accept collations by collators. +The Collator Protocol implements the network protocol by which collators and validators communicate. It is used by +collators to distribute collations to validators and used by validators to accept collations by collators. -Collator-to-Validator networking is more difficult than Validator-to-Validator networking because the set of possible collators for any given para is unbounded, unlike the validator set. Validator-to-Validator networking protocols can easily be implemented as gossip because the data can be bounded, and validators can authenticate each other by their `PeerId`s for the purposes of instantiating and accepting connections. +Collator-to-Validator networking is more difficult than Validator-to-Validator networking because the set of possible +collators for any given para is unbounded, unlike the validator set. Validator-to-Validator networking protocols can +easily be implemented as gossip because the data can be bounded, and validators can authenticate each other by their +`PeerId`s for the purposes of instantiating and accepting connections. -Since, at least at the level of the para abstraction, the collator-set for any given para is unbounded, validators need to make sure that they are receiving connections from capable and honest collators and that their bandwidth and time are not being wasted by attackers. Communicating across this trust-boundary is the most difficult part of this subsystem. +Since, at least at the level of the para abstraction, the collator-set for any given para is unbounded, validators need +to make sure that they are receiving connections from capable and honest collators and that their bandwidth and time are +not being wasted by attackers. Communicating across this trust-boundary is the most difficult part of this subsystem. -Validation of candidates is a heavy task, and furthermore, the [`PoV`][PoV] itself is a large piece of data. Empirically, `PoV`s are on the order of 10MB. +Validation of candidates is a heavy task, and furthermore, the [`PoV`][PoV] itself is a large piece of data. +Empirically, `PoV`s are on the order of 10MB. > TODO: note the incremental validation function Ximin proposes at https://github.com/paritytech/polkadot/issues/1348 -As this network protocol serves as a bridge between collators and validators, it communicates primarily with one subsystem on behalf of each. As a collator, this will receive messages from the [`CollationGeneration`][CG] subsystem. As a validator, this will communicate only with the [`CandidateBacking`][CB]. +As this network protocol serves as a bridge between collators and validators, it communicates primarily with one +subsystem on behalf of each. As a collator, this will receive messages from the [`CollationGeneration`][CG] subsystem. +As a validator, this will communicate only with the [`CandidateBacking`][CB]. ## Protocol @@ -18,9 +27,9 @@ Input: [`CollatorProtocolMessage`][CPM] Output: -- [`RuntimeApiMessage`][RAM] -- [`NetworkBridgeMessage`][NBM] -- [`CandidateBackingMessage`][CBM] +* [`RuntimeApiMessage`][RAM] +* [`NetworkBridgeMessage`][NBM] +* [`CandidateBackingMessage`][CBM] ## Functionality @@ -28,7 +37,8 @@ This network protocol uses the `Collation` peer-set of the [`NetworkBridge`][NB] It uses the [`CollatorProtocolV1Message`](../../types/network.md#collator-protocol) as its `WireMessage` -Since this protocol functions both for validators and collators, it is easiest to go through the protocol actions for each of them separately. +Since this protocol functions both for validators and collators, it is easiest to go through the protocol actions for +each of them separately. Validators and collators. ```dot process @@ -47,24 +57,44 @@ digraph { ### Collators -It is assumed that collators are only collating on a single parachain. Collations are generated by the [Collation Generation][CG] subsystem. We will keep up to one local collation per relay-parent, based on `DistributeCollation` messages. If the para is not scheduled on any core, at the relay-parent, or the relay-parent isn't in the active-leaves set, we ignore the message as it must be invalid in that case - although this indicates a logic error elsewhere in the node. +It is assumed that collators are only collating on a single parachain. Collations are generated by the [Collation +Generation][CG] subsystem. We will keep up to one local collation per relay-parent, based on `DistributeCollation` +messages. If the para is not scheduled on any core, at the relay-parent, or the relay-parent isn't in the active-leaves +set, we ignore the message as it must be invalid in that case - although this indicates a logic error elsewhere in the +node. -We keep track of the Para ID we are collating on as a collator. This starts as `None`, and is updated with each `CollateOn` message received. If the `ParaId` of a collation requested to be distributed does not match the one we expect, we ignore the message. +We keep track of the Para ID we are collating on as a collator. This starts as `None`, and is updated with each +`CollateOn` message received. If the `ParaId` of a collation requested to be distributed does not match the one we +expect, we ignore the message. As with most other subsystems, we track the active leaves set by following `ActiveLeavesUpdate` signals. -For the purposes of actually distributing a collation, we need to be connected to the validators who are interested in collations on that `ParaId` at this point in time. We assume that there is a discovery API for connecting to a set of validators. +For the purposes of actually distributing a collation, we need to be connected to the validators who are interested in +collations on that `ParaId` at this point in time. We assume that there is a discovery API for connecting to a set of +validators. -As seen in the [Scheduler Module][SCH] of the runtime, validator groups are fixed for an entire session and their rotations across cores are predictable. Collators will want to do these things when attempting to distribute collations at a given relay-parent: +As seen in the [Scheduler Module][SCH] of the runtime, validator groups are fixed for an entire session and their +rotations across cores are predictable. Collators will want to do these things when attempting to distribute collations +at a given relay-parent: * Determine which core the para collated-on is assigned to. * Determine the group on that core. - * Issue a discovery request for the validators of the current group with[`NetworkBridgeMessage`][NBM]`::ConnectToValidators`. - -Once connected to the relevant peers for the current group assigned to the core (transitively, the para), advertise the collation to any of them which advertise the relay-parent in their view (as provided by the [Network Bridge][NB]). If any respond with a request for the full collation, provide it. However, we only send one collation at a time per relay parent, other requests need to wait. This is done to reduce the bandwidth requirements of a collator and also increases the chance to fully send the collation to at least one validator. From the point where one validator has received the collation and seconded it, it will also start to share this collation with other validators in its backing group. Upon receiving a view update from any of these peers which includes a relay-parent for which we have a collation that they will find relevant, advertise the collation to them if we haven't already. + * Issue a discovery request for the validators of the current group + with[`NetworkBridgeMessage`][NBM]`::ConnectToValidators`. + +Once connected to the relevant peers for the current group assigned to the core (transitively, the para), advertise the +collation to any of them which advertise the relay-parent in their view (as provided by the [Network Bridge][NB]). If +any respond with a request for the full collation, provide it. However, we only send one collation at a time per relay +parent, other requests need to wait. This is done to reduce the bandwidth requirements of a collator and also increases +the chance to fully send the collation to at least one validator. From the point where one validator has received the +collation and seconded it, it will also start to share this collation with other validators in its backing group. Upon +receiving a view update from any of these peers which includes a relay-parent for which we have a collation that they +will find relevant, advertise the collation to them if we haven't already. ### Validators -On the validator side of the protocol, validators need to accept incoming connections from collators. They should keep some peer slots open for accepting new speculative connections from collators and should disconnect from collators who are not relevant. +On the validator side of the protocol, validators need to accept incoming connections from collators. They should keep +some peer slots open for accepting new speculative connections from collators and should disconnect from collators who +are not relevant. ```dot process digraph G { @@ -98,32 +128,62 @@ digraph G { } ``` -When peers connect to us, they can `Declare` that they represent a collator with given public key and intend to collate on a specific para ID. Once they've declared that, and we checked their signature, they can begin to send advertisements of collations. The peers should not send us any advertisements for collations that are on a relay-parent outside of our view or for a para outside of the one they've declared. +When peers connect to us, they can `Declare` that they represent a collator with given public key and intend to collate +on a specific para ID. Once they've declared that, and we checked their signature, they can begin to send advertisements +of collations. The peers should not send us any advertisements for collations that are on a relay-parent outside of our +view or for a para outside of the one they've declared. -The protocol tracks advertisements received and the source of the advertisement. The advertisement source is the `PeerId` of the peer who sent the message. We accept one advertisement per collator per source per relay-parent. +The protocol tracks advertisements received and the source of the advertisement. The advertisement source is the +`PeerId` of the peer who sent the message. We accept one advertisement per collator per source per relay-parent. -As a validator, we will handle requests from other subsystems to fetch a collation on a specific `ParaId` and relay-parent. These requests are made with the request response protocol `CollationFetchingRequest` request. To do so, we need to first check if we have already gathered a collation on that `ParaId` and relay-parent. If not, we need to select one of the advertisements and issue a request for it. If we've already issued a request, we shouldn't issue another one until the first has returned. +As a validator, we will handle requests from other subsystems to fetch a collation on a specific `ParaId` and +relay-parent. These requests are made with the request response protocol `CollationFetchingRequest` request. To do so, +we need to first check if we have already gathered a collation on that `ParaId` and relay-parent. If not, we need to +select one of the advertisements and issue a request for it. If we've already issued a request, we shouldn't issue +another one until the first has returned. -When acting on an advertisement, we issue a `Requests::CollationFetchingV1`. However, we only request one collation at a time per relay parent. This reduces the bandwidth requirements and as we can second only one candidate per relay parent, the others are probably not required anyway. If the request times out, we need to note the collator as being unreliable and reduce its priority relative to other collators. +When acting on an advertisement, we issue a `Requests::CollationFetchingV1`. However, we only request one collation at a +time per relay parent. This reduces the bandwidth requirements and as we can second only one candidate per relay parent, +the others are probably not required anyway. If the request times out, we need to note the collator as being unreliable +and reduce its priority relative to other collators. -As a validator, once the collation has been fetched some other subsystem will inspect and do deeper validation of the collation. The subsystem will report to this subsystem with a [`CollatorProtocolMessage`][CPM]`::ReportCollator`. In that case, if we are connected directly to the collator, we apply a cost to the `PeerId` associated with the collator and potentially disconnect or blacklist it. If the collation is seconded, we notify the collator and apply a benefit to the `PeerId` associated with the collator. +As a validator, once the collation has been fetched some other subsystem will inspect and do deeper validation of the +collation. The subsystem will report to this subsystem with a [`CollatorProtocolMessage`][CPM]`::ReportCollator`. In +that case, if we are connected directly to the collator, we apply a cost to the `PeerId` associated with the collator +and potentially disconnect or blacklist it. If the collation is seconded, we notify the collator and apply a benefit to +the `PeerId` associated with the collator. ### Interaction with [Candidate Backing][CB] -As collators advertise the availability, a validator will simply second the first valid parablock candidate per relay head by sending a [`CandidateBackingMessage`][CBM]`::Second`. Note that this message contains the relay parent of the advertised collation, the candidate receipt and the [PoV][PoV]. +As collators advertise the availability, a validator will simply second the first valid parablock candidate per relay +head by sending a [`CandidateBackingMessage`][CBM]`::Second`. Note that this message contains the relay parent of the +advertised collation, the candidate receipt and the [PoV][PoV]. -Subsequently, once a valid parablock candidate has been seconded, the [`CandidateBacking`][CB] subsystem will send a [`CollatorProtocolMessage`][CPM]`::Seconded`, which will trigger this subsystem to notify the collator at the `PeerId` that first advertised the parablock on the seconded relay head of their successful seconding. +Subsequently, once a valid parablock candidate has been seconded, the [`CandidateBacking`][CB] subsystem will send a +[`CollatorProtocolMessage`][CPM]`::Seconded`, which will trigger this subsystem to notify the collator at the `PeerId` +that first advertised the parablock on the seconded relay head of their successful seconding. ## Future Work Several approaches have been discussed, but all have some issues: -- The current approach is very straightforward. However, that protocol is vulnerable to a single collator which, as an attack or simply through chance, gets its block candidate to the node more often than its fair share of the time. -- If collators produce blocks via Aura, BABE or in future Sassafras, it may be possible to choose an "Official" collator for the round, but it may be tricky to ensure that the PVF logic is enforced at collator leader election. -- We could use relay-chain BABE randomness to generate some delay `D` on the order of 1 second, +- 1 second. The collator would then second the first valid parablock which arrives after `D`, or in case none has arrived by `2*D`, the last valid parablock which has arrived. This makes it very hard for a collator to game the system to always get its block nominated, but it reduces the maximum throughput of the system by introducing delay into an already tight schedule. -- A variation of that scheme would be to have a fixed acceptance window `D` for parablock candidates and keep track of count `C`: the number of parablock candidates received. At the end of the period `D`, we choose a random number I in the range `[0, C)` and second the block at Index I. Its drawback is the same: it must wait the full `D` period before seconding any of its received candidates, reducing throughput. -- In order to protect against DoS attacks, it may be prudent to run throw out collations from collators that have behaved poorly (whether recently or historically) and subsequently only verify the PoV for the most suitable of collations. +* The current approach is very straightforward. However, that protocol is vulnerable to a single collator which, as an + attack or simply through chance, gets its block candidate to the node more often than its fair share of the time. +* If collators produce blocks via Aura, BABE or in future Sassafras, it may be possible to choose an "Official" collator + for the round, but it may be tricky to ensure that the PVF logic is enforced at collator leader election. +* We could use relay-chain BABE randomness to generate some delay `D` on the order of 1 second, +* 1 second. The + collator would then second the first valid parablock which arrives after `D`, or in case none has arrived by `2*D`, + the last valid parablock which has arrived. This makes it very hard for a collator to game the system to always get + its block nominated, but it reduces the maximum throughput of the system by introducing delay into an already tight + schedule. +* A variation of that scheme would be to have a fixed acceptance window `D` for parablock candidates and keep track of + count `C`: the number of parablock candidates received. At the end of the period `D`, we choose a random number I in + the range `[0, C)` and second the block at Index I. Its drawback is the same: it must wait the full `D` period before + seconding any of its received candidates, reducing throughput. +* In order to protect against DoS attacks, it may be prudent to run throw out collations from collators that have + behaved poorly (whether recently or historically) and subsequently only verify the PoV for the most suitable of + collations. [CB]: ../backing/candidate-backing.md [CBM]: ../../types/overseer-protocol.md#candidate-backing-mesage diff --git a/polkadot/roadmap/implementers-guide/src/node/disputes/README.md b/polkadot/roadmap/implementers-guide/src/node/disputes/README.md index a6e126b1534b..36f497114a73 100644 --- a/polkadot/roadmap/implementers-guide/src/node/disputes/README.md +++ b/polkadot/roadmap/implementers-guide/src/node/disputes/README.md @@ -4,12 +4,12 @@ If approval voting finds an invalid candidate, a dispute is raised. The disputes subsystems are concerned with the following: 1. Disputes can be raised -2. Disputes (votes) get propagated to all other validators -3. Votes get recorded as necessary -3. Nodes will participate in disputes in a sensible fashion -4. Finality is stopped while a candidate is being disputed on chain -5. Chains can be reverted in case a dispute concludes invalid -6. Votes are provided to the provisioner for importing on chain, in order for +1. Disputes (votes) get propagated to all other validators +1. Votes get recorded as necessary +1. Nodes will participate in disputes in a sensible fashion +1. Finality is stopped while a candidate is being disputed on chain +1. Chains can be reverted in case a dispute concludes invalid +1. Votes are provided to the provisioner for importing on chain, in order for slashing to work. The dispute-coordinator subsystem interfaces with the provisioner and chain diff --git a/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md b/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md index f8bfe6506aa5..daba416e2639 100644 --- a/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md +++ b/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md @@ -1,86 +1,64 @@ # Dispute Coordinator -The coordinator is the central subsystem of the node-side components which -participate in disputes. It wraps a database, which is used to track statements -observed by _all_ validators over some window of sessions. Votes older than this +The coordinator is the central subsystem of the node-side components which participate in disputes. It wraps a database, +which is used to track statements observed by _all_ validators over some window of sessions. Votes older than this session window are pruned. In particular the dispute-coordinator is responsible for: -- Ensuring that the node is able to raise a dispute in case an invalid candidate - is found during approval checking. -- Ensuring that backing and approval votes will be recorded on chain. With these - votes on chain we can be certain that appropriate targets for slashing will be - available for concluded disputes. Also, scraping these votes during a dispute +- Ensuring that the node is able to raise a dispute in case an invalid candidate is found during approval checking. +- Ensuring that backing and approval votes will be recorded on chain. With these votes on chain we can be certain that + appropriate targets for slashing will be available for concluded disputes. Also, scraping these votes during a dispute is necessary for critical spam prevention measures. - Ensuring backing votes will never get overridden by explicit votes. -- Coordinating actual participation in a dispute, ensuring that the node - participates in any justified dispute in a way that ensures resolution of - disputes on the network even in the case of many disputes raised (flood/DoS - scenario). -- Ensuring disputes resolve, even for candidates on abandoned forks as much as - reasonably possible, to rule out "free tries" and thus guarantee our gambler's - ruin property. -- Providing an API for chain selection, so we can prevent finalization of any - chain which has included candidates for which a dispute is either ongoing or - concluded invalid and avoid building on chains with an included invalid +- Coordinating actual participation in a dispute, ensuring that the node participates in any justified dispute in a way + that ensures resolution of disputes on the network even in the case of many disputes raised (flood/DoS scenario). +- Ensuring disputes resolve, even for candidates on abandoned forks as much as reasonably possible, to rule out "free + tries" and thus guarantee our gambler's ruin property. +- Providing an API for chain selection, so we can prevent finalization of any chain which has included candidates for + which a dispute is either ongoing or concluded invalid and avoid building on chains with an included invalid candidate. -- Providing an API for retrieving (resolved) disputes, including all votes, both - implicit (approval, backing) and explicit dispute votes. So validators can get - rewarded/slashed accordingly. +- Providing an API for retrieving (resolved) disputes, including all votes, both implicit (approval, backing) and + explicit dispute votes. So validators can get rewarded/slashed accordingly. ## Ensuring That Disputes Can Be Raised -If a candidate turns out invalid in approval checking, the `approval-voting` -subsystem will try to issue a dispute. For this, it will send a message -`DisputeCoordinatorMessage::IssueLocalStatement` to the dispute coordinator, -indicating to cast an explicit invalid vote. It is the responsibility of the -dispute coordinator on reception of such a message to create and sign that -explicit invalid vote and trigger a dispute if none for that candidate is -already ongoing. - -In order to raise a dispute, a node has to be able to provide two opposing votes. -Given that the reason of the backing phase is to have validators with skin in -the game, the opposing valid vote will very likely be a backing vote. It could -also be some already cast approval vote, but the significant point here is: As -long as we have backing votes available, any node will be able to raise a -dispute. - -Therefore a vital responsibility of the dispute coordinator is to make sure -backing votes are available for all candidates that might still get disputed. To -accomplish this task in an efficient way the dispute-coordinator relies on chain -scraping. Whenever a candidate gets backed on chain, we record in chain storage -the backing votes imported in that block. This way, given the chain state for a -given relay chain block, we can retrieve via a provided runtime API the backing -votes imported by that block. The dispute coordinator makes sure to query those -votes for any non finalized blocks: In case of missed blocks, it will do chain -traversal as necessary. +If a candidate turns out invalid in approval checking, the `approval-voting` subsystem will try to issue a dispute. For +this, it will send a message `DisputeCoordinatorMessage::IssueLocalStatement` to the dispute coordinator, indicating to +cast an explicit invalid vote. It is the responsibility of the dispute coordinator on reception of such a message to +create and sign that explicit invalid vote and trigger a dispute if none for that candidate is already ongoing. + +In order to raise a dispute, a node has to be able to provide two opposing votes. Given that the reason of the backing +phase is to have validators with skin in the game, the opposing valid vote will very likely be a backing vote. It could +also be some already cast approval vote, but the significant point here is: As long as we have backing votes available, +any node will be able to raise a dispute. + +Therefore a vital responsibility of the dispute coordinator is to make sure backing votes are available for all +candidates that might still get disputed. To accomplish this task in an efficient way the dispute-coordinator relies on +chain scraping. Whenever a candidate gets backed on chain, we record in chain storage the backing votes imported in that +block. This way, given the chain state for a given relay chain block, we can retrieve via a provided runtime API the +backing votes imported by that block. The dispute coordinator makes sure to query those votes for any non finalized +blocks: In case of missed blocks, it will do chain traversal as necessary. Relying on chain scraping is very efficient for two reasons: -1. Votes are already batched. We import all available backing votes for a - candidate all at once. If instead we imported votes from candidate-backing as - they came along, we would import each vote individually which is - inefficient in the current dispute coordinator implementation (quadratic - complexity). -2. We also import less votes in total, as we avoid importing statements for - candidates that never got successfully backed on any chain. - -It also is secure, because disputes are only ever raised in the approval voting -phase. A node only starts the approval process after it has seen a candidate -included on some chain, for that to happen it must have been backed previously. -Therefore backing votes are available at that point in time. Signals are -processed first, so even if a block is skipped and we only start importing -backing votes on the including block, we will have seen the backing votes by the -time we process messages from approval voting. - -In summary, for making it possible for a dispute to be raised, recording of -backing votes from chain is sufficient and efficient. In particular there is no -need to preemptively import approval votes, which has shown to be a very +1. Votes are already batched. We import all available backing votes for a candidate all at once. If instead we imported + votes from candidate-backing as they came along, we would import each vote individually which is inefficient in the + current dispute coordinator implementation (quadratic complexity). +2. We also import less votes in total, as we avoid importing statements for candidates that never got successfully + backed on any chain. + +It also is secure, because disputes are only ever raised in the approval voting phase. A node only starts the approval +process after it has seen a candidate included on some chain, for that to happen it must have been backed previously. +Therefore backing votes are available at that point in time. Signals are processed first, so even if a block is skipped +and we only start importing backing votes on the including block, we will have seen the backing votes by the time we +process messages from approval voting. + +In summary, for making it possible for a dispute to be raised, recording of backing votes from chain is sufficient and +efficient. In particular there is no need to preemptively import approval votes, which has shown to be a very inefficient process. (Quadratic complexity adds up, with 35 votes in total per candidate) -Approval votes are very relevant nonetheless as we are going to see in the next -section. +Approval votes are very relevant nonetheless as we are going to see in the next section. ## Ensuring approval votes will be recorded @@ -88,521 +66,402 @@ section. Only votes recorded by the dispute coordinator will be considered for slashing. -While there is no need to record approval votes in the dispute coordinator -preemptively, we make some effort to have any in approval-voting received -approval votes recorded when a dispute actually happens: - -This is not required for concluding the dispute, as nodes send their own vote -anyway (either explicit valid or their existing approval-vote). What nodes can -do though, is participating in approval-voting, casting a vote, but later when a -dispute is raised reconsider their vote and send an explicit invalid vote. If -they managed to only have that one recorded, then they could avoid a slash. - -This is not a problem for our basic security assumptions: The backers are the -ones to be supposed to have skin in the game, so we are not too woried about -colluding approval voters getting away slash free as the gambler's ruin property -is maintained anyway. There is however a separate problem, from colluding -approval-voters, that is "lazy" approval voters. If it were easy and reliable -for approval-voters to reconsider their vote, in case of an actual dispute, then -they don't have a direct incentive (apart from playing a part in securing the -network) to properly run the validation function at all - they could just always -vote "valid" totally risk free. (While they would alwasy risk a slash by voting -invalid.) - - -So we do want to fetch approval votes from approval-voting. Importing votes is -most efficient when batched. At the same time approval voting and disputes are -running concurrently so approval votes are expected to trickle in still, when a +While there is no need to record approval votes in the dispute coordinator preemptively, we make some effort to have any +in approval-voting received approval votes recorded when a dispute actually happens: + +This is not required for concluding the dispute, as nodes send their own vote anyway (either explicit valid or their +existing approval-vote). What nodes can do though, is participating in approval-voting, casting a vote, but later when a +dispute is raised reconsider their vote and send an explicit invalid vote. If they managed to only have that one +recorded, then they could avoid a slash. + +This is not a problem for our basic security assumptions: The backers are the ones to be supposed to have skin in the +game, so we are not too woried about colluding approval voters getting away slash free as the gambler's ruin property is +maintained anyway. There is however a separate problem, from colluding approval-voters, that is "lazy" approval voters. +If it were easy and reliable for approval-voters to reconsider their vote, in case of an actual dispute, then they don't +have a direct incentive (apart from playing a part in securing the network) to properly run the validation function at +all - they could just always vote "valid" totally risk free. (While they would alwasy risk a slash by voting invalid.) + + +So we do want to fetch approval votes from approval-voting. Importing votes is most efficient when batched. At the same +time approval voting and disputes are running concurrently so approval votes are expected to trickle in still, when a dispute is already ongoing. Hence, we have the following requirements for importing approval votes: -1. Only import them when there is a dispute, because otherwise we are - wasting lots of resources _always_ for the exceptional case of a dispute. +1. Only import them when there is a dispute, because otherwise we are wasting lots of resources _always_ for the + exceptional case of a dispute. 2. Import votes batched when possible, to avoid quadratic import complexity. -3. Take into account that approval voting is still ongoing, while a dispute is - already running. - -With a design where approval voting sends votes to the dispute-coordinator by -itself, we would need to make approval voting aware of ongoing disputes and once -it is aware it could start sending all already existing votes batched and -trickling in votes as they come. The problem with this is, that it adds some -unnecessary complexity to approval-voting and also we might still import most of -the votes unbatched one-by-one, depending on what point in time the dispute was +3. Take into account that approval voting is still ongoing, while a dispute is already running. + +With a design where approval voting sends votes to the dispute-coordinator by itself, we would need to make approval +voting aware of ongoing disputes and once it is aware it could start sending all already existing votes batched and +trickling in votes as they come. The problem with this is, that it adds some unnecessary complexity to approval-voting +and also we might still import most of the votes unbatched one-by-one, depending on what point in time the dispute was raised. -Instead of the dispute coordinator informing approval-voting of an ongoing -dispute for it to begin forwarding votes to the dispute coordinator, it makes -more sense for the dispute-coordinator to just ask approval-voting for votes of -candidates in dispute. This way, the dispute coordinator can also pick the best -time for maximizing the number of votes in the batch. - -Now the question remains, when should the dispute coordinator ask -approval-voting for votes? - -In fact for slashing it is only relevant to have them once the dispute -concluded, so we can query approval voting the moment the dispute concludes! -Two concerns that come to mind, are easily addressed: - -1. Timing: We would like to rely as little as possible on implementation details - of approval voting. In particular, if the dispute is ongoing for a long time, - do we have any guarantees that approval votes are kept around long enough by - approval voting? Will approval votes still be present by the time the - dispute concludes in all cases? The answer is nuanced, but in general we - cannot rely on it. The problem is first, that finalization and - approval-voting is an off-chain process so there is no global consensus: As - soon as at least f+1 honest (f=n/3, where n is the number of - validators/nodes) nodes have seen the dispute conclude, finalization will - take place and approval votes will be cleared. This would still be fine, if - we had some guarantees that those honest nodes will be able to include those - votes in a block. This guarantee does not exist unfortunately, we will - discuss the problem and solutions in more detail [below][#Ensuring Chain Import]. - - The second problem is that approval-voting will abandon votes as soon as a - chain can no longer be finalized (some other/better fork already has been). - This second problem can somehow be mitigated by also importing votes as soon - as a dispute is detected, but not fully resolved. It is still inherently - racy. The good thing is, this should be good enough: We are worried about - lazy approval checkers, the system does not need to be perfect. It should be - enough if there is some risk of getting caught. -2. We are not worried about the dispute not concluding, as nodes will always - send their own vote, regardless of it being an explict or an already existing - approval-vote. - -Conclusion: As long as we make sure, if our own approval vote gets imported -(which would prevent dispute participation) to also distribute it via -dispute-distribution, disputes can conclude. To mitigate raciness with -approval-voting deleting votes we will import approval votes twice during a -dispute: Once when it is raised, to make as sure as possible to see approval -votes also for abandoned forks and second when the dispute concludes, to -maximize the amount of potentially malicious approval votes to be recorded. The -raciness obviously is not fully resolved by this, but this is fine as argued -above. +Instead of the dispute coordinator informing approval-voting of an ongoing dispute for it to begin forwarding votes to +the dispute coordinator, it makes more sense for the dispute-coordinator to just ask approval-voting for votes of +candidates in dispute. This way, the dispute coordinator can also pick the best time for maximizing the number of votes +in the batch. + +Now the question remains, when should the dispute coordinator ask approval-voting for votes? + +In fact for slashing it is only relevant to have them once the dispute concluded, so we can query approval voting the +moment the dispute concludes! Two concerns that come to mind, are easily addressed: + +1. Timing: We would like to rely as little as possible on implementation details of approval voting. In particular, if + the dispute is ongoing for a long time, do we have any guarantees that approval votes are kept around long enough by + approval voting? Will approval votes still be present by the time the dispute concludes in all cases? The answer is + nuanced, but in general we cannot rely on it. The problem is first, that finalization and approval-voting is an + off-chain process so there is no global consensus: As soon as at least f+1 honest (f=n/3, where n is the number of + validators/nodes) nodes have seen the dispute conclude, finalization will take place and approval votes will be + cleared. This would still be fine, if we had some guarantees that those honest nodes will be able to include those + votes in a block. This guarantee does not exist unfortunately, we will discuss the problem and solutions in more + detail [below][#Ensuring Chain Import]. + + The second problem is that approval-voting will abandon votes as soon as a chain can no longer be finalized (some + other/better fork already has been). This second problem can somehow be mitigated by also importing votes as soon as + a dispute is detected, but not fully resolved. It is still inherently racy. The good thing is, this should be good + enough: We are worried about lazy approval checkers, the system does not need to be perfect. It should be enough if + there is some risk of getting caught. +2. We are not worried about the dispute not concluding, as nodes will always send their own vote, regardless of it being + an explict or an already existing approval-vote. + +Conclusion: As long as we make sure, if our own approval vote gets imported (which would prevent dispute participation) +to also distribute it via dispute-distribution, disputes can conclude. To mitigate raciness with approval-voting +deleting votes we will import approval votes twice during a dispute: Once when it is raised, to make as sure as possible +to see approval votes also for abandoned forks and second when the dispute concludes, to maximize the amount of +potentially malicious approval votes to be recorded. The raciness obviously is not fully resolved by this, but this is +fine as argued above. Ensuring vote import on chain is covered in the next section. -What we don't care about is that honest approval-voters will likely validate -twice, once in approval voting and once via dispute-participation. Avoiding that -does not really seem worthwhile though, as disputes are for one exceptional, so -a little wasted effort won't affect everyday performance - second, even with -eager importing of approval votes, those doubled work is still present as -disputes and approvals are racing. Every time participation is faster than -approval, a node would do double work. +What we don't care about is that honest approval-voters will likely validate twice, once in approval voting and once via +dispute-participation. Avoiding that does not really seem worthwhile though, as disputes are for one exceptional, so a +little wasted effort won't affect everyday performance - second, even with eager importing of approval votes, those +doubled work is still present as disputes and approvals are racing. Every time participation is faster than approval, a +node would do double work. ### Ensuring Chain Import -While in the previous section we discussed means for nodes to ensure relevant -votes are recorded so lazy approval checkers get slashed properly, it is crucial -to also discuss the actual chain import. Only if we guarantee that recorded votes -will get imported on chain (on all potential chains really) we will succeed -in executing slashes. Particularly we need to make sure backing votes end up on -chain consistently. - -Dispute distribution will make sure all explicit dispute votes get distributed -among nodes which includes current block producers (current authority set) which -is an important property: If the dispute carries on across an era change, we -need to ensure that the new validator set will learn about any disputes and -their votes, so they can put that information on chain. Dispute-distribution -luckily has this property and always sends votes to the current authority set. -The issue is, for dispute-distribution, nodes send only their own explicit (or -in some cases their approval vote) in addition to some opposing vote. This -guarantees that at least some backing or approval vote will be present at the -block producer, but we don't have a 100% guarantee to have votes for all -backers, even less for approval checkers. - -Reason for backing votes: While backing votes will be present on at least some -chain, that does not mean that any such chain is still considered for block -production in the current set - they might only exist on an already abandoned -fork. This means a block producer that just joined the set, might not have seen -any of them. - -For approvals it is even more tricky and less necessary: Approval voting together -with finalization is a completely off-chain process therefore those protocols -don't care about block production at all. Approval votes only have a guarantee of -being propagated between the nodes that are responsible for finalizing the -concerned blocks. This implies that on an era change the current authority set, -will not necessarily get informed about any approval votes for the previous era. -Hence even if all validators of the previous era successfully recorded all approval -votes in the dispute coordinator, they won't get a chance to put them on chain, -hence they won't be considered for slashing. - -It is important to note, that the essential properties of the system still hold: -Dispute-distribution will distribute at _least one_ "valid" vote to the current -authority set, hence at least one node will get slashed in case of outcome -"invalid". Also in reality the validator set is rarely exchanged 100%, therefore -in practice some validators in the current authority set will overlap with the -ones in the previous set and will be able to record votes on chain. - -Still, for maximum accountability we need to make sure a previous authority set -can communicate votes to the next one, regardless of any chain: This is yet to -be implemented see section "Resiliency" in dispute-distribution and +While in the previous section we discussed means for nodes to ensure relevant votes are recorded so lazy approval +checkers get slashed properly, it is crucial to also discuss the actual chain import. Only if we guarantee that recorded +votes will get imported on chain (on all potential chains really) we will succeed in executing slashes. Particularly we +need to make sure backing votes end up on chain consistently. + +Dispute distribution will make sure all explicit dispute votes get distributed among nodes which includes current block +producers (current authority set) which is an important property: If the dispute carries on across an era change, we +need to ensure that the new validator set will learn about any disputes and their votes, so they can put that +information on chain. Dispute-distribution luckily has this property and always sends votes to the current authority +set. The issue is, for dispute-distribution, nodes send only their own explicit (or in some cases their approval vote) +in addition to some opposing vote. This guarantees that at least some backing or approval vote will be present at the +block producer, but we don't have a 100% guarantee to have votes for all backers, even less for approval checkers. + +Reason for backing votes: While backing votes will be present on at least some chain, that does not mean that any such +chain is still considered for block production in the current set - they might only exist on an already abandoned fork. +This means a block producer that just joined the set, might not have seen any of them. + +For approvals it is even more tricky and less necessary: Approval voting together with finalization is a completely +off-chain process therefore those protocols don't care about block production at all. Approval votes only have a +guarantee of being propagated between the nodes that are responsible for finalizing the concerned blocks. This implies +that on an era change the current authority set, will not necessarily get informed about any approval votes for the +previous era. Hence even if all validators of the previous era successfully recorded all approval votes in the dispute +coordinator, they won't get a chance to put them on chain, hence they won't be considered for slashing. + +It is important to note, that the essential properties of the system still hold: Dispute-distribution will distribute at +_least one_ "valid" vote to the current authority set, hence at least one node will get slashed in case of outcome +"invalid". Also in reality the validator set is rarely exchanged 100%, therefore in practice some validators in the +current authority set will overlap with the ones in the previous set and will be able to record votes on chain. + +Still, for maximum accountability we need to make sure a previous authority set can communicate votes to the next one, +regardless of any chain: This is yet to be implemented see section "Resiliency" in dispute-distribution and [this](https://github.com/paritytech/polkadot/issues/3398) ticket. ## Coordinating Actual Dispute Participation -Once the dispute coordinator learns about a dispute, it is its responsibility to -make sure the local node participates in that dispute. +Once the dispute coordinator learns about a dispute, it is its responsibility to make sure the local node participates +in that dispute. -The dispute coordinator learns about a dispute by importing votes from either -chain scraping or from dispute-distribution. If it finds opposing votes (always -the case when coming from dispute-distribution), it records the presence of a -dispute. Then, in case it does not find any local vote for that dispute already, -it needs to trigger participation in the dispute (see previous section for -considerations when the found local vote is an approval vote). +The dispute coordinator learns about a dispute by importing votes from either chain scraping or from +dispute-distribution. If it finds opposing votes (always the case when coming from dispute-distribution), it records the +presence of a dispute. Then, in case it does not find any local vote for that dispute already, it needs to trigger +participation in the dispute (see previous section for considerations when the found local vote is an approval vote). -Participation means, recovering availability and re-evaluating the POV. The -result of that validation (either valid or invalid) will be the node's vote on -that dispute: Either explicit "invalid" or "valid". The dispute coordinator will -inform `dispute-distribution` about our vote and `dispute-distribution` will make -sure that our vote gets distributed to all other validators. +Participation means, recovering availability and re-evaluating the POV. The result of that validation (either valid or +invalid) will be the node's vote on that dispute: Either explicit "invalid" or "valid". The dispute coordinator will +inform `dispute-distribution` about our vote and `dispute-distribution` will make sure that our vote gets distributed to +all other validators. -Nothing ever is that easy though. We can not blindly import anything that comes -along and trigger participation no matter what. +Nothing ever is that easy though. We can not blindly import anything that comes along and trigger participation no +matter what. ### Spam Considerations -In Polkadot's security model, it is important that attempts to attack the system -result in a slash of the offenders. Therefore we need to make sure that this -slash is actually happening. Attackers could try to prevent the slashing from -taking place, by overwhelming validators with disputes in such a way that no -single dispute ever concludes, because nodes are busy processing newly incoming -ones. Other attacks are imaginable as well, like raising disputes for candidates -that don't exist, just filling up everyone's disk slowly or worse making nodes -try to participate, which will result in lots of network requests for recovering -availability. - -The last point brings up a significant consideration in general: Disputes are -about escalation: Every node will suddenly want to check, instead of only a few. -A single message will trigger the whole network to start significant amount of -work and will cause lots of network traffic and messages. Hence the -dispute system is very susceptible to being a brutal amplifier for DoS attacks, -resulting in DoS attacks to become very easy and cheap, if we are not careful. - -One counter measure we are taking is making raising of disputes a costly thing: -If you raise a dispute, because you claim a candidate is invalid, although it is -in fact valid - you will get slashed, hence you pay for consuming those -resources. The issue is: This only works if the dispute concerns a candidate -that actually exists! - -If a node raises a dispute for a candidate that never got included (became -available) on any chain, then the dispute can never conclude, hence nobody gets -slashed. It makes sense to point out that this is less bad than it might sound -at first, as trying to participate in a dispute for a non existing candidate is -"relatively" cheap. Each node will send out a few hundred tiny request messages -for availability chunks, which all will end up in a tiny response "NoSuchChunk" -and then no participation will actually happen as there is nothing to -participate. Malicious nodes could provide chunks, which would make things more -costly, but at the full expense of the attackers bandwidth - no amplification -here. I am bringing that up for completeness only: Triggering a thousand nodes -to send out a thousand tiny network messages by just sending out a single -garbage message, is still a significant amplification and is nothing to ignore - -this could absolutely be used to cause harm! +In Polkadot's security model, it is important that attempts to attack the system result in a slash of the offenders. +Therefore we need to make sure that this slash is actually happening. Attackers could try to prevent the slashing from +taking place, by overwhelming validators with disputes in such a way that no single dispute ever concludes, because +nodes are busy processing newly incoming ones. Other attacks are imaginable as well, like raising disputes for +candidates that don't exist, just filling up everyone's disk slowly or worse making nodes try to participate, which will +result in lots of network requests for recovering availability. + +The last point brings up a significant consideration in general: Disputes are about escalation: Every node will suddenly +want to check, instead of only a few. A single message will trigger the whole network to start significant amount of +work and will cause lots of network traffic and messages. Hence the dispute system is very susceptible to being a brutal +amplifier for DoS attacks, resulting in DoS attacks to become very easy and cheap, if we are not careful. + +One counter measure we are taking is making raising of disputes a costly thing: If you raise a dispute, because you +claim a candidate is invalid, although it is in fact valid - you will get slashed, hence you pay for consuming those +resources. The issue is: This only works if the dispute concerns a candidate that actually exists! + +If a node raises a dispute for a candidate that never got included (became available) on any chain, then the dispute can +never conclude, hence nobody gets slashed. It makes sense to point out that this is less bad than it might sound at +first, as trying to participate in a dispute for a non existing candidate is "relatively" cheap. Each node will send out +a few hundred tiny request messages for availability chunks, which all will end up in a tiny response "NoSuchChunk" and +then no participation will actually happen as there is nothing to participate. Malicious nodes could provide chunks, +which would make things more costly, but at the full expense of the attackers bandwidth - no amplification here. I am +bringing that up for completeness only: Triggering a thousand nodes to send out a thousand tiny network messages by just +sending out a single garbage message, is still a significant amplification and is nothing to ignore - this could +absolutely be used to cause harm! ### Participation -As explained, just blindly participating in any "dispute" that comes along is -not a good idea. First we would like to make sure the dispute is actually -genuine, to prevent cheap DoS attacks. Secondly, in case of genuine disputes, we -would like to conclude one after the other, in contrast to -processing all at the same time, slowing down progress on all of them, bringing -individual processing to a complete halt in the worst case (nodes get overwhelmed -at some stage in the pipeline). - -To ensure to only spend significant work on genuine disputes, we only trigger -participation at all on any _vote import_ if any of the following holds true: - -- We saw the disputed candidate included in some not yet finalized block on at - least one fork of the chain. -- We have seen the disputed candidate backed in some not yet finalized block on - at least one fork of the chain. This ensures the candidate is at least not - completely made up and there has been some effort already flown into that - candidate. Generally speaking a dispute shouldn't be raised for a candidate - which is backed but is not yet included. Disputes are raised during approval - checking. We participate on such disputes as a precaution - maybe we haven't - seen the `CandidateIncluded` event yet? -- The dispute is already confirmed: Meaning that 1/3+1 nodes already - participated, as this suggests in our threat model that there was at least one - honest node that already voted, so the dispute must be genuine. - -Note: A node might be out of sync with the chain and we might only learn about a -block, including a candidate, after we learned about the dispute. This means, we -have to re-evaluate participation decisions on block import! - -With this, nodes won't waste significant resources on completely made up -candidates. The next step is to process dispute participation in a (globally) -ordered fashion. Meaning a majority of validators should arrive at at least -roughly at the same ordering of participation, for disputes to get resolved one -after another. This order is only relevant if there are lots of disputes, so we -obviously only need to worry about order if participations start queuing up. - -We treat participation for candidates that we have seen included with priority -and put them on a priority queue which sorts participation based on the block -number of the relay parent of the candidate and for candidates with the same -relay parent height further by the `CandidateHash`. This ordering is globally -unique and also prioritizes older candidates. - -The latter property makes sense, because if an older candidate turns out invalid, -we can roll back the full chain at once. If we resolved earlier disputes first -and they turned out invalid as well, we might need to roll back a couple of -times instead of just once to the oldest offender. This is obviously a good -idea, in particular it makes it impossible for an attacker to prevent rolling -back a very old candidate, by keeping raising disputes for newer candidates. - -For candidates we have not seen included, but we know are backed (thanks to -chain scraping) or we have seen a dispute with 1/3+1 participation (confirmed -dispute) on them - we put participation on a best-effort queue. It has got the -same ordering as the priority one - by block heights of the relay parent, older -blocks are with priority. There is a possibility not to be able to obtain the -block number of the parent when we are inserting the dispute in the queue. To -account for races, we will promote any existing participation request to the -priority queue once we learn about an including block. NOTE: this is still work -in progress and is tracked by [this +As explained, just blindly participating in any "dispute" that comes along is not a good idea. First we would like to +make sure the dispute is actually genuine, to prevent cheap DoS attacks. Secondly, in case of genuine disputes, we would +like to conclude one after the other, in contrast to processing all at the same time, slowing down progress on all of +them, bringing individual processing to a complete halt in the worst case (nodes get overwhelmed at some stage in the +pipeline). + +To ensure to only spend significant work on genuine disputes, we only trigger participation at all on any _vote import_ +if any of the following holds true: + +- We saw the disputed candidate included in some not yet finalized block on at least one fork of the chain. +- We have seen the disputed candidate backed in some not yet finalized block on at least one fork of the chain. This + ensures the candidate is at least not completely made up and there has been some effort already flown into that + candidate. Generally speaking a dispute shouldn't be raised for a candidate which is backed but is not yet included. + Disputes are raised during approval checking. We participate on such disputes as a precaution - maybe we haven't seen + the `CandidateIncluded` event yet? +- The dispute is already confirmed: Meaning that 1/3+1 nodes already participated, as this suggests in our threat model + that there was at least one honest node that already voted, so the dispute must be genuine. + +Note: A node might be out of sync with the chain and we might only learn about a block, including a candidate, after we +learned about the dispute. This means, we have to re-evaluate participation decisions on block import! + +With this, nodes won't waste significant resources on completely made up candidates. The next step is to process dispute +participation in a (globally) ordered fashion. Meaning a majority of validators should arrive at at least roughly at the +same ordering of participation, for disputes to get resolved one after another. This order is only relevant if there are +lots of disputes, so we obviously only need to worry about order if participations start queuing up. + +We treat participation for candidates that we have seen included with priority and put them on a priority queue which +sorts participation based on the block number of the relay parent of the candidate and for candidates with the same +relay parent height further by the `CandidateHash`. This ordering is globally unique and also prioritizes older +candidates. + +The latter property makes sense, because if an older candidate turns out invalid, we can roll back the full chain at +once. If we resolved earlier disputes first and they turned out invalid as well, we might need to roll back a couple of +times instead of just once to the oldest offender. This is obviously a good idea, in particular it makes it impossible +for an attacker to prevent rolling back a very old candidate, by keeping raising disputes for newer candidates. + +For candidates we have not seen included, but we know are backed (thanks to chain scraping) or we have seen a dispute +with 1/3+1 participation (confirmed dispute) on them - we put participation on a best-effort queue. It has got the same +ordering as the priority one - by block heights of the relay parent, older blocks are with priority. There is a +possibility not to be able to obtain the block number of the parent when we are inserting the dispute in the queue. To +account for races, we will promote any existing participation request to the priority queue once we learn about an +including block. NOTE: this is still work in progress and is tracked by [this issue](https://github.com/paritytech/polkadot/issues/5875). ### Abandoned Forks -Finalization: As mentioned we care about included and backed candidates on any -non-finalized chain, given that any disputed chain will not get finalized, we -don't need to care about finalized blocks, but what about forks that fall behind -the finalized chain in terms of block number? For those we would still like to -be able to participate in any raised disputes, otherwise attackers might be able -to avoid a slash if they manage to create a better fork after they learned about -the approval checkers. Therefore we do care about those forks even after they -have fallen behind the finalized chain. - -For simplicity we also care about the actual finalized chain (not just forks) up -to a certain depth. We do have to limit the depth, because otherwise we open a -DoS vector again. The depth (into the finalized chain) should be oriented on the -approval-voting execution timeout, in particular it should be significantly -larger. Otherwise by the time the execution is allowed to finish, we already -dropped information about those candidates and the dispute could not conclude. +Finalization: As mentioned we care about included and backed candidates on any non-finalized chain, given that any +disputed chain will not get finalized, we don't need to care about finalized blocks, but what about forks that fall +behind the finalized chain in terms of block number? For those we would still like to be able to participate in any +raised disputes, otherwise attackers might be able to avoid a slash if they manage to create a better fork after they +learned about the approval checkers. Therefore we do care about those forks even after they have fallen behind the +finalized chain. + +For simplicity we also care about the actual finalized chain (not just forks) up to a certain depth. We do have to limit +the depth, because otherwise we open a DoS vector again. The depth (into the finalized chain) should be oriented on the +approval-voting execution timeout, in particular it should be significantly larger. Otherwise by the time the execution +is allowed to finish, we already dropped information about those candidates and the dispute could not conclude. ## Import ### Spam Considerations -In the last section we looked at how to treat queuing participations to -handle heavy dispute load well. This already ensures, that honest nodes won't -amplify cheap DoS attacks. There is one minor issue remaining: Even if we delay -participation until we have some confirmation of the authenticity of the -dispute, we should also not blindly import all votes arriving into the database -as this might be used to just slowly fill up disk space, until the node is no -longer functional. This leads to our last protection mechanism at the dispute -coordinator level (dispute-distribution also has its own), which is spam slots. -For each import containing an invalid vote, where we don't know whether it might -be spam or not we increment a counter for each signing participant of explicit -`invalid` votes. - -What votes do we treat as a potential spam? A vote will increase a spam slot if -and only if all of the following conditions are satisfied: - -* the candidate under dispute was not seen included nor backed on any chain -* the dispute is not confirmed -* we haven't cast a vote for the dispute - -Whenever any vote on a dispute is imported these conditions are checked. If the -dispute is found not to be potential spam, then spam slots for the disputed candidate hash are cleared. This decrements the spam count for every validator +In the last section we looked at how to treat queuing participations to handle heavy dispute load well. This already +ensures, that honest nodes won't amplify cheap DoS attacks. There is one minor issue remaining: Even if we delay +participation until we have some confirmation of the authenticity of the dispute, we should also not blindly import all +votes arriving into the database as this might be used to just slowly fill up disk space, until the node is no longer +functional. This leads to our last protection mechanism at the dispute coordinator level (dispute-distribution also has +its own), which is spam slots. For each import containing an invalid vote, where we don't know whether it might be spam +or not we increment a counter for each signing participant of explicit `invalid` votes. + +What votes do we treat as a potential spam? A vote will increase a spam slot if and only if all of the following +conditions are satisfied: + +- the candidate under dispute was not seen included nor backed on any chain +- the dispute is not confirmed +- we haven't cast a vote for the dispute + +Whenever any vote on a dispute is imported these conditions are checked. If the dispute is found not to be potential +spam, then spam slots for the disputed candidate hash are cleared. This decrements the spam count for every validator which had voted invalid. -To keep spam slots from filling up unnecessarily we want to clear spam slots -whenever a candidate is seen to be backed or included. Fortunately this behavior -is acheived by clearing slots on vote import as described above. Because on chain -backing votes are processed when a block backing the disputed candidate is discovered, spam slots are cleared for every backed candidate. Included -candidates have also been seen as backed on the same fork, so decrementing spam -slots is handled in that case as well. - -The reason this works is because we only need to worry about actual dispute -votes. Import of backing votes are already rate limited and concern only real -candidates. For approval votes a similar argument holds (if they come from -approval-voting), but we also don't import them until a dispute already -concluded. For actual dispute votes we need two opposing votes, so there must be -an explicit `invalid` vote in the import. Only a third of the validators can be -malicious, so spam disk usage is limited to `2*vote_size*n/3*NUM_SPAM_SLOTS`, with -`n` being the number of validators. +To keep spam slots from filling up unnecessarily we want to clear spam slots whenever a candidate is seen to be backed +or included. Fortunately this behavior is acheived by clearing slots on vote import as described above. Because on chain +backing votes are processed when a block backing the disputed candidate is discovered, spam slots are cleared for every +backed candidate. Included candidates have also been seen as backed on the same fork, so decrementing spam slots is +handled in that case as well. + +The reason this works is because we only need to worry about actual dispute votes. Import of backing votes are already +rate limited and concern only real candidates. For approval votes a similar argument holds (if they come from +approval-voting), but we also don't import them until a dispute already concluded. For actual dispute votes we need two +opposing votes, so there must be an explicit `invalid` vote in the import. Only a third of the validators can be +malicious, so spam disk usage is limited to `2*vote_size*n/3*NUM_SPAM_SLOTS`, with `n` being the number of validators. ### Backing Votes -Backing votes are in some way special. For starters they are the only valid -votes that are guaranteed to exist for any valid dispute to be raised. Second -they are the only votes that commit to a shorter execution timeout -`BACKING_EXECUTION_TIMEOUT`, compared to a more lenient timeout used in approval -voting. To account properly for execution time variance across machines, -slashing might treat backing votes differently (more aggressively) than other -voting `valid` votes. Hence in import we shall never override a backing vote -with another valid vote. They can not be assumed to be interchangeable. +Backing votes are in some way special. For starters they are the only valid votes that are guaranteed to exist for any +valid dispute to be raised. Second they are the only votes that commit to a shorter execution timeout +`BACKING_EXECUTION_TIMEOUT`, compared to a more lenient timeout used in approval voting. To account properly for +execution time variance across machines, slashing might treat backing votes differently (more aggressively) than other +voting `valid` votes. Hence in import we shall never override a backing vote with another valid vote. They can not be +assumed to be interchangeable. ## Attacks & Considerations -The following attacks on the priority queue and best-effort queues are -considered in above design. +The following attacks on the priority queue and best-effort queues are considered in above design. ### Priority Queue -On the priority queue, we will only queue participations for candidates we have -seen included on any chain. Any attack attempt would start with a candidate -included on some chain, but an attacker could try to only reveal the including -relay chain blocks to just some honest validators and stop as soon as it learns -that some honest validator would have a relevant approval assignment. +On the priority queue, we will only queue participations for candidates we have seen included on any chain. Any attack +attempt would start with a candidate included on some chain, but an attacker could try to only reveal the including +relay chain blocks to just some honest validators and stop as soon as it learns that some honest validator would have a +relevant approval assignment. -Without revealing the including block to any honest validator, we don't really -have an attack yet. Once the block is revealed though, the above is actually -very hard. Each honest validator will re-distribute the block it just learned -about. This means an attacker would need to pull of a targeted DoS attack, which -allows the validator to send its assignment, but prevents it from forwarding and -sharing the relay chain block. +Without revealing the including block to any honest validator, we don't really have an attack yet. Once the block is +revealed though, the above is actually very hard. Each honest validator will re-distribute the block it just learned +about. This means an attacker would need to pull of a targeted DoS attack, which allows the validator to send its +assignment, but prevents it from forwarding and sharing the relay chain block. -This sounds already hard enough, provided that we also start participation if -we learned about an including block after the dispute has been raised already -(we need to update participation queues on new leaves), but to be even safer -we choose to have an additional best-effort queue. +This sounds already hard enough, provided that we also start participation if we learned about an including block after +the dispute has been raised already (we need to update participation queues on new leaves), but to be even safer we +choose to have an additional best-effort queue. ### Best-Effort Queue -While attacking the priority queue is already pretty hard, attacking the -best-effort queue is even harder. For a candidate to be a threat, it has to be -included on some chain. For it to be included, it has to have been backed before -and at least n/3 honest nodes must have seen that block, so availability -(inclusion) can be reached. Making a full third of the nodes not further -propagate a block, while at the same time allowing them to fetch chunks, sign -and distribute bitfields seems almost infeasible and even if accomplished, those -nodes would be enough to confirm a dispute and we have not even touched the -above fact that in addition, for an attack, the following including block must -be shared with honest validators as well. - -It is worth mentioning that a successful attack on the priority queue as -outlined above is already outside of our threat model, as it assumes n/3 -malicious nodes + additionally malfunctioning/DoSed nodes. Even more so for -attacks on the best-effort queue, as our threat model only allows for n/3 -malicious _or_ malfunctioning nodes in total. It would therefore be a valid -decision to ditch the best-effort queue, if it proves to become a burden or -creates other issues. - -One issue we should not be worried about though is spam. For abusing best-effort -for spam, the following scenario would be necessary: - -An attacker controls a backing group: The attacker can then have candidates -backed and choose to not provide chunks. This should come at a cost to miss out -on rewards for backing, so is not free. At the same time it is rate limited, as -a backing group can only back so many candidates legitimately. (~ 1 per slot): - -1. They have to wait until a malicious actor becomes block producer (for causing - additional forks via equivocation for example). +While attacking the priority queue is already pretty hard, attacking the best-effort queue is even harder. For a +candidate to be a threat, it has to be included on some chain. For it to be included, it has to have been backed before +and at least n/3 honest nodes must have seen that block, so availability (inclusion) can be reached. Making a full third +of the nodes not further propagate a block, while at the same time allowing them to fetch chunks, sign and distribute +bitfields seems almost infeasible and even if accomplished, those nodes would be enough to confirm a dispute and we have +not even touched the above fact that in addition, for an attack, the following including block must be shared with +honest validators as well. + +It is worth mentioning that a successful attack on the priority queue as outlined above is already outside of our threat +model, as it assumes n/3 malicious nodes + additionally malfunctioning/DoSed nodes. Even more so for attacks on the +best-effort queue, as our threat model only allows for n/3 malicious _or_ malfunctioning nodes in total. It would +therefore be a valid decision to ditch the best-effort queue, if it proves to become a burden or creates other issues. + +One issue we should not be worried about though is spam. For abusing best-effort for spam, the following scenario would +be necessary: + +An attacker controls a backing group: The attacker can then have candidates backed and choose to not provide chunks. +This should come at a cost to miss out on rewards for backing, so is not free. At the same time it is rate limited, as a +backing group can only back so many candidates legitimately. (~ 1 per slot): + +1. They have to wait until a malicious actor becomes block producer (for causing additional forks via equivocation for + example). 2. Forks are possible, but if caused by equivocation also not free. -3. For each fork the attacker has to wait until the candidate times out, for - backing another one. +3. For each fork the attacker has to wait until the candidate times out, for backing another one. -Assuming there can only be a handful of forks, 2) together with 3) the candidate -timeout restriction, frequency should indeed be in the ballpark of once per -slot. Scaling linearly in the number of controlled backing groups, so two groups +Assuming there can only be a handful of forks, 2) together with 3) the candidate timeout restriction, frequency should +indeed be in the ballpark of once per slot. Scaling linearly in the number of controlled backing groups, so two groups would mean 2 backings per slot, ... -So by this reasoning an attacker could only do very limited harm and at the same -time will have to pay some price for it (it will miss out on rewards). Overall -the work done by the network might even be in the same ballpark as if actors -just behaved honestly: +So by this reasoning an attacker could only do very limited harm and at the same time will have to pay some price for it +(it will miss out on rewards). Overall the work done by the network might even be in the same ballpark as if actors just +behaved honestly: 1. Validators would have fetched chunks 2. Approval checkers would have done approval checks -While because of the attack (backing, not providing chunks and afterwards -disputing the candidate), the work for 1000 validators would be: +While because of the attack (backing, not providing chunks and afterwards disputing the candidate), the work for 1000 +validators would be: -All validators sending out ~ 1000 tiny requests over already established -connections, with also tiny (byte) responses. +All validators sending out ~ 1000 tiny requests over already established connections, with also tiny (byte) responses. -This means around a million requests, while in the honest case it would be ~ -10000 (30 approval checkers x330) - where each request triggers a response in -the range of kilobytes. Hence network load alone will likely be higher in the -honest case than in the DoS attempt case, which would mean the DoS attempt -actually reduces load, while also costing rewards. +This means around a million requests, while in the honest case it would be ~ 10000 (30 approval checkers x330) - where +each request triggers a response in the range of kilobytes. Hence network load alone will likely be higher in the honest +case than in the DoS attempt case, which would mean the DoS attempt actually reduces load, while also costing rewards. -In the worst case this can happen multiple times, as we would retry that on -every vote import. The effect would still be in the same ballpark as honest -behavior though and can also be mitigated by chilling repeated availability -recovery requests for example. +In the worst case this can happen multiple times, as we would retry that on every vote import. The effect would still be +in the same ballpark as honest behavior though and can also be mitigated by chilling repeated availability recovery +requests for example. ## Out of Scope ### No Disputes for Non Included Candidates -We only ever care about disputes for candidates that have been included on at -least some chain (became available). This is because the availability system was -designed for precisely that: Only with inclusion (availability) we have -guarantees about the candidate to actually be available. Because only then we -have guarantees that malicious backers can be reliably checked and slashed. Also, by design non included candidates do not pose any threat to the system. - -One could think of an (additional) dispute system to make it possible to dispute -any candidate that has been proposed by a validator, no matter whether it got -successfully included or even backed. Unfortunately, it would be very brittle -(no availability) and also spam protection would be way harder than for the -disputes handled by the dispute-coordinator. In fact, all the spam handling -strategies described above would simply be unavailable. - -It is worth thinking about who could actually raise such disputes anyway: -Approval checkers certainly not, as they will only ever check once availability -succeeded. The only other nodes that meaningfully could/would are honest backing -nodes or collators. For collators spam considerations would be even worse as -there can be an unlimited number of them and we can not charge them for spam, so -trying to handle disputes raised by collators would be even more complex. For -honest backers: It actually makes more sense for them to wait until availability -is reached as well, as only then they have guarantees that other nodes will be -able to check. If they disputed before, all nodes would need to recover the data +We only ever care about disputes for candidates that have been included on at least some chain (became available). This +is because the availability system was designed for precisely that: Only with inclusion (availability) we have +guarantees about the candidate to actually be available. Because only then we have guarantees that malicious backers can +be reliably checked and slashed. Also, by design non included candidates do not pose any threat to the system. + +One could think of an (additional) dispute system to make it possible to dispute any candidate that has been proposed by +a validator, no matter whether it got successfully included or even backed. Unfortunately, it would be very brittle (no +availability) and also spam protection would be way harder than for the disputes handled by the dispute-coordinator. In +fact, all the spam handling strategies described above would simply be unavailable. + +It is worth thinking about who could actually raise such disputes anyway: Approval checkers certainly not, as they will +only ever check once availability succeeded. The only other nodes that meaningfully could/would are honest backing nodes +or collators. For collators spam considerations would be even worse as there can be an unlimited number of them and we +can not charge them for spam, so trying to handle disputes raised by collators would be even more complex. For honest +backers: It actually makes more sense for them to wait until availability is reached as well, as only then they have +guarantees that other nodes will be able to check. If they disputed before, all nodes would need to recover the data from them, so they would be an easy DoS target. -In summary: The availability system was designed for raising disputes in a -meaningful and secure way after availability was reached. Trying to raise -disputes before does not meaningfully contribute to the systems security/might -even weaken it as attackers are warned before availability is reached, while at -the same time adding signficant amount of complexity. We therefore punt on such -disputes and concentrate on disputes the system was designed to handle. +In summary: The availability system was designed for raising disputes in a meaningful and secure way after availability +was reached. Trying to raise disputes before does not meaningfully contribute to the systems security/might even weaken +it as attackers are warned before availability is reached, while at the same time adding signficant amount of +complexity. We therefore punt on such disputes and concentrate on disputes the system was designed to handle. ### No Disputes for Already Finalized Blocks -Note that by above rules in the `Participation` section, we will not participate -in disputes concerning a candidate in an already finalized block. This is -because, disputing an already finalized block is simply too late and therefore -of little value. Once finalized, bridges have already processed the block for -example, so we have to assume the damage is already done. Governance has to step -in and fix what can be fixed. +Note that by above rules in the `Participation` section, we will not participate in disputes concerning a candidate in +an already finalized block. This is because, disputing an already finalized block is simply too late and therefore of +little value. Once finalized, bridges have already processed the block for example, so we have to assume the damage is +already done. Governance has to step in and fix what can be fixed. -Making disputes for already finalized blocks possible would only provide two -features: +Making disputes for already finalized blocks possible would only provide two features: 1. We can at least still slash attackers. -2. We can freeze the chain to some governance only mode, in an attempt to - minimize potential harm done. +2. We can freeze the chain to some governance only mode, in an attempt to minimize potential harm done. -Both seem kind of worthwhile, although as argued above, it is likely that there -is not too much that can be done in 2 and we would likely only ending up DoSing -the whole system without much we can do. 1 can also be achieved via governance +Both seem kind of worthwhile, although as argued above, it is likely that there is not too much that can be done in 2 +and we would likely only ending up DoSing the whole system without much we can do. 1 can also be achieved via governance mechanisms. -In any case, our focus should be making as sure as reasonably possible that any -potentially invalid block does not get finalized in the first place. Not -allowing disputing already finalized blocks actually helps a great deal with -this goal as it massively reduces the amount of candidates that can be disputed. - -This makes attempts to overwhelm the system with disputes significantly harder -and counter measures way easier. We can limit inclusion for example (as -suggested [here](https://github.com/paritytech/polkadot/issues/5898) in case of -high dispute load. Another measure we have at our disposal is that on finality -lag block production will slow down, implicitly reducing the rate of new -candidates that can be disputed. Hence, the cutting-off of the unlimited -candidate supply of already finalized blocks, guarantees the necessary DoS -protection and ensures we can have measures in place to keep up with processing -of disputes. - -If we allowed participation for disputes for already finalized candidates, the -above spam protection mechanisms would be insufficient/relying 100% on full and -quick disabling of spamming validators. +In any case, our focus should be making as sure as reasonably possible that any potentially invalid block does not get +finalized in the first place. Not allowing disputing already finalized blocks actually helps a great deal with this goal +as it massively reduces the amount of candidates that can be disputed. + +This makes attempts to overwhelm the system with disputes significantly harder and counter measures way easier. We can +limit inclusion for example (as suggested [here](https://github.com/paritytech/polkadot/issues/5898) in case of high +dispute load. Another measure we have at our disposal is that on finality lag block production will slow down, +implicitly reducing the rate of new candidates that can be disputed. Hence, the cutting-off of the unlimited candidate +supply of already finalized blocks, guarantees the necessary DoS protection and ensures we can have measures in place to +keep up with processing of disputes. + +If we allowed participation for disputes for already finalized candidates, the above spam protection mechanisms would be +insufficient/relying 100% on full and quick disabling of spamming validators. ## Database Schema We use an underlying Key-Value database where we assume we have the following operations available: - * `write(key, value)` - * `read(key) -> Option` - * `iter_with_prefix(prefix) -> Iterator<(key, value)>` - gives all keys and values in - lexicographical order where the key starts with `prefix`. + - `write(key, value)` + - `read(key) -> Option` + - `iter_with_prefix(prefix) -> Iterator<(key, value)>` - gives all keys and values in lexicographical order where the + key starts with `prefix`. We use this database to encode the following schema: @@ -612,8 +471,8 @@ We use this database to encode the following schema: "earliest-session" -> Option ``` -The meta information that we track per-candidate is defined as the `CandidateVotes` struct. -This draws on the [dispute statement types][DisputeTypes] +The meta information that we track per-candidate is defined as the `CandidateVotes` struct. This draws on the [dispute +statement types][DisputeTypes] ```rust /// Tracked votes on candidates, for the purposes of dispute resolution. @@ -659,8 +518,7 @@ Output: ## Functionality -This assumes a constant `DISPUTE_WINDOW: SessionWindowSize`. This should correspond to at least 1 -day. +This assumes a constant `DISPUTE_WINDOW: SessionWindowSize`. This should correspond to at least 1 day. Ephemeral in-memory state: @@ -684,42 +542,36 @@ struct State { ### On startup -When the subsystem is initialised it waits for a new leaf (message -`OverseerSignal::ActiveLeaves`). The leaf is used to initialise a -`RollingSessionWindow` instance (contains leaf hash and `DISPUTE_WINDOW` which -is a constant). +When the subsystem is initialised it waits for a new leaf (message `OverseerSignal::ActiveLeaves`). The leaf is used to +initialise a `RollingSessionWindow` instance (contains leaf hash and `DISPUTE_WINDOW` which is a constant). -Next the active disputes are loaded from the DB and initialize spam slots -accordingly, then for each loaded dispute, we either send a -`DisputeDistribution::SendDispute` if there is a local vote from us available or -if there is none and participation is in order, we push the dispute to -participation. +Next the active disputes are loaded from the DB and initialize spam slots accordingly, then for each loaded dispute, we +either send a `DisputeDistribution::SendDispute` if there is a local vote from us available or if there is none and +participation is in order, we push the dispute to participation. ### The main loop -Just after the subsystem initialisation the main loop (`fn run_until_error()`) runs until -`OverseerSignal::Conclude` signal is received. Before executing the actual main loop the leaf and -the participations, obtained during startup are enqueued for processing. If there is capacity (the -number of running participations is less than `MAX_PARALLEL_PARTICIPATIONS`) participation jobs are -started (`func participate`). Finally the component waits for messages from Overseer. The behaviour -on each message is described in the following subsections. +Just after the subsystem initialisation the main loop (`fn run_until_error()`) runs until `OverseerSignal::Conclude` +signal is received. Before executing the actual main loop the leaf and the participations, obtained during startup are +enqueued for processing. If there is capacity (the number of running participations is less than +`MAX_PARALLEL_PARTICIPATIONS`) participation jobs are started (`func participate`). Finally the component waits for +messages from Overseer. The behaviour on each message is described in the following subsections. ### On `OverseerSignal::ActiveLeaves` -Initiates processing via the `Participation` module and updates the internal state of the subsystem. -More concretely: +Initiates processing via the `Participation` module and updates the internal state of the subsystem. More concretely: -* Passes the `ActiveLeavesUpdate` message to the ordering provider. -* Updates the session info cache. -* Updates `self.highest_session`. -* Prunes old spam slots in case the session window has advanced. -* Scrapes on chain votes. +- Passes the `ActiveLeavesUpdate` message to the ordering provider. +- Updates the session info cache. +- Updates `self.highest_session`. +- Prunes old spam slots in case the session window has advanced. +- Scrapes on chain votes. ### On `MuxedMessage::Participation` -This message is sent from `Participatuion` module and indicates a processed dispute participation. -It's the result of the processing job initiated with `OverseerSignal::ActiveLeaves`. The subsystem -issues a `DisputeMessage` with the result. +This message is sent from `Participatuion` module and indicates a processed dispute participation. It's the result of +the processing job initiated with `OverseerSignal::ActiveLeaves`. The subsystem issues a `DisputeMessage` with the +result. ### On `OverseerSignal::Conclude` @@ -731,14 +583,13 @@ Performs cleanup of the finalized candidate. ### On `DisputeCoordinatorMessage::ImportStatements` -Import statements by validators are processed in `fn handle_import_statements()`. The function has -got three main responsibilities: -* Initiate participation in disputes and sending out of any existing own - approval vote in case of a raised dispute. -* Persist all fresh votes in the database. Fresh votes in this context means votes that are not - already processed by the node. -* Spam protection on all invalid (`DisputeStatement::Invalid`) votes. Please check the SpamSlots - section for details on how spam protection works. +Import statements by validators are processed in `fn handle_import_statements()`. The function has got three main +responsibilities: +- Initiate participation in disputes and sending out of any existing own approval vote in case of a raised dispute. +- Persist all fresh votes in the database. Fresh votes in this context means votes that are not already processed by the + node. +- Spam protection on all invalid (`DisputeStatement::Invalid`) votes. Please check the SpamSlots section for details on + how spam protection works. ### On `DisputeCoordinatorMessage::RecentDisputes` @@ -750,38 +601,35 @@ Returns all recent disputes concluded within the last `ACTIVE_DURATION_SECS` . ### On `DisputeCoordinatorMessage::QueryCandidateVotes` -Loads `candidate-votes` for every `(SessionIndex, CandidateHash)` in the input query and returns -data within each `CandidateVote`. If a particular `candidate-vote` is missing, that particular -request is omitted from the response. +Loads `candidate-votes` for every `(SessionIndex, CandidateHash)` in the input query and returns data within each +`CandidateVote`. If a particular `candidate-vote` is missing, that particular request is omitted from the response. ### On `DisputeCoordinatorMessage::IssueLocalStatement` Executes `fn issue_local_statement()` which performs the following operations: -* Deconstruct into parts `{ session_index, candidate_hash, candidate_receipt, is_valid }`. -* Construct a [`DisputeStatement`][DisputeStatement] based on `Valid` or `Invalid`, depending on the - parameterization of this routine. -* Sign the statement with each key in the `SessionInfo`'s list of parachain validation keys which is - present in the keystore, except those whose indices appear in `voted_indices`. This will typically - just be one key, but this does provide some future-proofing for situations where the same node may - run on behalf multiple validators. At the time of writing, this is not a use-case we support as - other subsystems do not invariably provide this guarantee. -* Write statement to DB. -* Send a `DisputeDistributionMessage::SendDispute` message to get the vote distributed to other - validators. +- Deconstruct into parts `{ session_index, candidate_hash, candidate_receipt, is_valid }`. +- Construct a [`DisputeStatement`][DisputeStatement] based on `Valid` or `Invalid`, depending on the parameterization of + this routine. +- Sign the statement with each key in the `SessionInfo`'s list of parachain validation keys which is present in the + keystore, except those whose indices appear in `voted_indices`. This will typically just be one key, but this does + provide some future-proofing for situations where the same node may run on behalf multiple validators. At the time of + writing, this is not a use-case we support as other subsystems do not invariably provide this guarantee. +- Write statement to DB. +- Send a `DisputeDistributionMessage::SendDispute` message to get the vote distributed to other validators. ### On `DisputeCoordinatorMessage::DetermineUndisputedChain` Executes `fn determine_undisputed_chain()` which performs the following: -* Load `"recent-disputes"`. -* Deconstruct into parts `{ base_number, block_descriptions, rx }` -* Starting from the beginning of `block_descriptions`: +- Load `"recent-disputes"`. +- Deconstruct into parts `{ base_number, block_descriptions, rx }` +- Starting from the beginning of `block_descriptions`: 1. Check the `RecentDisputes` for a dispute of each candidate in the block description. 1. If there is a dispute which is active or concluded negative, exit the loop. -* For the highest index `i` reached in the `block_descriptions`, send `(base_number + i + 1, - block_hash)` on the channel, unless `i` is 0, in which case `None` should be sent. The - `block_hash` is determined by inspecting `block_descriptions[i]`. +- For the highest index `i` reached in the `block_descriptions`, send `(base_number + i + 1, block_hash)` on the + channel, unless `i` is 0, in which case `None` should be sent. The `block_hash` is determined by inspecting + `block_descriptions[i]`. [DisputeTypes]: ../../types/disputes.md [DisputeStatement]: ../../types/disputes.md#disputestatement diff --git a/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-distribution.md b/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-distribution.md index 3a45f53c45d7..4547e02352ec 100644 --- a/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-distribution.md @@ -202,8 +202,8 @@ the dispute-coordinator already knows about the dispute. Goal 3 and 4 are obviously very related and both can easily be solved via rate limiting as we shall see below. Rate limits should already be implemented at the -substrate level, but [are not](https://github.com/paritytech/substrate/issues/7750) -at the time of writing. But even if they were, the enforced substrate limits would +Substrate level, but [are not](https://github.com/paritytech/substrate/issues/7750) +at the time of writing. But even if they were, the enforced Substrate limits would likely not be configurable and thus would still be to high for our needs as we can rely on the following observations: @@ -282,10 +282,10 @@ well, we will do the following: to assume this is concerning a new dispute. 2. We open a batch and start collecting incoming messages for that candidate, instead of immediately forwarding. -4. We keep collecting votes in the batch until we receive less than +3. We keep collecting votes in the batch until we receive less than `MIN_KEEP_BATCH_ALIVE_VOTES` unique votes in the last `BATCH_COLLECTING_INTERVAL`. This is important to accommodate for goal 5 and also 3. -5. We send the whole batch to the dispute-coordinator. +4. We send the whole batch to the dispute-coordinator. This together with rate limiting explained above ensures we will be able to process valid disputes: We can limit the number of simultaneous existing batches @@ -312,8 +312,8 @@ of attackers, each has 10 messages per second, all are needed to maintain the batches in memory. Therefore we have a hard cap of around 330 (number of malicious nodes) open batches. Each can be filled with number of malicious actor's votes. So 330 batches with each 330 votes: Let's assume approximately 100 -bytes per signature/vote. This results in a worst case memory usage of 330 * 330 -* 100 ~= 10 MiB. +bytes per signature/vote. This results in a worst case memory usage of +`330 * 330 * 100 ~= 10 MiB`. For 10_000 validators, we are already in the Gigabyte range, which means that with a validator set that large we might want to be more strict with the rate limit or diff --git a/polkadot/roadmap/implementers-guide/src/node/grandpa-voting-rule.md b/polkadot/roadmap/implementers-guide/src/node/grandpa-voting-rule.md index 5e608ccfd62e..6997dc99f80e 100644 --- a/polkadot/roadmap/implementers-guide/src/node/grandpa-voting-rule.md +++ b/polkadot/roadmap/implementers-guide/src/node/grandpa-voting-rule.md @@ -1,10 +1,25 @@ # GRANDPA Voting Rule -Specifics on the motivation and types of constraints we apply to the GRANDPA voting logic as well as the definitions of **viable** and **finalizable** blocks can be found in the [Chain Selection Protocol](../protocol-chain-selection.md) section. -The subsystem which provides us with viable leaves is the [Chain Selection Subsystem](utility/chain-selection.md). +Specifics on the motivation and types of constraints we apply to the GRANDPA voting logic as well as the definitions of +**viable** and **finalizable** blocks can be found in the [Chain Selection Protocol](../protocol-chain-selection.md) +section. The subsystem which provides us with viable leaves is the [Chain Selection +Subsystem](utility/chain-selection.md). -GRANDPA's regular voting rule is for each validator to select the longest chain they are aware of. GRANDPA proceeds in rounds, collecting information from all online validators and determines the blocks that a supermajority of validators all have in common with each other. +GRANDPA's regular voting rule is for each validator to select the longest chain they are aware of. GRANDPA proceeds in +rounds, collecting information from all online validators and determines the blocks that a supermajority of validators +all have in common with each other. -The low-level GRANDPA logic will provide us with a **required block**. We can find the best leaf containing that block in its chain with the [`ChainSelectionMessage::BestLeafContaining`](../types/overseer-protocol.md#chain-selection-message). If the result is `None`, then we will simply cast a vote on the required block. +The low-level GRANDPA logic will provide us with a **required block**. We can find the best leaf containing that block +in its chain with the +[`ChainSelectionMessage::BestLeafContaining`](../types/overseer-protocol.md#chain-selection-message). If the result is +`None`, then we will simply cast a vote on the required block. -The **viable** leaves provided from the chain selection subsystem are not necessarily **finalizable**, so we need to perform further work to discover the finalizable ancestor of the block. The first constraint is to avoid voting on any unapproved block. The highest approved ancestor of a given block can be determined by querying the Approval Voting subsystem via the [`ApprovalVotingMessage::ApprovedAncestor`](../types/overseer-protocol.md#approval-voting) message. If the response is `Some`, we continue and apply the second constraint. The second constraint is to avoid voting on any block containing a candidate undergoing an active dispute. The list of block hashes and candidates returned from `ApprovedAncestor` should be reversed, and passed to the [`DisputeCoordinatorMessage::DetermineUndisputedChain`](../types/overseer-protocol.md#dispute-coordinator-message) to determine the **finalizable** block which will be our eventual vote. +The **viable** leaves provided from the chain selection subsystem are not necessarily **finalizable**, so we need to +perform further work to discover the finalizable ancestor of the block. The first constraint is to avoid voting on any +unapproved block. The highest approved ancestor of a given block can be determined by querying the Approval Voting +subsystem via the [`ApprovalVotingMessage::ApprovedAncestor`](../types/overseer-protocol.md#approval-voting) message. If +the response is `Some`, we continue and apply the second constraint. The second constraint is to avoid voting on any +block containing a candidate undergoing an active dispute. The list of block hashes and candidates returned from +`ApprovedAncestor` should be reversed, and passed to the +[`DisputeCoordinatorMessage::DetermineUndisputedChain`](../types/overseer-protocol.md#dispute-coordinator-message) to +determine the **finalizable** block which will be our eventual vote. diff --git a/polkadot/roadmap/implementers-guide/src/node/overseer.md b/polkadot/roadmap/implementers-guide/src/node/overseer.md index 21300d9098a2..53a115308101 100644 --- a/polkadot/roadmap/implementers-guide/src/node/overseer.md +++ b/polkadot/roadmap/implementers-guide/src/node/overseer.md @@ -24,27 +24,44 @@ The hierarchy of subsystems: ``` -The overseer determines work to do based on block import events and block finalization events. It does this by keeping track of the set of relay-parents for which work is currently being done. This is known as the "active leaves" set. It determines an initial set of active leaves on startup based on the data on-disk, and uses events about blockchain import to update the active leaves. Updates lead to [`OverseerSignal`](../types/overseer-protocol.md#overseer-signal)`::ActiveLeavesUpdate` being sent according to new relay-parents, as well as relay-parents to stop considering. Block import events inform the overseer of leaves that no longer need to be built on, now that they have children, and inform us to begin building on those children. Block finalization events inform us when we can stop focusing on blocks that appear to have been orphaned. - -The overseer is also responsible for tracking the freshness of active leaves. Leaves are fresh when they're encountered for the first time, and stale when they're encountered for subsequent times. This can occur after chain reversions or when the fork-choice rule abandons some chain. This distinction is used to manage **Reversion Safety**. Consensus messages are often localized to a specific relay-parent, and it is often a misbehavior to equivocate or sign two conflicting messages. When reverting the chain, we may begin work on a leaf that subsystems have already signed messages for. Subsystems which need to account for reversion safety should avoid performing work on stale leaves. +The overseer determines work to do based on block import events and block finalization events. It does this by keeping +track of the set of relay-parents for which work is currently being done. This is known as the "active leaves" set. It +determines an initial set of active leaves on startup based on the data on-disk, and uses events about blockchain import +to update the active leaves. Updates lead to +[`OverseerSignal`](../types/overseer-protocol.md#overseer-signal)`::ActiveLeavesUpdate` being sent according to new +relay-parents, as well as relay-parents to stop considering. Block import events inform the overseer of leaves that no +longer need to be built on, now that they have children, and inform us to begin building on those children. Block +finalization events inform us when we can stop focusing on blocks that appear to have been orphaned. + +The overseer is also responsible for tracking the freshness of active leaves. Leaves are fresh when they're encountered +for the first time, and stale when they're encountered for subsequent times. This can occur after chain reversions or +when the fork-choice rule abandons some chain. This distinction is used to manage **Reversion Safety**. Consensus +messages are often localized to a specific relay-parent, and it is often a misbehavior to equivocate or sign two +conflicting messages. When reverting the chain, we may begin work on a leaf that subsystems have already signed messages +for. Subsystems which need to account for reversion safety should avoid performing work on stale leaves. The overseer's logic can be described with these functions: ## On Startup * Start all subsystems -* Determine all blocks of the blockchain that should be built on. This should typically be the head of the best fork of the chain we are aware of. Sometimes add recent forks as well. +* Determine all blocks of the blockchain that should be built on. This should typically be the head of the best fork of + the chain we are aware of. Sometimes add recent forks as well. * Send an `OverseerSignal::ActiveLeavesUpdate` to all subsystems with `activated` containing each of these blocks. * Begin listening for block import and finality events ## On Block Import Event -* Apply the block import event to the active leaves. A new block should lead to its addition to the active leaves set and its parent being deactivated. -* Mark any stale leaves as stale. The overseer should track all leaves it activates to determine whether leaves are fresh or stale. -* Send an `OverseerSignal::ActiveLeavesUpdate` message to all subsystems containing all activated and deactivated leaves. +* Apply the block import event to the active leaves. A new block should lead to its addition to the active leaves set + and its parent being deactivated. +* Mark any stale leaves as stale. The overseer should track all leaves it activates to determine whether leaves are + fresh or stale. +* Send an `OverseerSignal::ActiveLeavesUpdate` message to all subsystems containing all activated and deactivated + leaves. * Ensure all `ActiveLeavesUpdate` messages are flushed before resuming activity as a message router. -> TODO: in the future, we may want to avoid building on too many sibling blocks at once. the notion of a "preferred head" among many competing sibling blocks would imply changes in our "active leaves" update rules here +> TODO: in the future, we may want to avoid building on too many sibling blocks at once. the notion of a "preferred +> head" among many competing sibling blocks would imply changes in our "active leaves" update rules here ## On Finalization Event @@ -54,11 +71,16 @@ The overseer's logic can be described with these functions: ## On Subsystem Failure -Subsystems are essential tasks meant to run as long as the node does. Subsystems can spawn ephemeral work in the form of jobs, but the subsystems themselves should not go down. If a subsystem goes down, it will be because of a critical error that should take the entire node down as well. +Subsystems are essential tasks meant to run as long as the node does. Subsystems can spawn ephemeral work in the form of +jobs, but the subsystems themselves should not go down. If a subsystem goes down, it will be because of a critical error +that should take the entire node down as well. ## Communication Between Subsystems -When a subsystem wants to communicate with another subsystem, or, more typically, a job within a subsystem wants to communicate with its counterpart under another subsystem, that communication must happen via the overseer. Consider this example where a job on subsystem A wants to send a message to its counterpart under subsystem B. This is a realistic scenario, where you can imagine that both jobs correspond to work under the same relay-parent. +When a subsystem wants to communicate with another subsystem, or, more typically, a job within a subsystem wants to +communicate with its counterpart under another subsystem, that communication must happen via the overseer. Consider this +example where a job on subsystem A wants to send a message to its counterpart under subsystem B. This is a realistic +scenario, where you can imagine that both jobs correspond to work under the same relay-parent. ```text +--------+ +--------+ @@ -78,21 +100,48 @@ When a subsystem wants to communicate with another subsystem, or, more typically +------------------------------+ ``` -First, the subsystem that spawned a job is responsible for handling the first step of the communication. The overseer is not aware of the hierarchy of tasks within any given subsystem and is only responsible for subsystem-to-subsystem communication. So the sending subsystem must pass on the message via the overseer to the receiving subsystem, in such a way that the receiving subsystem can further address the communication to one of its internal tasks, if necessary. - -This communication prevents a certain class of race conditions. When the Overseer determines that it is time for subsystems to begin working on top of a particular relay-parent, it will dispatch a `ActiveLeavesUpdate` message to all subsystems to do so, and those messages will be handled asynchronously by those subsystems. Some subsystems will receive those messsages before others, and it is important that a message sent by subsystem A after receiving `ActiveLeavesUpdate` message will arrive at subsystem B after its `ActiveLeavesUpdate` message. If subsystem A maintained an independent channel with subsystem B to communicate, it would be possible for subsystem B to handle the side message before the `ActiveLeavesUpdate` message, but it wouldn't have any logical course of action to take with the side message - leading to it being discarded or improperly handled. Well-architectured state machines should have a single source of inputs, so that is what we do here. - -One exception is reasonable to make for responses to requests. A request should be made via the overseer in order to ensure that it arrives after any relevant `ActiveLeavesUpdate` message. A subsystem issuing a request as a result of a `ActiveLeavesUpdate` message can safely receive the response via a side-channel for two reasons: - -1. It's impossible for a request to be answered before it arrives, it is provable that any response to a request obeys the same ordering constraint. -1. The request was sent as a result of handling a `ActiveLeavesUpdate` message. Then there is no possible future in which the `ActiveLeavesUpdate` message has not been handled upon the receipt of the response. - -So as a single exception to the rule that all communication must happen via the overseer we allow the receipt of responses to requests via a side-channel, which may be established for that purpose. This simplifies any cases where the outside world desires to make a request to a subsystem, as the outside world can then establish a side-channel to receive the response on. - -It's important to note that the overseer is not aware of the internals of subsystems, and this extends to the jobs that they spawn. The overseer isn't aware of the existence or definition of those jobs, and is only aware of the outer subsystems with which it interacts. This gives subsystem implementations leeway to define internal jobs as they see fit, and to wrap a more complex hierarchy of state machines than having a single layer of jobs for relay-parent-based work. Likewise, subsystems aren't required to spawn jobs. Certain types of subsystems, such as those for shared storage or networking resources, won't perform block-based work but would still benefit from being on the Overseer's message bus. These subsystems can just ignore the overseer's signals for block-based work. - -Furthermore, the protocols by which subsystems communicate with each other should be well-defined irrespective of the implementation of the subsystem. In other words, their interface should be distinct from their implementation. This will prevent subsystems from accessing aspects of each other that are beyond the scope of the communication boundary. +First, the subsystem that spawned a job is responsible for handling the first step of the communication. The overseer is +not aware of the hierarchy of tasks within any given subsystem and is only responsible for subsystem-to-subsystem +communication. So the sending subsystem must pass on the message via the overseer to the receiving subsystem, in such a +way that the receiving subsystem can further address the communication to one of its internal tasks, if necessary. + +This communication prevents a certain class of race conditions. When the Overseer determines that it is time for +subsystems to begin working on top of a particular relay-parent, it will dispatch a `ActiveLeavesUpdate` message to all +subsystems to do so, and those messages will be handled asynchronously by those subsystems. Some subsystems will receive +those messsages before others, and it is important that a message sent by subsystem A after receiving +`ActiveLeavesUpdate` message will arrive at subsystem B after its `ActiveLeavesUpdate` message. If subsystem A +maintained an independent channel with subsystem B to communicate, it would be possible for subsystem B to handle the +side message before the `ActiveLeavesUpdate` message, but it wouldn't have any logical course of action to take with the +side message - leading to it being discarded or improperly handled. Well-architectured state machines should have a +single source of inputs, so that is what we do here. + +One exception is reasonable to make for responses to requests. A request should be made via the overseer in order to +ensure that it arrives after any relevant `ActiveLeavesUpdate` message. A subsystem issuing a request as a result of a +`ActiveLeavesUpdate` message can safely receive the response via a side-channel for two reasons: + +1. It's impossible for a request to be answered before it arrives, it is provable that any response to a request obeys + the same ordering constraint. +1. The request was sent as a result of handling a `ActiveLeavesUpdate` message. Then there is no possible future in + which the `ActiveLeavesUpdate` message has not been handled upon the receipt of the response. + +So as a single exception to the rule that all communication must happen via the overseer we allow the receipt of +responses to requests via a side-channel, which may be established for that purpose. This simplifies any cases where the +outside world desires to make a request to a subsystem, as the outside world can then establish a side-channel to +receive the response on. + +It's important to note that the overseer is not aware of the internals of subsystems, and this extends to the jobs that +they spawn. The overseer isn't aware of the existence or definition of those jobs, and is only aware of the outer +subsystems with which it interacts. This gives subsystem implementations leeway to define internal jobs as they see fit, +and to wrap a more complex hierarchy of state machines than having a single layer of jobs for relay-parent-based work. +Likewise, subsystems aren't required to spawn jobs. Certain types of subsystems, such as those for shared storage or +networking resources, won't perform block-based work but would still benefit from being on the Overseer's message bus. +These subsystems can just ignore the overseer's signals for block-based work. + +Furthermore, the protocols by which subsystems communicate with each other should be well-defined irrespective of the +implementation of the subsystem. In other words, their interface should be distinct from their implementation. This will +prevent subsystems from accessing aspects of each other that are beyond the scope of the communication boundary. ## On shutdown -Send an `OverseerSignal::Conclude` message to each subsystem and wait some time for them to conclude before hard-exiting. +Send an `OverseerSignal::Conclude` message to each subsystem and wait some time for them to conclude before +hard-exiting. diff --git a/polkadot/roadmap/implementers-guide/src/node/subsystems-and-jobs.md b/polkadot/roadmap/implementers-guide/src/node/subsystems-and-jobs.md index 6e3b4cd2d166..a3ca7347eb63 100644 --- a/polkadot/roadmap/implementers-guide/src/node/subsystems-and-jobs.md +++ b/polkadot/roadmap/implementers-guide/src/node/subsystems-and-jobs.md @@ -1,25 +1,66 @@ # Subsystems and Jobs -In this section we define the notions of Subsystems and Jobs. These are guidelines for how we will employ an architecture of hierarchical state machines. We'll have a top-level state machine which oversees the next level of state machines which oversee another layer of state machines and so on. The next sections will lay out these guidelines for what we've called subsystems and jobs, since this model applies to many of the tasks that the Node-side behavior needs to encompass, but these are only guidelines and some Subsystems may have deeper hierarchies internally. - -Subsystems are long-lived worker tasks that are in charge of performing some particular kind of work. All subsystems can communicate with each other via a well-defined protocol. Subsystems can't generally communicate directly, but must coordinate communication through an [Overseer](overseer.md), which is responsible for relaying messages, handling subsystem failures, and dispatching work signals. - -Most work that happens on the Node-side is related to building on top of a specific relay-chain block, which is contextually known as the "relay parent". We call it the relay parent to explicitly denote that it is a block in the relay chain and not on a parachain. We refer to the parent because when we are in the process of building a new block, we don't know what that new block is going to be. The parent block is our only stable point of reference, even though it is usually only useful when it is not yet a parent but in fact a leaf of the block-DAG expected to soon become a parent (because validators are authoring on top of it). Furthermore, we are assuming a forkful blockchain-extension protocol, which means that there may be multiple possible children of the relay-parent. Even if the relay parent has multiple children blocks, the parent of those children is the same, and the context in which those children is authored should be the same. The parent block is the best and most stable reference to use for defining the scope of work items and messages, and is typically referred to by its cryptographic hash. - -Since this goal of determining when to start and conclude work relative to a specific relay-parent is common to most, if not all subsystems, it is logically the job of the Overseer to distribute those signals as opposed to each subsystem duplicating that effort, potentially being out of synchronization with each other. Subsystem A should be able to expect that subsystem B is working on the same relay-parents as it is. One of the Overseer's tasks is to provide this heartbeat, or synchronized rhythm, to the system. - -The work that subsystems spawn to be done on a specific relay-parent is known as a job. Subsystems should set up and tear down jobs according to the signals received from the overseer. Subsystems may share or cache state between jobs. - -Subsystems must be robust to spurious exits. The outputs of the set of subsystems as a whole comprises of signed messages and data committed to disk. Care must be taken to avoid issuing messages that are not substantiated. Since subsystems need to be safe under spurious exits, it is the expected behavior that an `OverseerSignal::Conclude` can just lead to breaking the loop and exiting directly as opposed to waiting for everything to shut down gracefully. +In this section we define the notions of Subsystems and Jobs. These are +guidelines for how we will employ an architecture of hierarchical state +machines. We'll have a top-level state machine which oversees the next level of +state machines which oversee another layer of state machines and so on. The next +sections will lay out these guidelines for what we've called subsystems and +jobs, since this model applies to many of the tasks that the Node-side behavior +needs to encompass, but these are only guidelines and some Subsystems may have +deeper hierarchies internally. + +Subsystems are long-lived worker tasks that are in charge of performing some +particular kind of work. All subsystems can communicate with each other via a +well-defined protocol. Subsystems can't generally communicate directly, but must +coordinate communication through an [Overseer](overseer.md), which is +responsible for relaying messages, handling subsystem failures, and dispatching +work signals. + +Most work that happens on the Node-side is related to building on top of a +specific relay-chain block, which is contextually known as the "relay parent". +We call it the relay parent to explicitly denote that it is a block in the relay +chain and not on a parachain. We refer to the parent because when we are in the +process of building a new block, we don't know what that new block is going to +be. The parent block is our only stable point of reference, even though it is +usually only useful when it is not yet a parent but in fact a leaf of the +block-DAG expected to soon become a parent (because validators are authoring on +top of it). Furthermore, we are assuming a forkful blockchain-extension +protocol, which means that there may be multiple possible children of the +relay-parent. Even if the relay parent has multiple children blocks, the parent +of those children is the same, and the context in which those children is +authored should be the same. The parent block is the best and most stable +reference to use for defining the scope of work items and messages, and is +typically referred to by its cryptographic hash. + +Since this goal of determining when to start and conclude work relative to a +specific relay-parent is common to most, if not all subsystems, it is logically +the job of the Overseer to distribute those signals as opposed to each subsystem +duplicating that effort, potentially being out of synchronization with each +other. Subsystem A should be able to expect that subsystem B is working on the +same relay-parents as it is. One of the Overseer's tasks is to provide this +heartbeat, or synchronized rhythm, to the system. + +The work that subsystems spawn to be done on a specific relay-parent is known as +a job. Subsystems should set up and tear down jobs according to the signals +received from the overseer. Subsystems may share or cache state between jobs. + +Subsystems must be robust to spurious exits. The outputs of the set of +subsystems as a whole comprises of signed messages and data committed to disk. +Care must be taken to avoid issuing messages that are not substantiated. Since +subsystems need to be safe under spurious exits, it is the expected behavior +that an `OverseerSignal::Conclude` can just lead to breaking the loop and +exiting directly as opposed to waiting for everything to shut down gracefully. ## Subsystem Message Traffic Which subsystems send messages to which other subsystems. -**Note**: This diagram omits the overseer for simplicity. In fact, all messages are relayed via the overseer. +**Note**: This diagram omits the overseer for simplicity. In fact, all messages +are relayed via the overseer. -**Note**: Messages with a filled diamond arrowhead ("♦") include a `oneshot::Sender` which communicates a response from the recipient. -Messages with an open triangle arrowhead ("Δ") do not include a return sender. +**Note**: Messages with a filled diamond arrowhead ("♦") include a +`oneshot::Sender` which communicates a response from the recipient. Messages +with an open triangle arrowhead ("Δ") do not include a return sender. ```dot process digraph { @@ -125,14 +166,17 @@ digraph { ## The Path to Inclusion (Node Side) -Let's contextualize that diagram a bit by following a parachain block from its creation through finalization. -Parachains can use completely arbitrary processes to generate blocks. The relay chain doesn't know or care about -the details; each parachain just needs to provide a [collator](collators/collation-generation.md). +Let's contextualize that diagram a bit by following a parachain block from its +creation through finalization. Parachains can use completely arbitrary processes +to generate blocks. The relay chain doesn't know or care about the details; each +parachain just needs to provide a [collator](collators/collation-generation.md). -**Note**: Inter-subsystem communications are relayed via the overseer, but that step is omitted here for brevity. +**Note**: Inter-subsystem communications are relayed via the overseer, but that +step is omitted here for brevity. -**Note**: Dashed lines indicate a request/response cycle, where the response is communicated asynchronously via -a oneshot channel. Adjacent dashed lines may be processed in parallel. +**Note**: Dashed lines indicate a request/response cycle, where the response is +communicated asynchronously via a oneshot channel. Adjacent dashed lines may be +processed in parallel. ```mermaid sequenceDiagram @@ -156,11 +200,13 @@ sequenceDiagram end ``` -The `DistributeCollation` messages that `CollationGeneration` sends to the `CollatorProtocol` contains -two items: a `CandidateReceipt` and `PoV`. The `CollatorProtocol` is then responsible for distributing -that collation to interested validators. However, not all potential collations are of interest. The -`CandidateSelection` subsystem is responsible for determining which collations are interesting, before -`CollatorProtocol` actually fetches the collation. +The `DistributeCollation` messages that `CollationGeneration` sends to the +`CollatorProtocol` contains two items: a `CandidateReceipt` and `PoV`. The +`CollatorProtocol` is then responsible for distributing that collation to +interested validators. However, not all potential collations are of interest. +The `CandidateSelection` subsystem is responsible for determining which +collations are interesting, before `CollatorProtocol` actually fetches the +collation. ```mermaid sequenceDiagram @@ -205,10 +251,11 @@ sequenceDiagram end ``` -Assuming we hit the happy path, flow continues with `CandidateSelection` receiving a `(candidate_receipt, pov)` as -the return value from its -`FetchCollation` request. The only time `CandidateSelection` actively requests a collation is when -it hasn't yet seconded one for some `relay_parent`, and is ready to second. +Assuming we hit the happy path, flow continues with `CandidateSelection` +receiving a `(candidate_receipt, pov)` as the return value from its +`FetchCollation` request. The only time `CandidateSelection` actively requests a +collation is when it hasn't yet seconded one for some `relay_parent`, and is +ready to second. ```mermaid sequenceDiagram @@ -243,15 +290,17 @@ sequenceDiagram end ``` -At this point, you'll see that control flows in two directions: to `StatementDistribution` to distribute -the `SignedStatement`, and to `PoVDistribution` to distribute the `PoV`. However, that's largely a mirage: -while the initial implementation distributes `PoV`s by gossip, that's inefficient, and will be replaced -with a system which fetches `PoV`s only when actually necessary. +At this point, you'll see that control flows in two directions: to +`StatementDistribution` to distribute the `SignedStatement`, and to +`PoVDistribution` to distribute the `PoV`. However, that's largely a mirage: +while the initial implementation distributes `PoV`s by gossip, that's +inefficient, and will be replaced with a system which fetches `PoV`s only when +actually necessary. > TODO: figure out more precisely the current status and plans; write them up -Therefore, we'll follow the `SignedStatement`. The `StatementDistribution` subsystem is largely concerned -with implementing a gossip protocol: +Therefore, we'll follow the `SignedStatement`. The `StatementDistribution` +subsystem is largely concerned with implementing a gossip protocol: ```mermaid sequenceDiagram @@ -278,8 +327,8 @@ sequenceDiagram end ``` -But who are these `Listener`s who've asked to be notified about incoming `SignedStatement`s? -Nobody, as yet. +But who are these `Listener`s who've asked to be notified about incoming +`SignedStatement`s? Nobody, as yet. Let's pick back up with the PoV Distribution subsystem. @@ -305,11 +354,13 @@ sequenceDiagram Note over PD,NB: On receipt of a network PoV, PovDistribution forwards it to each Listener.
It also penalizes bad gossipers. ``` -Unlike in the case of `StatementDistribution`, there is another subsystem which in various circumstances -already registers a listener to be notified when a new `PoV` arrives: `CandidateBacking`. Note that this -is the second time that `CandidateBacking` has gotten involved. The first instance was from the perspective -of the validator choosing to second a candidate via its `CandidateSelection` subsystem. This time, it's -from the perspective of some other validator, being informed that this foreign `PoV` has been received. +Unlike in the case of `StatementDistribution`, there is another subsystem which +in various circumstances already registers a listener to be notified when a new +`PoV` arrives: `CandidateBacking`. Note that this is the second time that +`CandidateBacking` has gotten involved. The first instance was from the +perspective of the validator choosing to second a candidate via its +`CandidateSelection` subsystem. This time, it's from the perspective of some +other validator, being informed that this foreign `PoV` has been received. ```mermaid sequenceDiagram @@ -326,10 +377,11 @@ sequenceDiagram CB ->> AS: StoreAvailableData ``` -At this point, things have gone a bit nonlinear. Let's pick up the thread again with `BitfieldSigning`. As -the `Overseer` activates each relay parent, it starts a `BitfieldSigningJob` which operates on an extremely -simple metric: after creation, it immediately goes to sleep for 1.5 seconds. On waking, it records the state -of the world pertaining to availability at that moment. +At this point, things have gone a bit nonlinear. Let's pick up the thread again +with `BitfieldSigning`. As the `Overseer` activates each relay parent, it starts +a `BitfieldSigningJob` which operates on an extremely simple metric: after +creation, it immediately goes to sleep for 1.5 seconds. On waking, it records +the state of the world pertaining to availability at that moment. ```mermaid sequenceDiagram @@ -350,9 +402,10 @@ sequenceDiagram end ``` -`BitfieldDistribution` is, like the other `*Distribution` subsystems, primarily interested in implementing -a peer-to-peer gossip network propagating its particular messages. However, it also serves as an essential -relay passing the message along. +`BitfieldDistribution` is, like the other `*Distribution` subsystems, primarily +interested in implementing a peer-to-peer gossip network propagating its +particular messages. However, it also serves as an essential relay passing the +message along. ```mermaid sequenceDiagram @@ -366,12 +419,14 @@ sequenceDiagram BD ->> NB: SendValidationMessage::BitfieldDistribution::Bitfield ``` -We've now seen the message flow to the `Provisioner`: both `CandidateBacking` and `BitfieldDistribution` -contribute provisionable data. Now, let's look at that subsystem. +We've now seen the message flow to the `Provisioner`: both `CandidateBacking` +and `BitfieldDistribution` contribute provisionable data. Now, let's look at +that subsystem. -Much like the `BitfieldSigning` subsystem, the `Provisioner` creates a new job for each newly-activated -leaf, and starts a timer. Unlike `BitfieldSigning`, we won't depict that part of the process, because -the `Provisioner` also has other things going on. +Much like the `BitfieldSigning` subsystem, the `Provisioner` creates a new job +for each newly-activated leaf, and starts a timer. Unlike `BitfieldSigning`, we +won't depict that part of the process, because the `Provisioner` also has other +things going on. ```mermaid sequenceDiagram @@ -411,8 +466,9 @@ sequenceDiagram end ``` -In principle, any arbitrary subsystem could send a `RequestInherentData` to the `Provisioner`. In practice, -only the `ParachainsInherentDataProvider` does so. +In principle, any arbitrary subsystem could send a `RequestInherentData` to the +`Provisioner`. In practice, only the `ParachainsInherentDataProvider` does so. -The tuple `(SignedAvailabilityBitfields, BackedCandidates, ParentHeader)` is injected by the `ParachainsInherentDataProvider` -into the inherent data. From that point on, control passes from the node to the runtime. +The tuple `(SignedAvailabilityBitfields, BackedCandidates, ParentHeader)` is +injected by the `ParachainsInherentDataProvider` into the inherent data. From +that point on, control passes from the node to the runtime. diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/availability-store.md b/polkadot/roadmap/implementers-guide/src/node/utility/availability-store.md index bd61455934e4..71d3f3245231 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/availability-store.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/availability-store.md @@ -9,13 +9,20 @@ The two data types: For each of these data we have pruning rules that determine how long we need to keep that data available. -PoV hypothetically only need to be kept around until the block where the data was made fully available is finalized. However, disputes can revert finality, so we need to be a bit more conservative and we add a delay. We should keep the PoV until a block that finalized availability of it has been finalized for 1 day + 1 hour. +PoV hypothetically only need to be kept around until the block where the data was made fully available is finalized. +However, disputes can revert finality, so we need to be a bit more conservative and we add a delay. We should keep the +PoV until a block that finalized availability of it has been finalized for 1 day + 1 hour. -Availability chunks need to be kept available until the dispute period for the corresponding candidate has ended. We can accomplish this by using the same criterion as the above. This gives us a pruning condition of the block finalizing availability of the chunk being final for 1 day + 1 hour. +Availability chunks need to be kept available until the dispute period for the corresponding candidate has ended. We can +accomplish this by using the same criterion as the above. This gives us a pruning condition of the block finalizing +availability of the chunk being final for 1 day + 1 hour. -There is also the case where a validator commits to make a PoV available, but the corresponding candidate is never backed. In this case, we keep the PoV available for 1 hour. +There is also the case where a validator commits to make a PoV available, but the corresponding candidate is never +backed. In this case, we keep the PoV available for 1 hour. -There may be multiple competing blocks all ending the availability phase for a particular candidate. Until finality, it will be unclear which of those is actually the canonical chain, so the pruning records for PoVs and Availability chunks should keep track of all such blocks. +There may be multiple competing blocks all ending the availability phase for a particular candidate. Until finality, it +will be unclear which of those is actually the canonical chain, so the pruning records for PoVs and Availability chunks +should keep track of all such blocks. ## Lifetime of the block data and chunks in storage @@ -44,7 +51,8 @@ We use an underlying Key-Value database where we assume we have the following op - `write(key, value)` - `read(key) -> Option` -- `iter_with_prefix(prefix) -> Iterator<(key, value)>` - gives all keys and values in lexicographical order where the key starts with `prefix`. +- `iter_with_prefix(prefix) -> Iterator<(key, value)>` - gives all keys and values in lexicographical order where the + key starts with `prefix`. We use this database to encode the following schema: @@ -57,7 +65,8 @@ We use this database to encode the following schema: ("prune_by_time", Timestamp, CandidateHash) -> Option<()> ``` -Timestamps are the wall-clock seconds since Unix epoch. Timestamps and block numbers are both encoded as big-endian so lexicographic order is ascending. +Timestamps are the wall-clock seconds since Unix epoch. Timestamps and block numbers are both encoded as big-endian so +lexicographic order is ascending. The meta information that we track per-candidate is defined as the `CandidateMeta` struct @@ -80,9 +89,12 @@ enum State { } ``` -We maintain the invariant that if a candidate has a meta entry, its available data exists on disk if `data_available` is true. All chunks mentioned in the meta entry are available. +We maintain the invariant that if a candidate has a meta entry, its available data exists on disk if `data_available` is +true. All chunks mentioned in the meta entry are available. -Additionally, there is exactly one `prune_by_time` entry which holds the candidate hash unless the state is `Unfinalized`. There may be zero, one, or many "unfinalized" keys with the given candidate, and this will correspond to the `state` of the meta entry. +Additionally, there is exactly one `prune_by_time` entry which holds the candidate hash unless the state is +`Unfinalized`. There may be zero, one, or many "unfinalized" keys with the given candidate, and this will correspond to +the `state` of the meta entry. ## Protocol @@ -96,9 +108,15 @@ Output: For each head in the `activated` list: -- Load all ancestors of the head back to the finalized block so we don't miss anything if import notifications are missed. If a `StoreChunk` message is received for a candidate which has no entry, then we will prematurely lose the data. -- Note any new candidates backed in the head. Update the `CandidateMeta` for each. If the `CandidateMeta` does not exist, create it as `Unavailable` with the current timestamp. Register a `"prune_by_time"` entry based on the current timestamp + 1 hour. -- Note any new candidate included in the head. Update the `CandidateMeta` for each, performing a transition from `Unavailable` to `Unfinalized` if necessary. That includes removing the `"prune_by_time"` entry. Add the head hash and number to the state, if unfinalized. Add an `"unfinalized"` entry for the block and candidate. +- Load all ancestors of the head back to the finalized block so we don't miss anything if import notifications are + missed. If a `StoreChunk` message is received for a candidate which has no entry, then we will prematurely lose the + data. +- Note any new candidates backed in the head. Update the `CandidateMeta` for each. If the `CandidateMeta` does not + exist, create it as `Unavailable` with the current timestamp. Register a `"prune_by_time"` entry based on the current + timestamp + 1 hour. +- Note any new candidate included in the head. Update the `CandidateMeta` for each, performing a transition from + `Unavailable` to `Unfinalized` if necessary. That includes removing the `"prune_by_time"` entry. Add the head hash and + number to the state, if unfinalized. Add an `"unfinalized"` entry for the block and candidate. - The `CandidateEvent` runtime API can be used for this purpose. On `OverseerSignal::BlockFinalized(finalized)` events: @@ -106,17 +124,22 @@ On `OverseerSignal::BlockFinalized(finalized)` events: - for each key in `iter_with_prefix("unfinalized")` - Stop if the key is beyond `("unfinalized, finalized)` - For each block number f that we encounter, load the finalized hash for that block. - - The state of each `CandidateMeta` we encounter here must be `Unfinalized`, since we loaded the candidate from an `"unfinalized"` key. + - The state of each `CandidateMeta` we encounter here must be `Unfinalized`, since we loaded the candidate from an + `"unfinalized"` key. - For each candidate that we encounter under `f` and the finalized block hash, - - Update the `CandidateMeta` to have `State::Finalized`. Remove all `"unfinalized"` entries from the old `Unfinalized` state. + - Update the `CandidateMeta` to have `State::Finalized`. Remove all `"unfinalized"` entries from the old + `Unfinalized` state. - Register a `"prune_by_time"` entry for the candidate based on the current time + 1 day + 1 hour. - For each candidate that we encounter under `f` which is not under the finalized block hash, - Remove all entries under `f` in the `Unfinalized` state. - - If the `CandidateMeta` has state `Unfinalized` with an empty list of blocks, downgrade to `Unavailable` and re-schedule pruning under the timestamp + 1 hour. We do not prune here as the candidate still may be included in a descendant of the finalized chain. + - If the `CandidateMeta` has state `Unfinalized` with an empty list of blocks, downgrade to `Unavailable` and + re-schedule pruning under the timestamp + 1 hour. We do not prune here as the candidate still may be included in + a descendant of the finalized chain. - Remove all `"unfinalized"` keys under `f`. - Update `last_finalized` = finalized. - This is roughly `O(n * m)` where n is the number of blocks finalized since the last update, and `m` is the number of parachains. + This is roughly `O(n * m)` where n is the number of blocks finalized since the last update, and `m` is the number of + parachains. On `QueryAvailableData` message: @@ -139,7 +162,8 @@ On `QueryChunk` message: On `QueryAllChunks` message: - Query `("meta", candidate_hash)`. If `None`, send an empty response and return. -- For all `1` bits in the `chunks_stored`, query `("chunk", candidate_hash, index)`. Ignore but warn on errors, and return a vector of all loaded chunks. +- For all `1` bits in the `chunks_stored`, query `("chunk", candidate_hash, index)`. Ignore but warn on errors, and + return a vector of all loaded chunks. On `QueryChunkAvailability` message: @@ -149,14 +173,17 @@ On `QueryChunkAvailability` message: On `StoreChunk` message: -- If there is a `CandidateMeta` under the candidate hash, set the bit of the erasure-chunk in the `chunks_stored` bitfield to `1`. If it was not `1` already, write the chunk under `("chunk", candidate_hash, chunk_index)`. +- If there is a `CandidateMeta` under the candidate hash, set the bit of the erasure-chunk in the `chunks_stored` + bitfield to `1`. If it was not `1` already, write the chunk under `("chunk", candidate_hash, chunk_index)`. This is `O(n)` in the size of the chunk. On `StoreAvailableData` message: -- Compute the erasure root of the available data and compare it with `expected_erasure_root`. Return `StoreAvailableDataError::InvalidErasureRoot` on mismatch. -- If there is no `CandidateMeta` under the candidate hash, create it with `State::Unavailable(now)`. Load the `CandidateMeta` otherwise. +- Compute the erasure root of the available data and compare it with `expected_erasure_root`. Return + `StoreAvailableDataError::InvalidErasureRoot` on mismatch. +- If there is no `CandidateMeta` under the candidate hash, create it with `State::Unavailable(now)`. Load the + `CandidateMeta` otherwise. - Store `data` under `("available", candidate_hash)` and set `data_available` to true. - Store each chunk under `("chunk", candidate_hash, index)` and set every bit in `chunks_stored` to `1`. @@ -172,12 +199,13 @@ Every 5 minutes, run a pruning routine: - For each erasure chunk bit set, remove `("chunk", candidate_hash, bit_index)`. - If `data_available`, remove `("available", candidate_hash)` - This is O(n * m) in the amount of candidates and average size of the data stored. This is probably the most expensive operation but does not need - to be run very often. + This is O(n * m) in the amount of candidates and average size of the data stored. This is probably the most expensive + operation but does not need to be run very often. ## Basic scenarios to test -Basically we need to test the correctness of data flow through state FSMs described earlier. These tests obviously assume that some mocking of time is happening. +Basically we need to test the correctness of data flow through state FSMs described earlier. These tests obviously +assume that some mocking of time is happening. - Stored data that is never included pruned in necessary timeout - A block (and/or a chunk) is added to the store. diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/candidate-validation.md b/polkadot/roadmap/implementers-guide/src/node/utility/candidate-validation.md index 4a1d02be5560..376fa187de1b 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/candidate-validation.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/candidate-validation.md @@ -2,7 +2,8 @@ This subsystem is responsible for handling candidate validation requests. It is a simple request/response server. -A variety of subsystems want to know if a parachain block candidate is valid. None of them care about the detailed mechanics of how a candidate gets validated, just the results. This subsystem handles those details. +A variety of subsystems want to know if a parachain block candidate is valid. None of them care about the detailed +mechanics of how a candidate gets validated, just the results. This subsystem handles those details. ## Protocol @@ -12,35 +13,53 @@ Output: Validation result via the provided response side-channel. ## Functionality -This subsystem groups the requests it handles in two categories: *candidate validation* and *PVF pre-checking*. +This subsystem groups the requests it handles in two categories: *candidate validation* and *PVF pre-checking*. -The first category can be further subdivided in two request types: one which draws out validation data from the state, and another which accepts all validation data exhaustively. Validation returns three possible outcomes on the response channel: the candidate is valid, the candidate is invalid, or an internal error occurred. +The first category can be further subdivided in two request types: one which draws out validation data from the state, +and another which accepts all validation data exhaustively. Validation returns three possible outcomes on the response +channel: the candidate is valid, the candidate is invalid, or an internal error occurred. -Parachain candidates are validated against their validation function: A piece of Wasm code that describes the state-transition of the parachain. Validation function execution is not metered. This means that an execution which is an infinite loop or simply takes too long must be forcibly exited by some other means. For this reason, we recommend dispatching candidate validation to be done on subprocesses which can be killed if they time-out. +Parachain candidates are validated against their validation function: A piece of Wasm code that describes the +state-transition of the parachain. Validation function execution is not metered. This means that an execution which is +an infinite loop or simply takes too long must be forcibly exited by some other means. For this reason, we recommend +dispatching candidate validation to be done on subprocesses which can be killed if they time-out. -Upon receiving a validation request, the first thing the candidate validation subsystem should do is make sure it has all the necessary parameters to the validation function. These are: +Upon receiving a validation request, the first thing the candidate validation subsystem should do is make sure it has +all the necessary parameters to the validation function. These are: * The Validation Function itself. * The [`CandidateDescriptor`](../../types/candidate.md#candidatedescriptor). * The [`ValidationData`](../../types/candidate.md#validationdata). * The [`PoV`](../../types/availability.md#proofofvalidity). -The second category is for PVF pre-checking. This is primarly used by the [PVF pre-checker](pvf-prechecker.md) subsystem. +The second category is for PVF pre-checking. This is primarly used by the [PVF pre-checker](pvf-prechecker.md) +subsystem. ### Determining Parameters For a [`CandidateValidationMessage`][CVM]`::ValidateFromExhaustive`, these parameters are exhaustively provided. -For a [`CandidateValidationMessage`][CVM]`::ValidateFromChainState`, some more work needs to be done. Due to the uncertainty of Availability Cores (implemented in the [`Scheduler`](../../runtime/scheduler.md) module of the runtime), a candidate at a particular relay-parent and for a particular para may have two different valid validation-data to be executed under depending on what is assumed to happen if the para is occupying a core at the onset of the new block. This is encoded as an `OccupiedCoreAssumption` in the runtime API. +For a [`CandidateValidationMessage`][CVM]`::ValidateFromChainState`, some more work needs to be done. Due to the +uncertainty of Availability Cores (implemented in the [`Scheduler`](../../runtime/scheduler.md) module of the runtime), +a candidate at a particular relay-parent and for a particular para may have two different valid validation-data to be +executed under depending on what is assumed to happen if the para is occupying a core at the onset of the new block. +This is encoded as an `OccupiedCoreAssumption` in the runtime API. -The way that we can determine which assumption the candidate is meant to be executed under is simply to do an exhaustive check of both possibilities based on the state of the relay-parent. First we fetch the validation data under the assumption that the block occupying becomes available. If the `validation_data_hash` of the `CandidateDescriptor` matches this validation data, we use that. Otherwise, if the `validation_data_hash` matches the validation data fetched under the `TimedOut` assumption, we use that. Otherwise, we return a `ValidationResult::Invalid` response and conclude. +The way that we can determine which assumption the candidate is meant to be executed under is simply to do an exhaustive +check of both possibilities based on the state of the relay-parent. First we fetch the validation data under the +assumption that the block occupying becomes available. If the `validation_data_hash` of the `CandidateDescriptor` +matches this validation data, we use that. Otherwise, if the `validation_data_hash` matches the validation data fetched +under the `TimedOut` assumption, we use that. Otherwise, we return a `ValidationResult::Invalid` response and conclude. -Then, we can fetch the validation code from the runtime based on which type of candidate this is. This gives us all the parameters. The descriptor and PoV come from the request itself, and the other parameters have been derived from the state. +Then, we can fetch the validation code from the runtime based on which type of candidate this is. This gives us all the +parameters. The descriptor and PoV come from the request itself, and the other parameters have been derived from the +state. > TODO: This would be a great place for caching to avoid making lots of runtime requests. That would need a job, though. ### Execution of the Parachain Wasm -Once we have all parameters, we can spin up a background task to perform the validation in a way that doesn't hold up the entire event loop. Before invoking the validation function itself, this should first do some basic checks: +Once we have all parameters, we can spin up a background task to perform the validation in a way that doesn't hold up +the entire event loop. Before invoking the validation function itself, this should first do some basic checks: * The collator signature is valid * The PoV provided matches the `pov_hash` field of the descriptor @@ -48,6 +67,8 @@ For more details please see [PVF Host and Workers](pvf-host-and-workers.md). ### Checking Validation Outputs -If we can assume the presence of the relay-chain state (that is, during processing [`CandidateValidationMessage`][CVM]`::ValidateFromChainState`) we can run all the checks that the relay-chain would run at the inclusion time thus confirming that the candidate will be accepted. +If we can assume the presence of the relay-chain state (that is, during processing +[`CandidateValidationMessage`][CVM]`::ValidateFromChainState`) we can run all the checks that the relay-chain would run +at the inclusion time thus confirming that the candidate will be accepted. [CVM]: ../../types/overseer-protocol.md#validationrequesttype diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/chain-api.md b/polkadot/roadmap/implementers-guide/src/node/utility/chain-api.md index e9ef9b5695bc..aab4f2d5cb56 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/chain-api.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/chain-api.md @@ -1,6 +1,7 @@ # Chain API -The Chain API subsystem is responsible for providing a single point of access to chain state data via a set of pre-determined queries. +The Chain API subsystem is responsible for providing a single point of access to chain state data via a set of +pre-determined queries. ## Protocol @@ -10,7 +11,8 @@ Output: None ## Functionality -On receipt of `ChainApiMessage`, answer the request and provide the response to the side-channel embedded within the request. +On receipt of `ChainApiMessage`, answer the request and provide the response to the side-channel embedded within the +request. Currently, the following requests are supported: * Block hash to number diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/chain-selection.md b/polkadot/roadmap/implementers-guide/src/node/utility/chain-selection.md index 640691e55961..1d1358b228b6 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/chain-selection.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/chain-selection.md @@ -1,8 +1,12 @@ # Chain Selection Subsystem -This subsystem implements the necessary metadata for the implementation of the [chain selection](../../protocol-chain-selection.md) portion of the protocol. +This subsystem implements the necessary metadata for the implementation of the [chain +selection](../../protocol-chain-selection.md) portion of the protocol. -The subsystem wraps a database component which maintains a view of the unfinalized chain and records the properties of each block: whether the block is **viable**, whether it is **stagnant**, and whether it is **reverted**. It should also maintain an updated set of active leaves in accordance with this view, which should be cheap to query. Leaves are ordered descending first by weight and then by block number. +The subsystem wraps a database component which maintains a view of the unfinalized chain and records the properties of +each block: whether the block is **viable**, whether it is **stagnant**, and whether it is **reverted**. It should also +maintain an updated set of active leaves in accordance with this view, which should be cheap to query. Leaves are +ordered descending first by weight and then by block number. This subsystem needs to update its information on the unfinalized chain: * On every leaf-activated signal @@ -11,32 +15,47 @@ This subsystem needs to update its information on the unfinalized chain: * On every `ChainSelectionMessage::RevertBlocks` * Periodically, to detect stagnation. -Simple implementations of these updates do `O(n_unfinalized_blocks)` disk operations. If the amount of unfinalized blocks is relatively small, the updates should not take very much time. However, in cases where there are hundreds or thousands of unfinalized blocks the naive implementations of these update algorithms would have to be replaced with more sophisticated versions. +Simple implementations of these updates do `O(n_unfinalized_blocks)` disk operations. If the amount of unfinalized +blocks is relatively small, the updates should not take very much time. However, in cases where there are hundreds or +thousands of unfinalized blocks the naive implementations of these update algorithms would have to be replaced with more +sophisticated versions. -### `OverseerSignal::ActiveLeavesUpdate` +## `OverseerSignal::ActiveLeavesUpdate` -Determine all new blocks implicitly referenced by any new active leaves and add them to the view. Update the set of viable leaves accordingly. The weights of imported blocks can be determined by the [`ChainApiMessage::BlockWeight`](../../types/overseer-protocol.md#chain-api-message). +Determine all new blocks implicitly referenced by any new active leaves and add them to the view. Update the set of +viable leaves accordingly. The weights of imported blocks can be determined by the +[`ChainApiMessage::BlockWeight`](../../types/overseer-protocol.md#chain-api-message). -### `OverseerSignal::BlockFinalized` +## `OverseerSignal::BlockFinalized` -Delete data for all orphaned chains and update all metadata descending from the new finalized block accordingly, along with the set of viable leaves. Note that finalizing a **reverted** or **stagnant** block means that the descendants of those blocks may lose that status because the definitions of those properties don't include the finalized chain. Update the set of viable leaves accordingly. +Delete data for all orphaned chains and update all metadata descending from the new finalized block accordingly, along +with the set of viable leaves. Note that finalizing a **reverted** or **stagnant** block means that the descendants of +those blocks may lose that status because the definitions of those properties don't include the finalized chain. Update +the set of viable leaves accordingly. -### `ChainSelectionMessage::Approved` +## `ChainSelectionMessage::Approved` -Update the approval status of the referenced block. If the block was stagnant and thus non-viable and is now viable, then the metadata of all of its descendants needs to be updated as well, as they may no longer be stagnant either. Update the set of viable leaves accordingly. +Update the approval status of the referenced block. If the block was stagnant and thus non-viable and is now viable, +then the metadata of all of its descendants needs to be updated as well, as they may no longer be stagnant either. +Update the set of viable leaves accordingly. -### `ChainSelectionMessage::Leaves` +## `ChainSelectionMessage::Leaves` -Gets all leaves of the chain, i.e. block hashes that are suitable to build upon and have no suitable children. Supplies the leaves in descending order by score. +Gets all leaves of the chain, i.e. block hashes that are suitable to build upon and have no suitable children. Supplies +the leaves in descending order by score. -### `ChainSelectionMessage::BestLeafContaining` +## `ChainSelectionMessage::BestLeafContaining` -If the required block is unknown or not viable, then return `None`. Iterate over all leaves in order of descending weight, returning the first leaf containing the required block in its chain, and `None` otherwise. +If the required block is unknown or not viable, then return `None`. Iterate over all leaves in order of descending +weight, returning the first leaf containing the required block in its chain, and `None` otherwise. -### `ChainSelectionMessage::RevertBlocks` -This message indicates that a dispute has concluded against a parachain block candidate. The message passes along a vector containing the block number and block hash of each block where the disputed candidate was included. The passed blocks will be marked as reverted, and their descendants will be marked as non-viable. +## `ChainSelectionMessage::RevertBlocks` +This message indicates that a dispute has concluded against a parachain block candidate. The message passes along a +vector containing the block number and block hash of each block where the disputed candidate was included. The passed +blocks will be marked as reverted, and their descendants will be marked as non-viable. -### Periodically +## Periodically -Detect stagnant blocks and apply the stagnant definition to all descendants. Update the set of viable leaves accordingly. +Detect stagnant blocks and apply the stagnant definition to all descendants. Update the set of viable leaves +accordingly. diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/network-bridge.md b/polkadot/roadmap/implementers-guide/src/node/utility/network-bridge.md index 3245772d9d8d..d2506fbe83e3 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/network-bridge.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/network-bridge.md @@ -1,30 +1,43 @@ # Network Bridge -One of the main features of the overseer/subsystem duality is to avoid shared ownership of resources and to communicate via message-passing. However, implementing each networking subsystem as its own network protocol brings a fair share of challenges. - -The most notable challenge is coordinating and eliminating race conditions of peer connection and disconnection events. If we have many network protocols that peers are supposed to be connected on, it is difficult to enforce that a peer is indeed connected on all of them or the order in which those protocols receive notifications that peers have connected. This becomes especially difficult when attempting to share peer state across protocols. All of the Parachain-Host's gossip protocols eliminate DoS with a data-dependency on current chain heads. However, it is inefficient and confusing to implement the logic for tracking our current chain heads as well as our peers' on each of those subsystems. Having one subsystem for tracking this shared state and distributing it to the others is an improvement in architecture and efficiency. - -One other piece of shared state to track is peer reputation. When peers are found to have provided value or cost, we adjust their reputation accordingly. - -So in short, this Subsystem acts as a bridge between an actual network component and a subsystem's protocol. The implementation of the underlying network component is beyond the scope of this module. We make certain assumptions about the network component: - * The network allows registering of protocols and multiple versions of each protocol. - * The network handles version negotiation of protocols with peers and only connects the peer on the highest version of the protocol. - * Each protocol has its own peer-set, although there may be some overlap. - * The network provides peer-set management utilities for discovering the peer-IDs of validators and a means of dialing peers with given IDs. - - -The network bridge makes use of the peer-set feature, but is not generic over peer-set. Instead, it exposes two peer-sets that event producers can attach to: `Validation` and `Collation`. More information can be found on the documentation of the [`NetworkBridgeMessage`][NBM]. +One of the main features of the overseer/subsystem duality is to avoid shared ownership of resources and to communicate +via message-passing. However, implementing each networking subsystem as its own network protocol brings a fair share of +challenges. + +The most notable challenge is coordinating and eliminating race conditions of peer connection and disconnection events. +If we have many network protocols that peers are supposed to be connected on, it is difficult to enforce that a peer is +indeed connected on all of them or the order in which those protocols receive notifications that peers have connected. +This becomes especially difficult when attempting to share peer state across protocols. All of the Parachain-Host's +gossip protocols eliminate DoS with a data-dependency on current chain heads. However, it is inefficient and confusing +to implement the logic for tracking our current chain heads as well as our peers' on each of those subsystems. Having +one subsystem for tracking this shared state and distributing it to the others is an improvement in architecture and +efficiency. + +One other piece of shared state to track is peer reputation. When peers are found to have provided value or cost, we +adjust their reputation accordingly. + +So in short, this Subsystem acts as a bridge between an actual network component and a subsystem's protocol. The +implementation of the underlying network component is beyond the scope of this module. We make certain assumptions about +the network component: + - The network allows registering of protocols and multiple versions of each protocol. + - The network handles version negotiation of protocols with peers and only connects the peer on the highest version of + the protocol. + - Each protocol has its own peer-set, although there may be some overlap. + - The network provides peer-set management utilities for discovering the peer-IDs of validators and a means of dialing + peers with given IDs. + +The network bridge makes use of the peer-set feature, but is not generic over peer-set. Instead, it exposes two +peer-sets that event producers can attach to: `Validation` and `Collation`. More information can be found on the +documentation of the [`NetworkBridgeMessage`][NBM]. ## Protocol Input: [`NetworkBridgeMessage`][NBM] - -Output: - - [`ApprovalDistributionMessage`][AppD]`::NetworkBridgeUpdate` - - [`BitfieldDistributionMessage`][BitD]`::NetworkBridgeUpdate` - - [`CollatorProtocolMessage`][CollP]`::NetworkBridgeUpdate` - - [`StatementDistributionMessage`][StmtD]`::NetworkBridgeUpdate` +Output: - [`ApprovalDistributionMessage`][AppD]`::NetworkBridgeUpdate` - + [`BitfieldDistributionMessage`][BitD]`::NetworkBridgeUpdate` - + [`CollatorProtocolMessage`][CollP]`::NetworkBridgeUpdate` - + [`StatementDistributionMessage`][StmtD]`::NetworkBridgeUpdate` ## Functionality @@ -37,7 +50,8 @@ enum WireMessage { } ``` -and instantiates this type twice, once using the [`ValidationProtocolV1`][VP1] message type, and once with the [`CollationProtocolV1`][CP1] message type. +and instantiates this type twice, once using the [`ValidationProtocolV1`][VP1] message type, and once with the +[`CollationProtocolV1`][CP1] message type. ```rust type ValidationV1Message = WireMessage; @@ -46,17 +60,21 @@ type CollationV1Message = WireMessage; ### Startup -On startup, we register two protocols with the underlying network utility. One for validation and one for collation. We register only version 1 of each of these protocols. +On startup, we register two protocols with the underlying network utility. One for validation and one for collation. We +register only version 1 of each of these protocols. ### Main Loop -The bulk of the work done by this subsystem is in responding to network events, signals from the overseer, and messages from other subsystems. +The bulk of the work done by this subsystem is in responding to network events, signals from the overseer, and messages +from other subsystems. Each network event is associated with a particular peer-set. ### Overseer Signal: `ActiveLeavesUpdate` -The `activated` and `deactivated` lists determine the evolution of our local view over time. A `ProtocolMessage::ViewUpdate` is issued to each connected peer on each peer-set, and a `NetworkBridgeEvent::OurViewChange` is issued to each event handler for each protocol. +The `activated` and `deactivated` lists determine the evolution of our local view over time. A +`ProtocolMessage::ViewUpdate` is issued to each connected peer on each peer-set, and a +`NetworkBridgeEvent::OurViewChange` is issued to each event handler for each protocol. We only send view updates if the node has indicated that it has finished major blockchain synchronization. @@ -64,24 +82,31 @@ If we are connected to the same peer on both peer-sets, we will send the peer tw ### Overseer Signal: `BlockFinalized` -We update our view's `finalized_number` to the provided one and delay `ProtocolMessage::ViewUpdate` and `NetworkBridgeEvent::OurViewChange` till the next `ActiveLeavesUpdate`. +We update our view's `finalized_number` to the provided one and delay `ProtocolMessage::ViewUpdate` and +`NetworkBridgeEvent::OurViewChange` till the next `ActiveLeavesUpdate`. ### Network Event: `PeerConnected` -Issue a `NetworkBridgeEvent::PeerConnected` for each [Event Handler](#event-handlers) of the peer-set and negotiated protocol version of the peer. Also issue a `NetworkBridgeEvent::PeerViewChange` and send the peer our current view, but only if the node has indicated that it has finished major blockchain synchronization. Otherwise, we only send the peer an empty view. +Issue a `NetworkBridgeEvent::PeerConnected` for each [Event Handler](#event-handlers) of the peer-set and negotiated +protocol version of the peer. Also issue a `NetworkBridgeEvent::PeerViewChange` and send the peer our current view, but +only if the node has indicated that it has finished major blockchain synchronization. Otherwise, we only send the peer +an empty view. ### Network Event: `PeerDisconnected` -Issue a `NetworkBridgeEvent::PeerDisconnected` for each [Event Handler](#event-handlers) of the peer-set and negotiated protocol version of the peer. +Issue a `NetworkBridgeEvent::PeerDisconnected` for each [Event Handler](#event-handlers) of the peer-set and negotiated +protocol version of the peer. ### Network Event: `ProtocolMessage` -Map the message onto the corresponding [Event Handler](#event-handlers) based on the peer-set this message was received on and dispatch via overseer. +Map the message onto the corresponding [Event Handler](#event-handlers) based on the peer-set this message was received +on and dispatch via overseer. ### Network Event: `ViewUpdate` - Check that the new view is valid and note it as the most recent view update of the peer on this peer-set. -- Map a `NetworkBridgeEvent::PeerViewChange` onto the corresponding [Event Handler](#event-handlers) based on the peer-set this message was received on and dispatch via overseer. +- Map a `NetworkBridgeEvent::PeerViewChange` onto the corresponding [Event Handler](#event-handlers) based on the + peer-set this message was received on and dispatch via overseer. ### `ReportPeer` @@ -108,22 +133,23 @@ Map the message onto the corresponding [Event Handler](#event-handlers) based on ### `NewGossipTopology` -- Map all `AuthorityDiscoveryId`s to `PeerId`s and issue a corresponding `NetworkBridgeUpdate` - to all validation subsystems. +- Map all `AuthorityDiscoveryId`s to `PeerId`s and issue a corresponding `NetworkBridgeUpdate` to all validation + subsystems. ## Event Handlers -Network bridge event handlers are the intended recipients of particular network protocol messages. These are each a variant of a message to be sent via the overseer. +Network bridge event handlers are the intended recipients of particular network protocol messages. These are each a +variant of a message to be sent via the overseer. ### Validation V1 -* `ApprovalDistributionV1Message -> ApprovalDistributionMessage::NetworkBridgeUpdate` -* `BitfieldDistributionV1Message -> BitfieldDistributionMessage::NetworkBridgeUpdate` -* `StatementDistributionV1Message -> StatementDistributionMessage::NetworkBridgeUpdate` +- `ApprovalDistributionV1Message -> ApprovalDistributionMessage::NetworkBridgeUpdate` +- `BitfieldDistributionV1Message -> BitfieldDistributionMessage::NetworkBridgeUpdate` +- `StatementDistributionV1Message -> StatementDistributionMessage::NetworkBridgeUpdate` ### Collation V1 -* `CollatorProtocolV1Message -> CollatorProtocolMessage::NetworkBridgeUpdate` +- `CollatorProtocolV1Message -> CollatorProtocolMessage::NetworkBridgeUpdate` [NBM]: ../../types/overseer-protocol.md#network-bridge-message [AppD]: ../../types/overseer-protocol.md#approval-distribution-message diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/provisioner.md b/polkadot/roadmap/implementers-guide/src/node/utility/provisioner.md index a3998cabba6c..0b4fe6a45873 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/provisioner.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/provisioner.md @@ -1,28 +1,43 @@ # Provisioner -Relay chain block authorship authority is governed by BABE and is beyond the scope of the Overseer and the rest of the subsystems. That said, ultimately the block author needs to select a set of backable parachain candidates and other consensus data, and assemble a block from them. This subsystem is responsible for providing the necessary data to all potential block authors. +Relay chain block authorship authority is governed by BABE and is beyond the scope of the Overseer and the rest of the +subsystems. That said, ultimately the block author needs to select a set of backable parachain candidates and other +consensus data, and assemble a block from them. This subsystem is responsible for providing the necessary data to all +potential block authors. ## Provisionable Data -There are several distinct types of provisionable data, but they share this property in common: all should eventually be included in a relay chain block. +There are several distinct types of provisionable data, but they share this property in common: all should eventually be +included in a relay chain block. ### Backed Candidates -The block author can choose 0 or 1 backed parachain candidates per parachain; the only constraint is that each backable candidate has the appropriate relay parent. However, the choice of a backed candidate must be the block author's. The provisioner subsystem is how those block authors make this choice in practice. +The block author can choose 0 or 1 backed parachain candidates per parachain; the only constraint is that each backable +candidate has the appropriate relay parent. However, the choice of a backed candidate must be the block author's. The +provisioner subsystem is how those block authors make this choice in practice. ### Signed Bitfields -[Signed bitfields](../../types/availability.md#signed-availability-bitfield) are attestations from a particular validator about which candidates it believes are available. Those will only be provided on fresh leaves. +[Signed bitfields](../../types/availability.md#signed-availability-bitfield) are attestations from a particular +validator about which candidates it believes are available. Those will only be provided on fresh leaves. ### Misbehavior Reports -Misbehavior reports are self-contained proofs of misbehavior by a validator or group of validators. For example, it is very easy to verify a double-voting misbehavior report: the report contains two votes signed by the same key, advocating different outcomes. Concretely, misbehavior reports become inherents which cause dots to be slashed. +Misbehavior reports are self-contained proofs of misbehavior by a validator or group of validators. For example, it is +very easy to verify a double-voting misbehavior report: the report contains two votes signed by the same key, advocating +different outcomes. Concretely, misbehavior reports become inherents which cause dots to be slashed. -Note that there is no mechanism in place which forces a block author to include a misbehavior report which it doesn't like, for example if it would be slashed by such a report. The chain's defense against this is to have a relatively long slash period, such that it's likely to encounter an honest author before the slash period expires. +Note that there is no mechanism in place which forces a block author to include a misbehavior report which it doesn't +like, for example if it would be slashed by such a report. The chain's defense against this is to have a relatively long +slash period, such that it's likely to encounter an honest author before the slash period expires. ### Dispute Inherent -The dispute inherent is similar to a misbehavior report in that it is an attestation of misbehavior on the part of a validator or group of validators. Unlike a misbehavior report, it is not self-contained: resolution requires coordinated action by several validators. The canonical example of a dispute inherent involves an approval checker discovering that a set of validators has improperly approved an invalid parachain block: resolving this requires the entire validator set to re-validate the block, so that the minority can be slashed. +The dispute inherent is similar to a misbehavior report in that it is an attestation of misbehavior on the part of a +validator or group of validators. Unlike a misbehavior report, it is not self-contained: resolution requires coordinated +action by several validators. The canonical example of a dispute inherent involves an approval checker discovering that +a set of validators has improperly approved an invalid parachain block: resolving this requires the entire validator set +to re-validate the block, so that the minority can be slashed. Dispute resolution is complex and is explained in substantially more detail [here](../../runtime/disputes.md). @@ -34,58 +49,85 @@ The subsystem should maintain a set of handles to Block Authorship Provisioning - `ActiveLeavesUpdate`: - For each `activated` head: - - spawn a Block Authorship Provisioning iteration with the given relay parent, storing a bidirectional channel with that iteration. + - spawn a Block Authorship Provisioning iteration with the given relay parent, storing a bidirectional channel with + that iteration. - For each `deactivated` head: - terminate the Block Authorship Provisioning iteration for the given relay parent, if any. -- `Conclude`: Forward `Conclude` to all iterations, waiting a small amount of time for them to join, and then hard-exiting. +- `Conclude`: Forward `Conclude` to all iterations, waiting a small amount of time for them to join, and then + hard-exiting. ### On `ProvisionerMessage` -Forward the message to the appropriate Block Authorship Provisioning iteration, or discard if no appropriate iteration is currently active. +Forward the message to the appropriate Block Authorship Provisioning iteration, or discard if no appropriate iteration +is currently active. ### Per Provisioning Iteration -Input: [`ProvisionerMessage`](../../types/overseer-protocol.md#provisioner-message). Backed candidates come from the [Candidate Backing subsystem](../backing/candidate-backing.md), signed bitfields come from the [Bitfield Distribution subsystem](../availability/bitfield-distribution.md), and disputes come from the [Disputes Subsystem](../disputes/dispute-coordinator.md). Misbehavior reports are currently sent from the [Candidate Backing subsystem](../backing/candidate-backing.md) and contain the following misbehaviors: +Input: [`ProvisionerMessage`](../../types/overseer-protocol.md#provisioner-message). Backed candidates come from the +[Candidate Backing subsystem](../backing/candidate-backing.md), signed bitfields come from the [Bitfield Distribution +subsystem](../availability/bitfield-distribution.md), and disputes come from the [Disputes +Subsystem](../disputes/dispute-coordinator.md). Misbehavior reports are currently sent from the [Candidate Backing +subsystem](../backing/candidate-backing.md) and contain the following misbehaviors: 1. `Misbehavior::ValidityDoubleVote` 2. `Misbehavior::MultipleCandidates` 3. `Misbehavior::UnauthorizedStatement` 4. `Misbehavior::DoubleSign` -But we choose not to punish these forms of misbehavior for the time being. Risks from misbehavior are sufficiently mitigated at the protocol level via reputation changes. Punitive actions here may become desirable enough to dedicate time to in the future. +But we choose not to punish these forms of misbehavior for the time being. Risks from misbehavior are sufficiently +mitigated at the protocol level via reputation changes. Punitive actions here may become desirable enough to dedicate +time to in the future. At initialization, this subsystem has no outputs. -Block authors request the inherent data they should use for constructing the inherent in the block which contains parachain execution information. +Block authors request the inherent data they should use for constructing the inherent in the block which contains +parachain execution information. ## Block Production -When a validator is selected by BABE to author a block, it becomes a block producer. The provisioner is the subsystem best suited to choosing which specific backed candidates and availability bitfields should be assembled into the block. To engage this functionality, a `ProvisionerMessage::RequestInherentData` is sent; the response is a [`ParaInherentData`](../../types/runtime.md#parainherentdata). Each relay chain block backs at most one backable parachain block candidate per parachain. Additionally no further block candidate can be backed until the previous one either gets declared available or expired. If bitfields indicate that candidate A, predecessor of B, should be declared available, then B can be backed in the same relay block. Appropriate bitfields, as outlined in the section on [bitfield selection](#bitfield-selection), and any dispute statements should be attached as well. +When a validator is selected by BABE to author a block, it becomes a block producer. The provisioner is the subsystem +best suited to choosing which specific backed candidates and availability bitfields should be assembled into the block. +To engage this functionality, a `ProvisionerMessage::RequestInherentData` is sent; the response is a +[`ParaInherentData`](../../types/runtime.md#parainherentdata). Each relay chain block backs at most one backable +parachain block candidate per parachain. Additionally no further block candidate can be backed until the previous one +either gets declared available or expired. If bitfields indicate that candidate A, predecessor of B, should be declared +available, then B can be backed in the same relay block. Appropriate bitfields, as outlined in the section on [bitfield +selection](#bitfield-selection), and any dispute statements should be attached as well. ### Bitfield Selection -Our goal with respect to bitfields is simple: maximize availability. However, it's not quite as simple as always including all bitfields; there are constraints which still need to be met: +Our goal with respect to bitfields is simple: maximize availability. However, it's not quite as simple as always +including all bitfields; there are constraints which still need to be met: - not more than one bitfield per validator - each 1 bit must correspond to an occupied core -Beyond that, a semi-arbitrary selection policy is fine. In order to meet the goal of maximizing availability, a heuristic of picking the bitfield with the greatest number of 1 bits set in the event of conflict is useful. +Beyond that, a semi-arbitrary selection policy is fine. In order to meet the goal of maximizing availability, a +heuristic of picking the bitfield with the greatest number of 1 bits set in the event of conflict is useful. ### Dispute Statement Selection -This is the point at which the block author provides further votes to active disputes or initiates new disputes in the runtime state. +This is the point at which the block author provides further votes to active disputes or initiates new disputes in the +runtime state. -The block-authoring logic of the runtime has an extra step between handling the inherent-data and producing the actual inherent call, which we assume performs the work of filtering out disputes which are not relevant to the on-chain state. Backing votes are always kept in the dispute statement set. This ensures we punish the maximum number of misbehaving backers. +The block-authoring logic of the runtime has an extra step between handling the inherent-data and producing the actual +inherent call, which we assume performs the work of filtering out disputes which are not relevant to the on-chain state. +Backing votes are always kept in the dispute statement set. This ensures we punish the maximum number of misbehaving +backers. To select disputes: -- Issue a `DisputeCoordinatorMessage::RecentDisputes` message and wait for the response. This is a set of all disputes in recent sessions which we are aware of. +- Issue a `DisputeCoordinatorMessage::RecentDisputes` message and wait for the response. This is a set of all disputes + in recent sessions which we are aware of. ### Determining Bitfield Availability -An occupied core has a `CoreAvailability` bitfield. We also have a list of `SignedAvailabilityBitfield`s. We need to determine from these whether or not a core at a particular index has become available. +An occupied core has a `CoreAvailability` bitfield. We also have a list of `SignedAvailabilityBitfield`s. We need to +determine from these whether or not a core at a particular index has become available. -The key insight required is that `CoreAvailability` is transverse to the `SignedAvailabilityBitfield`s: if we conceptualize the list of bitfields as many rows, each bit of which is its own column, then `CoreAvailability` for a given core index is the vertical slice of bits in the set at that index. +The key insight required is that `CoreAvailability` is transverse to the `SignedAvailabilityBitfield`s: if we +conceptualize the list of bitfields as many rows, each bit of which is its own column, then `CoreAvailability` for a +given core index is the vertical slice of bits in the set at that index. To compute bitfield availability, then: @@ -97,16 +139,22 @@ To compute bitfield availability, then: ### Candidate Selection: Prospective Parachains Mode -The state of the provisioner `PerRelayParent` tracks an important setting, `ProspectiveParachainsMode`. This setting determines which backable candidate selection method the provisioner uses. +The state of the provisioner `PerRelayParent` tracks an important setting, `ProspectiveParachainsMode`. This setting +determines which backable candidate selection method the provisioner uses. -`ProspectiveParachainsMode::Disabled` - The provisioner uses its own internal legacy candidate selection. -`ProspectiveParachainsMode::Enabled` - The provisioner requests that [prospective parachains](../backing/prospective-parachains.md) provide selected candidates. +`ProspectiveParachainsMode::Disabled` - The provisioner uses its own internal legacy candidate selection. +`ProspectiveParachainsMode::Enabled` - The provisioner requests that [prospective +parachains](../backing/prospective-parachains.md) provide selected candidates. -Candidates selected with `ProspectiveParachainsMode::Enabled` are able to benefit from the increased block production time asynchronous backing allows. For this reason all Polkadot protocol networks will eventually use prospective parachains candidate selection. Then legacy candidate selection will be removed as obsolete. +Candidates selected with `ProspectiveParachainsMode::Enabled` are able to benefit from the increased block production +time asynchronous backing allows. For this reason all Polkadot protocol networks will eventually use prospective +parachains candidate selection. Then legacy candidate selection will be removed as obsolete. ### Prospective Parachains Candidate Selection -The goal of candidate selection is to determine which cores are free, and then to the degree possible, pick a candidate appropriate to each free core. In prospective parachains candidate selection the provisioner handles the former process while [prospective parachains](../backing/prospective-parachains.md) handles the latter. +The goal of candidate selection is to determine which cores are free, and then to the degree possible, pick a candidate +appropriate to each free core. In prospective parachains candidate selection the provisioner handles the former process +while [prospective parachains](../backing/prospective-parachains.md) handles the latter. To select backable candidates: @@ -116,32 +164,50 @@ To select backable candidates: - The core is unscheduled and doesn’t need to be provisioned with a candidate - On `CoreState::Scheduled` - The core is unoccupied and scheduled to accept a backed block for a particular `para_id`. - - The provisioner requests a backable candidate from [prospective parachains](../backing/prospective-parachains.md) with the desired relay parent, the core’s scheduled `para_id`, and an empty required path. + - The provisioner requests a backable candidate from [prospective parachains](../backing/prospective-parachains.md) + with the desired relay parent, the core’s scheduled `para_id`, and an empty required path. - On `CoreState::Occupied` - - The availability core is occupied by a parachain block candidate pending availability. A further candidate need not be provided by the provisioner unless the core will be vacated this block. This is the case when either bitfields indicate the current core occupant has been made available or a timeout is reached. + - The availability core is occupied by a parachain block candidate pending availability. A further candidate need + not be provided by the provisioner unless the core will be vacated this block. This is the case when either + bitfields indicate the current core occupant has been made available or a timeout is reached. - If `bitfields_indicate_availability` - - If `Some(scheduled_core) = occupied_core.next_up_on_available`, the core will be vacated and in need of a provisioned candidate. The provisioner requests a backable candidate from [prospective parachains](../backing/prospective-parachains.md) with the core’s scheduled `para_id` and a required path with one entry. This entry corresponds to the parablock candidate previously occupying this core, which was made available and can be built upon even though it hasn’t been seen as included in a relay chain block yet. See the Required Path section below for more detail. - - If `occupied_core.next_up_on_available` is `None`, then the core being vacated is unscheduled and doesn’t need to be provisioned with a candidate. + - If `Some(scheduled_core) = occupied_core.next_up_on_available`, the core will be vacated and in need of a + provisioned candidate. The provisioner requests a backable candidate from [prospective + parachains](../backing/prospective-parachains.md) with the core’s scheduled `para_id` and a required path with + one entry. This entry corresponds to the parablock candidate previously occupying this core, which was made + available and can be built upon even though it hasn’t been seen as included in a relay chain block yet. See the + Required Path section below for more detail. + - If `occupied_core.next_up_on_available` is `None`, then the core being vacated is unscheduled and doesn’t need + to be provisioned with a candidate. - Else-if `occupied_core.time_out_at == block_number` - - If `Some(scheduled_core) = occupied_core.next_up_on_timeout`, the core will be vacated and in need of a provisioned candidate. A candidate is requested in exactly the same way as with `CoreState::Scheduled`. - - Else the core being vacated is unscheduled and doesn’t need to be provisioned with a candidate -The end result of this process is a vector of `CandidateHash`s, sorted in order of their core index. + - If `Some(scheduled_core) = occupied_core.next_up_on_timeout`, the core will be vacated and in need of a + provisioned candidate. A candidate is requested in exactly the same way as with `CoreState::Scheduled`. + - Else the core being vacated is unscheduled and doesn’t need to be provisioned with a candidate The end result of +this process is a vector of `CandidateHash`s, sorted in order of their core index. #### Required Path -Required path is a parameter for `ProspectiveParachainsMessage::GetBackableCandidate`, which the provisioner sends in candidate selection. +Required path is a parameter for `ProspectiveParachainsMessage::GetBackableCandidate`, which the provisioner sends in +candidate selection. -An empty required path indicates that the requested candidate should be a direct child of the most recently included parablock for the given `para_id` as of the given relay parent. +An empty required path indicates that the requested candidate should be a direct child of the most recently included +parablock for the given `para_id` as of the given relay parent. -In contrast, a required path with one or more entries prompts [prospective parachains](../backing/prospective-parachains.md) to step forward through its fragment tree for the given `para_id` and relay parent until the desired parablock is reached. We then select a direct child of that parablock to pass to the provisioner. +In contrast, a required path with one or more entries prompts [prospective +parachains](../backing/prospective-parachains.md) to step forward through its fragment tree for the given `para_id` and +relay parent until the desired parablock is reached. We then select a direct child of that parablock to pass to the +provisioner. -The parablocks making up a required path do not need to have been previously seen as included in relay chain blocks. Thus the ability to provision backable candidates based on a required path effectively decouples backing from inclusion. +The parablocks making up a required path do not need to have been previously seen as included in relay chain blocks. +Thus the ability to provision backable candidates based on a required path effectively decouples backing from inclusion. -### Legacy Candidate Selection +### Legacy Candidate Selection -Legacy candidate selection takes place in the provisioner. Thus the provisioner needs to keep an up to date record of all [backed_candidates](../../types/backing.md#backed-candidate) `PerRelayParent` to pick from. +Legacy candidate selection takes place in the provisioner. Thus the provisioner needs to keep an up to date record of +all [backed_candidates](../../types/backing.md#backed-candidate) `PerRelayParent` to pick from. -The goal of candidate selection is to determine which cores are free, and then to the degree possible, pick a candidate appropriate to each free core. +The goal of candidate selection is to determine which cores are free, and then to the degree possible, pick a candidate +appropriate to each free core. To determine availability: @@ -149,38 +215,54 @@ To determine availability: - For each core state: - On `CoreState::Scheduled`, then we can make an `OccupiedCoreAssumption::Free`. - On `CoreState::Occupied`, then we may be able to make an assumption: - - If the bitfields indicate availability and there is a scheduled `next_up_on_available`, then we can make an `OccupiedCoreAssumption::Included`. - - If the bitfields do not indicate availability, and there is a scheduled `next_up_on_time_out`, and `occupied_core.time_out_at == block_number_under_production`, then we can make an `OccupiedCoreAssumption::TimedOut`. + - If the bitfields indicate availability and there is a scheduled `next_up_on_available`, then we can make an + `OccupiedCoreAssumption::Included`. + - If the bitfields do not indicate availability, and there is a scheduled `next_up_on_time_out`, and + `occupied_core.time_out_at == block_number_under_production`, then we can make an + `OccupiedCoreAssumption::TimedOut`. - If we did not make an `OccupiedCoreAssumption`, then continue on to the next core. - - Now compute the core's `validation_data_hash`: get the `PersistedValidationData` from the runtime, given the known `ParaId` and `OccupiedCoreAssumption`; + - Now compute the core's `validation_data_hash`: get the `PersistedValidationData` from the runtime, given the known + `ParaId` and `OccupiedCoreAssumption`; - Find an appropriate candidate for the core. - - There are two constraints: `backed_candidate.candidate.descriptor.para_id == scheduled_core.para_id && candidate.candidate.descriptor.validation_data_hash == computed_validation_data_hash`. - - In the event that more than one candidate meets the constraints, selection between the candidates is arbitrary. However, not more than one candidate can be selected per core. + - There are two constraints: `backed_candidate.candidate.descriptor.para_id == scheduled_core.para_id && + candidate.candidate.descriptor.validation_data_hash == computed_validation_data_hash`. + - In the event that more than one candidate meets the constraints, selection between the candidates is arbitrary. + However, not more than one candidate can be selected per core. The end result of this process is a vector of `CandidateHash`s, sorted in order of their core index. ### Retrieving Full `BackedCandidate`s for Selected Hashes -Legacy candidate selection and prospective parachains candidate selection both leave us with a vector of `CandidateHash`s. These are passed to the backing subsystem with `CandidateBackingMessage::GetBackedCandidates`. +Legacy candidate selection and prospective parachains candidate selection both leave us with a vector of +`CandidateHash`s. These are passed to the backing subsystem with `CandidateBackingMessage::GetBackedCandidates`. -The response is a vector of `BackedCandidate`s, sorted in order of their core index and ready to be provisioned to block authoring. The candidate selection and retrieval process should select at maximum one candidate which upgrades the runtime validation code. +The response is a vector of `BackedCandidate`s, sorted in order of their core index and ready to be provisioned to block +authoring. The candidate selection and retrieval process should select at maximum one candidate which upgrades the +runtime validation code. ## Glossary -- **Relay-parent:** - - A particular relay-chain block which serves as an anchor and reference point for processes and data which depend on relay-chain state. -- **Active Leaf:** - - A relay chain block which is the head of an active fork of the relay chain. +- **Relay-parent:** + - A particular relay-chain block which serves as an anchor and reference point for processes and data which depend on + relay-chain state. +- **Active Leaf:** + - A relay chain block which is the head of an active fork of the relay chain. - Block authorship provisioning jobs are spawned per active leaf and concluded for any leaves which become inactive. -- **Candidate Selection:** +- **Candidate Selection:** - The process by which the provisioner selects backable parachain block candidates to pass to block authoring. - - Two versions, prospective parachains candidate selection and legacy candidate selection. See their respective protocol sections for details. -- **Availability Core:** - - Often referred to simply as "cores", availability cores are an abstraction used for resource management. For the provisioner, availability cores are most relevant in that core states determine which `para_id`s to provision backable candidates for. - - For more on availability cores see [Scheduler Module: Availability Cores](../../runtime/scheduler.md#availability-cores) + - Two versions, prospective parachains candidate selection and legacy candidate selection. See their respective + protocol sections for details. +- **Availability Core:** + - Often referred to simply as "cores", availability cores are an abstraction used for resource management. For the + provisioner, availability cores are most relevant in that core states determine which `para_id`s to provision + backable candidates for. + - For more on availability cores see [Scheduler Module: Availability + Cores](../../runtime/scheduler.md#availability-cores) - **Availability Bitfield:** - - Often referred to simply as a "bitfield", an availability bitfield represents the view of parablock candidate availability from a particular validator's perspective. Each bit in the bitfield corresponds to a single [availability core](../../runtime-api/availability-cores.md). + - Often referred to simply as a "bitfield", an availability bitfield represents the view of parablock candidate + availability from a particular validator's perspective. Each bit in the bitfield corresponds to a single + [availability core](../../runtime-api/availability-cores.md). - For more on availability bitfields see [availability](../../types/availability.md) - **Backable vs. Backed:** - Note that we sometimes use "backed" to refer to candidates that are "backable", but not yet backed on chain. - - Backable means that a quorum of the candidate's assigned backing group have provided signed affirming statements. \ No newline at end of file + - Backable means that a quorum of the candidate's assigned backing group have provided signed affirming statements. diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md b/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md index 3cae12e65f33..b722bdc6539a 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md @@ -1,45 +1,70 @@ # PVF Pre-checker -The PVF pre-checker is a subsystem that is responsible for watching the relay chain for new PVFs that require pre-checking. Head over to [overview] for the PVF pre-checking process overview. +The PVF pre-checker is a subsystem that is responsible for watching the relay chain for new PVFs that require +pre-checking. Head over to [overview] for the PVF pre-checking process overview. ## Protocol -There is no dedicated input mechanism for PVF pre-checker. Instead, PVF pre-checker looks on the `ActiveLeavesUpdate` event stream for work. +There is no dedicated input mechanism for PVF pre-checker. Instead, PVF pre-checker looks on the `ActiveLeavesUpdate` +event stream for work. -This subsytem does not produce any output messages either. The subsystem will, however, send messages to the [Runtime API] subsystem to query for the pending PVFs and to submit votes. In addition to that, it will also communicate with [Candidate Validation] Subsystem to request PVF pre-check. +This subsytem does not produce any output messages either. The subsystem will, however, send messages to the [Runtime +API] subsystem to query for the pending PVFs and to submit votes. In addition to that, it will also communicate with +[Candidate Validation] Subsystem to request PVF pre-check. ## Functionality -If the node is running in a collator mode, this subsystem will be disabled. The PVF pre-checker subsystem keeps track of the PVFs that are relevant for the subsystem. +If the node is running in a collator mode, this subsystem will be disabled. The PVF pre-checker subsystem keeps track of +the PVFs that are relevant for the subsystem. -To be relevant for the subsystem, a PVF must be returned by the [`pvfs_require_precheck` runtime API][PVF pre-checking runtime API] in any of the active leaves. If the PVF is not present in any of the active leaves, it ceases to be relevant. +To be relevant for the subsystem, a PVF must be returned by the [`pvfs_require_precheck` runtime API][PVF pre-checking +runtime API] in any of the active leaves. If the PVF is not present in any of the active leaves, it ceases to be +relevant. -When a PVF just becomes relevant, the subsystem will send a message to the [Candidate Validation] subsystem asking for the pre-check. +When a PVF just becomes relevant, the subsystem will send a message to the [Candidate Validation] subsystem asking for +the pre-check. -Upon receving a message from the candidate-validation subsystem, the pre-checker will note down that the PVF has its judgement and will also sign and submit a [`PvfCheckStatement`][PvfCheckStatement] via the [`submit_pvf_check_statement` runtime API][PVF pre-checking runtime API]. In case, a judgement was received for a PVF that is no longer in view it is ignored. +Upon receving a message from the candidate-validation subsystem, the pre-checker will note down that the PVF has its +judgement and will also sign and submit a [`PvfCheckStatement`][PvfCheckStatement] via the [`submit_pvf_check_statement` +runtime API][PVF pre-checking runtime API]. In case, a judgement was received for a PVF that is no longer in view it is +ignored. -Since a vote only is valid during [one session][overview], the subsystem will have to resign and submit the statements for the new session. The new session is assumed to be started if at least one of the leaves has a greater session index that was previously observed in any of the leaves. +Since a vote only is valid during [one session][overview], the subsystem will have to resign and submit the statements +for the new session. The new session is assumed to be started if at least one of the leaves has a greater session index +that was previously observed in any of the leaves. -The subsystem tracks all the statements that it submitted within a session. If for some reason a PVF became irrelevant and then becomes relevant again, the subsystem will not submit a new statement for that PVF within the same session. +The subsystem tracks all the statements that it submitted within a session. If for some reason a PVF became irrelevant +and then becomes relevant again, the subsystem will not submit a new statement for that PVF within the same session. -If the node is not in the active validator set, it will still perform all the checks. However, it will only submit the check statements when the node is in the active validator set. +If the node is not in the active validator set, it will still perform all the checks. However, it will only submit the +check statements when the node is in the active validator set. ### Rejecting failed PVFs -It is possible that the candidate validation was not able to check the PVF, e.g. if it timed out. In that case, the PVF pre-checker will vote against it. This is considered safe, as there is no slashing for being on the wrong side of a pre-check vote. +It is possible that the candidate validation was not able to check the PVF, e.g. if it timed out. In that case, the PVF +pre-checker will vote against it. This is considered safe, as there is no slashing for being on the wrong side of a +pre-check vote. Rejecting instead of abstaining is better in several ways: 1. Conclusion is reached faster - we have actual votes, instead of relying on a timeout. -1. Being strict in pre-checking makes it safer to be more lenient in preparation errors afterwards. Hence we have more leeway in avoiding raising dubious disputes, without making things less secure. +1. Being strict in pre-checking makes it safer to be more lenient in preparation errors afterwards. Hence we have more + leeway in avoiding raising dubious disputes, without making things less secure. -Also, if we only abstain, an attacker can specially craft a PVF wasm blob so that it will fail on e.g. 50% of the validators. In that case a supermajority will never be reached and the vote will repeat multiple times, most likely with the same result (since all votes are cleared on a session change). This is avoided by rejecting failed PVFs, and by only requiring 1/3 of validators to reject a PVF to reach a decision. +Also, if we only abstain, an attacker can specially craft a PVF wasm blob so that it will fail on e.g. 50% of the +validators. In that case a supermajority will never be reached and the vote will repeat multiple times, most likely with +the same result (since all votes are cleared on a session change). This is avoided by rejecting failed PVFs, and by only +requiring 1/3 of validators to reject a PVF to reach a decision. ### Note on Disputes -Having a pre-checking phase allows us to make certain assumptions later when preparing the PVF for execution. If a runtime passed pre-checking, then we know that the runtime should be valid, and therefore any issue during preparation for execution can be assumed to be a local problem on the current node. +Having a pre-checking phase allows us to make certain assumptions later when preparing the PVF for execution. If a +runtime passed pre-checking, then we know that the runtime should be valid, and therefore any issue during preparation +for execution can be assumed to be a local problem on the current node. -For this reason, even deterministic preparation errors should not trigger disputes. And since we do not dispute as a result of the pre-checking phase, as stated above, it should be impossible for preparation in general to result in disputes. +For this reason, even deterministic preparation errors should not trigger disputes. And since we do not dispute as a +result of the pre-checking phase, as stated above, it should be impossible for preparation in general to result in +disputes. [overview]: ../../pvf-prechecking.md [Runtime API]: runtime-api.md diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/runtime-api.md b/polkadot/roadmap/implementers-guide/src/node/utility/runtime-api.md index 6271429c2666..b687bd5684c5 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/runtime-api.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/runtime-api.md @@ -1,6 +1,7 @@ # Runtime API -The Runtime API subsystem is responsible for providing a single point of access to runtime state data via a set of pre-determined queries. This prevents shared ownership of a blockchain client resource by providing +The Runtime API subsystem is responsible for providing a single point of access to runtime state data via a set of +pre-determined queries. This prevents shared ownership of a blockchain client resource by providing ## Protocol @@ -10,8 +11,11 @@ Output: None ## Functionality -On receipt of `RuntimeApiMessage::Request(relay_parent, request)`, answer the request using the post-state of the `relay_parent` provided and provide the response to the side-channel embedded within the request. +On receipt of `RuntimeApiMessage::Request(relay_parent, request)`, answer the request using the post-state of the +`relay_parent` provided and provide the response to the side-channel embedded within the request. ## Jobs -> TODO Don't limit requests based on parent hash, but limit caching. No caching should be done for any requests on `relay_parent`s that are not active based on `ActiveLeavesUpdate` messages. Maybe with some leeway for things that have just been stopped. +> TODO Don't limit requests based on parent hash, but limit caching. No caching should be done for any requests on +> `relay_parent`s that are not active based on `ActiveLeavesUpdate` messages. Maybe with some leeway for things that +> have just been stopped. diff --git a/polkadot/roadmap/implementers-guide/src/protocol-approval.md b/polkadot/roadmap/implementers-guide/src/protocol-approval.md index 693822ce0797..9ba7f6da1734 100644 --- a/polkadot/roadmap/implementers-guide/src/protocol-approval.md +++ b/polkadot/roadmap/implementers-guide/src/protocol-approval.md @@ -1,19 +1,39 @@ # Approval Process -The Approval Process is the mechanism by which the relay-chain ensures that only valid parablocks are finalized and that backing validators are held accountable for managing to get bad blocks included into the relay chain. +The Approval Process is the mechanism by which the relay-chain ensures that only valid parablocks are finalized and that +backing validators are held accountable for managing to get bad blocks included into the relay chain. -Having a parachain include a bad block into a fork of the relay-chain is not catastrophic as long as the block isn't finalized by the relay-chain's finality gadget, GRANDPA. If the block isn't finalized, that means that the fork of the relay-chain can be reverted in favor of another by means of a dynamic fork-choice rule which leads honest validators to ignore any forks containing that parablock. +Having a parachain include a bad block into a fork of the relay-chain is not catastrophic as long as the block isn't +finalized by the relay-chain's finality gadget, GRANDPA. If the block isn't finalized, that means that the fork of the +relay-chain can be reverted in favor of another by means of a dynamic fork-choice rule which leads honest validators to +ignore any forks containing that parablock. Dealing with a bad parablock proceeds in these stages: 1. Detection 2. Escalation 3. Consequences -First, the bad block must be detected by an honest party. Second, the honest party must escalate the bad block to be checked by all validators. And last, the correct consequences of a bad block must occur. The first consequence, as mentioned above, is to revert the chain so what full nodes perceive to be best no longer contains the bad parablock. The second consequence is to slash all malicious validators. Note that, if the chain containing the bad block is reverted, that the result of the dispute needs to be transplanted or at least transplantable to all other forks of the chain so that malicious validators are slashed in all possible histories. Phrased alternatively, there needs to be no possible relay-chain in which malicious validators get away cost-free. - -Accepting a parablock is the end result of having passed through the detection stage without dispute, or having passed through the escalation/dispute stage with a positive outcome. For this to work, we need the detection procedure to have the properties that enough honest validators are always selected to check the parablock and that they cannot be interfered with by an adversary. This needs to be balanced with the scaling concern of parachains in general: the easiest way to get the first property is to have everyone check everything, but that is clearly too heavy. So we also have a desired constraint on the other property that we have as few validators as possible check any particular parablock. Our assignment function is the method by which we select validators to do approval checks on parablocks. - -It often makes more sense to think of relay-chain blocks as having been approved or not as opposed to thinking about whether parablocks have been approved. A relay-chain block containing a single bad parablock needs to be reverted, and a relay-chain block that contains only approved parablocks can be called approved, as long as its parent relay-chain block is also approved. It is important that the validity of any particular relay-chain block depend on the validity of its ancestry, so we do not finalize a block which has a bad block in its ancestry. +First, the bad block must be detected by an honest party. Second, the honest party must escalate the bad block to be +checked by all validators. And last, the correct consequences of a bad block must occur. The first consequence, as +mentioned above, is to revert the chain so what full nodes perceive to be best no longer contains the bad parablock. The +second consequence is to slash all malicious validators. Note that, if the chain containing the bad block is reverted, +that the result of the dispute needs to be transplanted or at least transplantable to all other forks of the chain so +that malicious validators are slashed in all possible histories. Phrased alternatively, there needs to be no possible +relay-chain in which malicious validators get away cost-free. + +Accepting a parablock is the end result of having passed through the detection stage without dispute, or having passed +through the escalation/dispute stage with a positive outcome. For this to work, we need the detection procedure to have +the properties that enough honest validators are always selected to check the parablock and that they cannot be +interfered with by an adversary. This needs to be balanced with the scaling concern of parachains in general: the +easiest way to get the first property is to have everyone check everything, but that is clearly too heavy. So we also +have a desired constraint on the other property that we have as few validators as possible check any particular +parablock. Our assignment function is the method by which we select validators to do approval checks on parablocks. + +It often makes more sense to think of relay-chain blocks as having been approved or not as opposed to thinking about +whether parablocks have been approved. A relay-chain block containing a single bad parablock needs to be reverted, and a +relay-chain block that contains only approved parablocks can be called approved, as long as its parent relay-chain block +is also approved. It is important that the validity of any particular relay-chain block depend on the validity of its +ancestry, so we do not finalize a block which has a bad block in its ancestry. ```dot process Approval Process digraph { @@ -24,29 +44,56 @@ digraph { Approval has roughly two parts: -- **Assignments** determines which validators performs approval checks on which candidates. It ensures that each candidate receives enough random checkers, while reducing adversaries' odds for obtaining enough checkers, and limiting adversaries' foreknowledge. It tracks approval votes to identify when "no show" approval check takes suspiciously long, perhaps indicating the node being under attack, and assigns more checks in this case. It tracks relay chain equivocations to determine when adversaries possibly gained foreknowledge about assignments, and adds additional checks in this case. +- **Assignments** determines which validators performs approval checks on which candidates. It ensures that each + candidate receives enough random checkers, while reducing adversaries' odds for obtaining enough checkers, and + limiting adversaries' foreknowledge. It tracks approval votes to identify when "no show" approval check takes + suspiciously long, perhaps indicating the node being under attack, and assigns more checks in this case. It tracks + relay chain equivocations to determine when adversaries possibly gained foreknowledge about assignments, and adds + additional checks in this case. -- **Approval checks** listens to the assignments subsystem for outgoing assignment notices that we shall check specific candidates. It then performs these checks by first invoking the reconstruction subsystem to obtain the candidate, second invoking the candidate validity utility subsystem upon the candidate, and finally sending out an approval vote, or perhaps initiating a dispute. +- **Approval checks** listens to the assignments subsystem for outgoing assignment notices that we shall check specific + candidates. It then performs these checks by first invoking the reconstruction subsystem to obtain the candidate, + second invoking the candidate validity utility subsystem upon the candidate, and finally sending out an approval vote, + or perhaps initiating a dispute. -These both run first as off-chain consensus protocols using messages gossiped among all validators, and second as an on-chain record of this off-chain protocols' progress after the fact. We need the on-chain protocol to provide rewards for the off-chain protocol. +These both run first as off-chain consensus protocols using messages gossiped among all validators, and second as an +on-chain record of this off-chain protocols' progress after the fact. We need the on-chain protocol to provide rewards +for the off-chain protocol. -Approval requires two gossiped message types, assignment notices created by its assignments subsystem, and approval votes sent by our approval checks subsystem when authorized by the candidate validity utility subsystem. +Approval requires two gossiped message types, assignment notices created by its assignments subsystem, and approval +votes sent by our approval checks subsystem when authorized by the candidate validity utility subsystem. -### Approval keys +## Approval keys We need two separate keys for the approval subsystem: -- **Approval assignment keys** are sr25519/schnorrkel keys used only for the assignment criteria VRFs. We implicitly sign assignment notices with approval assignment keys by including their relay chain context and additional data in the VRF's extra message, but exclude these from its VRF input. +- **Approval assignment keys** are sr25519/schnorrkel keys used only for the assignment criteria VRFs. We implicitly + sign assignment notices with approval assignment keys by including their relay chain context and additional data in + the VRF's extra message, but exclude these from its VRF input. -- **Approval vote keys** would only sign off on candidate parablock validity and has no natural key type restrictions. There's no need for this to actually embody a new session key type. We just want to make a distinction between assignments and approvals, although distant future node configurations might favor separate roles. We re-use the same keys as are used for parachain backing in practice. +- **Approval vote keys** would only sign off on candidate parablock validity and has no natural key type restrictions. + There's no need for this to actually embody a new session key type. We just want to make a distinction between + assignments and approvals, although distant future node configurations might favor separate roles. We re-use the same + keys as are used for parachain backing in practice. -Approval vote keys could relatively easily be handled by some hardened signer tooling, perhaps even HSMs assuming we select ed25519 for approval vote keys. Approval assignment keys might or might not support hardened signer tooling, but doing so sounds far more complex. In fact, assignment keys determine only VRF outputs that determine approval checker assignments, for which they can only act or not act, so they cannot equivocate, lie, etc. and represent little if any slashing risk for validator operators. +Approval vote keys could relatively easily be handled by some hardened signer tooling, perhaps even HSMs assuming we +select ed25519 for approval vote keys. Approval assignment keys might or might not support hardened signer tooling, but +doing so sounds far more complex. In fact, assignment keys determine only VRF outputs that determine approval checker +assignments, for which they can only act or not act, so they cannot equivocate, lie, etc. and represent little if any +slashing risk for validator operators. -In future, we shall determine which among the several hardening techniques best benefits the network as a whole. We could provide a multi-process multi-machine architecture for validators, perhaps even reminiscent of GNUNet, or perhaps more resembling smart HSM tooling. We might instead design a system that more resembled full systems, like like Cosmos' sentry nodes. In either case, approval assignments might be handled by a slightly hardened machine, but not necessarily nearly as hardened as approval votes, but approval votes machines must similarly run foreign WASM code, which increases their risk, so assignments being separate sounds helpful. +In future, we shall determine which among the several hardening techniques best benefits the network as a whole. We +could provide a multi-process multi-machine architecture for validators, perhaps even reminiscent of GNUNet, or perhaps +more resembling smart HSM tooling. We might instead design a system that more resembled full systems, like like Cosmos' +sentry nodes. In either case, approval assignments might be handled by a slightly hardened machine, but not necessarily +nearly as hardened as approval votes, but approval votes machines must similarly run foreign WASM code, which increases +their risk, so assignments being separate sounds helpful. ## Assignments -Approval assignment determines on which candidate parachain blocks each validator performs approval checks. An approval session considers only one relay chain block and assigns only those candidates that relay chain block declares available. +Approval assignment determines on which candidate parachain blocks each validator performs approval checks. An approval +session considers only one relay chain block and assigns only those candidates that relay chain block declares +available. Assignment balances several concerns: @@ -54,149 +101,286 @@ Assignment balances several concerns: - ensures enough checkers, and - distributes assignments relatively equitably. -Assignees determine their own assignments to check specific candidates using two or three assignment criteria. Assignees never reveal their assignments until relevant, and gossip delays assignments sent early, which limits others' foreknowledge. Assignees learn their assignment only with the relay chain block. +Assignees determine their own assignments to check specific candidates using two or three assignment criteria. +Assignees never reveal their assignments until relevant, and gossip delays assignments sent early, which limits others' +foreknowledge. Assignees learn their assignment only with the relay chain block. -All criteria require the validator evaluate a verifiable random function (VRF) using their VRF secret key. All criteria input specific data called "stories" about the session's relay chain block, and output candidates to check and a precedence called a `DelayTranche`. +All criteria require the validator evaluate a verifiable random function (VRF) using their VRF secret key. All criteria +input specific data called "stories" about the session's relay chain block, and output candidates to check and a +precedence called a `DelayTranche`. -We liberate availability cores when their candidate becomes available of course, but one approval assignment criteria continues associating each candidate with the core number it occupied when it became available. +We liberate availability cores when their candidate becomes available of course, but one approval assignment criteria +continues associating each candidate with the core number it occupied when it became available. -Assignment operates in loosely timed rounds determined by this `DelayTranche`s, which proceed roughly 12 times faster than six second block production assuming half second gossip times. If a candidate `C` needs more approval checkers by the time we reach round `t` then any validators with an assignment to `C` in delay tranche `t` gossip their send assignment notice for `C`. We continue until all candidates have enough approval checkers assigned. We take entire tranches together if we do not yet have enough, so we expect strictly more than enough checkers. We also take later tranches if some checkers return their approval votes too slow (see no shows below). +Assignment operates in loosely timed rounds determined by this `DelayTranche`s, which proceed roughly 12 times faster +than six second block production assuming half second gossip times. If a candidate `C` needs more approval checkers by +the time we reach round `t` then any validators with an assignment to `C` in delay tranche `t` gossip their send +assignment notice for `C`. We continue until all candidates have enough approval checkers assigned. We take entire +tranches together if we do not yet have enough, so we expect strictly more than enough checkers. We also take later +tranches if some checkers return their approval votes too slow (see no shows below). -Assignment ensures validators check those relay chain blocks for which they have delay tranche zero aka the highest precedence, so that adversaries always face honest checkers equal to the expected number of assignments with delay tranche zero. +Assignment ensures validators check those relay chain blocks for which they have delay tranche zero aka the highest +precedence, so that adversaries always face honest checkers equal to the expected number of assignments with delay +tranche zero. -Among these criteria, the BABE VRF output provides the story for two, which reduces how frequently adversaries could position their own checkers. We have one criterion whose story consists of the candidate's block hash plus external knowledge that a relay chain equivocation exists with a conflicting candidate. It provides unforeseeable assignments when adversaries gain foreknowledge about the other two by committing an equivocation in relay chain block production. +Among these criteria, the BABE VRF output provides the story for two, which reduces how frequently adversaries could +position their own checkers. We have one criterion whose story consists of the candidate's block hash plus external +knowledge that a relay chain equivocation exists with a conflicting candidate. It provides unforeseeable assignments +when adversaries gain foreknowledge about the other two by committing an equivocation in relay chain block production. ## Announcements / Notices -We gossip assignment notices among nodes so that all validators know which validators should check each candidate, and if any candidate requires more checkers. +We gossip assignment notices among nodes so that all validators know which validators should check each candidate, and +if any candidate requires more checkers. -Assignment notices consist of a relay chain context given by a block hash, an assignment criteria, consisting of the criteria identifier and optionally a criteria specific field, an assignee identifier, and a VRF signature by the assignee, which itself consists of a VRF pre-output and a DLEQ proof. Its VRF input consists of the criteria, usually including a criteria specific field, and a "story" about its relay chain context block. +Assignment notices consist of a relay chain context given by a block hash, an assignment criteria, consisting of the +criteria identifier and optionally a criteria specific field, an assignee identifier, and a VRF signature by the +assignee, which itself consists of a VRF pre-output and a DLEQ proof. Its VRF input consists of the criteria, usually +including a criteria specific field, and a "story" about its relay chain context block. -We never include stories inside the gossip messages containing assignment notices, but require each validator reconstruct them. We never care about assignments in the disputes process, so this does not complicate remote disputes. +We never include stories inside the gossip messages containing assignment notices, but require each validator +reconstruct them. We never care about assignments in the disputes process, so this does not complicate remote disputes. -In a Schnorr VRF, there is an extra signed message distinct from this input, which we set to the relay chain block hash. As a result, assignment notices are self signing and can be "politely" gossiped without additional signatures, meaning between nodes who can compute the story from the relay chain context. In other words, if we cannot compute the story required by an assignment notice's VRF part then our self signing property fails and we cannot verify its origin. We could fix this with either another signature layer (64 bytes) or by including the VRF input point computed from the story (32 bytes), but doing so appears unhelpful. +In a Schnorr VRF, there is an extra signed message distinct from this input, which we set to the relay chain block hash. +As a result, assignment notices are self signing and can be "politely" gossiped without additional signatures, meaning +between nodes who can compute the story from the relay chain context. In other words, if we cannot compute the story +required by an assignment notice's VRF part then our self signing property fails and we cannot verify its origin. We +could fix this with either another signature layer (64 bytes) or by including the VRF input point computed from the +story (32 bytes), but doing so appears unhelpful. -Any validator could send their assignment notices and/or approval votes too early. We gossip the approval votes early because they represent a major commitment by the validator. We delay gossiping the assignment notices until they agree with our local clock however. We also impose a politeness condition that the recipient knows the relay chain context used by the assignment notice. +Any validator could send their assignment notices and/or approval votes too early. We gossip the approval votes early +because they represent a major commitment by the validator. We delay gossiping the assignment notices until they agree +with our local clock however. We also impose a politeness condition that the recipient knows the relay chain context +used by the assignment notice. ## Stories -We based assignment criteria upon two possible "stories" about the relay chain block `R` that included the candidate aka declared the candidate available. All stories have an output that attempts to minimize adversarial influence, which then acts as the VRF input for an assignment criteria. +We based assignment criteria upon two possible "stories" about the relay chain block `R` that included the candidate aka +declared the candidate available. All stories have an output that attempts to minimize adversarial influence, which +then acts as the VRF input for an assignment criteria. -We first have a `RelayVRFStory` that outputs the randomness from another VRF output produced by the relay chain block producer when creating `R`. Among honest nodes, only this one relay chain block producer who creates `R` knew the story in advance, and even they knew nothing two epochs previously. +We first have a `RelayVRFStory` that outputs the randomness from another VRF output produced by the relay chain block +producer when creating `R`. Among honest nodes, only this one relay chain block producer who creates `R` knew the story +in advance, and even they knew nothing two epochs previously. -In BABE, we create this value calling `schnorrkel::vrf::VRFInOut::make_bytes` with a context "A&V RC-VRF", with the `VRFInOut` coming from either the VRF that authorized block production for primary blocks, or else from the secondary block VRF for the secondary block type. +In BABE, we create this value calling `schnorrkel::vrf::VRFInOut::make_bytes` with a context "A&V RC-VRF", with the +`VRFInOut` coming from either the VRF that authorized block production for primary blocks, or else from the secondary +block VRF for the secondary block type. -In Sassafras, we shall always use the non-anonymized recycling VRF output, never the anonymized ring VRF that authorizes block production. We do not currently know if Sassafras shall have a separate schnorrkel key, but if it reuses its ring VRF key there is an equivalent `ring_vrf::VRFInOut::make_bytes`. +In Sassafras, we shall always use the non-anonymized recycling VRF output, never the anonymized ring VRF that authorizes +block production. We do not currently know if Sassafras shall have a separate schnorrkel key, but if it reuses its ring +VRF key there is an equivalent `ring_vrf::VRFInOut::make_bytes`. -We like that `RelayVRFStory` admits relatively few choices, but an adversary who equivocates in relay chain block production could learn assignments that depend upon the `RelayVRFStory` too early because the same relay chain VRF appears in multiple blocks. +We like that `RelayVRFStory` admits relatively few choices, but an adversary who equivocates in relay chain block +production could learn assignments that depend upon the `RelayVRFStory` too early because the same relay chain VRF +appears in multiple blocks. -We therefore provide a secondary `RelayEquivocationStory` that outputs the candidate's block hash, but only for candidate equivocations. We say a candidate `C` in `R` is an equivocation when there exists another relay chain block `R1` that equivocates for `R` in the sense that `R` and `R1` have the same `RelayVRFStory`, but `R` contains `C` and `R1` does not contain `C`. +We therefore provide a secondary `RelayEquivocationStory` that outputs the candidate's block hash, but only for +candidate equivocations. We say a candidate `C` in `R` is an equivocation when there exists another relay chain block +`R1` that equivocates for `R` in the sense that `R` and `R1` have the same `RelayVRFStory`, but `R` contains `C` and +`R1` does not contain `C`. -We want checkers for candidate equivocations that lie outside our preferred relay chain as well, which represents a slightly different usage for the assignments module, and might require more information in the gossip messages. +We want checkers for candidate equivocations that lie outside our preferred relay chain as well, which represents a +slightly different usage for the assignments module, and might require more information in the gossip messages. ## Assignment criteria -Assignment criteria compute actual assignments using stories and the validators' secret approval assignment key. Assignment criteria output a `Position` consisting of both a `ParaId` to be checked, as well as a precedence `DelayTranche` for when the assignment becomes valid. +Assignment criteria compute actual assignments using stories and the validators' secret approval assignment key. +Assignment criteria output a `Position` consisting of both a `ParaId` to be checked, as well as a precedence +`DelayTranche` for when the assignment becomes valid. -Assignment criteria come in three flavors, `RelayVRFModulo`, `RelayVRFDelay` and `RelayEquivocation`. Among these, both `RelayVRFModulo` and `RelayVRFDelay` run a VRF whose input is the output of a `RelayVRFStory`, while `RelayEquivocation` runs a VRF whose input is the output of a `RelayEquivocationStory`. +Assignment criteria come in three flavors, `RelayVRFModulo`, `RelayVRFDelay` and `RelayEquivocation`. Among these, both +`RelayVRFModulo` and `RelayVRFDelay` run a VRF whose input is the output of a `RelayVRFStory`, while `RelayEquivocation` +runs a VRF whose input is the output of a `RelayEquivocationStory`. Among these, we have two distinct VRF output computations: -`RelayVRFModulo` runs several distinct samples whose VRF input is the `RelayVRFStory` and the sample number. It computes the VRF output with `schnorrkel::vrf::VRFInOut::make_bytes` using the context "A&V Core", reduces this number modulo the number of availability cores, and outputs the candidate just declared available by, and included by aka leaving, that availability core. We drop any samples that return no candidate because no candidate was leaving the sampled availability core in this relay chain block. We choose three samples initially, but we could make polkadot more secure and efficient by increasing this to four or five, and reducing the backing checks accordingly. All successful `RelayVRFModulo` samples are assigned delay tranche zero. +`RelayVRFModulo` runs several distinct samples whose VRF input is the `RelayVRFStory` and the sample number. It +computes the VRF output with `schnorrkel::vrf::VRFInOut::make_bytes` using the context "A&V Core", reduces this number +modulo the number of availability cores, and outputs the candidate just declared available by, and included by aka +leaving, that availability core. We drop any samples that return no candidate because no candidate was leaving the +sampled availability core in this relay chain block. We choose three samples initially, but we could make Polkadot more +secure and efficient by increasing this to four or five, and reducing the backing checks accordingly. All successful +`RelayVRFModulo` samples are assigned delay tranche zero. -There is no sampling process for `RelayVRFDelay` and `RelayEquivocation`. We instead run them on specific candidates and they compute a delay from their VRF output. `RelayVRFDelay` runs for all candidates included under, aka declared available by, a relay chain block, and inputs the associated VRF output via `RelayVRFStory`. `RelayEquivocation` runs only on candidate block equivocations, and inputs their block hashes via the `RelayEquivocation` story. +There is no sampling process for `RelayVRFDelay` and `RelayEquivocation`. We instead run them on specific candidates +and they compute a delay from their VRF output. `RelayVRFDelay` runs for all candidates included under, aka declared +available by, a relay chain block, and inputs the associated VRF output via `RelayVRFStory`. `RelayEquivocation` runs +only on candidate block equivocations, and inputs their block hashes via the `RelayEquivocation` story. -`RelayVRFDelay` and `RelayEquivocation` both compute their output with `schnorrkel::vrf::VRFInOut::make_bytes` using the context "A&V Tranche" and reduce the result modulo `num_delay_tranches + zeroth_delay_tranche_width`, and consolidate results 0 through `zeroth_delay_tranche_width` to be 0. In this way, they ensure the zeroth delay tranche has `zeroth_delay_tranche_width+1` times as many assignments as any other tranche. +`RelayVRFDelay` and `RelayEquivocation` both compute their output with `schnorrkel::vrf::VRFInOut::make_bytes` using the +context "A&V Tranche" and reduce the result modulo `num_delay_tranches + zeroth_delay_tranche_width`, and consolidate +results 0 through `zeroth_delay_tranche_width` to be 0. In this way, they ensure the zeroth delay tranche has +`zeroth_delay_tranche_width+1` times as many assignments as any other tranche. -As future work (or TODO?), we should merge assignment notices with the same delay and story using `vrf_merge`. We cannot merge those with the same delay and different stories because `RelayEquivocationStory`s could change but `RelayVRFStory` never changes. +As future work (or TODO?), we should merge assignment notices with the same delay and story using `vrf_merge`. We +cannot merge those with the same delay and different stories because `RelayEquivocationStory`s could change but +`RelayVRFStory` never changes. ## Announcer and Watcher/Tracker -We track all validators' announced approval assignments for each candidate associated to each relay chain block, which tells us which validators were assigned to which candidates. +We track all validators' announced approval assignments for each candidate associated to each relay chain block, which +tells us which validators were assigned to which candidates. -We permit at most one assignment per candidate per story per validator, so one validator could be assigned under both the `RelayVRFDelay` and `RelayEquivocation` criteria, but not under both `RelayVRFModulo` and `RelayVRFDelay` criteria, since those both use the same story. We permit only one approval vote per candidate per validator, which counts for any applicable criteria. +We permit at most one assignment per candidate per story per validator, so one validator could be assigned under both +the `RelayVRFDelay` and `RelayEquivocation` criteria, but not under both `RelayVRFModulo` and `RelayVRFDelay` criteria, +since those both use the same story. We permit only one approval vote per candidate per validator, which counts for any +applicable criteria. -We announce, and start checking for, our own assignments when the delay of their tranche is reached, but only if the tracker says the assignee candidate requires more approval checkers. We never announce an assignment we believe unnecessary because early announcements gives an adversary information. All delay tranche zero assignments always get announced, which includes all `RelayVRFModulo` assignments. +We announce, and start checking for, our own assignments when the delay of their tranche is reached, but only if the +tracker says the assignee candidate requires more approval checkers. We never announce an assignment we believe +unnecessary because early announcements gives an adversary information. All delay tranche zero assignments always get +announced, which includes all `RelayVRFModulo` assignments. -In other words, if some candidate `C` needs more approval checkers by the time we reach round `t` then any validators with an assignment to `C` in delay tranche `t` gossip their send assignment notice for `C`, and begin reconstruction and validation for 'C. If however `C` reached enough assignments, then validators with later assignments skip announcing their assignments. +In other words, if some candidate `C` needs more approval checkers by the time we reach round `t` then any validators +with an assignment to `C` in delay tranche `t` gossip their send assignment notice for `C`, and begin reconstruction and +validation for 'C. If however `C` reached enough assignments, then validators with later assignments skip announcing +their assignments. -We continue until all candidates have enough approval checkers assigned. We never prioritize assignments within tranches and count all or no assignments for a given tranche together, so we often overshoot the target number of assigned approval checkers. +We continue until all candidates have enough approval checkers assigned. We never prioritize assignments within +tranches and count all or no assignments for a given tranche together, so we often overshoot the target number of +assigned approval checkers. ### No shows -We have a "no show" timeout longer than one relay chain slot, so at least 6 seconds, during which we expect approval checks should succeed in reconstructing the candidate block, in redoing its erasure coding to check the candidate receipt, and finally in rechecking the candidate block itself. +We have a "no show" timeout longer than one relay chain slot, so at least 6 seconds, during which we expect approval +checks should succeed in reconstructing the candidate block, in redoing its erasure coding to check the candidate +receipt, and finally in rechecking the candidate block itself. -We consider a validator a "no show" if they do not approve or dispute within this "no show" timeout from our receiving their assignment notice. We time this from our receipt of their assignment notice instead of our imagined real time for their tranche because otherwise receiving late assignment notices creates immediate "no shows" and unnecessary work. +We consider a validator a "no show" if they do not approve or dispute within this "no show" timeout from our receiving +their assignment notice. We time this from our receipt of their assignment notice instead of our imagined real time for +their tranche because otherwise receiving late assignment notices creates immediate "no shows" and unnecessary work. -We worry "no shows" represent a validator under denial of service attack, presumably to prevent it from reconstructing the candidate, but perhaps delaying it form gossiping a dispute too. We therefore always replace "no shows" by adding one entire extra delay tranche worth of validators, so such attacks always result in additional checkers. +We worry "no shows" represent a validator under denial of service attack, presumably to prevent it from reconstructing +the candidate, but perhaps delaying it form gossiping a dispute too. We therefore always replace "no shows" by adding +one entire extra delay tranche worth of validators, so such attacks always result in additional checkers. -As an example, imagine we need 20 checkers, but tranche zero produces only 14, and tranche one only 4, then we take all 5 from tranche two, and thus require 23 checkers for that candidate. If one checker Charlie from tranche one or two does not respond within say 8 seconds, then we add all 7 checkers from tranche three. If again one checker Cindy from tranche three does not respond within 8 seconds then we take all 3 checkers from tranche four. We now have 33 checkers working on the candidate, so this escalated quickly. +As an example, imagine we need 20 checkers, but tranche zero produces only 14, and tranche one only 4, then we take all +5 from tranche two, and thus require 23 checkers for that candidate. If one checker Charlie from tranche one or two +does not respond within say 8 seconds, then we add all 7 checkers from tranche three. If again one checker Cindy from +tranche three does not respond within 8 seconds then we take all 3 checkers from tranche four. We now have 33 checkers +working on the candidate, so this escalated quickly. -We escalated so quickly because we worried that Charlie and Cindy might be the only honest checkers assigned to that candidate. If therefore either Charlie or Cindy finally return an approval, then we can conclude approval, and abandon the checkers from tranche four. +We escalated so quickly because we worried that Charlie and Cindy might be the only honest checkers assigned to that +candidate. If therefore either Charlie or Cindy finally return an approval, then we can conclude approval, and abandon +the checkers from tranche four. -We therefore require the "no show" timeout to be longer than a relay chain slot so that we can witness "no shows" on-chain. We discuss below how this helps reward validators who replace "no shows". +We therefore require the "no show" timeout to be longer than a relay chain slot so that we can witness "no shows" +on-chain. We discuss below how this helps reward validators who replace "no shows". -We avoid slashing for "no shows" by itself, although being "no show" could enter into some computation that punishes repeated poor performance, presumably replaces `ImOnline`, and we could reduce their rewards and further rewards those who filled in. +We avoid slashing for "no shows" by itself, although being "no show" could enter into some computation that punishes +repeated poor performance, presumably replaces `ImOnline`, and we could reduce their rewards and further rewards those +who filled in. -As future work, we foresee expanding the "no show" scheme to anonymize the additional checkers, like by using assignment noticed with a new criteria that employs a ring VRF and then all validators providing cover by requesting a couple erasure coded pieces, but such anonymity scheme sound extremely complex and lie far beyond our initial functionality. +As future work, we foresee expanding the "no show" scheme to anonymize the additional checkers, like by using assignment +noticed with a new criteria that employs a ring VRF and then all validators providing cover by requesting a couple +erasure coded pieces, but such anonymity scheme sound extremely complex and lie far beyond our initial functionality. ## Assignment postponement -We expect validators could occasionally overloaded when they randomly acquire too many assignments. All these fluctuations amortize over multiple blocks fairly well, but this slows down finality. +We expect validators could occasionally overloaded when they randomly acquire too many assignments. All these +fluctuations amortize over multiple blocks fairly well, but this slows down finality. -We therefore permit validators to delay sending their assignment noticed intentionally. If nobody knows about their assignment then they avoid creating "no shows" and the workload progresses normally. +We therefore permit validators to delay sending their assignment noticed intentionally. If nobody knows about their +assignment then they avoid creating "no shows" and the workload progresses normally. -We strongly prefer if postponements come from tranches higher aka less important than zero because tranche zero checks provide somewhat more security. +We strongly prefer if postponements come from tranches higher aka less important than zero because tranche zero checks +provide somewhat more security. TODO: When? Is this optimal for the network? etc. ## On-chain verification -We should verify approval on-chain to reward approval checkers. We therefore require the "no show" timeout to be longer than a relay chain slot so that we can witness "no shows" on-chain, which helps with this goal. The major challenge with an on-chain record of the off-chain process is adversarial block producers who may either censor votes or publish votes to the chain which cause other votes to be ignored and unrewarded (reward stealing). +We should verify approval on-chain to reward approval checkers. We therefore require the "no show" timeout to be longer +than a relay chain slot so that we can witness "no shows" on-chain, which helps with this goal. The major challenge with +an on-chain record of the off-chain process is adversarial block producers who may either censor votes or publish votes +to the chain which cause other votes to be ignored and unrewarded (reward stealing). -In principle, all validators have some "tranche" at which they're assigned to the parachain candidate, which ensures we reach enough validators eventually. As noted above, we often retract "no shows" when the slow validator eventually shows up, so witnessing their initially being a "no show" helps manage rewards. +In principle, all validators have some "tranche" at which they're assigned to the parachain candidate, which ensures we +reach enough validators eventually. As noted above, we often retract "no shows" when the slow validator eventually +shows up, so witnessing their initially being a "no show" helps manage rewards. -We expect on-chain verification should work in two phases: We first record assignments notices and approval votes on-chain in relay chain block, doing the VRF or regular signature verification again in block verification, and inserting chain authenticated unsigned notes into the relay chain state that contain the checker, tranche, paraid, and relay block height for each assignment notice. We then later have another relay chain block that runs some "approved" intrinsic, which extract all these notes from the state and feeds them into our approval code. +We expect on-chain verification should work in two phases: We first record assignments notices and approval votes +on-chain in relay chain block, doing the VRF or regular signature verification again in block verification, and +inserting chain authenticated unsigned notes into the relay chain state that contain the checker, tranche, paraid, and +relay block height for each assignment notice. We then later have another relay chain block that runs some "approved" +intrinsic, which extract all these notes from the state and feeds them into our approval code. -We now encounter one niche concern in the interaction between postponement and on-chain verification: Any validator with a tranche zero (or other low) assignment could delay sending an assignment notice, like because they postponed their assigned tranche (which is allowed). If they later send this assignment notices right around finality time, then they race with this approved. intrinsic: If their announcement gets on-chain (also allowed), then yes it delays finality. If it does not get on-chain, then yes we've one announcement that the off-chain consensus system says is valid, but the chain ignores for being too slow. +We now encounter one niche concern in the interaction between postponement and on-chain verification: Any validator +with a tranche zero (or other low) assignment could delay sending an assignment notice, like because they postponed +their assigned tranche (which is allowed). If they later send this assignment notices right around finality time, then +they race with this approved. intrinsic: If their announcement gets on-chain (also allowed), then yes it delays +finality. If it does not get on-chain, then yes we've one announcement that the off-chain consensus system says is +valid, but the chain ignores for being too slow. -We need the chain to win in this case, but doing this requires imposing an annoyingly long overarching delay upon finality. We might explore limits on postponement too, but this sounds much harder. +We need the chain to win in this case, but doing this requires imposing an annoyingly long overarching delay upon +finality. We might explore limits on postponement too, but this sounds much harder. ## Parameters -We prefer doing approval checkers assignments under `RelayVRFModulo` as opposed to `RelayVRFDelay` because `RelayVRFModulo` avoids giving individual checkers too many assignments and tranche zero assignments benefit security the most. We suggest assigning at least 16 checkers under `RelayVRFModulo` although assignment levels have never been properly analyzed. +We prefer doing approval checkers assignments under `RelayVRFModulo` as opposed to `RelayVRFDelay` because +`RelayVRFModulo` avoids giving individual checkers too many assignments and tranche zero assignments benefit security +the most. We suggest assigning at least 16 checkers under `RelayVRFModulo` although assignment levels have never been +properly analyzed. -Our delay criteria `RelayVRFDelay` and `RelayEquivocation` both have two primary paramaters, expected checkers per tranche and the zeroth delay tranche width. +Our delay criteria `RelayVRFDelay` and `RelayEquivocation` both have two primary paramaters, expected checkers per +tranche and the zeroth delay tranche width. -We require expected checkers per tranche to be less than three because otherwise an adversary with 1/3 stake could force all nodes into checking all blocks. We strongly recommend expected checkers per tranche to be less than two, which helps avoid both accidental and intentional explosions. We also suggest expected checkers per tranche be larger than one, which helps prevent adversaries from predicting than advancing one tranche adds only their own validators. +We require expected checkers per tranche to be less than three because otherwise an adversary with 1/3 stake could force +all nodes into checking all blocks. We strongly recommend expected checkers per tranche to be less than two, which +helps avoid both accidental and intentional explosions. We also suggest expected checkers per tranche be larger than +one, which helps prevent adversaries from predicting than advancing one tranche adds only their own validators. -We improve security more with tranche zero assignments, so `RelayEquivocation` should consolidates its first several tranches into tranche zero. We describe this as the zeroth delay tranche width, which initially we set to 12 for `RelayEquivocation` and `1` for `RelayVRFDelay`. +We improve security more with tranche zero assignments, so `RelayEquivocation` should consolidates its first several +tranches into tranche zero. We describe this as the zeroth delay tranche width, which initially we set to 12 for +`RelayEquivocation` and `1` for `RelayVRFDelay`. ## Why VRFs? We do assignments with VRFs to give "enough" checkers some meaning beyond merely "expected" checkers: -We could specify a protocol that used only system randomness, which works because our strongest defense is the expected number of honest checkers who assign themselves. In this, adversaries could trivially flood their own blocks with their own checkers, so this strong defense becomes our only defense, and delay tranches become useless, so some blocks actually have zero approval checkers and possibly only one checker overall. +We could specify a protocol that used only system randomness, which works because our strongest defense is the expected +number of honest checkers who assign themselves. In this, adversaries could trivially flood their own blocks with their +own checkers, so this strong defense becomes our only defense, and delay tranches become useless, so some blocks +actually have zero approval checkers and possibly only one checker overall. -VRFs though require adversaries wait far longer between such attacks, which also helps against adversaries with little at stake because they compromised validators. VRFs raise user confidence that no such "drive by" attacks occurred because the delay tranche system ensure at least some minimum number of approval checkers. In this vein, VRFs permit reducing backing checks and increasing approval checks, which makes polkadot more efficient. +VRFs though require adversaries wait far longer between such attacks, which also helps against adversaries with little +at stake because they compromised validators. VRFs raise user confidence that no such "drive by" attacks occurred +because the delay tranche system ensure at least some minimum number of approval checkers. In this vein, VRFs permit +reducing backing checks and increasing approval checks, which makes Polkadot more efficient. ## Gossip -Any validator could send their assignment notices and/or approval votes too early. We gossip the approval votes because they represent a major commitment by the validator. We retain but delay gossiping the assignment notices until they agree with our local clock. +Any validator could send their assignment notices and/or approval votes too early. We gossip the approval votes because +they represent a major commitment by the validator. We retain but delay gossiping the assignment notices until they +agree with our local clock. -Assignment notices being gossiped too early might create a denial of service vector. If so, we might exploit the relative time scheme that synchronizes our clocks, which conceivably permits just dropping excessively early assignments. +Assignment notices being gossiped too early might create a denial of service vector. If so, we might exploit the +relative time scheme that synchronizes our clocks, which conceivably permits just dropping excessively early +assignments. ## Finality GRANDPA Voting Rule -The relay-chain requires validators to participate in GRANDPA. In GRANDPA, validators submit off-chain votes on what they believe to be the best block of the chain, and GRANDPA determines the common block contained by a supermajority of sub-chains. There are also additional constraints on what can be submitted based on results of previous rounds of voting. +The relay-chain requires validators to participate in GRANDPA. In GRANDPA, validators submit off-chain votes on what +they believe to be the best block of the chain, and GRANDPA determines the common block contained by a supermajority of +sub-chains. There are also additional constraints on what can be submitted based on results of previous rounds of +voting. -In order to avoid finalizing anything which has not received enough approval votes or is disputed, we will pair the approval protocol with an alteration to the GRANDPA voting strategy for honest nodes which causes them to vote only on chains where every parachain candidate within has been approved. Furthermore, the voting rule prevents voting for chains where there is any live dispute or any dispute has resolved to a candidate being invalid. +In order to avoid finalizing anything which has not received enough approval votes or is disputed, we will pair the +approval protocol with an alteration to the GRANDPA voting strategy for honest nodes which causes them to vote only on +chains where every parachain candidate within has been approved. Furthermore, the voting rule prevents voting for +chains where there is any live dispute or any dispute has resolved to a candidate being invalid. -Thus, the finalized relay-chain should contain only relay-chain blocks where a majority believe that every block within has been sufficiently approved. +Thus, the finalized relay-chain should contain only relay-chain blocks where a majority believe that every block within +has been sufficiently approved. ### Future work -We could consider additional gossip messages with which nodes claims "slow availability" and/or "slow candidate" to fine tune the assignments "no show" system, but long enough "no show" delays suffice probably. +We could consider additional gossip messages with which nodes claims "slow availability" and/or "slow candidate" to fine +tune the assignments "no show" system, but long enough "no show" delays suffice probably. -We shall develop more practical experience with UDP once the availability system works using direct UDP connections. In this, we should discover if reconstruction performs adequately with a complete graphs or -benefits from topology restrictions. At this point, an assignment notices could implicitly request pieces from a random 1/3rd, perhaps topology restricted, which saves one gossip round. If this preliminary fast reconstruction fails, then nodes' request alternative pieces directly. There is an interesting design space in how this overlaps with "slow availability" claims. +We shall develop more practical experience with UDP once the availability system works using direct UDP connections. In +this, we should discover if reconstruction performs adequately with a complete graphs or benefits from topology +restrictions. At this point, an assignment notices could implicitly request pieces from a random 1/3rd, perhaps +topology restricted, which saves one gossip round. If this preliminary fast reconstruction fails, then nodes' request +alternative pieces directly. There is an interesting design space in how this overlaps with "slow availability" claims. diff --git a/polkadot/roadmap/implementers-guide/src/protocol-chain-selection.md b/polkadot/roadmap/implementers-guide/src/protocol-chain-selection.md index dd066df43cdd..9f0262243bd2 100644 --- a/polkadot/roadmap/implementers-guide/src/protocol-chain-selection.md +++ b/polkadot/roadmap/implementers-guide/src/protocol-chain-selection.md @@ -1,12 +1,21 @@ # Chain Selection -Chain selection processes in blockchains are used for the purpose of selecting blocks to build on and finalize. It is important for these processes to be consistent among nodes and resilient to a maximum proportion of malicious nodes which do not obey the chain selection process. +Chain selection processes in blockchains are used for the purpose of selecting blocks to build on and finalize. It is +important for these processes to be consistent among nodes and resilient to a maximum proportion of malicious nodes +which do not obey the chain selection process. -The parachain host uses both a block authoring system and a finality gadget. The chain selection strategy of the parachain host involves two key components: a _leaf-selection_ rule and a set of _finality constraints_. When it's a validator's turn to author on a block, they are expected to select the best block via the leaf-selection rule to build on top of. When a validator is participating in finality, there is a minimum block which can be voted on, which is usually the finalized block. The validator should select the best chain according to the leaf-selection rule and subsequently apply the finality constraints to arrive at the actual vote cast by that validator. +The parachain host uses both a block authoring system and a finality gadget. The chain selection strategy of the +parachain host involves two key components: a _leaf-selection_ rule and a set of _finality constraints_. When it's a +validator's turn to author on a block, they are expected to select the best block via the leaf-selection rule to build +on top of. When a validator is participating in finality, there is a minimum block which can be voted on, which is +usually the finalized block. The validator should select the best chain according to the leaf-selection rule and +subsequently apply the finality constraints to arrive at the actual vote cast by that validator. -Before diving into the particularities of the leaf-selection rule and the finality constraints, it's important to discuss the goals that these components are meant to achieve. For this it is useful to create the definitions of _viable_ and _finalizable_ blocks. +Before diving into the particularities of the leaf-selection rule and the finality constraints, it's important to +discuss the goals that these components are meant to achieve. For this it is useful to create the definitions of +_viable_ and _finalizable_ blocks. -### Property Definitions +## Property Definitions A block is considered **viable** when all of the following hold: 1. It is or descends from the finalized block @@ -32,17 +41,27 @@ A block is considered **finalizable** when all of the following hold: 4. It is either finalized or includes no candidates which have unresolved disputes or have lost a dispute. -### The leaf-selection rule +## The leaf-selection rule -We assume that every block has an implicit weight or score which can be used to compare blocks. In BABE, this is determined by the number of primary slots included in the chain. In PoW, this is the chain with either the most work or GHOST weight. +We assume that every block has an implicit weight or score which can be used to compare blocks. In BABE, this is +determined by the number of primary slots included in the chain. In PoW, this is the chain with either the most work or +GHOST weight. -The leaf-selection rule based on our definitions above is simple: we take the maximum-scoring viable leaf we are aware of. In the case of a tie we select the one with a lower lexicographical block hash. +The leaf-selection rule based on our definitions above is simple: we take the maximum-scoring viable leaf we are aware +of. In the case of a tie we select the one with a lower lexicographical block hash. -### The best-chain-containing rule +## The best-chain-containing rule -Finality gadgets, as mentioned above, will often impose an additional requirement to vote on a chain containing a specific block, known as the **required** block. Although this is typically the most recently finalized block, it is possible that it may be a block that is unfinalized. When receiving such a request: +Finality gadgets, as mentioned above, will often impose an additional requirement to vote on a chain containing a +specific block, known as the **required** block. Although this is typically the most recently finalized block, it is +possible that it may be a block that is unfinalized. When receiving such a request: 1. If the required block is the best finalized block, then select the best viable leaf. -2. If the required block is unfinalized and non-viable, then select the required block and go no further. This is likely an indication that something bad will be finalized in the network, which will never happen when approvals & disputes are functioning correctly. Nevertheless we account for the case here. -3. If the required block is unfinalized and viable, then iterate over the viable leaves in descending order by score and select the first one which contains the required block in its chain. Backwards iteration is a simple way to check this, but if unfinalized chains grow long then Merkle Mountain-Ranges will most likely be more efficient. - -Once selecting a leaf, the chain should be constrained to the maximum of the required block or the highest **finalizable** ancestor. +2. If the required block is unfinalized and non-viable, then select the required block and go no further. This is likely + an indication that something bad will be finalized in the network, which will never happen when approvals & disputes + are functioning correctly. Nevertheless we account for the case here. +3. If the required block is unfinalized and viable, then iterate over the viable leaves in descending order by score and + select the first one which contains the required block in its chain. Backwards iteration is a simple way to check + this, but if unfinalized chains grow long then Merkle Mountain-Ranges will most likely be more efficient. + +Once selecting a leaf, the chain should be constrained to the maximum of the required block or the highest +**finalizable** ancestor. diff --git a/polkadot/roadmap/implementers-guide/src/protocol-disputes.md b/polkadot/roadmap/implementers-guide/src/protocol-disputes.md index ebbc534f1992..2a4082cc07f9 100644 --- a/polkadot/roadmap/implementers-guide/src/protocol-disputes.md +++ b/polkadot/roadmap/implementers-guide/src/protocol-disputes.md @@ -4,14 +4,27 @@ Fast forward to [more detailed disputes requirements](./disputes-flow.md). ## Motivation and Background -All parachain blocks that end up in the finalized relay chain should be valid. This does not apply to blocks that are only backed, but not included. +All parachain blocks that end up in the finalized relay chain should be valid. This does not apply to blocks that are +only backed, but not included. We have two primary components for ensuring that nothing invalid ends up in the finalized relay chain: - * Approval Checking, as described [here](./protocol-approval.md) and implemented according to the [Approval Voting](node/approval/approval-voting.md) subsystem. This protocol can be shown to prevent invalid parachain blocks from making their way into the finalized relay chain as long as the amount of attempts are limited. - * Disputes, this protocol, which ensures that each attempt to include something bad is caught, and the offending validators are punished. -Disputes differ from backing and approval process (and can not be part of those) in that a dispute is independent of a particular fork, while both backing and approval operate on particular forks. This distinction is important! Approval voting stops, if an alternative fork which might not contain the currently approved candidate gets finalized. This is totally fine from the perspective of approval voting as its sole purpose is to make sure invalid blocks won't get finalized. For disputes on the other hand we have different requirements: Even though the "danger" is past and the adversaries were not able to get their invalid block approved, we still want them to get slashed for the attempt. Otherwise they just have been able to get a free try, but this is something we need to avoid in our security model, as it is based on the assumption that the probability of getting an invalid block finalized is very low and an attacker would get bankrupt before it could have tried often enough. - -Every dispute stems from a disagreement among two or more validators. If a bad actor creates a bad block, but the bad actor never distributes it to honest validators, then nobody will dispute it. Of course, such a situation is not even an attack on the network, so we don't need to worry about defending against it. + * Approval Checking, as described [here](./protocol-approval.md) and implemented according to the [Approval + Voting](node/approval/approval-voting.md) subsystem. This protocol can be shown to prevent invalid parachain blocks + from making their way into the finalized relay chain as long as the amount of attempts are limited. + * Disputes, this protocol, which ensures that each attempt to include something bad is caught, and the offending +validators are punished. Disputes differ from backing and approval process (and can not be part of those) in that a +dispute is independent of a particular fork, while both backing and approval operate on particular forks. This +distinction is important! Approval voting stops, if an alternative fork which might not contain the currently approved +candidate gets finalized. This is totally fine from the perspective of approval voting as its sole purpose is to make +sure invalid blocks won't get finalized. For disputes on the other hand we have different requirements: Even though the +"danger" is past and the adversaries were not able to get their invalid block approved, we still want them to get +slashed for the attempt. Otherwise they just have been able to get a free try, but this is something we need to avoid in +our security model, as it is based on the assumption that the probability of getting an invalid block finalized is very +low and an attacker would get bankrupt before it could have tried often enough. + +Every dispute stems from a disagreement among two or more validators. If a bad actor creates a bad block, but the bad +actor never distributes it to honest validators, then nobody will dispute it. Of course, such a situation is not even an +attack on the network, so we don't need to worry about defending against it. We are interested in identifying and deterring the following attack scenario: * A parablock included on a branch of the relay chain is bad @@ -20,48 +33,101 @@ We are also interested in identifying these additional scenarios: * A parablock backed on a branch of the relay chain is bad * A parablock seconded, but not backed on any branch of the relay chain, is bad. -Punishing misbehavior in the latter two scenarios doesn't effect our security guarantees and introduces substantial technical challenges as described in the `No Disputes for Non Included Candidates` section of [Dispute Coordinator](./node/disputes/dispute-coordinator.md). We therefore choose to punt on disputes in these cases, instead favoring the protocol simplicity resulting from only punishing in the first scenario. - -As covered in the [protocol overview](./protocol-overview.md), checking a parachain block requires 3 pieces of data: the parachain validation code, the [`AvailableData`](types/availability.md), and the [`CandidateReceipt`](types/candidate.md). The validation code is available on-chain, and published ahead of time, so that no two branches of the relay chain have diverging views of the validation code for a given parachain. Note that only for the first scenario, where the parablock has been included on a branch of the relay chain, is the data necessarily available. Thus, dispute processes should begin with an availability process to ensure availability of the `AvailableData`. This availability process will conclude quickly if the data is already available. If the data is not already available, then the initiator of the dispute must make it available. - -Disputes have both an on-chain and an off-chain component. Slashing and punishment is handled on-chain, so votes by validators on either side of the dispute must be placed on-chain. Furthermore, a dispute on one branch of the relay chain should be transposed to all other active branches of the relay chain. The fact that slashing occurs _in all histories_ is crucial for deterring attempts to attack the network. The attacker should not be able to escape with their funds because the network has moved on to another branch of the relay chain where no attack was attempted. - -In fact, this is why we introduce a distinction between _local_ and _remote_ disputes. We categorize disputes as either local or remote relative to any particular branch of the relay chain. Local disputes are about dealing with our first scenario, where a parablock has been included on the specific branch we are looking at. In these cases, the chain is corrupted all the way back to the point where the parablock was backed and must be discarded. However, as mentioned before, the dispute must propagate to all other branches of the relay chain. All other disputes are considered _remote_. For the on-chain component, when handling a dispute for a block which was not included in the current fork of the relay chain, it is impossible to discern between our attack scenarios. It is possible that the parablock was included somewhere, or backed somewhere, or wasn't backed anywhere. The on-chain component for handling these cases will be the same. +Punishing misbehavior in the latter two scenarios doesn't effect our security guarantees and introduces substantial +technical challenges as described in the `No Disputes for Non Included Candidates` section of [Dispute +Coordinator](./node/disputes/dispute-coordinator.md). We therefore choose to punt on disputes in these cases, instead +favoring the protocol simplicity resulting from only punishing in the first scenario. + +As covered in the [protocol overview](./protocol-overview.md), checking a parachain block requires 3 pieces of data: the +parachain validation code, the [`AvailableData`](types/availability.md), and the +[`CandidateReceipt`](types/candidate.md). The validation code is available on-chain, and published ahead of time, so +that no two branches of the relay chain have diverging views of the validation code for a given parachain. Note that +only for the first scenario, where the parablock has been included on a branch of the relay chain, is the data +necessarily available. Thus, dispute processes should begin with an availability process to ensure availability of the +`AvailableData`. This availability process will conclude quickly if the data is already available. If the data is not +already available, then the initiator of the dispute must make it available. + +Disputes have both an on-chain and an off-chain component. Slashing and punishment is handled on-chain, so votes by +validators on either side of the dispute must be placed on-chain. Furthermore, a dispute on one branch of the relay +chain should be transposed to all other active branches of the relay chain. The fact that slashing occurs _in all +histories_ is crucial for deterring attempts to attack the network. The attacker should not be able to escape with their +funds because the network has moved on to another branch of the relay chain where no attack was attempted. + +In fact, this is why we introduce a distinction between _local_ and _remote_ disputes. We categorize disputes as either +local or remote relative to any particular branch of the relay chain. Local disputes are about dealing with our first +scenario, where a parablock has been included on the specific branch we are looking at. In these cases, the chain is +corrupted all the way back to the point where the parablock was backed and must be discarded. However, as mentioned +before, the dispute must propagate to all other branches of the relay chain. All other disputes are considered _remote_. +For the on-chain component, when handling a dispute for a block which was not included in the current fork of the relay +chain, it is impossible to discern between our attack scenarios. It is possible that the parablock was included +somewhere, or backed somewhere, or wasn't backed anywhere. The on-chain component for handling these cases will be the +same. ## Initiation -Disputes are initiated by any validator who finds their opinion on the validity of a parablock in opposition to another issued statement. As all statements currently gathered by the relay chain imply validity, disputes will be initiated only by nodes which perceive that the parablock is bad. - -The initiation of a dispute begins off-chain. A validator signs a message indicating that it disputes the validity of the parablock and notifies all other validators, off-chain, of all of the statements it is aware of for the disputed parablock. These may be backing statements or approval-checking statements. It is worth noting that there is no special message type for initiating a dispute. It is the same message as is used to participate in a dispute and vote negatively. As such, there is no consensus required on who initiated a dispute, only on the fact that there is a dispute in-progress. - -In practice, the initiator of a dispute will be either one of the backers or one of the approval checkers for the parablock. If the result of execution is found to be invalid, the validator will initiate the dispute as described above. Furthermore, if the dispute occurs during the backing phase, the initiator must make the data available to other validators. If the dispute occurs during approval checking, the data is already available. - -Lastly, it is possible that for backing disputes, i.e. where the data is not already available among all validators, that an adversary may DoS the few parties who are checking the block to prevent them from distributing the data to other validators participating in the dispute process. Note that this can only occur pre-inclusion for any given parablock, so the downside of this attack is small and it is not security-critical to address these cases. However, we assume that the adversary can only prevent the validator from issuing messages for a limited amount of time. We also assume that there is a side-channel where the relay chain's governance mechanisms can trigger disputes by providing the full PoV and candidate receipt on-chain manually. +Disputes are initiated by any validator who finds their opinion on the validity of a parablock in opposition to another +issued statement. As all statements currently gathered by the relay chain imply validity, disputes will be initiated +only by nodes which perceive that the parablock is bad. + +The initiation of a dispute begins off-chain. A validator signs a message indicating that it disputes the validity of +the parablock and notifies all other validators, off-chain, of all of the statements it is aware of for the disputed +parablock. These may be backing statements or approval-checking statements. It is worth noting that there is no special +message type for initiating a dispute. It is the same message as is used to participate in a dispute and vote +negatively. As such, there is no consensus required on who initiated a dispute, only on the fact that there is a dispute +in-progress. + +In practice, the initiator of a dispute will be either one of the backers or one of the approval checkers for the +parablock. If the result of execution is found to be invalid, the validator will initiate the dispute as described +above. Furthermore, if the dispute occurs during the backing phase, the initiator must make the data available to other +validators. If the dispute occurs during approval checking, the data is already available. + +Lastly, it is possible that for backing disputes, i.e. where the data is not already available among all validators, +that an adversary may DoS the few parties who are checking the block to prevent them from distributing the data to other +validators participating in the dispute process. Note that this can only occur pre-inclusion for any given parablock, so +the downside of this attack is small and it is not security-critical to address these cases. However, we assume that the +adversary can only prevent the validator from issuing messages for a limited amount of time. We also assume that there +is a side-channel where the relay chain's governance mechanisms can trigger disputes by providing the full PoV and +candidate receipt on-chain manually. ## Dispute Participation -Once becoming aware of a dispute, it is the responsibility of all validators to participate in the dispute. Concretely, this means: - * Circulate all statements about the candidate that we are aware of - backing statements, approval checking statements, and dispute statements. +Once becoming aware of a dispute, it is the responsibility of all validators to participate in the dispute. Concretely, +this means: + * Circulate all statements about the candidate that we are aware of - backing statements, approval checking + statements, and dispute statements. * If we have already issued any type of statement about the candidate, go no further. - * Download the [`AvailableData`](types/availability.md). If possible, this should first be attempted from other dispute participants or backing validators, and then [(via erasure-coding)](node/availability/availability-recovery.md) from all validators. - * Extract the Validation Code from any recent relay chain block. Code is guaranteed to be kept available on-chain, so we don't need to download any particular fork of the chain. - * Execute the block under the validation code, using the `AvailableData`, and check that all outputs are correct, including the `erasure-root` of the [`CandidateReceipt`](types/candidate.md). + * Download the [`AvailableData`](types/availability.md). If possible, this should first be attempted from other + dispute participants or backing validators, and then [(via + erasure-coding)](node/availability/availability-recovery.md) from all validators. + * Extract the Validation Code from any recent relay chain block. Code is guaranteed to be kept available on-chain, so + we don't need to download any particular fork of the chain. + * Execute the block under the validation code, using the `AvailableData`, and check that all outputs are correct, + including the `erasure-root` of the [`CandidateReceipt`](types/candidate.md). * Issue a dispute participation statement to the effect of the validity of the candidate block. Disputes _conclude_ after ⅔ supermajority is reached in either direction. -The on-chain component of disputes can be initiated by providing any two conflicting votes and it also waits for a ⅔ supermajority on either side. The on-chain component also tracks which parablocks have already been disputed so the same parablock may only be disputed once on any particular branch of the relay chain. Lastly, it also tracks which blocks have been included on the current branch of the relay chain. When a dispute is initiated for a para, inclusion is halted for the para until the dispute concludes. +The on-chain component of disputes can be initiated by providing any two conflicting votes and it also waits for a ⅔ +supermajority on either side. The on-chain component also tracks which parablocks have already been disputed so the same +parablock may only be disputed once on any particular branch of the relay chain. Lastly, it also tracks which blocks +have been included on the current branch of the relay chain. When a dispute is initiated for a para, inclusion is halted +for the para until the dispute concludes. -The author of a relay chain block should initiate the on-chain component of disputes for all disputes which the chain is not aware of, and provide all statements to the on-chain component as well. This should all be done via _inherents_. +The author of a relay chain block should initiate the on-chain component of disputes for all disputes which the chain is +not aware of, and provide all statements to the on-chain component as well. This should all be done via _inherents_. Validators can learn about dispute statements in two ways: * Receiving them from other validators over gossip - * Scraping them from imported blocks of the relay chain. This is also used for validators to track other types of statements, such as backing statements. + * Scraping them from imported blocks of the relay chain. This is also used for validators to track other types of + statements, such as backing statements. -Validators are rewarded for providing statements to the chain as well as for participating in the dispute, on either side. However, the losing side of the dispute is slashed. +Validators are rewarded for providing statements to the chain as well as for participating in the dispute, on either +side. However, the losing side of the dispute is slashed. ## Dispute Conclusion -Disputes, roughly, are over when one side reaches a ⅔ supermajority. They may also never conclude without either side witnessing supermajority, which will only happen if the majority of validators are unable to vote for some reason. Furthermore, disputes on-chain will stay open for some fixed amount of time even after concluding, to accept new votes. +Disputes, roughly, are over when one side reaches a ⅔ supermajority. They may also never conclude without either side +witnessing supermajority, which will only happen if the majority of validators are unable to vote for some reason. +Furthermore, disputes on-chain will stay open for some fixed amount of time even after concluding, to accept new votes. Late votes, after the dispute already reached a ⅔ supermajority, must be rewarded (albeit a smaller amount) as well. diff --git a/polkadot/roadmap/implementers-guide/src/protocol-overview.md b/polkadot/roadmap/implementers-guide/src/protocol-overview.md index fa5a866e6121..96827e8c06bb 100644 --- a/polkadot/roadmap/implementers-guide/src/protocol-overview.md +++ b/polkadot/roadmap/implementers-guide/src/protocol-overview.md @@ -1,28 +1,61 @@ # Protocol Overview -This section aims to describe, at a high level, the actors and protocols involved in running parachains in Polkadot. Specifically, we describe how different actors communicate with each other, what data structures they keep both individually and collectively, and the high-level purpose on why they do these things. +This section aims to describe, at a high level, the actors and protocols involved in running parachains in Polkadot. +Specifically, we describe how different actors communicate with each other, what data structures they keep both +individually and collectively, and the high-level purpose on why they do these things. -Our top-level goal is to carry a parachain block from authoring to secure inclusion, and define a process which can be carried out repeatedly and in parallel for many different parachains to extend them over time. Understanding of the high-level approach taken here is important to provide context for the proposed architecture further on. The key parts of Polkadot relevant to this are the main Polkadot blockchain, known as the relay-chain, and the actors which provide security and inputs to this blockchain. +Our top-level goal is to carry a parachain block from authoring to secure inclusion, and define a process which can be +carried out repeatedly and in parallel for many different parachains to extend them over time. Understanding of the +high-level approach taken here is important to provide context for the proposed architecture further on. The key parts +of Polkadot relevant to this are the main Polkadot blockchain, known as the relay-chain, and the actors which provide +security and inputs to this blockchain. First, it's important to go over the main actors we have involved in this protocol. -1. Validators. These nodes are responsible for validating proposed parachain blocks. They do so by checking a Proof-of-Validity (PoV) of the block and ensuring that the PoV remains available. They put financial capital down as "skin in the game" which can be slashed (destroyed) if they are proven to have misvalidated. -1. Collators. These nodes are responsible for creating the Proofs-of-Validity that validators know how to check. Creating a PoV typically requires familiarity with the transaction format and block authoring rules of the parachain, as well as having access to the full state of the parachain. - -This implies a simple pipeline where collators send validators parachain blocks and their requisite PoV to check. Then, validators validate the block using the PoV, signing statements which describe either the positive or negative outcome, and with enough positive statements, the block can be noted on the relay-chain. Negative statements are not a veto but will lead to a dispute, with those on the wrong side being slashed. If another validator later detects that a validator or group of validators incorrectly signed a statement claiming a block was valid, then those validators will be _slashed_, with the checker receiving a bounty. - -However, there is a problem with this formulation. In order for another validator to check the previous group of validators' work after the fact, the PoV must remain _available_ so the other validator can fetch it in order to check the work. The PoVs are expected to be too large to include in the blockchain directly, so we require an alternate _data availability_ scheme which requires validators to prove that the inputs to their work will remain available, and so their work can be checked. Empirical tests tell us that many PoVs may be between 1 and 10MB during periods of heavy load. - -Here is a description of the Inclusion Pipeline: the path a parachain block (or parablock, for short) takes from creation to inclusion: +1. Validators. These nodes are responsible for validating proposed parachain blocks. They do so by checking a + Proof-of-Validity (PoV) of the block and ensuring that the PoV remains available. They put financial capital down as + "skin in the game" which can be slashed (destroyed) if they are proven to have misvalidated. +1. Collators. These nodes are responsible for creating the Proofs-of-Validity that validators know how to check. + Creating a PoV typically requires familiarity with the transaction format and block authoring rules of the parachain, + as well as having access to the full state of the parachain. + +This implies a simple pipeline where collators send validators parachain blocks and their requisite PoV to check. Then, +validators validate the block using the PoV, signing statements which describe either the positive or negative outcome, +and with enough positive statements, the block can be noted on the relay-chain. Negative statements are not a veto but +will lead to a dispute, with those on the wrong side being slashed. If another validator later detects that a validator +or group of validators incorrectly signed a statement claiming a block was valid, then those validators will be +_slashed_, with the checker receiving a bounty. + +However, there is a problem with this formulation. In order for another validator to check the previous group of +validators' work after the fact, the PoV must remain _available_ so the other validator can fetch it in order to check +the work. The PoVs are expected to be too large to include in the blockchain directly, so we require an alternate _data +availability_ scheme which requires validators to prove that the inputs to their work will remain available, and so +their work can be checked. Empirical tests tell us that many PoVs may be between 1 and 10MB during periods of heavy +load. + +Here is a description of the Inclusion Pipeline: the path a parachain block (or parablock, for short) takes from +creation to inclusion: 1. Validators are selected and assigned to parachains by the Validator Assignment routine. -1. A collator produces the parachain block, which is known as a parachain candidate or candidate, along with a PoV for the candidate. -1. The collator forwards the candidate and PoV to validators assigned to the same parachain via the [Collator Protocol](node/collators/collator-protocol.md). -1. The validators assigned to a parachain at a given point in time participate in the [Candidate Backing subsystem](node/backing/candidate-backing.md) to validate candidates that were put forward for validation. Candidates which gather enough signed validity statements from validators are considered "backable". Their backing is the set of signed validity statements. -1. A relay-chain block author, selected by BABE, can note up to one (1) backable candidate for each parachain to include in the relay-chain block alongside its backing. A backable candidate once included in the relay-chain is considered backed in that fork of the relay-chain. -1. Once backed in the relay-chain, the parachain candidate is considered to be "pending availability". It is not considered to be included as part of the parachain until it is proven available. -1. In the following relay-chain blocks, validators will participate in the [Availability Distribution subsystem](node/availability/availability-distribution.md) to ensure availability of the candidate. Information regarding the availability of the candidate will be noted in the subsequent relay-chain blocks. -1. Once the relay-chain state machine has enough information to consider the candidate's PoV as being available, the candidate is considered to be part of the parachain and is graduated to being a full parachain block, or parablock for short. +1. A collator produces the parachain block, which is known as a parachain candidate or candidate, along with a PoV for + the candidate. +1. The collator forwards the candidate and PoV to validators assigned to the same parachain via the [Collator + Protocol](node/collators/collator-protocol.md). +1. The validators assigned to a parachain at a given point in time participate in the [Candidate Backing + subsystem](node/backing/candidate-backing.md) to validate candidates that were put forward for validation. Candidates + which gather enough signed validity statements from validators are considered "backable". Their backing is the set of + signed validity statements. +1. A relay-chain block author, selected by BABE, can note up to one (1) backable candidate for each parachain to include + in the relay-chain block alongside its backing. A backable candidate once included in the relay-chain is considered + backed in that fork of the relay-chain. +1. Once backed in the relay-chain, the parachain candidate is considered to be "pending availability". It is not + considered to be included as part of the parachain until it is proven available. +1. In the following relay-chain blocks, validators will participate in the [Availability Distribution + subsystem](node/availability/availability-distribution.md) to ensure availability of the candidate. Information + regarding the availability of the candidate will be noted in the subsequent relay-chain blocks. +1. Once the relay-chain state machine has enough information to consider the candidate's PoV as being available, the + candidate is considered to be part of the parachain and is graduated to being a full parachain block, or parablock + for short. Note that the candidate can fail to be included in any of the following ways: @@ -31,21 +64,47 @@ Note that the candidate can fail to be included in any of the following ways: - The candidate is not selected by a relay-chain block author to be included in the relay chain - The candidate's PoV is not considered as available within a timeout and is discarded from the relay chain. -This process can be divided further down. Steps 2 & 3 relate to the work of the collator in collating and distributing the candidate to validators via the Collation Distribution Subsystem. Steps 3 & 4 relate to the work of the validators in the Candidate Backing Subsystem and the block author (itself a validator) to include the block into the relay chain. Steps 6, 7, and 8 correspond to the logic of the relay-chain state-machine (otherwise known as the Runtime) used to fully incorporate the block into the chain. Step 7 requires further work on the validators' parts to participate in the Availability Distribution Subsystem and include that information into the relay chain for step 8 to be fully realized. - -This brings us to the second part of the process. Once a parablock is considered available and part of the parachain, it is still "pending approval". At this stage in the pipeline, the parablock has been backed by a majority of validators in the group assigned to that parachain, and its data has been guaranteed available by the set of validators as a whole. Once it's considered available, the host will even begin to accept children of that block. At this point, we can consider the parablock as having been tentatively included in the parachain, although more confirmations are desired. However, the validators in the parachain-group (known as the "Parachain Validators" for that parachain) are sampled from a validator set which contains some proportion of byzantine, or arbitrarily malicious members. This implies that the Parachain Validators for some parachain may be majority-dishonest, which means that (secondary) approval checks must be done on the block before it can be considered approved. This is necessary only because the Parachain Validators for a given parachain are sampled from an overall validator set which is assumed to be up to <1/3 dishonest - meaning that there is a chance to randomly sample Parachain Validators for a parachain that are majority or fully dishonest and can back a candidate wrongly. The Approval Process allows us to detect such misbehavior after-the-fact without allocating more Parachain Validators and reducing the throughput of the system. A parablock's failure to pass the approval process will invalidate the block as well as all of its descendants. However, only the validators who backed the block in question will be slashed, not the validators who backed the descendants. +This process can be divided further down. Steps 2 & 3 relate to the work of the collator in collating and distributing +the candidate to validators via the Collation Distribution Subsystem. Steps 3 & 4 relate to the work of the validators +in the Candidate Backing Subsystem and the block author (itself a validator) to include the block into the relay chain. +Steps 6, 7, and 8 correspond to the logic of the relay-chain state-machine (otherwise known as the Runtime) used to +fully incorporate the block into the chain. Step 7 requires further work on the validators' parts to participate in the +Availability Distribution Subsystem and include that information into the relay chain for step 8 to be fully realized. + +This brings us to the second part of the process. Once a parablock is considered available and part of the parachain, it +is still "pending approval". At this stage in the pipeline, the parablock has been backed by a majority of validators in +the group assigned to that parachain, and its data has been guaranteed available by the set of validators as a whole. +Once it's considered available, the host will even begin to accept children of that block. At this point, we can +consider the parablock as having been tentatively included in the parachain, although more confirmations are desired. +However, the validators in the parachain-group (known as the "Parachain Validators" for that parachain) are sampled from +a validator set which contains some proportion of byzantine, or arbitrarily malicious members. This implies that the +Parachain Validators for some parachain may be majority-dishonest, which means that (secondary) approval checks must be +done on the block before it can be considered approved. This is necessary only because the Parachain Validators for a +given parachain are sampled from an overall validator set which is assumed to be up to <1/3 dishonest - meaning that +there is a chance to randomly sample Parachain Validators for a parachain that are majority or fully dishonest and can +back a candidate wrongly. The Approval Process allows us to detect such misbehavior after-the-fact without allocating +more Parachain Validators and reducing the throughput of the system. A parablock's failure to pass the approval process +will invalidate the block as well as all of its descendants. However, only the validators who backed the block in +question will be slashed, not the validators who backed the descendants. The Approval Process, at a glance, looks like this: -1. Parablocks that have been included by the Inclusion Pipeline are pending approval for a time-window known as the secondary checking window. +1. Parablocks that have been included by the Inclusion Pipeline are pending approval for a time-window known as the + secondary checking window. 1. During the secondary-checking window, validators randomly self-select to perform secondary checks on the parablock. -1. These validators, known in this context as secondary checkers, acquire the parablock and its PoV, and re-run the validation function. -1. The secondary checkers gossip the result of their checks. Contradictory results lead to escalation, where all validators are required to check the block. The validators on the losing side of the dispute are slashed. -1. At the end of the Approval Process, the parablock is either Approved or it is rejected. More on the rejection process later. +1. These validators, known in this context as secondary checkers, acquire the parablock and its PoV, and re-run the + validation function. +1. The secondary checkers gossip the result of their checks. Contradictory results lead to escalation, where all + validators are required to check the block. The validators on the losing side of the dispute are slashed. +1. At the end of the Approval Process, the parablock is either Approved or it is rejected. More on the rejection process + later. -More information on the Approval Process can be found in the dedicated section on [Approval](protocol-approval.md). More information on Disputes can be found in the dedicated section on [Disputes](protocol-disputes.md). +More information on the Approval Process can be found in the dedicated section on [Approval](protocol-approval.md). More +information on Disputes can be found in the dedicated section on [Disputes](protocol-disputes.md). -These two pipelines sum up the sequence of events necessary to extend and acquire full security on a Parablock. Note that the Inclusion Pipeline must conclude for a specific parachain before a new block can be accepted on that parachain. After inclusion, the Approval Process kicks off, and can be running for many parachain blocks at once. +These two pipelines sum up the sequence of events necessary to extend and acquire full security on a Parablock. Note +that the Inclusion Pipeline must conclude for a specific parachain before a new block can be accepted on that parachain. +After inclusion, the Approval Process kicks off, and can be running for many parachain blocks at once. Reiterating the lifecycle of a candidate: @@ -129,8 +188,11 @@ digraph { The diagram above shows the happy path of a block from (1) Candidate to the (7) Approved state. -It is also important to take note of the fact that the relay-chain is extended by BABE, which is a forkful algorithm. That means that different block authors can be chosen at the same time, and may not be building on the same block parent. Furthermore, the set of validators is not fixed, nor is the set of parachains. And even with the same set of validators and parachains, the validators' assignments to parachains is flexible. This means that the architecture proposed in the next chapters must deal with the variability and multiplicity of the network state. - +It is also important to take note of the fact that the relay-chain is extended by BABE, which is a forkful algorithm. +That means that different block authors can be chosen at the same time, and may not be building on the same block +parent. Furthermore, the set of validators is not fixed, nor is the set of parachains. And even with the same set of +validators and parachains, the validators' assignments to parachains is flexible. This means that the architecture +proposed in the next chapters must deal with the variability and multiplicity of the network state. ```dot process digraph { @@ -169,7 +231,9 @@ digraph { } ``` -In this example, group 1 has received block C while the others have not due to network asynchrony. Now, a validator from group 2 may be able to build another block on top of B, called `C'`. Assume that afterwards, some validators become aware of both C and `C'`, while others remain only aware of one. +In this example, group 1 has received block C while the others have not due to network asynchrony. Now, a validator from +group 2 may be able to build another block on top of B, called `C'`. Assume that afterwards, some validators become +aware of both C and `C'`, while others remain only aware of one. ```dot process digraph { @@ -216,4 +280,7 @@ digraph { } ``` -Those validators that are aware of many competing heads must be aware of the work happening on each one. They may contribute to some or a full extent on both. It is possible that due to network asynchrony two forks may grow in parallel for some time, although in the absence of an adversarial network this is unlikely in the case where there are validators who are aware of both chain heads. +Those validators that are aware of many competing heads must be aware of the work happening on each one. They may +contribute to some or a full extent on both. It is possible that due to network asynchrony two forks may grow in +parallel for some time, although in the absence of an adversarial network this is unlikely in the case where there are +validators who are aware of both chain heads. diff --git a/polkadot/roadmap/implementers-guide/src/pvf-prechecking.md b/polkadot/roadmap/implementers-guide/src/pvf-prechecking.md index 91cc8f9b6a20..44ddb0abbe08 100644 --- a/polkadot/roadmap/implementers-guide/src/pvf-prechecking.md +++ b/polkadot/roadmap/implementers-guide/src/pvf-prechecking.md @@ -2,20 +2,28 @@ ## Motivation -Parachains' validation function is described by a wasm module that we refer to as a PVF. Since a PVF is a wasm module the typical way of executing it is to compile it to machine code. +Parachains' validation function is described by a wasm module that we refer to as a PVF. Since a PVF is a wasm module +the typical way of executing it is to compile it to machine code. -Typically an optimizing compiler consists of algorithms that are able to optimize the resulting machine code heavily. However, while those algorithms perform quite well for a typical wasm code produced by standard toolchains (e.g. rustc/LLVM), those algorithms can be abused to consume a lot of resources. Moreover, since those algorithms are rather complex there is a lot of room for a bug that can crash the compiler. +Typically an optimizing compiler consists of algorithms that are able to optimize the resulting machine code heavily. +However, while those algorithms perform quite well for a typical wasm code produced by standard toolchains (e.g. +rustc/LLVM), those algorithms can be abused to consume a lot of resources. Moreover, since those algorithms are rather +complex there is a lot of room for a bug that can crash the compiler. -If compilation of a Parachain Validation Function (PVF) takes too long or uses too much memory, this can leave a node in limbo as to whether a candidate of that parachain is valid or not. +If compilation of a Parachain Validation Function (PVF) takes too long or uses too much memory, this can leave a node in +limbo as to whether a candidate of that parachain is valid or not. -The amount of time that a PVF takes to compile is a subjective resource limit and as such PVFs may be maliciously crafted so that there is e.g. a 50/50 split of validators which can and cannot compile and execute the PVF. +The amount of time that a PVF takes to compile is a subjective resource limit and as such PVFs may be maliciously +crafted so that there is e.g. a 50/50 split of validators which can and cannot compile and execute the PVF. This has the following implications: - In backing, inclusion may be slow due to backing groups being unable to execute the block - In approval checking, there may be many no-shows, leading to slow finality -- In disputes, neither side may reach supermajority. Nobody will get slashed and the chain will not be reverted or finalized. +- In disputes, neither side may reach supermajority. Nobody will get slashed and the chain will not be reverted or + finalized. -As a result of this issue we need a fairly hard guarantee that the PVFs of registered parachains/threads can be compiled within a reasonable amount of time. +As a result of this issue we need a fairly hard guarantee that the PVFs of registered parachains/threads can be compiled +within a reasonable amount of time. ## Solution @@ -23,9 +31,12 @@ The problem is solved by having a pre-checking process. ### Pre-checking -Pre-checking mostly consists of attempting to prepare (compile) the PVF WASM blob. We use more strict limits (e.g. timeouts) here compared to regular preparation for execution. This way errors during preparation later are likely unrelated to the PVF itself, as it already passed pre-checking. We can treat such errors as local node issues. +Pre-checking mostly consists of attempting to prepare (compile) the PVF WASM blob. We use more strict limits (e.g. +timeouts) here compared to regular preparation for execution. This way errors during preparation later are likely +unrelated to the PVF itself, as it already passed pre-checking. We can treat such errors as local node issues. -We also have an additional step where we attempt to instantiate the WASM runtime without running it. This is unrelated to preparation so we don't time it, but it does help us catch more issues. +We also have an additional step where we attempt to instantiate the WASM runtime without running it. This is unrelated +to preparation so we don't time it, but it does help us catch more issues. ### Protocol @@ -34,27 +45,41 @@ Pre-checking is run when a new validation code is included in the chain. A new P - A new parachain is registered. - An existing parachain signalled an upgrade of its validation code. -Before any of those operations finish, the PVF pre-checking vote is initiated. The PVF pre-checking vote is identified by the PVF code hash that is being voted on. If there is already PVF pre-checking process running, then no -new PVF pre-checking vote will be started. Instead, the operation just subscribes to the existing vote. +Before any of those operations finish, the PVF pre-checking vote is initiated. The PVF pre-checking vote is identified +by the PVF code hash that is being voted on. If there is already PVF pre-checking process running, then no new PVF +pre-checking vote will be started. Instead, the operation just subscribes to the existing vote. -The pre-checking vote can be concluded either by obtaining a threshold of votes for a decision, or if it expires. The threshold to accept is a supermajority of 2/3 of validators. We reject once a supermajority is no longer possible. +The pre-checking vote can be concluded either by obtaining a threshold of votes for a decision, or if it expires. The +threshold to accept is a supermajority of 2/3 of validators. We reject once a supermajority is no longer possible. -Each validator checks the list of PVFs available for voting. The vote is binary, i.e. accept or reject a given PVF. As soon as the threshold of votes are collected for one of the sides of the vote, the voting is concluded in that direction and the effects of the voting are enacted. +Each validator checks the list of PVFs available for voting. The vote is binary, i.e. accept or reject a given PVF. As +soon as the threshold of votes are collected for one of the sides of the vote, the voting is concluded in that direction +and the effects of the voting are enacted. -Only validators from the active set can participate in the vote. The set of active validators can change each session. That's why we reset the votes each session. A voting that observed a certain number of sessions will be rejected. +Only validators from the active set can participate in the vote. The set of active validators can change each session. +That's why we reset the votes each session. A voting that observed a certain number of sessions will be rejected. The effects of the PVF accepting depend on the operations requested it: -1. All onboardings subscribed to the approved PVF pre-checking process will get scheduled and after passing 2 session boundaries they will be onboarded. -1. All upgrades subscribed to the approved PVF pre-checking process will get scheduled very similarly to the existing process. Upgrades with pre-checking are really the same process that is just delayed by the time required for pre-checking voting. In case of instant approval the mechanism is exactly the same. +1. All onboardings subscribed to the approved PVF pre-checking process will get scheduled and after passing 2 session + boundaries they will be onboarded. +1. All upgrades subscribed to the approved PVF pre-checking process will get scheduled very similarly to the existing + process. Upgrades with pre-checking are really the same process that is just delayed by the time required for + pre-checking voting. In case of instant approval the mechanism is exactly the same. -In case PVF pre-checking process was concluded with rejection, then all the operations that are subscribed to the rejected PVF pre-checking process will be processed as follows. That is, onboarding or upgrading will be cancelled. +In case PVF pre-checking process was concluded with rejection, then all the operations that are subscribed to the +rejected PVF pre-checking process will be processed as follows. That is, onboarding or upgrading will be cancelled. The logic described above is implemented by the [paras] module. ### Subsystem -On the node-side, there is a PVF pre-checking [subsystem][pvf-prechecker-subsystem] that scans the chain for new PVFs via using [runtime APIs][pvf-runtime-api]. Upon finding a new PVF, the subsystem will initiate a PVF pre-checking request and wait for the result. Whenever the result is obtained, the subsystem will use the [runtime API][pvf-runtime-api] to submit a vote for the PVF. The vote is an unsigned transaction. The vote will be distributed via the gossip similarly to a normal transaction. Eventually a block producer will include the vote into the block where it will be handled by the [runtime][paras]. +On the node-side, there is a PVF pre-checking [subsystem][pvf-prechecker-subsystem] that scans the chain for new PVFs +via using [runtime APIs][pvf-runtime-api]. Upon finding a new PVF, the subsystem will initiate a PVF pre-checking +request and wait for the result. Whenever the result is obtained, the subsystem will use the [runtime +API][pvf-runtime-api] to submit a vote for the PVF. The vote is an unsigned transaction. The vote will be distributed +via the gossip similarly to a normal transaction. Eventually a block producer will include the vote into the block where +it will be handled by the [runtime][paras]. ## Summary @@ -62,11 +87,15 @@ Parachains' validation function is described by a wasm module that we refer to a In order to make the PVF usable for candidate validation it has to be registered on-chain. -As part of the registration process, it has to go through pre-checking. Pre-checking is a game of attempting preparation and additional checks, and reporting the results back on-chain. +As part of the registration process, it has to go through pre-checking. Pre-checking is a game of attempting preparation +and additional checks, and reporting the results back on-chain. -We define preparation as a process that: validates the consistency of the wasm binary (aka prevalidation) and the compilation of the wasm module into machine code (referred to as an artifact). +We define preparation as a process that: validates the consistency of the wasm binary (aka prevalidation) and the +compilation of the wasm module into machine code (referred to as an artifact). -Besides pre-checking, preparation can also be triggered by execution, since a compiled artifact is needed for the execution. If an artifact already exists, execution will skip preparation. If it does do preparation, execution uses a more lenient timeout than preparation, to avoid the situation where honest validators fail on valid, pre-checked PVFs. +Besides pre-checking, preparation can also be triggered by execution, since a compiled artifact is needed for the +execution. If an artifact already exists, execution will skip preparation. If it does do preparation, execution uses a +more lenient timeout than preparation, to avoid the situation where honest validators fail on valid, pre-checked PVFs. [paras]: runtime/paras.md [pvf-runtime-api]: runtime-api/pvf-prechecking.md diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/README.md b/polkadot/roadmap/implementers-guide/src/runtime-api/README.md index 740ffd38ccee..d74100f2e262 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/README.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/README.md @@ -2,9 +2,16 @@ Runtime APIs are the means by which the node-side code extracts information from the state of the runtime. -Every block in the relay-chain contains a *state root* which is the root hash of a state trie encapsulating all storage of runtime modules after execution of the block. This is a cryptographic commitment to a unique state. We use the terminology of accessing the *state at* a block to refer accessing the state referred to by the state root of that block. +Every block in the relay-chain contains a *state root* which is the root hash of a state trie encapsulating all storage +of runtime modules after execution of the block. This is a cryptographic commitment to a unique state. We use the +terminology of accessing the *state at* a block to refer accessing the state referred to by the state root of that +block. -Although Runtime APIs are often used for simple storage access, they are actually empowered to do arbitrary computation. The implementation of the Runtime APIs lives within the Runtime as Wasm code and exposes `extern` functions that can be invoked with arguments and have a return value. Runtime APIs have access to a variety of host functions, which are contextual functions provided by the Wasm execution context, that allow it to carry out many different types of behaviors. +Although Runtime APIs are often used for simple storage access, they are actually empowered to do arbitrary computation. +The implementation of the Runtime APIs lives within the Runtime as Wasm code and exposes `extern` functions that can be +invoked with arguments and have a return value. Runtime APIs have access to a variety of host functions, which are +contextual functions provided by the Wasm execution context, that allow it to carry out many different types of +behaviors. Abilities provided by host functions includes: @@ -14,16 +21,25 @@ Abilities provided by host functions includes: * Optimized versions of cryptographic functions * More -So it is clear that Runtime APIs are a versatile and powerful tool to leverage the state of the chain. In general, we will use Runtime APIs for these purposes: +So it is clear that Runtime APIs are a versatile and powerful tool to leverage the state of the chain. In general, we +will use Runtime APIs for these purposes: * Access of a storage item * Access of a bundle of related storage items * Deriving a value from storage based on arguments * Submitting misbehavior reports -More broadly, we have the goal of using Runtime APIs to write Node-side code that fulfills the requirements set by the Runtime. In particular, the constraints set forth by the [Scheduler](../runtime/scheduler.md) and [Inclusion](../runtime/inclusion.md) modules. These modules are responsible for advancing paras with a two-phase protocol where validators are first chosen to validate and back a candidate and then required to ensure availability of referenced data. In the second phase, validators are meant to attest to those para-candidates that they have their availability chunk for. As the Node-side code needs to generate the inputs into these two phases, the runtime API needs to transmit information from the runtime that is aware of the Availability Cores model instantiated by the Scheduler and Inclusion modules. +More broadly, we have the goal of using Runtime APIs to write Node-side code that fulfills the requirements set by the +Runtime. In particular, the constraints set forth by the [Scheduler](../runtime/scheduler.md) and +[Inclusion](../runtime/inclusion.md) modules. These modules are responsible for advancing paras with a two-phase +protocol where validators are first chosen to validate and back a candidate and then required to ensure availability of +referenced data. In the second phase, validators are meant to attest to those para-candidates that they have their +availability chunk for. As the Node-side code needs to generate the inputs into these two phases, the runtime API needs +to transmit information from the runtime that is aware of the Availability Cores model instantiated by the Scheduler and +Inclusion modules. -Node-side code is also responsible for detecting and reporting misbehavior performed by other validators, and the set of Runtime APIs needs to provide methods for observing live disputes and submitting reports as transactions. +Node-side code is also responsible for detecting and reporting misbehavior performed by other validators, and the set of +Runtime APIs needs to provide methods for observing live disputes and submitting reports as transactions. The next sections will contain information on specific runtime APIs. The format is this: @@ -38,9 +54,16 @@ The next sections will contain information on specific runtime APIs. The format fn some_runtime_api(at: Block, arg1: Type1, arg2: Type2, ...) -> ReturnValue; ``` -Certain runtime APIs concerning the state of a para require the caller to provide an `OccupiedCoreAssumption`. This indicates how the result of the runtime API should be computed if there is a candidate from the para occupying an availability core in the [Inclusion Module](../runtime/inclusion.md). +Certain runtime APIs concerning the state of a para require the caller to provide an `OccupiedCoreAssumption`. This +indicates how the result of the runtime API should be computed if there is a candidate from the para occupying an +availability core in the [Inclusion Module](../runtime/inclusion.md). -The choices of assumption are whether the candidate occupying that core should be assumed to have been made available and included or timed out and discarded, along with a third option to assert that the core was not occupied. This choice affects everything from the parent head-data, the validation code, and the state of message-queues. Typically, users will take the assumption that either the core was free or that the occupying candidate was included, as timeouts are expected only in adversarial circumstances and even so, only in a small minority of blocks directly following validator set rotations. +The choices of assumption are whether the candidate occupying that core should be assumed to have been made available +and included or timed out and discarded, along with a third option to assert that the core was not occupied. This choice +affects everything from the parent head-data, the validation code, and the state of message-queues. Typically, users +will take the assumption that either the core was free or that the occupying candidate was included, as timeouts are +expected only in adversarial circumstances and even so, only in a small minority of blocks directly following validator +set rotations. ```rust /// An assumption being made about the state of an occupied core. @@ -52,4 +75,4 @@ enum OccupiedCoreAssumption { /// The core was not occupied to begin with. Free, } -``` \ No newline at end of file +``` diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/availability-cores.md b/polkadot/roadmap/implementers-guide/src/runtime-api/availability-cores.md index 9402924f0013..432881160896 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/availability-cores.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/availability-cores.md @@ -1,14 +1,26 @@ # Availability Cores -Yields information on all availability cores. Cores are either free or occupied. Free cores can have paras assigned to them. Occupied cores don't, but they can become available part-way through a block due to bitfields and then have something scheduled on them. To allow optimistic validation of candidates, the occupied cores are accompanied by information on what is upcoming. This information can be leveraged when validators perceive that there is a high likelihood of a core becoming available based on bitfields seen, and then optimistically validate something that would become scheduled based on that, although there is no guarantee on what the block producer will actually include in the block. +Yields information on all availability cores. Cores are either free or occupied. Free cores can have paras assigned to +them. Occupied cores don't, but they can become available part-way through a block due to bitfields and then have +something scheduled on them. To allow optimistic validation of candidates, the occupied cores are accompanied by +information on what is upcoming. This information can be leveraged when validators perceive that there is a high +likelihood of a core becoming available based on bitfields seen, and then optimistically validate something that would +become scheduled based on that, although there is no guarantee on what the block producer will actually include in the +block. -See also the [Scheduler Module](../runtime/scheduler.md) for a high-level description of what an availability core is and why it exists. +See also the [Scheduler Module](../runtime/scheduler.md) for a high-level description of what an availability core is +and why it exists. ```rust fn availability_cores(at: Block) -> Vec; ``` -This is all the information that a validator needs about scheduling for the current block. It includes all information on [Scheduler](../runtime/scheduler.md) core-assignments and [Inclusion](../runtime/inclusion.md) state of blocks occupying availability cores. It includes data necessary to determine not only which paras are assigned now, but which cores are likely to become freed after processing bitfields, and exactly which bitfields would be necessary to make them so. The implementation of this runtime API should invoke `Scheduler::clear` and `Scheduler::schedule(Vec::new(), current_block_number + 1)` to ensure that scheduling is accurate. +This is all the information that a validator needs about scheduling for the current block. It includes all information +on [Scheduler](../runtime/scheduler.md) core-assignments and [Inclusion](../runtime/inclusion.md) state of blocks +occupying availability cores. It includes data necessary to determine not only which paras are assigned now, but which +cores are likely to become freed after processing bitfields, and exactly which bitfields would be necessary to make them +so. The implementation of this runtime API should invoke `Scheduler::clear` and `Scheduler::schedule(Vec::new(), +current_block_number + 1)` to ensure that scheduling is accurate. ```rust struct OccupiedCore { diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/candidate-pending-availability.md b/polkadot/roadmap/implementers-guide/src/runtime-api/candidate-pending-availability.md index 9c8969f6a958..e118757d83ce 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/candidate-pending-availability.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/candidate-pending-availability.md @@ -1,6 +1,7 @@ # Candidate Pending Availability -Get the receipt of a candidate pending availability. This returns `Some` for any paras assigned to occupied cores in `availability_cores` and `None` otherwise. +Get the receipt of a candidate pending availability. This returns `Some` for any paras assigned to occupied cores in +`availability_cores` and `None` otherwise. ```rust fn candidate_pending_availability(at: Block, ParaId) -> Option; diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/disputes-info.md b/polkadot/roadmap/implementers-guide/src/runtime-api/disputes-info.md index 3548d5fb5793..24f64a815382 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/disputes-info.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/disputes-info.md @@ -1,6 +1,9 @@ # Disputes Info -Get information about all disputes known by the chain as well as information about which validators the disputes subsystem will accept disputes from. These disputes may be either live or concluded. The [`DisputeState`](../types/disputes.md#disputestate) can be used to determine whether the dispute still accepts votes, as well as which validators' votes may be included. +Get information about all disputes known by the chain as well as information about which validators the disputes +subsystem will accept disputes from. These disputes may be either live or concluded. The +[`DisputeState`](../types/disputes.md#disputestate) can be used to determine whether the dispute still accepts votes, as +well as which validators' votes may be included. ```rust struct Dispute { diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/persisted-validation-data.md b/polkadot/roadmap/implementers-guide/src/runtime-api/persisted-validation-data.md index 2fd3e55c8712..e741008a7370 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/persisted-validation-data.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/persisted-validation-data.md @@ -1,6 +1,8 @@ # Persisted Validation Data -Yields the [`PersistedValidationData`](../types/candidate.md#persistedvalidationdata) for the given [`ParaId`](../types/candidate.md#paraid) along with an assumption that should be used if the para currently occupies a core: +Yields the [`PersistedValidationData`](../types/candidate.md#persistedvalidationdata) for the given +[`ParaId`](../types/candidate.md#paraid) along with an assumption that should be used if the para currently occupies a +core: ```rust /// Returns the persisted validation data for the given para and occupied core assumption. @@ -8,4 +10,4 @@ Yields the [`PersistedValidationData`](../types/candidate.md#persistedvalidation /// Returns `None` if either the para is not registered or the assumption is `Freed` /// and the para already occupies a core. fn persisted_validation_data(at: Block, ParaId, OccupiedCoreAssumption) -> Option; -``` \ No newline at end of file +``` diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/pvf-prechecking.md b/polkadot/roadmap/implementers-guide/src/runtime-api/pvf-prechecking.md index c74232367bff..ef9b801a81c6 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/pvf-prechecking.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/pvf-prechecking.md @@ -4,18 +4,18 @@ There are two main runtime APIs to work with PVF pre-checking. -The first runtime API is designed to fetch all PVFs that require pre-checking voting. The PVFs are -identified by their code hashes. As soon as the PVF gains required support, the runtime API will -not return the PVF anymore. +The first runtime API is designed to fetch all PVFs that require pre-checking voting. The PVFs are identified by their +code hashes. As soon as the PVF gains required support, the runtime API will not return the PVF anymore. ```rust fn pvfs_require_precheck() -> Vec; ``` -The second runtime API is needed to submit the judgement for a PVF, whether it is approved or not. -The voting process uses unsigned transactions. The [`PvfCheckStatement`](../types/pvf-prechecking.md) is circulated through the network via gossip similar to a normal transaction. At some point the validator -will include the statement in the block, where it will be processed by the runtime. If that was the -last vote before gaining the super-majority, this PVF will not be returned by `pvfs_require_precheck` anymore. +The second runtime API is needed to submit the judgement for a PVF, whether it is approved or not. The voting process +uses unsigned transactions. The [`PvfCheckStatement`](../types/pvf-prechecking.md) is circulated through the network via +gossip similar to a normal transaction. At some point the validator will include the statement in the block, where it +will be processed by the runtime. If that was the last vote before gaining the super-majority, this PVF will not be +returned by `pvfs_require_precheck` anymore. ```rust fn submit_pvf_check_statement(stmt: PvfCheckStatement, signature: ValidatorSignature); diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/session-index.md b/polkadot/roadmap/implementers-guide/src/runtime-api/session-index.md index 1baf6a167dbb..d1441a3a7397 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/session-index.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/session-index.md @@ -2,7 +2,8 @@ Get the session index that is expected at the child of a block. -In the [`Initializer`](../runtime/initializer.md) module, session changes are buffered by one block. The session index of the child of any relay block is always predictable by that block's state. +In the [`Initializer`](../runtime/initializer.md) module, session changes are buffered by one block. The session index +of the child of any relay block is always predictable by that block's state. This session index can be used to derive a [`SigningContext`](../types/candidate.md#signing-context). diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/validator-groups.md b/polkadot/roadmap/implementers-guide/src/runtime-api/validator-groups.md index 8815a0217411..e5ed7b43aa94 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/validator-groups.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/validator-groups.md @@ -1,6 +1,7 @@ # Validator Groups -Yields the validator groups used during the current session. The validators in the groups are referred to by their index into the validator-set and this is assumed to be as-of the child of the block whose state is being queried. +Yields the validator groups used during the current session. The validators in the groups are referred to by their index +into the validator-set and this is assumed to be as-of the child of the block whose state is being queried. ```rust /// A helper data-type for tracking validator-group rotations. diff --git a/polkadot/roadmap/implementers-guide/src/runtime-api/validators.md b/polkadot/roadmap/implementers-guide/src/runtime-api/validators.md index b7f1d9647547..e9d94d736b20 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime-api/validators.md +++ b/polkadot/roadmap/implementers-guide/src/runtime-api/validators.md @@ -1,6 +1,7 @@ # Validators -Yields the validator-set at the state of a given block. This validator set is always the one responsible for backing parachains in the child of the provided block. +Yields the validator-set at the state of a given block. This validator set is always the one responsible for backing +parachains in the child of the provided block. ```rust fn validators(at: Block) -> Vec; diff --git a/polkadot/roadmap/implementers-guide/src/runtime/README.md b/polkadot/roadmap/implementers-guide/src/runtime/README.md index 995b684b1f06..459f0e6b69d9 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/README.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/README.md @@ -1,42 +1,83 @@ # Runtime Architecture -It's clear that we want to separate different aspects of the runtime logic into different modules. Modules define their own storage, routines, and entry-points. They also define initialization and finalization logic. +It's clear that we want to separate different aspects of the runtime logic into different modules. Modules define their +own storage, routines, and entry-points. They also define initialization and finalization logic. -Due to the (lack of) guarantees provided by a particular blockchain-runtime framework, there is no defined or dependable order in which modules' initialization or finalization logic will run. Supporting this blockchain-runtime framework is important enough to include that same uncertainty in our model of runtime modules in this guide. Furthermore, initialization logic of modules can trigger the entry-points or routines of other modules. This is one architectural pressure against dividing the runtime logic into multiple modules. However, in this case the benefits of splitting things up outweigh the costs, provided that we take certain precautions against initialization and entry-point races. +Due to the (lack of) guarantees provided by a particular blockchain-runtime framework, there is no defined or dependable +order in which modules' initialization or finalization logic will run. Supporting this blockchain-runtime framework is +important enough to include that same uncertainty in our model of runtime modules in this guide. Furthermore, +initialization logic of modules can trigger the entry-points or routines of other modules. This is one architectural +pressure against dividing the runtime logic into multiple modules. However, in this case the benefits of splitting +things up outweigh the costs, provided that we take certain precautions against initialization and entry-point races. -We also expect, although it's beyond the scope of this guide, that these runtime modules will exist alongside various other modules. This has two facets to consider. First, even if the modules that we describe here don't invoke each others' entry points or routines during initialization, we still have to protect against those other modules doing that. Second, some of those modules are expected to provide governance capabilities for the chain. Configuration exposed by parachain-host modules is mostly for the benefit of these governance modules, to allow the operators or community of the chain to tweak parameters. +We also expect, although it's beyond the scope of this guide, that these runtime modules will exist alongside various +other modules. This has two facets to consider. First, even if the modules that we describe here don't invoke each +others' entry points or routines during initialization, we still have to protect against those other modules doing that. +Second, some of those modules are expected to provide governance capabilities for the chain. Configuration exposed by +parachain-host modules is mostly for the benefit of these governance modules, to allow the operators or community of the +chain to tweak parameters. -The runtime's primary role is to manage scheduling and updating of parachains, as well as handling misbehavior reports and slashing. This guide doesn't focus on how parachains are registered, only that they are. Also, this runtime description assumes that validator sets are selected somehow, but doesn't assume any other details than a periodic _session change_ event. Session changes give information about the incoming validator set and the validator set of the following session. +The runtime's primary role is to manage scheduling and updating of parachains, as well as handling misbehavior reports +and slashing. This guide doesn't focus on how parachains are registered, only that they are. Also, this runtime +description assumes that validator sets are selected somehow, but doesn't assume any other details than a periodic +_session change_ event. Session changes give information about the incoming validator set and the validator set of the +following session. -The runtime also serves another role, which is to make data available to the Node-side logic via Runtime APIs. These Runtime APIs should be sufficient for the Node-side code to author blocks correctly. +The runtime also serves another role, which is to make data available to the Node-side logic via Runtime APIs. These +Runtime APIs should be sufficient for the Node-side code to author blocks correctly. -There is some functionality of the relay chain relating to parachains that we also consider beyond the scope of this document. In particular, all modules related to how parachains are registered aren't part of this guide, although we do provide routines that should be called by the registration process. +There is some functionality of the relay chain relating to parachains that we also consider beyond the scope of this +document. In particular, all modules related to how parachains are registered aren't part of this guide, although we do +provide routines that should be called by the registration process. We will split the logic of the runtime up into these modules: -* Initializer: manages initialization order of the other modules. -* Shared: manages shared storage and configurations for other modules. -* Configuration: manages configuration and configuration updates in a non-racy manner. -* Paras: manages chain-head and validation code for parachains. -* Scheduler: manages parachain scheduling as well as validator assignments. -* Inclusion: handles the inclusion and availability of scheduled parachains. -* SessionInfo: manages various session keys of validators and other params stored per session. -* Disputes: handles dispute resolution for included, available parablocks. -* Slashing: handles slashing logic for concluded disputes. -* HRMP: handles horizontal messages between paras. -* UMP: handles upward messages from a para to the relay chain. -* DMP: handles downward messages from the relay chain to the para. +- Initializer: manages initialization order of the other modules. +- Shared: manages shared storage and configurations for other modules. +- Configuration: manages configuration and configuration updates in a non-racy manner. +- Paras: manages chain-head and validation code for parachains. +- Scheduler: manages parachain scheduling as well as validator assignments. +- Inclusion: handles the inclusion and availability of scheduled parachains. +- SessionInfo: manages various session keys of validators and other params stored per session. +- Disputes: handles dispute resolution for included, available parablocks. +- Slashing: handles slashing logic for concluded disputes. +- HRMP: handles horizontal messages between paras. +- UMP: handles upward messages from a para to the relay chain. +- DMP: handles downward messages from the relay chain to the para. -The [Initializer module](initializer.md) is special - it's responsible for handling the initialization logic of the other modules to ensure that the correct initialization order and related invariants are maintained. The other modules won't specify a on-initialize logic, but will instead expose a special semi-private routine that the initialization module will call. The other modules are relatively straightforward and perform the roles described above. +The [Initializer module](initializer.md) is special - it's responsible for handling the initialization logic of the +other modules to ensure that the correct initialization order and related invariants are maintained. The other modules +won't specify a on-initialize logic, but will instead expose a special semi-private routine that the initialization +module will call. The other modules are relatively straightforward and perform the roles described above. -The Parachain Host operates under a changing set of validators. Time is split up into periodic sessions, where each session brings a potentially new set of validators. Sessions are buffered by one, meaning that the validators of the upcoming session `n+1` are determined at the end of session `n-1`, right before session `n` starts. Parachain Host runtime modules need to react to changes in the validator set, as it will affect the runtime logic for processing candidate backing, availability bitfields, and misbehavior reports. The Parachain Host modules can't determine ahead-of-time exactly when session change notifications are going to happen within the block (note: this depends on module initialization order again - better to put session before parachains modules). +The Parachain Host operates under a changing set of validators. Time is split up into periodic sessions, where each +session brings a potentially new set of validators. Sessions are buffered by one, meaning that the validators of the +upcoming session `n+1` are determined at the end of session `n-1`, right before session `n` starts. Parachain Host +runtime modules need to react to changes in the validator set, as it will affect the runtime logic for processing +candidate backing, availability bitfields, and misbehavior reports. The Parachain Host modules can't determine +ahead-of-time exactly when session change notifications are going to happen within the block (note: this depends on +module initialization order again - better to put session before parachains modules). -The relay chain is intended to use BABE or SASSAFRAS, which both have the property that a session changing at a block is determined not by the number of the block but instead by the time the block is authored. In some sense, sessions change in-between blocks, not at blocks. This has the side effect that the session of a child block cannot be determined solely by the parent block's identifier. Being able to unilaterally determine the validator-set at a specific block based on its parent hash would make a lot of Node-side logic much simpler. +The relay chain is intended to use BABE or SASSAFRAS, which both have the property that a session changing at a block is +determined not by the number of the block but instead by the time the block is authored. In some sense, sessions change +in-between blocks, not at blocks. This has the side effect that the session of a child block cannot be determined solely +by the parent block's identifier. Being able to unilaterally determine the validator-set at a specific block based on +its parent hash would make a lot of Node-side logic much simpler. -In order to regain the property that the validator set of a block is predictable by its parent block, we delay session changes' application to Parachains by 1 block. This means that if there is a session change at block X, that session change will be stored and applied during initialization of direct descendants of X. This principal side effect of this change is that the Parachains runtime can disagree with session or consensus modules about which session it currently is. Misbehavior reporting routines in particular will be affected by this, although not severely. The parachains runtime might believe it is the last block of the session while the system is really in the first block of the next session. In such cases, a historical validator-set membership proof will need to accompany any misbehavior report, although they typically do not need to during current-session misbehavior reports. +In order to regain the property that the validator set of a block is predictable by its parent block, we delay session +changes' application to Parachains by 1 block. This means that if there is a session change at block X, that session +change will be stored and applied during initialization of direct descendants of X. This principal side effect of this +change is that the Parachains runtime can disagree with session or consensus modules about which session it currently +is. Misbehavior reporting routines in particular will be affected by this, although not severely. The parachains runtime +might believe it is the last block of the session while the system is really in the first block of the next session. In +such cases, a historical validator-set membership proof will need to accompany any misbehavior report, although they +typically do not need to during current-session misbehavior reports. -So the other role of the initializer module is to forward session change notifications to modules in the initialization order. Session change is also the point at which the [Configuration Module](configuration.md) updates the configuration. Most of the other modules will handle changes in the configuration during their session change operation, so the initializer should provide both the old and new configuration to all the other -modules alongside the session change notification. This means that a session change notification should consist of the following data: +So the other role of the initializer module is to forward session change notifications to modules in the initialization +order. Session change is also the point at which the [Configuration Module](configuration.md) updates the configuration. +Most of the other modules will handle changes in the configuration during their session change operation, so the +initializer should provide both the old and new configuration to all the other modules alongside the session change +notification. This means that a session change notification should consist of the following data: ```rust struct SessionChangeNotification { diff --git a/polkadot/roadmap/implementers-guide/src/runtime/configuration.md b/polkadot/roadmap/implementers-guide/src/runtime/configuration.md index be62ab2d4d5e..37885bd48159 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/configuration.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/configuration.md @@ -1,6 +1,11 @@ # Configuration Pallet -This module is responsible for managing all configuration of the parachain host in-flight. It provides a central point for configuration updates to prevent races between configuration changes and parachain-processing logic. Configuration can only change during the session change routine, and as this module handles the session change notification first it provides an invariant that the configuration does not change throughout the entire session. Both the [scheduler](scheduler.md) and [inclusion](inclusion.md) modules rely on this invariant to ensure proper behavior of the scheduler. +This module is responsible for managing all configuration of the parachain host in-flight. It provides a central point +for configuration updates to prevent races between configuration changes and parachain-processing logic. Configuration +can only change during the session change routine, and as this module handles the session change notification first it +provides an invariant that the configuration does not change throughout the entire session. Both the +[scheduler](scheduler.md) and [inclusion](inclusion.md) modules rely on this invariant to ensure proper behavior of the +scheduler. The configuration that we will be tracking is the [`HostConfiguration`](../types/runtime.md#host-configuration) struct. @@ -23,7 +28,8 @@ The session change routine works as follows: - If there is no pending configurations, then return early. - Take all pending configurations that are less than or equal to the current session index. - - Get the pending configuration with the highest session index and apply it to the current configuration. Discard the earlier ones if any. + - Get the pending configuration with the highest session index and apply it to the current configuration. Discard the + earlier ones if any. ## Routines @@ -41,17 +47,17 @@ pub fn configuration() -> HostConfiguration { Configuration::get() } -/// Schedules updating the host configuration. The update is given by the `updater` closure. The -/// closure takes the current version of the configuration and returns the new version. -/// Returns an `Err` if the closure returns a broken configuration. However, there are a couple of -/// exceptions: +/// Schedules updating the host configuration. The update is given by the `updater` closure. The +/// closure takes the current version of the configuration and returns the new version. +/// Returns an `Err` if the closure returns a broken configuration. However, there are a couple of +/// exceptions: /// -/// - if the configuration that was passed in the closure is already broken, then it will pass the +/// - if the configuration that was passed in the closure is already broken, then it will pass the /// update: you cannot break something that is already broken. /// - If the `BypassConsistencyCheck` flag is set, then the checks will be skipped. /// /// The changes made by this function will always be scheduled at session X, where X is the current session index + 2. -/// If there is already a pending update for X, then the closure will receive the already pending configuration for +/// If there is already a pending update for X, then the closure will receive the already pending configuration for /// session X. /// /// If there is already a pending update for the current session index + 1, then it won't be touched. Otherwise, @@ -61,4 +67,6 @@ fn schedule_config_update(updater: impl FnOnce(&mut HostConfiguration Option, Frozen: Option, ``` -> `byzantine_threshold` refers to the maximum number `f` of validators which may be byzantine. The total number of validators is `n = 3f + e` where `e in { 1, 2, 3 }`. +> `byzantine_threshold` refers to the maximum number `f` of validators which may be byzantine. The total number of +> validators is `n = 3f + e` where `e in { 1, 2, 3 }`. ## Session Change 1. If the current session is not greater than `config.dispute_period + 1`, nothing to do here. -1. Set `pruning_target = current_session - config.dispute_period - 1`. We add the extra `1` because we want to keep things for `config.dispute_period` _full_ sessions. - The stuff at the end of the most recent session has been around for a little over 0 sessions, not a little over 1. +1. Set `pruning_target = current_session - config.dispute_period - 1`. We add the extra `1` because we want to keep + things for `config.dispute_period` _full_ sessions. The stuff at the end of the most recent session has been around + for a little over 0 sessions, not a little over 1. 1. If `LastPrunedSession` is `None`, then set `LastPrunedSession` to `Some(pruning_target)` and return. -2. Otherwise, clear out all disputes and included candidates entries in the range `last_pruned..=pruning_target` and set `LastPrunedSession` to `Some(pruning_target)`. +1. Otherwise, clear out all disputes and included candidates entries in the range `last_pruned..=pruning_target` and set + `LastPrunedSession` to `Some(pruning_target)`. ## Block Initialization @@ -61,11 +82,10 @@ This is currently a `no op`. ## Routines * `filter_multi_dispute_data(MultiDisputeStatementSet) -> MultiDisputeStatementSet`: - 1. Takes a `MultiDisputeStatementSet` and filters it down to a `MultiDisputeStatementSet` - that satisfies all the criteria of `provide_multi_dispute_data`. That is, eliminating - ancient votes, duplicates and unconfirmed disputes. - This can be used by block authors to create the final submission in a block which is - guaranteed to pass the `provide_multi_dispute_data` checks. + 1. Takes a `MultiDisputeStatementSet` and filters it down to a `MultiDisputeStatementSet` that satisfies all the + criteria of `provide_multi_dispute_data`. That is, eliminating ancient votes, duplicates and unconfirmed disputes. + This can be used by block authors to create the final submission in a block which is guaranteed to pass the + `provide_multi_dispute_data` checks. * `provide_multi_dispute_data(MultiDisputeStatementSet) -> Vec<(SessionIndex, Hash)>`: 1. Pass on each dispute statement set to `provide_dispute_data`, propagating failure. @@ -76,46 +96,55 @@ This is currently a `no op`. 1. `SessionInfo` is used to check statement signatures and this function should fail if any signatures are invalid. 1. If there is no dispute under `Disputes`, create a new `DisputeState` with blank bitfields. 1. If `concluded_at` is `Some`, and is `concluded_at + config.post_conclusion_acceptance_period < now`, return false. - 2. Import all statements into the dispute. This should fail if any statements are duplicate or if the corresponding bit for the corresponding validator is set in the dispute already. - 3. If `concluded_at` is `None`, reward all statements. - 4. If `concluded_at` is `Some`, reward all statements slightly less. - 5. If either side now has supermajority and did not previously, slash the other side. This may be both sides, and we support this possibility in code, but note that this requires validators to participate on both sides which has negative expected value. Set `concluded_at` to `Some(now)` if it was `None`. - 6. If just concluded against the candidate and the `Included` map contains `(session, candidate)`: invoke `revert_and_freeze` with the stored block number. - 7. Return true if just initiated, false otherwise. - -* `disputes() -> Vec<(SessionIndex, CandidateHash, DisputeState)>`: Get a list of all disputes and info about dispute state. + 1. Import all statements into the dispute. This should fail if any statements are duplicate or if the corresponding + bit for the corresponding validator is set in the dispute already. + 1. If `concluded_at` is `None`, reward all statements. + 1. If `concluded_at` is `Some`, reward all statements slightly less. + 1. If either side now has supermajority and did not previously, slash the other side. This may be both sides, and we + support this possibility in code, but note that this requires validators to participate on both sides which has + negative expected value. Set `concluded_at` to `Some(now)` if it was `None`. + 1. If just concluded against the candidate and the `Included` map contains `(session, candidate)`: invoke + `revert_and_freeze` with the stored block number. + 1. Return true if just initiated, false otherwise. + +* `disputes() -> Vec<(SessionIndex, CandidateHash, DisputeState)>`: Get a list of all disputes and info about dispute + state. 1. Iterate over all disputes in `Disputes` and collect into a vector. * `note_included(SessionIndex, CandidateHash, included_in: BlockNumber)`: 1. Add `(SessionIndex, CandidateHash)` to the `Included` map with `included_in - 1` as the value. - 1. If there is a dispute under `(SessionIndex, CandidateHash)` that has concluded against the candidate, invoke `revert_and_freeze` with the stored block number. + 1. If there is a dispute under `(SessionIndex, CandidateHash)` that has concluded against the candidate, invoke + `revert_and_freeze` with the stored block number. -* `concluded_invalid(SessionIndex, CandidateHash) -> bool`: Returns whether a candidate has already concluded a dispute in the negative. +* `concluded_invalid(SessionIndex, CandidateHash) -> bool`: Returns whether a candidate has already concluded a dispute + in the negative. * `is_frozen()`: Load the value of `Frozen` from storage. Return true if `Some` and false if `None`. -* `last_valid_block()`: Load the value of `Frozen` from storage and return. None indicates that all blocks in the chain are potentially valid. +* `last_valid_block()`: Load the value of `Frozen` from storage and return. None indicates that all blocks in the chain + are potentially valid. * `revert_and_freeze(BlockNumber)`: 1. If `is_frozen()` return. 1. Set `Frozen` to `Some(BlockNumber)` to indicate a rollback to the block number. - 1. Issue a `Revert(BlockNumber + 1)` log to indicate a rollback of the block's child in the header chain, which is the same as a rollback to the block number. + 1. Issue a `Revert(BlockNumber + 1)` log to indicate a rollback of the block's child in the header chain, which is the + same as a rollback to the block number. # Disputes filtering All disputes delivered to the runtime by the client are filtered before the actual import. In this context actual import means persisted in the runtime storage. The filtering has got two purposes: -- Limit the amount of data saved onchain. -- Prevent persisting malicious dispute data onchain. +* Limit the amount of data saved onchain. +* Prevent persisting malicious dispute data onchain. *Implementation note*: Filtering is performed in function `filter_dispute_data` from `Disputes` pallet. The filtering is performed on the whole statement set which is about to be imported onchain. The following filters are applied: 1. Remove ancient disputes - if a dispute is concluded before the block number indicated in `OLDEST_ACCEPTED` parameter - it is removed from the set. `OLDEST_ACCEPTED` is a runtime configuration option. - *Implementation note*: `dispute_post_conclusion_acceptance_period` from - `HostConfiguration` is used in the current Polkadot/Kusama implementation. + it is removed from the set. `OLDEST_ACCEPTED` is a runtime configuration option. *Implementation note*: + `dispute_post_conclusion_acceptance_period` from `HostConfiguration` is used in the current Polkadot/Kusama + implementation. 2. Remove votes from unknown validators. If there is a vote from a validator which wasn't an authority in the session where the dispute was raised - they are removed. Please note that this step removes only single votes instead of removing the whole dispute. @@ -138,4 +167,4 @@ inconclusive disputes are not slashed. Thanks to the applied filtering (describe confident that there are no spam disputes in the runtime. So if a validator is not voting it is due to another reason (e.g. being under DoS attack). There is no reason to punish such validators with a slash. -*Implementation note*: Slashing is performed in `process_checked_dispute_data` from `Disputes` pallet. \ No newline at end of file +*Implementation note*: Slashing is performed in `process_checked_dispute_data` from `Disputes` pallet. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/dmp.md b/polkadot/roadmap/implementers-guide/src/runtime/dmp.md index f56df31934ef..5aeb3bd68ef3 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/dmp.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/dmp.md @@ -28,7 +28,8 @@ No initialization routine runs for this module. Candidate Acceptance Function: * `check_processed_downward_messages(P: ParaId, relay_parent_number: BlockNumber, processed_downward_messages: u32)`: - 1. Checks that `processed_downward_messages` is at least 1 if `DownwardMessageQueues` for `P` is not empty at the given `relay_parent_number`. + 1. Checks that `processed_downward_messages` is at least 1 if `DownwardMessageQueues` for `P` is not empty at the + given `relay_parent_number`. 1. Checks that `DownwardMessageQueues` for `P` is at least `processed_downward_messages` long. Candidate Enactment: @@ -38,11 +39,11 @@ Candidate Enactment: Utility routines. -`queue_downward_message(P: ParaId, M: DownwardMessage)`: - 1. Check if the size of `M` exceeds the `config.max_downward_message_size`. If so, return an error. - 1. Wrap `M` into `InboundDownwardMessage` using the current block number for `sent_at`. - 1. Obtain a new MQC link for the resulting `InboundDownwardMessage` and replace `DownwardMessageQueueHeads` for `P` with the resulting hash. - 1. Add the resulting `InboundDownwardMessage` into `DownwardMessageQueues` for `P`. +`queue_downward_message(P: ParaId, M: DownwardMessage)`: 1. Check if the size of `M` exceeds the + `config.max_downward_message_size`. If so, return an error. 1. Wrap `M` into `InboundDownwardMessage` using the + current block number for `sent_at`. 1. Obtain a new MQC link for the resulting `InboundDownwardMessage` and replace + `DownwardMessageQueueHeads` for `P` with the resulting hash. 1. Add the resulting `InboundDownwardMessage` into + `DownwardMessageQueues` for `P`. ## Session Change diff --git a/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md b/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md index 927c14cd5969..aa31491d72f6 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md @@ -1,6 +1,7 @@ # HRMP Pallet -A module responsible for Horizontally Relay-routed Message Passing (HRMP). See [Messaging Overview](../messaging.md) for more details. +A module responsible for Horizontally Relay-routed Message Passing (HRMP). See [Messaging Overview](../messaging.md) for +more details. ## Storage @@ -132,7 +133,8 @@ Candidate Acceptance Function: 1. or in `HrmpChannelDigests` for `P` an entry with the block number should exist * `check_outbound_hrmp(sender: ParaId, Vec)`: 1. Checks that there are at most `config.hrmp_max_message_num_per_candidate` messages. - 1. Checks that horizontal messages are sorted by ascending recipient ParaId and there is no two horizontal messages have the same recipient. + 1. Checks that horizontal messages are sorted by ascending recipient ParaId and there is no two horizontal messages + have the same recipient. 1. For each horizontal message `M` with the channel `C` identified by `(sender, M.recipient)` check: 1. exists 1. `M`'s payload size doesn't exceed a preconfigured limit `C.max_message_size` @@ -143,42 +145,48 @@ Candidate Enactment: * `queue_outbound_hrmp(sender: ParaId, Vec)`: 1. For each horizontal message `HM` with the channel `C` identified by `(sender, HM.recipient)`: - 1. Append `HM` into `HrmpChannelContents` that corresponds to `C` with `sent_at` equals to the current block number. - 1. Locate or create an entry in `HrmpChannelDigests` for `HM.recipient` and append `sender` into the entry's list. + 1. Append `HM` into `HrmpChannelContents` that corresponds to `C` with `sent_at` equals to the current block + number. + 1. Locate or create an entry in `HrmpChannelDigests` for `HM.recipient` and append `sender` into the entry's + list. 1. Increment `C.msg_count` 1. Increment `C.total_size` by `HM`'s payload size - 1. Append a new link to the MQC and save the new head in `C.mqc_head`. Note that the current block number as of enactment is used for the link. + 1. Append a new link to the MQC and save the new head in `C.mqc_head`. Note that the current block number as of + enactment is used for the link. * `prune_hrmp(recipient, new_hrmp_watermark)`: - 1. From `HrmpChannelDigests` for `recipient` remove all entries up to an entry with block number equal to `new_hrmp_watermark`. - 1. From the removed digests construct a set of paras that sent new messages within the interval between the old and new watermarks. - 1. For each channel `C` identified by `(sender, recipient)` for each `sender` coming from the set, prune messages up to the `new_hrmp_watermark`. + 1. From `HrmpChannelDigests` for `recipient` remove all entries up to an entry with block number equal to + `new_hrmp_watermark`. + 1. From the removed digests construct a set of paras that sent new messages within the interval between the old and + new watermarks. + 1. For each channel `C` identified by `(sender, recipient)` for each `sender` coming from the set, prune messages up + to the `new_hrmp_watermark`. 1. For each pruned message `M` from channel `C`: 1. Decrement `C.msg_count` 1. Decrement `C.total_size` by `M`'s payload size. 1. Set `HrmpWatermarks` for `P` to be equal to `new_hrmp_watermark` > NOTE: That collecting digests can be inefficient and the time it takes grows very fast. Thanks to the aggressive - > parameterization this shouldn't be a big of a deal. - > If that becomes a problem consider introducing an extra dictionary which says at what block the given sender - > sent a message to the recipient. + > parameterization this shouldn't be a big of a deal. If that becomes a problem consider introducing an extra + > dictionary which says at what block the given sender sent a message to the recipient. ## Entry-points The following entry-points are meant to be used for HRMP channel management. -Those entry-points are meant to be called from a parachain. `origin` is defined as the `ParaId` of -the parachain executed the message. +Those entry-points are meant to be called from a parachain. `origin` is defined as the `ParaId` of the parachain +executed the message. * `hrmp_init_open_channel(recipient, proposed_max_capacity, proposed_max_message_size)`: 1. Check that the `origin` is not `recipient`. 1. Check that `proposed_max_capacity` is less or equal to `config.hrmp_channel_max_capacity` and greater than zero. - 1. Check that `proposed_max_message_size` is less or equal to `config.hrmp_channel_max_message_size` and greater than zero. + 1. Check that `proposed_max_message_size` is less or equal to `config.hrmp_channel_max_message_size` and greater + than zero. 1. Check that `recipient` is a valid para. 1. Check that there is no existing channel for `(origin, recipient)` in `HrmpChannels`. 1. Check that there is no existing open channel request (`origin`, `recipient`) in `HrmpOpenChannelRequests`. - 1. Check that the sum of the number of already opened HRMP channels by the `origin` (the size - of the set found `HrmpEgressChannelsIndex` for `origin`) and the number of open requests by the - `origin` (the value from `HrmpOpenChannelRequestCount` for `origin`) doesn't exceed the limit of - channels (`config.hrmp_max_parachain_outbound_channels` or `config.hrmp_max_parathread_outbound_channels`) minus 1. + 1. Check that the sum of the number of already opened HRMP channels by the `origin` (the size of the set found + `HrmpEgressChannelsIndex` for `origin`) and the number of open requests by the `origin` (the value from + `HrmpOpenChannelRequestCount` for `origin`) doesn't exceed the limit of channels + (`config.hrmp_max_parachain_outbound_channels` or `config.hrmp_max_parathread_outbound_channels`) minus 1. 1. Check that `origin`'s balance is more or equal to `config.hrmp_sender_deposit` 1. Reserve the deposit for the `origin` according to `config.hrmp_sender_deposit` 1. Increase `HrmpOpenChannelRequestCount` by 1 for `origin`. @@ -189,27 +197,26 @@ the parachain executed the message. 1. Set `max_message_size` to `proposed_max_message_size` 1. Set `max_total_size` to `config.hrmp_channel_max_total_size` 1. Send a downward message to `recipient` notifying about an inbound HRMP channel request. - - The DM is sent using `queue_downward_message`. - - The DM is represented by the `HrmpNewChannelOpenRequest` XCM message. - - `sender` is set to `origin`, - - `max_message_size` is set to `proposed_max_message_size`, - - `max_capacity` is set to `proposed_max_capacity`. + * The DM is sent using `queue_downward_message`. + * The DM is represented by the `HrmpNewChannelOpenRequest` XCM message. + * `sender` is set to `origin`, + * `max_message_size` is set to `proposed_max_message_size`, + * `max_capacity` is set to `proposed_max_capacity`. * `hrmp_accept_open_channel(sender)`: 1. Check that there is an existing request between (`sender`, `origin`) in `HrmpOpenChannelRequests` 1. Check that it is not confirmed. - 1. Check that the sum of the number of inbound HRMP channels opened to `origin` (the size of the set - found in `HrmpIngressChannelsIndex` for `origin`) and the number of accepted open requests by the `origin` - (the value from `HrmpAcceptedChannelRequestCount` for `origin`) doesn't exceed the limit of channels - (`config.hrmp_max_parachain_inbound_channels` or `config.hrmp_max_parathread_inbound_channels`) - minus 1. + 1. Check that the sum of the number of inbound HRMP channels opened to `origin` (the size of the set found in + `HrmpIngressChannelsIndex` for `origin`) and the number of accepted open requests by the `origin` (the value from + `HrmpAcceptedChannelRequestCount` for `origin`) doesn't exceed the limit of channels + (`config.hrmp_max_parachain_inbound_channels` or `config.hrmp_max_parathread_inbound_channels`) minus 1. 1. Check that `origin`'s balance is more or equal to `config.hrmp_recipient_deposit`. 1. Reserve the deposit for the `origin` according to `config.hrmp_recipient_deposit` 1. For the request in `HrmpOpenChannelRequests` identified by `(sender, P)`, set `confirmed` flag to `true`. 1. Increase `HrmpAcceptedChannelRequestCount` by 1 for `origin`. 1. Send a downward message to `sender` notifying that the channel request was accepted. - - The DM is sent using `queue_downward_message`. - - The DM is represented by the `HrmpChannelAccepted` XCM message. - - `recipient` is set to `origin`. + * The DM is sent using `queue_downward_message`. + * The DM is represented by the `HrmpChannelAccepted` XCM message. + * `recipient` is set to `origin`. * `hrmp_cancel_open_request(ch)`: 1. Check that `origin` is either `ch.sender` or `ch.recipient` 1. Check that the open channel request `ch` exists. @@ -221,15 +228,15 @@ the parachain executed the message. 1. Check that `origin` is either `ch.sender` or `ch.recipient` 1. Check that `HrmpChannels` for `ch` exists. 1. Check that `ch` is not in the `HrmpCloseChannelRequests` set. - 1. If not already there, insert a new entry `Some(())` to `HrmpCloseChannelRequests` for `ch` - and append `ch` to `HrmpCloseChannelRequestsList`. + 1. If not already there, insert a new entry `Some(())` to `HrmpCloseChannelRequests` for `ch` and append `ch` to + `HrmpCloseChannelRequestsList`. 1. Send a downward message to the opposite party notifying about the channel closing. - - The DM is sent using `queue_downward_message`. - - The DM is represented by the `HrmpChannelClosing` XCM message with: - - `initator` is set to `origin`, - - `sender` is set to `ch.sender`, - - `recipient` is set to `ch.recipient`. - - The opposite party is `ch.sender` if `origin` is `ch.recipient` and `ch.recipient` if `origin` is `ch.sender`. + * The DM is sent using `queue_downward_message`. + * The DM is represented by the `HrmpChannelClosing` XCM message with: + * `initator` is set to `origin`, + * `sender` is set to `ch.sender`, + * `recipient` is set to `ch.recipient`. + * The opposite party is `ch.sender` if `origin` is `ch.recipient` and `ch.recipient` if `origin` is `ch.sender`. ## Session Change @@ -241,13 +248,15 @@ the parachain executed the message. 1. Remove `HrmpOpenChannelRequests` and `HrmpOpenChannelRequestsList` for `(P, _)` and `(_, P)`. 1. For each removed channel request `C`: 1. Unreserve the sender's deposit if the sender is not present in `outgoing_paras` - 1. Unreserve the recipient's deposit if `C` is confirmed and the recipient is not present in `outgoing_paras` -1. For each channel designator `D` in `HrmpOpenChannelRequestsList` we query the request `R` from `HrmpOpenChannelRequests`: + 1. Unreserve the recipient's deposit if `C` is confirmed and the recipient is not present in + `outgoing_paras` +1. For each channel designator `D` in `HrmpOpenChannelRequestsList` we query the request `R` from + `HrmpOpenChannelRequests`: 1. if `R.confirmed = true`, 1. if both `D.sender` and `D.recipient` are not offboarded. 1. create a new channel `C` between `(D.sender, D.recipient)`. - 1. Initialize the `C.sender_deposit` with `R.sender_deposit` and `C.recipient_deposit` - with the value found in the configuration `config.hrmp_recipient_deposit`. + 1. Initialize the `C.sender_deposit` with `R.sender_deposit` and `C.recipient_deposit` with the value + found in the configuration `config.hrmp_recipient_deposit`. 1. Insert `sender` into the set `HrmpIngressChannelsIndex` for the `recipient`. 1. Insert `recipient` into the set `HrmpEgressChannelsIndex` for the `sender`. 1. decrement `HrmpOpenChannelRequestCount` for `D.sender` by 1. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md b/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md index 3fe7711ae2d0..f73df209981a 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md @@ -1,6 +1,7 @@ # Inclusion Pallet -The inclusion module is responsible for inclusion and availability of scheduled parachains. It also manages the UMP dispatch queue of each parachain. +The inclusion module is responsible for inclusion and availability of scheduled parachains. It also manages the UMP +dispatch queue of each parachain. ## Storage @@ -37,11 +38,9 @@ PendingAvailabilityCommitments: map ParaId => CandidateCommitments; ## Config Dependencies -* `MessageQueue`: - The message queue provides general queueing and processing functionality. Currently it - replaces the old `UMP` dispatch queue. Other use-cases can be implemented as well by - adding new variants to `AggregateMessageOrigin`. Normally it should be set to an instance - of the `MessageQueue` pallet. +* `MessageQueue`: The message queue provides general queueing and processing functionality. Currently it replaces the + old `UMP` dispatch queue. Other use-cases can be implemented as well by adding new variants to + `AggregateMessageOrigin`. Normally it should be set to an instance of the `MessageQueue` pallet. ## Session Change @@ -49,11 +48,13 @@ PendingAvailabilityCommitments: map ParaId => CandidateCommitments; 1. Clear out all validator bitfields. Optional: -1. The UMP queue of all outgoing paras can be "swept". This would prevent the dispatch queue from automatically being serviced. It is a consideration for the chain and specific behaviour is not defined. +1. The UMP queue of all outgoing paras can be "swept". This would prevent the dispatch queue from automatically being + serviced. It is a consideration for the chain and specific behaviour is not defined. ## Initialization -No initialization routine runs for this module. However, the initialization of the `MessageQueue` pallet will attempt to process any pending UMP messages. +No initialization routine runs for this module. However, the initialization of the `MessageQueue` pallet will attempt to +process any pending UMP messages. ## Routines @@ -63,20 +64,19 @@ All failed checks should lead to an unrecoverable error making the block invalid * `process_bitfields(expected_bits, Bitfields, core_lookup: Fn(CoreIndex) -> Option)`: 1. Call `sanitize_bitfields` and use the sanitized `signed_bitfields` from now on. 1. Call `sanitize_backed_candidates` and use the sanitized `backed_candidates` from now on. - 1. Apply each bit of bitfield to the corresponding pending candidate, looking up on-demand parachain cores using the `core_lookup`. Disregard bitfields that have a `1` bit for any free cores. - 1. For each applied bit of each availability-bitfield, set the bit for the validator in the `CandidatePendingAvailability`'s `availability_votes` bitfield. Track all candidates that now have >2/3 of bits set in their `availability_votes`. These candidates are now available and can be enacted. + 1. Apply each bit of bitfield to the corresponding pending candidate, looking up on-demand parachain cores using the + `core_lookup`. Disregard bitfields that have a `1` bit for any free cores. + 1. For each applied bit of each availability-bitfield, set the bit for the validator in the + `CandidatePendingAvailability`'s `availability_votes` bitfield. Track all candidates that now have >2/3 of bits set + in their `availability_votes`. These candidates are now available and can be enacted. 1. For all now-available candidates, invoke the `enact_candidate` routine with the candidate and relay-parent number. - 1. Return a list of `(CoreIndex, CandidateHash)` from freed cores consisting of the cores where candidates have become available. -* `sanitize_bitfields( - unchecked_bitfields: UncheckedSignedAvailabilityBitfields, - disputed_bitfield: DisputedBitfield, - expected_bits: usize, - parent_hash: T::Hash, - session_index: SessionIndex, - validators: &[ValidatorId], - full_check: FullCheck, - )`: - 1. check that `disputed_bitfield` has the same number of bits as the `expected_bits`, iff not return early with an empty vec. + 1. Return a list of `(CoreIndex, CandidateHash)` from freed cores consisting of the cores where candidates have become + available. +* `sanitize_bitfields( unchecked_bitfields: UncheckedSignedAvailabilityBitfields, + disputed_bitfield: DisputedBitfield, expected_bits: usize, parent_hash: T::Hash, session_index: SessionIndex, + validators: &[ValidatorId], full_check: FullCheck, )`: + 1. check that `disputed_bitfield` has the same number of bits as the `expected_bits`, iff not return early with an + empty vec. 1. each of the below checks is for each bitfield. If a check does not pass the bitfield will be skipped. 1. check that there are no bits set that reference a disputed candidate. 1. check that the number of bits is equal to `expected_bits`. @@ -84,41 +84,58 @@ All failed checks should lead to an unrecoverable error making the block invalid 1. check that the validator bit index is not out of bounds. 1. check the validators signature, iff `full_check=FullCheck::Yes`. -* `sanitize_backed_candidates) -> bool>( - mut backed_candidates: Vec>, - candidate_has_concluded_invalid_dispute: F, - scheduled: &[CoreAssignment], - ) ` +* `sanitize_backed_candidates) -> bool>( mut + backed_candidates: Vec>, candidate_has_concluded_invalid_dispute: F, scheduled: + &[CoreAssignment], )` 1. filter out any backed candidates that have concluded invalid. 1. filters backed candidates whom's paraid was scheduled by means of the provided `scheduled` parameter. 1. sorts remaining candidates with respect to the core index assigned to them. -* `process_candidates(allowed_relay_parents, BackedCandidates, scheduled: Vec, group_validators: Fn(GroupIndex) -> Option>)`: +* `process_candidates(allowed_relay_parents, BackedCandidates, scheduled: Vec, group_validators: + Fn(GroupIndex) -> Option>)`: > For details on `AllowedRelayParentsTracker` see documentation for [Shared](./shared.md) module. - 1. check that each candidate corresponds to a scheduled core and that they are ordered in the same order the cores appear in assignments in `scheduled`. + 1. check that each candidate corresponds to a scheduled core and that they are ordered in the same order the cores + appear in assignments in `scheduled`. 1. check that `scheduled` is sorted ascending by `CoreIndex`, without duplicates. 1. check that the relay-parent from each candidate receipt is one of the allowed relay-parents. 1. check that there is no candidate pending availability for any scheduled `ParaId`. - 1. check that each candidate's `validation_data_hash` corresponds to a `PersistedValidationData` computed from the state of the context block. + 1. check that each candidate's `validation_data_hash` corresponds to a `PersistedValidationData` computed from the + state of the context block. 1. If the core assignment includes a specific collator, ensure the backed candidate is issued by that collator. - 1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_cooldown` of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` for the given para ID. + 1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_cooldown` + of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` + for the given para ID. 1. Check the collator's signature on the candidate data. - 1. check the backing of the candidate using the signatures and the bitfields, comparing against the validators assigned to the groups, fetched with the `group_validators` lookup, while group indices are computed by `Scheduler` according to group rotation info. - 1. call `check_upward_messages(config, para, commitments.upward_messages)` to check that the upward messages are valid. - 1. call `Dmp::check_processed_downward_messages(para, commitments.processed_downward_messages)` to check that the DMQ is properly drained. - 1. call `Hrmp::check_hrmp_watermark(para, commitments.hrmp_watermark)` for each candidate to check rules of processing the HRMP watermark. - 1. using `Hrmp::check_outbound_hrmp(sender, commitments.horizontal_messages)` ensure that the each candidate sent a valid set of horizontal messages - 1. create an entry in the `PendingAvailability` map for each backed candidate with a blank `availability_votes` bitfield. + 1. check the backing of the candidate using the signatures and the bitfields, comparing against the validators + assigned to the groups, fetched with the `group_validators` lookup, while group indices are computed by `Scheduler` + according to group rotation info. + 1. call `check_upward_messages(config, para, commitments.upward_messages)` to check that the upward messages are + valid. + 1. call `Dmp::check_processed_downward_messages(para, commitments.processed_downward_messages)` to check that the DMQ + is properly drained. + 1. call `Hrmp::check_hrmp_watermark(para, commitments.hrmp_watermark)` for each candidate to check rules of processing + the HRMP watermark. + 1. using `Hrmp::check_outbound_hrmp(sender, commitments.horizontal_messages)` ensure that the each candidate sent a + valid set of horizontal messages + 1. create an entry in the `PendingAvailability` map for each backed candidate with a blank `availability_votes` + bitfield. 1. create a corresponding entry in the `PendingAvailabilityCommitments` with the commitments. - 1. Return a `Vec` of all scheduled cores of the list of passed assignments that a candidate was successfully backed for, sorted ascending by CoreIndex. + 1. Return a `Vec` of all scheduled cores of the list of passed assignments that a candidate was + successfully backed for, sorted ascending by CoreIndex. * `enact_candidate(relay_parent_number: BlockNumber, CommittedCandidateReceipt)`: - 1. If the receipt contains a code upgrade, Call `Paras::schedule_code_upgrade(para_id, code, relay_parent_number, config)`. - > TODO: Note that this is safe as long as we never enact candidates where the relay parent is across a session boundary. In that case, which we should be careful to avoid with contextual execution, the configuration might have changed and the para may de-sync from the host's understanding of it. + 1. If the receipt contains a code upgrade, Call `Paras::schedule_code_upgrade(para_id, code, relay_parent_number, + config)`. + > TODO: Note that this is safe as long as we never enact candidates where the relay parent is across a session + > boundary. In that case, which we should be careful to avoid with contextual execution, the configuration might + > have changed and the para may de-sync from the host's understanding of it. 1. Reward all backing validators of each candidate, contained within the `backers` field. - 1. call `receive_upward_messages` for each backed candidate, using the [`UpwardMessage`s](../types/messages.md#upward-message) from the [`CandidateCommitments`](../types/candidate.md#candidate-commitments). + 1. call `receive_upward_messages` for each backed candidate, using the + [`UpwardMessage`s](../types/messages.md#upward-message) from the + [`CandidateCommitments`](../types/candidate.md#candidate-commitments). 1. call `Dmp::prune_dmq` with the para id of the candidate and the candidate's `processed_downward_messages`. 1. call `Hrmp::prune_hrmp` with the para id of the candiate and the candidate's `hrmp_watermark`. - 1. call `Hrmp::queue_outbound_hrmp` with the para id of the candidate and the list of horizontal messages taken from the commitment, + 1. call `Hrmp::queue_outbound_hrmp` with the para id of the candidate and the list of horizontal messages taken from + the commitment, 1. Call `Paras::note_new_head` using the `HeadData` from the receipt and `relay_parent_number`. * `collect_pending`: @@ -130,21 +147,28 @@ All failed checks should lead to an unrecoverable error making the block invalid // return a vector of cleaned-up core IDs. } ``` -* `force_enact(ParaId)`: Forcibly enact the candidate with the given ID as though it had been deemed available by bitfields. Is a no-op if there is no candidate pending availability for this para-id. This should generally not be used but it is useful during execution of Runtime APIs, where the changes to the state are expected to be discarded directly after. -* `candidate_pending_availability(ParaId) -> Option`: returns the `CommittedCandidateReceipt` pending availability for the para provided, if any. -* `pending_availability(ParaId) -> Option`: returns the metadata around the candidate pending availability for the para, if any. -* `collect_disputed(disputed: Vec) -> Vec`: Sweeps through all paras pending availability. If the candidate hash is one of the disputed candidates, then clean up the corresponding storage for that candidate and the commitments. Return a vector of cleaned-up core IDs. +* `force_enact(ParaId)`: Forcibly enact the candidate with the given ID as though it had been deemed available by + bitfields. Is a no-op if there is no candidate pending availability for this para-id. This should generally not be + used but it is useful during execution of Runtime APIs, where the changes to the state are expected to be discarded + directly after. +* `candidate_pending_availability(ParaId) -> Option`: returns the `CommittedCandidateReceipt` + pending availability for the para provided, if any. +* `pending_availability(ParaId) -> Option`: returns the metadata around the candidate + pending availability for the para, if any. +* `collect_disputed(disputed: Vec) -> Vec`: Sweeps through all paras pending availability. If + the candidate hash is one of the disputed candidates, then clean up the corresponding storage for that candidate and + the commitments. Return a vector of cleaned-up core IDs. These functions were formerly part of the UMP pallet: * `check_upward_messages(P: ParaId, Vec)`: - 1. Checks that the parachain is not currently offboarding and error otherwise. + 1. Checks that the parachain is not currently offboarding and error otherwise. 1. Checks that there are at most `config.max_upward_message_num_per_candidate` messages to be enqueued. 1. Checks that no message exceeds `config.max_upward_message_size`. 1. Checks that the total resulting queue size would not exceed `co`. - 1. Verify that queuing up the messages could not result in exceeding the queue's footprint - according to the config items `config.max_upward_queue_count` and `config.max_upward_queue_size`. The queue's current footprint is provided in `well_known_keys` - in order to facilitate oraclisation on to the para. + 1. Verify that queuing up the messages could not result in exceeding the queue's footprint according to the config + items `config.max_upward_queue_count` and `config.max_upward_queue_size`. The queue's current footprint is provided + in `well_known_keys` in order to facilitate oraclisation on to the para. Candidate Enactment: diff --git a/polkadot/roadmap/implementers-guide/src/runtime/initializer.md b/polkadot/roadmap/implementers-guide/src/runtime/initializer.md index 19dfcbde50a9..a8522b369692 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/initializer.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/initializer.md @@ -1,6 +1,7 @@ # Initializer Pallet -This module is responsible for initializing the other modules in a deterministic order. It also has one other purpose as described in the overview of the runtime: accepting and forwarding session change notifications. +This module is responsible for initializing the other modules in a deterministic order. It also has one other purpose as +described in the overview of the runtime: accepting and forwarding session change notifications. ## Storage @@ -15,7 +16,9 @@ BufferedSessionChanges: Vec<(BlockNumber, ValidatorSet, ValidatorSet)>; ## Initialization -Before initializing modules, remove all changes from the `BufferedSessionChanges` with number less than or equal to the current block number, and apply the last one. The session change is applied to all modules in the same order as initialization. +Before initializing modules, remove all changes from the `BufferedSessionChanges` with number less than or equal to the +current block number, and apply the last one. The session change is applied to all modules in the same order as +initialization. The other parachains modules are initialized in this order: @@ -30,16 +33,24 @@ The other parachains modules are initialized in this order: 1. UMP 1. HRMP -The [Configuration Module](configuration.md) is first, since all other modules need to operate under the same configuration as each other. Then the [Shared](shared.md) module is invoked, which determines the set of active validators. It would lead to inconsistency if, for example, the scheduler ran first and then the configuration was updated before the Inclusion module. +The [Configuration Module](configuration.md) is first, since all other modules need to operate under the same +configuration as each other. Then the [Shared](shared.md) module is invoked, which determines the set of active +validators. It would lead to inconsistency if, for example, the scheduler ran first and then the configuration was +updated before the Inclusion module. Set `HasInitialized` to true. ## Session Change -Store the session change information in `BufferedSessionChange` along with the block number at which it was submitted, plus one. Although the expected operational parameters of the block authorship system should prevent more than one change from being buffered at any time, it may occur. Regardless, we always need to track the block number at which the session change can be applied so as to remain flexible over session change notifications being issued before or after initialization of the current block. +Store the session change information in `BufferedSessionChange` along with the block number at which it was submitted, +plus one. Although the expected operational parameters of the block authorship system should prevent more than one +change from being buffered at any time, it may occur. Regardless, we always need to track the block number at which the +session change can be applied so as to remain flexible over session change notifications being issued before or after +initialization of the current block. ## Finalization -Finalization order is less important in this case than initialization order, so we finalize the modules in the reverse order from initialization. +Finalization order is less important in this case than initialization order, so we finalize the modules in the reverse +order from initialization. Set `HasInitialized` to false. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md b/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md index 405468c609a7..4a771f1df644 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md @@ -1,15 +1,27 @@ # `ParaInherent` -This module is responsible for providing all data given to the runtime by the block author to the various parachains modules. The entry-point is mandatory, in that it must be invoked exactly once within every block, and it is also "inherent", in that it is provided with no origin by the block author. The data within it carries its own authentication; i.e. the data takes the form of signed statements by validators. Invalid data will be filtered and not applied. +This module is responsible for providing all data given to the runtime by the block author to the various parachains +modules. The entry-point is mandatory, in that it must be invoked exactly once within every block, and it is also +"inherent", in that it is provided with no origin by the block author. The data within it carries its own +authentication; i.e. the data takes the form of signed statements by validators. Invalid data will be filtered and not +applied. -This module does not have the same initialization/finalization concerns as the others, as it only requires that entry points be triggered after all modules have initialized and that finalization happens after entry points are triggered. Both of these are assumptions we have already made about the runtime's order of operations, so this module doesn't need to be initialized or finalized by the `Initializer`. +This module does not have the same initialization/finalization concerns as the others, as it only requires that entry +points be triggered after all modules have initialized and that finalization happens after entry points are triggered. +Both of these are assumptions we have already made about the runtime's order of operations, so this module doesn't need +to be initialized or finalized by the `Initializer`. There are a couple of important notes to the operations in this inherent as they relate to disputes. -1. We don't accept bitfields or backed candidates if in "governance-only" mode from having a local dispute conclude on this fork. -1. When disputes are initiated, we remove the block from pending availability. This allows us to roll back chains to the block before blocks are included as opposed to backing. It's important to do this before processing bitfields. -1. `Inclusion::collect_disputed` is kind of expensive so it's important to gate this on whether there are actually any new disputes. Which should be never. -1. And we don't accept parablocks that have open disputes or disputes that have concluded against the candidate. It's important to import dispute statements before backing, but this is already the case as disputes are imported before processing bitfields. +1. We don't accept bitfields or backed candidates if in "governance-only" mode from having a local dispute conclude on + this fork. +1. When disputes are initiated, we remove the block from pending availability. This allows us to roll back chains to the + block before blocks are included as opposed to backing. It's important to do this before processing bitfields. +1. `Inclusion::collect_disputed` is kind of expensive so it's important to gate this on whether there are actually any + new disputes. Which should be never. +1. And we don't accept parablocks that have open disputes or disputes that have concluded against the candidate. It's + important to import dispute statements before backing, but this is already the case as disputes are imported before + processing bitfields. ## Storage @@ -32,26 +44,19 @@ OnChainVotes: Option, * `enter`: This entry-point accepts one parameter: [`ParaInherentData`](../types/runtime.md#ParaInherentData). * `create_inherent`: This entry-point accepts one parameter: `InherentData`. -Both entry points share mostly the same code. `create_inherent` will -meaningfully limit inherent data to adhere to the weight limit, in addition to -sanitizing any inputs and filtering out invalid data. Conceptually it is part of -the block production. The `enter` call on the other hand is part of block import -and consumes/imports the data previously produced by `create_inherent`. - -In practice both calls process inherent data and apply it to the state. Block -production and block import should arrive at the same new state. Hence we re-use -the same logic to ensure this is the case. - -The only real difference between the two is, that on `create_inherent` we -actually need the processed and filtered inherent data to build the block, while -on `enter` the processed data should for one be identical to the incoming -inherent data (assuming honest block producers) and second it is irrelevant, as -we are not building a block but just processing it, so the processed inherent -data is simply dropped. - -This also means that the `enter` function keeps data around for no good reason. -This seems acceptable though as the size of a block is rather limited. -Nevertheless if we ever wanted to optimize this we can easily implement an -inherent collector that has two implementations, where one clones and stores the -data and the other just passes it on. +Both entry points share mostly the same code. `create_inherent` will meaningfully limit inherent data to adhere to the +weight limit, in addition to sanitizing any inputs and filtering out invalid data. Conceptually it is part of the block +production. The `enter` call on the other hand is part of block import and consumes/imports the data previously produced +by `create_inherent`. +In practice both calls process inherent data and apply it to the state. Block production and block import should arrive +at the same new state. Hence we re-use the same logic to ensure this is the case. + +The only real difference between the two is, that on `create_inherent` we actually need the processed and filtered +inherent data to build the block, while on `enter` the processed data should for one be identical to the incoming +inherent data (assuming honest block producers) and second it is irrelevant, as we are not building a block but just +processing it, so the processed inherent data is simply dropped. + +This also means that the `enter` function keeps data around for no good reason. This seems acceptable though as the size +of a block is rather limited. Nevertheless if we ever wanted to optimize this we can easily implement an inherent +collector that has two implementations, where one clones and stores the data and the other just passes it on. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/paras.md b/polkadot/roadmap/implementers-guide/src/runtime/paras.md index b3015bd57290..ac9b1520c3df 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/paras.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/paras.md @@ -1,14 +1,12 @@ # Paras Pallet -The Paras module is responsible for storing information on parachains. Registered -parachains cannot change except at session boundaries and after at least a full -session has passed. This is primarily to ensure that the number and meaning of bits required for the -availability bitfields does not change except at session boundaries. +The Paras module is responsible for storing information on parachains. Registered parachains cannot change except at +session boundaries and after at least a full session has passed. This is primarily to ensure that the number and meaning +of bits required for the availability bitfields does not change except at session boundaries. It's also responsible for: -- managing parachain validation code upgrades as well as maintaining availability of old parachain -code and its pruning. +- managing parachain validation code upgrades as well as maintaining availability of old parachain code and its pruning. - vetting PVFs by means of the PVF pre-checking mechanism. ## Storage @@ -102,8 +100,8 @@ struct PvfCheckActiveVoteState { #### Para Lifecycle -Because the state changes of parachains are delayed, we track the specific state of -the para using the `ParaLifecycle` enum. +Because the state changes of parachains are delayed, we track the specific state of the para using the `ParaLifecycle` +enum. ``` None Parathread (on-demand parachain) Parachain @@ -132,8 +130,8 @@ None Parathread (on-demand parachain) Parachain + + + ``` -Note that if PVF pre-checking is enabled, onboarding of a para may potentially be delayed. This can -happen due to PVF pre-checking voting concluding late. +Note that if PVF pre-checking is enabled, onboarding of a para may potentially be delayed. This can happen due to PVF +pre-checking voting concluding late. During the transition period, the para object is still considered in its existing state. @@ -210,7 +208,7 @@ UpcomingUpgrades: Vec<(ParaId, BlockNumberFor)>; ActionsQueue: map SessionIndex => Vec; /// Upcoming paras instantiation arguments. /// -/// NOTE that after PVF pre-checking is enabled the para genesis arg will have it's code set +/// NOTE that after PVF pre-checking is enabled the para genesis arg will have it's code set /// to empty. Instead, the code will be saved into the storage right away via `CodeByHash`. UpcomingParasGenesis: map ParaId => Option; /// The number of references on the validation code in `CodeByHash` storage. @@ -223,12 +221,13 @@ CodeByHash: map ValidationCodeHash => Option 1. Execute all queued actions for paralifecycle changes: 1. Clean up outgoing paras. - 1. This means removing the entries under `Heads`, `CurrentCode`, `FutureCodeUpgrades`, - `FutureCode` and `MostRecentContext`. An according entry should be added to `PastCode`, `PastCodeMeta`, and `PastCodePruning` using the outgoing `ParaId` and removed `CurrentCode` value. This is because any outdated validation code must remain available on-chain for a determined amount - of blocks, and validation code outdated by de-registering the para is still subject to that - invariant. - 1. Apply all incoming paras by initializing the `Heads` and `CurrentCode` using the genesis - parameters as well as `MostRecentContext` to `0`. + 1. This means removing the entries under `Heads`, `CurrentCode`, `FutureCodeUpgrades`, `FutureCode` and + `MostRecentContext`. An according entry should be added to `PastCode`, `PastCodeMeta`, and `PastCodePruning` + using the outgoing `ParaId` and removed `CurrentCode` value. This is because any outdated validation code must + remain available on-chain for a determined amount of blocks, and validation code outdated by de-registering the + para is still subject to that invariant. + 1. Apply all incoming paras by initializing the `Heads` and `CurrentCode` using the genesis parameters as well as + `MostRecentContext` to `0`. 1. Amend the `Parachains` list and `ParaLifecycle` to reflect changes in registered parachains. 1. Amend the `ParaLifecycle` set to reflect changes in registered on-demand parachains. 1. Upgrade all on-demand parachains that should become lease holding parachains, updating the `Parachains` list and @@ -239,40 +238,50 @@ CodeByHash: map ValidationCodeHash => Option 1. Go over all active PVF pre-checking votes: 1. Increment `age` of the vote. 1. If `age` reached `cfg.pvf_voting_ttl`, then enact PVF rejection and remove the vote from the active list. - 1. Otherwise, reinitialize the ballots. - 1. Resize the `votes_accept`/`votes_reject` to have the same length as the incoming validator set. - 1. Zero all the votes. + 1. Otherwise, reinitialize the ballots. 1. Resize the `votes_accept`/`votes_reject` to have the same length as the + incoming validator set. 1. Zero all the votes. ## Initialization -1. Do pruning based on all entries in `PastCodePruning` with `BlockNumber <= now`. Update the - corresponding `PastCodeMeta` and `PastCode` accordingly. +1. Do pruning based on all entries in `PastCodePruning` with `BlockNumber <= now`. Update the corresponding + `PastCodeMeta` and `PastCode` accordingly. 1. Toggle the upgrade related signals - 1. Collect all `(para_id, expected_at)` from `UpcomingUpgrades` where `expected_at <= now` and prune them. For each para pruned set `UpgradeGoAheadSignal` to `GoAhead`. Reserve weight for the state modification to upgrade each para pruned. - 1. Collect all `(para_id, next_possible_upgrade_at)` from `UpgradeCooldowns` where `next_possible_upgrade_at <= now`. For each para obtained this way reserve weight to remove its `UpgradeRestrictionSignal` on finalization. + 1. Collect all `(para_id, expected_at)` from `UpcomingUpgrades` where `expected_at <= now` and prune them. For each + para pruned set `UpgradeGoAheadSignal` to `GoAhead`. Reserve weight for the state modification to upgrade each para + pruned. + 1. Collect all `(para_id, next_possible_upgrade_at)` from `UpgradeCooldowns` where `next_possible_upgrade_at <= now`. + For each para obtained this way reserve weight to remove its `UpgradeRestrictionSignal` on finalization. ## Routines -* `schedule_para_initialize(ParaId, ParaGenesisArgs)`: Schedule a para to be initialized at the next - session. Noop if para is already registered in the system with some `ParaLifecycle`. -* `schedule_para_cleanup(ParaId)`: Schedule a para to be cleaned up after the next full session. -* `schedule_parathread_upgrade(ParaId)`: Schedule a parathread (on-demand parachain) to be upgraded to a parachain. -* `schedule_parachain_downgrade(ParaId)`: Schedule a parachain to be downgraded from lease holding to on-demand. -* `schedule_code_upgrade(ParaId, new_code, relay_parent: BlockNumber, HostConfiguration)`: Schedule a future code - upgrade of the given parachain. In case the PVF pre-checking is disabled, or the new code is already present in the storage, the upgrade will be applied after inclusion of a block of the same parachain - executed in the context of a relay-chain block with number >= `relay_parent + config.validation_upgrade_delay`. If the upgrade is scheduled `UpgradeRestrictionSignal` is set and it will remain set until `relay_parent + config.validation_upgrade_cooldown`. -In case the PVF pre-checking is enabled, or the new code is not already present in the storage, then the PVF pre-checking run will be scheduled for that validation code. If the pre-checking concludes with rejection, then the upgrade is canceled. Otherwise, after pre-checking is concluded the upgrade will be scheduled and be enacted as described above. -* `note_new_head(ParaId, HeadData, BlockNumber)`: note that a para has progressed to a new head, - where the new head was executed in the context of a relay-chain block with given number, the latter value is inserted into the `MostRecentContext` mapping. This will apply pending code upgrades based on the block number provided. If an upgrade took place it will clear the `UpgradeGoAheadSignal`. -* `lifecycle(ParaId) -> Option`: Return the `ParaLifecycle` of a para. -* `is_parachain(ParaId) -> bool`: Returns true if the para ID references any live lease holding parachain, - including those which may be transitioning to an on-demand parachain in the future. -* `is_parathread(ParaId) -> bool`: Returns true if the para ID references any live parathread (on-demand parachain), +- `schedule_para_initialize(ParaId, ParaGenesisArgs)`: Schedule a para to be initialized at the next session. Noop if + para is already registered in the system with some `ParaLifecycle`. +- `schedule_para_cleanup(ParaId)`: Schedule a para to be cleaned up after the next full session. +- `schedule_parathread_upgrade(ParaId)`: Schedule a parathread (on-demand parachain) to be upgraded to a parachain. +- `schedule_parachain_downgrade(ParaId)`: Schedule a parachain to be downgraded from lease holding to on-demand. +- `schedule_code_upgrade(ParaId, new_code, relay_parent: BlockNumber, HostConfiguration)`: Schedule a future code + upgrade of the given parachain. In case the PVF pre-checking is disabled, or the new code is already present in the + storage, the upgrade will be applied after inclusion of a block of the same parachain executed in the context of a +relay-chain block with number >= `relay_parent + config.validation_upgrade_delay`. If the upgrade is scheduled +`UpgradeRestrictionSignal` is set and it will remain set until `relay_parent + config.validation_upgrade_cooldown`. In +case the PVF pre-checking is enabled, or the new code is not already present in the storage, then the PVF pre-checking +run will be scheduled for that validation code. If the pre-checking concludes with rejection, then the upgrade is +canceled. Otherwise, after pre-checking is concluded the upgrade will be scheduled and be enacted as described above. +- `note_new_head(ParaId, HeadData, BlockNumber)`: note that a para has progressed to a new head, where the new head was + executed in the context of a relay-chain block with given number, the latter value is inserted into the + `MostRecentContext` mapping. This will apply pending code upgrades based on the block number provided. If an upgrade + took place it will clear the `UpgradeGoAheadSignal`. +- `lifecycle(ParaId) -> Option`: Return the `ParaLifecycle` of a para. +- `is_parachain(ParaId) -> bool`: Returns true if the para ID references any live lease holding parachain, including + those which may be transitioning to an on-demand parachain in the future. +- `is_parathread(ParaId) -> bool`: Returns true if the para ID references any live parathread (on-demand parachain), including those which may be transitioning to a lease holding parachain in the future. -* `is_valid_para(ParaId) -> bool`: Returns true if the para ID references either a live on-demand parachain - or live lease holding parachain. -* `can_upgrade_validation_code(ParaId) -> bool`: Returns true if the given para can signal code upgrade right now. -* `pvfs_require_prechecking() -> Vec`: Returns the list of PVF validation code hashes that require PVF pre-checking votes. +- `is_valid_para(ParaId) -> bool`: Returns true if the para ID references either a live on-demand parachain or live + lease holding parachain. +- `can_upgrade_validation_code(ParaId) -> bool`: Returns true if the given para can signal code upgrade right now. +- `pvfs_require_prechecking() -> Vec`: Returns the list of PVF validation code hashes that require + PVF pre-checking votes. ## Finalization -Collect all `(para_id, next_possible_upgrade_at)` from `UpgradeCooldowns` where `next_possible_upgrade_at <= now` and prune them. For each para pruned remove its `UpgradeRestrictionSignal`. +Collect all `(para_id, next_possible_upgrade_at)` from `UpgradeCooldowns` where `next_possible_upgrade_at <= now` and +prune them. For each para pruned remove its `UpgradeRestrictionSignal`. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md index 312ecedcb50f..2b8832946fc9 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md @@ -1,6 +1,7 @@ # Scheduler Pallet -> TODO: this section is still heavily under construction. key questions about availability cores and validator assignment are still open and the flow of the the section may be contradictory or inconsistent +> TODO: this section is still heavily under construction. key questions about availability cores and validator +> assignment are still open and the flow of the the section may be contradictory or inconsistent The Scheduler module is responsible for two main tasks: @@ -9,16 +10,29 @@ The Scheduler module is responsible for two main tasks: It aims to achieve these tasks with these goals in mind: -- It should be possible to know at least a block ahead-of-time, ideally more, which validators are going to be assigned to which parachains. +- It should be possible to know at least a block ahead-of-time, ideally more, which validators are going to be assigned + to which parachains. - Parachains that have a candidate pending availability in this fork of the chain should not be assigned. -- Validator assignments should not be gameable. Malicious cartels should not be able to manipulate the scheduler to assign themselves as desired. +- Validator assignments should not be gameable. Malicious cartels should not be able to manipulate the scheduler to + assign themselves as desired. - High or close to optimal throughput of parachains. Work among validator groups should be balanced. ## Availability Cores -The Scheduler manages resource allocation using the concept of "Availability Cores". There will be one availability core for each lease holding parachain, and a fixed number of cores used for multiplexing on-demand parachains. Validators will be partitioned into groups, with the same number of groups as availability cores. Validator groups will be assigned to different availability cores over time. - -An availability core can exist in either one of two states at the beginning or end of a block: free or occupied. A free availability core can have a lease holding or on-demand parachain assigned to it for the potential to have a backed candidate included. After backing, the core enters the occupied state as the backed candidate is pending availability. There is an important distinction: a core is not considered occupied until it is in charge of a block pending availability, although the implementation may treat scheduled cores the same as occupied ones for brevity. A core exits the occupied state when the candidate is no longer pending availability - either on timeout or on availability. A core starting in the occupied state can move to the free state and back to occupied all within a single block, as availability bitfields are processed before backed candidates. At the end of the block, there is a possible timeout on availability which can move the core back to the free state if occupied. +The Scheduler manages resource allocation using the concept of "Availability Cores". There will be one availability core +for each lease holding parachain, and a fixed number of cores used for multiplexing on-demand parachains. Validators +will be partitioned into groups, with the same number of groups as availability cores. Validator groups will be assigned +to different availability cores over time. + +An availability core can exist in either one of two states at the beginning or end of a block: free or occupied. A free +availability core can have a lease holding or on-demand parachain assigned to it for the potential to have a backed +candidate included. After backing, the core enters the occupied state as the backed candidate is pending availability. +There is an important distinction: a core is not considered occupied until it is in charge of a block pending +availability, although the implementation may treat scheduled cores the same as occupied ones for brevity. A core exits +the occupied state when the candidate is no longer pending availability - either on timeout or on availability. A core +starting in the occupied state can move to the free state and back to occupied all within a single block, as +availability bitfields are processed before backed candidates. At the end of the block, there is a possible timeout on +availability which can move the core back to the free state if occupied. Cores are treated as an ordered list and are typically referred to by their index in that list. @@ -82,19 +96,47 @@ digraph { ## Validator Groups -Validator group assignments do not need to change very quickly. The security benefits of fast rotation are redundant with the challenge mechanism in the [Approval process](../protocol-approval.md). Because of this, we only divide validators into groups at the beginning of the session and do not shuffle membership during the session. However, we do take steps to ensure that no particular validator group has dominance over a single lease holding parachain or on-demand parachain-multiplexer for an entire session to provide better guarantees of live-ness. - -Validator groups rotate across availability cores in a round-robin fashion, with rotation occurring at fixed intervals. The i'th group will be assigned to the `(i+k)%n`'th core at any point in time, where `k` is the number of rotations that have occurred in the session, and `n` is the number of cores. This makes upcoming rotations within the same session predictable. - -When a rotation occurs, validator groups are still responsible for distributing availability chunks for any previous cores that are still occupied and pending availability. In practice, rotation and availability-timeout frequencies should be set so this will only be the core they have just been rotated from. It is possible that a validator group is rotated onto a core which is currently occupied. In this case, the validator group will have nothing to do until the previously-assigned group finishes their availability work and frees the core or the availability process times out. Depending on if the core is for a lease holding parachain or on-demand parachain, a different timeout `t` from the [`HostConfiguration`](../types/runtime.md#host-configuration) will apply. Availability timeouts should only be triggered in the first `t-1` blocks after the beginning of a rotation. +Validator group assignments do not need to change very quickly. The security benefits of fast rotation are redundant +with the challenge mechanism in the [Approval process](../protocol-approval.md). Because of this, we only divide +validators into groups at the beginning of the session and do not shuffle membership during the session. However, we do +take steps to ensure that no particular validator group has dominance over a single lease holding parachain or on-demand +parachain-multiplexer for an entire session to provide better guarantees of live-ness. + +Validator groups rotate across availability cores in a round-robin fashion, with rotation occurring at fixed intervals. +The i'th group will be assigned to the `(i+k)%n`'th core at any point in time, where `k` is the number of rotations that +have occurred in the session, and `n` is the number of cores. This makes upcoming rotations within the same session +predictable. + +When a rotation occurs, validator groups are still responsible for distributing availability chunks for any previous +cores that are still occupied and pending availability. In practice, rotation and availability-timeout frequencies +should be set so this will only be the core they have just been rotated from. It is possible that a validator group is +rotated onto a core which is currently occupied. In this case, the validator group will have nothing to do until the +previously-assigned group finishes their availability work and frees the core or the availability process times out. +Depending on if the core is for a lease holding parachain or on-demand parachain, a different timeout `t` from the +[`HostConfiguration`](../types/runtime.md#host-configuration) will apply. Availability timeouts should only be triggered +in the first `t-1` blocks after the beginning of a rotation. ## Claims -On-demand parachains operate on a system of claims. Collators purchase claims on authoring the next block of an on-demand parachain, although the purchase mechanism is beyond the scope of the scheduler. The scheduler guarantees that they'll be given at least a certain number of attempts to author a candidate that is backed. Attempts that fail during the availability phase are not counted, since ensuring availability at that stage is the responsibility of the backing validators, not of the collator. When a claim is accepted, it is placed into a queue of claims, and each claim is assigned to a particular on-demand parachain-multiplexing core in advance. Given that the current assignments of validator groups to cores are known, and the upcoming assignments are predictable, it is possible for on-demand parachain collators to know who they should be talking to now and how they should begin establishing connections with as a fallback. - -With this information, the Node-side can be aware of which on-demand parachains have a good chance of being includable within the relay-chain block and can focus any additional resources on backing candidates from those on-demand parachains. Furthermore, Node-side code is aware of which validator group will be responsible for that thread. If the necessary conditions are reached for core reassignment, those candidates can be backed within the same block as the core being freed. - -On-demand claims, when scheduled onto a free core, may not result in a block pending availability. This may be due to collator error, networking timeout, or censorship by the validator group. In this case, the claims should be retried a certain number of times to give the collator a fair shot. +On-demand parachains operate on a system of claims. Collators purchase claims on authoring the next block of an +on-demand parachain, although the purchase mechanism is beyond the scope of the scheduler. The scheduler guarantees that +they'll be given at least a certain number of attempts to author a candidate that is backed. Attempts that fail during +the availability phase are not counted, since ensuring availability at that stage is the responsibility of the backing +validators, not of the collator. When a claim is accepted, it is placed into a queue of claims, and each claim is +assigned to a particular on-demand parachain-multiplexing core in advance. Given that the current assignments of +validator groups to cores are known, and the upcoming assignments are predictable, it is possible for on-demand +parachain collators to know who they should be talking to now and how they should begin establishing connections with as +a fallback. + +With this information, the Node-side can be aware of which on-demand parachains have a good chance of being includable +within the relay-chain block and can focus any additional resources on backing candidates from those on-demand +parachains. Furthermore, Node-side code is aware of which validator group will be responsible for that thread. If the +necessary conditions are reached for core reassignment, those candidates can be backed within the same block as the core +being freed. + +On-demand claims, when scheduled onto a free core, may not result in a block pending availability. This may be due to +collator error, networking timeout, or censorship by the validator group. In this case, the claims should be retried a +certain number of times to give the collator a fair shot. ## Storage @@ -104,7 +146,7 @@ Utility structs: // A claim on authoring the next block for a given parathread (on-demand parachain). struct ParathreadClaim(ParaId, CollatorId); -// An entry tracking a parathread (on-demand parachain) claim to ensure it does not +// An entry tracking a parathread (on-demand parachain) claim to ensure it does not // pass the maximum number of retries. struct ParathreadEntry { claim: ParathreadClaim, @@ -165,7 +207,7 @@ ParathreadClaimIndex: Vec; /// The block number where the session start occurred. Used to track how many group rotations have occurred. SessionStartBlock: BlockNumber; /// Currently scheduled cores - free but up to be occupied. -/// The value contained here will not be valid after the end of a block. +/// The value contained here will not be valid after the end of a block. /// Runtime APIs should be used to determine scheduled cores /// for the upcoming block. Scheduled: Vec, // sorted ascending by CoreIndex. @@ -173,13 +215,17 @@ Scheduled: Vec, // sorted ascending by CoreIndex. ## Session Change -Session changes are the only time that configuration can change, and the [Configuration module](configuration.md)'s session-change logic is handled before this module's. We also lean on the behavior of the [Inclusion module](inclusion.md) which clears all its occupied cores on session change. Thus we don't have to worry about cores being occupied across session boundaries and it is safe to re-size the `AvailabilityCores` bitfield. +Session changes are the only time that configuration can change, and the [Configuration module](configuration.md)'s +session-change logic is handled before this module's. We also lean on the behavior of the [Inclusion +module](inclusion.md) which clears all its occupied cores on session change. Thus we don't have to worry about cores +being occupied across session boundaries and it is safe to re-size the `AvailabilityCores` bitfield. Actions: 1. Set `SessionStartBlock` to current block number + 1, as session changes are applied at the end of the block. 1. Clear all `Some` members of `AvailabilityCores`. Return all parathread claims to queue with retries un-incremented. -1. Set `configuration = Configuration::configuration()` (see [`HostConfiguration`](../types/runtime.md#host-configuration)) +1. Set `configuration = Configuration::configuration()` (see + [`HostConfiguration`](../types/runtime.md#host-configuration)) 1. Fetch `Shared::ActiveValidators` as AV. 1. Determine the number of cores & validator groups as `n_cores`. This is the maximum of 1. `Paras::parachains().len() + configuration.parathread_cores` @@ -187,13 +233,18 @@ Actions: 1. Resize `AvailabilityCores` to have length `n_cores` with all `None` entries. 1. Compute new validator groups by shuffling using a secure randomness beacon - Note that the total number of validators `V` in AV may not be evenly divided by `n_cores`. - - The groups are selected by partitioning AV. The first `V % N` groups will have `(V / n_cores) + 1` members, while the remaining groups will have `(V / N)` members each. - - Instead of using the indices within AV, which point to the broader set, indices _into_ AV should be used. This implies that groups should have simply ascending validator indices. + - The groups are selected by partitioning AV. The first `V % N` groups will have `(V / n_cores) + 1` members, while + the remaining groups will have `(V / N)` members each. + - Instead of using the indices within AV, which point to the broader set, indices _into_ AV should be used. This + implies that groups should have simply ascending validator indices. 1. Prune the parathread (on-demand parachain) queue to remove all retries beyond `configuration.parathread_retries`. - Also prune all on-demand claims corresponding to de-registered parachains. - all pruned claims should have their entry removed from the parathread (on-demand parachain) index. - - assign all non-pruned claims to new cores if the number of on-demand parachain cores has changed between the `new_config` and `old_config` of the `SessionChangeNotification`. - - Assign claims in equal balance across all cores if rebalancing, and set the `next_core` of the `ParathreadQueue` (on-demand queue) by incrementing the relative index of the last assigned core and taking it modulo the number of on-demand cores. + - assign all non-pruned claims to new cores if the number of on-demand parachain cores has changed between the + `new_config` and `old_config` of the `SessionChangeNotification`. + - Assign claims in equal balance across all cores if rebalancing, and set the `next_core` of the `ParathreadQueue` + (on-demand queue) by incrementing the relative index of the last assigned core and taking it modulo the number of + on-demand cores. ## Initialization @@ -208,28 +259,52 @@ No finalization routine runs for this module. - `add_parathread_claim(ParathreadClaim)`: Add a parathread (on-demand parachain) claim to the queue. - Fails if any on-demand claim on the same parachain is currently indexed. - Fails if the queue length is >= `config.scheduling_lookahead * config.parathread_cores`. - - The core used for the on-demand claim is the `next_core` field of the `ParathreadQueue` (on-demand queue) and adding `Paras::parachains().len()` to it. + - The core used for the on-demand claim is the `next_core` field of the `ParathreadQueue` (on-demand queue) and adding + `Paras::parachains().len()` to it. - `next_core` is then updated by adding 1 and taking it modulo `config.parathread_cores`. - The claim is then added to the claim index. -- `free_cores(Vec<(CoreIndex, FreedReason)>)`: indicate previosuly-occupied cores which are to be considered returned and why they are being returned. +- `free_cores(Vec<(CoreIndex, FreedReason)>)`: indicate previosuly-occupied cores which are to be considered returned + and why they are being returned. - All freed lease holding parachain cores should be assigned to their respective parachain - - All freed on-demand parachain cores whose reason for freeing was `FreedReason::Concluded` should have the claim removed from the claim index. - - All freed on-demand cores whose reason for freeing was `FreedReason::TimedOut` should have the claim added to the parathread queue (on-demand queue) again without retries incremented + - All freed on-demand parachain cores whose reason for freeing was `FreedReason::Concluded` should have the claim + removed from the claim index. + - All freed on-demand cores whose reason for freeing was `FreedReason::TimedOut` should have the claim added to the + parathread queue (on-demand queue) again without retries incremented - All freed on-demand cores should take the next on-demand parachain entry from the queue. -- `schedule(Vec<(CoreIndex, FreedReason)>, now: BlockNumber)`: schedule new core assignments, with a parameter indicating previously-occupied cores which are to be considered returned and why they are being returned. +- `schedule(Vec<(CoreIndex, FreedReason)>, now: BlockNumber)`: schedule new core assignments, with a parameter + indicating previously-occupied cores which are to be considered returned and why they are being returned. - Invoke `free_cores(freed_cores)` - - The i'th validator group will be assigned to the `(i+k)%n`'th core at any point in time, where `k` is the number of rotations that have occurred in the session, and `n` is the total number of cores. This makes upcoming rotations within the same session predictable. Rotations are based off of `now`. + - The i'th validator group will be assigned to the `(i+k)%n`'th core at any point in time, where `k` is the number of + rotations that have occurred in the session, and `n` is the total number of cores. This makes upcoming rotations + within the same session predictable. Rotations are based off of `now`. - `scheduled() -> Vec`: Get currently scheduled core assignments. - `occupied(Vec)`. Note that the given cores have become occupied. - Behavior undefined if any given cores were not scheduled. - Behavior undefined if the given cores are not sorted ascending by core index - This clears them from `Scheduled` and marks each corresponding `core` in the `AvailabilityCores` as occupied. - - Since both the availability cores and the newly-occupied cores lists are sorted ascending, this method can be implemented efficiently. + - Since both the availability cores and the newly-occupied cores lists are sorted ascending, this method can be + implemented efficiently. - `core_para(CoreIndex) -> ParaId`: return the currently-scheduled or occupied ParaId for the given core. -- `group_validators(GroupIndex) -> Option>`: return all validators in a given group, if the group index is valid for this session. -- `availability_timeout_predicate() -> Option bool>`: returns an optional predicate that should be used for timing out occupied cores. if `None`, no timing-out should be done. The predicate accepts the index of the core, and the block number since which it has been occupied. The predicate should be implemented based on the time since the last validator group rotation, and the respective parachain timeouts, i.e. only within `max(config.chain_availability_period, config.thread_availability_period)` of the last rotation would this return `Some`. +- `group_validators(GroupIndex) -> Option>`: return all validators in a given group, if the group + index is valid for this session. +- `availability_timeout_predicate() -> Option bool>`: returns an optional predicate + that should be used for timing out occupied cores. if `None`, no timing-out should be done. The predicate accepts the + index of the core, and the block number since which it has been occupied. The predicate should be implemented based on + the time since the last validator group rotation, and the respective parachain timeouts, i.e. only within + `max(config.chain_availability_period, config.thread_availability_period)` of the last rotation would this return + `Some`. - `group_rotation_info(now: BlockNumber) -> GroupRotationInfo`: Returns a helper for determining group rotation. -- `next_up_on_available(CoreIndex) -> Option`: Return the next thing that will be scheduled on this core assuming it is currently occupied and the candidate occupying it became available. Returns in `ScheduledCore` format (todo: link to Runtime APIs page; linkcheck doesn't allow this right now). For lease holding parachains, this is always the ID of the parachain and no specified collator. For on-demand parachains, this is based on the next item in the `ParathreadQueue` (on-demand queue) assigned to that core, and is `None` if there isn't one. -- `next_up_on_time_out(CoreIndex) -> Option`: Return the next thing that will be scheduled on this core assuming it is currently occupied and the candidate occupying it timed out. Returns in `ScheduledCore` format (todo: link to Runtime APIs page; linkcheck doesn't allow this right now). For parachains, this is always the ID of the parachain and no specified collator. For on-demand parachains, this is based on the next item in the `ParathreadQueue` (on-demand queue) assigned to that core, or if there isn't one, the claim that is currently occupying the core. Otherwise `None`. +- `next_up_on_available(CoreIndex) -> Option`: Return the next thing that will be scheduled on this core + assuming it is currently occupied and the candidate occupying it became available. Returns in `ScheduledCore` format + (todo: link to Runtime APIs page; linkcheck doesn't allow this right now). For lease holding parachains, this is + always the ID of the parachain and no specified collator. For on-demand parachains, this is based on the next item in + the `ParathreadQueue` (on-demand queue) assigned to that core, and is `None` if there isn't one. +- `next_up_on_time_out(CoreIndex) -> Option`: Return the next thing that will be scheduled on this core + assuming it is currently occupied and the candidate occupying it timed out. Returns in `ScheduledCore` format (todo: + link to Runtime APIs page; linkcheck doesn't allow this right now). For parachains, this is always the ID of the + parachain and no specified collator. For on-demand parachains, this is based on the next item in the `ParathreadQueue` + (on-demand queue) assigned to that core, or if there isn't one, the claim that is currently occupying the core. + Otherwise `None`. - `clear()`: - - Free all scheduled cores and return on-demand claims to queue, with retries incremented. Skip on-demand parachains which no longer exist under paras. + - Free all scheduled cores and return on-demand claims to queue, with retries incremented. Skip on-demand parachains + which no longer exist under paras. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/session_info.md b/polkadot/roadmap/implementers-guide/src/runtime/session_info.md index 5ee63ab5a903..0442ee57505d 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/session_info.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/session_info.md @@ -1,6 +1,8 @@ # Session Info -For disputes and approvals, we need access to information about validator sets from prior sessions. We also often want easy access to the same information about the current session's validator set. This module aggregates and stores this information in a rolling window while providing easy APIs for access. +For disputes and approvals, we need access to information about validator sets from prior sessions. We also often want +easy access to the same information about the current session's validator set. This module aggregates and stores this +information in a rolling window while providing easy APIs for access. ## Storage @@ -66,10 +68,14 @@ Sessions: map SessionIndex => Option, ## Session Change -1. Update `EarliestStoredSession` based on `config.dispute_period` and remove all entries from `Sessions` from the previous value up to the new value. -1. Create a new entry in `Sessions` with information about the current session. Use `shared::ActiveValidators` to determine the indices into the broader validator sets (validation, assignment, discovery) which are actually used for parachain validation. Only these validators should appear in the `SessionInfo`. +1. Update `EarliestStoredSession` based on `config.dispute_period` and remove all entries from `Sessions` from the + previous value up to the new value. +1. Create a new entry in `Sessions` with information about the current session. Use `shared::ActiveValidators` to + determine the indices into the broader validator sets (validation, assignment, discovery) which are actually used for + parachain validation. Only these validators should appear in the `SessionInfo`. ## Routines * `earliest_stored_session() -> SessionIndex`: Yields the earliest session for which we have information stored. -* `session_info(session: SessionIndex) -> Option`: Yields the session info for the given session, if stored. +* `session_info(session: SessionIndex) -> Option`: Yields the session info for the given session, if + stored. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/shared.md b/polkadot/roadmap/implementers-guide/src/runtime/shared.md index 0f173134e2a2..ebed240838ab 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/shared.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/shared.md @@ -2,11 +2,11 @@ This module is responsible for managing shared storage and configuration for other modules. -It is important that other pallets are able to use the Shared Module, so it should not have a -dependency on any other modules in the Parachains Runtime. +It is important that other pallets are able to use the Shared Module, so it should not have a dependency on any other +modules in the Parachains Runtime. -For the moment, it is used exclusively to track the current session index across the Parachains -Runtime system, and when it should be allowed to schedule future changes to Paras or Configurations. +For the moment, it is used exclusively to track the current session index across the Parachains Runtime system, and when +it should be allowed to schedule future changes to Paras or Configurations. ## Constants @@ -57,24 +57,26 @@ AllowedRelayParents: AllowedRelayParentsTracker, The Shared Module currently has no initialization routines. -The Shared Module is initialized directly after the Configuration module, but before all other -modules. It is important to update the Shared Module before any other module since its state may be -used within the logic of other modules, and it is important that the state is consistent across -them. +The Shared Module is initialized directly after the Configuration module, but before all other modules. It is important +to update the Shared Module before any other module since its state may be used within the logic of other modules, and +it is important that the state is consistent across them. ## Session Change -During a session change, the Shared Module receives and stores the current Session Index directly from the initializer module, along with the broader validator set, and it returns the new list of validators. +During a session change, the Shared Module receives and stores the current Session Index directly from the initializer +module, along with the broader validator set, and it returns the new list of validators. -The list of validators should be first shuffled according to the chain's random seed and then truncated. The indices of these validators should be set to `ActiveValidatorIndices` and then returned back to the initializer. `ActiveValidatorKeys` should be set accordingly. +The list of validators should be first shuffled according to the chain's random seed and then truncated. The indices of +these validators should be set to `ActiveValidatorIndices` and then returned back to the initializer. +`ActiveValidatorKeys` should be set accordingly. This information is used in the: -* Configuration Module: For delaying updates to configurations until at lease one full session has - passed. +* Configuration Module: For delaying updates to configurations until at lease one full session has passed. * Paras Module: For delaying updates to paras until at least one full session has passed. -Allowed relay parents buffer, which is maintained by [ParaInherent](./parainherent.md) module, is cleared on every session change. +Allowed relay parents buffer, which is maintained by [ParaInherent](./parainherent.md) module, is cleared on every +session change. ## Finalization @@ -82,6 +84,6 @@ The Shared Module currently has no finalization routines. ## Functions -* `scheduled_sessions() -> SessionIndex`: Return the next session index where updates to the - Parachains Runtime system would be safe to apply. +* `scheduled_sessions() -> SessionIndex`: Return the next session index where updates to the Parachains Runtime system + would be safe to apply. * `set_session_index(SessionIndex)`: For tests. Set the current session index in the Shared Module. diff --git a/polkadot/roadmap/implementers-guide/src/types/approval.md b/polkadot/roadmap/implementers-guide/src/types/approval.md index b58e0a8187e1..bc33f024426f 100644 --- a/polkadot/roadmap/implementers-guide/src/types/approval.md +++ b/polkadot/roadmap/implementers-guide/src/types/approval.md @@ -6,9 +6,11 @@ The public key of a keypair used by a validator for determining assignments to a ## `AssignmentCert` -An `AssignmentCert`, short for Assignment Certificate, is a piece of data provided by a validator to prove that they have been selected to perform approval checks on an included candidate. +An `AssignmentCert`, short for Assignment Certificate, is a piece of data provided by a validator to prove that they +have been selected to perform approval checks on an included candidate. -These certificates can be checked in the context of a specific block, candidate, and validator assignment VRF key. The block state will also provide further context about the availability core states at that block. +These certificates can be checked in the context of a specific block, candidate, and validator assignment VRF key. The +block state will also provide further context about the availability core states at that block. ```rust enum AssignmentCertKind { @@ -53,7 +55,8 @@ struct ApprovalVote(Hash); ## `SignedApprovalVote` -An approval vote signed with a validator's key. This should be verifiable under the `ValidatorId` corresponding to the `ValidatorIndex` of the session, which should be implicit from context. +An approval vote signed with a validator's key. This should be verifiable under the `ValidatorId` corresponding to the +`ValidatorIndex` of the session, which should be implicit from context. ```rust struct SignedApprovalVote { @@ -65,9 +68,11 @@ struct SignedApprovalVote { ## `IndirectSignedApprovalVote` -A signed approval vote which references the candidate indirectly via the block. If there exists a look-up to the candidate hash from the block hash and candidate index, then this can be transformed into a `SignedApprovalVote`. +A signed approval vote which references the candidate indirectly via the block. If there exists a look-up to the +candidate hash from the block hash and candidate index, then this can be transformed into a `SignedApprovalVote`. -Although this vote references the candidate by a specific block hash and candidate index, the signature is computed on the actual `SignedApprovalVote` payload. +Although this vote references the candidate by a specific block hash and candidate index, the signature is computed on +the actual `SignedApprovalVote` payload. ```rust struct IndirectSignedApprovalVote { @@ -82,7 +87,9 @@ struct IndirectSignedApprovalVote { ## `CheckedAssignmentCert` -An assignment cert which has checked both the VRF and the validity of the implied assignment according to the selection criteria rules of the protocol. This type should be declared in such a way as to be instantiatable only when the checks have actually been done. Fields should be accessible via getters, not direct struct access. +An assignment cert which has checked both the VRF and the validity of the implied assignment according to the selection +criteria rules of the protocol. This type should be declared in such a way as to be instantiatable only when the checks +have actually been done. Fields should be accessible via getters, not direct struct access. ```rust struct CheckedAssignmentCert { diff --git a/polkadot/roadmap/implementers-guide/src/types/availability.md b/polkadot/roadmap/implementers-guide/src/types/availability.md index e2b90e86f43f..a04b896c1281 100644 --- a/polkadot/roadmap/implementers-guide/src/types/availability.md +++ b/polkadot/roadmap/implementers-guide/src/types/availability.md @@ -1,13 +1,12 @@ # Availability -One of the key roles of validators is to ensure availability of all data necessary to validate -candidates for the duration of a challenge period. This is done via an erasure-coding of the data to keep available. +One of the key roles of validators is to ensure availability of all data necessary to validate candidates for the +duration of a challenge period. This is done via an erasure-coding of the data to keep available. ## Signed Availability Bitfield A bitfield [signed](backing.md#signed-wrapper) by a particular validator about the availability of pending candidates. - ```rust type SignedAvailabilityBitfield = Signed; @@ -16,26 +15,30 @@ struct Bitfields(Vec<(SignedAvailabilityBitfield)>), // bitfields sorted by vali ### Semantics -A `SignedAvailabilityBitfield` represents the view from a particular validator's perspective. Each bit in the bitfield corresponds to a single [availability core](../runtime-api/availability-cores.md). A `1` bit indicates that the validator believes the following statements to be true for a core: +A `SignedAvailabilityBitfield` represents the view from a particular validator's perspective. Each bit in the bitfield +corresponds to a single [availability core](../runtime-api/availability-cores.md). A `1` bit indicates that the +validator believes the following statements to be true for a core: - the availability core is occupied -- there exists a [`CommittedCandidateReceipt`](candidate.html#committed-candidate-receipt) corresponding to that core. In other words, that para has a block in progress. +- there exists a [`CommittedCandidateReceipt`](candidate.html#committed-candidate-receipt) corresponding to that core. + In other words, that para has a block in progress. - the validator's [Availability Store](../node/utility/availability-store.md) contains a chunk of that parablock's PoV. In other words, it is the transpose of [`OccupiedCore::availability`](../runtime-api/availability-cores.md). ## Proof-of-Validity -Often referred to as PoV, this is a type-safe wrapper around bytes (`Vec`) when referring to data that acts as a stateless-client proof of validity of a candidate, when used as input to the validation function of the para. +Often referred to as PoV, this is a type-safe wrapper around bytes (`Vec`) when referring to data that acts as a +stateless-client proof of validity of a candidate, when used as input to the validation function of the para. ```rust struct PoV(Vec); ``` - ## Available Data -This is the data we want to keep available for each [candidate](candidate.md) included in the relay chain. This is the PoV of the block, as well as the [`PersistedValidationData`](candidate.md#persistedvalidationdata) +This is the data we want to keep available for each [candidate](candidate.md) included in the relay chain. This is the +PoV of the block, as well as the [`PersistedValidationData`](candidate.md#persistedvalidationdata) ```rust struct AvailableData { @@ -50,7 +53,10 @@ struct AvailableData { ## Erasure Chunk -The [`AvailableData`](#availabledata) is split up into an erasure-coding as part of the availability process. Each validator gets a chunk. This describes one of those chunks, along with its proof against a merkle root hash, which should be apparent from context, and is the `erasure_root` field of a [`CandidateDescriptor`](candidate.md#candidatedescriptor). +The [`AvailableData`](#availabledata) is split up into an erasure-coding as part of the availability process. Each +validator gets a chunk. This describes one of those chunks, along with its proof against a merkle root hash, which +should be apparent from context, and is the `erasure_root` field of a +[`CandidateDescriptor`](candidate.md#candidatedescriptor). ```rust diff --git a/polkadot/roadmap/implementers-guide/src/types/backing.md b/polkadot/roadmap/implementers-guide/src/types/backing.md index 5fcb3ae161b6..7e43325ec5cd 100644 --- a/polkadot/roadmap/implementers-guide/src/types/backing.md +++ b/polkadot/roadmap/implementers-guide/src/types/backing.md @@ -1,12 +1,15 @@ # Backing Types -[Candidates](candidate.md) go through many phases before being considered included in a fork of the relay chain and eventually accepted. +[Candidates](candidate.md) go through many phases before being considered included in a fork of the relay chain and +eventually accepted. -These types describe the data used in the backing phase. Some are sent over the wire within subsystems, and some are simply included in the relay-chain block. +These types describe the data used in the backing phase. Some are sent over the wire within subsystems, and some are +simply included in the relay-chain block. ## Validity Attestation -An attestation of validity for a candidate, used as part of a backing. Both the `Seconded` and `Valid` statements are considered attestations of validity. This structure is only useful where the candidate referenced is apparent. +An attestation of validity for a candidate, used as part of a backing. Both the `Seconded` and `Valid` statements are +considered attestations of validity. This structure is only useful where the candidate referenced is apparent. ```rust enum ValidityAttestation { @@ -21,7 +24,8 @@ enum ValidityAttestation { ## Signed Wrapper -There are a few distinct types which we desire to sign, and validate the signatures of. Instead of duplicating this work, we extract a signed wrapper. +There are a few distinct types which we desire to sign, and validate the signatures of. Instead of duplicating this +work, we extract a signed wrapper. ```rust,ignore /// A signed type which encapsulates the common desire to sign some data and validate a signature. @@ -44,13 +48,18 @@ impl, RealPayload: Encode> Signed`. Therefore, for the generic case where `RealPayload = Payload`, it changes nothing. However, we `impl EncodeAs for Statement`, which helps efficiency. +`EncodeAs` is a helper trait with a blanket impl which ensures that any `T` can `EncodeAs`. Therefore, for the +generic case where `RealPayload = Payload`, it changes nothing. However, we `impl EncodeAs for +Statement`, which helps efficiency. ## Statement Type -The [Candidate Backing subsystem](../node/backing/candidate-backing.md) issues and signs these after candidate validation. +The [Candidate Backing subsystem](../node/backing/candidate-backing.md) issues and signs these after candidate +validation. ```rust /// A statement about the validity of a parachain candidate. @@ -94,11 +103,13 @@ pub type SignedFullStatement = Signed; pub type SignedStatement = Signed; ``` -Munging the signed `Statement` into a `CompactStatement` before signing allows the candidate receipt itself to be omitted when checking a signature on a `Seconded` statement. +Munging the signed `Statement` into a `CompactStatement` before signing allows the candidate receipt itself to be +omitted when checking a signature on a `Seconded` statement. ## Backed Candidate -An [`CommittedCandidateReceipt`](candidate.md#committed-candidate-receipt) along with all data necessary to prove its backing. This is submitted to the relay-chain to process and move along the candidate to the pending-availability stage. +An [`CommittedCandidateReceipt`](candidate.md#committed-candidate-receipt) along with all data necessary to prove its +backing. This is submitted to the relay-chain to process and move along the candidate to the pending-availability stage. ```rust struct BackedCandidate { diff --git a/polkadot/roadmap/implementers-guide/src/types/candidate.md b/polkadot/roadmap/implementers-guide/src/types/candidate.md index a37f98054c5e..00176229e5a4 100644 --- a/polkadot/roadmap/implementers-guide/src/types/candidate.md +++ b/polkadot/roadmap/implementers-guide/src/types/candidate.md @@ -1,15 +1,18 @@ # Candidate Types -Para candidates are some of the most common types, both within the runtime and on the Node-side. -Candidates are the fundamental datatype for advancing parachains, encapsulating the collator's signature, the context of the parablock, the commitments to the output, and a commitment to the data which proves it valid. +Para candidates are some of the most common types, both within the runtime and on the Node-side. Candidates are the +fundamental datatype for advancing parachains, encapsulating the collator's signature, the context of the parablock, the +commitments to the output, and a commitment to the data which proves it valid. -In a way, this entire guide is about these candidates: how they are scheduled, constructed, backed, included, and challenged. +In a way, this entire guide is about these candidates: how they are scheduled, constructed, backed, included, and +challenged. This section will describe the base candidate type, its components, and variants that contain extra data. ## Para Id -A unique 32-bit identifier referring to a specific para (chain or thread). The relay-chain runtime guarantees that `ParaId`s are unique for the duration of any session, but recycling and reuse over a longer period of time is permitted. +A unique 32-bit identifier referring to a specific para (chain or thread). The relay-chain runtime guarantees that +`ParaId`s are unique for the duration of any session, but recycling and reuse over a longer period of time is permitted. ```rust struct ParaId(u32); @@ -17,9 +20,12 @@ struct ParaId(u32); ## Candidate Receipt -Much info in a [`FullCandidateReceipt`](#full-candidate-receipt) is duplicated from the relay-chain state. When the corresponding relay-chain state is considered widely available, the Candidate Receipt should be favored over the `FullCandidateReceipt`. +Much info in a [`FullCandidateReceipt`](#full-candidate-receipt) is duplicated from the relay-chain state. When the +corresponding relay-chain state is considered widely available, the Candidate Receipt should be favored over the +`FullCandidateReceipt`. -Examples of situations where the state is readily available includes within the scope of work done by subsystems working on a given relay-parent, or within the logic of the runtime importing a backed candidate. +Examples of situations where the state is readily available includes within the scope of work done by subsystems working +on a given relay-parent, or within the logic of the runtime importing a backed candidate. ```rust /// A candidate-receipt. @@ -33,9 +39,13 @@ struct CandidateReceipt { ## Full Candidate Receipt -This is the full receipt type. The `PersistedValidationData` are technically redundant with the `inner.relay_parent`, which uniquely describes the block in the blockchain from whose state these values are derived. The [`CandidateReceipt`](#candidate-receipt) variant is often used instead for this reason. +This is the full receipt type. The `PersistedValidationData` are technically redundant with the `inner.relay_parent`, +which uniquely describes the block in the blockchain from whose state these values are derived. The +[`CandidateReceipt`](#candidate-receipt) variant is often used instead for this reason. -However, the Full Candidate Receipt type is useful as a means of avoiding the implicit dependency on availability of old blockchain state. In situations such as availability and approval, having the full description of the candidate within a self-contained struct is convenient. +However, the Full Candidate Receipt type is useful as a means of avoiding the implicit dependency on availability of old +blockchain state. In situations such as availability and approval, having the full description of the candidate within a +self-contained struct is convenient. ```rust /// All data pertaining to the execution of a para candidate. @@ -47,9 +57,13 @@ struct FullCandidateReceipt { ## Committed Candidate Receipt -This is a variant of the candidate receipt which includes the commitments of the candidate receipt alongside the descriptor. This should be favored over the [`Candidate Receipt`](#candidate-receipt) in situations where the candidate is not going to be executed but the actual data committed to is important. This is often the case in the backing phase. +This is a variant of the candidate receipt which includes the commitments of the candidate receipt alongside the +descriptor. This should be favored over the [`Candidate Receipt`](#candidate-receipt) in situations where the candidate +is not going to be executed but the actual data committed to is important. This is often the case in the backing phase. -The hash of the committed candidate receipt will be the same as the corresponding [`Candidate Receipt`](#candidate-receipt), because it is computed by first hashing the encoding of the commitments to form a plain [`Candidate Receipt`](#candidate-receipt). +The hash of the committed candidate receipt will be the same as the corresponding [`Candidate +Receipt`](#candidate-receipt), because it is computed by first hashing the encoding of the commitments to form a plain +[`Candidate Receipt`](#candidate-receipt). ```rust /// A candidate-receipt with commitments directly included. @@ -110,15 +124,24 @@ pub struct ValidationParams { ## `PersistedValidationData` -The validation data provides information about how to create the inputs for validation of a candidate. This information is derived from the chain state and will vary from para to para, although some of the fields may be the same for every para. +The validation data provides information about how to create the inputs for validation of a candidate. This information +is derived from the chain state and will vary from para to para, although some of the fields may be the same for every +para. -Since this data is used to form inputs to the validation function, it needs to be persisted by the availability system to avoid dependence on availability of the relay-chain state. +Since this data is used to form inputs to the validation function, it needs to be persisted by the availability system +to avoid dependence on availability of the relay-chain state. -Furthermore, the validation data acts as a way to authorize the additional data the collator needs to pass to the validation function. For example, the validation function can check whether the incoming messages (e.g. downward messages) were actually sent by using the data provided in the validation data using so called MQC heads. +Furthermore, the validation data acts as a way to authorize the additional data the collator needs to pass to the +validation function. For example, the validation function can check whether the incoming messages (e.g. downward +messages) were actually sent by using the data provided in the validation data using so called MQC heads. -Since the commitments of the validation function are checked by the relay-chain, approval checkers can rely on the invariant that the relay-chain only includes para-blocks for which these checks have already been done. As such, there is no need for the validation data used to inform validators and collators about the checks the relay-chain will perform to be persisted by the availability system. +Since the commitments of the validation function are checked by the relay-chain, approval checkers can rely on the +invariant that the relay-chain only includes para-blocks for which these checks have already been done. As such, there +is no need for the validation data used to inform validators and collators about the checks the relay-chain will perform +to be persisted by the availability system. -The `PersistedValidationData` should be relatively lightweight primarily because it is constructed during inclusion for each candidate and therefore lies on the critical path of inclusion. +The `PersistedValidationData` should be relatively lightweight primarily because it is constructed during inclusion for +each candidate and therefore lies on the critical path of inclusion. ```rust struct PersistedValidationData { @@ -150,7 +173,8 @@ struct HeadData(Vec); ## Candidate Commitments -The execution and validation of parachain candidates produces a number of values which either must be committed to blocks on the relay chain or committed to the state of the relay chain. +The execution and validation of parachain candidates produces a number of values which either must be committed to +blocks on the relay chain or committed to the state of the relay chain. ```rust /// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. @@ -174,7 +198,9 @@ struct CandidateCommitments { ## Signing Context -This struct provides context to signatures by combining with various payloads to localize the signature to a particular session index and relay-chain hash. Having these fields included in the signature makes misbehavior attribution much simpler. +This struct provides context to signatures by combining with various payloads to localize the signature to a particular +session index and relay-chain hash. Having these fields included in the signature makes misbehavior attribution much +simpler. ```rust struct SigningContext { diff --git a/polkadot/roadmap/implementers-guide/src/types/disputes.md b/polkadot/roadmap/implementers-guide/src/types/disputes.md index 24f152b1308f..c49e0fea2625 100644 --- a/polkadot/roadmap/implementers-guide/src/types/disputes.md +++ b/polkadot/roadmap/implementers-guide/src/types/disputes.md @@ -28,7 +28,8 @@ enum DisputeStatement { ## Dispute Statement Kinds -Kinds of dispute statements. Each of these can be combined with a candidate hash, session index, validator public key, and validator signature to reproduce and check the original statement. +Kinds of dispute statements. Each of these can be combined with a candidate hash, session index, validator public key, +and validator signature to reproduce and check the original statement. ```rust enum ValidDisputeStatementKind { diff --git a/polkadot/roadmap/implementers-guide/src/types/network.md b/polkadot/roadmap/implementers-guide/src/types/network.md index b698ca2075bf..60f5bda28fa9 100644 --- a/polkadot/roadmap/implementers-guide/src/types/network.md +++ b/polkadot/roadmap/implementers-guide/src/types/network.md @@ -139,7 +139,8 @@ enum CollationProtocolV1 { ## Network Bridge Event -These updates are posted from the [Network Bridge Subsystem](../node/utility/network-bridge.md) to other subsystems based on registered listeners. +These updates are posted from the [Network Bridge Subsystem](../node/utility/network-bridge.md) to other subsystems +based on registered listeners. ```rust struct NewGossipTopology { diff --git a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md index 3d9037699da6..fababbff3540 100644 --- a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -1,6 +1,7 @@ # Overseer Protocol -This chapter contains message types sent to and from the overseer, and the underlying subsystem message types that are transmitted using these. +This chapter contains message types sent to and from the overseer, and the underlying subsystem message types that are +transmitted using these. ## Overseer Signal @@ -17,7 +18,8 @@ enum OverseerSignal { } ``` -All subsystems have their own message types; all of them need to be able to listen for overseer signals as well. There are currently two proposals for how to handle that with unified communication channels: +All subsystems have their own message types; all of them need to be able to listen for overseer signals as well. There +are currently two proposals for how to handle that with unified communication channels: 1. Retaining the `OverseerSignal` definition above, add `enum FromOrchestra {Signal(OverseerSignal), Message(T)}`. 1. Add a generic varint to `OverseerSignal`: `Message(T)`. @@ -26,7 +28,8 @@ Either way, there will be some top-level type encapsulating messages from the ov ## Active Leaves Update -Indicates a change in active leaves. Activated leaves should have jobs, whereas deactivated leaves should lead to winding-down of work based on those leaves. +Indicates a change in active leaves. Activated leaves should have jobs, whereas deactivated leaves should lead to +winding-down of work based on those leaves. ```rust enum LeafStatus { @@ -201,7 +204,8 @@ enum ApprovalDistributionMessage { Messages received by the availability distribution subsystem. -This is a network protocol that receives messages of type [`AvailabilityDistributionV1Message`][AvailabilityDistributionV1NetworkMessage]. +This is a network protocol that receives messages of type +[`AvailabilityDistributionV1Message`][AvailabilityDistributionV1NetworkMessage]. ```rust enum AvailabilityDistributionMessage { @@ -293,7 +297,7 @@ pub enum AvailabilityStoreMessage { tx: oneshot::Sender>, }, - /// Computes and checks the erasure root of `AvailableData` before storing all of its chunks in + /// Computes and checks the erasure root of `AvailableData` before storing all of its chunks in /// the AV store. /// /// Return `Ok(())` if the store operation succeeded, `Err(StoreAvailableData)` if it failed. @@ -319,8 +323,8 @@ pub enum StoreAvailableDataError { ## Bitfield Distribution Message -Messages received by the bitfield distribution subsystem. -This is a network protocol that receives messages of type [`BitfieldDistributionV1Message`][BitfieldDistributionV1NetworkMessage]. +Messages received by the bitfield distribution subsystem. This is a network protocol that receives messages of type +[`BitfieldDistributionV1Message`][BitfieldDistributionV1NetworkMessage]. ```rust enum BitfieldDistributionMessage { @@ -354,7 +358,7 @@ enum CandidateBackingMessage { /// The PoV is expected to match the `pov_hash` in the descriptor. Second(Hash, CandidateReceipt, PoV), /// Note a peer validator's statement about a particular candidate. Disagreements about validity must be escalated - /// to a broader check by the Disputes Subsystem, though that escalation is deferred until the approval voting + /// to a broader check by the Disputes Subsystem, though that escalation is deferred until the approval voting /// stage to guarantee availability. Agreements are simply tallied until a quorum is reached. Statement(Statement), } @@ -420,7 +424,8 @@ enum ChainSelectionMessage { Messages received by the [Collator Protocol subsystem](../node/collators/collator-protocol.md) -This is a network protocol that receives messages of type [`CollatorProtocolV1Message`][CollatorProtocolV1NetworkMessage]. +This is a network protocol that receives messages of type +[`CollatorProtocolV1Message`][CollatorProtocolV1NetworkMessage]. ```rust enum CollatorProtocolMessage { @@ -452,7 +457,8 @@ enum CollatorProtocolMessage { Messages received by the [Collation Generation subsystem](../node/collators/collation-generation.md) -This is the core interface by which collators built on top of a Polkadot node submit collations to validators. As such, these messages are not sent by any subsystem but are instead sent from outside of the overseer. +This is the core interface by which collators built on top of a Polkadot node submit collations to validators. As such, +these messages are not sent by any subsystem but are instead sent from outside of the overseer. ```rust /// A function provided to the subsystem which it uses to pull new collations. @@ -503,7 +509,8 @@ enum CollationGenerationMessage { Messages received by the [Dispute Coordinator subsystem](../node/disputes/dispute-coordinator.md) -This subsystem coordinates participation in disputes, tracks live disputes, and observed statements of validators from subsystems. +This subsystem coordinates participation in disputes, tracks live disputes, and observed statements of validators from +subsystems. ```rust enum DisputeCoordinatorMessage { @@ -572,11 +579,9 @@ pub enum ImportStatementsResult { } ``` - ## Dispute Distribution Message -Messages received by the [Dispute Distribution -subsystem](../node/disputes/dispute-distribution.md). This subsystem is +Messages received by the [Dispute Distribution subsystem](../node/disputes/dispute-distribution.md). This subsystem is responsible of distributing explicit dispute statements. ```rust @@ -602,8 +607,8 @@ enum DisputeDistributionMessage { ## Network Bridge Message -Messages received by the network bridge. This subsystem is invoked by others to manipulate access -to the low-level networking code. +Messages received by the network bridge. This subsystem is invoked by others to manipulate access to the low-level +networking code. ```rust /// Peer-sets handled by the network bridge. @@ -778,7 +783,8 @@ enum ProvisionerMessage { The Runtime API subsystem is responsible for providing an interface to the state of the chain's runtime. -This is fueled by an auxiliary type encapsulating all request types defined in the [Runtime API section](../runtime-api) of the guide. +This is fueled by an auxiliary type encapsulating all request types defined in the [Runtime API section](../runtime-api) +of the guide. ```rust enum RuntimeApiRequest { @@ -835,10 +841,12 @@ enum RuntimeApiMessage { ## Statement Distribution Message -The Statement Distribution subsystem distributes signed statements and candidates from validators to other validators. It does this by distributing full statements, which embed the candidate receipt, as opposed to compact statements which don't. -It receives updates from the network bridge and signed statements to share with other validators. +The Statement Distribution subsystem distributes signed statements and candidates from validators to other validators. +It does this by distributing full statements, which embed the candidate receipt, as opposed to compact statements which +don't. It receives updates from the network bridge and signed statements to share with other validators. -This is a network protocol that receives messages of type [`StatementDistributionV1Message`][StatementDistributionV1NetworkMessage]. +This is a network protocol that receives messages of type +[`StatementDistributionV1Message`][StatementDistributionV1NetworkMessage]. ```rust enum StatementDistributionMessage { @@ -855,7 +863,8 @@ enum StatementDistributionMessage { ## Validation Request Type -Various modules request that the [Candidate Validation subsystem](../node/utility/candidate-validation.md) validate a block with this message. It returns [`ValidationOutputs`](candidate.md#validationoutputs) for successful validation. +Various modules request that the [Candidate Validation subsystem](../node/utility/candidate-validation.md) validate a +block with this message. It returns [`ValidationOutputs`](candidate.md#validationoutputs) for successful validation. ```rust diff --git a/polkadot/roadmap/implementers-guide/src/whence-parachains.md b/polkadot/roadmap/implementers-guide/src/whence-parachains.md index 41842e93943b..faec46be2c62 100644 --- a/polkadot/roadmap/implementers-guide/src/whence-parachains.md +++ b/polkadot/roadmap/implementers-guide/src/whence-parachains.md @@ -1,29 +1,50 @@ # Whence Parachains -Parachains are the solution to a problem. As with any solution, it cannot be understood without first understanding the problem. So let's start by going over the issues faced by blockchain technology that led to us beginning to explore the design space for something like parachains. +Parachains are the solution to a problem. As with any solution, it cannot be understood without first understanding the +problem. So let's start by going over the issues faced by blockchain technology that led to us beginning to explore the +design space for something like parachains. ## Issue 1: Scalability -It became clear a few years ago that the transaction throughput of simple Proof-of-Work (PoW) blockchains such as Bitcoin, Ethereum, and myriad others was simply too low. +It became clear a few years ago that the transaction throughput of simple Proof-of-Work (PoW) blockchains such as +Bitcoin, Ethereum, and myriad others was simply too low. > TODO: what if there were more blockchains, etc. -Proof-of-Stake (PoS) systems can accomplish higher throughput than PoW blockchains. PoS systems are secured by bonded capital as opposed to spent effort - liquidity opportunity cost vs. burning electricity. The way they work is by selecting a set of validators with known economic identity who lock up tokens in exchange for earning the right to "validate" or participate in the consensus process. If they are found to carry out that process wrongly, they will be slashed, meaning some or all of the locked tokens will be burned. This provides a strong disincentive in the direction of misbehavior. +Proof-of-Stake (PoS) systems can accomplish higher throughput than PoW blockchains. PoS systems are secured by bonded +capital as opposed to spent effort - liquidity opportunity cost vs. burning electricity. The way they work is by +selecting a set of validators with known economic identity who lock up tokens in exchange for earning the right to +"validate" or participate in the consensus process. If they are found to carry out that process wrongly, they will be +slashed, meaning some or all of the locked tokens will be burned. This provides a strong disincentive in the direction +of misbehavior. -Since the consensus protocol doesn't revolve around wasting effort, block times and agreement can occur much faster. Solutions to PoW challenges don't have to be found before a block can be authored, so the overhead of authoring a block is reduced to only the costs of creating and distributing the block. +Since the consensus protocol doesn't revolve around wasting effort, block times and agreement can occur much faster. +Solutions to PoW challenges don't have to be found before a block can be authored, so the overhead of authoring a block +is reduced to only the costs of creating and distributing the block. -However, consensus on a PoS chain requires full agreement of 2/3+ of the validator set for everything that occurs at Layer 1: all logic which is carried out as part of the blockchain's state machine. This means that everybody still needs to check everything. Furthermore, validators may have different views of the system based on the information that they receive over an asynchronous network, making agreement on the latest state more difficult. +However, consensus on a PoS chain requires full agreement of 2/3+ of the validator set for everything that occurs at +Layer 1: all logic which is carried out as part of the blockchain's state machine. This means that everybody still needs +to check everything. Furthermore, validators may have different views of the system based on the information that they +receive over an asynchronous network, making agreement on the latest state more difficult. -Parachains are an example of a **sharded** protocol. Sharding is a concept borrowed from traditional database architecture. Rather than requiring every participant to check every transaction, we require each participant to check some subset of transactions, with enough redundancy baked in that byzantine (arbitrarily malicious) participants can't sneak in invalid transactions - at least not without being detected and getting slashed, with those transactions reverted. +Parachains are an example of a **sharded** protocol. Sharding is a concept borrowed from traditional database +architecture. Rather than requiring every participant to check every transaction, we require each participant to check +some subset of transactions, with enough redundancy baked in that byzantine (arbitrarily malicious) participants can't +sneak in invalid transactions - at least not without being detected and getting slashed, with those transactions +reverted. -Sharding and Proof-of-Stake in coordination with each other allow a parachain host to provide full security on many parachains, even without all participants checking all state transitions. +Sharding and Proof-of-Stake in coordination with each other allow a parachain host to provide full security on many +parachains, even without all participants checking all state transitions. > TODO: note about network effects & bridging ## Issue 2: Flexibility / Specialization -"dumb" VMs don't give you the flexibility. Any engineer knows that being able to specialize on a problem gives them and their users more _leverage_. +"dumb" VMs don't give you the flexibility. Any engineer knows that being able to specialize on a problem gives them and +their users more _leverage_. > TODO: expand on leverage -Having recognized these issues, we set out to find a solution to these problems, which could allow developers to create and deploy purpose-built blockchains unified under a common source of security, with the capability of message-passing between them; a _heterogeneous sharding solution_, which we have come to know as **Parachains**. +Having recognized these issues, we set out to find a solution to these problems, which could allow developers to create +and deploy purpose-built blockchains unified under a common source of security, with the capability of message-passing +between them; a _heterogeneous sharding solution_, which we have come to know as **Parachains**. diff --git a/polkadot/roadmap/parachains.md b/polkadot/roadmap/parachains.md index 9d6c014a1c7c..77e974336767 100644 --- a/polkadot/roadmap/parachains.md +++ b/polkadot/roadmap/parachains.md @@ -1,17 +1,23 @@ # Parachains Roadmap -This is a roadmap for the core technology underlying Parachains - what protocols, APIs, and code paths need to be in place to fully instantiate a self-sufficient and secure parachain. We don't attempt to cover anything on what APIs a parachain toolkit might expose in order to make use of parachain features - only how those features are implemented and the low-level APIs that they expose to the validation function, if any. + +This is a roadmap for the core technology underlying Parachains - what protocols, APIs, and code paths need to be in +place to fully instantiate a self-sufficient and secure parachain. We don't attempt to cover anything on what APIs a +parachain toolkit might expose in order to make use of parachain features - only how those features are implemented and +the low-level APIs that they expose to the validation function, if any. ## Categories We will use these categories to delineate features: -*Runtime*: Runtime code for the Relay chain specifying consensus-critical state and updates that all full nodes must maintain or perform. +*Runtime*: Runtime code for the Relay chain specifying consensus-critical state and updates that all full nodes must +maintain or perform. *Networking*: Protocols for nodes to speak to each other and transmit information across the network. -*Node*: State or updates that must be maintained or performed by some or all nodes off-chain. Often interfaces with networking components, and references runtime state. +*Node*: State or updates that must be maintained or performed by some or all nodes off-chain. Often interfaces with +networking components, and references runtime state. --- -## Sub-projects and features: +## Sub-projects and features This section contains various sub-projects and the features that make them up. ### Infrastructure/API @@ -20,7 +26,8 @@ This section contains various sub-projects and the features that make them up. Category: Networking -Validators assigned to a parachain need a way to discover and connect to collators in order to get fresh parachain blocks to validate. +Validators assigned to a parachain need a way to discover and connect to collators in order to get fresh parachain +blocks to validate. Collators need to discover and connect to validators in order to submit parachain blocks. @@ -30,7 +37,9 @@ Some connections are long-lived, some are just for a single request. #### Custom libp2p sub-protocols -Polkadot parachains involve many distinct networking protocols. Ideally, we'd be able to spawn each of these as a separate futures task which communicates via channel with other protocols or node code as necessary. This requires changes in Substrate and libp2p. +Polkadot parachains involve many distinct networking protocols. Ideally, we'd be able to spawn each of these as a +separate futures task which communicates via channel with other protocols or node code as necessary. This requires +changes in Substrate and libp2p. --- ### Assignment @@ -39,21 +48,26 @@ Polkadot parachains involve many distinct networking protocols. Ideally, we'd be Category: Runtime -Auctioning and registration of parachains. This is already implemented and follows the [Parachain Allocation — Research at W3F](https://research.web3.foundation/en/latest/polkadot/Parachain-Allocation.html) document. +Auctioning and registration of parachains. This is already implemented and follows the [Parachain Allocation — Research +at W3F](https://research.web3.foundation/en/latest/polkadot/Parachain-Allocation.html) document. #### *On-demand Blockspace Purchase* Category: Runtime -The blockspace purchasing system for on-demand parachains consists of an on-chain mechanism for resolving block space purchases by collators and ensuring that they author a block. +The blockspace purchasing system for on-demand parachains consists of an on-chain mechanism for resolving block space +purchases by collators and ensuring that they author a block. -The node-side portion of on-demand parachains is for collators to actually purchase blockspace and to configure the conditions in which purchases are made. +The node-side portion of on-demand parachains is for collators to actually purchase blockspace and to configure the +conditions in which purchases are made. #### *Validator Assignment* Category: Runtime -Assignment of validators to parachains. Validators are only assigned to parachains for a short period of time. Tweakable parameters include length of time assigned to each parachain and length of time in advance that the network is aware of validators' assignments. +Assignment of validators to parachains. Validators are only assigned to parachains for a short period of time. Tweakable +parameters include length of time assigned to each parachain and length of time in advance that the network is aware of +validators' assignments. --- ### Agreement @@ -62,19 +76,26 @@ Assignment of validators to parachains. Validators are only assigned to parachai Category: Networking -A black-box networking component for circulating attestation messages (`Candidate`, `Valid`, `Invalid`) between validators of any given parachain to create a quorum on which blocks can be included. +A black-box networking component for circulating attestation messages (`Candidate`, `Valid`, `Invalid`) between +validators of any given parachain to create a quorum on which blocks can be included. #### *Availability Erasure-coding* Category: Node, Networking -For each potential, considered parachain block, perform an erasure-coding of the PoV and outgoing messages of the block. Call the number of validators on the relay chain for the Relay-chain block this parachain block is being considered for inclusion in `n`. Erasure-code into `n` pieces, where any `f + 1` can recover (`f` being the maximum number of tolerated faulty nodes = ~ `n / 3`). The `i'th` validator stores the `i'th` piece of the coding and provides it to any who ask. +For each potential, considered parachain block, perform an erasure-coding of the PoV and outgoing messages of the block. +Call the number of validators on the relay chain for the Relay-chain block this parachain block is being considered for +inclusion in `n`. Erasure-code into `n` pieces, where any `f + 1` can recover (`f` being the maximum number of tolerated +faulty nodes = ~ `n / 3`). The `i'th` validator stores the `i'th` piece of the coding and provides it to any who ask. #### *PoV block fetching* Category: Networking -A black-box networking component for validators or fishermen on a parachain to obtain the PoV block referenced by hash in an attestation, for the purpose of validating. When fetching "current" PoV blocks (close to the head of the chain, or relating to the block currently being built), this should be fast. When fetching "old" PoV blocks, it should be possible and fall back on recovering from the availability erasure-coding. +A black-box networking component for validators or fishermen on a parachain to obtain the PoV block referenced by hash +in an attestation, for the purpose of validating. When fetching "current" PoV blocks (close to the head of the chain, or +relating to the block currently being built), this should be fast. When fetching "old" PoV blocks, it should be possible +and fall back on recovering from the availability erasure-coding. #### *On-demand Blockspace Purchase* @@ -95,58 +116,80 @@ The main event loop of a collator node: --- ### Cross-chain Messaging -https://hackmd.io/ILoQltEISP697oMYe4HbrA?view -https://github.com/paritytech/polkadot/issues/597 +https://hackmd.io/ILoQltEISP697oMYe4HbrA?view https://github.com/paritytech/polkadot/issues/597 -The biggest sub-project of the parachains roadmap - how messages are sent between parachains. This involves the state-machine ordering of incoming messages, protocols for fetching those messages, and node logic for persisting the messages. +The biggest sub-project of the parachains roadmap - how messages are sent between parachains. This involves the +state-machine ordering of incoming messages, protocols for fetching those messages, and node logic for persisting the +messages. -This is designed around a concept of unidirectional _channels_ between paras, which consist of a sender and receiver. At each relay chain block, each para has an opportunity to send a message on each channel for which it controls the sending half. It will also attempt to process messages on each receiving half of the channel which it controls _in order_: messages sent at block height `b` must be processed before those sent at block height `b+1`. For messages on different channels sent at the same block height, there will be some well-defined order in which they should be processed. +This is designed around a concept of unidirectional _channels_ between paras, which consist of a sender and receiver. At +each relay chain block, each para has an opportunity to send a message on each channel for which it controls the sending +half. It will also attempt to process messages on each receiving half of the channel which it controls _in order_: +messages sent at block height `b` must be processed before those sent at block height `b+1`. For messages on different +channels sent at the same block height, there will be some well-defined order in which they should be processed. -This means that a receiving para will have a maximum height differential of `1` in terms of the most recently processed message's send-height across all of the channels it is receiving on. The minimum processed send-height of a receiving para is known as its _watermark_. All messages on all channels sending to this para before or at the watermark have been processed. +This means that a receiving para will have a maximum height differential of `1` in terms of the most recently processed +message's send-height across all of the channels it is receiving on. The minimum processed send-height of a receiving +para is known as its _watermark_. All messages on all channels sending to this para before or at the watermark have been +processed. #### *Finalize CandidateReceipt format* Category: Runtime / Node -The `CandidateReceipt` is the wrapper around a parablock header which is submitted to the runtime. It contains cryptographic commitments to data which is important for validation or interpretation of the parablock, including the hash of the witness data and outgoing message data. +The `CandidateReceipt` is the wrapper around a parablock header which is submitted to the runtime. It contains +cryptographic commitments to data which is important for validation or interpretation of the parablock, including the +hash of the witness data and outgoing message data. -The `CandidateReceipt` format should be finalized in accordance to the XCMP writeups linked above - most importantly, to be altered to hold `bitfield` and `message_root` fields which cryptographically commit to the state of each open channel. +The `CandidateReceipt` format should be finalized in accordance to the XCMP writeups linked above - most importantly, to +be altered to hold `bitfield` and `message_root` fields which cryptographically commit to the state of each open +channel. #### *Finalize PovBlock format* Category: Runtime / Node -The `PovBlock` or `Proof-of-Validity` block contains all the data you need to validate a parablock. It will need to contain incoming message queues and potentially outgoing ones as well. +The `PovBlock` or `Proof-of-Validity` block contains all the data you need to validate a parablock. It will need to +contain incoming message queues and potentially outgoing ones as well. #### *CST Update Procedure* Category: Runtime -Storage definitions and update logic of the Channel State Table (CST) based on the supplied `CandidateReceipt`s in a relay chain block. +Storage definitions and update logic of the Channel State Table (CST) based on the supplied `CandidateReceipt`s in a +relay chain block. #### *CST Entry Proof Generation and Checking* Category: Node -Means for full nodes of the relay chain to generate proofs of items in the CST and for light clients or pruned nodes to check those proofs. +Means for full nodes of the relay chain to generate proofs of items in the CST and for light clients or pruned nodes to +check those proofs. #### *MQC Storage and Distribution Protocol* Category: Node -Every channel's state is described by a Message Queue Chain (MQC) which is a hash-chain, where the links are defined by `(M, b, H)`: the message most recently sent, the block height at which the prior message was sent, and the hash of the prior link. +Every channel's state is described by a Message Queue Chain (MQC) which is a hash-chain, where the links are defined by +`(M, b, H)`: the message most recently sent, the block height at which the prior message was sent, and the hash of the +prior link. -It is the responsibility of the full nodes of the _sending_ para to maintain all links of the MQC up to and including the link where `b` is less than the watermark of the _receiving_ para. +It is the responsibility of the full nodes of the _sending_ para to maintain all links of the MQC up to and including +the link where `b` is less than the watermark of the _receiving_ para. -Full nodes of the para will be aware of the head of all MQCs for its channels because they are produced by execution of the block. This will take collaboration with the Cumulus team (https://github.com/paritytech/cumulus) on APIs. +Full nodes of the para will be aware of the head of all MQCs for its channels because they are produced by execution of +the block. This will take collaboration with the Cumulus team (https://github.com/paritytech/cumulus) on APIs. -We will need a network where collators of paras can discover and fetch the relevant portion of the MQC incoming from all channels. +We will need a network where collators of paras can discover and fetch the relevant portion of the MQC incoming from all +channels. #### *Channel Registrar and Economics* Category: Runtime -Runtime logic for paras to open and close channels by putting down a deposit. The amount of channels an on-demand parachain can open will be limited. Channels that are pending close should remain open until the watermark of the recipient has reached the block height of the close request. +Runtime logic for paras to open and close channels by putting down a deposit. The amount of channels an on-demand +parachain can open will be limited. Channels that are pending close should remain open until the watermark of the +recipient has reached the block height of the close request. --- ### Fishing/Slashing @@ -155,17 +198,29 @@ Runtime logic for paras to open and close channels by putting down a deposit. Th Category: Runtime -In Polkadot, a bad parachain group can force inclusion of an invalid or unavailable parachain block. It is the job of fishermen to detect those blocks and report them to the runtime. This item is about the report handler +In Polkadot, a bad parachain group can force inclusion of an invalid or unavailable parachain block. It is the job of +fishermen to detect those blocks and report them to the runtime. This item is about the report handler -The W3F-research writeup on availability/validity provides a high-level view of the dispute resolution process: [Availability and Validity — Research at W3F](https://research.web3.foundation/en/latest/polkadot/Availability_and_Validity.html) +The W3F-research writeup on availability/validity provides a high-level view of the dispute resolution process: +[Availability and Validity — Research at +W3F](https://research.web3.foundation/en/latest/polkadot/Availability_and_Validity.html) -One of the main behaviors that is unimplemented and needs to be is the _rollback_ that occurs when the dispute resolution process concludes that an error has been made. When we mark a parachain block as having been invalid or unavailable, we need to roll back all parachains to a point from just before this state. We would also need to roll back relay chain state, because there may have been messages from a parachain to a relay chain that now need to be rolled back. The easiest thing to do would be to side-step that by putting a delay on upwards messages, but this would impact the UX of parachain participation in slot auctions, council votes, etc. considerably. Assuming we can't side-step this, we will have to find a way to roll back selected state of the relay chain. +One of the main behaviors that is unimplemented and needs to be is the _rollback_ that occurs when the dispute +resolution process concludes that an error has been made. When we mark a parachain block as having been invalid or +unavailable, we need to roll back all parachains to a point from just before this state. We would also need to roll +back relay chain state, because there may have been messages from a parachain to a relay chain that now need to be +rolled back. The easiest thing to do would be to side-step that by putting a delay on upwards messages, but this would +impact the UX of parachain participation in slot auctions, council votes, etc. considerably. Assuming we can't side-step +this, we will have to find a way to roll back selected state of the relay chain. #### *Double-vote Slash Handler* Category: Runtime -In the attestation process, validators may submit only one `Candidate` message for a given relay chain block. If issuing a `Candidate` message on a parachain block, neither a `Valid` or `Invalid` vote cannot be issued on that parachain block, as the `Candidate` message is an implicit validity vote. Otherwise, it is illegal to cast both a `Valid` and `Invalid` vote on a given parachain block. +In the attestation process, validators may submit only one `Candidate` message for a given relay chain block. If issuing +a `Candidate` message on a parachain block, neither a `Valid` or `Invalid` vote cannot be issued on that parachain +block, as the `Candidate` message is an implicit validity vote. Otherwise, it is illegal to cast both a `Valid` and +`Invalid` vote on a given parachain block. Runtime handlers that take two conflicting votes as arguments and slash the offender are needed. @@ -173,9 +228,11 @@ Runtime handlers that take two conflicting votes as arguments and slash the offe Category: Node -This code-path is also taken by validators who self-select based on VRF [Availability and Validity — Research at W3F](https://research.web3.foundation/en/latest/polkadot/Availability_and_Validity.html). Validators and fishermen will select parachain blocks to re-validate. In these steps: -* Attempt to recover the PoV block, falling back on the erasure-coding. If not available, issue report. -* Attempt to validate the PoV block. If invalid, issue report. +This code-path is also taken by validators who self-select based on VRF [Availability and Validity — Research at +W3F](https://research.web3.foundation/en/latest/polkadot/Availability_and_Validity.html). Validators and fishermen will +select parachain blocks to re-validate. In these steps: +- Attempt to recover the PoV block, falling back on the erasure-coding. If not available, issue report. +- Attempt to validate the PoV block. If invalid, issue report. #### *Double-vote Fishing* @@ -186,45 +243,50 @@ Nodes that observe a double-vote in the attestation process should submit a repo --- # Phases -This roadmap is divided up into phases, where each represents another set of deliverables or iteration on a black-box component with respect to the prior phase. +This roadmap is divided up into phases, where each represents another set of deliverables or iteration on a black-box +component with respect to the prior phase. ## Phase 0: MVP -The very first phase - this is parachains without slashing (full security) or cross-chain messaging. It is primarily a PoC that registration and validation are working correctly. +The very first phase - this is parachains without slashing (full security) or cross-chain messaging. It is primarily a +PoC that registration and validation are working correctly. -### Infrastructure/API: - - Custom libp2p sub-protocols - - Peer Set Management +### Infrastructure/API +- Custom libp2p sub-protocols +- Peer Set Management -### Assignment: - - Auctions - - On-demand Blockspace purchase - - Validator Assignment +### Assignment +- Auctions +- On-demand Blockspace purchase +- Validator Assignment -### Agreement: - - Attestation Circulation (black box: gossip) - - Availability Erasure-coding (black box: gossip) - - PoV block fetching (black box: gossip) - - Collation Loop +### Agreement +- Attestation Circulation (black box: gossip) +- Availability Erasure-coding (black box: gossip) +- PoV block fetching (black box: gossip) +- Collation Loop -### Cross-chain Messaging: - - Finalize `CandidateReceipt` format +### Cross-chain Messaging +- Finalize `CandidateReceipt` format ## Phase 1: Fishing and Slashing -This phase marks advancement in the security of parachains. Once completed, parachains are a full-fledged cryptoeconomically secure rollup primitive. This phase also includes implementation work on XCMP, but does not enable it fully. +This phase marks advancement in the security of parachains. Once completed, parachains are a full-fledged +cryptoeconomically secure rollup primitive. This phase also includes implementation work on XCMP, but does not enable it +fully. ### Agreement - - Availability Erasure-coding (black box: targeted distribution) - - PoV block fetching (black box: targeted distribution and fetching) +- Availability Erasure-coding (black box: targeted distribution) +- PoV block fetching (black box: targeted distribution and fetching) ### Fishing/Slashing - - Validity/Availability Report Handler - - Double-vote Slash Handler - - Validity/Availability Fishing - - Double-vote Fishing -### Cross-chain Messaging: - - Finalize `PoVBlock` format. +- Validity/Availability Report Handler +- Double-vote Slash Handler +- Validity/Availability Fishing +- Double-vote Fishing + +### Cross-chain Messaging +- Finalize `PoVBlock` format. ## Phase 2: Messaging diff --git a/polkadot/runtime/rococo/README.md b/polkadot/runtime/rococo/README.md index 0f35665ca172..465afd25549b 100644 --- a/polkadot/runtime/rococo/README.md +++ b/polkadot/runtime/rococo/README.md @@ -4,8 +4,10 @@ Rococo is a testnet runtime with no stability guarantees. ## How to run `rococo-local` -The [Cumulus Tutorial](https://docs.substrate.io/tutorials/v3/cumulus/start-relay/) details building, starting, and testing `rococo-local` and parachains connecting to it. +The [Cumulus Tutorial](https://docs.substrate.io/tutorials/v3/cumulus/start-relay/) details building, starting, and +testing `rococo-local` and parachains connecting to it. ## How to register a parachain on the Rococo testnet -The [parachain registration process](https://docs.substrate.io/tutorials/v3/cumulus/rococo/) on the public Rococo testnet is also outlined. +The [parachain registration process](https://docs.substrate.io/tutorials/v3/cumulus/rococo/) on the public Rococo +testnet is also outlined. diff --git a/polkadot/utils/staking-miner/README.md b/polkadot/utils/staking-miner/README.md index 7e7254dc7759..8fec746e6eea 100644 --- a/polkadot/utils/staking-miner/README.md +++ b/polkadot/utils/staking-miner/README.md @@ -1,11 +1,19 @@ # Staking Miner -Substrate chains validators compute a basic solution for the NPoS election. The optimization of the solution is computing-intensive and can be delegated to the `staking-miner`. The `staking-miner` does not act as validator and focuses solely on the optimization of the solution. +Substrate chains validators compute a basic solution for the NPoS election. The optimization of the solution is +computing-intensive and can be delegated to the `staking-miner`. The `staking-miner` does not act as validator and +focuses solely on the optimization of the solution. -The staking miner connects to a specified chain and keeps listening to new Signed phase of the [pallet-election-provider-multi-phase](https://crates.parity.io/pallet_election_provider_multi_phase/index.html) in order to submit solutions to the NPoS election. When the correct time comes, it computes its solution and submit it to the chain. -The default miner algorithm is [sequential-phragmen](https://crates.parity.io/sp_npos_elections/phragmen/fn.seq_phragmen_core.html)] with a configurable number of balancing iterations that improve the score. +The staking miner connects to a specified chain and keeps listening to new Signed phase of the +[pallet-election-provider-multi-phase](https://crates.parity.io/pallet_election_provider_multi_phase/index.html) in +order to submit solutions to the NPoS election. When the correct time comes, it computes its solution and submit it to +the chain. The default miner algorithm is +[sequential-phragmen](https://crates.parity.io/sp_npos_elections/phragmen/fn.seq_phragmen_core.html)] with a +configurable number of balancing iterations that improve the score. -Running the staking-miner requires passing the seed of a funded account in order to pay the fees for the transactions that will be sent. The same account's balance is used to reserve deposits as well. The best solution in each round is rewarded. All correct solutions will get their bond back. Any invalid solution will lose their bond. +Running the staking-miner requires passing the seed of a funded account in order to pay the fees for the transactions +that will be sent. The same account's balance is used to reserve deposits as well. The best solution in each round is +rewarded. All correct solutions will get their bond back. Any invalid solution will lose their bond. You can check the help with: ``` @@ -22,13 +30,15 @@ cargo build --profile production --locked --package staking-miner --bin staking- ## Docker There are 2 options to build a staking-miner Docker image: -- injected binary: the binary is first built on a Linux host and then injected into a Docker base image. This method only works if you have a Linux host or access to a pre-built binary from a Linux host. -- multi-stage: the binary is entirely built within the multi-stage Docker image. There is no requirement on the host in terms of OS and the host does not even need to have any Rust toolchain installed. +- injected binary: the binary is first built on a Linux host and then injected into a Docker base image. This method + only works if you have a Linux host or access to a pre-built binary from a Linux host. +- multi-stage: the binary is entirely built within the multi-stage Docker image. There is no requirement on the host in + terms of OS and the host does not even need to have any Rust toolchain installed. ### Building the injected image -First build the binary as documented [above](#building). -You may then inject the binary into a Docker base image: `parity/base-bin` (running the command from the root of the Polkadot repository): +First build the binary as documented [above](#building). You may then inject the binary into a Docker base image: +`parity/base-bin` (running the command from the root of the Polkadot repository): ``` TODO: UPDATE THAT docker build -t staking-miner -f scripts/ci/dockerfiles/staking-miner/staking-miner_injected.Dockerfile target/release @@ -36,9 +46,9 @@ docker build -t staking-miner -f scripts/ci/dockerfiles/staking-miner/staking-mi ### Building the multi-stage image -Unlike the injected image that requires a Linux pre-built binary, this option does not requires a Linux host, nor Rust to be installed. -The trade-off however is that it takes a little longer to build and this option is less ideal for CI tasks. -You may build the multi-stage image the root of the Polkadot repository with: +Unlike the injected image that requires a Linux pre-built binary, this option does not requires a Linux host, nor Rust +to be installed. The trade-off however is that it takes a little longer to build and this option is less ideal for CI +tasks. You may build the multi-stage image the root of the Polkadot repository with: ``` TODO: UPDATE THAT docker build -t staking-miner -f scripts/ci/dockerfiles/staking-miner/staking-miner_builder.Dockerfile . @@ -46,8 +56,9 @@ docker build -t staking-miner -f scripts/ci/dockerfiles/staking-miner/staking-mi ### Running -A Docker container, especially one holding one of your `SEED` should be kept as secure as possible. -While it won't prevent a malicious actor to read your `SEED` if they gain access to your container, it is nonetheless recommended running this container in `read-only` mode: +A Docker container, especially one holding one of your `SEED` should be kept as secure as possible. While it won't +prevent a malicious actor to read your `SEED` if they gain access to your container, it is nonetheless recommended +running this container in `read-only` mode: ``` # The following line starts with an extra space on purpose: diff --git a/polkadot/xcm/xcm-simulator/fuzzer/README.md b/polkadot/xcm/xcm-simulator/fuzzer/README.md index 69e8cd377b97..0b3fdd8ec776 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/README.md +++ b/polkadot/xcm/xcm-simulator/fuzzer/README.md @@ -1,6 +1,7 @@ # XCM Simulator Fuzzer -This project will fuzz-test the XCM simulator. It can catch reachable panics, timeouts as well as integer overflows and underflows. +This project will fuzz-test the XCM simulator. It can catch reachable panics, timeouts as well as integer overflows and +underflows. ## Install dependencies @@ -29,7 +30,8 @@ cargo hfuzz run-debug xcm-fuzzer hfuzz_workspace/xcm-fuzzer/fuzzer_input_file In this directory, run these four commands: ``` -RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" CARGO_INCREMENTAL=0 SKIP_WASM_BUILD=1 CARGO_HOME=./cargo cargo build +RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" \ +CARGO_INCREMENTAL=0 SKIP_WASM_BUILD=1 CARGO_HOME=./cargo cargo build ../../../target/debug/xcm-fuzzer hfuzz_workspace/xcm-fuzzer/input/ zip -0 ccov.zip `find ../../../target/ \( -name "*.gc*" -o -name "test-*.gc*" \) -print` grcov ccov.zip -s ../../../ -t html --llvm --branch --ignore-not-existing -o ./coverage diff --git a/polkadot/zombienet_tests/README.md b/polkadot/zombienet_tests/README.md index 84334c3e1cfe..516ff880b2eb 100644 --- a/polkadot/zombienet_tests/README.md +++ b/polkadot/zombienet_tests/README.md @@ -1,34 +1,38 @@ # Zombienet tests -_The content of this directory is meant to be used by Parity's private CI/CD infrastructure with private tools. At the moment those tools are still early stage of development and we don't know if / when they will available for public use._ +_The content of this directory is meant to be used by Parity's private CI/CD infrastructure with private tools. At the +moment those tools are still early stage of development and we don't know if / when they will available for public use._ ## Contents of this directory -`parachains` - At the moment this directory only have one test related to parachains: `/parachains-smoke-test`, that check the parachain registration and the block height. +`parachains` At the moment this directory only have one test related to parachains: `/parachains-smoke-test`, that check + the parachain registration and the block height. ## Resources -* [zombienet repo](https://github.com/paritytech/zombienet) -* [zombienet book](https://paritytech.github.io/zombienet/) +- [zombienet repo](https://github.com/paritytech/zombienet) +- [zombienet book](https://paritytech.github.io/zombienet/) ## Running tests locally -To run any test locally use the native provider (`zombienet test -p native ...`) you need first build the binaries. They are: +To run any test locally use the native provider (`zombienet test -p native ...`) you need first build the binaries. They +are: -* adder-collator -> polkadot/target/testnet/adder-collator -* malus -> polkadot/target/testnet/malus -* polkadot -> polkadot/target/testnet/polkadot, polkadot/target/testnet/polkadot-prepare-worker, polkadot/target/testnet/polkadot-execute-worker -* polkadot-collator -> cumulus/target/release/polkadot-parachain -* undying-collator -> polkadot/target/testnet/undying-collator +- `adder-collator` -> `polkadot/target/testnet/adder-collator` +- `malus` -> `polkadot/target/testnet/malus` +- `polkadot` -> `polkadot/target/testnet/polkadot`, `polkadot/target/testnet/polkadot-prepare-worker`, + `polkadot/target/testnet/polkadot-execute-worker` +- `polkadot-collator` -> `cumulus/target/release/polkadot-parachain` +- `undying-collator` -> `polkadot/target/testnet/undying-collator` To build them use: -* adder-collator -> `cargo build --profile testnet -p test-parachain-adder-collator` -* undying-collator -> `cargo build --profile testnet -p test-parachain-undying-collator` -* malus -> `cargo build --profile testnet -p polkadot-test-malus` -* polkadot (in polkadot repo) and polkadot-collator (in cumulus repo) -> `cargo build --profile testnet` +- `adder-collator` -> `cargo build --profile testnet -p test-parachain-adder-collator` +- `undying-collator` -> `cargo build --profile testnet -p test-parachain-undying-collator` +- `malus` -> `cargo build --profile testnet -p polkadot-test-malus` +- `polkadot` (in the Polkadot repo) and `polkadot-collator` (in Cumulus repo) -> `cargo build --profile testnet` -One solution is to use the `.set_env` file (from this directory) and fill the `CUSTOM_PATHS` before *source* it to patch the PATH of your system to find the binaries you just built. +One solution is to use the `.set_env` file (from this directory) and fill the `CUSTOM_PATHS` before _source_ it to patch +the PATH of your system to find the binaries you just built. E.g.: ``` @@ -45,8 +49,9 @@ CUSTOM_PATHS=( source .set_env ``` -Then you have your `PATH` customized and ready to run `zombienet`. - **NOTE**: You should need to do this ones per terminal session, since we are patching the `PATH` and re-exporting. **Or** you can also `source` this file in your `.bashrc` file to get executed automatically in each new session. +Then you have your `PATH` customized and ready to run `zombienet`. **NOTE**: You should need to do this ones per + terminal session, since we are patching the `PATH` and re-exporting. **Or** you can also `source` this file in your + `.bashrc` file to get executed automatically in each new session. Example: @@ -57,4 +62,5 @@ zombienet test -p native 0001-parachains-pvf.zndsl ## Questions / permissions -Ping in element Javier (@javier:matrix.parity.io) to ask questions or grant permission to run the test from your local setup. +Ping in element Javier (`@javier:matrix.parity.io`) to ask questions or grant permission to run the test from your local +setup. diff --git a/substrate/README.md b/substrate/README.md index 6ed64ac82eed..f7afa7a894d8 100644 --- a/substrate/README.md +++ b/substrate/README.md @@ -1,27 +1,35 @@ -# Substrate · [![GitHub license](https://img.shields.io/badge/license-GPL3%2FApache2-blue)](#LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/mirrors/polkadot-sdk/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.md) [![Stack Exchange](https://img.shields.io/badge/Substrate-Community%20&%20Support-24CC85?logo=stackexchange)](https://substrate.stackexchange.com/) +# Substrate + +[![GitHub license](https://img.shields.io/badge/license-GPL3%2FApache2-blue)](#LICENSE) +[![GitLab +Status](https://gitlab.parity.io/parity/mirrors/polkadot-sdk/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/pipelines) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.md) +[![Stack +Exchange](https://img.shields.io/badge/Substrate-Community%20&%20Support-24CC85?logo=stackexchange)](https://substrate.stackexchange.com/)

- +

Substrate is a next-generation framework for blockchain innovation 🚀. ## Getting Started -Head to [docs.substrate.io](https://docs.substrate.io) and follow the -[installation](https://docs.substrate.io/install/) instructions. Then try out one of the -[tutorials](https://docs.substrate.io/tutorials/). Refer to the [Docker instructions](./docker/README.md) to quickly run Substrate, Substrate Node Template, Subkey, or to build a chain spec. +Head to [`docs.substrate.io`](https://docs.substrate.io) and follow the [installation](https://docs.substrate.io/install/) +instructions. Then try out one of the [tutorials](https://docs.substrate.io/tutorials/). Refer to the [Docker +instructions](./docker/README.md) to quickly run Substrate, Substrate Node Template, Subkey, or to build a chain spec. ## Community & Support -Join the highly active and supportive community on the -[Substrate Stack Exchange](https://substrate.stackexchange.com/) to ask questions about use and problems you run into using this software. -Please do report bugs and [issues here](https://github.com/paritytech/polkadot-sdk/issues) for anything you suspect requires action in the source. +Join the highly active and supportive community on the [Substrate Stack Exchange](https://substrate.stackexchange.com/) +to ask questions about use and problems you run into using this software. Please do report bugs and [issues +here](https://github.com/paritytech/polkadot-sdk/issues) for anything you suspect requires action in the source. ## Contributions & Code of Conduct Please follow the contributions guidelines as outlined in -[`docs/CONTRIBUTING.md`](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CONTRIBUTING.md). -In all communications and contributions, this project follows the [Contributor Covenant Code of Conduct](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CODE_OF_CONDUCT.md). +[`docs/CONTRIBUTING.md`](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CONTRIBUTING.md). In all +communications and contributions, this project follows the [Contributor Covenant Code of +Conduct](https://github.com/paritytech/polkadot-sdk/blob/master/docs/CODE_OF_CONDUCT.md). ## Security @@ -30,15 +38,13 @@ The security policy and procedures can be found in ## License -- Substrate Primitives (`sp-*`), Frame (`frame-*`) and the pallets (`pallets-*`), binaries (`/bin`) -and all other utilities are licensed under [Apache 2.0](LICENSE-APACHE2). - Substrate Client -(`/client/*` / `sc-*`) is licensed under [GPL v3.0 with a classpath linking -exception](LICENSE-GPL3). +- Substrate Primitives (`sp-*`), Frame (`frame-*`) and the pallets (`pallets-*`), binaries (`/bin`) and all other +utilities are licensed under [Apache 2.0](LICENSE-APACHE2). - Substrate Client (`/client/*` / `sc-*`) is licensed under +[GPL v3.0 with a classpath linking exception](LICENSE-GPL3). -The reason for the split-licensing is to ensure that for the vast majority of teams using Substrate -to create feature-chains, then all changes can be made entirely in Apache2-licensed code, allowing -teams full freedom over what and how they release and giving licensing clarity to commercial teams. +The reason for the split-licensing is to ensure that for the vast majority of teams using Substrate to create +feature-chains, then all changes can be made entirely in Apache2-licensed code, allowing teams full freedom over what +and how they release and giving licensing clarity to commercial teams. -In the interests of the community, we require any deeper improvements made to Substrate's core logic -(e.g. Substrate's internal consensus, crypto or database code) to be contributed back so everyone -can benefit. +In the interests of the community, we require any deeper improvements made to Substrate's core logic (e.g. Substrate's +internal consensus, crypto or database code) to be contributed back so everyone can benefit. diff --git a/substrate/bin/node-template/README.md b/substrate/bin/node-template/README.md index 337facaaf089..a07328df88c1 100644 --- a/substrate/bin/node-template/README.md +++ b/substrate/bin/node-template/README.md @@ -2,17 +2,26 @@ A fresh [Substrate](https://substrate.io/) node, ready for hacking :rocket: -A standalone version of this template is available for each release of Polkadot in the [Substrate Developer Hub Parachain Template](https://github.com/substrate-developer-hub/substrate-parachain-template/) repository. -The parachain template is generated directly at each Polkadot release branch from the [Node Template in Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) upstream - -It is usually best to use the stand-alone version to start a new project. -All bugs, suggestions, and feature requests should be made upstream in the [Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) repository. +A standalone version of this template is available for each release of Polkadot +in the [Substrate Developer Hub Parachain +Template](https://github.com/substrate-developer-hub/substrate-parachain-template/) +repository. The parachain template is generated directly at each Polkadot +release branch from the [Node Template in +Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) +upstream + +It is usually best to use the stand-alone version to start a new project. All +bugs, suggestions, and feature requests should be made upstream in the +[Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) +repository. ## Getting Started -Depending on your operating system and Rust version, there might be additional packages required to compile this template. -Check the [Install](https://docs.substrate.io/install/) instructions for your platform for the most common dependencies. -Alternatively, you can use one of the [alternative installation](#alternatives-installations) options. +Depending on your operating system and Rust version, there might be additional +packages required to compile this template. Check the +[Install](https://docs.substrate.io/install/) instructions for your platform for +the most common dependencies. Alternatively, you can use one of the [alternative +installation](#alternatives-installations) options. ### Build @@ -24,13 +33,16 @@ cargo build --release ### Embedded Docs -After you build the project, you can use the following command to explore its parameters and subcommands: +After you build the project, you can use the following command to explore its +parameters and subcommands: ```sh ./target/release/node-template -h ``` -You can generate and view the [Rust Docs](https://doc.rust-lang.org/cargo/commands/cargo-doc.html) for this template with this command: +You can generate and view the [Rust +Docs](https://doc.rust-lang.org/cargo/commands/cargo-doc.html) for this template +with this command: ```sh cargo +nightly doc --open @@ -38,7 +50,8 @@ cargo +nightly doc --open ### Single-Node Development Chain -The following command starts a single-node development chain that doesn't persist state: +The following command starts a single-node development chain that doesn't +persist state: ```sh ./target/release/node-template --dev @@ -61,10 +74,12 @@ Development chains: - Maintain state in a `tmp` folder while the node is running. - Use the **Alice** and **Bob** accounts as default validator authorities. - Use the **Alice** account as the default `sudo` account. -- Are preconfigured with a genesis state (`/node/src/chain_spec.rs`) that includes several prefunded development accounts. +- Are preconfigured with a genesis state (`/node/src/chain_spec.rs`) that + includes several prefunded development accounts. -To persist chain state between runs, specify a base path by running a command similar to the following: +To persist chain state between runs, specify a base path by running a command +similar to the following: ```sh // Create a folder to use as the db base path @@ -84,81 +99,127 @@ db keystore network ### Connect with Polkadot-JS Apps Front-End -After you start the node template locally, you can interact with it using the hosted version of the [Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) front-end by connecting to the local node endpoint. -A hosted version is also available on [IPFS (redirect) here](https://dotapps.io/) or [IPNS (direct) here](ipns://dotapps.io/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/explorer). -You can also find the source code and instructions for hosting your own instance on the [polkadot-js/apps](https://github.com/polkadot-js/apps) repository. +After you start the node template locally, you can interact with it using the +hosted version of the [Polkadot/Substrate +Portal](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) +front-end by connecting to the local node endpoint. A hosted version is also +available on [IPFS (redirect) here](https://dotapps.io/) or [IPNS (direct) +here](ipns://dotapps.io/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/explorer). You can +also find the source code and instructions for hosting your own instance on the +[`polkadot-js/apps`](https://github.com/polkadot-js/apps) repository. ### Multi-Node Local Testnet -If you want to see the multi-node consensus algorithm in action, see [Simulate a network](https://docs.substrate.io/tutorials/build-a-blockchain/simulate-network/). +If you want to see the multi-node consensus algorithm in action, see [Simulate a +network](https://docs.substrate.io/tutorials/build-a-blockchain/simulate-network/). ## Template Structure -A Substrate project such as this consists of a number of components that are spread across a few directories. +A Substrate project such as this consists of a number of components that are +spread across a few directories. ### Node -A blockchain node is an application that allows users to participate in a blockchain network. -Substrate-based blockchain nodes expose a number of capabilities: - -- Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the - nodes in the network to communicate with one another. -- Consensus: Blockchains must have a way to come to [consensus](https://docs.substrate.io/fundamentals/consensus/) on the state of the network. - Substrate makes it possible to supply custom consensus engines and also ships with several consensus mechanisms that have been built on top of [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). -- RPC Server: A remote procedure call (RPC) server is used to interact with Substrate nodes. - -There are several files in the `node` directory. -Take special note of the following: - -- [`chain_spec.rs`](./node/src/chain_spec.rs): A [chain specification](https://docs.substrate.io/build/chain-spec/) is a source code file that defines a Substrate chain's initial (genesis) state. - Chain specifications are useful for development and testing, and critical when architecting the launch of a production chain. - Take note of the `development_config` and `testnet_genesis` functions,. - These functions are used to define the genesis state for the local development chain configuration. - These functions identify some [well-known accounts](https://docs.substrate.io/reference/command-line-tools/subkey/) and use them to configure the blockchain's initial state. -- [`service.rs`](./node/src/service.rs): This file defines the node implementation. - Take note of the libraries that this file imports and the names of the functions it invokes. - In particular, there are references to consensus-related topics, such as the [block finalization and forks](https://docs.substrate.io/fundamentals/consensus/#finalization-and-forks) and other [consensus mechanisms](https://docs.substrate.io/fundamentals/consensus/#default-consensus-models) such as Aura for block authoring and GRANDPA for finality. - +A blockchain node is an application that allows users to participate in a +blockchain network. Substrate-based blockchain nodes expose a number of +capabilities: + +- Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking + stack to allow the nodes in the network to communicate with one another. +- Consensus: Blockchains must have a way to come to + [consensus](https://docs.substrate.io/fundamentals/consensus/) on the state of + the network. Substrate makes it possible to supply custom consensus engines + and also ships with several consensus mechanisms that have been built on top + of [Web3 Foundation + research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). +- RPC Server: A remote procedure call (RPC) server is used to interact with + Substrate nodes. + +There are several files in the `node` directory. Take special note of the +following: + +- [`chain_spec.rs`](./node/src/chain_spec.rs): A [chain + specification](https://docs.substrate.io/build/chain-spec/) is a source code + file that defines a Substrate chain's initial (genesis) state. Chain + specifications are useful for development and testing, and critical when + architecting the launch of a production chain. Take note of the + `development_config` and `testnet_genesis` functions,. These functions are + used to define the genesis state for the local development chain + configuration. These functions identify some [well-known + accounts](https://docs.substrate.io/reference/command-line-tools/subkey/) and + use them to configure the blockchain's initial state. +- [`service.rs`](./node/src/service.rs): This file defines the node + implementation. Take note of the libraries that this file imports and the + names of the functions it invokes. In particular, there are references to + consensus-related topics, such as the [block finalization and + forks](https://docs.substrate.io/fundamentals/consensus/#finalization-and-forks) + and other [consensus + mechanisms](https://docs.substrate.io/fundamentals/consensus/#default-consensus-models) + such as Aura for block authoring and GRANDPA for finality. ### Runtime In Substrate, the terms "runtime" and "state transition function" are analogous. -Both terms refer to the core logic of the blockchain that is responsible for validating blocks and executing the state changes they define. -The Substrate project in this repository uses [FRAME](https://docs.substrate.io/learn/runtime-development/#frame) to construct a blockchain runtime. -FRAME allows runtime developers to declare domain-specific logic in modules called "pallets". -At the heart of FRAME is a helpful [macro language](https://docs.substrate.io/reference/frame-macros/) that makes it easy to create pallets and flexibly compose them to create blockchains that can address [a variety of needs](https://substrate.io/ecosystem/projects/). - -Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this template and note the following: - -- This file configures several pallets to include in the runtime. - Each pallet configuration is defined by a code block that begins with `impl $PALLET_NAME::Config for Runtime`. -- The pallets are composed into a single runtime by way of the [`construct_runtime!`](https://paritytech.github.io/substrate/master/frame_support/macro.construct_runtime.html) macro, which is part of the [core FRAME pallet library](https://docs.substrate.io/reference/frame-pallets/#system-pallets). +Both terms refer to the core logic of the blockchain that is responsible for +validating blocks and executing the state changes they define. The Substrate +project in this repository uses +[FRAME](https://docs.substrate.io/learn/runtime-development/#frame) to construct +a blockchain runtime. FRAME allows runtime developers to declare domain-specific +logic in modules called "pallets". At the heart of FRAME is a helpful [macro +language](https://docs.substrate.io/reference/frame-macros/) that makes it easy +to create pallets and flexibly compose them to create blockchains that can +address [a variety of needs](https://substrate.io/ecosystem/projects/). + +Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this +template and note the following: + +- This file configures several pallets to include in the runtime. Each pallet + configuration is defined by a code block that begins with `impl + $PALLET_NAME::Config for Runtime`. +- The pallets are composed into a single runtime by way of the + [`construct_runtime!`](https://paritytech.github.io/substrate/master/frame_support/macro.construct_runtime.html) + macro, which is part of the [core FRAME pallet + library](https://docs.substrate.io/reference/frame-pallets/#system-pallets). ### Pallets -The runtime in this project is constructed using many FRAME pallets that ship with [the Substrate repository](https://github.com/paritytech/substrate/tree/master/frame) and a template pallet that is [defined in the `pallets`](./pallets/template/src/lib.rs) directory. +The runtime in this project is constructed using many FRAME pallets that ship +with [the Substrate +repository](https://github.com/paritytech/substrate/tree/master/frame) and a +template pallet that is [defined in the +`pallets`](./pallets/template/src/lib.rs) directory. A FRAME pallet is comprised of a number of blockchain primitives, including: -- Storage: FRAME defines a rich set of powerful [storage abstractions](https://docs.substrate.io/build/runtime-storage/) that makes it easy to use Substrate's efficient key-value database to manage the evolving state of a blockchain. -- Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) from outside of the runtime in order to update its state. -- Events: Substrate uses [events](https://docs.substrate.io/build/events-and-errors/) to notify users of significant state changes. +- Storage: FRAME defines a rich set of powerful [storage + abstractions](https://docs.substrate.io/build/runtime-storage/) that makes it + easy to use Substrate's efficient key-value database to manage the evolving + state of a blockchain. +- Dispatchables: FRAME pallets define special types of functions that can be + invoked (dispatched) from outside of the runtime in order to update its state. +- Events: Substrate uses + [events](https://docs.substrate.io/build/events-and-errors/) to notify users + of significant state changes. - Errors: When a dispatchable fails, it returns an error. -Each pallet has its own `Config` trait which serves as a configuration interface to generically define the types and parameters it depends on. +Each pallet has its own `Config` trait which serves as a configuration interface +to generically define the types and parameters it depends on. ## Alternatives Installations -Instead of installing dependencies and building this source directly, consider the following alternatives. +Instead of installing dependencies and building this source directly, consider +the following alternatives. ### Nix Install [nix](https://nixos.org/) and -[nix-direnv](https://github.com/nix-community/nix-direnv) for a fully plug-and-play -experience for setting up the development environment. -To get all the correct dependencies, activate direnv `direnv allow`. +[nix-direnv](https://github.com/nix-community/nix-direnv) for a fully +plug-and-play experience for setting up the development environment. To get all +the correct dependencies, activate direnv `direnv allow`. ### Docker -Please follow the [Substrate Docker instructions here](https://github.com/paritytech/substrate/blob/master/docker/README.md) to build the Docker container with the Substrate Node Template binary. +Please follow the [Substrate Docker instructions +here](https://github.com/paritytech/substrate/blob/master/docker/README.md) to +build the Docker container with the Substrate Node Template binary. diff --git a/substrate/bin/node-template/docs/rust-setup.md b/substrate/bin/node-template/docs/rust-setup.md index 133db0277bb4..38fddd5026bb 100644 --- a/substrate/bin/node-template/docs/rust-setup.md +++ b/substrate/bin/node-template/docs/rust-setup.md @@ -1,22 +1,18 @@ ---- -title: Installation ---- +# Installation -This guide is for reference only, please check the latest information on getting started with Substrate -[here](https://docs.substrate.io/main-docs/install/). +This guide is for reference only, please check the latest information on getting started with Substrate [here](https://docs.substrate.io/main-docs/install/). -This page will guide you through the **2 steps** needed to prepare a computer for **Substrate** development. -Since Substrate is built with [the Rust programming language](https://www.rust-lang.org/), the first -thing you will need to do is prepare the computer for Rust development - these steps will vary based -on the computer's operating system. Once Rust is configured, you will use its toolchains to interact -with Rust projects; the commands for Rust's toolchains will be the same for all supported, -Unix-based operating systems. +This page will guide you through the **2 steps** needed to prepare a computer for **Substrate** development. Since +Substrate is built with [the Rust programming language](https://www.rust-lang.org/), the first thing you will need to do +is prepare the computer for Rust development - these steps will vary based on the computer's operating system. Once Rust +is configured, you will use its toolchains to interact with Rust projects; the commands for Rust's toolchains will be +the same for all supported, Unix-based operating systems. ## Build dependencies -Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples -in the [Substrate Docs](https://docs.substrate.io) use Unix-style terminals to demonstrate how to -interact with Substrate from the command line. +Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples in the [Substrate +Docs](https://docs.substrate.io) use Unix-style terminals to demonstrate how to interact with Substrate from the command +line. ### Ubuntu/Debian @@ -55,10 +51,9 @@ sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel ### macOS -> **Apple M1 ARM** -> If you have an Apple M1 ARM system on a chip, make sure that you have Apple Rosetta 2 -> installed through `softwareupdate --install-rosetta`. This is only needed to run the -> `protoc` tool during the build. The build itself and the target binaries would remain native. +> **Apple M1 ARM** If you have an Apple M1 ARM system on a chip, make sure that you have Apple Rosetta 2 installed +> through `softwareupdate --install-rosetta`. This is only needed to run the `protoc` tool during the build. The build +> itself and the target binaries would remain native. Open the Terminal application and execute the following commands: @@ -81,8 +76,8 @@ Please refer to the separate ## Rust developer environment -This guide uses installer and the `rustup` tool to manage the Rust toolchain. -First install and configure `rustup`: +This guide uses installer and the `rustup` tool to manage the Rust toolchain. First install and +configure `rustup`: ```bash # Install @@ -102,13 +97,13 @@ rustup target add wasm32-unknown-unknown --toolchain nightly ## Test your set-up -Now the best way to ensure that you have successfully prepared a computer for Substrate -development is to follow the steps in [our first Substrate tutorial](https://docs.substrate.io/tutorials/v3/create-your-first-substrate-chain/). +Now the best way to ensure that you have successfully prepared a computer for Substrate development is to follow the +steps in [our first Substrate tutorial](https://docs.substrate.io/tutorials/v3/create-your-first-substrate-chain/). ## Troubleshooting Substrate builds -Sometimes you can't get the Substrate node template -to compile out of the box. Here are some tips to help you work through that. +Sometimes you can't get the Substrate node template to compile out of the box. Here are some tips to help you work +through that. ### Rust configuration check @@ -144,27 +139,27 @@ stable-x86_64-unknown-linux-gnu (default) rustc 1.50.0 (cb75ad5db 2021-02-10) ``` -As you can see above, the default toolchain is stable, and the -`nightly-x86_64-unknown-linux-gnu` toolchain as well as its `wasm32-unknown-unknown` target is installed. -You also see that `nightly-2020-10-06-x86_64-unknown-linux-gnu` is installed, but is not used unless explicitly defined as illustrated in the [specify your nightly version](#specifying-nightly-version) -section. +As you can see above, the default toolchain is stable, and the `nightly-x86_64-unknown-linux-gnu` toolchain as well as +its `wasm32-unknown-unknown` target is installed. You also see that `nightly-2020-10-06-x86_64-unknown-linux-gnu` is +installed, but is not used unless explicitly defined as illustrated in the [specify your nightly +version](#specifying-nightly-version) section. ### WebAssembly compilation -Substrate uses [WebAssembly](https://webassembly.org) (Wasm) to produce portable blockchain -runtimes. You will need to configure your Rust compiler to use -[`nightly` builds](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) to allow you to -compile Substrate runtime code to the Wasm target. +Substrate uses [WebAssembly](https://webassembly.org) (Wasm) to produce portable blockchain runtimes. You will need to +configure your Rust compiler to use [`nightly` builds](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) to +allow you to compile Substrate runtime code to the Wasm target. > There are upstream issues in Rust that need to be resolved before all of Substrate can use the stable Rust toolchain. -> [This is our tracking issue](https://github.com/paritytech/substrate/issues/1252) if you're curious as to why and how this will be resolved. +> [This is our tracking issue](https://github.com/paritytech/substrate/issues/1252) if you're curious as to why and how +> this will be resolved. #### Latest nightly for Substrate `master` -Developers who are building Substrate _itself_ should always use the latest bug-free versions of -Rust stable and nightly. This is because the Substrate codebase follows the tip of Rust nightly, -which means that changes in Substrate often depend on upstream changes in the Rust nightly compiler. -To ensure your Rust compiler is always up to date, you should run: +Developers who are building Substrate _itself_ should always use the latest bug-free versions of Rust stable and +nightly. This is because the Substrate codebase follows the tip of Rust nightly, which means that changes in Substrate +often depend on upstream changes in the Rust nightly compiler. To ensure your Rust compiler is always up to date, you +should run: ```bash rustup update @@ -172,21 +167,19 @@ rustup update nightly rustup target add wasm32-unknown-unknown --toolchain nightly ``` -> NOTE: It may be necessary to occasionally rerun `rustup update` if a change in the upstream Substrate -> codebase depends on a new feature of the Rust compiler. When you do this, both your nightly -> and stable toolchains will be pulled to the most recent release, and for nightly, it is -> generally _not_ expected to compile WASM without error (although it very often does). -> Be sure to [specify your nightly version](#specifying-nightly-version) if you get WASM build errors -> from `rustup` and [downgrade nightly as needed](#downgrading-rust-nightly). +> NOTE: It may be necessary to occasionally rerun `rustup update` if a change in the upstream Substrate codebase depends +> on a new feature of the Rust compiler. When you do this, both your nightly and stable toolchains will be pulled to the +> most recent release, and for nightly, it is generally _not_ expected to compile WASM without error (although it very +> often does). Be sure to [specify your nightly version](#specifying-nightly-version) if you get WASM build errors from +> `rustup` and [downgrade nightly as needed](#downgrading-rust-nightly). #### Rust nightly toolchain -If you want to guarantee that your build works on your computer as you update Rust and other -dependencies, you should use a specific Rust nightly version that is known to be -compatible with the version of Substrate they are using; this version will vary from project to -project and different projects may use different mechanisms to communicate this version to -developers. For instance, the Polkadot client specifies this information in its -[release notes](https://github.com/paritytech/polkadot/releases). +If you want to guarantee that your build works on your computer as you update Rust and other dependencies, you should +use a specific Rust nightly version that is known to be compatible with the version of Substrate they are using; this +version will vary from project to project and different projects may use different mechanisms to communicate this +version to developers. For instance, the Polkadot client specifies this information in its [release +notes](https://github.com/paritytech/polkadot/releases). ```bash # Specify the specific nightly toolchain in the date below: @@ -203,20 +196,20 @@ rustup target add wasm32-unknown-unknown --toolchain nightly- ### Specifying nightly version -Use the `WASM_BUILD_TOOLCHAIN` environment variable to specify the Rust nightly version a Substrate -project should use for Wasm compilation: +Use the `WASM_BUILD_TOOLCHAIN` environment variable to specify the Rust nightly version a Substrate project should use +for Wasm compilation: ```bash WASM_BUILD_TOOLCHAIN=nightly- cargo build --release ``` -> Note that this only builds _the runtime_ with the specified nightly. The rest of project will be -> compiled with **your default toolchain**, i.e. the latest installed stable toolchain. +> Note that this only builds _the runtime_ with the specified nightly. The rest of project will be compiled with **your +> default toolchain**, i.e. the latest installed stable toolchain. ### Downgrading Rust nightly -If your computer is configured to use the latest Rust nightly and you would like to downgrade to a -specific nightly version, follow these steps: +If your computer is configured to use the latest Rust nightly and you would like to downgrade to a specific nightly +version, follow these steps: ```bash rustup uninstall nightly diff --git a/substrate/bin/node-template/pallets/template/README.md b/substrate/bin/node-template/pallets/template/README.md index d0d59537c12d..9e4dc55267d6 100644 --- a/substrate/bin/node-template/pallets/template/README.md +++ b/substrate/bin/node-template/pallets/template/README.md @@ -1 +1 @@ -License: MIT-0 \ No newline at end of file +License: MIT-0 diff --git a/substrate/bin/utils/subkey/README.md b/substrate/bin/utils/subkey/README.md index d19ccefb59aa..60e5a9ca9350 100644 --- a/substrate/bin/utils/subkey/README.md +++ b/substrate/bin/utils/subkey/README.md @@ -1,26 +1,33 @@ # Subkey -Subkey is a commandline utility included with Substrate. It allows generating and restoring keys for Substrate based chains such as Polkadot, Kusama and a growing number of parachains and Substrate based projects. +Subkey is a commandline utility included with Substrate. It allows generating and restoring keys for Substrate based +chains such as Polkadot, Kusama and a growing number of parachains and Substrate based projects. `subkey` provides a few sub-commands to generate keys, check keys, sign messages, verify messages, etc... -You can see the full list of commands with `subkey --help`. Most commands have additional help available with for instance `subkey generate --help` for the `generate` command. +You can see the full list of commands with `subkey --help`. Most commands have additional help available with for +instance `subkey generate --help` for the `generate` command. ## Safety first -`subkey` does not need an internet connection to work. Indeed, for the best security, you should be using `subkey` on a machine that is **not connected** to the internet. +`subkey` does not need an internet connection to work. Indeed, for the best security, you should be using `subkey` on a +machine that is **not connected** to the internet. -`subkey` deals with **seeds** and **private keys**. Make sure to use `subkey` in a safe environment (ie. no one looking over your shoulder) and on a safe computer (ie. no one able to check your command history). +`subkey` deals with **seeds** and **private keys**. Make sure to use `subkey` in a safe environment (ie. no one looking +over your shoulder) and on a safe computer (ie. no one able to check your command history). -If you save any output of `subkey` into a file, make sure to apply proper permissions and/or delete the file as soon as possible. +If you save any output of `subkey` into a file, make sure to apply proper permissions and/or delete the file as soon as +possible. ## Usage -The following guide explains *some* of the `subkey` commands. For the full list and the most up to date documentation, make sure to check the integrated help with `subkey --help`. +The following guide explains *some* of the `subkey` commands. For the full list and the most up to date documentation, +make sure to check the integrated help with `subkey --help`. ### Install with Cargo -You will need to have the Substrate build dependencies to install Subkey. Use the following two commands to install the dependencies and Subkey, respectively: +You will need to have the Substrate build dependencies to install Subkey. Use the following two commands to install the +dependencies and Subkey, respectively: Command: @@ -58,19 +65,26 @@ Secret phrase `hotel forest jar hover kite book view eight stuff angle legend de --- ☠️ DO NT RE-USE ANY OF THE SEEDS AND SECRETS FROM THIS PAGE ☠️. -You can read more about security and risks in [SECURITY.md](./SECURITY.md) and in the [Polkadot Wiki](https://wiki.polkadot.network/docs/learn-account-generation). +You can read more about security and risks in [SECURITY.md](./SECURITY.md) and in the [Polkadot +Wiki](https://wiki.polkadot.network/docs/learn-account-generation). --- -The output above shows a **secret phrase** (also called **mnemonic phrase**) and the **secret seed** (also called **Private Key**). Those 2 secrets are the pieces of information you MUST keep safe and secret. All the other information below can be derived from those secrets. +The output above shows a **secret phrase** (also called **mnemonic phrase**) and the **secret seed** (also called +**Private Key**). Those 2 secrets are the pieces of information you MUST keep safe and secret. All the other information +below can be derived from those secrets. -The output above also show the **public key** and the **Account ID**. Those are the independant from the network where you will use the key. +The output above also show the **public key** and the **Account ID**. Those are the independant from the network where +you will use the key. -The **SS58 address** (or **Public Address**) of a new account is a reprensentation of the public keys of an account for a given network (for instance Kusama or Polkadot). +The **SS58 address** (or **Public Address**) of a new account is a reprensentation of the public keys of an account for +a given network (for instance Kusama or Polkadot). -You can read more about the [SS58 format in the Substrate Docs](https://docs.substrate.io/reference/address-formats/) and see the list of reserved prefixes in the [SS58 Registry](https://github.com/paritytech/ss58-registry). +You can read more about the [SS58 format in the Substrate Docs](https://docs.substrate.io/reference/address-formats/) +and see the list of reserved prefixes in the [SS58 Registry](https://github.com/paritytech/ss58-registry). -For instance, considering the previous seed `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` the SS58 addresses are: +For instance, considering the previous seed `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` the +SS58 addresses are: - Polkadot: `16m4J167Mptt8UXL8aGSAi7U2FnPpPxZHPrCgMG9KJzVoFqM` - Kusama: `JLNozAv8QeLSbLFwe2UvWeKKE4yvmDbfGxTuiYkF2BUMx4M` @@ -129,13 +143,17 @@ Secret phrase `soup lyrics media market way crouch elevator put moon useful ques SS58 Address: 5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC ``` -Using the `inspect` command (see more details below), we see that knowning only the **secret seed** is no longer sufficient to recover the account: +Using the `inspect` command (see more details below), we see that knowning only the **secret seed** is no longer +sufficient to recover the account: ```bash subkey inspect "soup lyrics media market way crouch elevator put moon useful question wide" ``` -which recovers the account `5Fe4sqj2K4fRuzEGvToi4KATqZfiDU7TqynjXG6PZE2dxwyh` and not `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC` as we expected. The additional user-defined **password** (`extra_secret` in our example) is now required to fully recover the account. Let's inspect the the previous mnemonic, this time passing also the required `password` as shown below: +which recovers the account `5Fe4sqj2K4fRuzEGvToi4KATqZfiDU7TqynjXG6PZE2dxwyh` and not +`5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC` as we expected. The additional user-defined **password** +(`extra_secret` in our example) is now required to fully recover the account. Let's inspect the the previous mnemonic, +this time passing also the required `password` as shown below: ```bash subkey inspect --password extra_secret "soup lyrics media market way crouch elevator put moon useful question wide" @@ -161,7 +179,8 @@ subkey inspect --public < pubkey | address > **NOTE**: While you will be able to recover the secret seed from the mnemonic, the opposite is not possible. -**NOTE**: For obvious reasons, the **secrets** cannot be recovered from passing **public data** such as `pubkey` or `address` as input. +**NOTE**: For obvious reasons, the **secrets** cannot be recovered from passing **public data** such as `pubkey` or +`address` as input. command: @@ -181,7 +200,8 @@ Secret Key URI `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c9 ### Signing -`subkey` allows using a **secret key** to sign a random message. The signature can then be verified by anyone using your **public key**: +`subkey` allows using a **secret key** to sign a random message. The signature can then be verified by anyone using your +**public key**: ```bash echo -n | subkey sign --suri @@ -201,11 +221,13 @@ output: 9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c ``` -**NOTE**: Each run of the `sign` command will yield a different output. While each signature is different, they are all valid. +**NOTE**: Each run of the `sign` command will yield a different output. While each signature is different, they are all +valid. ### Verifying a signature -Given a message, a signature and an address, `subkey` can verify whether the **message** has been digitally signed by the holder (or one of the holders) of the **private key** for the given **address**: +Given a message, a signature and an address, `subkey` can verify whether the **message** has been digitally signed by +the holder (or one of the holders) of the **private key** for the given **address**: ```bash echo -n | subkey verify
@@ -234,7 +256,8 @@ Error: SignatureInvalid ### Using the vanity generator -You can use the included vanity generator to find a seed that provides an address which includes the desired pattern. Be warned, depending on your hardware this may take a while. +You can use the included vanity generator to find a seed that provides an address which includes the desired pattern. Be +warned, depending on your hardware this may take a while. command: @@ -256,7 +279,9 @@ Secret Key URI `0x8c9a73097f235b84021a446bc2826a00c690ea0be3e0d81a84931cb4146d66 `Bob` now got a nice address starting with their name: 1**bob**YxBPjZWRPbVo35aSwci1u5Zmq8P6J2jpa4kkudBZMqE. -**Note**: While `Bob`, having a short name (3 chars), got a result rather quickly, it will take much longer for `Alice` who has a much longer name, thus the chances to generate a random address that contains the chain `alice` will be much smaller. +**Note**: While `Bob`, having a short name (3 chars), got a result rather quickly, it will take much longer for `Alice` +who has a much longer name, thus the chances to generate a random address that contains the chain `alice` will be much +smaller. ## License diff --git a/substrate/bin/utils/subkey/SECURITY.md b/substrate/bin/utils/subkey/SECURITY.md index 672d2965c7ea..698f119c2920 100644 --- a/substrate/bin/utils/subkey/SECURITY.md +++ b/substrate/bin/utils/subkey/SECURITY.md @@ -1,8 +1,9 @@ # Keys and Security -The following information is not exhaustive but meant to prevent the most common mistakes. -You can read more about security and risks in the [Polkadot Wiki](https://wiki.polkadot.network/docs/learn-account-generation). -The Polkadot network has a few **test networks**, e.g. **Westend**. Test networks are a great way to experiment and learn safely as you can lose tokens on those networks without any financial consequences. +The following information is not exhaustive but meant to prevent the most common mistakes. You can read more about +security and risks in the [Polkadot Wiki](https://wiki.polkadot.network/docs/learn-account-generation). The Polkadot +network has a few **test networks**, e.g. **Westend**. Test networks are a great way to experiment and learn safely as +you can lose tokens on those networks without any financial consequences. `subkey` generates and provides 2 pieces of **secret** information: - **secret phrase**: a bunch of words, exactly 12 by default (can be 12, 15, 18, 21 or 24) @@ -10,16 +11,22 @@ The Polkadot network has a few **test networks**, e.g. **Westend**. Test network There are 2 risks related to private keys: - loss of keys: this can happen if you don't have a proper backup -- leak of the keys: this can unfortunately happen in many ways, including malware, phishing, key logger, backups on system that are online and not properly secured +- leak of the keys: this can unfortunately happen in many ways, including malware, phishing, key logger, backups on + system that are online and not properly secured You want to ensure that: - you **do not lose** those secrets - **no one but you can access** those secrets -☠️ **DO NOT SHARE** your mnemonic phrase or secret seed with ANYONE under **ANY** circumstances. Doing so would give them access to your funds and to send transactions on your behalf. +☠️ **DO NOT SHARE** your mnemonic phrase or secret seed with ANYONE under **ANY** circumstances. Doing so would give +them access to your funds and to send transactions on your behalf. -☠️ If someone is asking for your **secret** phrase or **secret** seed, you can be **SURE** they are attempting to steal your funds. +☠️ If someone is asking for your **secret** phrase or **secret** seed, you can be **SURE** they are attempting to steal +your funds. -✅ It is however fine to share your **SS58 Address** as this is meant to be public information and is needed by anyone you want to be able to make transfer to or otherwise interact with your account. They will only ever need your **Public Address**. +✅ It is however fine to share your **SS58 Address** as this is meant to be public information and is needed by anyone +you want to be able to make transfer to or otherwise interact with your account. They will only ever need your **Public +Address**. -⚠️ While using the same key on multiple networks is possible, it is usually **not** recommended unless you have good motivations for doing so and understand the associated risks and drawbacks. +⚠️ While using the same key on multiple networks is possible, it is usually **not** recommended unless you have good +motivations for doing so and understand the associated risks and drawbacks. diff --git a/substrate/client/allocator/README.md b/substrate/client/allocator/README.md index b89348b4c695..e5a94e50f36d 100644 --- a/substrate/client/allocator/README.md +++ b/substrate/client/allocator/README.md @@ -3,4 +3,4 @@ Collection of allocator implementations. This crate provides the following allocator implementations: - A freeing-bump allocator: [`FreeingBumpHeapAllocator`](https://docs.rs/sc-allocator/latest/sc_allocator/struct.FreeingBumpHeapAllocator.html) -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/client/api/README.md b/substrate/client/api/README.md index 142f5b32dd9a..7f94b1ca5e69 100644 --- a/substrate/client/api/README.md +++ b/substrate/client/api/README.md @@ -1,3 +1,3 @@ Substrate client interfaces. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/block-builder/README.md b/substrate/client/block-builder/README.md index b105d4203362..f255b9a5480b 100644 --- a/substrate/client/block-builder/README.md +++ b/substrate/client/block-builder/README.md @@ -6,4 +6,4 @@ This crate provides the [`BlockBuilder`] utility and the corresponding runtime a The block builder utility is used in the node as an abstraction over the runtime api to initialize a block, to push extrinsics and to finalize a block. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/chain-spec/README.md b/substrate/client/chain-spec/README.md index 5525affbed81..dad1662d3230 100644 --- a/substrate/client/chain-spec/README.md +++ b/substrate/client/chain-spec/README.md @@ -89,4 +89,4 @@ pub struct Extension { pub type MyChainSpec = GenericChainSpec; ``` -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/cli/README.md b/substrate/client/cli/README.md index 2504dbb0c03b..aeaee1e12194 100644 --- a/substrate/client/cli/README.md +++ b/substrate/client/cli/README.md @@ -1,3 +1,3 @@ Substrate CLI library. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/aura/README.md b/substrate/client/consensus/aura/README.md index 85d82cd7dfd3..cefa5f6c7d9d 100644 --- a/substrate/client/consensus/aura/README.md +++ b/substrate/client/consensus/aura/README.md @@ -1,4 +1,4 @@ -Aura (Authority-round) consensus in substrate. +Aura (Authority-round) consensus in Substrate. Aura works by having a list of authorities A who are expected to roughly agree on the current time. Time is divided up into discrete slots of t @@ -12,4 +12,4 @@ far in the future they are. NOTE: Aura itself is designed to be generic over the crypto used. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/babe/README.md b/substrate/client/consensus/babe/README.md index a404d2ea4470..a3cf944b513b 100644 --- a/substrate/client/consensus/babe/README.md +++ b/substrate/client/consensus/babe/README.md @@ -45,4 +45,4 @@ blocks) and will go with the longest one in case of a tie. An in-depth description and analysis of the protocol can be found here: -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/babe/rpc/README.md b/substrate/client/consensus/babe/rpc/README.md index e76dd3dc67f8..e1a366204cd0 100644 --- a/substrate/client/consensus/babe/rpc/README.md +++ b/substrate/client/consensus/babe/rpc/README.md @@ -1,3 +1,3 @@ RPC api for babe. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/common/README.md b/substrate/client/consensus/common/README.md index a6717a1d7a6d..9b953fbf3274 100644 --- a/substrate/client/consensus/common/README.md +++ b/substrate/client/consensus/common/README.md @@ -1,3 +1,3 @@ Collection of common consensus specific implementations -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/epochs/README.md b/substrate/client/consensus/epochs/README.md index 1e74e04172c2..e4abc58c6c0d 100644 --- a/substrate/client/consensus/epochs/README.md +++ b/substrate/client/consensus/epochs/README.md @@ -1,3 +1,3 @@ Generic utilities for epoch-based consensus engines. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/grandpa/README.md b/substrate/client/consensus/grandpa/README.md index 64a7e70bc6a5..f40458965990 100644 --- a/substrate/client/consensus/grandpa/README.md +++ b/substrate/client/consensus/grandpa/README.md @@ -1,4 +1,4 @@ -Integration of the GRANDPA finality gadget into substrate. +Integration of the GRANDPA finality gadget into Substrate. This crate is unstable and the API and usage may change. @@ -36,4 +36,4 @@ number (this is num(signal) + N). When finalizing a block, we either apply or prune any signaled changes based on whether the signaling block is included in the newly-finalized chain. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/grandpa/rpc/README.md b/substrate/client/consensus/grandpa/rpc/README.md index 0007f55dbd4d..ad73878a61bd 100644 --- a/substrate/client/consensus/grandpa/rpc/README.md +++ b/substrate/client/consensus/grandpa/rpc/README.md @@ -1,3 +1,3 @@ RPC API for GRANDPA. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/manual-seal/README.md b/substrate/client/consensus/manual-seal/README.md index b355f8b73183..131b620cb2fe 100644 --- a/substrate/client/consensus/manual-seal/README.md +++ b/substrate/client/consensus/manual-seal/README.md @@ -1,4 +1,4 @@ A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks. This is suitable for a testing environment. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/slots/README.md b/substrate/client/consensus/slots/README.md index 9ab3c3742f33..aa896430f7dc 100644 --- a/substrate/client/consensus/slots/README.md +++ b/substrate/client/consensus/slots/README.md @@ -4,4 +4,4 @@ Some consensus algorithms have a concept of *slots*, which are intervals in time during which certain events can and/or must occur. This crate provides generic functionality for slots. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/db/README.md b/substrate/client/db/README.md index e5fb3fce1d97..a11ae0d6f57e 100644 --- a/substrate/client/db/README.md +++ b/substrate/client/db/README.md @@ -8,4 +8,4 @@ having discarded heavy state that will allow a chain reorganization. Finality implies canonicality but not vice-versa. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/executor/README.md b/substrate/client/executor/README.md index ab7b3d45206f..6a35697962fa 100644 --- a/substrate/client/executor/README.md +++ b/substrate/client/executor/README.md @@ -10,4 +10,4 @@ provided into the wasm runtime module. by the current value of `:code` in the provided externalities), i.e. interfacing with wasm engine used, instance cache. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/executor/common/README.md b/substrate/client/executor/common/README.md index 0c0d3bf08bcb..253d73403137 100644 --- a/substrate/client/executor/common/README.md +++ b/substrate/client/executor/common/README.md @@ -1,3 +1,3 @@ A set of common definitions that are needed for defining execution engines. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/executor/wasmtime/README.md b/substrate/client/executor/wasmtime/README.md index 3e9ac0bddbdc..64fc2fa0c284 100644 --- a/substrate/client/executor/wasmtime/README.md +++ b/substrate/client/executor/wasmtime/README.md @@ -1 +1 @@ -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/informant/README.md b/substrate/client/informant/README.md index b494042590a4..a5ad89a932d3 100644 --- a/substrate/client/informant/README.md +++ b/substrate/client/informant/README.md @@ -1,3 +1,3 @@ Console informant. Prints sync progress and block events. Runs on the calling thread. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/keystore/README.md b/substrate/client/keystore/README.md index 9946a61d6fde..5d50f7ad2cfa 100644 --- a/substrate/client/keystore/README.md +++ b/substrate/client/keystore/README.md @@ -1,3 +1,3 @@ Keystore (and session key management) for ed25519 based chains like Polkadot. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/network-gossip/README.md b/substrate/client/network-gossip/README.md index 9030fac05640..900f223251d7 100644 --- a/substrate/client/network-gossip/README.md +++ b/substrate/client/network-gossip/README.md @@ -38,4 +38,4 @@ opens the door for neighbor status packets to be baked into the gossip protocol. These status packets will typically contain light pieces of information used to inform peers of a current view of protocol state. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/network/README.md b/substrate/client/network/README.md index cad46d059092..f4031fbd3085 100644 --- a/substrate/client/network/README.md +++ b/substrate/client/network/README.md @@ -80,8 +80,8 @@ is "dot". In the protocol names below, `` must be replaced with the protocol ID. > **Note**: It is possible for the same connection to be used for multiple chains. For example, -> one can use both the `/dot/sync/2` and `/sub/sync/2` protocols on the same -> connection, provided that the remote supports them. +> one can use both the `/dot/sync/2` and `/sub/sync/2` protocols on the same +> connection, provided that the remote supports them. Substrate uses the following standard libp2p protocols: @@ -138,7 +138,7 @@ substream is closed, the entire connection is closed as well. This is a bug that resolved by deprecating the protocol entirely. Within the unique Substrate substream, messages encoded using -[*parity-scale-codec*](https://github.com/paritytech/parity-scale-codec) are exchanged. +[`parity-scale-codec``](https://github.com/paritytech/parity-scale-codec) are exchanged. The detail of theses messages is not totally in place, but they can be found in the `message.rs` file. @@ -240,7 +240,7 @@ The state is then imported into the database and the keep-up sync starts in norm This is similar to fast sync, but instead of downloading and verifying full header chain, the algorithm only downloads finalized authority set changes. -### GRANDPA warp sync. +### GRANDPA warp sync GRANDPA keeps justifications for each finalized authority set change. Each change is signed by the authorities from the previous set. By downloading and verifying these signed hand-offs starting from genesis, @@ -254,7 +254,7 @@ the fast sync. The state is verified to match the header storage root. After the database it is queried for the information that allows GRANDPA and BABE to continue operating from that state. This includes BABE epoch information and GRANDPA authority set id. -### Background block download. +### Background block download After the latest state has been imported the node is fully operational, but is still missing historic block data. I.e. it is unable to serve bock bodies and headers other than the most recent one. To make sure all diff --git a/substrate/client/offchain/README.md b/substrate/client/offchain/README.md index f7c097e8e0b2..74d54c0c234d 100644 --- a/substrate/client/offchain/README.md +++ b/substrate/client/offchain/README.md @@ -15,4 +15,4 @@ for instance via: 2. Majority voting for results 3. etc -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/proposer-metrics/README.md b/substrate/client/proposer-metrics/README.md index 9669c7d35191..27a6b726814c 100644 --- a/substrate/client/proposer-metrics/README.md +++ b/substrate/client/proposer-metrics/README.md @@ -1,3 +1,3 @@ Prometheus basic proposer metrics. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/rpc-api/README.md b/substrate/client/rpc-api/README.md index e860e0c2334d..8ea6e686c1a6 100644 --- a/substrate/client/rpc-api/README.md +++ b/substrate/client/rpc-api/README.md @@ -1,5 +1,5 @@ Substrate RPC interfaces. -A collection of RPC methods and subscriptions supported by all substrate clients. +A collection of RPC methods and subscriptions supported by all Substrate clients. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/rpc-servers/README.md b/substrate/client/rpc-servers/README.md index cf00b3169a62..16f1bb9f2a36 100644 --- a/substrate/client/rpc-servers/README.md +++ b/substrate/client/rpc-servers/README.md @@ -1,3 +1,3 @@ Substrate RPC servers. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/rpc-spec-v2/README.md b/substrate/client/rpc-spec-v2/README.md index e860e0c2334d..8ea6e686c1a6 100644 --- a/substrate/client/rpc-spec-v2/README.md +++ b/substrate/client/rpc-spec-v2/README.md @@ -1,5 +1,5 @@ Substrate RPC interfaces. -A collection of RPC methods and subscriptions supported by all substrate clients. +A collection of RPC methods and subscriptions supported by all Substrate clients. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/rpc/README.md b/substrate/client/rpc/README.md index 6066af4da71a..7490d0dc2b09 100644 --- a/substrate/client/rpc/README.md +++ b/substrate/client/rpc/README.md @@ -2,4 +2,4 @@ Substrate RPC implementation. A core implementation of Substrate RPC interfaces. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/service/README.md b/substrate/client/service/README.md index 26f940f16df0..0a36138a366f 100644 --- a/substrate/client/service/README.md +++ b/substrate/client/service/README.md @@ -1,4 +1,4 @@ Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. Manages communication between them. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/state-db/README.md b/substrate/client/state-db/README.md index a02b3929088f..c97cc23400fa 100644 --- a/substrate/client/state-db/README.md +++ b/substrate/client/state-db/README.md @@ -2,15 +2,15 @@ State database maintenance. Handles canonicalization and pruning in the database this module is a `ChangeSet` which is basically a list of key-value pairs (trie nodes) that were added or deleted during block execution. -# Canonicalization. +# Canonicalization Canonicalization window tracks a tree of blocks identified by header hash. The in-memory overlay allows to get any node that was inserted in any of the blocks within the window. The tree is journaled to the backing database and rebuilt on startup. Canonicalization function selects one root from the top of the tree and discards all other roots and their subtrees. -# Pruning. +# Pruning See `RefWindow` for pruning algorithm details. `StateDb` prunes on each canonicalization until pruning constraints are satisfied. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/telemetry/README.md b/substrate/client/telemetry/README.md index 2e3e19bd2f62..849fad8bec70 100644 --- a/substrate/client/telemetry/README.md +++ b/substrate/client/telemetry/README.md @@ -1,6 +1,6 @@ # sc-telemetry -Substrate's client telemetry is a part of substrate that allows ingesting telemetry data +Substrate's client telemetry is a part of Substrate that allows ingesting telemetry data with for example [Polkadot telemetry](https://github.com/paritytech/substrate-telemetry). It works using Tokio's [tracing](https://github.com/tokio-rs/tracing/) library. The telemetry @@ -9,8 +9,8 @@ tracing `Layer`. This layer will then send the data through an asynchronous chan background task called [`TelemetryWorker`] which will send the information to the configured remote telemetry servers. -If multiple substrate nodes are running in the same process, it uses a `tracing::Span` to -identify which substrate node is reporting the telemetry. Every task spawned using sc-service's +If multiple Substrate nodes are running in the same process, it uses a `tracing::Span` to +identify which Substrate node is reporting the telemetry. Every task spawned using sc-service's `TaskManager` automatically inherit this span. Substrate's nodes initialize/register with the [`TelemetryWorker`] using a [`TelemetryHandle`]. diff --git a/substrate/client/tracing/README.md b/substrate/client/tracing/README.md index b008436df9bb..f52e9d4dbc66 100644 --- a/substrate/client/tracing/README.md +++ b/substrate/client/tracing/README.md @@ -1,4 +1,4 @@ -Instrumentation implementation for substrate. +Instrumentation implementation for Substrate. This crate is unstable and the API and usage may change. @@ -8,4 +8,4 @@ See `sp-tracing` for examples on how to use tracing. Currently we provide `Log` (default), `Telemetry` variants for `Receiver` -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/transaction-pool/README.md b/substrate/client/transaction-pool/README.md index 4a2bbb8838f9..b34b623b26e0 100644 --- a/substrate/client/transaction-pool/README.md +++ b/substrate/client/transaction-pool/README.md @@ -232,7 +232,7 @@ are interested in. Since the pool is expected to store more transactions than what can fit in a single block, validating the entire pool on every block might not be -feasible. This means that the actual implementation might need to take some +feasible. This means that the actual implementation might need to take some shortcuts. ## Suggestions & caveats @@ -255,7 +255,7 @@ shortcuts. lot of re-orgs. Make sure that transactions are never lost. 1. The UTXO model is quite challenging. A transaction becomes valid right after - it's included in a block, however it is waiting for exactly the same inputs + it's included in a block, however it is waiting for exactly the same inputs to be spent, so it will never really be included again. 1. Note that in a non-ideal implementation the state of the pool will most @@ -278,7 +278,7 @@ shortcuts. 1. We periodically validate all transactions in the pool in batches. -1. To minimize runtime calls, we introduce the batch-verify call. Note it should +1. To minimize runtime calls, we introduce the batch-verify call. Note it should reset the state (overlay) after every verification. 1. Consider leveraging finality. Maybe we could verify against latest finalised @@ -355,7 +355,7 @@ figure out what tags were satisfied by a transaction in that block. For each blo transaction we either call into the runtime to get it's `ValidTransaction` object, or we check the pool if that transaction is already known to spare the runtime call. From this we gather the full set of `provides` tags and perform pruning of -the `ready` pool based on that. Also, we promote all transactions from `future` +the `ready` pool based on that. Also, we promote all transactions from `future` that have their tags satisfied. In case we remove transactions that we are unsure if they were already included diff --git a/substrate/docker/README.md b/substrate/docker/README.md index 71ddb2dffd1b..f9cc7ed14653 100644 --- a/substrate/docker/README.md +++ b/substrate/docker/README.md @@ -1,27 +1,32 @@ # Substrate Builder Docker Image -The Docker image in this folder is a `builder` image. It is self contained and allows users to build the binaries themselves. -There is no requirement on having Rust or any other toolchain installed but a working Docker environment. +The Docker image in this folder is a `builder` image. It is self contained and allows users to build the binaries +themselves. There is no requirement on having Rust or any other toolchain installed but a working Docker environment. -Unlike the `parity/polkadot` image which contains a single binary (`polkadot`!) used by default, the image in this folder builds and contains several binaries and you need to provide the name of the binary to be called. +Unlike the `parity/polkadot` image which contains a single binary (`polkadot`!) used by default, the image in this +folder builds and contains several binaries and you need to provide the name of the binary to be called. -You should refer to the [.Dockerfile](./substrate_builder.Dockerfile) for the actual list. At the time of editing, the list of included binaries is: +You should refer to the [.Dockerfile](./substrate_builder.Dockerfile) for the actual list. At the time of editing, the +list of included binaries is: -- substrate -- subkey -- node-template -- chain-spec-builder +- `substrate` +- `subkey` +- `node-template` +- `chain-spec-builder` First, install [Docker](https://docs.docker.com/get-docker/). -Then to generate the latest parity/substrate image. Please run: +Then to generate the latest `parity/substrate` image. Please run: ```sh ./build.sh ``` -> If you wish to create a debug build rather than a production build, then you may modify the [.Dockerfile](./substrate_builder.Dockerfile) replacing `cargo build --locked --release` with just `cargo build --locked` and replacing `target/release` with `target/debug`. +If you wish to create a debug build rather than a production build, then you may modify the +[.Dockerfile](./substrate_builder.Dockerfile) replacing `cargo build --locked --release` with just +`cargo build --locked` and replacing `target/release` with `target/debug`. -> If you get an error that a tcp port address is already in use then find an available port to use for the host port in the [.Dockerfile](./substrate_builder.Dockerfile). +If you get an error that a tcp port address is already in use then find an available port to use for the host port in +the [.Dockerfile](./substrate_builder.Dockerfile). The image can be used by passing the selected binary followed by the appropriate tags for this binary. @@ -32,7 +37,8 @@ Your best guess to get started is to pass the `--help flag`. Here are a few exam - `./run.sh node-template --version` - `./run.sh chain-spec-builder --help` -Then try running the following command to start a single node development chain using the Substrate Node Template binary `node-template`: +Then try running the following command to start a single node development chain using the Substrate Node Template binary +`node-template`: ```sh ./run.sh node-template --dev --ws-external diff --git a/substrate/docs/CHANGELOG.md b/substrate/docs/CHANGELOG.md index 25f8e582c78f..8a1b245a5b0c 100644 --- a/substrate/docs/CHANGELOG.md +++ b/substrate/docs/CHANGELOG.md @@ -8,24 +8,36 @@ The format is based on [Keep a Changelog]. ## 2.0.1-> 3.0.0 - Apollo 14 -Most notably, this is the first release of the new FRAME (2.0) with its new macro-syntax and some changes in types, and pallet versioning. This release also incorporates the faster and improve version 2.0 of the parity-scale-codec and upgraded dependencies all-around. While the `FinalityTracker` pallet has been dropped, this release marks the first public appearance of a few new pallets, too;Bounties, Lottery, Tips (extracted from the `Treasury`-pallet, see #7536) and Merkle-Mountain-Ranges (MMR). - -On the client side, the most notable changes are around the keystore, making it async and switching to a different signing model allowing for remote-signing to be implemented; and various changes to improve networking and light-client support, like adding the Grandpa warp sync request-response protocol (#7711). - -_Contracts_: Please note that the contracts pallet _is not part_ of this release. The pallet is not yet ready and will be released separately in the coming weeks. The currently released contracts pallet _is not compatible_ with the new FRAME, thus if you need the contracts pallet, we recommend you wait with the upgrade until it has been released, too. +Most notably, this is the first release of the new FRAME (2.0) with its new macro-syntax and some changes in types, and +pallet versioning. This release also incorporates the faster and improve version 2.0 of the `parity-scale-codec` and +upgraded dependencies all-around. While the `FinalityTracker` pallet has been dropped, this release marks the first +public appearance of a few new pallets, too;Bounties, Lottery, Tips (extracted from the `Treasury`-pallet, see #7536) +and Merkle-Mountain-Ranges (MMR). + +On the client side, the most notable changes are around the keystore, making it async and switching to a different +signing model allowing for remote-signing to be implemented; and various changes to improve networking and light-client +support, like adding the Grandpa warp sync request-response protocol (#7711). + +_Contracts_: Please note that the contracts pallet _is not part_ of this release. The pallet is not yet ready and will +be released separately in the coming weeks. The currently released contracts pallet _is not compatible_ with the new +FRAME, thus if you need the contracts pallet, we recommend you wait with the upgrade until it has been released, too. ### Upgrade instructions -Not too much has changed on the top and API level for developing Substrate between 2.0 and 3.0. The easiest and quickest path for upgrading is just to take the latest node-template and try applying your changes to it: +Not too much has changed on the top and API level for developing Substrate between 2.0 and 3.0. The easiest and quickest +path for upgrading is just to take the latest node-template and try applying your changes to it: 1. take a diff between 2.0 and your changes 2. store that diff 3. remove everything, copy over the 3.0 node-template 4. try re-applying your diff, manually, a hunk at a time. -If that doesn't work for you, we are working on an in-depth-guide for all major changes that took place and how you need to adapt your code for it. [You can find the upgrade guide under `docs/` in the repo](https://github.com/paritytech/substrate/blob/master/docs/Upgrading-2.0-to-3.0.md), if you have further questions or problem, please [feel free to ask in the github discussion board](https://github.com/paritytech/substrate/discussions). +If that doesn't work for you, we are working on an in-depth-guide for all major changes that took place and how you need +to adapt your code for it. [You can find the upgrade guide under `docs/` in the +repo](https://github.com/paritytech/substrate/blob/master/docs/Upgrading-2.0-to-3.0.md), if you have further questions +or problem, please [feel free to ask in the github discussion +board](https://github.com/paritytech/substrate/discussions). -Runtime -------- +#### Runtime * contracts: Charge rent for code storage (#7935) * contracts: Emit event on contract termination (#8014) @@ -63,8 +75,7 @@ Runtime * Move proxies migration (#7205) * Introduce `cancel_proposal` to rid us of those pesky proposals (#7111) -Client ------- +#### Client * Remove backwards-compatibility networking hack (#8068) * Extend SS58 network identifiers (#8039) @@ -97,8 +108,7 @@ Client * Refactor CurrencyToVote (#6896) * client/network: Stop sending noise legacy handshake (#7211) -API ---- +#### API * pallet macro: easier syntax for `#[pallet::pallet]` with `struct Pallet(_)` (#8091) * WasmExecutor takes a cache directory (#8057) @@ -106,7 +116,7 @@ API * Migrate assets pallet to new macros (#7984) * contracts: Make ChainExtension trait generic over the runtime (#8003) * Decouple the session validators from im-online (#7127) -* Update parity-scale-codec to 2.0 (#7994) +* Update `parity-scale-codec` to 2.0 (#7994) * Merkle Mountain Range pallet improvements (#7891) * Cleaner GRANDPA RPC API for proving finality (#7339) * Migrate frame-system to pallet attribute macro (#7898) @@ -136,8 +146,7 @@ API * SystemOrigin trait (#7226) * permit setting treasury pallet initial funding through genesis (#7214) -Runtime Migrations ------------------- +#### Runtime Migrations * Migrate assets pallet to new macros (#7984) * Fix elections-phragmen and proxy issue (#7040) @@ -149,8 +158,7 @@ Runtime Migrations ## 2.0.0-> 2.0.1 -Patch release with backports to fix broken nightly builds. -Namely contains backports of +Patch release with backports to fix broken nightly builds. Namely contains backports of * [#7381: Make Substrate compile with latest nightly](https://github.com/paritytech/substrate/pull/7381) * [#7238: Fix compilation with environmental on latest nightly](https://github.com/paritytech/substrate/pull/7238) @@ -161,8 +169,7 @@ Namely contains backports of ## 2.0.0-rc6 -> 2.0.0 – two dot 😮 -Runtime -------- +### Runtime * Rename `ModuleToIndex` to `PalletRuntimeSetup` (#7148) * Bounties (#5715) @@ -174,8 +181,7 @@ Runtime * Time-delay proxies (#6770) * Refcounts are now u32 (#7164) -Client ------- +### Client * Rename `inspect-key` to `inspect` (#7160) * Send import notification always for re-orgs (#7118) @@ -190,8 +196,7 @@ Client * Fix benchmark read/write key tracker for keys in child storages. (#6905) * *: Update to next libp2p version 0.24.0 (#6891) -API ---- +### API * grandpa-rpc: use FinalityProofProvider to check finality for rpc (#6215) * pow: replace the thread-base mining loop with a future-based mining worker (#7060) @@ -204,16 +209,14 @@ API * Add a `LightSyncState` field to the chain spec (#6894) * *: Update to next libp2p version 0.24.0 (#6891) -Runtime Migrations ------------------- +### Runtime Migrations * Time-delay proxies (#6770) ## 2.0.0-rc5 -> 2.0.0-rc6 – Rock Hyrax -Runtime -------- +### Runtime * Custom Codec Implementation for NPoS Election (#6720) * Successful `note_imminent_preimage` is free (#6793) @@ -224,8 +227,7 @@ Runtime * pallet-evm: add support for tuple-based precompile declarations (#6681) * grandpa: allow noting that the set has stalled (#6725) -Client ------- +#### Client * Merge Subkey into sc-cli (#4954) * RpcHandlers Refactorings (#6846) @@ -239,8 +241,7 @@ Client * Name all the tasks! (#6726) * Child nodes can be handled by adding a child `TaskManager` to the parent's `TaskManager` (#6771) -API ---- +### API * pow: add access to pre-digest for algorithm verifiers (#6900) * babe, aura, pow: only call check_inherents if authoring version is compatible (#6862) @@ -254,8 +255,7 @@ API ## 2.0.0-rc4 -> 2.0.0-rc5 – River Dolphin -Runtime -------- +### Runtime * Support using system storage directly for EVM balance and nonce (#6659) * Properly filter out duplicate voters in elections. (#6693) @@ -273,14 +273,13 @@ Runtime * pallet-evm: customizable chain id (#6537) * Refactor as_sub to make things clearer. (#6503) -Client ------- +### Client * Update wasmtime to (almost) latest master (#6662) * Update to latest sysinfo prevents leaking fd-handlers (#6708) * Tracing values (#6679) * Graceful shutdown for the task manager (#6654) -* Update substrate-networking Grafana dashboard (#6649) +* Update `substrate-networking` Grafana dashboard (#6649) * *: Update to libp2p v0.21.1 (#6559) * Send Status message on all newly-opened legacy substreams (#6593) * babe: report equivocations (#6362) @@ -288,8 +287,7 @@ Client * Remove the service, replacing it with a struct of individual chain components (#6352) * Fix tx-pool returning the same transaction multiple times (#6535) -API ---- +### API * Better handling of stable-only build (#6569) * Remove the service builder (#6557) @@ -302,8 +300,7 @@ API ## 2.0.0-rc3 -> 2.0.0-rc4 (Rhinoceros) -Runtime -------- +### Runtime * Staking Payout Creates Controller (#6496) * `pallet-scheduler`: Check that `when` is not in the past (#6480) @@ -321,8 +318,7 @@ Runtime * Add events for balance reserve and unreserve functions (#6330) * Introduce frozen indices. (#6307) -Client ------- +### Client * client/network/service: Add primary dimension to connection metrics (#6472) * Fix Babe secondary plain slots claiming (#6451) @@ -340,8 +336,7 @@ Client * new crate sc-light (#6235) * Allow adding a prefix to the informant (#6174) -API ---- +### API * seal: Remove ext_dispatch_call and ext_get_runtime_storage (#6464) * seal: Refactor ext_gas_price (#6478) @@ -356,16 +351,14 @@ API ## 2.0.0-rc2 -> 2.0.0-rc3 -Runtime -------- +### Runtime * Introduce stacked filtering (#6273) * Allow "pure" proxied accounts (#6236) * Allow over-weight collective proposals to be closed (#6163) * Fix Election when ForceNone V1 (#6166) -Client ------- +### Client * Make transaction pool prune transactions only of canonical blocks (#6123) * Rename all the election operations (#6245) @@ -381,14 +374,12 @@ Client ## 2.0.0-alpha.8 -> 2.0.0-rc1 -Runtime -------- +### Runtime * Allow operational recovery path if on_initialize use fullblock. (#6089) * Maximum extrinsic weight limit (#6067) -Client ------- +### Client * Add JSON format to import blocks and set it as default (#5816) * Upgrade to libp2p v0.19 - Changes the default PeerId representation (#6064) @@ -396,17 +387,17 @@ Client ## 2.0.0-alpha.7 -> 2.0.0-alpha.8 -**License Changed** -From this release forward, the code is released under a new – more relaxed – license scheme: Client (`sc-*`) is released under "GPL 3.0 or newer with the Classpath Exception", while primitives, FRAME, the pallets, utils and test-utils are released under "Apache 2.0". More details in the [Relax licensing scheme PR](https://github.com/paritytech/substrate/pull/5947). +**License Changed** From this release forward, the code is released under a new – more relaxed – license scheme: Client +(`sc-*`) is released under "GPL 3.0 or newer with the Classpath Exception", while primitives, FRAME, the pallets, utils +and test-utils are released under "Apache 2.0". More details in the [Relax licensing scheme +PR](https://github.com/paritytech/substrate/pull/5947). -Runtime -------- +### Runtime * Democracy weight (#5828) * Make `Digest` support `StorageAppend` (#5922) -Client ------- +### Client * Meter block import results via prometheus (#6025) * Added RuntimePublic for ecdsa public key. (#6029) @@ -418,8 +409,7 @@ Client ## 2.0.0-alpha.6 -> 2.0.0-alpha.7 -Runtime -------- +### Runtime * Use `storage::append` in the implementation of the storage types (#5889) * pallet-sudo: Store `DispatchResult` in `Sudid` event (#5804) @@ -431,8 +421,7 @@ Runtime * Transaction versioning in the RuntimeVersion (#5582) * emit TipClosed event on success tip payout (#5656) -Client ------- +### Client * Adds `export-state` subcommand (#5842) * Drop ClientProvider (#5823) @@ -454,8 +443,7 @@ Client * Use a Kademlia instance per `ProtocolId`. (#5045) * Report tasks metrics to Prometheus (#5619) -API ---- +### API * Child trie api changes BREAKING (#4857) * Pass max-total to RewardRemainder on end_era (#5697) @@ -463,8 +451,7 @@ API ## 2.0.0-alpha.5 -> 2.0.0-alpha.6 -Runtime -------- +### Runtime * Unsigned Validation best practices (#5563) * Generate Unit Tests for Benchmarks (#5527) @@ -473,8 +460,7 @@ Runtime * Pass transaction source to validate_transaction (#5366) * on_initialize return weight consumed and default cost to default DispatchInfo instead of zero (#5382) -Client ------- +### Client * Add new RPC method to get the chain type (#5576) * Reuse wasmtime instances, the PR (#5567) @@ -488,10 +474,10 @@ Client * Make transactions and block announces use notifications substre… (#5360) * Adds state_queryStorageAt (#5362) * Offchain Phragmén BREAKING. (#4517) -* `sc_rpc::system::SystemInfo.impl_version` now returns the full version (2.0.0-alpha.2-b950f731c-x86_64-linux-gnu) instead of the short version (1.0.0) (#5271) +* `sc_rpc::system::SystemInfo.impl_version` now returns the full version (2.0.0-alpha.2-b950f731c-x86_64-linux-gnu) + instead of the short version (1.0.0) (#5271) -API ---- +### API * Unsigned Validation best practices (#5563) * Split the Roles in three types (#5520) @@ -501,16 +487,14 @@ API ## 2.0.0-alpha.4 -> 2.0.0-alpha.5 -Runtime -------- +### Runtime * pallet-evm: configurable gasometer config (#5320) * Adds new event phase `Initialization` (#5302) ## 2.0.0-alpha.3 -> 2.0.0-alpha.4 -Runtime -------- +### Runtime * Move runtime upgrade to `frame-executive` (#5197) * Split fees and tips between author and treasury independently (#5207) @@ -520,22 +504,20 @@ Runtime * Adds `vested_transfer` to Vesting pallet (#5029) * Change extrinsic_count to extrinsic_index in pallet-utility (#5044) -Client ------- +### Client * client/finality-grandpa: Add Prometheus metrics to GossipValidator (#5237) * removes use of sc_client::Client from node-transaction-factory (#5158) * removes use of sc_client::Client from sc_network (#5147) * Use CLI to configure max instances cache (#5177) * client/service/src/builder.rs: Add build_info metric (#5192) -* Remove substrate-ui.parity.io from CORS whitelist (#5142) +* Remove `substrate-ui.parity.io` from CORS whitelist (#5142) * removes use of sc_client::Client from sc-rpc (#5063) * Use 128mb for db cache default (#5134) * Drop db-cache default from 1gig to 32mb (#5128) * Add more metrics to prometheus (#5034) -API ---- +### API * Produce block always on updated transaction pool state (#5227) * Add `ext_terminate` (#5234) diff --git a/substrate/docs/SECURITY.md b/substrate/docs/SECURITY.md index 19f5b145feb5..0d2064863d85 100644 --- a/substrate/docs/SECURITY.md +++ b/substrate/docs/SECURITY.md @@ -1,11 +1,14 @@ # Security Policy -Parity Technologies is committed to resolving security vulnerabilities in our software quickly and carefully. We take the necessary steps to minimize risk, provide timely information, and deliver vulnerability fixes and mitigations required to address security issues. +Parity Technologies is committed to resolving security vulnerabilities in our software quickly and carefully. We take +the necessary steps to minimize risk, provide timely information, and deliver vulnerability fixes and mitigations +required to address security issues. ## Reporting a Vulnerability -Security vulnerabilities in Parity software should be reported by email to security@parity.io. If you think your report might be eligible for the Parity Bug Bounty Program, your email should be send to bugbounty@parity.io. +Security vulnerabilities in Parity software should be reported by email to security@parity.io. If you think your report +might be eligible for the Parity Bug Bounty Program, your email should be send to bugbounty@parity.io. Your report should include the following: @@ -16,11 +19,16 @@ Your report should include the following: - reproduction - other details -Try to include as much information in your report as you can, including a description of the vulnerability, its potential impact, and steps for reproducing it. Be sure to use a descriptive subject line. +Try to include as much information in your report as you can, including a description of the vulnerability, its +potential impact, and steps for reproducing it. Be sure to use a descriptive subject line. -You'll receive a response to your email within two business days indicating the next steps in handling your report. We encourage finders to use encrypted communication channels to protect the confidentiality of vulnerability reports. You can encrypt your report using our public key. This key is [on MIT's key server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) server and reproduced below. +You'll receive a response to your email within two business days indicating the next steps in handling your report. We +encourage finders to use encrypted communication channels to protect the confidentiality of vulnerability reports. You +can encrypt your report using our public key. This key is [on MIT's key +server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) server and reproduced below. -After the initial reply to your report, our team will endeavor to keep you informed of the progress being made towards a fix. These updates will be sent at least every five business days. +After the initial reply to your report, our team will endeavor to keep you informed of the progress being made towards a +fix. These updates will be sent at least every five business days. Thank you for taking the time to responsibly disclose any vulnerabilities you find. @@ -29,19 +37,23 @@ Thank you for taking the time to responsibly disclose any vulnerabilities you fi Responsible investigation and reporting includes, but isn't limited to, the following: - Don't violate the privacy of other users, destroy data, etc. -- Don’t defraud or harm Parity Technologies Ltd or its users during your research; you should make a good faith effort to not interrupt or degrade our services. -- Don't target our physical security measures, or attempt to use social engineering, spam, distributed denial of service (DDOS) attacks, etc. +- Don’t defraud or harm Parity Technologies Ltd or its users during your research; you should make a good faith effort + to not interrupt or degrade our services. +- Don't target our physical security measures, or attempt to use social engineering, spam, distributed denial of service + (DDOS) attacks, etc. - Initially report the bug only to us and not to anyone else. -- Give us a reasonable amount of time to fix the bug before disclosing it to anyone else, and give us adequate written warning before disclosing it to anyone else. -- In general, please investigate and report bugs in a way that makes a reasonable, good faith effort not to be disruptive or harmful to us or our users. Otherwise your actions might be interpreted as an attack rather than an effort to be helpful. +- Give us a reasonable amount of time to fix the bug before disclosing it to anyone else, and give us adequate written + warning before disclosing it to anyone else. +- In general, please investigate and report bugs in a way that makes a reasonable, good faith effort not to be + disruptive or harmful to us or our users. Otherwise your actions might be interpreted as an attack rather than an + effort to be helpful. ## Bug Bounty Program -Our Bug Bounty Program allows us to recognize and reward members of the Parity community for helping us find and address significant bugs, in accordance with the terms of the Parity Bug Bounty Program. A detailed description on eligibility, rewards, legal information and terms & conditions for contributors can be found on [our website](https://paritytech.io/bug-bounty.html). - - - - +Our Bug Bounty Program allows us to recognize and reward members of the Parity community for helping us find and address +significant bugs, in accordance with the terms of the Parity Bug Bounty Program. A detailed description on eligibility, +rewards, legal information and terms & conditions for contributors can be found on [our +website](https://paritytech.io/bug-bounty.html). ## Plaintext PGP Key diff --git a/substrate/docs/STYLE_GUIDE.md b/substrate/docs/STYLE_GUIDE.md index a89dcf52ffc0..6ea0755d0807 100644 --- a/substrate/docs/STYLE_GUIDE.md +++ b/substrate/docs/STYLE_GUIDE.md @@ -2,19 +2,18 @@ title: Style Guide for Rust in Substrate --- -Where possible these styles are enforced by settings in `rustfmt.toml` so if you run `cargo fmt` -then you will adhere to most of these style guidelines automatically. +Where possible these styles are enforced by settings in `rustfmt.toml` so if you run `cargo fmt` then you will adhere to +most of these style guidelines automatically. # Code Formatting -- Indent using tabs. -- Lines should be longer than 100 characters long only in exceptional circumstances and certainly - no longer than 120. For this purpose, tabs are considered 4 characters wide. -- Indent levels should be greater than 5 only in exceptional circumstances and certainly no - greater than 8. If they are greater than 5, then consider using `let` or auxiliary functions in - order to strip out complex inline expressions. -- Never have spaces on a line prior to a non-whitespace character -- Follow-on lines are only ever a single indent from the original line. +- Indent using tabs. +- Lines should be longer than 100 characters long only in exceptional circumstances and certainly no longer than 120. + For this purpose, tabs are considered 4 characters wide. +- Indent levels should be greater than 5 only in exceptional circumstances and certainly no greater than 8. If they are + greater than 5, then consider using `let` or auxiliary functions in order to strip out complex inline expressions. +- Never have spaces on a line prior to a non-whitespace character +- Follow-on lines are only ever a single indent from the original line. ```rust fn calculation(some_long_variable_a: i8, some_long_variable_b: i8) -> bool { @@ -25,8 +24,8 @@ fn calculation(some_long_variable_a: i8, some_long_variable_b: i8) -> bool { } ``` -- Indent level should follow open parens/brackets, but should be collapsed to the smallest number - of levels actually used: +- Indent level should follow open parens/brackets, but should be collapsed to the smallest number of levels actually + used: ```rust fn calculate( @@ -45,10 +44,10 @@ fn calculate( } ``` -- `where` is indented, and its items are indented one further. -- Argument lists or function invocations that are too long to fit on one line are indented - similarly to code blocks, and once one param is indented in such a way, all others should be, - too. Run-on parameter lists are also acceptable for single-line run-ons of basic function calls. +- `where` is indented, and its items are indented one further. +- Argument lists or function invocations that are too long to fit on one line are indented similarly to code blocks, and + once one param is indented in such a way, all others should be, too. Run-on parameter lists are also acceptable for + single-line run-ons of basic function calls. ```rust // OK @@ -92,7 +91,7 @@ fn foo(really_long_parameter_name_1: SomeLongTypeName, really_long_parameter_nam } ``` -- Always end last item of a multi-line comma-delimited set with `,` when legal: +- Always end last item of a multi-line comma-delimited set with `,` when legal: ```rust struct Point { @@ -104,7 +103,7 @@ struct Point { enum Meal { Breakfast, Lunch, Dinner }; ``` -- Avoid trailing `;`s where unneeded. +- Avoid trailing `;`s where unneeded. ```rust if condition { @@ -112,8 +111,8 @@ if condition { } ``` -- `match` arms may be either blocks or have a trailing `,` but not both. -- Blocks should not be used unnecessarily. +- `match` arms may be either blocks or have a trailing `,` but not both. +- Blocks should not be used unnecessarily. ```rust match meal { @@ -126,9 +125,8 @@ match meal { # Style -- Panickers require explicit proofs they don't trigger. Calling `unwrap` is discouraged. The - exception to this rule is test code. Avoiding panickers by restructuring code is preferred if - feasible. +- Panickers require explicit proofs they don't trigger. Calling `unwrap` is discouraged. The exception to this rule is + test code. Avoiding panickers by restructuring code is preferred if feasible. ```rust let mut target_path = @@ -139,21 +137,22 @@ let mut target_path = ); ``` -- Unsafe code requires explicit proofs just as panickers do. When introducing unsafe code, - consider trade-offs between efficiency on one hand and reliability, maintenance costs, and - security on the other. Here is a list of questions that may help evaluating the trade-off while - preparing or reviewing a PR: - - how much more performant or compact the resulting code will be using unsafe code, - - how likely is it that invariants could be violated, - - are issues stemming from the use of unsafe code caught by existing tests/tooling, - - what are the consequences if the problems slip into production. +- Unsafe code requires explicit proofs just as panickers do. When introducing unsafe code, consider trade-offs between + efficiency on one hand and reliability, maintenance costs, and security on the other. Here is a list of questions + that may help evaluating the trade-off while preparing or reviewing a PR: + - how much more performant or compact the resulting code will be using unsafe code, + - how likely is it that invariants could be violated, + - are issues stemming from the use of unsafe code caught by existing tests/tooling, + - what are the consequences if the problems slip into production. # Manifest Formatting -> **TLDR** -> You can use the CLI tool [Zepter](https://crates.io/crates/zepter) to format the files: `zepter format features` +> **TLDR** You can use the CLI tool [Zepter](https://crates.io/crates/zepter) to format the files: `zepter format +> features` -Rust `Cargo.toml` files need to respect certain formatting rules. All entries need to be alphabetically sorted. This makes it easier to read them and insert new entries. The exhaustive list of rules is enforced by the CI. The general format looks like this: +Rust `Cargo.toml` files need to respect certain formatting rules. All entries need to be alphabetically sorted. This +makes it easier to read them and insert new entries. The exhaustive list of rules is enforced by the CI. The general +format looks like this: - The feature is written as a single line if it fits within 80 chars: ```toml @@ -161,7 +160,8 @@ Rust `Cargo.toml` files need to respect certain formatting rules. All entries ne default = [ "std" ] ``` -- Otherwise the feature is broken down into multiple lines with one entry per line. Each line is padded with one tab and no trailing spaces but a trailing comma. +- Otherwise the feature is broken down into multiple lines with one entry per line. Each line is padded with one tab and + no trailing spaces but a trailing comma. ```toml [features] default = [ diff --git a/substrate/docs/Upgrade.md b/substrate/docs/Upgrade.md index 4908d53f579e..08b5a7d37b64 100644 --- a/substrate/docs/Upgrade.md +++ b/substrate/docs/Upgrade.md @@ -1,5 +1,7 @@ -# Upgrade path for you building on substrate +# Upgrade path for you building on Substrate ## master - - crate rename has been fixed `sp-application-crypto` (was `sc-application-crypto`); `.maintain/rename-crates-for-2.0.sh` has been updated accordingly, you can use it to upgrade to latest naming convention - - crates have been renamed, run `bash .maintain/rename-crates-for-2.0.sh` \ No newline at end of file + - crate rename has been fixed `sp-application-crypto` (was `sc-application-crypto`); + `.maintain/rename-crates-for-2.0.sh` has been updated accordingly, you can use it to upgrade to latest naming + convention + - crates have been renamed, run `bash .maintain/rename-crates-for-2.0.sh` diff --git a/substrate/docs/Upgrading-2.0-to-3.0.md b/substrate/docs/Upgrading-2.0-to-3.0.md index 906018db9a70..58066ce074de 100644 --- a/substrate/docs/Upgrading-2.0-to-3.0.md +++ b/substrate/docs/Upgrading-2.0-to-3.0.md @@ -4,7 +4,8 @@ An incomplete guide. ## Refreshing the node-template -Not much has changed on the top and API level for developing Substrate between 2.0 and 3.0. If you've made only small changes to the node-template, we recommend to do the following - it is easiest and quickest path forward: +Not much has changed on the top and API level for developing Substrate between 2.0 and 3.0. If you've made only small +changes to the node-template, we recommend to do the following - it is easiest and quickest path forward: 1. take a diff between 2.0 and your changes 2. store that diff 3. remove everything, copy over the 3.0 node-template @@ -12,19 +13,30 @@ Not much has changed on the top and API level for developing Substrate between 2 ## In-Depth guide on the changes -If you've made significant changes or diverted from the node-template a lot, starting out with that is probably not helping. For that case, we'll take a look at all changes between 2.0 and 3.0 to the fully-implemented node and explain them one by one, so you can follow up, what needs to be changing for your node. +If you've made significant changes or diverted from the node-template a lot, starting out with that is probably not +helping. For that case, we'll take a look at all changes between 2.0 and 3.0 to the fully-implemented node and explain +them one by one, so you can follow up, what needs to be changing for your node. _Note_: Of course, step 1 is to upgrade your `Cargo.toml`'s to use the latest version of Substrate and all dependencies. -We'll be taking the diff from 2.0.1 to 3.0.0 on `bin/node` as the baseline of what has changed between these two versions in terms of adapting ones code base. We will not be covering the changes made on the tests and bench-marking as they are mostly reactions to the other changes. +We'll be taking the diff from 2.0.1 to 3.0.0 on `bin/node` as the baseline of what has changed between these two +versions in terms of adapting ones code base. We will not be covering the changes made on the tests and bench-marking as +they are mostly reactions to the other changes. ### Versions upgrade -First and foremost you have to upgrade the version pf the dependencies of course, that's `0.8.x -> 0.9.0` and `2.0.x -> 3.0.0` for all `sc-`, `sp-`, `frame-`, and `pallet-` coming from Parity. Further more this release also upgraded its own dependencies, most notably, we are now using `parity-scale-codec 2.0`, `parking_lot 0.11` and `substrate-wasm-builder 3.0.0` (as build dependency). All other dependency upgrades should resolve automatically or are just internal. However you might see some error that another dependency/type you have as a dependency and one of our upgraded crates don't match up, if so please check the version of said dependency - we've probably upgraded it. +First and foremost you have to upgrade the version pf the dependencies of course, that's `0.8.x -> 0.9.0` and `2.0.x -> +3.0.0` for all `sc-`, `sp-`, `frame-`, and `pallet-` coming from Parity. Further more this release also upgraded its own +dependencies, most notably, we are now using `parity-scale-codec 2.0`, `parking_lot 0.11` and `substrate-wasm-builder +3.0.0` (as build dependency). All other dependency upgrades should resolve automatically or are just internal. However +you might see some error that another dependency/type you have as a dependency and one of our upgraded crates don't +match up, if so please check the version of said dependency - we've probably upgraded it. ### WASM-Builder -The new version of wasm-builder has gotten a bit smarter and a lot faster (you should definitely switch). Once you've upgraded the dependency, in most cases you just have to remove the now obsolete `with_wasm_builder_from_crates_or_path`-function and you are good to go: +The new version of wasm-builder has gotten a bit smarter and a lot faster (you should definitely switch). Once you've +upgraded the dependency, in most cases you just have to remove the now obsolete +`with_wasm_builder_from_crates_or_path`-function and you are good to go: ```diff: rust --- a/bin/node/runtime/build.rs @@ -49,11 +61,15 @@ The new version of wasm-builder has gotten a bit smarter and a lot faster (you s #### FRAME 2.0 -The new FRAME 2.0 macros are a lot nicer to use and easier to read. While we were on that change though, we also cleaned up some mainly internal names and traits. The old `macro`'s still work and also produce the new structure, however, when plugging all that together as a Runtime, there's some things we have to adapt now: +The new FRAME 2.0 macros are a lot nicer to use and easier to read. While we were on that change though, we also cleaned +up some mainly internal names and traits. The old `macro`'s still work and also produce the new structure, however, when +plugging all that together as a Runtime, there's some things we have to adapt now: ##### `::Trait for Runtime` becomes `::Config for Runtime` -The most visible and significant change is that the macros no longer generate the `$pallet::Trait` but now a much more aptly named `$pallet::Config`. Thus, we need to rename all `::Trait for Runtime` into`::Config for Runtime`, e.g. for the `sudo` pallet we must do: +The most visible and significant change is that the macros no longer generate the `$pallet::Trait` but now a much more +aptly named `$pallet::Config`. Thus, we need to rename all `::Trait for Runtime` into`::Config for Runtime`, e.g. for +the `sudo` pallet we must do: ```diff -impl pallet_sudo::Trait for Runtime { @@ -65,11 +81,15 @@ The same goes for all `` and alike, which simply be #### SS58 Prefix is now a runtime param -Since [#7810](https://github.com/paritytech/substrate/pull/7810) we don't define the ss58 prefix in the chainspec anymore but moved it into the runtime. Namely, `frame_system` now needs a new `SS58Prefix`, which in substrate node we have defined for ourselves as: `pub const SS58Prefix: u8 = 42;`. Use your own chain-specific value there. +Since [#7810](https://github.com/paritytech/substrate/pull/7810) we don't define the ss58 prefix in the chainspec +anymore but moved it into the runtime. Namely, `frame_system` now needs a new `SS58Prefix`, which in Substrate node we +have defined for ourselves as: `pub const SS58Prefix: u8 = 42;`. Use your own chain-specific value there. #### Weight Definition -`type WeightInfo` has changed and instead on `weights::pallet_$name::WeightInfo` is now bound to the Runtime as `pallet_$name::weights::SubstrateWeight`. As a result we have to the change the type definitions everywhere in our Runtime accordingly: +`type WeightInfo` has changed and instead on `weights::pallet_$name::WeightInfo` is now bound to the Runtime as +`pallet_$name::weights::SubstrateWeight`. As a result we have to the change the type definitions everywhere in +our Runtime accordingly: ```diff - type WeightInfo = weights::pallet_$name::WeightInfo; @@ -170,24 +190,29 @@ And update the overall definition for weights on frame and a few related types a + type SystemWeightInfo = frame_system::weights::SubstrateWeight; ``` -#### Pallets: +#### Pallets ##### Assets The assets pallet has seen a variety of changes: -- [Features needed for reserve-backed stablecoins #7152 ](https://github.com/paritytech/substrate/pull/7152) -- [Freeze Assets and Asset Metadata #7346 ](https://github.com/paritytech/substrate/pull/7346) -- [Introduces account existence providers reference counting #7363 ]((https://github.com/paritytech/substrate/pull/7363)) +- [Features needed for reserve-backed stablecoins #7152](https://github.com/paritytech/substrate/pull/7152) +- [Freeze Assets and Asset Metadata #7346](https://github.com/paritytech/substrate/pull/7346) +- [Introduces account existence providers reference counting #7363]((https://github.com/paritytech/substrate/pull/7363)) -have all altered the feature set and changed the concepts. However, it has some of the best documentation and explains the current state very well. If you are using the assets pallet and need to upgrade from an earlier version, we recommend you use the current docs to guide your way! +have all altered the feature set and changed the concepts. However, it has some of the best documentation and explains +the current state very well. If you are using the assets pallet and need to upgrade from an earlier version, we +recommend you use the current docs to guide your way! ##### Contracts -As noted in the changelog, the `contracts`-pallet is still undergoing massive changes and is not yet part of this release. We are expecting for it to be released a few weeks after. If your chain is dependent on this pallet, we recommend to wait until it has been released as the currently released version is not compatible with FRAME 2.0. +As noted in the changelog, the `contracts`-pallet is still undergoing massive changes and is not yet part of this +release. We are expecting for it to be released a few weeks after. If your chain is dependent on this pallet, we +recommend to wait until it has been released as the currently released version is not compatible with FRAME 2.0. #### (changes) Treasury -As mentioned above, Bounties, Tips and Lottery have been extracted out of treasury into their own pallets - removing these options here. Secondly we must now specify the `BurnDestination` and `SpendFunds`, which now go the `Bounties`. +As mentioned above, Bounties, Tips and Lottery have been extracted out of treasury into their own pallets - removing +these options here. Secondly we must now specify the `BurnDestination` and `SpendFunds`, which now go the `Bounties`. ```diff - type Tippers = Elections; @@ -206,9 +231,10 @@ As mentioned above, Bounties, Tips and Lottery have been extracted out of treasu + type SpendFunds = Bounties; ``` -Factoring out Bounties and Tips means most of these definitions have now moved there, while the parameter types can be left as they were: +Factoring out Bounties and Tips means most of these definitions have now moved there, while the parameter types can be +left as they were: -###### 🆕 Bounties +##### 🆕 Bounties ```rust= impl pallet_bounties::Config for Runtime { @@ -241,11 +267,15 @@ impl pallet_tips::Config for Runtime { #### `FinalityTracker` removed -Finality Tracker has been removed in favor of a different approach to handle the issue in GRANDPA, [see #7228 for details](https://github.com/paritytech/substrate/pull/7228). With latest GRANDPA this is not needed anymore and can be removed without worry. +Finality Tracker has been removed in favor of a different approach to handle the issue in GRANDPA, [see #7228 for +details](https://github.com/paritytech/substrate/pull/7228). With latest GRANDPA this is not needed anymore and can be +removed without worry. #### (changes) Elections Phragmen -The pallet has been moved to a new system in which the exact amount of deposit for each voter, candidate, member, or runner-up is now deposited on-chain. Moreover, the concept of a `defunct_voter` is removed, since votes now have adequate deposit associated with them. A number of configuration parameters has changed to reflect this, as shown below: +The pallet has been moved to a new system in which the exact amount of deposit for each voter, candidate, member, or +runner-up is now deposited on-chain. Moreover, the concept of a `defunct_voter` is removed, since votes now have +adequate deposit associated with them. A number of configuration parameters has changed to reflect this, as shown below: ```diff= parameter_types! { @@ -277,11 +307,16 @@ The pallet has been moved to a new system in which the exact amount of deposit f type TermDuration = TermDuration; ``` - **This upgrade requires storage [migration](https://github.com/paritytech/substrate/blob/master/frame/elections-phragmen/src/migrations_3_0_0.rs)**. Further details can be found in the [pallet-specific changelog](https://github.com/paritytech/substrate/blob/master/frame/elections-phragmen/CHANGELOG.md#security). + **This upgrade requires storage + [migration](https://github.com/paritytech/substrate/blob/master/frame/elections-phragmen/src/migrations_3_0_0.rs)**. + Further details can be found in the [pallet-specific + changelog](https://github.com/paritytech/substrate/blob/master/frame/elections-phragmen/CHANGELOG.md#security). #### (changes) Democracy -Democracy brings three new settings with this release, all to allow for better influx- and spam-control. Namely these allow to specify the maximum number of proposals at a time, who can blacklist and who can cancel proposals. This diff acts as a good starting point: +Democracy brings three new settings with this release, all to allow for better influx- and spam-control. Namely these +allow to specify the maximum number of proposals at a time, who can blacklist and who can cancel proposals. This diff +acts as a good starting point: ```diff= @@ -508,6 +537,14 @@ impl pallet_democracy::Trait for Runtime { @@ -311,7 +346,9 @@ Democracy brings three new settings with this release, all to allow for better i ### Primitives -The shared primitives define the API between Client and Runtime. Usually, you don't have to touch nor directly interact with them, unless you created your own client or frame-less runtime. Therefore we'd expect you to understand whether you are effected by changes and how to update your code yourself. +The shared primitives define the API between Client and Runtime. Usually, you don't have to touch nor directly interact +with them, unless you created your own client or frame-less runtime. Therefore we'd expect you to understand whether you +are effected by changes and how to update your code yourself. ---- @@ -321,10 +358,17 @@ The shared primitives define the API between Client and Runtime. Usually, you do A few minor things have changed in the `cli` (compared to 2.0.1): -1. we've [replaced the newly added `BuildSyncSpec` subcommand with an RPC API](https://github.com/paritytech/substrate/commit/65cc9af9b8df8d36928f6144ee7474cefbd70454#diff-c57da6fbeff8c46ce15f55ea42fedaa5a4684d79578006ce4af01ae04fd6b8f8) in an on-going effort to make light-client-support smoother, see below -2. we've [removed double accounts from our chainspec-builder](https://github.com/paritytech/substrate/commit/31499cd29ed30df932fb71b7459796f7160d0272) -3. we [don't fallback to `--chain flaming-fir` anymore](https://github.com/paritytech/substrate/commit/13cdf1c8cd2ee62d411f82b64dc7eba860c9c6c6), if no chain is given our substrate-node will error. -4. [the `subkey`-integration has seen a fix to the `insert`-command](https://github.com/paritytech/substrate/commit/54bde60cfd2c544c54e9e8623b6b8725b99557f8) that requires you to now add the `&cli` as a param. +1. we've [replaced the newly added `BuildSyncSpec` subcommand with an RPC + API](https://github.com/paritytech/substrate/commit/65cc9af9b8df8d36928f6144ee7474cefbd70454#diff-c57da6fbeff8c46ce15f55ea42fedaa5a4684d79578006ce4af01ae04fd6b8f8) + in an on-going effort to make light-client-support smoother, see below +2. we've [removed double accounts from our + chainspec-builder](https://github.com/paritytech/substrate/commit/31499cd29ed30df932fb71b7459796f7160d0272) +3. we [don't fallback to `--chain flaming-fir` + anymore](https://github.com/paritytech/substrate/commit/13cdf1c8cd2ee62d411f82b64dc7eba860c9c6c6), if no chain is + given our `substrate-node` will error. +4. [the `subkey`-integration has seen a fix to the + `insert`-command](https://github.com/paritytech/substrate/commit/54bde60cfd2c544c54e9e8623b6b8725b99557f8) that + requires you to now add the `&cli` as a param. ```diff= --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -344,7 +388,8 @@ A few minor things have changed in the `cli` (compared to 2.0.1): ##### Light client support -As said, we've added a new optional RPC service for improved light client support. For that to work, we need to pass the `chain_spec` and give access to the `AuxStore` to our `rpc`: +As said, we've added a new optional RPC service for improved light client support. For that to work, we need to pass the +`chain_spec` and give access to the `AuxStore` to our `rpc`: ```diff= @@ -438,17 +483,30 @@ and add the new service: ##### Telemetry -The telemetry subsystem has seen a few fixes and refactorings to allow for a more flexible handling, in particular in regards to parachains. Most notably `sc_service::spawn_tasks` now returns the `telemetry_connection_notifier` as the second member of the tuple, (`let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(`), which should be passed to `telemetry_on_connect` of `new_full_base` now: `telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()),` (see the service-section below for a full diff). +The telemetry subsystem has seen a few fixes and refactorings to allow for a more flexible handling, in particular in +regards to parachains. Most notably `sc_service::spawn_tasks` now returns the `telemetry_connection_notifier` as the +second member of the tuple, (`let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(`), which +should be passed to `telemetry_on_connect` of `new_full_base` now: `telemetry_on_connect: +telemetry_connection_notifier.map(|x| x.on_connect_stream()),` (see the service-section below for a full diff). ##### Async & Remote Keystore support -In order to allow for remote-keystores, the keystore-subsystem has been reworked to support async operations and generally refactored to not provide the keys itself but only sign on request. This allows for remote-keystore to never hand out keys and thus to operate any substrate-based node in a manner without ever having the private keys in the local system memory. +In order to allow for remote-keystores, the keystore-subsystem has been reworked to support async operations and +generally refactored to not provide the keys itself but only sign on request. This allows for remote-keystore to never +hand out keys and thus to operate any Substrate-based node in a manner without ever having the private keys in the local +system memory. -There are some operations, however, that the keystore must be local for performance reasons and for which a remote keystore won't work (in particular around parachains). As such, the keystore has both a slot for remote but also always a local instance, where some operations hard bind to the local variant, while most subsystems just ask the generic keystore which prefers a remote signer if given. To reflect this change, `sc_service::new_full_parts` now returns a `KeystoreContainer` rather than the keystore, and the other subsystems (e.g. `sc_service::PartialComponents`) expect to be given that. +There are some operations, however, that the keystore must be local for performance reasons and for which a remote +keystore won't work (in particular around parachains). As such, the keystore has both a slot for remote but also always +a local instance, where some operations hard bind to the local variant, while most subsystems just ask the generic +keystore which prefers a remote signer if given. To reflect this change, `sc_service::new_full_parts` now returns a +`KeystoreContainer` rather than the keystore, and the other subsystems (e.g. `sc_service::PartialComponents`) expect to +be given that. -###### on RPC: +###### on RPC -This has most visible changes for the rpc, where we are switching from the previous `KeyStorePtr` to the new `SyncCryptoStorePtr`: +This has most visible changes for the rpc, where we are switching from the previous `KeyStorePtr` to the new +`SyncCryptoStorePtr`: ```diff @@ -483,9 +541,15 @@ This has most visible changes for the rpc, where we are switching from the previ ##### GRANDPA -As already in the changelog, a few things significant things have changed in regards to GRANDPA: the finality tracker has been replaced, an RPC command has been added and WARP-sync-support for faster light client startup has been implemented. All this means we have to do a few changes to our GRANDPA setup procedures in the client. +As already in the changelog, a few things significant things have changed in regards to GRANDPA: the finality tracker +has been replaced, an RPC command has been added and WARP-sync-support for faster light client startup has been +implemented. All this means we have to do a few changes to our GRANDPA setup procedures in the client. -First and foremost, grandpa internalised a few aspects, and thus `new_partial` doesn't expect a tuple but only the `grandpa::SharedVoterState` as input now, and unpacking that again later is not needed anymore either. On the opposite side `grandpa::FinalityProofProvider::new_for_service` now requires the `Some(shared_authority_set)` to be passed as a new third parameter. This set also becomes relevant when adding warp-sync-support, which is added as an extra-protocol-layer to the networking as: +First and foremost, grandpa internalised a few aspects, and thus `new_partial` doesn't expect a tuple but only the +`grandpa::SharedVoterState` as input now, and unpacking that again later is not needed anymore either. On the opposite +side `grandpa::FinalityProofProvider::new_for_service` now requires the `Some(shared_authority_set)` to be passed as a +new third parameter. This set also becomes relevant when adding warp-sync-support, which is added as an +extra-protocol-layer to the networking as: ```diff= + config.network.extra_sets.push(grandpa::grandpa_peers_set_config()); @@ -496,11 +560,13 @@ First and foremost, grandpa internalised a few aspects, and thus `new_partial` d + )); ``` -As these changes pull through the entirety of `cli/src/service.rs`, we recommend looking at the final diff below for guidance. +As these changes pull through the entirety of `cli/src/service.rs`, we recommend looking at the final diff below for +guidance. ##### In a nutshell -Altogether this accumulates to the following diff for `node/cli/src/service.rs`. If you want these features and have modified your chain you should probably try to apply these patches: +Altogether this accumulates to the following diff for `node/cli/src/service.rs`. If you want these features and have +modified your chain you should probably try to apply these patches: ```diff= diff --git a/substrate/docs/node-template-release.md b/substrate/docs/node-template-release.md index 911e6a2bbe71..0acaf3bdc611 100644 --- a/substrate/docs/node-template-release.md +++ b/substrate/docs/node-template-release.md @@ -1,71 +1,65 @@ # Substrate Node Template Release Process -1. This release process has to be run in a github checkout Substrate directory with your work -committed into `https://github.com/paritytech/substrate/`, because the build script will check -the existence of your current git commit ID in the remote repository. +## This release process has to be run in a github checkout Substrate directory with your work committed into +`https://github.com/paritytech/substrate/`, because the build script will check the existence of your current git commit +ID in the remote repository. - Assume you are in root directory of Substrate. Run: +Assume you are in root directory of Substrate. Run: - ```bash - cd scripts/ci/ - ./node-template-release.sh - ``` +```bash +cd scripts/ci/ ./node-template-release.sh +``` -2. Expand the output tar gzipped file and replace files in current Substrate Node Template -by running the following command. +## Expand the output tar gzipped file and replace files in current Substrate Node Template by running the following +command. - ```bash - # This is where the tar.gz file uncompressed - cd substrate-node-template - # rsync with force copying. Note the slash at the destination directory is important - rsync -avh * / - # For dry-running add `-n` argument - # rsync -avhn * / - ``` +```bash +# This is where the tar.gz file uncompressed cd substrate-node-template # rsync with force copying. Note the +slash at the destination directory is important rsync -avh * / # For dry-running +add `-n` argument # rsync -avhn * / +``` - The above command only copies existing files from the source to the destination, but does not - delete files/directories that are removed from the source. So you need to manually check and - remove them in the destination. +The above command only copies existing files from the source to the destination, but does not delete files/directories +that are removed from the source. So you need to manually check and remove them in the destination. -3. There is a `Cargo.toml` file in the root directory. Inside, dependencies are listed form and -linked to a certain git commit in Substrate remote repository, such as: +## There is a `Cargo.toml` file in the root directory. Inside, dependencies are listed form and linked to a certain git +commit in Substrate remote repository, such as: - ```toml - sp-core = { version = "7.0.0", git = "https://github.com/paritytech/substrate.git", rev = "de80d0107336a9c7a2efdc0199015e4d67fcbdb5", default-features = false } - ``` +```toml +toml sp-core = { version = "7.0.0", git = "https://github.com/paritytech/substrate.git", rev = +"de80d0107336a9c7a2efdc0199015e4d67fcbdb5", default-features = false } +``` - We will update each of them to link to the Rust [crate registry](https://crates.io/). -After confirming the versioned package is published in the crate, the above will become: +e will update each of them to link to the Rust [crate registry](https://crates.io/). After confirming the versioned +package is published in the crate, the above will become: - ```toml - [workspace.dependencies] - sp-core = { version = "7.0.0", default-features = false } - ``` +```toml +[workspace.dependencies] sp-core = { version = "7.0.0", default-features = false } +``` - P.S: This step can be automated if we update `node-template-release` package in - `scripts/ci/node-template-release`. +P.S: This step can be automated if we update `node-template-release` package in `scripts/ci/node-template-release`. -4. Once the `Cargo.toml` is updated, compile and confirm that the Node Template builds. Then commit -the changes to a new branch in [Substrate Node Template](https://github.com/substrate-developer-hub/substrate-node-template), and make a PR. +## Once the `Cargo.toml` is updated, compile and confirm that the Node Template builds. Then commit the changes to a new +branch in [Substrate Node Template](https://github.com/substrate-developer-hub/substrate-node-template), and make a PR. - > Note that there is a chance the code in Substrate Node Template works with the linked Substrate git - commit but not with published packages due to the latest (as yet) unpublished features. In this case, - rollback that section of the Node Template to its previous version to ensure the Node Template builds. +> Note that there is a chance the code in Substrate Node Template works with the linked Substrate git commit but not +with published packages due to the latest (as yet) unpublished features. In this case, rollback that section of the +Node Template to its previous version to ensure the Node Template builds. -5. Once the PR is merged, tag the merged commit in master branch with the version number -`vX.Y.Z+A` (e.g. `v3.0.0+1`). The `X`(major), `Y`(minor), and `Z`(patch) version number should -follow Substrate release version. The last digit is any significant fixes made in the Substrate -Node Template apart from Substrate. When the Substrate version is updated, this digit is reset to 0. +## Once the PR is merged, tag the merged commit in master branch with the version number `vX.Y.Z+A` (e.g. `v3.0.0+1`) +The `X`(major), `Y`(minor), and `Z`(patch) version number should follow Substrate release version. The last digit is any +significant fixes made in the Substrate Node Template apart from Substrate. When the Substrate version is updated, this +digit is reset to 0. ## Troubleshooting -- Running the script `./node-template-release.sh `, after all tests passed - successfully, seeing the following error message: +- Running the script `./node-template-release.sh `, after all tests passed successfully, seeing the + following error message: - ``` - thread 'main' panicked at 'Creates output file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:250:10 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - ``` +``` +thread 'main' panicked at 'Creates output file: Os { code: 2, kind: NotFound, message: "No such file or directory" +}', src/main.rs:250:10 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` - This is likely due to that your output path is not a valid `tar.gz` filename or you don't have write - permission to the destination. Try with a simple output path such as `~/node-tpl.tar.gz`. +This is likely due to that your output path is not a valid `tar.gz` filename or you don't have write permission to the +destination. Try with a simple output path such as `~/node-tpl.tar.gz`. diff --git a/substrate/frame/README.md b/substrate/frame/README.md index 47a7892c2c8d..0a6c01fd035d 100644 --- a/substrate/frame/README.md +++ b/substrate/frame/README.md @@ -1,11 +1,12 @@ # FRAME -The FRAME development environment provides modules (called "pallets") and support libraries that you can use, modify, and extend to build the runtime logic to suit the needs of your blockchain. +The FRAME development environment provides modules (called "pallets") and support libraries that you can use, modify, +and extend to build the runtime logic to suit the needs of your blockchain. -### Documentation +## Documentation https://docs.substrate.io/reference/frame-pallets/ -### Issues +## Issues https://github.com/orgs/paritytech/projects/40 diff --git a/substrate/frame/assets/README.md b/substrate/frame/assets/README.md index aae5244953e5..863bcccbbaf8 100644 --- a/substrate/frame/assets/README.md +++ b/substrate/frame/assets/README.md @@ -4,21 +4,21 @@ A simple, secure module for dealing with fungible assets. ## Overview -The Assets module provides functionality for asset management of fungible asset classes -with a fixed supply, including: +The Assets module provides functionality for asset management of fungible asset classes with a fixed supply, including: * Asset Issuance * Asset Transfer * Asset Destruction -To use it in your runtime, you need to implement the assets [`assets::Config`](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/trait.Config.html). +To use it in your runtime, you need to implement the assets +[`assets::Config`](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/trait.Config.html). -The supported dispatchable functions are documented in the [`assets::Call`](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/enum.Call.html) enum. +The supported dispatchable functions are documented in the +[`assets::Call`](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/enum.Call.html) enum. ### Terminology -* **Asset issuance:** The creation of a new asset, whose total supply will belong to the - account that issues the asset. +* **Asset issuance:** The creation of a new asset, whose total supply will belong to the account that issues the asset. * **Asset transfer:** The action of transferring assets from one account to another. * **Asset destruction:** The process of an account removing its entire holding of an asset. * **Fungible asset:** An asset whose units are interchangeable. @@ -30,20 +30,19 @@ The assets system in Substrate is designed to make the following possible: * Issue a unique asset to its creator's account. * Move assets between accounts. -* Remove an account's balance of an asset when requested by that account's owner and update - the asset's total supply. +* Remove an account's balance of an asset when requested by that account's owner and update the asset's total supply. ## Interface ### Dispatchable Functions * `issue` - Issues the total supply of a new fungible asset to the account of the caller of the function. -* `transfer` - Transfers an `amount` of units of fungible asset `id` from the balance of -the function caller's account (`origin`) to a `target` account. -* `destroy` - Destroys the entire holding of a fungible asset `id` associated with the account -that called the function. +* `transfer` - Transfers an `amount` of units of fungible asset `id` from the balance of the function caller's account +(`origin`) to a `target` account. +* `destroy` - Destroys the entire holding of a fungible asset `id` associated with the account that called the function. -Please refer to the [`Call`](https://docs.rs/pallet-assets/latest/pallet_assets/enum.Call.html) enum and its associated variants for documentation on each function. +Please refer to the [`Call`](https://docs.rs/pallet-assets/latest/pallet_assets/enum.Call.html) enum and its associated +variants for documentation on each function. ### Public Functions @@ -51,7 +50,8 @@ Please refer to the [`Call`](https://docs.rs/pallet-assets/latest/pallet_assets/ * `balance` - Get the asset `id` balance of `who`. * `total_supply` - Get the total supply of an asset `id`. -Please refer to the [`Pallet`](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/struct.Pallet.html) struct for details on publicly available functions. +Please refer to the [`Pallet`](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/struct.Pallet.html) struct for +details on publicly available functions. ## Usage @@ -111,11 +111,10 @@ pub mod pallet { ## Assumptions -Below are assumptions that must be held when using this module. If any of -them are violated, the behavior of this module is undefined. +Below are assumptions that must be held when using this module. If any of them are violated, the behavior of this +module is undefined. -* The total count of assets should be less than - `Config::AssetId::max_value()`. +* The total count of assets should be less than `Config::AssetId::max_value()`. ## Related Modules diff --git a/substrate/frame/atomic-swap/README.md b/substrate/frame/atomic-swap/README.md index 888a64ec7e06..d5f924c64fc8 100644 --- a/substrate/frame/atomic-swap/README.md +++ b/substrate/frame/atomic-swap/README.md @@ -16,8 +16,8 @@ claimed within a specified duration of time, the sender may cancel it. ### Dispatchable Functions -* `create_swap` - called by a sender to register a new atomic swap -* `claim_swap` - called by the target to approve a swap -* `cancel_swap` - may be called by a sender after a specified duration +- `create_swap` - called by a sender to register a new atomic swap +- `claim_swap` - called by the target to approve a swap +- `cancel_swap` - may be called by a sender after a specified duration License: Apache-2.0 diff --git a/substrate/frame/aura/README.md b/substrate/frame/aura/README.md index 263f158d7906..3ce9652a5385 100644 --- a/substrate/frame/aura/README.md +++ b/substrate/frame/aura/README.md @@ -23,6 +23,7 @@ consensus rounds (via `slots`). If you're interested in hacking on this module, it is useful to understand the interaction with `substrate/primitives/inherents/src/lib.rs` and, specifically, the required implementation of [`ProvideInherent`](https://docs.rs/sp-inherents/latest/sp_inherents/trait.ProvideInherent.html) and -[`ProvideInherentData`](https://docs.rs/sp-inherents/latest/sp_inherents/trait.ProvideInherentData.html) to create and check inherents. +[`ProvideInherentData`](https://docs.rs/sp-inherents/latest/sp_inherents/trait.ProvideInherentData.html) to create and +check inherents. License: Apache-2.0 diff --git a/substrate/frame/authority-discovery/README.md b/substrate/frame/authority-discovery/README.md index 9a534dcbeb6f..f4435a9f3161 100644 --- a/substrate/frame/authority-discovery/README.md +++ b/substrate/frame/authority-discovery/README.md @@ -1,6 +1,6 @@ -# Authority discovery module. +# Authority discovery module This module is used by the `client/authority-discovery` to retrieve the current set of authorities. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/authorship/README.md b/substrate/frame/authorship/README.md index d61747da3e10..db4b979319ab 100644 --- a/substrate/frame/authorship/README.md +++ b/substrate/frame/authorship/README.md @@ -2,4 +2,4 @@ Authorship tracking for FRAME runtimes. This tracks the current author of the block and recent uncles. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/babe/README.md b/substrate/frame/babe/README.md index 6f20be89efc0..3d1af534eeb6 100644 --- a/substrate/frame/babe/README.md +++ b/substrate/frame/babe/README.md @@ -1,4 +1,4 @@ Consensus extension module for BABE consensus. Collects on-chain randomness from VRF outputs and manages epoch transitions. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/balances/README.md b/substrate/frame/balances/README.md index fa1ee622d48c..1dc93a6bd8fd 100644 --- a/substrate/frame/balances/README.md +++ b/substrate/frame/balances/README.md @@ -21,49 +21,48 @@ The Balances module provides functions for: ### Terminology -- **Existential Deposit:** The minimum balance required to create or keep an account open. This prevents -"dust accounts" from filling storage. When the free plus the reserved balance (i.e. the total balance) - fall below this, then the account is said to be dead; and it loses its functionality as well as any - prior history and all information on it is removed from the chain's state. - No account should ever have a total balance that is strictly between 0 and the existential - deposit (exclusive). If this ever happens, it indicates either a bug in this module or an - erroneous raw mutation of storage. +- **Existential Deposit:** The minimum balance required to create or keep an account open. This prevents "dust accounts" +from filling storage. When the free plus the reserved balance (i.e. the total balance) fall below this, then the account + is said to be dead; and it loses its functionality as well as any prior history and all information on it is removed + from the chain's state. No account should ever have a total balance that is strictly between 0 and the existential + deposit (exclusive). If this ever happens, it indicates either a bug in this module or an erroneous raw mutation of + storage. - **Total Issuance:** The total number of units in existence in a system. -- **Reaping an account:** The act of removing an account by resetting its nonce. Happens after its -total balance has become zero (or, strictly speaking, less than the Existential Deposit). +- **Reaping an account:** The act of removing an account by resetting its nonce. Happens after its total balance has +become zero (or, strictly speaking, less than the Existential Deposit). -- **Free Balance:** The portion of a balance that is not reserved. The free balance is the only - balance that matters for most operations. +- **Free Balance:** The portion of a balance that is not reserved. The free balance is the only balance that matters for + most operations. -- **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. - Reserved balance can still be slashed, but only after all the free balance has been slashed. +- **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. Reserved balance can + still be slashed, but only after all the free balance has been slashed. -- **Imbalance:** A condition when some funds were credited or debited without equal and opposite accounting -(i.e. a difference between total issuance and account balances). Functions that result in an imbalance will -return an object of the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is -simply dropped, it should automatically maintain any book-keeping such as total issuance.) +- **Imbalance:** A condition when some funds were credited or debited without equal and opposite accounting (i.e. a +difference between total issuance and account balances). Functions that result in an imbalance will return an object of +the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is simply dropped, it should +automatically maintain any book-keeping such as total issuance.) -- **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple -locks always operate over the same funds, so they "overlay" rather than "stack". +- **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple locks +always operate over the same funds, so they "overlay" rather than "stack". ### Implementations -The Balances module provides implementations for the following traits. If these traits provide the functionality -that you need, then you can avoid coupling with the Balances module. +The Balances module provides implementations for the following traits. If these traits provide the functionality that +you need, then you can avoid coupling with the Balances module. -- [`Currency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.Currency.html): Functions for dealing with a -fungible assets system. +- [`Currency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.Currency.html): Functions for dealing +with a fungible assets system. - [`ReservableCurrency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.ReservableCurrency.html): Functions for dealing with assets that can be reserved from an account. -- [`LockableCurrency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.LockableCurrency.html): Functions for -dealing with accounts that allow liquidity restrictions. +- [`LockableCurrency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.LockableCurrency.html): Functions +for dealing with accounts that allow liquidity restrictions. - [`Imbalance`](https://docs.rs/frame-support/latest/frame_support/traits/trait.Imbalance.html): Functions for handling -imbalances between total issuance in the system and account balances. Must be used when a function -creates new funds (e.g. a reward) or destroys some funds (e.g. a system fee). -- [`IsDeadAccount`](https://docs.rs/frame-support/latest/frame_support/traits/trait.IsDeadAccount.html): Determiner to say whether a -given account is unused. +imbalances between total issuance in the system and account balances. Must be used when a function creates new funds +(e.g. a reward) or destroys some funds (e.g. a system fee). +- [`IsDeadAccount`](https://docs.rs/frame-support/latest/frame_support/traits/trait.IsDeadAccount.html): Determiner to +say whether a given account is unused. ## Interface @@ -113,10 +112,11 @@ fn update_ledger( ## Genesis config -The Balances module depends on the [`GenesisConfig`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/struct.GenesisConfig.html). +The Balances module depends on the +[`GenesisConfig`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/struct.GenesisConfig.html). ## Assumptions -* Total issued balanced of all accounts should be less than `Config::Balance::max_value()`. +- Total issued balanced of all accounts should be less than `Config::Balance::max_value()`. License: Apache-2.0 diff --git a/substrate/frame/benchmarking/README.md b/substrate/frame/benchmarking/README.md index dc6a184435df..bf0bde2c3df5 100644 --- a/substrate/frame/benchmarking/README.md +++ b/substrate/frame/benchmarking/README.md @@ -1,99 +1,86 @@ # Substrate Runtime Benchmarking Framework -This crate contains a set of utilities that can be used to benchmark and weigh FRAME pallets that -you develop for your Substrate Runtime. +This crate contains a set of utilities that can be used to benchmark and weigh FRAME pallets that you develop for your +Substrate Runtime. ## Overview -Substrate's FRAME framework allows you to develop custom logic for your blockchain that can be -included in your runtime. This flexibility is key to help you design complex and interactive -pallets, but without accurate weights assigned to dispatchables, your blockchain may become -vulnerable to denial of service (DoS) attacks by malicious actors. +Substrate's FRAME framework allows you to develop custom logic for your blockchain that can be included in your runtime. +This flexibility is key to help you design complex and interactive pallets, but without accurate weights assigned to +dispatchables, your blockchain may become vulnerable to denial of service (DoS) attacks by malicious actors. -The Substrate Runtime Benchmarking Framework is a tool you can use to mitigate DoS attacks against -your blockchain network by benchmarking the computational resources required to execute different -functions in the runtime, for example extrinsics, `on_initialize`, `verify_unsigned`, etc... +The Substrate Runtime Benchmarking Framework is a tool you can use to mitigate DoS attacks against your blockchain +network by benchmarking the computational resources required to execute different functions in the runtime, for example +extrinsics, `on_initialize`, `verify_unsigned`, etc... -The general philosophy behind the benchmarking system is: If your node can know ahead of time how -long it will take to execute an extrinsic, it can safely make decisions to include or exclude that -extrinsic based on its available resources. By doing this, it can keep the block production and -import process running smoothly. +The general philosophy behind the benchmarking system is: If your node can know ahead of time how long it will take to +execute an extrinsic, it can safely make decisions to include or exclude that extrinsic based on its available +resources. By doing this, it can keep the block production and import process running smoothly. To achieve this, we need to model how long it takes to run each function in the runtime by: * Creating custom benchmarking logic that executes a specific code path of a function. -* Executing the benchmark in the Wasm execution environment, on a specific set of hardware, with a - custom runtime configuration, etc... -* Executing the benchmark across controlled ranges of possible values that may affect the result of - the benchmark (called "components"). +* Executing the benchmark in the Wasm execution environment, on a specific set of hardware, with a custom runtime + configuration, etc... +* Executing the benchmark across controlled ranges of possible values that may affect the result of the benchmark + (called "components"). * Executing the benchmark multiple times at each point in order to isolate and remove outliers. * Using the results of the benchmark to create a linear model of the function across its components. -With this linear model, we are able to estimate ahead of time how long it takes to execute some -logic, and thus make informed decisions without actually spending any significant resources at -runtime. +With this linear model, we are able to estimate ahead of time how long it takes to execute some logic, and thus make +informed decisions without actually spending any significant resources at runtime. -Note that we assume that all extrinsics are assumed to be of linear complexity, which is why we are -able to always fit them to a linear model. Quadratic or higher complexity functions are, in general, -considered to be dangerous to the runtime as the weight of these functions may explode as the -runtime state or input becomes too complex. +Note that we assume that all extrinsics are assumed to be of linear complexity, which is why we are able to always fit +them to a linear model. Quadratic or higher complexity functions are, in general, considered to be dangerous to the +runtime as the weight of these functions may explode as the runtime state or input becomes too complex. The benchmarking framework comes with the following tools: -* [A set of macros](./src/lib.rs) (`benchmarks!`, `add_benchmark!`, etc...) to make it easy to - write, test, and add runtime benchmarks. +* [A set of macros](./src/lib.rs) (`benchmarks!`, `add_benchmark!`, etc...) to make it easy to write, test, and add + runtime benchmarks. * [A set of linear regression analysis functions](./src/analysis.rs) for processing benchmark data. -* [A CLI extension](../../utils/frame/benchmarking-cli/README.md) to make it easy to execute benchmarks on your - node. +* [A CLI extension](../../utils/frame/benchmarking-cli/README.md) to make it easy to execute benchmarks on your node. -The end-to-end benchmarking pipeline is disabled by default when compiling a node. If you want to -run benchmarks, you need to enable it by compiling with a Rust feature flag `runtime-benchmarks`. -More details about this below. +The end-to-end benchmarking pipeline is disabled by default when compiling a node. If you want to run benchmarks, you +need to enable it by compiling with a Rust feature flag `runtime-benchmarks`. More details about this below. ### Weight -Substrate represents computational resources using a generic unit of measurement called "Weight". It -defines 10^12 Weight as 1 second of computation on the physical machine used for benchmarking. This -means that the weight of a function may change based on the specific hardware used to benchmark the -runtime functions. +Substrate represents computational resources using a generic unit of measurement called "Weight". It defines 10^12 +Weight as 1 second of computation on the physical machine used for benchmarking. This means that the weight of a +function may change based on the specific hardware used to benchmark the runtime functions. -By modeling the expected weight of each runtime function, the blockchain is able to calculate how -many transactions or system level functions it will be able to execute within a certain period of -time. Often, the limiting factor for a blockchain is the fixed block production time for the -network. +By modeling the expected weight of each runtime function, the blockchain is able to calculate how many transactions or +system level functions it will be able to execute within a certain period of time. Often, the limiting factor for a +blockchain is the fixed block production time for the network. -Within FRAME, each dispatchable function must have a `#[weight]` annotation with a function that can -return the expected weight for the worst case scenario execution of that function given its inputs. -This benchmarking framework will result in a file that automatically generates those formulas for -you, which you can then use in your pallet. +Within FRAME, each dispatchable function must have a `#[weight]` annotation with a function that can return the expected +weight for the worst case scenario execution of that function given its inputs. This benchmarking framework will result +in a file that automatically generates those formulas for you, which you can then use in your pallet. ## Writing Benchmarks -Writing a runtime benchmark is much like writing a unit test for your pallet. It needs to be -carefully crafted to execute a certain logical path in your code. In tests you want to check for -various success and failure conditions, but with benchmarks you specifically look for the **most -computationally heavy** path, a.k.a the "worst case scenario". +Writing a runtime benchmark is much like writing a unit test for your pallet. It needs to be carefully crafted to +execute a certain logical path in your code. In tests you want to check for various success and failure conditions, but +with benchmarks you specifically look for the **most computationally heavy** path, a.k.a the "worst case scenario". -This means that if there are certain storage items or runtime state that may affect the complexity -of the function, for example triggering more iterations in a `for` loop, to get an accurate result, -you must set up your benchmark to trigger this. +This means that if there are certain storage items or runtime state that may affect the complexity of the function, for +example triggering more iterations in a `for` loop, to get an accurate result, you must set up your benchmark to trigger +this. -It may be that there are multiple paths your function can go down, and it is not clear which one is -the heaviest. In this case, you should just create a benchmark for each scenario! You may find that -there are paths in your code where complexity may become unbounded depending on user input. This may -be a hint that you should enforce sane boundaries for how a user can use your pallet. For example: -limiting the number of elements in a vector, limiting the number of iterations in a `for` loop, -etc... +It may be that there are multiple paths your function can go down, and it is not clear which one is the heaviest. In +this case, you should just create a benchmark for each scenario! You may find that there are paths in your code where +complexity may become unbounded depending on user input. This may be a hint that you should enforce sane boundaries for +how a user can use your pallet. For example: limiting the number of elements in a vector, limiting the number of +iterations in a `for` loop, etc... -Examples of end-to-end benchmarks can be found in the [pallets provided by Substrate](../), and the -specific details on how to use the `benchmarks!` macro can be found in [its -documentation](./src/lib.rs). +Examples of end-to-end benchmarks can be found in the [pallets provided by Substrate](../), and the specific details on +how to use the `benchmarks!` macro can be found in [its documentation](./src/lib.rs). ## Testing Benchmarks -You can test your benchmarks using the same test runtime that you created for your pallet's unit -tests. By creating your benchmarks in the `benchmarks!` macro, it automatically generates test -functions for you: +You can test your benchmarks using the same test runtime that you created for your pallet's unit tests. By creating your +benchmarks in the `benchmarks!` macro, it automatically generates test functions for you: ```rust fn test_benchmark_[benchmark_name]::() -> Result<(), &'static str> @@ -101,19 +88,18 @@ fn test_benchmark_[benchmark_name]::() -> Result<(), &'static str> Simply add these functions to a unit test and ensure that the result of the function is `Ok(())`. -> **Note:** If your test runtime and production runtime have different configurations, you may get -different results when testing your benchmark and actually running it. +> **Note:** If your test runtime and production runtime have different configurations, you may get different results +when testing your benchmark and actually running it. -In general, benchmarks returning `Ok(())` is all you need to check for since it signals the executed -extrinsic has completed successfully. However, you can optionally include a `verify` block with your -benchmark, which can additionally verify any final conditions, such as the final state of your -runtime. +In general, benchmarks returning `Ok(())` is all you need to check for since it signals the executed extrinsic has +completed successfully. However, you can optionally include a `verify` block with your benchmark, which can additionally +verify any final conditions, such as the final state of your runtime. These additional `verify` blocks will not affect the results of your final benchmarking process. -To run the tests, you need to enable the `runtime-benchmarks` feature flag. This may also mean you -need to move into your node's binary folder. For example, with the Substrate repository, this is how -you would test the Balances pallet's benchmarks: +To run the tests, you need to enable the `runtime-benchmarks` feature flag. This may also mean you need to move into +your node's binary folder. For example, with the Substrate repository, this is how you would test the Balances pallet's +benchmarks: ```bash cargo test -p pallet-balances --features runtime-benchmarks @@ -123,19 +109,20 @@ cargo test -p pallet-balances --features runtime-benchmarks > ``` > error: --features is not allowed in the root of a virtual workspace` > ``` -> To solve this, navigate to the folder of the node (`cd bin/node/cli`) or pallet (`cd frame/pallet`) and run the command there. +> To solve this, navigate to the folder of the node (`cd bin/node/cli`) or pallet (`cd frame/pallet`) and run the +> command there. -This will instance each linear component with different values. The number of values per component is set to six and can be changed with the `VALUES_PER_COMPONENT` environment variable. +This will instance each linear component with different values. The number of values per component is set to six and can +be changed with the `VALUES_PER_COMPONENT` environment variable. ## Adding Benchmarks -The benchmarks included with each pallet are not automatically added to your node. To actually -execute these benchmarks, you need to implement the `frame_benchmarking::Benchmark` trait. You can -see an example of how to do this in the [included Substrate -node](../../bin/node/runtime/src/lib.rs). +The benchmarks included with each pallet are not automatically added to your node. To actually execute these benchmarks, +you need to implement the `frame_benchmarking::Benchmark` trait. You can see an example of how to do this in the +[included Substrate node](../../bin/node/runtime/src/lib.rs). -Assuming there are already some benchmarks set up on your node, you just need to add another -instance of the `add_benchmark!` macro: +Assuming there are already some benchmarks set up on your node, you just need to add another instance of the +`add_benchmark!` macro: ```rust /// configuration for running benchmarks @@ -147,22 +134,20 @@ add_benchmark!(params, batches, pallet_balances, Balances); /// the `struct` created for your pallet by `construct_runtime!` ``` -Once you have done this, you will need to compile your node binary with the `runtime-benchmarks` -feature flag: +Once you have done this, you will need to compile your node binary with the `runtime-benchmarks` feature flag: ```bash cd bin/node/cli cargo build --profile=production --features runtime-benchmarks ``` -The production profile applies various compiler optimizations. -These optimizations slow down the compilation process *a lot*. +The production profile applies various compiler optimizations. +These optimizations slow down the compilation process *a lot*. If you are just testing things out and don't need final numbers, don't include `--profile=production`. ## Running Benchmarks -Finally, once you have a node binary with benchmarks enabled, you need to execute your various -benchmarks. +Finally, once you have a node binary with benchmarks enabled, you need to execute your various benchmarks. You can get a list of the available benchmarks by running: @@ -183,24 +168,24 @@ Then you can run a benchmark like so: --output \ # Output benchmark results into a folder or file ``` -This will output a file `pallet_name.rs` which implements the `WeightInfo` trait you should include -in your pallet. Double colons `::` will be replaced with a `_` in the output name if you specify a directory. Each blockchain should generate their own benchmark file with their custom -implementation of the `WeightInfo` trait. This means that you will be able to use these modular -Substrate pallets while still keeping your network safe for your specific configuration and +This will output a file `pallet_name.rs` which implements the `WeightInfo` trait you should include in your pallet. +Double colons `::` will be replaced with a `_` in the output name if you specify a directory. Each blockchain should +generate their own benchmark file with their custom implementation of the `WeightInfo` trait. This means that you will +be able to use these modular Substrate pallets while still keeping your network safe for your specific configuration and requirements. -The benchmarking CLI uses a Handlebars template to format the final output file. You can optionally -pass the flag `--template` pointing to a custom template that can be used instead. Within the -template, you have access to all the data provided by the `TemplateData` struct in the -[benchmarking CLI writer](../../utils/frame/benchmarking-cli/src/writer.rs). You can find the -default template used [here](../../utils/frame/benchmarking-cli/src/template.hbs). +The benchmarking CLI uses a Handlebars template to format the final output file. You can optionally pass the flag +`--template` pointing to a custom template that can be used instead. Within the template, you have access to all the +data provided by the `TemplateData` struct in the [benchmarking CLI +writer](../../utils/frame/benchmarking-cli/src/writer.rs). You can find the default template used +[here](../../utils/frame/benchmarking-cli/src/template.hbs). There are some custom Handlebars helpers included with our output generation: -* `underscore`: Add an underscore to every 3rd character from the right of a string. Primarily to be -used for delimiting large numbers. -* `join`: Join an array of strings into a space-separated string for the template. Primarily to be -used for joining all the arguments passed to the CLI. +* `underscore`: Add an underscore to every 3rd character from the right of a string. Primarily to be used for delimiting +large numbers. +* `join`: Join an array of strings into a space-separated string for the template. Primarily to be used for joining all +the arguments passed to the CLI. To get a full list of available options when running benchmarks, run: diff --git a/substrate/frame/child-bounties/README.md b/substrate/frame/child-bounties/README.md index 695b6616b175..cf62698dcaf9 100644 --- a/substrate/frame/child-bounties/README.md +++ b/substrate/frame/child-bounties/README.md @@ -8,7 +8,7 @@ With child bounties, a large bounty proposal can be divided into smaller chunks, for parallel execution, and for efficient governance and tracking of spent funds. A child bounty is a smaller piece of work, extracted from a parent bounty. A curator is assigned after the child bounty is created by the parent bounty curator, -to be delegated with the responsibility of assigning a payout address once +to be delegated with the responsibility of assigning a payout address once the specified set of tasks is completed. ## Interface diff --git a/substrate/frame/contracts/CHANGELOG.md b/substrate/frame/contracts/CHANGELOG.md index dcb9d6d4d2b2..aca94e5b1491 100644 --- a/substrate/frame/contracts/CHANGELOG.md +++ b/substrate/frame/contracts/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -The semantic versioning guarantees cover the interface to the substrate runtime which +The semantic versioning guarantees cover the interface to the Substrate runtime which includes this pallet as a dependency. This module will also add storage migrations whenever changes require it. Stability with regard to offchain tooling is explicitly excluded from this guarantee: For example adding a new field to an in-storage data structure will require diff --git a/substrate/frame/contracts/README.md b/substrate/frame/contracts/README.md index aeb30cef32fc..0b6548cf6414 100644 --- a/substrate/frame/contracts/README.md +++ b/substrate/frame/contracts/README.md @@ -9,66 +9,68 @@ The Contracts module provides functionality for the runtime to deploy and execut ## Overview -This module extends accounts based on the [`frame_support::traits::fungible`] traits to have smart-contract functionality. It can -be used with other modules that implement accounts based on [`frame_support::traits::fungible`]. These "smart-contract accounts" -have the ability to instantiate smart-contracts and make calls to other contract and non-contract accounts. +This module extends accounts based on the [`frame_support::traits::fungible`] traits to have smart-contract +functionality. It can be used with other modules that implement accounts based on [`frame_support::traits::fungible`]. +These "smart-contract accounts" have the ability to instantiate smart-contracts and make calls to other contract and +non-contract accounts. -The smart-contract code is stored once, and later retrievable via its `code_hash`. -This means that multiple smart-contracts can be instantiated from the same `code`, without replicating -the code each time. +The smart-contract code is stored once, and later retrievable via its `code_hash`. This means that multiple +smart-contracts can be instantiated from the same `code`, without replicating the code each time. -When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. -This call can alter the storage entries of the smart-contract account, instantiate new smart-contracts, -or call other smart-contracts. +When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. This call can +alter the storage entries of the smart-contract account, instantiate new smart-contracts, or call other smart-contracts. -Finally, when an account is reaped, its associated code and storage of the smart-contract account -will also be deleted. +Finally, when an account is reaped, its associated code and storage of the smart-contract account will also be deleted. ### Weight -Senders must specify a [`Weight`](https://paritytech.github.io/substrate/master/sp_weights/struct.Weight.html) limit with every call, as all instructions invoked by the smart-contract require weight. -Unused weight is refunded after the call, regardless of the execution outcome. +Senders must specify a [`Weight`](https://paritytech.github.io/substrate/master/sp_weights/struct.Weight.html) limit +with every call, as all instructions invoked by the smart-contract require weight. Unused weight is refunded after the +call, regardless of the execution outcome. -If the weight limit is reached, then all calls and state changes (including balance transfers) are only -reverted at the current call's contract level. For example, if contract A calls B and B runs out of weight mid-call, -then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state -changes still persist. +If the weight limit is reached, then all calls and state changes (including balance transfers) are only reverted at the +current call's contract level. For example, if contract A calls B and B runs out of weight mid-call, then all of B's +calls are reverted. Assuming correct error handling by contract A, A's other calls and state changes still persist. One `ref_time` `Weight` is defined as one picosecond of execution time on the runtime's reference machine. ### Revert Behaviour -Contract call failures are not cascading. When failures occur in a sub-call, they do not "bubble up", -and the call will only revert at the specific contract level. For example, if contract A calls contract B, and B -fails, A can decide how to handle that failure, either proceeding or reverting A's changes. +Contract call failures are not cascading. When failures occur in a sub-call, they do not "bubble up", and the call will +only revert at the specific contract level. For example, if contract A calls contract B, and B fails, A can decide how +to handle that failure, either proceeding or reverting A's changes. ### Off-chain Execution -In general, a contract execution needs to be deterministic so that all nodes come to the same -conclusion when executing it. To that end we disallow any instructions that could cause -indeterminism. Most notable are any floating point arithmetic. That said, sometimes contracts -are executed off-chain and hence are not subject to consensus. If code is only executed by a -single node and implicitly trusted by other actors is such a case. Trusted execution environments -come to mind. To that end we allow the execution of indeterminstic code for off-chain usages -with the following constraints: - -1. No contract can ever be instantiated from an indeterministic code. The only way to execute -the code is to use a delegate call from a deterministic contract. -2. The code that wants to use this feature needs to depend on `pallet-contracts` and use [`bare_call()`](https://paritytech.github.io/substrate/master/pallet_contracts/pallet/struct.Pallet.html#method.bare_call) +In general, a contract execution needs to be deterministic so that all nodes come to the same conclusion when executing +it. To that end we disallow any instructions that could cause indeterminism. Most notable are any floating point +arithmetic. That said, sometimes contracts are executed off-chain and hence are not subject to consensus. If code is +only executed by a single node and implicitly trusted by other actors is such a case. Trusted execution environments +come to mind. To that end we allow the execution of indeterminstic code for off-chain usages with the following +constraints: + +1. No contract can ever be instantiated from an indeterministic code. The only way to execute the code is to use a +delegate call from a deterministic contract. +2. The code that wants to use this feature needs to depend on `pallet-contracts` and use +[`bare_call()`](https://paritytech.github.io/substrate/master/pallet_contracts/pallet/struct.Pallet.html#method.bare_call) directly. This makes sure that by default `pallet-contracts` does not expose any indeterminism. #### How to use -An indeterministic code can be deployed on-chain by passing `Determinism::Relaxed` -to [`upload_code()`](https://paritytech.github.io/substrate/master/pallet_contracts/pallet/struct.Pallet.html#method.upload_code). A deterministic contract can then delegate call into it if and only if it -is ran by using [`bare_call()`](https://paritytech.github.io/substrate/master/pallet_contracts/pallet/struct.Pallet.html#method.bare_call) and passing [`Determinism::Relaxed`](https://paritytech.github.io/substrate/master/pallet_contracts/enum.Determinism.html#variant.Relaxed) to it. **Never use -this argument when the contract is called from an on-chain transaction.** +An indeterministic code can be deployed on-chain by passing `Determinism::Relaxed` to +[`upload_code()`](https://paritytech.github.io/substrate/master/pallet_contracts/pallet/struct.Pallet.html#method.upload_code). +A deterministic contract can then delegate call into it if and only if it is ran by using +[`bare_call()`](https://paritytech.github.io/substrate/master/pallet_contracts/pallet/struct.Pallet.html#method.bare_call) +and passing +[`Determinism::Relaxed`](https://paritytech.github.io/substrate/master/pallet_contracts/enum.Determinism.html#variant.Relaxed) +to it. **Never use this argument when the contract is called from an on-chain transaction.** ## Interface ### Dispatchable functions -Those are documented in the [reference documentation](https://paritytech.github.io/substrate/master/pallet_contracts/index.html#dispatchable-functions). +Those are documented in the [reference +documentation](https://paritytech.github.io/substrate/master/pallet_contracts/index.html#dispatchable-functions). ### Interface exposed to contracts @@ -99,43 +101,43 @@ The documentation of all importable functions can be found ## Usage -This module executes WebAssembly smart contracts. These can potentially be written in any language -that compiles to Wasm. However, using a language that specifically targets this module -will make things a lot easier. One such language is [`ink!`](https://use.ink). It enables -writing WebAssembly-based smart-contracts in the Rust programming language. +This module executes WebAssembly smart contracts. These can potentially be written in any language that compiles to +Wasm. However, using a language that specifically targets this module will make things a lot easier. One such language +is [`ink!`](https://use.ink). It enables writing WebAssembly-based smart-contracts in the Rust programming language. ## Debugging -Contracts can emit messages to the client when called as RPC through the [`debug_message`](https://paritytech.github.io/substrate/master/pallet_contracts/api_doc/trait.Current.html#tymethod.debug_message) +Contracts can emit messages to the client when called as RPC through the +[`debug_message`](https://paritytech.github.io/substrate/master/pallet_contracts/api_doc/trait.Current.html#tymethod.debug_message) API. This is exposed in [ink!](https://use.ink) via [`ink_env::debug_message()`](https://paritytech.github.io/ink/ink_env/fn.debug_message.html). -Those messages are gathered into an internal buffer and sent to the RPC client. -It is up the the individual client if and how those messages are presented to the user. +Those messages are gathered into an internal buffer and sent to the RPC client. It is up the the individual client if +and how those messages are presented to the user. -This buffer is also printed as a debug message. In order to see these messages on the node -console the log level for the `runtime::contracts` target needs to be raised to at least -the `debug` level. However, those messages are easy to overlook because of the noise generated -by block production. A good starting point for observing them on the console is using this -command line in the root directory of the substrate repository: +This buffer is also printed as a debug message. In order to see these messages on the node console the log level for the +`runtime::contracts` target needs to be raised to at least the `debug` level. However, those messages are easy to +overlook because of the noise generated by block production. A good starting point for observing them on the console is +using this command line in the root directory of the Substrate repository: ```bash cargo run --release -- --dev -lerror,runtime::contracts=debug ``` -This raises the log level of `runtime::contracts` to `debug` and all other targets -to `error` in order to prevent them from spamming the console. +This raises the log level of `runtime::contracts` to `debug` and all other targets to `error` in order to prevent them +from spamming the console. -`--dev`: Use a dev chain spec -`--tmp`: Use temporary storage for chain data (the chain state is deleted on exit) +`--dev`: Use a dev chain spec `--tmp`: Use temporary storage for chain data (the chain state is deleted on exit) ## Host function tracing -For contract authors, it can be a helpful debugging tool to see which host functions are called, with which arguments, and what the result was. +For contract authors, it can be a helpful debugging tool to see which host functions are called, with which arguments, +and what the result was. -In order to see these messages on the node console, the log level for the `runtime::contracts::strace` target needs to be raised to the `trace` level. +In order to see these messages on the node console, the log level for the `runtime::contracts::strace` target needs to +be raised to the `trace` level. -Example: +Example: ```bash cargo run --release -- --dev -lerror,runtime::contracts::strace=trace,runtime::contracts=debug @@ -143,18 +145,16 @@ cargo run --release -- --dev -lerror,runtime::contracts::strace=trace,runtime::c ## Unstable Interfaces -Driven by the desire to have an iterative approach in developing new contract interfaces -this pallet contains the concept of an unstable interface. Akin to the rust nightly compiler -it allows us to add new interfaces but mark them as unstable so that contract languages can -experiment with them and give feedback before we stabilize those. +Driven by the desire to have an iterative approach in developing new contract interfaces this pallet contains the +concept of an unstable interface. Akin to the rust nightly compiler it allows us to add new interfaces but mark them as +unstable so that contract languages can experiment with them and give feedback before we stabilize those. In order to access interfaces marked as `#[unstable]` in [`runtime.rs`](src/wasm/runtime.rs) one need to set -`pallet_contracts::Config::UnsafeUnstableInterface` to `ConstU32`. **It should be obvious -that any production runtime should never be compiled with this feature: In addition to be -subject to change or removal those interfaces might not have proper weights associated with -them and are therefore considered unsafe**. +`pallet_contracts::Config::UnsafeUnstableInterface` to `ConstU32`. **It should be obvious that any production +runtime should never be compiled with this feature: In addition to be subject to change or removal those interfaces +might not have proper weights associated with them and are therefore considered unsafe**. -New interfaces are generally added as unstable and might go through several iterations -before they are promoted to a stable interface. +New interfaces are generally added as unstable and might go through several iterations before they are promoted to a +stable interface. License: Apache-2.0 diff --git a/substrate/frame/contracts/benchmarks/README.md b/substrate/frame/contracts/benchmarks/README.md index a621dd65d593..e4441d6bab2c 100644 --- a/substrate/frame/contracts/benchmarks/README.md +++ b/substrate/frame/contracts/benchmarks/README.md @@ -1,9 +1,8 @@ # Benchmarks -This directory contains real world ([ink!](https://use.ink), [solang](https://github.com/hyperledger/solang)) contracts which are used in macro benchmarks. -Those benchmarks are not used to determine weights but rather to compare different contract -languages and execution engines with larger wasm modules. - -Files in this directory are used by `#[extra]` benchmarks in `src/benchmarking`. The json -files are for informational purposes only and are not consumed by the benchmarks. +This directory contains real world ([ink!](https://use.ink), [solang](https://github.com/hyperledger/solang)) contracts +which are used in macro benchmarks. Those benchmarks are not used to determine weights but rather to compare different +contract languages and execution engines with larger wasm modules. +Files in this directory are used by `#[extra]` benchmarks in `src/benchmarking`. The json files are for informational +purposes only and are not consumed by the benchmarks. diff --git a/substrate/frame/contracts/primitives/README.md b/substrate/frame/contracts/primitives/README.md index 12718cd86425..c84cfbfe1a87 100644 --- a/substrate/frame/contracts/primitives/README.md +++ b/substrate/frame/contracts/primitives/README.md @@ -1,3 +1,3 @@ A crate that hosts a common definitions that are relevant for the pallet-contracts. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/core-fellowship/README.md b/substrate/frame/core-fellowship/README.md index 3c9b1f63e089..97718eef7a32 100644 --- a/substrate/frame/core-fellowship/README.md +++ b/substrate/frame/core-fellowship/README.md @@ -1,3 +1,3 @@ # Core Fellowship -Logic specific to the core Polkadot Fellowship. \ No newline at end of file +Logic specific to the core Polkadot Fellowship. diff --git a/substrate/frame/elections-phragmen/README.md b/substrate/frame/elections-phragmen/README.md index 26b3f260da56..f5ed609f2129 100644 --- a/substrate/frame/elections-phragmen/README.md +++ b/substrate/frame/elections-phragmen/README.md @@ -1,64 +1,58 @@ -# Phragmén Election Module. +# Phragmén Election Module An election module based on sequential phragmen. -### Term and Round - -The election happens in _rounds_: every `N` blocks, all previous members are retired and a new -set is elected (which may or may not have an intersection with the previous set). Each round -lasts for some number of blocks defined by `TermDuration` storage item. The words _term_ and -_round_ can be used interchangeably in this context. - -`TermDuration` might change during a round. This can shorten or extend the length of the round. -The next election round's block number is never stored but rather always checked on the fly. -Based on the current block number and `TermDuration`, the condition `BlockNumber % TermDuration -== 0` being satisfied will always trigger a new election round. - -### Voting - -Voters can vote for any set of the candidates by providing a list of account ids. Invalid votes -(voting for non-candidates) are ignored during election. Yet, a voter _might_ vote for a future -candidate. Voters reserve a bond as they vote. Each vote defines a `value`. This amount is -locked from the account of the voter and indicates the weight of the vote. Voters can update -their votes at any time by calling `vote()` again. This keeps the bond untouched but can -optionally change the locked `value`. After a round, votes are kept and might still be valid for -further rounds. A voter is responsible for calling `remove_voter` once they are done to have -their bond back and remove the lock. - -Voters also report other voters as being defunct to earn their bond. A voter is defunct once all -of the candidates that they have voted for are neither a valid candidate anymore nor a member. -Upon reporting, if the target voter is actually defunct, the reporter will be rewarded by the -voting bond of the target. The target will lose their bond and get removed. If the target is not -defunct, the reporter is slashed and removed. To prevent being reported, voters should manually -submit a `remove_voter()` as soon as they are in the defunct state. - -### Candidacy and Members - -Candidates also reserve a bond as they submit candidacy. A candidate cannot take their candidacy -back. A candidate can end up in one of the below situations: - - **Winner**: A winner is kept as a _member_. They must still have a bond in reserve and they - are automatically counted as a candidate for the next election. - - **Runner-up**: Runners-up are the best candidates immediately after the winners. The number - of runners_up to keep is configurable. Runners-up are used, in order that they are elected, - as replacements when a candidate is kicked by `[remove_member]`, or when an active member - renounces their candidacy. Runners are automatically counted as a candidate for the next - election. - - **Loser**: Any of the candidate who are not a winner are left as losers. A loser might be an - _outgoing member or runner_, meaning that they are an active member who failed to keep their - spot. An outgoing will always lose their bond. - -##### Renouncing candidacy. - -All candidates, elected or not, can renounce their candidacy. A call to [`Module::renounce_candidacy`] -will always cause the candidacy bond to be refunded. - -Note that with the members being the default candidates for the next round and votes persisting -in storage, the election system is entirely stable given no further input. This means that if -the system has a particular set of candidates `C` and voters `V` that lead to a set of members -`M` being elected, as long as `V` and `C` don't remove their candidacy and votes, `M` will keep -being re-elected at the end of each round. - -### Module Information +## Term and Round + +The election happens in _rounds_: every `N` blocks, all previous members are retired and a new set is elected (which may +or may not have an intersection with the previous set). Each round lasts for some number of blocks defined by +`TermDuration` storage item. The words _term_ and _round_ can be used interchangeably in this context. + +`TermDuration` might change during a round. This can shorten or extend the length of the round. The next election +round's block number is never stored but rather always checked on the fly. Based on the current block number and +`TermDuration`, the condition `BlockNumber % TermDuration == 0` being satisfied will always trigger a new election +round. + +## Voting + +Voters can vote for any set of the candidates by providing a list of account ids. Invalid votes (voting for +non-candidates) are ignored during election. Yet, a voter _might_ vote for a future candidate. Voters reserve a bond as +they vote. Each vote defines a `value`. This amount is locked from the account of the voter and indicates the weight of +the vote. Voters can update their votes at any time by calling `vote()` again. This keeps the bond untouched but can +optionally change the locked `value`. After a round, votes are kept and might still be valid for further rounds. A voter +is responsible for calling `remove_voter` once they are done to have their bond back and remove the lock. + +Voters also report other voters as being defunct to earn their bond. A voter is defunct once all of the candidates that +they have voted for are neither a valid candidate anymore nor a member. Upon reporting, if the target voter is actually +defunct, the reporter will be rewarded by the voting bond of the target. The target will lose their bond and get +removed. If the target is not defunct, the reporter is slashed and removed. To prevent being reported, voters should +manually submit a `remove_voter()` as soon as they are in the defunct state. + +## Candidacy and Members + +Candidates also reserve a bond as they submit candidacy. A candidate cannot take their candidacy back. A candidate can +end up in one of the below situations: + - **Winner**: A winner is kept as a _member_. They must still have a bond in reserve and they are automatically + counted as a candidate for the next election. + - **Runner-up**: Runners-up are the best candidates immediately after the winners. The number of runners_up to keep is + configurable. Runners-up are used, in order that they are elected, as replacements when a candidate is kicked by + `[remove_member]`, or when an active member renounces their candidacy. Runners are automatically counted as a + candidate for the next election. + - **Loser**: Any of the candidate who are not a winner are left as losers. A loser might be an _outgoing member or + runner_, meaning that they are an active member who failed to keep their spot. An outgoing will always lose their + bond. + +### Renouncing candidacy + +All candidates, elected or not, can renounce their candidacy. A call to [`Module::renounce_candidacy`] will always cause +the candidacy bond to be refunded. + +Note that with the members being the default candidates for the next round and votes persisting in storage, the election +system is entirely stable given no further input. This means that if the system has a particular set of candidates `C` +and voters `V` that lead to a set of members `M` being elected, as long as `V` and `C` don't remove their candidacy and +votes, `M` will keep being re-elected at the end of each round. + +## Module Information - [`election_sp_phragmen::Config`](https://docs.rs/pallet-elections-phragmen/latest/pallet_elections_phragmen/trait.Config.html) - [`Call`](https://docs.rs/pallet-elections-phragmen/latest/pallet_elections_phragmen/enum.Call.html) diff --git a/substrate/frame/examples/basic/README.md b/substrate/frame/examples/basic/README.md index 2af50573f807..be787d1b6ecc 100644 --- a/substrate/frame/examples/basic/README.md +++ b/substrate/frame/examples/basic/README.md @@ -9,7 +9,7 @@ Run `cargo doc --package pallet-example-basic --open` to view this pallet's docu **This pallet serves as an example and is not meant to be used in production.** -### Documentation Guidelines: +## Documentation Guidelines diff --git a/substrate/frame/examples/split/README.md b/substrate/frame/examples/split/README.md index 413ce9b913cb..9c4d5443ca06 100644 --- a/substrate/frame/examples/split/README.md +++ b/substrate/frame/examples/split/README.md @@ -3,7 +3,7 @@ A simple example of a FRAME pallet demonstrating the ability to split sections across multiple files. -Note that this is purely experimental at this point. +Note that this is purely experimental at this point. Run `cargo doc --package pallet-example-split --open` to view this pallet's documentation. diff --git a/substrate/frame/executive/README.md b/substrate/frame/executive/README.md index c14c3912b082..96a412a4537a 100644 --- a/substrate/frame/executive/README.md +++ b/substrate/frame/executive/README.md @@ -1,13 +1,13 @@ # Executive Module -The Executive module acts as the orchestration layer for the runtime. It dispatches incoming -extrinsic calls to the respective modules in the runtime. +The Executive module acts as the orchestration layer for the runtime. It dispatches incoming extrinsic calls to the +respective modules in the runtime. ## Overview -The executive module is not a typical pallet providing functionality around a specific feature. -It is a cross-cutting framework component for the FRAME. It works in conjunction with the -[FRAME System module](https://docs.rs/frame-system/latest/frame_system/) to perform these cross-cutting functions. +The executive module is not a typical pallet providing functionality around a specific feature. It is a cross-cutting +framework component for the FRAME. It works in conjunction with the [FRAME System +module](https://docs.rs/frame-system/latest/frame_system/) to perform these cross-cutting functions. The Executive module provides functions to: @@ -26,7 +26,8 @@ The Executive module provides the following implementations: ## Usage -The default Substrate node template declares the [`Executive`](https://docs.rs/frame-executive/latest/frame_executive/struct.Executive.html) type in its library. +The default Substrate node template declares the +[`Executive`](https://docs.rs/frame-executive/latest/frame_executive/struct.Executive.html) type in its library. ### Example @@ -46,9 +47,8 @@ pub type Executive = executive::Executive< ### Custom `OnRuntimeUpgrade` logic -You can add custom logic that should be called in your runtime on a runtime upgrade. This is -done by setting an optional generic parameter. The custom logic will be called before -the on runtime upgrade logic of all modules is called. +You can add custom logic that should be called in your runtime on a runtime upgrade. This is done by setting an optional +generic parameter. The custom logic will be called before the on runtime upgrade logic of all modules is called. ```rust # diff --git a/substrate/frame/glutton/README.md b/substrate/frame/glutton/README.md index 8ad4f7917182..89dbe26ec7a9 100644 --- a/substrate/frame/glutton/README.md +++ b/substrate/frame/glutton/README.md @@ -4,6 +4,9 @@ # Glutton Pallet -The `Glutton` pallet gets the name from its property to consume vast amounts of resources. It can be used to push para-chains and their relay-chains to the limits. This is good for testing out theoretical limits in a practical way. +The `Glutton` pallet gets the name from its property to consume vast amounts of resources. It can be used to push +para-chains and their relay-chains to the limits. This is good for testing out theoretical limits in a practical way. -The `Glutton` can be set to consume a fraction of the available unused weight of a chain. It accomplishes this by utilizing the `on_idle` hook and consuming a specific ration of the remaining weight. The rations can be set via `set_compute` and `set_storage`. Initially the `Glutton` needs to be initialized once with `initialize_pallet`. +The `Glutton` can be set to consume a fraction of the available unused weight of a chain. It accomplishes this by +utilizing the `on_idle` hook and consuming a specific ration of the remaining weight. The rations can be set via +`set_compute` and `set_storage`. Initially the `Glutton` needs to be initialized once with `initialize_pallet`. diff --git a/substrate/frame/grandpa/README.md b/substrate/frame/grandpa/README.md index 84b181a8b31e..5978931c5a85 100644 --- a/substrate/frame/grandpa/README.md +++ b/substrate/frame/grandpa/README.md @@ -9,4 +9,4 @@ finality notifications. For full integration with GRANDPA, the `GrandpaApi` should be implemented. The necessary items are re-exported via the `fg_primitives` crate. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/identity/README.md b/substrate/frame/identity/README.md index a67c259e2537..0203656eff46 100644 --- a/substrate/frame/identity/README.md +++ b/substrate/frame/identity/README.md @@ -28,27 +28,27 @@ no state-bloat attack is viable. ### Dispatchable Functions #### For general users -* `set_identity` - Set the associated identity of an account; a small deposit is reserved if not +- `set_identity` - Set the associated identity of an account; a small deposit is reserved if not already taken. -* `clear_identity` - Remove an account's associated identity; the deposit is returned. -* `request_judgement` - Request a judgement from a registrar, paying a fee. -* `cancel_request` - Cancel the previous request for a judgement. +- `clear_identity` - Remove an account's associated identity; the deposit is returned. +- `request_judgement` - Request a judgement from a registrar, paying a fee. +- `cancel_request` - Cancel the previous request for a judgement. #### For general users with sub-identities -* `set_subs` - Set the sub-accounts of an identity. -* `add_sub` - Add a sub-identity to an identity. -* `remove_sub` - Remove a sub-identity of an identity. -* `rename_sub` - Rename a sub-identity of an identity. -* `quit_sub` - Remove a sub-identity of an identity (called by the sub-identity). +- `set_subs` - Set the sub-accounts of an identity. +- `add_sub` - Add a sub-identity to an identity. +- `remove_sub` - Remove a sub-identity of an identity. +- `rename_sub` - Rename a sub-identity of an identity. +- `quit_sub` - Remove a sub-identity of an identity (called by the sub-identity). #### For registrars -* `set_fee` - Set the fee required to be paid for a judgement to be given by the registrar. -* `set_fields` - Set the fields that a registrar cares about in their judgements. -* `provide_judgement` - Provide a judgement to an identity. +- `set_fee` - Set the fee required to be paid for a judgement to be given by the registrar. +- `set_fields` - Set the fields that a registrar cares about in their judgements. +- `provide_judgement` - Provide a judgement to an identity. #### For super-users -* `add_registrar` - Add a new registrar to the system. -* `kill_identity` - Forcibly remove the associated identity; the deposit is lost. +- `add_registrar` - Add a new registrar to the system. +- `kill_identity` - Forcibly remove the associated identity; the deposit is lost. [`Call`]: ./enum.Call.html [`Config`]: ./trait.Config.html diff --git a/substrate/frame/indices/README.md b/substrate/frame/indices/README.md index 243392780db2..ba4b9679a294 100644 --- a/substrate/frame/indices/README.md +++ b/substrate/frame/indices/README.md @@ -1,4 +1,4 @@ An index is a short form of an address. This module handles allocation of indices for a newly created accounts. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/insecure-randomness-collective-flip/README.md b/substrate/frame/insecure-randomness-collective-flip/README.md index ef02e4b5c844..4f02782fa659 100644 --- a/substrate/frame/insecure-randomness-collective-flip/README.md +++ b/substrate/frame/insecure-randomness-collective-flip/README.md @@ -1,25 +1,27 @@ # DO NOT USE IN PRODUCTION -The produced values do not fulfill the cryptographic requirements for random numbers. Should not be used for high-stake production use-cases. +The produced values do not fulfill the cryptographic requirements for random numbers. Should not be used for high-stake +production use-cases. # Randomness Module -The Randomness Collective Flip module provides a [`random`](https://docs.rs/pallet-insecure-randomness-collective-flip/latest/pallet_insecure_randomness_collective_flip/struct.Module.html#method.random) -function that generates low-influence random values based on the block hashes from the previous -`81` blocks. Low-influence randomness can be useful when defending against relatively weak -adversaries. Using this pallet as a randomness source is advisable primarily in low-security -situations like testing. +The Randomness Collective Flip module provides a +[`random`](https://docs.rs/pallet-insecure-randomness-collective-flip/latest/pallet_insecure_randomness_collective_flip/struct.Module.html#method.random) +function that generates low-influence random values based on the block hashes from the previous `81` blocks. +Low-influence randomness can be useful when defending against relatively weak adversaries. Using this pallet as a +randomness source is advisable primarily in low-security situations like testing. ## Public Functions -See the [`Module`](https://docs.rs/pallet-insecure-randomness-collective-flip/latest/pallet_insecure_randomness_collective_flip/struct.Module.html) struct for details of publicly available functions. +See the +[`Module`](https://docs.rs/pallet-insecure-randomness-collective-flip/latest/pallet_insecure_randomness_collective_flip/struct.Module.html) +struct for details of publicly available functions. ## Usage ### Prerequisites -Import the Randomness Collective Flip module and derive your module's configuration trait from -the system trait. +Import the Randomness Collective Flip module and derive your module's configuration trait from the system trait. ### Example - Get random seed for the current block diff --git a/substrate/frame/multisig/README.md b/substrate/frame/multisig/README.md index 5f320377d345..e9095198585b 100644 --- a/substrate/frame/multisig/README.md +++ b/substrate/frame/multisig/README.md @@ -18,10 +18,10 @@ not available or desired. ### Dispatchable Functions -* `as_multi` - Approve and if possible dispatch a call from a composite origin formed from a +- `as_multi` - Approve and if possible dispatch a call from a composite origin formed from a number of signed origins. -* `approve_as_multi` - Approve a call from a composite origin. -* `cancel_as_multi` - Cancel a call from a composite origin. +- `approve_as_multi` - Approve a call from a composite origin. +- `cancel_as_multi` - Cancel a call from a composite origin. [`Call`]: ./enum.Call.html [`Config`]: ./trait.Config.html diff --git a/substrate/frame/nft-fractionalization/README.md b/substrate/frame/nft-fractionalization/README.md index 180eef22cc46..3f83ae9d150d 100644 --- a/substrate/frame/nft-fractionalization/README.md +++ b/substrate/frame/nft-fractionalization/README.md @@ -1,6 +1,8 @@ -### Lock NFT +# Lock NFT Lock an NFT from `pallet-nfts` and mint fungible assets from `pallet-assets`. -The NFT gets locked by putting a system-level attribute named `Locked`. This prevents the NFT from being transferred further. -The NFT becomes unlocked when the `Locked` attribute is removed. In order to unify the fungible asset and unlock the NFT, an account must hold the full issuance of the asset the NFT was fractionalised into. Holding less of the fungible asset will not allow the unlocking of the NFT. +The NFT gets locked by putting a system-level attribute named `Locked`. This prevents the NFT from being transferred +further. The NFT becomes unlocked when the `Locked` attribute is removed. In order to unify the fungible asset and +unlock the NFT, an account must hold the full issuance of the asset the NFT was fractionalised into. Holding less of the +fungible asset will not allow the unlocking of the NFT. diff --git a/substrate/frame/nfts/README.md b/substrate/frame/nfts/README.md index 7de4b9440e7f..93ccf2949852 100644 --- a/substrate/frame/nfts/README.md +++ b/substrate/frame/nfts/README.md @@ -13,9 +13,11 @@ The NFTs pallet provides functionality for non-fungible tokens' management, incl * Attributes Management * NFT Burning -To use it in your runtime, you need to implement [`nfts::Config`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/trait.Config.html). +To use it in your runtime, you need to implement +[`nfts::Config`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/trait.Config.html). -The supported dispatchable functions are documented in the [`nfts::Call`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/enum.Call.html) enum. +The supported dispatchable functions are documented in the +[`nfts::Call`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/enum.Call.html) enum. ### Terminology @@ -24,8 +26,9 @@ The supported dispatchable functions are documented in the [`nfts::Call`](https: * **NFT transfer:** The action of sending an item from one account to another. * **Atomic swap:** The action of exchanging items between accounts without needing a 3rd party service. * **NFT burning:** The destruction of an item. -* **Non-fungible token (NFT):** An item for which each unit has unique characteristics. There is exactly - one instance of such an item in existence and there is exactly one owning account (though that owning account could be a proxy account or multi-sig account). +* **Non-fungible token (NFT):** An item for which each unit has unique characteristics. There is exactly one instance of + such an item in existence and there is exactly one owning account (though that owning account could be a proxy account + or multi-sig account). * **Soul Bound NFT:** An item that is non-transferable from the account which it is minted into. ### Goals @@ -35,10 +38,8 @@ The NFTs pallet in Substrate is designed to make the following possible: * Allow accounts to permissionlessly create nft collections. * Allow a named (permissioned) account to mint and burn unique items within a collection. * Move items between accounts permissionlessly. -* Allow a named (permissioned) account to freeze and unfreeze items within a - collection or the entire collection. -* Allow the owner of an item to delegate the ability to transfer the item to some - named third-party. +* Allow a named (permissioned) account to freeze and unfreeze items within a collection or the entire collection. +* Allow the owner of an item to delegate the ability to transfer the item to some named third-party. * Allow third-parties to store information in an NFT _without_ owning it (Eg. save game state). ## Interface @@ -71,7 +72,8 @@ The NFTs pallet in Substrate is designed to make the following possible: * `clear_all_transfer_approvals`: Clears all transfer approvals set by calling the `approve_transfer`. * `lock_collection`: Prevent all items within a collection from being transferred (making them all `soul bound`). * `lock_item_properties`: Lock item's metadata or attributes. -* `transfer_ownership`: Alter the owner of a collection, moving all associated deposits. (Ownership of individual items will not be affected.) +* `transfer_ownership`: Alter the owner of a collection, moving all associated deposits. (Ownership of individual items + will not be affected.) * `set_team`: Alter the permissioned accounts of a collection. * `set_collection_max_supply`: Change the max supply of a collection. * `update_mint_settings`: Update the minting settings for collection. @@ -94,8 +96,8 @@ The NFTs pallet in Substrate is designed to make the following possible: * `force_collection_config`: Change collection's config. * `force_set_attribute`: Set an attribute. -Please refer to the [`Call`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/enum.Call.html) enum -and its associated variants for documentation on each function. +Please refer to the [`Call`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/enum.Call.html) enum and +its associated variants for documentation on each function. ## Related Modules diff --git a/substrate/frame/nicks/README.md b/substrate/frame/nicks/README.md index 768043ffb9bf..2b05f32d3344 100644 --- a/substrate/frame/nicks/README.md +++ b/substrate/frame/nicks/README.md @@ -14,10 +14,10 @@ have not been designed to be economically secure. Do not use this pallet as-is i ### Dispatchable Functions -* `set_name` - Set the associated name of an account; a small deposit is reserved if not already +- `set_name` - Set the associated name of an account; a small deposit is reserved if not already taken. -* `clear_name` - Remove an account's associated name; the deposit is returned. -* `kill_name` - Forcibly remove the associated name; the deposit is lost. +- `clear_name` - Remove an account's associated name; the deposit is returned. +- `kill_name` - Forcibly remove the associated name; the deposit is lost. [`Call`]: ./enum.Call.html [`Config`]: ./trait.Config.html diff --git a/substrate/frame/nis/README.md b/substrate/frame/nis/README.md index 0c3f0c383a16..032df7d01868 100644 --- a/substrate/frame/nis/README.md +++ b/substrate/frame/nis/README.md @@ -2,4 +2,4 @@ Provides a non-interactiove variant of staking. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/nomination-pools/runtime-api/README.md b/substrate/frame/nomination-pools/runtime-api/README.md index af90b31733b0..499af052a73e 100644 --- a/substrate/frame/nomination-pools/runtime-api/README.md +++ b/substrate/frame/nomination-pools/runtime-api/README.md @@ -1,3 +1,3 @@ Runtime API definition for nomination-pools pallet. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/offences/README.md b/substrate/frame/offences/README.md index 454c7effaf36..e7cf302fb8a0 100644 --- a/substrate/frame/offences/README.md +++ b/substrate/frame/offences/README.md @@ -2,4 +2,4 @@ Tracks reported offences -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/offences/benchmarking/README.md b/substrate/frame/offences/benchmarking/README.md index cbfe91d73a6a..95892a8f344f 100644 --- a/substrate/frame/offences/benchmarking/README.md +++ b/substrate/frame/offences/benchmarking/README.md @@ -1,3 +1,3 @@ Offences pallet benchmarking. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/ranked-collective/README.md b/substrate/frame/ranked-collective/README.md index b5fe65ef3492..e9624159d2fd 100644 --- a/substrate/frame/ranked-collective/README.md +++ b/substrate/frame/ranked-collective/README.md @@ -1,4 +1,4 @@ -# Ranked collective system. +# Ranked collective system This is a membership pallet providing a `Tally` implementation ready for use with polling systems such as the Referenda pallet. Members each have a rank, with zero being the lowest. diff --git a/substrate/frame/recovery/README.md b/substrate/frame/recovery/README.md index 31416c65c46a..7e2dd7a23619 100644 --- a/substrate/frame/recovery/README.md +++ b/substrate/frame/recovery/README.md @@ -16,11 +16,11 @@ friends are needed to give another account access to the recoverable account. The recovery process for each recoverable account can be configured by the account owner. They are able to choose: -* `friends` - The list of friends that the account owner trusts to protect the +- `friends` - The list of friends that the account owner trusts to protect the recovery process for their account. -* `threshold` - The number of friends that need to approve a recovery process for +- `threshold` - The number of friends that need to approve a recovery process for the account to be successfully recovered. -* `delay_period` - The minimum number of blocks after the beginning of the recovery +- `delay_period` - The minimum number of blocks after the beginning of the recovery process that need to pass before the account can be successfully recovered. There is a configurable deposit that all users need to pay to create a recovery @@ -84,20 +84,20 @@ It is important to note that this is a powerful pallet that can compromise the security of an account if used incorrectly. Some recommended practices for users of this pallet are: -* Configure a significant `delay_period` for your recovery process: As long as you +- Configure a significant `delay_period` for your recovery process: As long as you have access to your recoverable account, you need only check the blockchain once every `delay_period` blocks to ensure that no recovery attempt is successful against your account. Using off-chain notification systems can help with this, but ultimately, setting a large `delay_period` means that even the most skilled attacker will need to wait this long before they can access your account. -* Use a high threshold of approvals: Setting a value of 1 for the threshold means +- Use a high threshold of approvals: Setting a value of 1 for the threshold means that any of your friends would be able to recover your account. They would simply need to start a recovery process and approve their own process. Similarly, a threshold of 2 would mean that any 2 friends could work together to gain access to your account. The only way to prevent against these kinds of attacks is to choose a high threshold of approvals and select from a diverse friend group that would not be able to reasonably coordinate with one another. -* Reset your configuration over time: Since the entire deposit of creating a +- Reset your configuration over time: Since the entire deposit of creating a recovery configuration is returned to the user, the only cost of updating your recovery configuration is the transaction fees for the calls. Thus, it is strongly encouraged to regularly update your recovery configuration @@ -110,25 +110,25 @@ of this pallet are: #### For General Users -* `create_recovery` - Create a recovery configuration for your account and make it recoverable. -* `initiate_recovery` - Start the recovery process for a recoverable account. +- `create_recovery` - Create a recovery configuration for your account and make it recoverable. +- `initiate_recovery` - Start the recovery process for a recoverable account. #### For Friends of a Recoverable Account -* `vouch_recovery` - As a `friend` of a recoverable account, vouch for a recovery attempt on the account. +- `vouch_recovery` - As a `friend` of a recoverable account, vouch for a recovery attempt on the account. #### For a User Who Successfully Recovered an Account -* `claim_recovery` - Claim access to the account that you have successfully completed the recovery process for. -* `as_recovered` - Send a transaction as an account that you have recovered. See other functions below. +- `claim_recovery` - Claim access to the account that you have successfully completed the recovery process for. +- `as_recovered` - Send a transaction as an account that you have recovered. See other functions below. #### For the Recoverable Account -* `close_recovery` - Close an active recovery process for your account and reclaim the recovery deposit. -* `remove_recovery` - Remove the recovery configuration from the account, making it un-recoverable. +- `close_recovery` - Close an active recovery process for your account and reclaim the recovery deposit. +- `remove_recovery` - Remove the recovery configuration from the account, making it un-recoverable. #### For Super Users -* `set_recovered` - The ROOT origin is able to skip the recovery process and directly allow +- `set_recovered` - The ROOT origin is able to skip the recovery process and directly allow one account to access another. License: Apache-2.0 diff --git a/substrate/frame/remark/README.md b/substrate/frame/remark/README.md index f2341d6a0eae..5224f1b28820 100644 --- a/substrate/frame/remark/README.md +++ b/substrate/frame/remark/README.md @@ -1,6 +1,6 @@ # Remark Storage Pallet -Allows storing arbitrary data off chain. +Allows storing arbitrary data off chain. License: Apache-2.0 diff --git a/substrate/frame/root-offences/README.md b/substrate/frame/root-offences/README.md index c58215872181..b4e8381df2e7 100644 --- a/substrate/frame/root-offences/README.md +++ b/substrate/frame/root-offences/README.md @@ -2,4 +2,4 @@ Pallet that allows the root to create an offence. -NOTE: This pallet should only be used for testing purposes. \ No newline at end of file +NOTE: This pallet should only be used for testing purposes. diff --git a/substrate/frame/root-testing/README.md b/substrate/frame/root-testing/README.md index 637430445a22..aa231e3ef20a 100644 --- a/substrate/frame/root-testing/README.md +++ b/substrate/frame/root-testing/README.md @@ -2,4 +2,4 @@ Pallet that contains extrinsics that can be usefull in testing. -NOTE: This pallet should only be used for testing purposes and should not be used in production runtimes! \ No newline at end of file +NOTE: This pallet should only be used for testing purposes and should not be used in production runtimes! diff --git a/substrate/frame/salary/README.md b/substrate/frame/salary/README.md index 25c1be0e805d..ec3882dd0978 100644 --- a/substrate/frame/salary/README.md +++ b/substrate/frame/salary/README.md @@ -1,3 +1,3 @@ # Salary -Make periodic payment to members of a ranked collective according to rank. \ No newline at end of file +Make periodic payment to members of a ranked collective according to rank. diff --git a/substrate/frame/scheduler/README.md b/substrate/frame/scheduler/README.md index bdd2c2226c88..6aec2ddb0e43 100644 --- a/substrate/frame/scheduler/README.md +++ b/substrate/frame/scheduler/README.md @@ -23,12 +23,12 @@ then those filter will not be used when dispatching the schedule call. ### Dispatchable Functions -* `schedule` - schedule a dispatch, which may be periodic, to occur at a +- `schedule` - schedule a dispatch, which may be periodic, to occur at a specified block and with a specified priority. -* `cancel` - cancel a scheduled dispatch, specified by block number and +- `cancel` - cancel a scheduled dispatch, specified by block number and index. -* `schedule_named` - augments the `schedule` interface with an additional +- `schedule_named` - augments the `schedule` interface with an additional `Vec` parameter that can be used for identification. -* `cancel_named` - the named complement to the cancel function. +- `cancel_named` - the named complement to the cancel function. License: Apache 2.0 diff --git a/substrate/frame/session/README.md b/substrate/frame/session/README.md index 09132470d443..fa7c9b3f9834 100644 --- a/substrate/frame/session/README.md +++ b/substrate/frame/session/README.md @@ -1,7 +1,7 @@ # Session Pallet -The Session module allows validators to manage their session keys, provides a function for changing -the session length, and handles session rotation. +The Session module allows validators to manage their session keys, provides a function for changing the session length, +and handles session rotation. - [`session::Trait`](https://docs.rs/pallet-session/latest/pallet_session/trait.Config.html) - [`Call`](https://docs.rs/pallet-session/latest/pallet_session/enum.Call.html) @@ -12,34 +12,31 @@ the session length, and handles session rotation. ### Terminology -- **Session:** A session is a period of time that has a constant set of validators. Validators can only join -or exit the validator set at a session change. It is measured in block numbers. The block where a session is -ended is determined by the `ShouldEndSession` trait. When the session is ending, a new validator set -can be chosen by `OnSessionEnding` implementations. -- **Session key:** A session key is actually several keys kept together that provide the various signing -functions required by network authorities/validators in pursuit of their duties. -- **Validator ID:** Every account has an associated validator ID. For some simple staking systems, this -may just be the same as the account ID. For staking systems using a stash/controller model, -the validator ID would be the stash account ID of the controller. -- **Session key configuration process:** Session keys are set using `set_keys` for use not in -the next session, but the session after next. They are stored in `NextKeys`, a mapping between -the caller's `ValidatorId` and the session keys provided. `set_keys` allows users to set their -session key prior to being selected as validator. -It is a public call since it uses `ensure_signed`, which checks that the origin is a signed account. -As such, the account ID of the origin stored in `NextKeys` may not necessarily be associated with -a block author or a validator. The session keys of accounts are removed once their account balance is zero. -- **Session length:** This pallet does not assume anything about the length of each session. -Rather, it relies on an implementation of `ShouldEndSession` to dictate a new session's start. -This pallet provides the `PeriodicSessions` struct for simple periodic sessions. -- **Session rotation configuration:** Configure as either a 'normal' (rewardable session where rewards are -applied) or 'exceptional' (slashable) session rotation. -- **Session rotation process:** At the beginning of each block, the `on_initialize` function -queries the provided implementation of `ShouldEndSession`. If the session is to end the newly -activated validator IDs and session keys are taken from storage and passed to the -`SessionHandler`. The validator set supplied by `SessionManager::new_session` and the corresponding session -keys, which may have been registered via `set_keys` during the previous session, are written -to storage where they will wait one session before being passed to the `SessionHandler` -themselves. +- **Session:** A session is a period of time that has a constant set of validators. Validators can only join or exit the +validator set at a session change. It is measured in block numbers. The block where a session is ended is determined by +the `ShouldEndSession` trait. When the session is ending, a new validator set can be chosen by `OnSessionEnding` +implementations. +- **Session key:** A session key is actually several keys kept together that provide the various signing functions +required by network authorities/validators in pursuit of their duties. +- **Validator ID:** Every account has an associated validator ID. For some simple staking systems, this may just be the +same as the account ID. For staking systems using a stash/controller model, the validator ID would be the stash account +ID of the controller. +- **Session key configuration process:** Session keys are set using `set_keys` for use not in the next session, but the +session after next. They are stored in `NextKeys`, a mapping between the caller's `ValidatorId` and the session keys +provided. `set_keys` allows users to set their session key prior to being selected as validator. It is a public call +since it uses `ensure_signed`, which checks that the origin is a signed account. As such, the account ID of the origin +stored in `NextKeys` may not necessarily be associated with a block author or a validator. The session keys of accounts +are removed once their account balance is zero. +- **Session length:** This pallet does not assume anything about the length of each session. Rather, it relies on an +implementation of `ShouldEndSession` to dictate a new session's start. This pallet provides the `PeriodicSessions` +struct for simple periodic sessions. +- **Session rotation configuration:** Configure as either a 'normal' (rewardable session where rewards are applied) or +'exceptional' (slashable) session rotation. +- **Session rotation process:** At the beginning of each block, the `on_initialize` function queries the provided +implementation of `ShouldEndSession`. If the session is to end the newly activated validator IDs and session keys are +taken from storage and passed to the `SessionHandler`. The validator set supplied by `SessionManager::new_session` and +the corresponding session keys, which may have been registered via `set_keys` during the previous session, are written +to storage where they will wait one session before being passed to the `SessionHandler` themselves. ### Goals @@ -57,8 +54,8 @@ The Session pallet is designed to make the following possible: ### Public Functions -- `rotate_session` - Change to the next session. Register the new authority set. Queue changes -for next session rotation. +- `rotate_session` - Change to the next session. Register the new authority set. Queue changes for next session +rotation. - `disable_index` - Disable a validator by index. - `disable` - Disable a validator by Validator ID @@ -66,7 +63,8 @@ for next session rotation. ### Example from the FRAME -The [Staking pallet](https://docs.rs/pallet-staking/latest/pallet_staking/) uses the Session pallet to get the validator set. +The [Staking pallet](https://docs.rs/pallet-staking/latest/pallet_staking/) uses the Session pallet to get the validator +set. ```rust use pallet_session as session; diff --git a/substrate/frame/session/benchmarking/README.md b/substrate/frame/session/benchmarking/README.md index d034a9ec7328..e097f03f34a8 100644 --- a/substrate/frame/session/benchmarking/README.md +++ b/substrate/frame/session/benchmarking/README.md @@ -1,3 +1,3 @@ Benchmarks for the Session Pallet. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/society/README.md b/substrate/frame/society/README.md index 809986186642..c091d6c97d41 100644 --- a/substrate/frame/society/README.md +++ b/substrate/frame/society/README.md @@ -11,16 +11,16 @@ and maintain a membership society. ### User Types At any point, a user in the society can be one of a: -* Bidder - A user who has submitted intention of joining the society. -* Candidate - A user who will be voted on to join the society. -* Suspended Candidate - A user who failed to win a vote. -* Member - A user who is a member of the society. -* Suspended Member - A member of the society who has accumulated too many strikes +- Bidder - A user who has submitted intention of joining the society. +- Candidate - A user who will be voted on to join the society. +- Suspended Candidate - A user who failed to win a vote. +- Member - A user who is a member of the society. +- Suspended Member - A member of the society who has accumulated too many strikes or failed their membership challenge. Of the non-suspended members, there is always a: -* Head - A member who is exempt from suspension. -* Defender - A member whose membership is under question and voted on again. +- Head - A member who is exempt from suspension. +- Defender - A member whose membership is under question and voted on again. Of the non-suspended members of the society, a random set of them are chosen as "skeptics". The mechanics of skeptics is explained in the @@ -201,28 +201,28 @@ future payouts slashed. #### For General Users -* `bid` - A user can make a bid to join the membership society by reserving a deposit. -* `unbid` - A user can withdraw their bid for entry, the deposit is returned. +- `bid` - A user can make a bid to join the membership society by reserving a deposit. +- `unbid` - A user can withdraw their bid for entry, the deposit is returned. #### For Members -* `vouch` - A member can place a bid on behalf of a user to join the membership society. -* `unvouch` - A member can revoke their vouch for a user. -* `vote` - A member can vote to approve or reject a candidate's request to join the society. -* `defender_vote` - A member can vote to approve or reject a defender's continued membership +- `vouch` - A member can place a bid on behalf of a user to join the membership society. +- `unvouch` - A member can revoke their vouch for a user. +- `vote` - A member can vote to approve or reject a candidate's request to join the society. +- `defender_vote` - A member can vote to approve or reject a defender's continued membership to the society. -* `payout` - A member can claim their first matured payment. -* `unfound` - Allow the founder to unfound the society when they are the only member. +- `payout` - A member can claim their first matured payment. +- `unfound` - Allow the founder to unfound the society when they are the only member. #### For Super Users -* `found` - The founder origin can initiate this society. Useful for bootstrapping the Society +- `found` - The founder origin can initiate this society. Useful for bootstrapping the Society pallet on an already running chain. -* `judge_suspended_member` - The suspension judgement origin is able to make +- `judge_suspended_member` - The suspension judgement origin is able to make judgement on a suspended member. -* `judge_suspended_candidate` - The suspension judgement origin is able to +- `judge_suspended_candidate` - The suspension judgement origin is able to make judgement on a suspended candidate. -* `set_max_membership` - The ROOT origin can update the maximum member count for the society. +- `set_max_membership` - The ROOT origin can update the maximum member count for the society. The max membership count must be greater than 1. License: Apache-2.0 diff --git a/substrate/frame/staking/README.md b/substrate/frame/staking/README.md index ccb9901a6796..387b94b6a681 100644 --- a/substrate/frame/staking/README.md +++ b/substrate/frame/staking/README.md @@ -8,25 +8,24 @@ The Staking module is used to manage funds at stake by network maintainers. ## Overview -The Staking module is the means by which a set of network maintainers (known as _authorities_ in -some contexts and _validators_ in others) are chosen based upon those who voluntarily place -funds under deposit. Under deposit, those funds are rewarded under normal operation but are held -at pain of _slash_ (expropriation) should the staked maintainer be found not to be discharging -its duties properly. +The Staking module is the means by which a set of network maintainers (known as _authorities_ in some contexts and +_validators_ in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those +funds are rewarded under normal operation but are held at pain of _slash_ (expropriation) should the staked maintainer +be found not to be discharging its duties properly. ### Terminology -- Staking: The process of locking up funds for some time, placing them at risk of slashing - (loss) in order to become a rewarded maintainer of the network. -- Validating: The process of running a node to actively maintain the network, either by - producing blocks or guaranteeing finality of the chain. -- Nominating: The process of placing staked funds behind one or more validators in order to - share in any reward, and punishment, they take. +- Staking: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a + rewarded maintainer of the network. +- Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing + finality of the chain. +- Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and + punishment, they take. - Stash account: The account holding an owner's funds used for staking. - Controller account: The account that controls an owner's funds for staking. -- Era: A (whole) number of sessions, which is the period that the validator set (and each - validator's active nominator set) is recalculated and where rewards are paid out. +- Era: A (whole) number of sessions, which is the period that the validator set (and each validator's active nominator + set) is recalculated and where rewards are paid out. - Slash: The punishment of a staker by reducing its funds. ### Goals @@ -42,91 +41,90 @@ The staking system in Substrate NPoS is designed to make the following possible: #### Staking -Almost any interaction with the Staking module requires a process of _**bonding**_ (also known -as being a _staker_). To become *bonded*, a fund-holding account known as the _stash account_, -which holds some or all of the funds that become frozen in place as part of the staking process, -is paired with an active **controller** account, which issues instructions on how they shall be -used. +Almost any interaction with the Staking module requires a process of _**bonding**_ (also known as being a _staker_). To +become *bonded*, a fund-holding account known as the _stash account_, which holds some or all of the funds that become +frozen in place as part of the staking process, is paired with an active **controller** account, which issues +instructions on how they shall be used. -An account pair can become bonded using the [`bond`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.bond) call. +An account pair can become bonded using the +[`bond`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.bond) call. Stash accounts can update their associated controller back to their stash account using the -[`set_controller`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.set_controller) -call. +[`set_controller`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.set_controller) call. -Note: Controller accounts are being deprecated in favor of proxy accounts, so it is no longer -possible to set a unique address for a stash's controller. +Note: Controller accounts are being deprecated in favor of proxy accounts, so it is no longer possible to set a unique +address for a stash's controller. -There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` -and `Idle` (defined in [`StakerStatus`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.StakerStatus.html)). There are three +There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` and `Idle` (defined in +[`StakerStatus`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.StakerStatus.html)). There are three corresponding instructions to change between roles, namely: [`validate`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.validate), -[`nominate`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.nominate), and [`chill`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.chill). +[`nominate`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.nominate), and +[`chill`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.chill). #### Validating -A **validator** takes the role of either validating blocks or ensuring their finality, -maintaining the veracity of the network. A validator should avoid both any sort of malicious -misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT -get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they -_might_ get elected at the _next era_ as a validator. The result of the election is determined -by nominators and their votes. +A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the +network. A validator should avoid both any sort of malicious misbehavior and going offline. Bonded accounts that state +interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ +and they _might_ get elected at the _next era_ as a validator. The result of the election is determined by nominators +and their votes. An account can become a validator candidate via the [`validate`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.validate) call. #### Nomination -A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on -a set of validators to be elected. Once interest in nomination is stated by an account, it -takes effect at the next election round. The funds in the nominator's stash account indicate the -_weight_ of its vote. Both the rewards and any punishment that a validator earns are shared -between the validator and its nominators. This rule incentivizes the nominators to NOT vote for -the misbehaving/offline validators as much as possible, simply because the nominators will also -lose funds if they vote poorly. +A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to +be elected. Once interest in nomination is stated by an account, it takes effect at the next election round. The funds +in the nominator's stash account indicate the _weight_ of its vote. Both the rewards and any punishment that a validator +earns are shared between the validator and its nominators. This rule incentivizes the nominators to NOT vote for the +misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote +poorly. -An account can become a nominator via the [`nominate`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.nominate) call. +An account can become a nominator via the +[`nominate`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.nominate) call. #### Rewards and Slash -The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace -valid behavior_ while _punishing any misbehavior or lack of availability_. +The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace valid behavior_ while +_punishing any misbehavior or lack of availability_. -Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the -`payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to the -validator as well as its nominators. Only the [`Config::MaxNominatorRewardedPerValidator`] -biggest stakers can claim their reward. This is to limit the i/o cost to mutate storage for each -nominator's account. +Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the `payout_stakers` call. Any +account can call `payout_stakers`, which pays the reward to the validator as well as its nominators. Only the +[`Config::MaxNominatorRewardedPerValidator`] biggest stakers can claim their reward. This is to limit the i/o cost to +mutate storage for each nominator's account. -Slashing can occur at any point in time, once misbehavior is reported. Once slashing is -determined, a value is deducted from the balance of the validator and all the nominators who -voted for this validator (values are deducted from the _stash_ account of the slashed entity). +Slashing can occur at any point in time, once misbehavior is reported. Once slashing is determined, a value is deducted +from the balance of the validator and all the nominators who voted for this validator (values are deducted from the +_stash_ account of the slashed entity). Slashing logic is further described in the documentation of the `slashing` module. -Similar to slashing, rewards are also shared among a validator and its associated nominators. -Yet, the reward funds are not always transferred to the stash account and can be configured. See -[Reward Calculation](https://docs.rs/pallet-staking/latest/pallet_staking/#reward-calculation) for more details. +Similar to slashing, rewards are also shared among a validator and its associated nominators. Yet, the reward funds are +not always transferred to the stash account and can be configured. See [Reward +Calculation](https://docs.rs/pallet-staking/latest/pallet_staking/#reward-calculation) for more details. #### Chilling -Finally, any of the roles above can choose to step back temporarily and just chill for a while. -This means that if they are a nominator, they will not be considered as voters anymore and if -they are validators, they will no longer be a candidate for the next election. +Finally, any of the roles above can choose to step back temporarily and just chill for a while. This means that if they +are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a +candidate for the next election. -An account can step back via the [`chill`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.chill) call. +An account can step back via the +[`chill`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.chill) call. ### Session managing -The module implement the trait `SessionManager`. Which is the only API to query new validator -set and allowing these validator set to be rewarded once their era is ended. +The module implement the trait `SessionManager`. Which is the only API to query new validator set and allowing these +validator set to be rewarded once their era is ended. ## Interface ### Dispatchable Functions -The dispatchable functions of the Staking module enable the steps needed for entities to accept -and change their role, alongside some helper functions to get/set the metadata of the module. +The dispatchable functions of the Staking module enable the steps needed for entities to accept and change their role, +alongside some helper functions to get/set the metadata of the module. ### Public Functions @@ -134,7 +132,7 @@ The Staking module contains many public storage items and (im)mutable functions. ## Usage -### Example: Rewarding a validator by id. +### Example: Rewarding a validator by id ```rust use pallet_staking::{self as staking}; @@ -169,7 +167,8 @@ pub mod pallet { ### Era payout The era payout is computed using yearly inflation curve defined at -[`T::RewardCurve`](https://docs.rs/pallet-staking/latest/pallet_staking/trait.Config.html#associatedtype.RewardCurve) as such: +[`T::RewardCurve`](https://docs.rs/pallet-staking/latest/pallet_staking/trait.Config.html#associatedtype.RewardCurve) as +such: ```nocompile staker_payout = yearly_inflation(npos_token_staked / total_tokens) * total_tokens / era_per_year @@ -184,37 +183,38 @@ The remaining reward is send to the configurable end-point ### Reward Calculation -Validators and nominators are rewarded at the end of each era. The total reward of an era is -calculated using the era duration and the staking rate (the total amount of tokens staked by -nominators and validators, divided by the total token supply). It aims to incentivize toward a -defined staking rate. The full specification can be found +Validators and nominators are rewarded at the end of each era. The total reward of an era is calculated using the era +duration and the staking rate (the total amount of tokens staked by nominators and validators, divided by the total +token supply). It aims to incentivize toward a defined staking rate. The full specification can be found [here](https://research.web3.foundation/en/latest/polkadot/economics/1-token-economics.html#inflation-model). -Total reward is split among validators and their nominators depending on the number of points -they received during the era. Points are added to a validator using +Total reward is split among validators and their nominators depending on the number of points they received during the +era. Points are added to a validator using [`reward_by_ids`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.reward_by_ids) or [`reward_by_indices`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.reward_by_indices). [`Module`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Module.html) implements -[`pallet_authorship::EventHandler`](https://docs.rs/pallet-authorship/latest/pallet_authorship/trait.EventHandler.html) to add reward -points to block producer and block producer of referenced uncles. +[`pallet_authorship::EventHandler`](https://docs.rs/pallet-authorship/latest/pallet_authorship/trait.EventHandler.html) +to add reward points to block producer and block producer of referenced uncles. The validator and its nominator split their reward as following: The validator can declare an amount, named -[`commission`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.ValidatorPrefs.html#structfield.commission), that does not get shared -with the nominators at each reward payout through its -[`ValidatorPrefs`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.ValidatorPrefs.html). This value gets deducted from the total reward -that is paid to the validator and its nominators. The remaining portion is split among the -validator and all of the nominators that nominated the validator, proportional to the value -staked behind this validator (_i.e._ dividing the +[`commission`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.ValidatorPrefs.html#structfield.commission), +that does not get shared with the nominators at each reward payout through its +[`ValidatorPrefs`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.ValidatorPrefs.html). This value gets +deducted from the total reward that is paid to the validator and its nominators. The remaining portion is split among +the validator and all of the nominators that nominated the validator, proportional to the value staked behind this +validator (_i.e._ dividing the [`own`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Exposure.html#structfield.own) or [`others`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Exposure.html#structfield.others) by -[`total`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Exposure.html#structfield.total) in [`Exposure`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Exposure.html)). +[`total`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Exposure.html#structfield.total) in +[`Exposure`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Exposure.html)). All entities who receive a reward have the option to choose their reward destination through the [`Payee`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.Payee.html) storage item (see -[`set_payee`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.set_payee)), to be one of the following: +[`set_payee`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.set_payee)), to be one of the +following: - Controller account, (obviously) not increasing the staked value. - Stash account, not increasing the staked value. @@ -225,32 +225,33 @@ All entities who receive a reward have the option to choose their reward destina Any funds already placed into stash can be the target of the following operations: The controller account can free a portion (or all) of the funds using the -[`unbond`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.unbond) call. Note that the funds are not immediately -accessible. Instead, a duration denoted by [`BondingDuration`](https://docs.rs/pallet-staking/latest/pallet_staking/trait.Config.html#associatedtype.BondingDuration) -(in number of eras) must pass until the funds can actually be removed. Once the -`BondingDuration` is over, the [`withdraw_unbonded`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.withdraw_unbonded) +[`unbond`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.unbond) call. Note that the funds +are not immediately accessible. Instead, a duration denoted by +[`BondingDuration`](https://docs.rs/pallet-staking/latest/pallet_staking/trait.Config.html#associatedtype.BondingDuration) +(in number of eras) must pass until the funds can actually be removed. Once the `BondingDuration` is over, the +[`withdraw_unbonded`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.withdraw_unbonded) call can be used to actually withdraw the funds. -Note that there is a limitation to the number of fund-chunks that can be scheduled to be -unlocked in the future via [`unbond`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.unbond). In case this maximum -(`MAX_UNLOCKING_CHUNKS`) is reached, the bonded account _must_ first wait until a successful -call to `withdraw_unbonded` to remove some of the chunks. +Note that there is a limitation to the number of fund-chunks that can be scheduled to be unlocked in the future via +[`unbond`](https://docs.rs/pallet-staking/latest/pallet_staking/enum.Call.html#variant.unbond). In case this maximum +(`MAX_UNLOCKING_CHUNKS`) is reached, the bonded account _must_ first wait until a successful call to `withdraw_unbonded` +to remove some of the chunks. ### Election Algorithm -The current election algorithm is implemented based on Phragmén. The reference implementation -can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). +The current election algorithm is implemented based on Phragmén. The reference implementation can be found +[here](https://github.com/w3f/consensus/tree/master/NPoS). -The election algorithm, aside from electing the validators with the most stake value and votes, -tries to divide the nominator votes among candidates in an equal manner. To further assure this, -an optional post-processing can be applied that iteratively normalizes the nominator staked -values until the total difference among votes of a particular nominator are less than a -threshold. +The election algorithm, aside from electing the validators with the most stake value and votes, tries to divide the +nominator votes among candidates in an equal manner. To further assure this, an optional post-processing can be applied +that iteratively normalizes the nominator staked values until the total difference among votes of a particular nominator +are less than a threshold. ## GenesisConfig -The Staking module depends on the [`GenesisConfig`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.GenesisConfig.html). The -`GenesisConfig` is optional and allow to set some initial stakers. +The Staking module depends on the +[`GenesisConfig`](https://docs.rs/pallet-staking/latest/pallet_staking/struct.GenesisConfig.html). The `GenesisConfig` +is optional and allow to set some initial stakers. ## Related Modules diff --git a/substrate/frame/sudo/README.md b/substrate/frame/sudo/README.md index 886dc5981778..371f89e5348c 100644 --- a/substrate/frame/sudo/README.md +++ b/substrate/frame/sudo/README.md @@ -16,8 +16,8 @@ Only one account can be the sudo key at a time. Only the sudo key can call the dispatchable functions from the Sudo module. -* `sudo` - Make a `Root` call to a dispatchable function. -* `set_key` - Assign a new account to be the sudo key. +- `sudo` - Make a `Root` call to a dispatchable function. +- `set_key` - Assign a new account to be the sudo key. ## Usage @@ -68,7 +68,7 @@ You need to set an initial superuser account as the sudo `key`. ## Related Modules -* [Democracy](https://docs.rs/pallet-democracy/latest/pallet_democracy/) +- [Democracy](https://docs.rs/pallet-democracy/latest/pallet_democracy/) [`Call`]: ./enum.Call.html [`Config`]: ./trait.Config.html diff --git a/substrate/frame/support/README.md b/substrate/frame/support/README.md index 2282870aca05..dd2a07346dda 100644 --- a/substrate/frame/support/README.md +++ b/substrate/frame/support/README.md @@ -1,3 +1,3 @@ Support code for the runtime. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 88aad32225a0..1898246470c7 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -1386,7 +1386,7 @@ fn metadata() { } } - let readme = "Support code for the runtime.\n\nLicense: Apache-2.0"; + let readme = "Support code for the runtime.\n\nLicense: Apache-2.0\n"; let expected_pallet_doc = vec![" Pallet documentation", readme, readme]; let pallets = vec![ @@ -1889,7 +1889,7 @@ fn metadata_ir_pallet_runtime_docs() { .find(|pallet| pallet.name == "Example") .expect("Pallet should be present"); - let readme = "Support code for the runtime.\n\nLicense: Apache-2.0"; + let readme = "Support code for the runtime.\n\nLicense: Apache-2.0\n"; let expected = vec![" Pallet documentation", readme, readme]; assert_eq!(pallet.docs, expected); } @@ -1919,7 +1919,7 @@ fn extrinsic_metadata_ir_types() { #[test] fn test_pallet_runtime_docs() { let docs = crate::pallet::Pallet::::pallet_documentation_metadata(); - let readme = "Support code for the runtime.\n\nLicense: Apache-2.0"; + let readme = "Support code for the runtime.\n\nLicense: Apache-2.0\n"; let expected = vec![" Pallet documentation", readme, readme]; assert_eq!(docs, expected); } diff --git a/substrate/frame/system/README.md b/substrate/frame/system/README.md index 30b2ea73720c..c15281d365ba 100644 --- a/substrate/frame/system/README.md +++ b/substrate/frame/system/README.md @@ -1,20 +1,20 @@ # System Module -The System module provides low-level access to core types and cross-cutting utilities. -It acts as the base layer for other pallets to interact with the Substrate framework components. +The System module provides low-level access to core types and cross-cutting utilities. It acts as the base layer for +other pallets to interact with the Substrate framework components. - [`system::Config`](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) ## Overview -The System module defines the core data types used in a Substrate runtime. -It also provides several utility functions (see [`Pallet`](https://docs.rs/frame-system/latest/frame_system/pallet/struct.Pallet.html)) for other FRAME pallets. +The System module defines the core data types used in a Substrate runtime. It also provides several utility functions +(see [`Pallet`](https://docs.rs/frame-system/latest/frame_system/pallet/struct.Pallet.html)) for other FRAME pallets. -In addition, it manages the storage items for extrinsics data, indexes, event records, and digest items, -among other things that support the execution of the current block. +In addition, it manages the storage items for extrinsics data, indexes, event records, and digest items, among other +things that support the execution of the current block. -It also handles low-level tasks like depositing logs, basic set up and take down of -temporary storage entries, and access to previous block hashes. +It also handles low-level tasks like depositing logs, basic set up and take down of temporary storage entries, and +access to previous block hashes. ## Interface @@ -24,26 +24,22 @@ The System module does not implement any dispatchable functions. ### Public Functions -See the [`Pallet`](https://docs.rs/frame-system/latest/frame_system/pallet/struct.Pallet.html) struct for details of publicly available functions. +See the [`Pallet`](https://docs.rs/frame-system/latest/frame_system/pallet/struct.Pallet.html) struct for details of +publicly available functions. ### Signed Extensions The System module defines the following extensions: - - [`CheckWeight`]: Checks the weight and length of the block and ensure that it does not - exceed the limits. - - [`CheckNonce`]: Checks the nonce of the transaction. Contains a single payload of type - `T::Nonce`. + - [`CheckWeight`]: Checks the weight and length of the block and ensure that it does not exceed the limits. + - [`CheckNonce`]: Checks the nonce of the transaction. Contains a single payload of type `T::Nonce`. - [`CheckEra`]: Checks the era of the transaction. Contains a single payload of type `Era`. - - [`CheckGenesis`]: Checks the provided genesis hash of the transaction. Must be a part of the - signed payload of the transaction. - - [`CheckSpecVersion`]: Checks that the runtime version is the same as the one used to sign the - transaction. - - [`CheckTxVersion`]: Checks that the transaction version is the same as the one used to sign the + - [`CheckGenesis`]: Checks the provided genesis hash of the transaction. Must be a part of the signed payload of the transaction. + - [`CheckSpecVersion`]: Checks that the runtime version is the same as the one used to sign the transaction. + - [`CheckTxVersion`]: Checks that the transaction version is the same as the one used to sign the transaction. -Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed -extensions included in a chain. +Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed extensions included in a chain. ## Usage diff --git a/substrate/frame/system/benchmarking/README.md b/substrate/frame/system/benchmarking/README.md index 9718db58b37e..811207fd8c0f 100644 --- a/substrate/frame/system/benchmarking/README.md +++ b/substrate/frame/system/benchmarking/README.md @@ -1 +1 @@ -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/system/benchmarking/res/README.md b/substrate/frame/system/benchmarking/res/README.md index 43bb2b5c283e..6eca9229531a 100644 --- a/substrate/frame/system/benchmarking/res/README.md +++ b/substrate/frame/system/benchmarking/res/README.md @@ -2,4 +2,5 @@ These runtimes are used for benchmarking the `set_code` intrinsic. **Don't use them in production environments!** -To update the just copy the new runtime from `target/release/wbuild/kitchensink-runtime/kitchensink_runtime.compact.compressed.wasm` to here. +To update the just copy the new runtime from +`target/release/wbuild/kitchensink-runtime/kitchensink_runtime.compact.compressed.wasm` to here. diff --git a/substrate/frame/system/rpc/runtime-api/README.md b/substrate/frame/system/rpc/runtime-api/README.md index ab46c22a8be3..d418cad5a342 100644 --- a/substrate/frame/system/rpc/runtime-api/README.md +++ b/substrate/frame/system/rpc/runtime-api/README.md @@ -4,4 +4,4 @@ This API should be imported and implemented by the runtime, of a node that wants to use the custom RPC extension adding System access methods. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/frame/timestamp/README.md b/substrate/frame/timestamp/README.md index 1546377ee674..69dba60550e4 100644 --- a/substrate/frame/timestamp/README.md +++ b/substrate/frame/timestamp/README.md @@ -22,16 +22,16 @@ because of cumulative calculation errors and hence should be avoided. ### Dispatchable Functions -* `set` - Sets the current time. +- `set` - Sets the current time. ### Public functions -* `get` - Gets the current time for the current block. If this function is called prior to +- `get` - Gets the current time for the current block. If this function is called prior to setting the timestamp, it will return the timestamp of the previous block. ### Config Getters -* `MinimumPeriod` - Gets the minimum (and advised) period between blocks for the chain. +- `MinimumPeriod` - Gets the minimum (and advised) period between blocks for the chain. ## Usage @@ -78,6 +78,6 @@ the Timestamp module for session management. ## Related Modules -* [Session](https://docs.rs/pallet-session/latest/pallet_session/) +- [Session](https://docs.rs/pallet-session/latest/pallet_session/) License: Apache-2.0 diff --git a/substrate/frame/tips/README.md b/substrate/frame/tips/README.md index d885ce770f79..1960172c497a 100644 --- a/substrate/frame/tips/README.md +++ b/substrate/frame/tips/README.md @@ -11,7 +11,7 @@ entered where any remaining members can declare their tip amounts also. After th countdown period, the median of all declared tips is paid to the reported beneficiary, along with any finders fee, in case of a public (and bonded) original report. -### Terminology +## Terminology - **Tipping:** The process of gathering declarations of amounts to tip and taking the median amount to be transferred from the treasury to a beneficiary account. @@ -30,4 +30,4 @@ any finders fee, in case of a public (and bonded) original report. - `tip_new` - Report an item worthy of a tip and declare a specific amount to tip. - `tip` - Declare or redeclare an amount to tip for a particular reason. - `close_tip` - Close and pay out a tip. -- `slash_tip` - Remove and slash an already-open tip. \ No newline at end of file +- `slash_tip` - Remove and slash an already-open tip. diff --git a/substrate/frame/transaction-storage/README.md b/substrate/frame/transaction-storage/README.md index 0ed3ba279c2a..1066968469d4 100644 --- a/substrate/frame/transaction-storage/README.md +++ b/substrate/frame/transaction-storage/README.md @@ -2,8 +2,9 @@ Indexes transactions and manages storage proofs. -Allows storing arbitrary data on the chain. Data is automatically removed after `StoragePeriod` blocks, unless the storage is renewed. -Validators must submit proof of storing a random chunk of data for block `N - StoragePeriod` when producing block `N`. +Allows storing arbitrary data on the chain. Data is automatically removed after `StoragePeriod` blocks, unless the +storage is renewed. Validators must submit proof of storing a random chunk of data for block `N - StoragePeriod` when +producing block `N`. # Running a chain @@ -15,8 +16,9 @@ Start with generating a chain spec. cargo run --release -- build-spec --chain=local > sc_init.json ``` -Edit the json chain spec file to customise the chain. The storage chain genesis params are configured in the `transactionStorage` section. -Note that `storagePeriod` is specified in blocks and changing it also requires code changes at the moment. +Edit the json chain spec file to customise the chain. The storage chain genesis params are configured in the +`transactionStorage` section. Note that `storagePeriod` is specified in blocks and changing it also requires code +changes at the moment. Build a raw spec from the init spec. @@ -31,11 +33,11 @@ cargo run --release -- --chain=sc.json -d /tmp/alice --storage-chain --keep-bloc cargo run --release -- --chain=sc.json -d /tmp/bob --storage-chain --keep-blocks=100800 --ipfs-server --validator --bob ``` -`--storage-chain` enables transaction indexing. -`--keep-blocks=100800` enables block pruning. The value here should be greater or equal than the storage period. -`--ipfs-server` enables serving stored content over IPFS. +`--storage-chain` enables transaction indexing. `--keep-blocks=100800` enables block pruning. The value here should be +greater or equal than the storage period. `--ipfs-server` enables serving stored content over IPFS. -Once the network is started, any other joining nodes need to sync with `--sync=fast`. Regular sync will fail because block pruning removes old blocks. The chain does not keep full block history. +Once the network is started, any other joining nodes need to sync with `--sync=fast`. Regular sync will fail because +block pruning removes old blocks. The chain does not keep full block history. ```bash cargo run --release -- --chain=sc.json -d /tmp/charlie --storage-chain --keep-blocks=100800 --ipfs-server --validator --charlie --sync=fast @@ -43,7 +45,8 @@ cargo run --release -- --chain=sc.json -d /tmp/charlie --storage-chain --keep-bl # Making transactions -To store data use the `transactionStorage.store` extrinsic. And IPFS CID can be generated from the Blake2-256 hash of the data. +To store data use the `transactionStorage.store` extrinsic. And IPFS CID can be generated from the Blake2-256 hash of +the data. ```js const util_crypto = require('@polkadot/util-crypto'); @@ -76,7 +79,8 @@ ipfs block get /ipfs/ > kitten.jpeg ``` To renew data and prevent it from being disposed after the storage period, use `transactionStorage.renew(block, index)` -where `block` is the block number of the previous store or renew transction, and index is the index of that transaction in the block. +where `block` is the block number of the previous store or renew transction, and index is the index of that transaction +in the block. License: Apache-2.0 diff --git a/substrate/frame/uniques/README.md b/substrate/frame/uniques/README.md index 6cdbcf79f1c9..538fd9e70a26 100644 --- a/substrate/frame/uniques/README.md +++ b/substrate/frame/uniques/README.md @@ -13,9 +13,11 @@ The Uniques module provides functionality for non-fungible tokens' management, i * Attributes Management * Item Burning -To use it in your runtime, you need to implement [`uniques::Config`](https://paritytech.github.io/substrate/master/pallet_uniques/pallet/trait.Config.html). +To use it in your runtime, you need to implement +[`uniques::Config`](https://paritytech.github.io/substrate/master/pallet_uniques/pallet/trait.Config.html). -The supported dispatchable functions are documented in the [`uniques::Call`](https://paritytech.github.io/substrate/master/pallet_uniques/pallet/enum.Call.html) enum. +The supported dispatchable functions are documented in the +[`uniques::Call`](https://paritytech.github.io/substrate/master/pallet_uniques/pallet/enum.Call.html) enum. ### Terminology @@ -23,8 +25,8 @@ The supported dispatchable functions are documented in the [`uniques::Call`](htt * **Item minting:** The action of creating a new item within a collection. * **Item transfer:** The action of sending an item from one account to another. * **Item burning:** The destruction of an item. -* **Non-fungible token (NFT):** An item for which each unit has unique characteristics. There is exactly - one instance of such an item in existence and there is exactly one owning account. +* **Non-fungible token (NFT):** An item for which each unit has unique characteristics. There is exactly one instance of + such an item in existence and there is exactly one owning account. ### Goals @@ -33,10 +35,8 @@ The Uniques pallet in Substrate is designed to make the following possible: * Allow accounts to permissionlessly create NFT collections. * Allow a named (permissioned) account to mint and burn unique items within a collection. * Move items between accounts permissionlessly. -* Allow a named (permissioned) account to freeze and unfreeze unique items within a - collection or the entire collection. -* Allow the owner of an item to delegate the ability to transfer the item to some - named third-party. +* Allow a named (permissioned) account to freeze and unfreeze unique items within a collection or the entire collection. +* Allow the owner of an item to delegate the ability to transfer the item to some named third-party. ## Interface diff --git a/substrate/frame/utility/README.md b/substrate/frame/utility/README.md index db19b0cf8cf9..00fff76cd626 100644 --- a/substrate/frame/utility/README.md +++ b/substrate/frame/utility/README.md @@ -27,10 +27,10 @@ filtered by any proxy. ### Dispatchable Functions #### For batch dispatch -* `batch` - Dispatch multiple calls from the sender's origin. +- `batch` - Dispatch multiple calls from the sender's origin. #### For pseudonymal dispatch -* `as_derivative` - Dispatch a call from a derivative signed origin. +- `as_derivative` - Dispatch a call from a derivative signed origin. [`Call`]: ./enum.Call.html [`Config`]: ./trait.Config.html diff --git a/substrate/primitives/api/README.md b/substrate/primitives/api/README.md index 1cf9437373c7..ee0e402f9d7f 100644 --- a/substrate/primitives/api/README.md +++ b/substrate/primitives/api/README.md @@ -14,4 +14,4 @@ api, the [`ApiExt`] trait, the [`CallApiAt`] trait and the [`ConstructRuntimeApi On a meta level this implies, the client calls the generated API from the client perspective. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/application-crypto/README.md b/substrate/primitives/application-crypto/README.md index c86e33552f60..a686b7465812 100644 --- a/substrate/primitives/application-crypto/README.md +++ b/substrate/primitives/application-crypto/README.md @@ -1,3 +1,3 @@ Traits and macros for constructing application specific strongly typed crypto wrappers. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/arithmetic/README.md b/substrate/primitives/arithmetic/README.md index e6e52c2a8269..b5dcfdb29446 100644 --- a/substrate/primitives/arithmetic/README.md +++ b/substrate/primitives/arithmetic/README.md @@ -1,3 +1,3 @@ Minimal fixed point arithmetic primitives and types for runtime. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/authority-discovery/README.md b/substrate/primitives/authority-discovery/README.md index 65c2e22dde00..3b48ddc61c51 100644 --- a/substrate/primitives/authority-discovery/README.md +++ b/substrate/primitives/authority-discovery/README.md @@ -1,3 +1,3 @@ Runtime Api to help discover authorities. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/block-builder/README.md b/substrate/primitives/block-builder/README.md index 433197d3be9e..952c94798d3a 100644 --- a/substrate/primitives/block-builder/README.md +++ b/substrate/primitives/block-builder/README.md @@ -1,3 +1,3 @@ The block builder runtime api. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/blockchain/README.md b/substrate/primitives/blockchain/README.md index 8298bfd7ae60..a0a5b2edce51 100644 --- a/substrate/primitives/blockchain/README.md +++ b/substrate/primitives/blockchain/README.md @@ -1,3 +1,3 @@ Substrate blockchain traits and primitives. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/consensus/aura/README.md b/substrate/primitives/consensus/aura/README.md index 0f360ae67eb2..725c6fc6db49 100644 --- a/substrate/primitives/consensus/aura/README.md +++ b/substrate/primitives/consensus/aura/README.md @@ -1,3 +1,3 @@ Primitives for Aura. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/consensus/babe/README.md b/substrate/primitives/consensus/babe/README.md index 54bae05fd6db..59f8d925af75 100644 --- a/substrate/primitives/consensus/babe/README.md +++ b/substrate/primitives/consensus/babe/README.md @@ -1,3 +1,3 @@ Primitives for BABE. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/consensus/common/README.md b/substrate/primitives/consensus/common/README.md index 963bb0fbdba4..f61a00c42c84 100644 --- a/substrate/primitives/consensus/common/README.md +++ b/substrate/primitives/consensus/common/README.md @@ -1,7 +1,7 @@ -Common utilities for building and using consensus engines in substrate. +Common utilities for building and using consensus engines in Substrate. Much of this crate is _unstable_ and thus the API is likely to undergo change. Implementors of traits should not rely on the interfaces to remain the same. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/consensus/grandpa/README.md b/substrate/primitives/consensus/grandpa/README.md index 77a7abca2eef..d357904cd1f1 100644 --- a/substrate/primitives/consensus/grandpa/README.md +++ b/substrate/primitives/consensus/grandpa/README.md @@ -1,3 +1,3 @@ Primitives for GRANDPA integration, suitable for WASM compilation. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/consensus/pow/README.md b/substrate/primitives/consensus/pow/README.md index 881864377649..390190c5d183 100644 --- a/substrate/primitives/consensus/pow/README.md +++ b/substrate/primitives/consensus/pow/README.md @@ -1,3 +1,3 @@ Primitives for Substrate Proof-of-Work (PoW) consensus. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/consensus/slots/README.md b/substrate/primitives/consensus/slots/README.md index f451c32888a4..3052131721ad 100644 --- a/substrate/primitives/consensus/slots/README.md +++ b/substrate/primitives/consensus/slots/README.md @@ -1,3 +1,3 @@ Primitives for slots-based consensus engines. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/database/README.md b/substrate/primitives/database/README.md index cd0677eb9eb4..26f58ea8d458 100644 --- a/substrate/primitives/database/README.md +++ b/substrate/primitives/database/README.md @@ -1,3 +1,3 @@ The main database trait, allowing Substrate to store data persistently. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/externalities/README.md b/substrate/primitives/externalities/README.md index 3141b2609e63..543b63ecbdb6 100644 --- a/substrate/primitives/externalities/README.md +++ b/substrate/primitives/externalities/README.md @@ -6,4 +6,4 @@ access the node from the runtime via the runtime interfaces. This crate exposes the main [`Externalities`] trait. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/inherents/README.md b/substrate/primitives/inherents/README.md index 78aa625fe856..20ceb5294691 100644 --- a/substrate/primitives/inherents/README.md +++ b/substrate/primitives/inherents/README.md @@ -14,4 +14,4 @@ A module can also just check given inherents. For using a module as inherent pro to be registered by the `construct_runtime!` macro. The macro documentation gives more information on how that is done. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/io/README.md b/substrate/primitives/io/README.md index a24370cc566b..5e252eeacb09 100644 --- a/substrate/primitives/io/README.md +++ b/substrate/primitives/io/README.md @@ -1,3 +1,3 @@ -I/O host interface for substrate runtime. +I/O host interface for Substrate runtime. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/keyring/README.md b/substrate/primitives/keyring/README.md index 1610f237df97..555a35f09bc3 100644 --- a/substrate/primitives/keyring/README.md +++ b/substrate/primitives/keyring/README.md @@ -1,3 +1,3 @@ Support code for the runtime. A set of test accounts. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/npos-elections/README.md b/substrate/primitives/npos-elections/README.md index 6881fc6418f3..e65f22ca271a 100644 --- a/substrate/primitives/npos-elections/README.md +++ b/substrate/primitives/npos-elections/README.md @@ -1,30 +1,29 @@ -A set of election algorithms to be used with a substrate runtime, typically within the staking -sub-system. Notable implementation include: +# sp-npos-elections -- [`seq_phragmen`]: Implements the Phragmén Sequential Method. An un-ranked, relatively fast - election method that ensures PJR, but does not provide a constant factor approximation of the - maximin problem. -- [`phragmms`]: Implements a hybrid approach inspired by Phragmén which is executed faster but - it can achieve a constant factor approximation of the maximin problem, similar to that of the - MMS algorithm. -- [`balance_solution`]: Implements the star balancing algorithm. This iterative process can push - a solution toward being more `balanced`, which in turn can increase its score. +A set of election algorithms to be used with a Substrate runtime, typically within the staking sub-system. Notable +implementation include: -### Terminology +- [`seq_phragmen`]: Implements the Phragmén Sequential Method. An un-ranked, relatively fast election method that + ensures PJR, but does not provide a constant factor approximation of the maximin problem. +- [`phragmms`]: Implements a hybrid approach inspired by Phragmén which is executed faster but it can achieve a constant + factor approximation of the maximin problem, similar to that of the MMS algorithm. +- [`balance_solution`]: Implements the star balancing algorithm. This iterative process can push a solution toward being + more `balanced`, which in turn can increase its score. -This crate uses context-independent words, not to be confused with staking. This is because the -election algorithms of this crate, while designed for staking, can be used in other contexts as -well. +## Terminology -`Voter`: The entity casting some votes to a number of `Targets`. This is the same as `Nominator` -in the context of staking. `Target`: The entities eligible to be voted upon. This is the same as -`Validator` in the context of staking. `Edge`: A mapping from a `Voter` to a `Target`. +This crate uses context-independent words, not to be confused with staking. This is because the election algorithms of +this crate, while designed for staking, can be used in other contexts as well. + +`Voter`: The entity casting some votes to a number of `Targets`. This is the same as `Nominator` in the context of +staking. `Target`: The entities eligible to be voted upon. This is the same as `Validator` in the context of staking. +`Edge`: A mapping from a `Voter` to a `Target`. The goal of an election algorithm is to provide an `ElectionResult`. A data composed of: -- `winners`: A flat list of identifiers belonging to those who have won the election, usually - ordered in some meaningful way. They are zipped with their total backing stake. -- `assignment`: A mapping from each voter to their winner-only targets, zipped with a ration - denoting the amount of support given to that particular target. +- `winners`: A flat list of identifiers belonging to those who have won the election, usually ordered in some meaningful + way. They are zipped with their total backing stake. +- `assignment`: A mapping from each voter to their winner-only targets, zipped with a ration denoting the amount of + support given to that particular target. ```rust // the winners. @@ -44,16 +43,14 @@ let election_result = ElectionResult { winners, assignments }; ``` -The `Assignment` field of the election result is voter-major, i.e. it is from the perspective of -the voter. The struct that represents the opposite is called a `Support`. This struct is usually -accessed in a map-like manner, i.e. keyed by voters, therefore it is stored as a mapping called -`SupportMap`. +The `Assignment` field of the election result is voter-major, i.e. it is from the perspective of the voter. The struct +that represents the opposite is called a `Support`. This struct is usually accessed in a map-like manner, i.e. keyed by +voters, therefore it is stored as a mapping called `SupportMap`. -Moreover, the support is built from absolute backing values, not ratios like the example above. -A struct similar to `Assignment` that has stake value instead of ratios is called an -`StakedAssignment`. +Moreover, the support is built from absolute backing values, not ratios like the example above. A struct similar to +`Assignment` that has stake value instead of ratios is called an `StakedAssignment`. More information can be found at: https://arxiv.org/abs/2004.12990 -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/offchain/README.md b/substrate/primitives/offchain/README.md index a8620d3bb9d5..5c239d2e0e73 100644 --- a/substrate/primitives/offchain/README.md +++ b/substrate/primitives/offchain/README.md @@ -1,3 +1,3 @@ The Offchain Worker runtime api primitives. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/panic-handler/README.md b/substrate/primitives/panic-handler/README.md index c08396960f4c..f4f974ea6e1c 100644 --- a/substrate/primitives/panic-handler/README.md +++ b/substrate/primitives/panic-handler/README.md @@ -7,4 +7,4 @@ given URL. By default, the panic handler aborts the process by calling [`std::process::exit`]. This can temporarily be disabled by using an [`AbortGuard`]. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/rpc/README.md b/substrate/primitives/rpc/README.md index 8a9c17edd475..4d48fc56aed9 100644 --- a/substrate/primitives/rpc/README.md +++ b/substrate/primitives/rpc/README.md @@ -1,3 +1,3 @@ Substrate RPC primitives and utilities. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/runtime-interface/README.md b/substrate/primitives/runtime-interface/README.md index 49e13f1b2e74..f6dfea945ddb 100644 --- a/substrate/primitives/runtime-interface/README.md +++ b/substrate/primitives/runtime-interface/README.md @@ -1,43 +1,42 @@ Substrate runtime interface -This crate provides types, traits and macros around runtime interfaces. A runtime interface is -a fixed interface between a Substrate runtime and a Substrate node. For a native runtime the -interface maps to a direct function call of the implementation. For a wasm runtime the interface -maps to an external function call. These external functions are exported by the wasm executor -and they map to the same implementation as the native calls. +This crate provides types, traits and macros around runtime interfaces. A runtime interface is a fixed interface between +a Substrate runtime and a Substrate node. For a native runtime the interface maps to a direct function call of the +implementation. For a wasm runtime the interface maps to an external function call. These external functions are +exported by the wasm executor and they map to the same implementation as the native calls. # Using a type in a runtime interface -Any type that should be used in a runtime interface as argument or return value needs to -implement [`RIType`]. The associated type [`FFIType`](https:/docs.rs/sp-runtime-interface/latest/sp_runtime_interface/trait.RIType.html#associatedtype.FFIType) -is the type that is used in the FFI function to represent the actual type. For example `[T]` is -represented by an `u64`. The slice pointer and the length will be mapped to an `u64` value. -For more information see this [table](https:/docs.rs/sp-runtime-interface/latest/sp_runtime_interface/#ffi-type-and-conversion). -The FFI function definition is used when calling from the wasm runtime into the node. +Any type that should be used in a runtime interface as argument or return value needs to implement [`RIType`]. The +associated type +[`FFIType`](https:/docs.rs/sp-runtime-interface/latest/sp_runtime_interface/trait.RIType.html#associatedtype.FFIType) is +the type that is used in the FFI function to represent the actual type. For example `[T]` is represented by an `u64`. +The slice pointer and the length will be mapped to an `u64` value. For more information see this +[table](https:/docs.rs/sp-runtime-interface/latest/sp_runtime_interface/#ffi-type-and-conversion). The FFI function +definition is used when calling from the wasm runtime into the node. Traits are used to convert from a type to the corresponding [`RIType::FFIType`](https:/docs.rs/sp-runtime-interface/latest/sp_runtime_interface/trait.RIType.html#associatedtype.FFIType). -Depending on where and how a type should be used in a function signature, a combination of the -following traits need to be implemented: +Depending on where and how a type should be used in a function signature, a combination of the following traits need to +be implemented: 1. Pass as function argument: [`wasm::IntoFFIValue`] and [`host::FromFFIValue`] 2. As function return value: [`wasm::FromFFIValue`] and [`host::IntoFFIValue`] 3. Pass as mutable function argument: [`host::IntoPreallocatedFFIValue`] -The traits are implemented for most of the common types like `[T]`, `Vec`, arrays and -primitive types. +The traits are implemented for most of the common types like `[T]`, `Vec`, arrays and primitive types. -For custom types, we provide the [`PassBy`](https://docs.rs/sp-runtime-interface/latest/sp_runtime_interface/pass_by#PassBy) trait and strategies that define -how a type is passed between the wasm runtime and the node. Each strategy also provides a derive -macro to simplify the implementation. +For custom types, we provide the +[`PassBy`](https://docs.rs/sp-runtime-interface/latest/sp_runtime_interface/pass_by#PassBy) trait and strategies that +define how a type is passed between the wasm runtime and the node. Each strategy also provides a derive macro to +simplify the implementation. # Performance -To not waste any more performance when calling into the node, not all types are SCALE encoded -when being passed as arguments between the wasm runtime and the node. For most types that -are raw bytes like `Vec`, `[u8]` or `[u8; N]` we pass them directly, without SCALE encoding -them in front of. The implementation of [`RIType`] each type provides more information on how -the data is passed. +To not waste any more performance when calling into the node, not all types are SCALE encoded when being passed as +arguments between the wasm runtime and the node. For most types that are raw bytes like `Vec`, `[u8]` or `[u8; N]` +we pass them directly, without SCALE encoding them in front of. The implementation of [`RIType`] each type provides more +information on how the data is passed. # Declaring a runtime interface @@ -57,9 +56,10 @@ For more information on declaring a runtime interface, see # FFI type and conversion -The following table documents how values of types are passed between the wasm and -the host side and how they are converted into the corresponding type. +The following table documents how values of types are passed between the wasm and the host side and how they are +converted into the corresponding type. + | Type | FFI type | Conversion | |----|----|----| | `u8` | `u8` | `Identity` | diff --git a/substrate/primitives/runtime/README.md b/substrate/primitives/runtime/README.md index 1515cd8e2961..2755690e4b32 100644 --- a/substrate/primitives/runtime/README.md +++ b/substrate/primitives/runtime/README.md @@ -1,3 +1,3 @@ Runtime Modules shared primitive types. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/session/README.md b/substrate/primitives/session/README.md index 2d1f9d9bc1d5..9ad3e2747034 100644 --- a/substrate/primitives/session/README.md +++ b/substrate/primitives/session/README.md @@ -1,3 +1,3 @@ Substrate core types around sessions. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/staking/README.md b/substrate/primitives/staking/README.md index 892e1379d9a5..3e0ea0ba1fa2 100644 --- a/substrate/primitives/staking/README.md +++ b/substrate/primitives/staking/README.md @@ -1,4 +1,4 @@ A crate which contains primitives that are useful for implementation that uses staking approaches in general. Definitions related to sessions, slashing, etc go here. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/state-machine/README.md b/substrate/primitives/state-machine/README.md index aa244da62d50..91d706f860e1 100644 --- a/substrate/primitives/state-machine/README.md +++ b/substrate/primitives/state-machine/README.md @@ -1,3 +1,3 @@ Substrate state machine implementation. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/statement-store/README.md b/substrate/primitives/statement-store/README.md index 2cde0d669eef..f224f6ce4319 100644 --- a/substrate/primitives/statement-store/README.md +++ b/substrate/primitives/statement-store/README.md @@ -1,18 +1,35 @@ +# Statement store + Statement store is an off-chain data-store for signed statements accessible via RPC and OCW. -Nodes hold a number of statements with a proof of authenticity owing to an account ID. OCWs can place items in the data-store (with valid signatures) for any accounts whose keys they control. Users can also submit pre-signed statements via RPC. Statements can also be submitted from on-chain logic through an on-chain event. +Nodes hold a number of statements with a proof of authenticity owing to an account ID. OCWs can place items in the +data-store (with valid signatures) for any accounts whose keys they control. Users can also submit pre-signed statements +via RPC. Statements can also be submitted from on-chain logic through an on-chain event. -A new system event `NewStatement` is added to the runtime. This event allows any account on-chain to declare that they want to make a statement for the store. Within the node store and for broadcasting, the statement would be accompanied with the hash of the block and index of the event within it, essentially taking the place of a real signature. +A new system event `NewStatement` is added to the runtime. This event allows any account on-chain to declare that they +want to make a statement for the store. Within the node store and for broadcasting, the statement would be accompanied +with the hash of the block and index of the event within it, essentially taking the place of a real signature. -Statements comprise an optional proof of authenticity (e.g. a signature) and a number of fields. For statements without a proof, nodes would gossip statements randomly with a rate-limiter to minimise the chance of being overrun by a misbehaving node. These will generally be disregarded by nodes unless they are gossiped by several different peers or if a peer pays for it somehow (e.g. gossiping something valuable). +Statements comprise an optional proof of authenticity (e.g. a signature) and a number of fields. For statements without +a proof, nodes would gossip statements randomly with a rate-limiter to minimise the chance of being overrun by a +misbehaving node. These will generally be disregarded by nodes unless they are gossiped by several different peers or if +a peer pays for it somehow (e.g. gossiping something valuable). -Each field is effectively a key/value pair. Fields must be sorted and the same field type may not be repeated. Depending on which keys are present, clients may index the message for ease of retrieval. +Each field is effectively a key/value pair. Fields must be sorted and the same field type may not be repeated. Depending +on which keys are present, clients may index the message for ease of retrieval. Formally, `Statement` is equivalent to the type `Vec` and `Field` is the SCALE-encoded enumeration: -- 0: `AuthenticityProof(Proof)`: The signature of the message. For cryptography where the public key cannot be derived from the signature together with the message data, then this will also include the signer's public key. The message data is all fields of the messages fields except the signature concatenated together *without the length prefix that a `Vec` would usually imply*. This is so that the signature can be derived without needing to re-encode the statement. -- 1: `DecryptionKey([u8; 32])`: The decryption key identifier which should be used to decrypt the statement's data. In the absence of this field `Data` should be treated as not encrypted. -- 2: `Priority(u32)`: Priority specifier. Higher priority statements should be kept around at the cost of lower priority statements if multiple statements from the same sender are competing for persistence or transport. Nodes should disregard when considering unsigned statements. -- 3: `Channel([u8; 32])`: The channel identifier. Only one message of a given channel should be retained at once (the one of highest priority). Nodes should disregard when considering unsigned statements. +- 0: `AuthenticityProof(Proof)`: The signature of the message. For cryptography where the public key cannot be derived + from the signature together with the message data, then this will also include the signer's public key. The message + data is all fields of the messages fields except the signature concatenated together *without the length prefix that a + `Vec` would usually imply*. This is so that the signature can be derived without needing to re-encode the statement. +- 1: `DecryptionKey([u8; 32])`: The decryption key identifier which should be used to decrypt the statement's data. In + the absence of this field `Data` should be treated as not encrypted. +- 2: `Priority(u32)`: Priority specifier. Higher priority statements should be kept around at the cost of lower priority + statements if multiple statements from the same sender are competing for persistence or transport. Nodes should + disregard when considering unsigned statements. +- 3: `Channel([u8; 32])`: The channel identifier. Only one message of a given channel should be retained at once (the + one of highest priority). Nodes should disregard when considering unsigned statements. - 4: `Topic1([u8; 32]))`: First topic identifier. - 5: `Topic2([u8; 32]))`: Second topic identifier. - 6: `Topic3([u8; 32]))`: Third topic identifier. @@ -25,7 +42,7 @@ Formally, `Statement` is equivalent to the type `Vec` and `Field` is the - 2: `Secp256k1Ecdsa { signature: [u8; 65], signer: [u8; 33] )` - 3: `OnChain { who: [u8; 32], block_hash: [u8; 32], event_index: u64 }` -### Potential uses +## Potential uses Potential use-cases are various and include: - ring-signature aggregation; diff --git a/substrate/primitives/std/README.md b/substrate/primitives/std/README.md index 6dddd8fbbdd9..e186ccecf7b9 100644 --- a/substrate/primitives/std/README.md +++ b/substrate/primitives/std/README.md @@ -1,4 +1,4 @@ Lowest-abstraction level for the Substrate runtime: just exports useful primitives from std or client/alloc to be used with any code that depends on the runtime. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/storage/README.md b/substrate/primitives/storage/README.md index c33144fc4f66..ac922f139ffe 100644 --- a/substrate/primitives/storage/README.md +++ b/substrate/primitives/storage/README.md @@ -1,3 +1,3 @@ Primitive types for storage related stuff. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/timestamp/README.md b/substrate/primitives/timestamp/README.md index a61a776912c9..41649cdfc8e2 100644 --- a/substrate/primitives/timestamp/README.md +++ b/substrate/primitives/timestamp/README.md @@ -1,3 +1,3 @@ Substrate core types and inherents for timestamps. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/tracing/README.md b/substrate/primitives/tracing/README.md index d66bb90016c7..4582a34d918e 100644 --- a/substrate/primitives/tracing/README.md +++ b/substrate/primitives/tracing/README.md @@ -12,4 +12,4 @@ Additionally, we have a const: `WASM_TRACE_IDENTIFIER`, which holds a span name to signal that the 'actual' span name and target should be retrieved instead from the associated Fields mentioned above. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/transaction-pool/README.md b/substrate/primitives/transaction-pool/README.md index 417565ebfce0..209d23e9980f 100644 --- a/substrate/primitives/transaction-pool/README.md +++ b/substrate/primitives/transaction-pool/README.md @@ -1,3 +1,3 @@ Transaction pool primitives types & Runtime API. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/trie/README.md b/substrate/primitives/trie/README.md index 634ba4bdead2..e82080da5ff8 100644 --- a/substrate/primitives/trie/README.md +++ b/substrate/primitives/trie/README.md @@ -1,3 +1,3 @@ Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie"). -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/version/README.md b/substrate/primitives/version/README.md index 84f0ae57d9db..8decaaa85f8c 100644 --- a/substrate/primitives/version/README.md +++ b/substrate/primitives/version/README.md @@ -1,3 +1,3 @@ Version module for the Substrate runtime; Provides a function that returns the runtime version. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/primitives/wasm-interface/README.md b/substrate/primitives/wasm-interface/README.md index 7e6c46581ae4..2e584adeb83c 100644 --- a/substrate/primitives/wasm-interface/README.md +++ b/substrate/primitives/wasm-interface/README.md @@ -1,3 +1,3 @@ Types and traits for interfacing between the host and the wasm runtime. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/scripts/ci/docker/subkey.Dockerfile.README.md b/substrate/scripts/ci/docker/subkey.Dockerfile.README.md index 30a5e8212150..fe3359d01e81 100644 --- a/substrate/scripts/ci/docker/subkey.Dockerfile.README.md +++ b/substrate/scripts/ci/docker/subkey.Dockerfile.README.md @@ -1,8 +1,11 @@ -# The `subkey` program is a key management utility for Substrate-based blockchains. You can use the `subkey` program to perform the following tasks: +# Subkey + +The `subkey` program is a key management utility for Substrate-based blockchains. You can use the `subkey` program to +perform the following tasks * Generate and inspect cryptographically-secure public and private key pairs. * Restore keys from secret phrases and raw seeds. * Sign and verify signatures on messages. * Sign and verify signatures for encoded transactions. * Derive hierarchical deterministic child key pairs. -* [Documentation](https://docs.substrate.io/reference/command-line-tools/subkey/) \ No newline at end of file +* [Documentation](https://docs.substrate.io/reference/command-line-tools/subkey/) diff --git a/substrate/scripts/ci/docker/substrate.Dockerfile.README.md b/substrate/scripts/ci/docker/substrate.Dockerfile.README.md index 557fd8f835d7..9e97701e92f6 100644 --- a/substrate/scripts/ci/docker/substrate.Dockerfile.README.md +++ b/substrate/scripts/ci/docker/substrate.Dockerfile.README.md @@ -1 +1 @@ -# Substrate Docker Image \ No newline at end of file +# Substrate Docker Image diff --git a/substrate/scripts/ci/monitoring/grafana-dashboards/README_dashboard.md b/substrate/scripts/ci/monitoring/grafana-dashboards/README_dashboard.md index 50f54a107e93..2267cfbefb7f 100644 --- a/substrate/scripts/ci/monitoring/grafana-dashboards/README_dashboard.md +++ b/substrate/scripts/ci/monitoring/grafana-dashboards/README_dashboard.md @@ -1,4 +1,4 @@ -## Substrate Dashboard +# Substrate Dashboard Shared templated Grafana dashboards. diff --git a/substrate/utils/build-script-utils/README.md b/substrate/utils/build-script-utils/README.md index 1c184f67326e..f857d04710b1 100644 --- a/substrate/utils/build-script-utils/README.md +++ b/substrate/utils/build-script-utils/README.md @@ -1,3 +1,3 @@ Crate with utility functions for `build.rs` scripts. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/utils/fork-tree/README.md b/substrate/utils/fork-tree/README.md index fef7db57f68f..ba573dfff41d 100644 --- a/substrate/utils/fork-tree/README.md +++ b/substrate/utils/fork-tree/README.md @@ -1,4 +1,4 @@ Utility library for managing tree-like ordered data with logic for pruning the tree while finalizing nodes. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/utils/frame/benchmarking-cli/README.md b/substrate/utils/frame/benchmarking-cli/README.md index e6a48b61fd22..27673ea9580d 100644 --- a/substrate/utils/frame/benchmarking-cli/README.md +++ b/substrate/utils/frame/benchmarking-cli/README.md @@ -1,10 +1,11 @@ # The Benchmarking CLI -This crate contains commands to benchmark various aspects of Substrate and the hardware. -All commands are exposed by the Substrate node but can be exposed by any Substrate client. -The goal is to have a comprehensive suite of benchmarks that cover all aspects of Substrate and the hardware that its running on. +This crate contains commands to benchmark various aspects of Substrate and the hardware. +All commands are exposed by the Substrate node but can be exposed by any Substrate client. +The goal is to have a comprehensive suite of benchmarks that cover all aspects of Substrate and the hardware that its +running on. -Invoking the root benchmark command prints a help menu: +Invoking the root benchmark command prints a help menu: ```sh $ cargo run --profile=production -- benchmark @@ -25,10 +26,12 @@ SUBCOMMANDS: storage Benchmark the storage speed of a chain snapshot ``` -All examples use the `production` profile for correctness which makes the compilation *very* slow; for testing you can use `--release`. -For the final results the `production` profile and reference hardware should be used, otherwise the results are not comparable. +All examples use the `production` profile for correctness which makes the compilation *very* slow; for testing you can +use `--release`. +For the final results the `production` profile and reference hardware should be used, otherwise the results are not +comparable. -The sub-commands are explained in depth here: +The sub-commands are explained in depth here: - [block] Compare the weight of a historic block to its actual resource usage - [machine] Gauges the speed of the hardware - [overhead] Creates weight files for the *Block*- and *Extrinsic*-base weights diff --git a/substrate/utils/frame/benchmarking-cli/src/block/README.md b/substrate/utils/frame/benchmarking-cli/src/block/README.md index 7e99f0df9d43..e03f60e76276 100644 --- a/substrate/utils/frame/benchmarking-cli/src/block/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/block/README.md @@ -1,65 +1,62 @@ # The `benchmark block` command -The whole benchmarking process in Substrate aims to predict the resource usage of an unexecuted block. -This command measures how accurate this prediction was by executing a block and comparing the predicted weight to its actual resource usage. -It can be used to measure the accuracy of the pallet benchmarking. +The whole benchmarking process in Substrate aims to predict the resource usage of an unexecuted block. This command +measures how accurate this prediction was by executing a block and comparing the predicted weight to its actual resource +usage. It can be used to measure the accuracy of the pallet benchmarking. -In the following it will be explained once for Polkadot and once for Substrate. +In the following it will be explained once for Polkadot and once for Substrate. ## Polkadot # 1 (Also works for Kusama, Westend and Rococo) -Suppose you either have a synced Polkadot node or downloaded a snapshot from [Polkachu]. -This example uses a pruned ParityDB snapshot from the 2022-4-19 with the last block being 9939462. -For pruned snapshots you need to know the number of the last block (to be improved [here]). -Pruned snapshots normally store the last 256 blocks, archive nodes can use any block range. +Suppose you either have a synced Polkadot node or downloaded a snapshot from [Polkachu]. This example uses a pruned +ParityDB snapshot from the 2022-4-19 with the last block being 9939462. For pruned snapshots you need to know the number +of the last block (to be improved [here]). Pruned snapshots normally store the last 256 blocks, archive nodes can use +any block range. -In this example we will benchmark just the last 10 blocks: +In this example we will benchmark just the last 10 blocks: ```sh cargo run --profile=production -- benchmark block --from 9939453 --to 9939462 --db paritydb ``` Output: ```pre -Block 9939453 with 2 tx used 4.57% of its weight ( 26,458,801 of 579,047,053 ns) -Block 9939454 with 3 tx used 4.80% of its weight ( 28,335,826 of 590,414,831 ns) -Block 9939455 with 2 tx used 4.76% of its weight ( 27,889,567 of 586,484,595 ns) -Block 9939456 with 2 tx used 4.65% of its weight ( 27,101,306 of 582,789,723 ns) -Block 9939457 with 2 tx used 4.62% of its weight ( 26,908,882 of 582,789,723 ns) -Block 9939458 with 2 tx used 4.78% of its weight ( 28,211,440 of 590,179,467 ns) -Block 9939459 with 4 tx used 4.78% of its weight ( 27,866,077 of 583,260,451 ns) -Block 9939460 with 3 tx used 4.72% of its weight ( 27,845,836 of 590,462,629 ns) -Block 9939461 with 2 tx used 4.58% of its weight ( 26,685,119 of 582,789,723 ns) -Block 9939462 with 2 tx used 4.60% of its weight ( 26,840,938 of 583,697,101 ns) +Block 9939453 with 2 tx used 4.57% of its weight ( 26,458,801 of 579,047,053 ns) +Block 9939454 with 3 tx used 4.80% of its weight ( 28,335,826 of 590,414,831 ns) +Block 9939455 with 2 tx used 4.76% of its weight ( 27,889,567 of 586,484,595 ns) +Block 9939456 with 2 tx used 4.65% of its weight ( 27,101,306 of 582,789,723 ns) +Block 9939457 with 2 tx used 4.62% of its weight ( 26,908,882 of 582,789,723 ns) +Block 9939458 with 2 tx used 4.78% of its weight ( 28,211,440 of 590,179,467 ns) +Block 9939459 with 4 tx used 4.78% of its weight ( 27,866,077 of 583,260,451 ns) +Block 9939460 with 3 tx used 4.72% of its weight ( 27,845,836 of 590,462,629 ns) +Block 9939461 with 2 tx used 4.58% of its weight ( 26,685,119 of 582,789,723 ns) +Block 9939462 with 2 tx used 4.60% of its weight ( 26,840,938 of 583,697,101 ns) ``` ### Output Interpretation (Only results from reference hardware are relevant) -Each block is executed multiple times and the results are averaged. -The percent number is the interesting part and indicates how much weight was used as compared to how much was predicted. -The closer to 100% this is without exceeding 100%, the better. -If it exceeds 100%, the block is marked with "**OVER WEIGHT!**" to easier spot them. This is not good since then the benchmarking under-estimated the weight. -This would mean that an honest validator would possibly not be able to keep up with importing blocks since users did not pay for enough weight. -If that happens the validator could lag behind the chain and get slashed for missing deadlines. -It is therefore important to investigate any overweight blocks. +Each block is executed multiple times and the results are averaged. The percent number is the interesting part and +indicates how much weight was used as compared to how much was predicted. The closer to 100% this is without exceeding +100%, the better. If it exceeds 100%, the block is marked with "**OVER WEIGHT!**" to easier spot them. This is not good +since then the benchmarking under-estimated the weight. This would mean that an honest validator would possibly not be +able to keep up with importing blocks since users did not pay for enough weight. If that happens the validator could lag +behind the chain and get slashed for missing deadlines. It is therefore important to investigate any overweight blocks. -In this example you can see an unexpected result; only < 5% of the weight was used! -The measured blocks can be executed much faster than predicted. -This means that the benchmarking process massively over-estimated the execution time. -Since they are off by so much, it is an issue [polkadot#5192]. +In this example you can see an unexpected result; only < 5% of the weight was used! The measured blocks can be executed +much faster than predicted. This means that the benchmarking process massively over-estimated the execution time. Since +they are off by so much, it is an issue [`polkadot#5192`]. The ideal range for these results would be 85-100%. ## Polkadot # 2 -Let's take a more interesting example where the blocks use more of their predicted weight. -Every day when validators pay out rewards, the blocks are nearly full. -Using an archive node here is the easiest. +Let's take a more interesting example where the blocks use more of their predicted weight. Every day when validators pay +out rewards, the blocks are nearly full. Using an archive node here is the easiest. -The Polkadot blocks TODO-TODO for example contain large batch transactions for staking payout. +The Polkadot blocks TODO-TODO for example contain large batch transactions for staking payout. ```sh cargo run --profile=production -- benchmark block --from TODO --to TODO --db paritydb @@ -71,21 +68,20 @@ TODO ## Substrate -It is also possible to try the procedure in Substrate, although it's a bit boring. +It is also possible to try the procedure in Substrate, although it's a bit boring. -First you need to create some blocks with either a local or dev chain. -This example will use the standard development spec. -Pick a non existing directory where the chain data will be stored, eg `/tmp/dev`. +First you need to create some blocks with either a local or dev chain. This example will use the standard development +spec. Pick a non existing directory where the chain data will be stored, eg `/tmp/dev`. ```sh cargo run --profile=production -- --dev -d /tmp/dev ``` -You should see after some seconds that it started to produce blocks: +You should see after some seconds that it started to produce blocks: ```pre … ✨ Imported #1 (0x801d…9189) … ``` -You can now kill the node with `Ctrl+C`. Then measure how long it takes to execute these blocks: +You can now kill the node with `Ctrl+C`. Then measure how long it takes to execute these blocks: ```sh cargo run --profile=production -- benchmark block --from 1 --to 1 --dev -d /tmp/dev --pruning archive ``` @@ -94,9 +90,8 @@ This will benchmark the first block. If you killed the node at a later point, yo Block 1 with 1 tx used 72.04% of its weight ( 4,945,664 of 6,864,702 ns) ``` -In this example the block used ~72% of its weight. -The benchmarking therefore over-estimated the effort to execute the block. -Since this block is empty, its not very interesting. +In this example the block used ~72% of its weight. The benchmarking therefore over-estimated the effort to execute the +block. Since this block is empty, its not very interesting. ## Arguments diff --git a/substrate/utils/frame/benchmarking-cli/src/machine/README.md b/substrate/utils/frame/benchmarking-cli/src/machine/README.md index f22a8ea54b81..d3c9a0ec8406 100644 --- a/substrate/utils/frame/benchmarking-cli/src/machine/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/machine/README.md @@ -1,17 +1,17 @@ # The `benchmark machine` command -Different Substrate chains can have different hardware requirements. -It is therefore important to be able to quickly gauge if a piece of hardware fits a chains' requirements. -The `benchmark machine` command archives this by measuring key metrics and making them comparable. +Different Substrate chains can have different hardware requirements. +It is therefore important to be able to quickly gauge if a piece of hardware fits a chains' requirements. +The `benchmark machine` command archives this by measuring key metrics and making them comparable. -Invoking the command looks like this: +Invoking the command looks like this: ```sh cargo run --profile=production -- benchmark machine --dev ``` ## Output -The output on reference hardware: +The output on reference hardware: ```pre +----------+----------------+---------------+--------------+-------------------+ @@ -29,37 +29,49 @@ The output on reference hardware: +----------+----------------+---------------+--------------+-------------------+ ``` -The *score* is the average result of each benchmark. It always adheres to "higher is better". +The *score* is the average result of each benchmark. It always adheres to "higher is better". -The *category* indicate which part of the hardware was benchmarked: +The *category* indicate which part of the hardware was benchmarked: - **CPU** Processor intensive task - **Memory** RAM intensive task - **Disk** Hard drive intensive task -The *function* is the concrete benchmark that was run: -- **BLAKE2-256** The throughput of the [Blake2-256] cryptographic hashing function with 32 KiB input. The [blake2_256 function] is used in many places in Substrate. The throughput of a hash function strongly depends on the input size, therefore we settled to use a fixed input size for comparable results. -- **SR25519 Verify** Sr25519 is an optimized version of the [Curve25519] signature scheme. Signature verification is used by Substrate when verifying extrinsics and blocks. +The *function* is the concrete benchmark that was run: +- **BLAKE2-256** The throughput of the [Blake2-256] cryptographic hashing function with 32 KiB input. The [blake2_256 + function] is used in many places in Substrate. The throughput of a hash function strongly depends on the input size, + therefore we settled to use a fixed input size for comparable results. +- **SR25519 Verify** Sr25519 is an optimized version of the [Curve25519] signature scheme. Signature verification is + used by Substrate when verifying extrinsics and blocks. - **Copy** The throughput of copying memory from one place in the RAM to another. -- **Seq Write** The throughput of writing data to the storage location sequentially. It is important that the same disk is used that will later-on be used to store the chain data. -- **Rnd Write** The throughput of writing data to the storage location in a random order. This is normally much slower than the sequential write. +- **Seq Write** The throughput of writing data to the storage location sequentially. It is important that the same disk + is used that will later-on be used to store the chain data. +- **Rnd Write** The throughput of writing data to the storage location in a random order. This is normally much slower + than the sequential write. -The *score* needs to reach the *minimum* in order to pass the benchmark. This can be reduced with the `--tolerance` flag. +The *score* needs to reach the *minimum* in order to pass the benchmark. This can be reduced with the `--tolerance` +flag. -The *result* indicated if a specific benchmark was passed by the machine or not. The percent number is the relative score reached to the *minimum* that is needed. The `--tolerance` flag is taken into account for this decision. For example a benchmark that passes even with 95% since the *tolerance* was set to 10% would look like this: `✅ Pass ( 95.0 %)`. +The *result* indicated if a specific benchmark was passed by the machine or not. The percent number is the relative +score reached to the *minimum* that is needed. The `--tolerance` flag is taken into account for this decision. For +example a benchmark that passes even with 95% since the *tolerance* was set to 10% would look like this: `✅ Pass ( 95.0 +%)`. ## Interpretation -Ideally all results show a `Pass` and the program exits with code 0. Currently some of the benchmarks can fail even on reference hardware; they are still being improved to make them more deterministic. -Make sure to run nothing else on the machine when benchmarking it. +Ideally all results show a `Pass` and the program exits with code 0. Currently some of the benchmarks can fail even on +reference hardware; they are still being improved to make them more deterministic. +Make sure to run nothing else on the machine when benchmarking it. You can re-run them multiple times to get more reliable results. ## Arguments -- `--tolerance` A percent number to reduce the *minimum* requirement. This should be used to ignore outliers of the benchmarks. The default value is 10%. +- `--tolerance` A percent number to reduce the *minimum* requirement. This should be used to ignore outliers of the + benchmarks. The default value is 10%. - `--verify-duration` How long the verification benchmark should run. - `--disk-duration` How long the *read* and *write* benchmarks should run each. - `--allow-fail` Always exit the program with code 0. -- `--chain` / `--dev` Specify the chain config to use. This will be used to compare the results with the requirements of the chain (WIP). +- `--chain` / `--dev` Specify the chain config to use. This will be used to compare the results with the requirements of + the chain (WIP). - [`--base-path`] License: Apache-2.0 diff --git a/substrate/utils/frame/benchmarking-cli/src/overhead/README.md b/substrate/utils/frame/benchmarking-cli/src/overhead/README.md index 390bc09e4170..648908010ba0 100644 --- a/substrate/utils/frame/benchmarking-cli/src/overhead/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/overhead/README.md @@ -1,21 +1,21 @@ # The `benchmark overhead` command -Each time an extrinsic or a block is executed, a fixed weight is charged as "execution overhead". -This is necessary since the weight that is calculated by the pallet benchmarks does not include this overhead. -The exact overhead to can vary per Substrate chain and needs to be calculated per chain. -This command calculates the exact values of these overhead weights for any Substrate chain that supports it. +Each time an extrinsic or a block is executed, a fixed weight is charged as "execution overhead". This is necessary +since the weight that is calculated by the pallet benchmarks does not include this overhead. The exact overhead to can +vary per Substrate chain and needs to be calculated per chain. This command calculates the exact values of these +overhead weights for any Substrate chain that supports it. ## How does it work? -The benchmark consists of two parts; the [`BlockExecutionWeight`] and the [`ExtrinsicBaseWeight`]. -Both are executed sequentially when invoking the command. +The benchmark consists of two parts; the [`BlockExecutionWeight`] and the [`ExtrinsicBaseWeight`]. Both are executed +sequentially when invoking the command. ## BlockExecutionWeight -The block execution weight is defined as the weight that it takes to execute an *empty block*. -It is measured by constructing an empty block and measuring its executing time. -The result are written to a `block_weights.rs` file which is created from a template. -The file will contain the concrete weight value and various statistics about the measurements. For example: +The block execution weight is defined as the weight that it takes to execute an *empty block*. It is measured by +constructing an empty block and measuring its executing time. The result are written to a `block_weights.rs` file which +is created from a template. The file will contain the concrete weight value and various statistics about the +measurements. For example: ```rust /// Time to execute an empty block. /// Calculated by multiplying the *Average* with `1` and adding `0`. @@ -34,16 +34,17 @@ pub const BlockExecutionWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(3_532_484), 0); ``` -In this example it takes 3.5 ms to execute an empty block. That means that it always takes at least 3.5 ms to execute *any* block. -This constant weight is therefore added to each block to ensure that Substrate budgets enough time to execute it. +In this example it takes 3.5 ms to execute an empty block. That means that it always takes at least 3.5 ms to execute +*any* block. This constant weight is therefore added to each block to ensure that Substrate budgets enough time to +execute it. ## ExtrinsicBaseWeight -The extrinsic base weight is defined as the weight that it takes to execute an *empty* extrinsic. -An *empty* extrinsic is also called a *NO-OP*. It does nothing and is the equivalent to the empty block form above. -The benchmark now constructs a block which is filled with only NO-OP extrinsics. -This block is then executed many times and the weights are measured. -The result is divided by the number of extrinsics in that block and the results are written to `extrinsic_weights.rs`. +The extrinsic base weight is defined as the weight that it takes to execute an *empty* extrinsic. An *empty* extrinsic +is also called a *NO-OP*. It does nothing and is the equivalent to the empty block form above. The benchmark now +constructs a block which is filled with only NO-OP extrinsics. This block is then executed many times and the weights +are measured. The result is divided by the number of extrinsics in that block and the results are written to +`extrinsic_weights.rs`. The relevant section in the output file looks like this: ```rust @@ -64,8 +65,9 @@ pub const ExtrinsicBaseWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(67_745), 0); ``` -In this example it takes 67.7 µs to execute a NO-OP extrinsic. That means that it always takes at least 67.7 µs to execute *any* extrinsic. -This constant weight is therefore added to each extrinsic to ensure that Substrate budgets enough time to execute it. +In this example it takes 67.7 µs to execute a NO-OP extrinsic. That means that it always takes at least 67.7 µs to +execute *any* extrinsic. This constant weight is therefore added to each extrinsic to ensure that Substrate budgets +enough time to execute it. ## Invocation @@ -106,15 +108,18 @@ The complete command for Polkadot looks like this: cargo run --profile=production -- benchmark overhead --chain=polkadot-dev --wasm-execution=compiled --weight-path=runtime/polkadot/constants/src/weights/ ``` -This will overwrite the the [block_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/block_weights.rs) and [extrinsic_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/extrinsic_weights.rs) files in the Polkadot runtime directory. -You can try the same for *Rococo* and to see that the results slightly differ. +This will overwrite the the +[block_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/block_weights.rs) +and +[extrinsic_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/extrinsic_weights.rs) +files in the Polkadot runtime directory. You can try the same for *Rococo* and to see that the results slightly differ. 👉 It is paramount to use `--profile=production` and `--wasm-execution=compiled` as the results are otherwise useless. ## Output Interpretation -Lower is better. The less weight the execution overhead needs, the better. -Since the weights of the overhead is charged per extrinsic and per block, a larger weight results in less extrinsics per block. -Minimizing this is important to have a large transaction throughput. +Lower is better. The less weight the execution overhead needs, the better. Since the weights of the overhead is charged +per extrinsic and per block, a larger weight results in less extrinsics per block. Minimizing this is important to have +a large transaction throughput. ## Arguments @@ -132,7 +137,10 @@ Minimizing this is important to have a large transaction throughput. License: Apache-2.0 -[`ExtrinsicBaseWeight`]: https://github.com/paritytech/substrate/blob/580ebae17fa30082604f1c9720f6f4a1cfe95b50/frame/support/src/weights/extrinsic_weights.rs#L26 -[`BlockExecutionWeight`]: https://github.com/paritytech/substrate/blob/580ebae17fa30082604f1c9720f6f4a1cfe95b50/frame/support/src/weights/block_weights.rs#L26 +[`ExtrinsicBaseWeight`]: + https://github.com/paritytech/substrate/blob/580ebae17fa30082604f1c9720f6f4a1cfe95b50/frame/support/src/weights/extrinsic_weights.rs#L26 +[`BlockExecutionWeight`]: + https://github.com/paritytech/substrate/blob/580ebae17fa30082604f1c9720f6f4a1cfe95b50/frame/support/src/weights/block_weights.rs#L26 -[System::Remark]: https://github.com/paritytech/substrate/blob/580ebae17fa30082604f1c9720f6f4a1cfe95b50/frame/system/src/lib.rs#L382 +[System::Remark]: + https://github.com/paritytech/substrate/blob/580ebae17fa30082604f1c9720f6f4a1cfe95b50/frame/system/src/lib.rs#L382 diff --git a/substrate/utils/frame/benchmarking-cli/src/shared/README.md b/substrate/utils/frame/benchmarking-cli/src/shared/README.md index 08e25b0e08f7..0b1128bca3a6 100644 --- a/substrate/utils/frame/benchmarking-cli/src/shared/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/shared/README.md @@ -10,7 +10,10 @@ Contains code that is shared among multiple sub-commands. - `--weight-path` Set the file or directory to write the weight files to. - `--db` The database backend to use. This depends on your snapshot. - `--pruning` Set the pruning mode of the node. Some benchmarks require you to set this to `archive`. -- `--base-path` The location on the disk that should be used for the benchmarks. You can try this on different disks or even on a mounted RAM-disk. It is important to use the same location that will later-on be used to store the chain data to get the correct results. -- `--header` Optional file header which will be prepended to the weight output file. Can be used for adding LICENSE headers. +- `--base-path` The location on the disk that should be used for the benchmarks. You can try this on different disks or + even on a mounted RAM-disk. It is important to use the same location that will later-on be used to store the chain + data to get the correct results. +- `--header` Optional file header which will be prepended to the weight output file. Can be used for adding LICENSE + headers. License: Apache-2.0 diff --git a/substrate/utils/frame/benchmarking-cli/src/storage/README.md b/substrate/utils/frame/benchmarking-cli/src/storage/README.md index f61b7ba1bddd..95c83d2edbc5 100644 --- a/substrate/utils/frame/benchmarking-cli/src/storage/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/storage/README.md @@ -1,17 +1,19 @@ # The `benchmark storage` command -The cost of storage operations in a Substrate chain depends on the current chain state. -It is therefore important to regularly update these weights as the chain grows. -This sub-command measures the cost of storage operations for a concrete snapshot. +The cost of storage operations in a Substrate chain depends on the current chain state. +It is therefore important to regularly update these weights as the chain grows. +This sub-command measures the cost of storage operations for a concrete snapshot. -For the Substrate node it looks like this (for debugging you can use `--release`): +For the Substrate node it looks like this (for debugging you can use `--release`): ```sh cargo run --profile=production -- benchmark storage --dev --state-version=1 ``` -Running the command on Substrate itself is not verify meaningful, since the genesis state of the `--dev` chain spec is used. +Running the command on Substrate itself is not verify meaningful, since the genesis state of the `--dev` chain spec is +used. -The output for the Polkadot client with a recent chain snapshot will give you a better impression. A recent snapshot can be downloaded from [Polkachu]. +The output for the Polkadot client with a recent chain snapshot will give you a better impression. A recent snapshot can +be downloaded from [Polkachu]. Then run (remove the `--db=paritydb` if you have a RocksDB snapshot): ```sh cargo run --profile=production -- benchmark storage --dev --state-version=0 --db=paritydb --weight-path runtime/polkadot/constants/src/weights @@ -20,8 +22,8 @@ cargo run --profile=production -- benchmark storage --dev --state-version=0 --db This takes a while since reads and writes all keys from the snapshot: ```pre # The 'read' benchmark -Preparing keys from block BlockId::Number(9939462) -Reading 1379083 keys +Preparing keys from block BlockId::Number(9939462) +Reading 1379083 keys Time summary [ns]: Total: 19668919930 Min: 6450, Max: 1217259 @@ -31,11 +33,11 @@ Value size summary: Total: 265702275 Min: 1, Max: 1381859 Average: 192, Median: 80, Stddev: 3427.53 -Percentiles 99th, 95th, 75th: 3368, 383, 80 +Percentiles 99th, 95th, 75th: 3368, 383, 80 # The 'write' benchmark -Preparing keys from block BlockId::Number(9939462) -Writing 1379083 keys +Preparing keys from block BlockId::Number(9939462) +Writing 1379083 keys Time summary [ns]: Total: 98393809781 Min: 12969, Max: 13282577 @@ -49,12 +51,13 @@ Percentiles 99th, 95th, 75th: 3368, 383, 80 Writing weights to "paritydb_weights.rs" ``` -You will see that the [paritydb_weights.rs] files was modified and now contains new weights. -The exact command for Polkadot can be seen at the top of the file. -This uses the most recent block from your snapshot which is printed at the top. -The value size summary tells us that the pruned Polkadot chain state is ~253 MiB in size. -Reading a value on average takes (in this examples) 14.3 µs and writing 71.3 µs. -The interesting part in the generated weight file tells us the weight constants and some statistics about the measurements: +You will see that the [paritydb_weights.rs] files was modified and now contains new weights. The exact command for +Polkadot can be seen at the top of the file. +This uses the most recent block from your snapshot which is printed at the top. +The value size summary tells us that the pruned Polkadot chain state is ~253 MiB in size. +Reading a value on average takes (in this examples) 14.3 µs and writing 71.3 µs. +The interesting part in the generated weight file tells us the weight constants and some statistics about the +measurements: ```rust /// Time to read one storage item. /// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`. @@ -90,7 +93,8 @@ write: 71_347 * constants::WEIGHT_REF_TIME_PER_NANOS, ## Arguments - `--db` Specify which database backend to use. This greatly influences the results. -- `--state-version` Set the version of the state encoding that this snapshot uses. Should be set to `1` for Substrate `--dev` and `0` for Polkadot et al. Using the wrong version can corrupt the snapshot. +- `--state-version` Set the version of the state encoding that this snapshot uses. Should be set to `1` for Substrate + `--dev` and `0` for Polkadot et al. Using the wrong version can corrupt the snapshot. - [`--mul`](../shared/README.md#arguments) - [`--add`](../shared/README.md#arguments) - [`--metric`](../shared/README.md#arguments) @@ -103,4 +107,5 @@ License: Apache-2.0 [Polkachu]: https://polkachu.com/snapshots -[paritydb_weights.rs]: https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/paritydb_weights.rs#L60 +[paritydb_weights.rs]: + https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/paritydb_weights.rs#L60 diff --git a/substrate/utils/frame/frame-utilities-cli/README.md b/substrate/utils/frame/frame-utilities-cli/README.md index b1e4f869af75..54467a3ad770 100644 --- a/substrate/utils/frame/frame-utilities-cli/README.md +++ b/substrate/utils/frame/frame-utilities-cli/README.md @@ -1,3 +1,3 @@ frame-system CLI utilities -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/utils/frame/rpc/support/README.md b/substrate/utils/frame/rpc/support/README.md index ca5750612931..72e39b761183 100644 --- a/substrate/utils/frame/rpc/support/README.md +++ b/substrate/utils/frame/rpc/support/README.md @@ -1,4 +1,4 @@ Combines [sc_rpc_api::state::StateClient] with [frame_support::storage::generator] traits to provide strongly typed chain state queries over rpc. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/utils/frame/rpc/system/README.md b/substrate/utils/frame/rpc/system/README.md index 38986983d93c..4eb4a74ceceb 100644 --- a/substrate/utils/frame/rpc/system/README.md +++ b/substrate/utils/frame/rpc/system/README.md @@ -1,3 +1,3 @@ System FRAME specific RPC methods. -License: Apache-2.0 \ No newline at end of file +License: Apache-2.0 diff --git a/substrate/utils/prometheus/README.md b/substrate/utils/prometheus/README.md index 9dd0882105c6..507b9b24fb7e 100644 --- a/substrate/utils/prometheus/README.md +++ b/substrate/utils/prometheus/README.md @@ -2,15 +2,19 @@ ## Introduction -[Prometheus](https://prometheus.io/) is one of the most widely used monitoring tools for managing highly available services supported by [Cloud Native Computing Foundation](https://www.cncf.io/). By providing Prometheus metrics in Substrate, node operators can easily adopt widely used display/alert tools such -as [Grafana](https://grafana.com/) and [Alertmanager](https://prometheus.io/docs/alerting/alertmanager/). Easy access to such monitoring tools will benefit parachain developers/operators and validators to have much higher availability of their services. +[Prometheus](https://prometheus.io/) is one of the most widely used monitoring tools for managing highly available +services supported by [Cloud Native Computing Foundation](https://www.cncf.io/). By providing Prometheus metrics in +Substrate, node operators can easily adopt widely used display/alert tools such as [Grafana](https://grafana.com/) and +[Alertmanager](https://prometheus.io/docs/alerting/alertmanager/). Easy access to such monitoring tools will benefit +parachain developers/operators and validators to have much higher availability of their services. Metrics will be served under `/metrics` on TCP port 9615 by default. ## Quick Start - + 1. From the root of the repository start Substrate `cargo run --release`. 2. In another terminal run `curl localhost:9615/metrics` to retrieve the metrics. -To learn how to configure Prometheus see the Prometheus [Getting Started](https://prometheus.io/docs/prometheus/latest/getting_started/) guide. \ No newline at end of file +To learn how to configure Prometheus see the Prometheus [Getting +Started](https://prometheus.io/docs/prometheus/latest/getting_started/) guide. diff --git a/substrate/utils/wasm-builder/README.md b/substrate/utils/wasm-builder/README.md index b1ccb1b35b10..db32f5cbc955 100644 --- a/substrate/utils/wasm-builder/README.md +++ b/substrate/utils/wasm-builder/README.md @@ -1,14 +1,15 @@ # Wasm builder is a utility for building a project as a Wasm binary -The Wasm builder is a tool that integrates the process of building the WASM binary of your project into the main -`cargo` build process. +The Wasm builder is a tool that integrates the process of building the WASM binary of your project into the main `cargo` +build process. ## Project setup A project that should be compiled as a Wasm binary needs to: 1. Add a `build.rs` file. -2. Add `wasm-builder` as dependency into `build-dependencies` (can be made optional and only enabled when `std` feature is used). +2. Add `wasm-builder` as dependency into `build-dependencies` (can be made optional and only enabled when `std` feature + is used). The `build.rs` file needs to contain the following code: @@ -35,43 +36,40 @@ As the final step, you need to add the following to your project: include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); ``` -This will include the generated Wasm binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. -The former is a compact Wasm binary and the latter is the Wasm binary as being generated by the compiler. -Both variables have `Option<&'static [u8]>` as type. +This will include the generated Wasm binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. The former is a +compact Wasm binary and the latter is the Wasm binary as being generated by the compiler. Both variables have +`Option<&'static [u8]>` as type. ### Features -Wasm builder supports to enable cargo features while building the Wasm binary. By default it will -enable all features in the wasm build that are enabled for the native build except the -`default` and `std` features. Besides that, wasm builder supports the special `runtime-wasm` -feature. This `runtime-wasm` feature will be enabled by the wasm builder when it compiles the -Wasm binary. If this feature is not present, it will not be enabled. +Wasm builder supports to enable cargo features while building the Wasm binary. By default it will enable all features in +the wasm build that are enabled for the native build except the `default` and `std` features. Besides that, wasm builder +supports the special `runtime-wasm` feature. This `runtime-wasm` feature will be enabled by the wasm builder when it +compiles the Wasm binary. If this feature is not present, it will not be enabled. ## Environment variables By using environment variables, you can configure which Wasm binaries are built and how: -- `SKIP_WASM_BUILD` - Skips building any Wasm binary. This is useful when only native should be recompiled. - If this is the first run and there doesn't exist a Wasm binary, this will set both - variables to `None`. -- `WASM_BUILD_TYPE` - Sets the build type for building Wasm binaries. Supported values are `release` or `debug`. - By default the build type is equal to the build type used by the main build. -- `FORCE_WASM_BUILD` - Can be set to force a Wasm build. On subsequent calls the value of the variable - needs to change. As wasm-builder instructs `cargo` to watch for file changes - this environment variable should only be required in certain circumstances. +- `SKIP_WASM_BUILD` - Skips building any Wasm binary. This is useful when only native should be recompiled. If this is + the first run and there doesn't exist a Wasm binary, this will set both variables to `None`. +- `WASM_BUILD_TYPE` - Sets the build type for building Wasm binaries. Supported values are `release` or `debug`. By + default the build type is equal to the build type used by the main build. +- `FORCE_WASM_BUILD` - Can be set to force a Wasm build. On subsequent calls the value of the variable needs to change. + As wasm-builder instructs `cargo` to watch for file changes this environment variable should only + be required in certain circumstances. - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. -- `WASM_TARGET_DIRECTORY` - Will copy any build Wasm binary to the given directory. The path needs - to be absolute. -- `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the Wasm binaries. The - format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`. -- `CARGO_NET_OFFLINE` - If `true`, `--offline` will be passed to all processes launched to prevent network access. Useful in offline environments. +- `WASM_TARGET_DIRECTORY` - Will copy any build Wasm binary to the given directory. The path needs to be absolute. +- `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the Wasm binaries. The format needs to be the same + as used by cargo, e.g. `nightly-2020-02-20`. +- `CARGO_NET_OFFLINE` - If `true`, `--offline` will be passed to all processes launched to prevent network access. + Useful in offline environments. -Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. -Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will -be `NODE_RUNTIME`. +Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. Where +`PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will be `NODE_RUNTIME`. -## Prerequisites: +## Prerequisites Wasm builder requires the following prerequisites for building the Wasm binary: @@ -81,9 +79,8 @@ or - rust stable and version at least 1.68.0 + `wasm32-unknown-unknown` toolchain -If a specific rust is installed with `rustup`, it is important that the wasm target is -installed as well. For example if installing the rust from 20.02.2020 using `rustup -install nightly-2020-02-20`, the wasm target needs to be installed as well `rustup target add -wasm32-unknown-unknown --toolchain nightly-2020-02-20`. +If a specific rust is installed with `rustup`, it is important that the wasm target is installed as well. For example if +installing the rust from 20.02.2020 using `rustup install nightly-2020-02-20`, the wasm target needs to be installed as +well `rustup target add wasm32-unknown-unknown --toolchain nightly-2020-02-20`. License: Apache-2.0 diff --git a/substrate/zombienet/0001-basic-warp-sync/README.md b/substrate/zombienet/0001-basic-warp-sync/README.md index 7550ca89236f..1f8bddee640c 100644 --- a/substrate/zombienet/0001-basic-warp-sync/README.md +++ b/substrate/zombienet/0001-basic-warp-sync/README.md @@ -35,8 +35,8 @@ Once the zombienet is stopped, the database snapshot (`{alice,bob}/data/chains/local_testnet/db/` dirs) was created using the following commands: ```bash -mkdir -p db-snapshot/{alice,bob}/data/chains/local_testnet/db/ -cp -r db-test-gen/alice/data/chains/local_testnet/db/full db-snapshot/alice/data/chains/local_testnet/db/ +mkdir -p db-snapshot/{alice,bob}/data/chains/local_testnet/db/ +cp -r db-test-gen/alice/data/chains/local_testnet/db/full db-snapshot/alice/data/chains/local_testnet/db/ cp -r db-test-gen/bob/data/chains/local_testnet/db/full db-snapshot/bob/data/chains/local_testnet/db/ ``` @@ -72,7 +72,8 @@ Chain spec was simply built with: substrate build-spec --chain=local > chain-spec.json ``` -Please note that `chain-spec.json` committed into repository is `raw` version produced by `zombienet` during database snapshot generation. Zombienet applies some modifications to plain versions of chain-spec. +Please note that `chain-spec.json` committed into repository is `raw` version produced by `zombienet` during database +snapshot generation. Zombienet applies some modifications to plain versions of chain-spec. # Run the test Test can be run with the following command: @@ -91,7 +92,7 @@ index 23fb13cfb0..89f8646291 100644 --- a/bin/node/runtime/src/constants.rs +++ b/bin/node/runtime/src/constants.rs @@ -63,7 +63,7 @@ pub mod time { - + // NOTE: Currently it is not possible to change the epoch duration after the chain has started. // Attempting to do so will brick block production. - pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES; diff --git a/substrate/zombienet/0002-validators-warp-sync/README.md b/substrate/zombienet/0002-validators-warp-sync/README.md index 662360fbf3c6..99fcb7313804 100644 --- a/substrate/zombienet/0002-validators-warp-sync/README.md +++ b/substrate/zombienet/0002-validators-warp-sync/README.md @@ -1,4 +1,3 @@ -Refer to ../0001-basic-warp-sync/README.md for more details. This test is nearly a clone. We want to warp-sync validators and make sure they can build blocks. -0001-basic-warp-sync chainspec (copied) and database are reused in this test. - - +Refer to ../0001-basic-warp-sync/README.md for more details. This test is nearly a clone. We want to warp-sync +validators and make sure they can build blocks. 0001-basic-warp-sync chainspec (copied) and database are reused in this +test. diff --git a/substrate/zombienet/0003-block-building-warp-sync/README.md b/substrate/zombienet/0003-block-building-warp-sync/README.md index 311d3550f766..08dc730a58b6 100644 --- a/substrate/zombienet/0003-block-building-warp-sync/README.md +++ b/substrate/zombienet/0003-block-building-warp-sync/README.md @@ -1,4 +1,3 @@ -Refer to ../0001-basic-warp-sync/README.md for more details. This test is nearly a clone. We want to warp-sync full nodes in the presence of validators. +Refer to ../0001-basic-warp-sync/README.md for more details. This test is nearly a clone. We want to warp-sync full nodes +in the presence of validators. 0001-basic-warp-sync chainspec (copied) and database are reused in this test. - - From b14a9089231c0f4fb17f20fe1af63a4fc267a990 Mon Sep 17 00:00:00 2001 From: Ignacio Palacios Date: Mon, 4 Sep 2023 12:30:25 +0200 Subject: [PATCH 016/103] [xcm-emulator] Redo Parachain init (#1356) * bring back proper init * refactor block cycle * ".git/.scripts/commands/fmt/fmt.sh" * Update cumulus/xcm/xcm-emulator/src/lib.rs Co-authored-by: Squirrel --------- Co-authored-by: command-bot <> Co-authored-by: Giles Cope --- .../assets/asset-hub-kusama/src/tests/send.rs | 2 - .../asset-hub-polkadot/src/tests/send.rs | 2 - .../asset-hub-polkadot/src/tests/teleport.rs | 2 - .../asset-hub-westend/src/tests/send.rs | 2 - .../bridge-hub-rococo/src/tests/example.rs | 141 +++++++++--------- .../src/tests/fellowship.rs | 3 - cumulus/xcm/xcm-emulator/src/lib.rs | 128 +++++++++------- 7 files changed, 142 insertions(+), 138 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs index 598256db83a0..d633c25b7324 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs @@ -174,8 +174,6 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { PenpalKusamaA::assert_xcm_pallet_sent(); }); - PenpalKusamaA::execute_with(|| {}); - AssetHubKusama::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs index 978377b0fda3..143ab06b4e99 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs @@ -177,8 +177,6 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { PenpalPolkadotA::assert_xcm_pallet_sent(); }); - PenpalPolkadotA::execute_with(|| {}); - AssetHubPolkadot::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs index 166f73137e75..f0fbcf37fccf 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs @@ -187,7 +187,6 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { /// Limited Teleport of native asset from System Parachain to Relay Chain /// should work when there is enough balance in Relay Chain's `CheckAccount` #[test] -#[cfg(feature = "FIXME-IGNORED")] // fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { // Dependency - Relay Chain's `CheckAccount` should have enough balance limited_teleport_native_assets_from_relay_to_system_para_works(); @@ -226,7 +225,6 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { /// Limited Teleport of native asset from System Parachain to Relay Chain /// should't work when there is not enough balance in Relay Chain's `CheckAccount` #[test] -#[cfg(feature = "FIXME-IGNORED")] // fn limited_teleport_native_assets_from_system_para_to_relay_fails() { // Init values for Relay Chain let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs index f2040351e5db..fcaffdabc4cf 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs @@ -116,8 +116,6 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { PenpalWestendA::assert_xcm_pallet_sent(); }); - PenpalWestendA::execute_with(|| {}); - AssetHubWestend::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs index 127292829fd5..777acd2aa972 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs @@ -14,85 +14,86 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +use crate::*; + #[test] -#[ignore] fn example() { - // // Init tests variables - // // XcmPallet send arguments - // let sudo_origin = ::RuntimeOrigin::root(); - // let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); - // let weight_limit = WeightLimit::Unlimited; - // let check_origin = None; + // Init tests variables + // XcmPallet send arguments + let sudo_origin = ::RuntimeOrigin::root(); + let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + let weight_limit = WeightLimit::Unlimited; + let check_origin = None; - // let remote_xcm = Xcm(vec![ClearOrigin]); + let remote_xcm = Xcm(vec![ClearOrigin]); - // let xcm = VersionedXcm::from(Xcm(vec![ - // UnpaidExecution { weight_limit, check_origin }, - // ExportMessage { - // network: WococoId, - // destination: X1(Parachain(AssetHubWococo::para_id().into())), - // xcm: remote_xcm, - // }, - // ])); + let xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit, check_origin }, + ExportMessage { + network: WococoId, + destination: X1(Parachain(AssetHubWococo::para_id().into())), + xcm: remote_xcm, + }, + ])); - // //Rococo Global Consensus - // // Send XCM message from Relay Chain to Bridge Hub source Parachain - // Rococo::execute_with(|| { - // assert_ok!(::XcmPallet::send( - // sudo_origin, - // bx!(destination), - // bx!(xcm), - // )); + //Rococo Global Consensus + // Send XCM message from Relay Chain to Bridge Hub source Parachain + Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin, + bx!(destination), + bx!(xcm), + )); - // type RuntimeEvent = ::RuntimeEvent; + type RuntimeEvent = ::RuntimeEvent; - // assert_expected_events!( - // Rococo, - // vec![ - // RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, - // ] - // ); - // }); - // // Receive XCM message in Bridge Hub source Parachain - // BridgeHubRococo::execute_with(|| { - // type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + // Receive XCM message in Bridge Hub source Parachain + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; - // assert_expected_events!( - // BridgeHubRococo, - // vec![ - // RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { - // outcome: Outcome::Complete(_), - // .. - // }) => {}, - // RuntimeEvent::BridgeWococoMessages(pallet_bridge_messages::Event::MessageAccepted { - // lane_id: LaneId([0, 0, 0, 1]), - // nonce: 1, - // }) => {}, - // ] - // ); - // }); + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + RuntimeEvent::BridgeWococoMessages(pallet_bridge_messages::Event::MessageAccepted { + lane_id: LaneId([0, 0, 0, 1]), + nonce: 1, + }) => {}, + ] + ); + }); - // // Wococo GLobal Consensus - // // Receive XCM message in Bridge Hub target Parachain - // BridgeHubWococo::execute_with(|| { - // type RuntimeEvent = ::RuntimeEvent; + // Wococo GLobal Consensus + // Receive XCM message in Bridge Hub target Parachain + BridgeHubWococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; - // assert_expected_events!( - // BridgeHubWococo, - // vec![ - // RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, - // ] - // ); - // }); - // // Receive embeded XCM message within `ExportMessage` in Parachain destination - // AssetHubWococo::execute_with(|| { - // type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + BridgeHubWococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + ] + ); + }); + // Receive embeded XCM message within `ExportMessage` in Parachain destination + AssetHubWococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; - // assert_expected_events!( - // AssetHubWococo, - // vec![ - // RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Fail { .. }) => {}, - // ] - // ); - // }); + assert_expected_events!( + AssetHubWococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Fail { .. }) => {}, + ] + ); + }); } diff --git a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs index 26fa55acb0d6..82e998f5a76c 100644 --- a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs +++ b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs @@ -58,11 +58,8 @@ fn pay_salary() { ); }); - Collectives::execute_with(|| {}); - AssetHubPolkadot::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; - assert_expected_events!( AssetHubPolkadot, vec![ diff --git a/cumulus/xcm/xcm-emulator/src/lib.rs b/cumulus/xcm/xcm-emulator/src/lib.rs index 59f238528fc1..9fda0632bae4 100644 --- a/cumulus/xcm/xcm-emulator/src/lib.rs +++ b/cumulus/xcm/xcm-emulator/src/lib.rs @@ -248,6 +248,14 @@ pub trait Parachain: Chain { type ParachainInfo: Get; type ParachainSystem; + fn init(); + + fn new_block(); + + fn finalize_block(); + + fn set_last_head(); + fn para_id() -> ParaId { Self::ext_wrapper(|| Self::ParachainInfo::get()) } @@ -263,8 +271,6 @@ pub trait Parachain: Chain { fn sovereign_account_id_of(location: MultiLocation) -> AccountId { Self::LocationToAccountId::convert_location(&location).unwrap() } - - fn init(); } pub trait Bridge { @@ -603,28 +609,74 @@ macro_rules! decl_test_parachains { type ParachainSystem = $crate::ParachainSystemPallet<::Runtime>; type ParachainInfo = $parachain_info; + // We run an empty block during initialisation to open HRMP channels + // and have them ready for the next block fn init() { use $crate::{Chain, HeadData, Network, NetworkComponent, Hooks, Encode, Parachain, TestExt}; + // Set the last block head for later use in the next block + Self::set_last_head(); + // Initialize a new block + Self::new_block(); + // Finalize the new block + Self::finalize_block(); + } + + fn new_block() { + use $crate::{Chain, HeadData, Network, NetworkComponent, Hooks, Encode, Parachain, TestExt}; + + let para_id = Self::para_id().into(); + + Self::ext_wrapper(|| { + // Increase Relay Chain block number + let mut relay_block_number = <$name as NetworkComponent>::Network::relay_block_number(); + relay_block_number += 1; + <$name as NetworkComponent>::Network::set_relay_block_number(relay_block_number); + + // Initialize a new Parachain block + let mut block_number = ::System::block_number(); + block_number += 1; + let parent_head_data = $crate::LAST_HEAD.with(|b| b.borrow_mut() + .get_mut(::Network::name()) + .expect("network not initialized?") + .get(¶_id) + .expect("network not initialized?") + .clone() + ); + ::System::initialize(&block_number, &parent_head_data.hash(), &Default::default()); + <::ParachainSystem as Hooks<$crate::BlockNumber>>::on_initialize(block_number); + + let _ = ::ParachainSystem::set_validation_data( + ::RuntimeOrigin::none(), + <$name as NetworkComponent>::Network::hrmp_channel_parachain_inherent_data(para_id, relay_block_number, parent_head_data), + ); + }); + } - let para_id = Self::para_id(); + fn finalize_block() { + use $crate::{Chain, Encode, Hooks, Network, NetworkComponent, Parachain, TestExt}; Self::ext_wrapper(|| { let block_number = ::System::block_number(); - let mut relay_block_number = ::Network::relay_block_number(); + ::ParachainSystem::on_finalize(block_number); + }); + + Self::set_last_head(); + } - // Get parent head data - let header = ::System::finalize(); - let parent_head_data = HeadData(header.encode()); + fn set_last_head() { + use $crate::{Chain, Encode, HeadData, Network, NetworkComponent, Parachain, TestExt}; + + let para_id = Self::para_id().into(); + + Self::ext_wrapper(|| { + // Store parent head data for use later. + let created_header = ::System::finalize(); $crate::LAST_HEAD.with(|b| b.borrow_mut() .get_mut(::Network::name()) .expect("network not initialized?") - .insert(para_id.into(), parent_head_data.clone()) + .insert(para_id, HeadData(created_header.encode())) ); - - let next_block_number = block_number + 1; - ::System::initialize(&next_block_number, &header.hash(), &Default::default()); - <::ParachainSystem as Hooks<$crate::BlockNumber>>::on_initialize(next_block_number); }); } } @@ -746,43 +798,20 @@ macro_rules! __impl_test_ext_for_parachain { // Make sure the Network is initialized <$name as NetworkComponent>::Network::init(); - let para_id = <$name>::para_id().into(); - - // Initialize block - $local_ext.with(|v| { - v.borrow_mut().execute_with(|| { - let parent_head_data = $crate::LAST_HEAD.with(|b| b.borrow_mut() - .get_mut(::Network::name()) - .expect("network not initialized?") - .get(¶_id) - .expect("network not initialized?") - .clone() - ); - - // Increase block number - let mut relay_block_number = <$name as NetworkComponent>::Network::relay_block_number(); - relay_block_number += 1; - <$name as NetworkComponent>::Network::set_relay_block_number(relay_block_number); - - let _ = ::ParachainSystem::set_validation_data( - ::RuntimeOrigin::none(), - <$name as NetworkComponent>::Network::hrmp_channel_parachain_inherent_data(para_id, relay_block_number, parent_head_data), - ); - }) - }); + // Initialize a new block + Self::new_block(); // Execute let r = $local_ext.with(|v| v.borrow_mut().execute_with(execute)); - // provide inbound DMP/HRMP messages through a side-channel. - // normally this would come through the `set_validation_data`, - // but we go around that. - <$name as NetworkComponent>::Network::process_messages(); + // Finalize the block + Self::finalize_block(); - // Finalize block and send messages if needed + let para_id = <$name>::para_id().into(); + + // Send messages if needed $local_ext.with(|v| { v.borrow_mut().execute_with(|| { - let block_number = ::System::block_number(); let mock_header = $crate::HeaderT::new( 0, Default::default(), @@ -791,16 +820,6 @@ macro_rules! __impl_test_ext_for_parachain { Default::default(), ); - // Finalize to get xcmp messages. - ::ParachainSystem::on_finalize(block_number); - // Store parent head data for use later. - let created_header = ::System::finalize(); - $crate::LAST_HEAD.with(|b| b.borrow_mut() - .get_mut(::Network::name()) - .expect("network not initialized?") - .insert(para_id.into(), $crate::HeadData(created_header.encode())) - ); - let collation_info = ::ParachainSystem::collect_collation_info(&mock_header); // send upward messages @@ -834,11 +853,6 @@ macro_rules! __impl_test_ext_for_parachain { // clean events ::System::reset_events(); - - // reinitialize before next call. - let next_block_number = block_number + 1; - ::System::initialize(&next_block_number, &created_header.hash(), &Default::default()); - <::ParachainSystem as Hooks<$crate::BlockNumber>>::on_initialize(next_block_number); }) }); From 5d37b8168331789c2252ac7e523f116fe2cbe65b Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Mon, 4 Sep 2023 23:42:19 +1200 Subject: [PATCH 017/103] add Treasurer to SchedulerOrigin (#1325) --- polkadot/runtime/kusama/src/lib.rs | 3 ++- polkadot/runtime/polkadot/src/lib.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index 4b5f03b38c6c..94af807fb5de 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -228,7 +228,8 @@ impl pallet_scheduler::Config for Runtime { type MaximumWeight = MaximumSchedulerWeight; // The goal of having ScheduleOrigin include AuctionAdmin is to allow the auctions track of // OpenGov to schedule periodic auctions. - type ScheduleOrigin = EitherOf, AuctionAdmin>; + // Also allow Treasurer to schedule recurring payments. + type ScheduleOrigin = EitherOf, AuctionAdmin>, Treasurer>; type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = weights::pallet_scheduler::WeightInfo; type OriginPrivilegeCmp = OriginPrivilegeCmp; diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index 2efd329eea0c..b71e0f726c55 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -212,7 +212,8 @@ impl pallet_scheduler::Config for Runtime { type MaximumWeight = MaximumSchedulerWeight; // The goal of having ScheduleOrigin include AuctionAdmin is to allow the auctions track of // OpenGov to schedule periodic auctions. - type ScheduleOrigin = EitherOf, AuctionAdmin>; + // Also allow Treasurer to schedule recurring payments. + type ScheduleOrigin = EitherOf, AuctionAdmin>, Treasurer>; type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = weights::pallet_scheduler::WeightInfo; type OriginPrivilegeCmp = OriginPrivilegeCmp; From 3d4089c5bd0cec0f86334121285d46834db99b87 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 4 Sep 2023 14:45:33 +0200 Subject: [PATCH 018/103] Cleanup repo (a tiny bit) (#1382) * Delete stale adoc files Signed-off-by: Oliver Tale-Yazdi * Convert adoc to md Signed-off-by: Oliver Tale-Yazdi * Add adoc to gitignore Signed-off-by: Oliver Tale-Yazdi * Delete more random unmaintained files Signed-off-by: Oliver Tale-Yazdi * Markdown lint Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi --- .gitignore | 1 + cumulus/bridges/rustfmt.toml | 24 - polkadot/RELEASE.md | 52 -- polkadot/doc/release-checklist.md | 91 --- polkadot/node/service/README.adoc | 5 - polkadot/parachain/README.adoc | 5 - polkadot/primitives/README.adoc | 5 - polkadot/runtime/polkadot/README.adoc | 5 - polkadot/src/README.adoc | 5 - polkadot/statement-table/README.adoc | 5 - substrate/.maintain/getgoing.sh | 6 - substrate/.maintain/runtime-dep.py | 34 -- substrate/.maintain/update-deps.sh | 9 - ...ll-completion.adoc => shell-completion.md} | 23 +- substrate/client/cli/README.adoc | 6 - substrate/docs/README.adoc | 522 ------------------ substrate/docs/Structure.adoc | 121 ---- 17 files changed, 9 insertions(+), 910 deletions(-) delete mode 100644 cumulus/bridges/rustfmt.toml delete mode 100644 polkadot/RELEASE.md delete mode 100644 polkadot/doc/release-checklist.md delete mode 100644 polkadot/node/service/README.adoc delete mode 100644 polkadot/parachain/README.adoc delete mode 100644 polkadot/primitives/README.adoc delete mode 100644 polkadot/runtime/polkadot/README.adoc delete mode 100644 polkadot/src/README.adoc delete mode 100644 polkadot/statement-table/README.adoc delete mode 100644 substrate/.maintain/getgoing.sh delete mode 100755 substrate/.maintain/runtime-dep.py delete mode 100755 substrate/.maintain/update-deps.sh rename substrate/bin/node/cli/doc/{shell-completion.adoc => shell-completion.md} (75%) delete mode 100644 substrate/client/cli/README.adoc delete mode 100644 substrate/docs/README.adoc delete mode 100644 substrate/docs/Structure.adoc diff --git a/.gitignore b/.gitignore index bd7f34b48104..35e02e706b42 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ .local .vscode .wasm-binaries +*.adoc *.bin *.iml *.orig diff --git a/cumulus/bridges/rustfmt.toml b/cumulus/bridges/rustfmt.toml deleted file mode 100644 index 082150daf04e..000000000000 --- a/cumulus/bridges/rustfmt.toml +++ /dev/null @@ -1,24 +0,0 @@ -# Basic -hard_tabs = true -max_width = 100 -use_small_heuristics = "Max" -# Imports -imports_granularity = "Crate" -reorder_imports = true -# Consistency -newline_style = "Unix" -# Format comments -comment_width = 100 -wrap_comments = true -# Misc -chain_width = 80 -spaces_around_ranges = false -binop_separator = "Back" -reorder_impl_items = false -match_arm_leading_pipes = "Preserve" -match_arm_blocks = false -match_block_trailing_comma = true -trailing_comma = "Vertical" -trailing_semicolon = false -use_field_init_shorthand = true - diff --git a/polkadot/RELEASE.md b/polkadot/RELEASE.md deleted file mode 100644 index 196f27e595d6..000000000000 --- a/polkadot/RELEASE.md +++ /dev/null @@ -1,52 +0,0 @@ -# Polkadot Release Process - -## Branches -* release-candidate branch: The branch used for staging of the next release. Named like `release-v0.8.26` - -## Notes -* The release-candidate branch *must* be made in the `paritytech/polkadot` repo in order for release automation to work -correctly -* Any new pushes/merges to the release-candidate branch (for example, refs/heads/release-v0.8.26) will result in the rc -index being bumped (e.g., v0.8.26-rc1 to v0.8.26-rc2) and new wasm built. - -## Release workflow - -Below are the steps of the release workflow. Steps prefixed with NOACTION are automated and require no human action. - -1. To initiate the release process: - 1. branch master off to a release candidate branch: - `git checkout master; git pull; git checkout -b release-v0.8.26` - 1. In the [Substrate](https://github.com/paritytech/substrate) repo, check out the commit used by Polkadot (this can - be found using the following command in the *Polkadot* repo: `grep 'paritytech/substrate' Cargo.lock | grep -E - '[0-9a-f]{40}' | sort | uniq` - 1. Branch off this **Substrate** commit into its own branch: `git branch -b polkadot-v0.8.26; git push origin - refs/heads/polkadot-v0.8.26` - 1. In the **Polkadot** repository, use [diener](https://github.com/bkchr/diener/) to switch to this branch: `diener - update --branch "polkadot-v0.8.26" --substrate`. Update Cargo.lock (to do this, you can run `cargo build` and then - ctrl+c once it finishes fetching and begins compiling) - 1. Push the **Polkadot** `release-v0.8.26` branch to Github: `git push origin refs/heads/release-v0.8.26` -1. NOACTION: The current HEAD of the release-candidate branch is tagged `v0.8.26-rc1` -1. NOACTION: A draft release and runtime WASMs are created for this release-candidate automatically. A link to the draft - release will be linked in the internal Polkadot matrix channel. -1. NOACTION: A new Github issue is created containing a checklist of manual steps to be completed before we are - confident with the release. This will be linked in Matrix. -1. Complete the steps in the issue created in step 4, signing them off as completed -1. (optional) If a fix is required to the release-candidate: - 1. Merge the fix with `master` first - 1. Cherry-pick the commit from `master` to `release-v0.8.26`, fixing any merge conflicts. Try to avoid unnecessarily - bumping crates. - 1. Push the release-candidate branch to Github - this is now the new release- candidate - 1. Depending on the cherry-picked changes, it may be necessary to perform some or all of the manual tests again. - 1. If there are **Substrate** changes required, these should be cherry-picked to the Substrate `polkadot-v0.8.26` - branch and pushed, and the version of Substrate used in **Polkadot** updated using `cargo update -p sp-io` -1. Once happy with the release-candidate, tag the current top commit in the release candidate branch and push to Github: - `git tag -s -m 'v0.8.26' v0.8.26; git push --tags` -1. NOACTION: The HEAD of the `release` branch will be tagged with `v0.8.26`, and a final draft release will be created - on Github. - -## Security releases - -Occasionally there may be changes that need to be made to the most recently released version of Polkadot, without taking -*every* change to `master` since the last release. For example, in the event of a security vulnerability being found, -where releasing a fixed version is a matter of some expediency. In cases like this, the fix should first be merged with -master, cherry-picked to a branch forked from `release`, tested, and then finally merged with `release`. A sensible -versioning scheme for changes like this is `vX.Y.Z-1`. diff --git a/polkadot/doc/release-checklist.md b/polkadot/doc/release-checklist.md deleted file mode 100644 index 8c57791fed1d..000000000000 --- a/polkadot/doc/release-checklist.md +++ /dev/null @@ -1,91 +0,0 @@ - -# Notes - -## Burn In - -Ensure that Parity DevOps has run the new release on Westend, Kusama, and Polkadot validators for at least 12 hours -prior to publishing the release. - -## Build Artifacts - -Add any necessary assets to the release. They should include: - -* Linux binary -* GPG signature of the Linux binary -* SHA256 of binary -* Source code -* Wasm binaries of any runtimes - -## Release notes - -The release notes should list: - -* The priority of the release (i.e., how quickly users should upgrade) - this is based on the max priority of any - *client* changes. -* Which native runtimes and their versions are included -* The proposal hashes of the runtimes as built with [srtool](https://gitlab.com/chevdor/srtool) -* Any changes in this release that are still awaiting audit - -The release notes may also list: - -* Free text at the beginning of the notes mentioning anything important regarding this release -* Notable changes (those labelled with B[1-9]-* labels) separated into sections - -## Spec Version - -A runtime upgrade must bump the spec number. This may follow a pattern with the client release (e.g. runtime v12 -corresponds to v0.8.12, even if the current runtime is not v11). - -## Old Migrations Removed - -Any previous `on_runtime_upgrade` functions from old upgrades must be removed to prevent them from executing a second -time. The `on_runtime_upgrade` function can be found in `runtime//src/lib.rs`. - -## New Migrations - -Ensure that any migrations that are required due to storage or logic changes are included in the `on_runtime_upgrade` -function of the appropriate pallets. - -## Extrinsic Ordering - -Offline signing libraries depend on a consistent ordering of call indices and functions. Compare the metadata of the -current and new runtimes and ensure that the `module index, call index` tuples map to the same set of functions. In case -of a breaking change, increase `transaction_version`. - -To verify the order has not changed, you may manually start the following [Github -Action](https://github.com/paritytech/polkadot/actions/workflows/extrinsic-ordering-check-from-bin.yml). It takes around -a minute to run and will produce the report as artifact you need to manually check. - -The things to look for in the output are lines like: - * `[Identity] idx 28 -> 25 (calls 15)` - indicates the index for `Identity` has changed - * `[+] Society, Recovery` - indicates the new version includes 2 additional modules/pallets. - * If no indices have changed, every modules line should look something like `[Identity] idx 25 (calls 15)` - -Note: Adding new functions to the runtime does not constitute a breaking change as long as the indexes did not change. - -## Proxy Filtering - -The runtime contains proxy filters that map proxy types to allowable calls. If the new runtime contains any new calls, -verify that the proxy filters are up to date to include them. - -## Benchmarks - -There are three benchmarking machines reserved for updating the weights at release-time. To initialise a benchmark run -for each production runtime (`westend`, `kusama`, `polkadot`): -* Go to https://gitlab.parity.io/parity/polkadot/-/pipelines?page=1&scope=branches&ref=master -* Click the link to the last pipeline run for master -* Start each of the manual jobs: - * `update_westend_weights` - * `update_polkadot_weights` - * `update_kusama_weights` -* When these jobs have completed (it takes a few hours), a git PATCH file will be available to download as an artifact. -* On your local machine, branch off master -* Download the patch file and apply it to your branch with `git patch patchfile.patch` -* Commit the changes to your branch and submit a PR against master -* The weights should be (Currently manually) checked to make sure there are no big outliers (i.e., twice or half the - weight). - -## Polkadot JS - -Ensure that a release of [Polkadot JS API](https://github.com/polkadot-js/api) contains any new types or interfaces -necessary to interact with the new runtime. diff --git a/polkadot/node/service/README.adoc b/polkadot/node/service/README.adoc deleted file mode 100644 index 2196d5467806..000000000000 --- a/polkadot/node/service/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -= Polkadot Service - -placeholder -//TODO Write content :) (https://github.com/paritytech/polkadot/issues/159) diff --git a/polkadot/parachain/README.adoc b/polkadot/parachain/README.adoc deleted file mode 100644 index 8650919e64ec..000000000000 --- a/polkadot/parachain/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -= Polkadot Parachain - -placeholder -//TODO Write content :) (https://github.com/paritytech/polkadot/issues/159) diff --git a/polkadot/primitives/README.adoc b/polkadot/primitives/README.adoc deleted file mode 100644 index 0e5c9412f002..000000000000 --- a/polkadot/primitives/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -= Polkadot primitives - -placeholder -//TODO Write content :) (https://github.com/paritytech/polkadot/issues/159) diff --git a/polkadot/runtime/polkadot/README.adoc b/polkadot/runtime/polkadot/README.adoc deleted file mode 100644 index 33373310819f..000000000000 --- a/polkadot/runtime/polkadot/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -= Polkadot Runtime - -placeholder -//TODO Write content :) (https://github.com/paritytech/polkadot/issues/159) diff --git a/polkadot/src/README.adoc b/polkadot/src/README.adoc deleted file mode 100644 index 4ec8e18d8afe..000000000000 --- a/polkadot/src/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -= Polkadot Src - -placeholder -//TODO Write content :) (https://github.com/paritytech/polkadot/issues/159) diff --git a/polkadot/statement-table/README.adoc b/polkadot/statement-table/README.adoc deleted file mode 100644 index a4da4dee80ff..000000000000 --- a/polkadot/statement-table/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -= Polkadot Statement table - -placeholder -//TODO Write content :) (https://github.com/paritytech/polkadot/issues/159) diff --git a/substrate/.maintain/getgoing.sh b/substrate/.maintain/getgoing.sh deleted file mode 100644 index 98f360837d04..000000000000 --- a/substrate/.maintain/getgoing.sh +++ /dev/null @@ -1,6 +0,0 @@ -/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" -brew install openssl cmake -curl https://sh.rustup.rs -sSf | sh -source ~/.cargo/env -cargo install --git https://github.com/paritytech/substrate subkey -cargo install --git https://github.com/paritytech/substrate substrate diff --git a/substrate/.maintain/runtime-dep.py b/substrate/.maintain/runtime-dep.py deleted file mode 100755 index 3198bb3e2669..000000000000 --- a/substrate/.maintain/runtime-dep.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 - -# To run this script, you need to install the 'toml' python package and install the 'graphviz' package: -# pip install toml -# sudo apt-get install graphviz -# the first parameter is the runtime folder -# python ./.maintain/runtime-dep.py ./substrate/runtime | dot -Tpng -o output.png -import sys -import os -import toml - -if len(sys.argv) != 2: - print("needs the runtime folder.") - sys.exit(-1) - -runtime_dir = sys.argv[1] - -files = [os.path.join(runtime_dir, f, 'Cargo.toml') for f in os.listdir(runtime_dir) if os.path.isfile(os.path.join(runtime_dir, f, 'Cargo.toml')) and f != 'example'] - -print("digraph G {") - - -PREFIX = "substrate-runtime-" - -for f in files: - manifest = toml.load(f) - - package_name = manifest['package']['name'] - deps = [d for d in manifest['dependencies'].keys() if d.startswith(PREFIX)] - - for d in deps: - print(" \"{}\" -> \"{}\";".format(package_name, d)) - -print("}") diff --git a/substrate/.maintain/update-deps.sh b/substrate/.maintain/update-deps.sh deleted file mode 100755 index cd6b7c853825..000000000000 --- a/substrate/.maintain/update-deps.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -- -set -eu -case $0 in - (/*) dir=${0%/*}/;; - (*/*) dir=./${0%/*};; - (*) dir=.;; -esac - -find "$dir/.." -name Cargo.lock -execdir cargo update \; diff --git a/substrate/bin/node/cli/doc/shell-completion.adoc b/substrate/bin/node/cli/doc/shell-completion.md similarity index 75% rename from substrate/bin/node/cli/doc/shell-completion.adoc rename to substrate/bin/node/cli/doc/shell-completion.md index 168f00994fb2..3f009a04373d 100644 --- a/substrate/bin/node/cli/doc/shell-completion.adoc +++ b/substrate/bin/node/cli/doc/shell-completion.md @@ -1,12 +1,11 @@ +# Shell completion -== Shell completion - -The Substrate cli command supports shell auto-completion. For this to work, you will need to run the completion script matching your build and system. +The Substrate cli command supports shell auto-completion. For this to work, you will need to run the +completion script matching your build and system. Assuming you built a release version using `cargo build --release` and use `bash` run the following: -[source, shell] -source target/release/completion-scripts/substrate.bash +`source target/release/completion-scripts/substrate.bash` You can find completion scripts for: - bash @@ -17,25 +16,19 @@ You can find completion scripts for: To make this change persistent, you can proceed as follows: -.First install - -[source, shell] ----- +```shell COMPL_DIR=$HOME/.completion mkdir -p $COMPL_DIR cp -f target/release/completion-scripts/substrate.bash $COMPL_DIR/ echo "source $COMPL_DIR/substrate.bash" >> $HOME/.bash_profile source $HOME/.bash_profile ----- - -.Update +``` When you build a new version of Substrate, the following will ensure your auto-completion script matches the current binary: -[source, shell] ----- +```shell COMPL_DIR=$HOME/.completion mkdir -p $COMPL_DIR cp -f target/release/completion-scripts/substrate.bash $COMPL_DIR/ source $HOME/.bash_profile ----- +``` diff --git a/substrate/client/cli/README.adoc b/substrate/client/cli/README.adoc deleted file mode 100644 index fc58908fdf23..000000000000 --- a/substrate/client/cli/README.adoc +++ /dev/null @@ -1,6 +0,0 @@ - -= Substrate CLI - -Substrate CLI library - -include::doc/shell-completion.adoc[] diff --git a/substrate/docs/README.adoc b/substrate/docs/README.adoc deleted file mode 100644 index 3537e346a66e..000000000000 --- a/substrate/docs/README.adoc +++ /dev/null @@ -1,522 +0,0 @@ -= Substrate -:Author: Substrate developers -:Revision: 0.2.0 -:toc: -:sectnums: - -== Intro in one sentence - -Substrate is a next-generation framework for blockchain innovation. - -== Description - -At its heart, Substrate is a combination of three technologies: https://webassembly.org/[WebAssembly], https://libp2p.io/[Libp2p] and GRANDPA Consensus. About GRANDPA, see this https://hackmd.io/Jd0byWX0RiqFiXUVC78Bdw?view#GRANDPA[definition], https://medium.com/polkadot-network/grandpa-block-finality-in-polkadot-an-introduction-part-1-d08a24a021b5[introduction] and https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf[formal specification]. It is both a library for building new blockchains and a "skeleton key" of a blockchain client, able to synchronize to any Substrate-based chain. - -Substrate chains have three distinct features that make them "next-generation": a dynamic, self-defining state-transition function; light-client functionality from day one; and a progressive consensus algorithm with fast block production and adaptive, definite finality. The STF, encoded in WebAssembly, is known as the "runtime". This defines the `execute_block` function, and can specify everything from the staking algorithm, transaction semantics, logging mechanisms and procedures for replacing any aspect of itself or of the blockchain's state ("governance"). Because the runtime is entirely dynamic all of these can be switched out or upgraded at any time. A Substrate chain is very much a "living organism". - -See also https://www.parity.io/what-is-substrate/. - -== Usage - -Substrate is still an early stage project, and while it has already been used as the basis of major projects like Polkadot, using it is still a significant undertaking. In particular, you should have a good knowledge of blockchain concepts and basic cryptography. Terminology like header, block, client, hash, transaction and signature should be familiar. At present you will need a working knowledge of Rust to be able to do anything interesting (though eventually, we aim for this not to be the case). - -Substrate is designed for use in one of three ways: - -**1. Trivial**: By running the Substrate binary `substrate` and configuring it with a genesis block that includes the current demonstration runtime. In this case, you just build Substrate, configure a JSON file, and launch your own blockchain. This affords you the least amount of customizability, primarily allowing you to change the genesis parameters of the various included runtime modules such as balances, staking, block-period, fees, and governance. - -**2. Modular**: By hacking together pallets built with Substrate FRAME into a new runtime and possibly altering or reconfiguring the Substrate client's block authoring logic. This affords you a very large amount of freedom over your blockchain's logic, letting you change data types, add or remove modules, and crucially, add your own modules. Much can be changed without touching the block authoring logic (since it is generic). If this is the case, then the existing Substrate binary can be used for block authoring and syncing. If the block authoring logic needs to be tweaked, then a new, altered block authoring binary must be built as a separate project and used by validators. This is how the Polkadot relay chain is built and should suffice for almost all circumstances in the near to mid-term. - -**3. Generic**: The entire FRAME can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, provided it can target WebAssembly. If the runtime can be made compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term, far-reaching upgrade path for the Substrate paradigm. - -=== The Basics of Substrate - -Substrate is a blockchain platform with a completely generic state transition function. That said, it does come with both standards and conventions (particularly regarding the Runtime Module Library) regarding underlying data structures. Roughly speaking, these core data types correspond to +trait+s in terms of the actual non-negotiable standard and generic +struct+s in terms of the convention. - -``` -Header := Parent + ExtrinsicsRoot + StorageRoot + Digest -Block := Header + Extrinsics + Justifications -``` - -=== Extrinsics - -Extrinsics in Substrate are pieces of information from "the outside world" that are contained in the blocks of the chain. You might think "ahh, that means *transactions*": in fact, no. Extrinsics fall into two broad categories of which only one is *transactions*. The other is known as *inherents*. The difference between these two is that transactions are signed and gossiped on the network and can be deemed useful *per se*. This fits the mold of what you would call transactions in Bitcoin or Ethereum. - -Inherents, meanwhile, are not passed on the network and are not signed. They represent data which describes the environment but which cannot call upon anything to prove it such as a signature. Rather they are assumed to be "true" simply because a sufficiently large number of validators have agreed on them being reasonable. - -To give an example, there is the timestamp inherent, which sets the current timestamp of the block. This is not a fixed part of Substrate, but does come as part of FRAME to be used as desired. No signature could fundamentally prove that a block were authored at a given time in quite the same way that a signature can "prove" the desire to spend some particular funds. Rather, it is the business of each validator to ensure that they believe the timestamp is set to something reasonable before they agree that the block candidate is valid. - -Other examples include the parachain-heads extrinsic in Polkadot and the "note-missed-proposal" extrinsic used in FRAME to determine and punish or deactivate offline validators. - - -=== Runtime and API - -Substrate chains all have a runtime. The runtime is a WebAssembly "blob" that includes a number of entry-points. Some entry-points are required as part of the underlying Substrate specification. Others are merely convention and required for the default implementation of the Substrate client to be able to author blocks. - -If you want to develop a chain with Substrate, you will need to implement the `Core` trait. This `Core` trait generates an API with the minimum necessary functionality to interact with your runtime. A special macro is provided called `impl_runtime_apis!` that help you implement runtime API traits. All runtime API trait implementations need to be done in one call of the `impl_runtime_apis!` macro. All parameters and return values need to implement https://crates.io/crates/parity-codec[`parity-codec`] to be encodable and decodable. - -Here's a snippet of the Polkadot API implementation as of PoC-3: - -```rust -impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: ::Header) { - Executive::initialize_block(&header) - } - } - // ---snip--- -} -``` - - -=== Inherent Extrinsics - -Substrate FRAME includes functionality for timestamps and slashing. If used, these rely on "trusted" external information being passed in via inherent extrinsics. The Substrate reference block authoring client software will expect to be able to call into the runtime API with collated data (in the case of the reference Substrate authoring client, this is merely the current timestamp and which nodes were offline) in order to return the appropriate extrinsics ready for inclusion. If new inherent extrinsic types and data are to be used in a modified runtime, then it is this function (and its argument type) that would change. - -=== Block-authoring Logic - -In Substrate, there is a major distinction between blockchain *syncing* and block *authoring* ("authoring" is a more general term for what is called "mining" in Bitcoin). The first case might be referred to as a "full node" (or "light node" - Substrate supports both): authoring necessarily requires a synced node and, therefore, all authoring clients must necessarily be able to synchronize. However, the reverse is not true. The primary functionality that authoring nodes have which is not in "sync nodes" is threefold: transaction queue logic, inherent transaction knowledge and BFT consensus logic. BFT consensus logic is provided as a core element of Substrate and can be ignored since it is only exposed in the SDK under the `authorities()` API entry. - -Transaction queue logic in Substrate is designed to be as generic as possible, allowing a runtime to express which transactions are fit for inclusion in a block through the `initialize_block` and `apply_extrinsic` calls. However, more subtle aspects like prioritization and replacement policy must currently be expressed "hard coded" as part of the blockchain's authoring code. That said, Substrate's reference implementation for a transaction queue should be sufficient for an initial chain implementation. - -Inherent extrinsic knowledge is again somewhat generic, and the actual construction of the extrinsics is, by convention, delegated to the "soft code" in the runtime. If ever there needs to be additional extrinsic information in the chain, then both the block authoring logic will need to be altered to provide it into the runtime and the runtime's `inherent_extrinsics` call will need to use this extra information in order to construct any additional extrinsic transactions for inclusion in the block. - -== Roadmap - -=== So far - -- 0.1 "PoC-1": PBFT consensus, Wasm runtime engine, basic runtime modules. -- 0.2 "PoC-2": Libp2p - -=== In progress - -- AfG consensus -- Improved PoS -- Smart contract runtime module - -=== The future - -- Splitting out runtime modules into separate repo -- Introduce substrate executable (the skeleton-key runtime) -- Introduce basic but extensible transaction queue and block-builder and place them in the executable. -- DAO runtime module -- Audit - -== Trying out Substrate Node - -Substrate Node is Substrate's pre-baked blockchain client. You can run a development node locally or configure a new chain and launch your own global testnet. - -=== On Mac and Ubuntu - -To get going as fast as possible, there is a simple script that installs all required dependencies and installs Substrate into your path. Just open a terminal and run: - -[source, shell] ----- -curl https://getsubstrate.io -sSf | bash ----- - -You can start a local Substrate development chain with running `substrate --dev`. - -To create your own global network/cryptocurrency, you'll need to make a new Substrate Node chain specification file ("chainspec"). - -First let's get a template chainspec that you can edit. We'll use the "staging" chain, a sort of default chain that the node comes pre-configured with: - -[source, shell] ----- -substrate build-spec --chain=staging > ~/chainspec.json ----- - -Now, edit `~/chainspec.json` in your editor. There are a lot of individual fields for each module, and one very large one which contains the WebAssembly code blob for this chain. The easiest field to edit is the block `period`. Change it to 10 (seconds): - -[source, json] ----- - "timestamp": { - "minimumPeriod": 10 - }, ----- - -Now with this new chainspec file, you can build a "raw" chain definition for your new chain: - -[source, shell] ----- -substrate build-spec --chain ~/chainspec.json --raw > ~/mychain.json ----- - -This can be fed into Substrate: - -[source, shell] ----- -substrate --chain ~/mychain.json ----- - -It won't do much until you start producing blocks though, so to do that you'll need to use the `--validator` option together with passing the seed for the account(s) that is configured to be the initial authorities: - -[source, shell] ----- -substrate --chain ~/mychain.json --validator ----- - -You can distribute `mychain.json` so that everyone can synchronize and (depending on your authorities list) validate on your chain. - - -== Building - -=== Hacking on Substrate - -If you'd actually like to hack on Substrate, you can just grab the source code and -build it. Ensure you have Rust and the support software installed: - -==== Linux and Mac - -For Unix-based operating systems, you should run the following commands: - -[source, shell] ----- -curl https://sh.rustup.rs -sSf | sh - -rustup update nightly -rustup target add wasm32-unknown-unknown --toolchain nightly -rustup update stable ----- - -You will also need to install the following packages: - - - Linux: -[source, shell] -sudo apt install cmake pkg-config libssl-dev git clang libclang-dev llvm - -- Linux on ARM: -`rust-lld` is required for linking wasm, but is missing on non Tier 1 platforms. -So, use this https://github.com/Plume-org/Plume/blob/master/script/wasm-deps.sh[script] -to build `lld` and create the symlink `/usr/bin/rust-lld` to the build binary. - - - Mac: -[source, shell] -brew install cmake pkg-config openssl git llvm - -To finish installation of Substrate, jump down to <>. - -==== Windows - -If you are trying to set up Substrate on Windows, you should do the following: - -1. First, you will need to download and install "Build Tools for Visual Studio:" - - * You can get it at this link: https://aka.ms/buildtools - * Run the installation file: `vs_buildtools.exe` - * Please ensure the Windows 10 SDK component is included when installing the Visual C++ Build Tools. - * image:https://i.imgur.com/zayVLmu.png[image] - * Restart your computer. - -2. Next, you need to install Rust: - - * Detailed instructions are provided by the https://doc.rust-lang.org/book/ch01-01-installation.html#installing-rustup-on-windows[Rust Book]. - * Download from: https://www.rust-lang.org/tools/install - * Run the installation file: `rustup-init.exe` - > Note that it should not prompt you to install vs_buildtools since you did it in step 1. - * Choose "Default Installation." - * To get started, you need Cargo's bin directory (%USERPROFILE%\.cargo\bin) in your PATH environment variable. Future applications will automatically have the correct environment, but you may need to restart your current shell. - -3. Then, you will need to run some commands in CMD to set up your Wasm Build Environment: - - rustup update nightly - rustup update stable - rustup target add wasm32-unknown-unknown --toolchain nightly - -4. Then, you need to install LLVM: https://releases.llvm.org/download.html - -5. Next, you need to install OpenSSL, which we will do with `vcpkg`: - - mkdir \Tools - cd \Tools - git clone https://github.com/Microsoft/vcpkg.git - cd vcpkg - .\bootstrap-vcpkg.bat - .\vcpkg.exe install openssl:x64-windows-static - -6. After, you need to add OpenSSL to your System Variables. Note that in order for the following commands to work, you need to use Windows Powershell: - - $env:OPENSSL_DIR = 'C:\Tools\vcpkg\installed\x64-windows-static' - $env:OPENSSL_STATIC = 'Yes' - [System.Environment]::SetEnvironmentVariable('OPENSSL_DIR', $env:OPENSSL_DIR, [System.EnvironmentVariableTarget]::User) - [System.Environment]::SetEnvironmentVariable('OPENSSL_STATIC', $env:OPENSSL_STATIC, [System.EnvironmentVariableTarget]::User) - -7. Finally, you need to install `cmake`: https://cmake.org/download/ - -==== Docker - -You can use https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-linux[Parity CI docker image] with all necessary dependencies to build Substrate: - -[source, shell] ----- -#run it in the folder with the Substrate source code -docker run --rm -it -w /shellhere/substrate \ - -v $(pwd):/shellhere/substrate \ - paritytech/ci-linux:production ----- - -You can find necessary cargo commands in <> - -==== Shared Steps - -Then, grab the Substrate source code: - -[source, shell] ----- -git clone https://github.com/paritytech/substrate.git -cd substrate ----- - -Then build the code: - -[source, shell] ----- -cargo build # Builds all native code ----- - -You can run all the tests if you like: - -[source, shell] -cargo test --all - -Or just run the tests of a specific package (i.e. `cargo test -p pallet-assets`) - -You can start a development chain with: - -[source, shell] -cargo run --release -- --dev - -Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run --release \-- --dev`. - -If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on link:https://telemetry.polkadot.io/#/Local%20Testnet[Telemetry]. You'll need two terminal windows open. - -We'll start Alice's Substrate node first on default TCP port 30333 with their chain database stored locally at `/tmp/alice`. The Bootnode ID of Alice's node is `QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`, which is generated from the `--node-key` value that we specify below: - -[source, shell] -cargo run --release \-- \ - --base-path /tmp/alice \ - --chain=local \ - --alice \ - --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ - --telemetry-url 'ws://telemetry.polkadot.io:1024 0' \ - --validator - -In the second terminal, we'll run the following to start Bob's Substrate node on a different TCP port of 30334, and with their chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect Bob's node to Alice's Bootnode ID on TCP port 30333: - -[source, shell] -cargo run --release \-- \ - --base-path /tmp/bob \ - --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR \ - --chain=local \ - --bob \ - --port 30334 \ - --telemetry-url 'ws://telemetry.polkadot.io:1024 0' \ - --validator - -Additional Substrate CLI usage options are available and may be shown by running `cargo run \-- --help`. - -[[flaming-fir]] -=== Joining the Flaming Fir Testnet - -Flaming Fir is the new testnet for Substrate master (2.0) to test the latest development features. Please note that master is not compatible with the BBQ Birch, Charred Cherry, Dried Danta or Emberic Elm testnets. Ensure you have the dependencies listed above before compiling. - -Since Flaming Fir is targeting the master branch we make absolutely no guarantees of stability and/or persistence of the network. We might reset the chain at any time if it is necessary to deploy new changes. Currently, the validators are running with a client built from `d013bd900`, if you build from this commit you should be able to successfully sync, later commits may not work as new breaking changes may be introduced in master. - -Latest known working version: `a2a0eb5398d6223e531455b4c155ef053a4a3a2b` - -[source, shell] ----- -git clone https://github.com/paritytech/substrate.git -cd substrate -git checkout -b flaming-fir a2a0eb5398d6223e531455b4c155ef053a4a3a2b ----- - -You can run the tests if you like: - -[source, shell] -cargo test --all - -Start your node: - -[source, shell] -cargo run --release \-- - -To see a list of command line options, enter: - -[source, shell] -cargo run --release \-- --help - -For example, you can choose a custom node name: - -[source, shell] -cargo run --release \-- --name my_custom_name - -If you are successful, you will see your node syncing at https://telemetry.polkadot.io/#/Flaming%20Fir - -=== Joining the Emberic Elm Testnet - -Emberic Elm is the testnet for Substrate 1.0. Please note that 1.0 is not compatible with the BBQ Birch, Charred Cherry, Dried Danta or Flaming Fir testnets. -In order to join the Emberic Elm testnet you should build from the `v1.0` branch. Ensure you have the dependencies listed above before compiling. - -[source, shell] ----- -git clone https://github.com/paritytech/substrate.git -cd substrate -git checkout -b v1.0 origin/v1.0 ----- - -You can then follow the same steps for building and running as described above in <>. - -== Key management - -Keys in Substrate are stored in the keystore in the file system. To store keys into this keystore, -you need to use one of the two provided RPC calls. If your keys are encrypted or should be encrypted -by the keystore, you need to provide the key using one of the cli arguments `--password`, -`--password-interactive` or `--password-filename`. - -=== Recommended RPC call - -For most users who want to run a validator node, the `author_rotateKeys` RPC call is sufficient. -The RPC call will generate `N` Session keys for you and return their public keys. `N` is the number -of session keys configured in the runtime. The output of the RPC call can be used as input for the -`session::set_keys` transaction. - -``` -curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_rotateKeys", "id":1 }' localhost:9933 -``` - -=== Advanced RPC call - -If the Session keys need to match a fixed seed, they can be set individually key by key. The RPC call -expects the key seed and the key type. The key types supported by default in Substrate are listed -https://github.com/paritytech/substrate/blob/master/core/primitives/src/crypto.rs#L767[here], but the -user can declare any key type. - -``` -curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_insertKey", "params":["KEY_TYPE", "SEED", "PUBLIC"],"id":1 }' localhost:9933 -``` - -`KEY_TYPE` - needs to be replaced with the 4-character key type identifier. -`SEED` - is the seed of the key. -`PUBLIC` - public key for the given key. - -== Documentation - -=== Viewing documentation for Substrate packages - -You can generate documentation for a Substrate Rust package and have it automatically open in your web browser using https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo[rustdoc with Cargo], -(of the The Rustdoc Book), by running the following command: - -``` -cargo doc --package --open -``` - -Replacing `` with one of the following (i.e. `cargo doc --package substrate --open`): - -* All Substrate Packages -[source, shell] -substrate -* Substrate Core -[source, shell] -substrate, substrate-cli, substrate-client, substrate-client-db, -substrate-consensus-common, substrate-consensus-rhd, -substrate-executor, substrate-finality-grandpa, substrate-keyring, substrate-keystore, substrate-network, -substrate-network-libp2p, substrate-primitives, substrate-rpc, substrate-rpc-servers, -substrate-serializer, substrate-service, substrate-service-test, substrate-state-db, -substrate-state-machine, substrate-telemetry, substrate-test-client, -substrate-test-runtime, substrate-transaction-graph, sp-transaction-pool, -substrate-trie -* Substrate Runtime -[source, shell] -sr-api, sr-io, sr-primitives, sr-sandbox, sr-std, sr-version -* FRAME Core -[source, shell] -frame-metadata, frame-support, frame-system -* FRAME Pallets -[source, shell] -pallet-assets, pallet-balances, pallet-consensus, pallet-contracts, pallet-council, pallet-democracy, pallet-example, -frame-executive, pallet-session, pallet-staking, pallet-timestamp, pallet-treasury -* Node -[source, shell] -node-cli, node-consensus, node-executor, node-network, node-primitives, kitchensink-runtime -* Subkey -[source, shell] -subkey - -=== Contributing to documentation for Substrate packages - -https://doc.rust-lang.org/1.9.0/book/documentation.html[Document source code] for Substrate packages by annotating the source code with documentation comments. - -Example (generic): -```markdown -/// Summary -/// -/// Description -/// -/// # Panics -/// -/// # Errors -/// -/// # Safety -/// -/// # Examples -/// -/// Summary of Example 1 -/// -/// ```rust -/// // insert example 1 code here -/// ``` -/// -``` - -* Important notes: -** Documentation comments must use annotations with a triple slash `///` -** Modules are documented using `//!` -``` -//! Summary (of module) -//! -//! Description (of module) -``` -* Special section header is indicated with a hash `#`. -** `Panics` section requires an explanation if the function triggers a panic -** `Errors` section is for describing conditions under which a function of method returns `Err(E)` if it returns a `Result` -** `Safety` section requires an explanation if the function is `unsafe` -** `Examples` section includes examples of using the function or method -* Code block annotations for examples are included between triple graves, as shown above. -Instead of including the programming language to use for syntax highlighting as the annotation -after the triple graves, alternative annotations include the `ignore`, `text`, `should_panic`, or `no_run`. -* Summary sentence is a short high level single sentence of its functionality -* Description paragraph is for details additional to the summary sentence -* Missing documentation annotations may be used to identify where to generate warnings with `#![warn(missing_docs)]` -or errors `#![deny(missing_docs)]` -* Hide documentation for items with `#[doc(hidden)]` - -=== Contributing to documentation (tests, extended examples, macros) for Substrate packages - -The code block annotations in the `# Example` section may be used as https://doc.rust-lang.org/1.9.0/book/documentation.html#documentation-as-tests[documentation as tests and for extended examples]. - -* Important notes: -** Rustdoc will automatically add a `main()` wrapper around the code block to test it -** https://doc.rust-lang.org/1.9.0/book/documentation.html#documenting-macros[Documenting macros]. -** Documentation as tests examples are included when running `cargo test` - -== Contributing - -=== Contributing Guidelines - -include::CONTRIBUTING.md[] - -=== Contributor Code of Conduct - -include::CODE_OF_CONDUCT.md[] - -== License - -https://github.com/paritytech/substrate/blob/master/LICENSE[LICENSE] diff --git a/substrate/docs/Structure.adoc b/substrate/docs/Structure.adoc deleted file mode 100644 index 6c810a83c51b..000000000000 --- a/substrate/docs/Structure.adoc +++ /dev/null @@ -1,121 +0,0 @@ -= Structure -:Author: Substrate developers -:Revision: 0.3.0 -:toc: -:sectnums: - - -== Overview - -Substrate is split into multiple levels with increasing opinion and decreasing flexibility: - -* primitives -* client -* FRAME (formerly `srml`) - -Putting all these components together we have: - -* Integration Tests -* Node -* Node template -* Subkey - -=== Runtime - -* _found in_: `/primitives` -* _crates prefix_: `sp-` -* _constraints_: -** must be `[no_std]` -** crates may not (dev-)depend on crates in other subfolders of this repo - -In the lowest level, Substrate defines primitives, interfaces and traits to implement any on-chain Substrate transition system and its interactions with the outside world. This is the lowest level of abstraction and opinion that everything else builds upon. - -=== Client - -* _found in_: `/client` -* _crates prefix_: `sc-` -* _constraints_: -** crates may not (dev-)depend on any `frame-`-crates - -In the client you can find a set of crates to construct the outer substrate-node, implementing outer runtime interfaces, thus it depends on `runtime`. It provides the outer building blocks like transaction queue, networking layer, database backend, full* and light-client support. - -=== FRAME (formerly `srml`) - -* _found in_: `/frame` -* _crates prefix_: `frame-` and `pallet-` -* _constraints_: -** all crates that go on chain must be `[no_std]` -** must not (dev-)depend on anything in `/client` - -FRAME is a set of modules that implement specific transition functions and features one might want to have in their runtime. - -_Pallets_ are individual modules within _FRAME._ These are containers that host domain-specific logic. They have the `pallet-` prefix. For example, `pallet-staking` contains logic for staking tokens. - -There are a few crates with the `frame-` prefix. These do not contain domain-specific logic. Rather, they are the main FRAME support infrastructure. These are: - -- Executive -- Metadata -- Support -- System -- Utility - -=== Integration Tests - -* _found in_: `/test` -* _crates prefix_: `substrate-test` -* _constraints_: -** only helpers may be published -** purely testing crates must be `publish = false` - -All tests that have to pull (dev)-dependencies out of their subtree and would thus break the dependency rules are considered integration tests and should be stored in here. Only helper-crates in here shall be published, everything else is expected to be non-publish. - -=== Binaries and template - -* _found in_: `/bin` - -We also provide some binaries pulling from the components creating full applications. - -==== Node - -* _found in_: `/bin/node` - -The default (testing) application pulling together our recommended setup of substrate-client with a wasm-contracts-supporting frame-runtime. The node pulls it all together, constructs the (upgradable) runtime, and wires up the client around it. You can find an example client, which includes a full wasm-contracts chain in `node`. This is also what is being built and run if you do `cargo run`. - -==== Node Template - -* _found in_: `/bin/node-template` - -We also provide a template to get you started building your own node. - -==== Utils - -* _found in_: `/bin/utils` - -- **subkey** - Subkey is a client library to generate keys and sign transactions to send to a substrate node. -- **chain-spec-builder** - The chain spec builder builds a chain specification that includes a Substrate runtime compiled as WASM. To ensure proper functioning of the included runtime compile (or run) the chain spec builder binary in `--release` mode. - -== Internal Dependency Tree - -[ditaa] -.... -+---------------+ +----------------+ -| | | | -| runtime +<------+ frame | -| | | | -+------+-----+--+ +-------------+--+ - ^ ^ ^ - | +----------------+ | - | | | -+------+--------+ | | -| | | | -| client | +--+-------+--------+ -| +<---------+ | -+---------------+ | | - | test /bin/* | - | | - | | - +-------------------+ - -.... From 79edd91f8a7eaadbcb4a642b2bbf8af08fd57bec Mon Sep 17 00:00:00 2001 From: ordian Date: Mon, 4 Sep 2023 16:48:12 +0200 Subject: [PATCH 019/103] approval-voting: use proper hash when querying session info (#1387) --- polkadot/node/core/approval-voting/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 0087f8e14350..ddef736feab7 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -2350,7 +2350,7 @@ async fn process_wakeup( match get_extended_session_info( session_info_provider, ctx.sender(), - block_entry.parent_hash(), + block_entry.block_hash(), block_entry.session(), ) .await From daf614109ff917b9e63995052190b17b60208409 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:58:32 +0200 Subject: [PATCH 020/103] [ci] Remove runtime-benchmarks from tests (#1335) * [ci] Remove runtime-benchmarks from tests * Update .gitlab/pipeline/test.yml Co-authored-by: Oliver Tale-Yazdi * remove ing * move benchmark tests to additional tests * rm -q option * try release profile * use testnet profile * move to a separate job * rm dup --------- Co-authored-by: Oliver Tale-Yazdi --- .gitlab/pipeline/test.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index c81750d49f92..d128cb099021 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -34,7 +34,7 @@ test-linux-stable: --locked \ --release \ --no-fail-fast \ - --features runtime-benchmarks,try-runtime,experimental \ + --features try-runtime,experimental \ --partition count:${CI_NODE_INDEX}/${CI_NODE_TOTAL} # run runtime-api tests with `enable-staging-api` feature on the 1st node - if [ ${CI_NODE_INDEX} == 1 ]; then time cargo nextest run -p sp-api-test --features enable-staging-api; fi @@ -92,7 +92,22 @@ test-linux-stable-additional-tests: --locked \ --release \ --features runtime-benchmarks,try-runtime - allow_failure: true + +# https://github.com/paritytech/ci_cd/issues/864 +test-linux-stable-runtime-benchmarks: + stage: test + extends: + - .docker-env + - .common-refs + - .run-immediately + - .pipeline-stopper-artifacts + variables: + RUST_TOOLCHAIN: stable + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings" + script: + - time cargo nextest run --features runtime-benchmarks benchmark --locked --cargo-profile testnet # these ones can be really slow so it's better to run them separately test-linux-stable-slow: From c08d14d93e29a3f8b609389714bd8681df861e1b Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Mon, 4 Sep 2023 18:27:53 +0300 Subject: [PATCH 021/103] Extract block announce validation from `ChainSync` (#1170) --- substrate/client/network/common/src/sync.rs | 68 +-- .../sync/src/block_announce_validator.rs | 405 +++++++++++++++ substrate/client/network/sync/src/engine.rs | 153 +++--- .../client/network/sync/src/futures_stream.rs | 134 +++++ substrate/client/network/sync/src/lib.rs | 488 ++++-------------- substrate/client/network/sync/src/mock.rs | 15 +- substrate/client/utils/src/mpsc.rs | 10 + 7 files changed, 727 insertions(+), 546 deletions(-) create mode 100644 substrate/client/network/sync/src/block_announce_validator.rs create mode 100644 substrate/client/network/sync/src/futures_stream.rs diff --git a/substrate/client/network/common/src/sync.rs b/substrate/client/network/common/src/sync.rs index b142925aeb10..461c4ae411d6 100644 --- a/substrate/client/network/common/src/sync.rs +++ b/substrate/client/network/common/src/sync.rs @@ -22,12 +22,12 @@ pub mod message; pub mod metrics; pub mod warp; -use crate::{role::Roles, types::ReputationChange}; +use crate::{role::Roles, sync::message::BlockAnnounce, types::ReputationChange}; use futures::Stream; use libp2p_identity::PeerId; -use message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse}; +use message::{BlockData, BlockRequest, BlockResponse}; use sc_consensus::{import_queue::RuntimeOrigin, IncomingBlock}; use sp_consensus::BlockOrigin; use sp_runtime::{ @@ -157,38 +157,6 @@ pub enum ImportResult { JustificationImport(RuntimeOrigin, B::Hash, NumberFor, Justifications), } -/// Value polled from `ChainSync` -#[derive(Debug)] -pub enum PollResult { - Import(ImportResult), - Announce(PollBlockAnnounceValidation), -} - -/// Result of [`ChainSync::poll_block_announce_validation`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum PollBlockAnnounceValidation { - /// The announcement failed at validation. - /// - /// The peer reputation should be decreased. - Failure { - /// Who sent the processed block announcement? - who: PeerId, - /// Should the peer be disconnected? - disconnect: bool, - }, - /// The announcement does not require further handling. - Nothing { - /// Who sent the processed block announcement? - who: PeerId, - /// Was this their new best block? - is_best: bool, - /// The announcement. - announce: BlockAnnounce, - }, - /// The block announcement should be skipped. - Skip, -} - /// Sync operation mode. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum SyncMode { @@ -408,29 +376,14 @@ pub trait ChainSync: Send { /// Notify about finalization of the given block. fn on_block_finalized(&mut self, hash: &Block::Hash, number: NumberFor); - /// Push a block announce validation. - /// - /// It is required that [`ChainSync::poll_block_announce_validation`] is called - /// to check for finished block announce validations. - fn push_block_announce_validation( + /// Notify about pre-validated block announcement. + fn on_validated_block_announce( &mut self, - who: PeerId, - hash: Block::Hash, - announce: BlockAnnounce, is_best: bool, + who: PeerId, + announce: &BlockAnnounce, ); - /// Poll block announce validation. - /// - /// Block announce validations can be pushed by using - /// [`ChainSync::push_block_announce_validation`]. - /// - /// This should be polled until it returns [`Poll::Pending`]. - fn poll_block_announce_validation( - &mut self, - cx: &mut std::task::Context<'_>, - ) -> Poll>; - /// Call when a peer has disconnected. /// Canceled obsolete block request may result in some blocks being ready for /// import, so this functions checks for such blocks and returns them. @@ -447,14 +400,7 @@ pub trait ChainSync: Send { ) -> Result>, String>; /// Advance the state of `ChainSync` - /// - /// Internally calls [`ChainSync::poll_block_announce_validation()`] and - /// this function should be polled until it returns [`Poll::Pending`] to - /// consume all pending events. - fn poll( - &mut self, - cx: &mut std::task::Context, - ) -> Poll>; + fn poll(&mut self, cx: &mut std::task::Context) -> Poll<()>; /// Send block request to peer fn send_block_request(&mut self, who: PeerId, request: BlockRequest); diff --git a/substrate/client/network/sync/src/block_announce_validator.rs b/substrate/client/network/sync/src/block_announce_validator.rs new file mode 100644 index 000000000000..f083f9e29e44 --- /dev/null +++ b/substrate/client/network/sync/src/block_announce_validator.rs @@ -0,0 +1,405 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 . + +//! `BlockAnnounceValidator` is responsible for async validation of block announcements. + +use crate::futures_stream::FuturesStream; +use futures::{Future, FutureExt, Stream, StreamExt}; +use libp2p::PeerId; +use log::{debug, error, trace, warn}; +use sc_network_common::sync::message::BlockAnnounce; +use sp_consensus::block_validation::Validation; +use sp_runtime::traits::{Block as BlockT, Header, Zero}; +use std::{ + collections::{hash_map::Entry, HashMap}, + default::Default, + pin::Pin, + task::{Context, Poll}, +}; + +/// Log target for this file. +const LOG_TARGET: &str = "sync"; + +/// Maximum number of concurrent block announce validations. +/// +/// If the queue reaches the maximum, we drop any new block +/// announcements. +const MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS: usize = 256; + +/// Maximum number of concurrent block announce validations per peer. +/// +/// See [`MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS`] for more information. +const MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS_PER_PEER: usize = 4; + +/// Item that yields [`Stream`] implementation of [`BlockAnnounceValidator`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum BlockAnnounceValidationResult { + /// The announcement failed at validation. + /// + /// The peer reputation should be decreased. + Failure { + /// The id of the peer that send us the announcement. + peer_id: PeerId, + /// Should the peer be disconnected? + disconnect: bool, + }, + /// The announcement was validated successfully and should be passed to [`crate::ChainSync`]. + Process { + /// The id of the peer that send us the announcement. + peer_id: PeerId, + /// Was this their new best block? + is_new_best: bool, + /// The announcement. + announce: BlockAnnounce, + }, + /// The block announcement should be skipped. + Skip { + /// The id of the peer that send us the announcement. + peer_id: PeerId, + }, +} + +impl BlockAnnounceValidationResult { + fn peer_id(&self) -> &PeerId { + match self { + BlockAnnounceValidationResult::Failure { peer_id, .. } | + BlockAnnounceValidationResult::Process { peer_id, .. } | + BlockAnnounceValidationResult::Skip { peer_id } => peer_id, + } + } +} + +/// Result of [`BlockAnnounceValidator::allocate_slot_for_block_announce_validation`]. +enum AllocateSlotForBlockAnnounceValidation { + /// Success, there is a slot for the block announce validation. + Allocated, + /// We reached the total maximum number of validation slots. + TotalMaximumSlotsReached, + /// We reached the maximum number of validation slots for the given peer. + MaximumPeerSlotsReached, +} + +pub(crate) struct BlockAnnounceValidator { + /// A type to check incoming block announcements. + validator: Box + Send>, + /// All block announcements that are currently being validated. + validations: FuturesStream< + Pin> + Send>>, + >, + /// Number of concurrent block announce validations per peer. + validations_per_peer: HashMap, +} + +impl BlockAnnounceValidator { + pub(crate) fn new( + validator: Box + Send>, + ) -> Self { + Self { + validator, + validations: Default::default(), + validations_per_peer: Default::default(), + } + } + + /// Push a block announce validation. + pub(crate) fn push_block_announce_validation( + &mut self, + peer_id: PeerId, + hash: B::Hash, + announce: BlockAnnounce, + is_best: bool, + ) { + let header = &announce.header; + let number = *header.number(); + debug!( + target: LOG_TARGET, + "Pre-validating received block announcement {:?} with number {:?} from {}", + hash, + number, + peer_id, + ); + + if number.is_zero() { + warn!( + target: LOG_TARGET, + "💔 Ignored genesis block (#0) announcement from {}: {}", + peer_id, + hash, + ); + return + } + + // Try to allocate a slot for this block announce validation. + match self.allocate_slot_for_block_announce_validation(&peer_id) { + AllocateSlotForBlockAnnounceValidation::Allocated => {}, + AllocateSlotForBlockAnnounceValidation::TotalMaximumSlotsReached => { + warn!( + target: LOG_TARGET, + "💔 Ignored block (#{} -- {}) announcement from {} because all validation slots are occupied.", + number, + hash, + peer_id, + ); + return + }, + AllocateSlotForBlockAnnounceValidation::MaximumPeerSlotsReached => { + warn!( + target: LOG_TARGET, + "💔 Ignored block (#{} -- {}) announcement from {} because all validation slots for this peer are occupied.", + number, + hash, + peer_id, + ); + return + }, + } + + // Let external validator check the block announcement. + let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice()); + let future = self.validator.validate(header, assoc_data); + + self.validations.push( + async move { + match future.await { + Ok(Validation::Success { is_new_best }) => { + let is_new_best = is_new_best || is_best; + + trace!( + target: LOG_TARGET, + "Block announcement validated successfully: from {}: {:?}. Local best: {}.", + peer_id, + announce.summary(), + is_new_best, + ); + + BlockAnnounceValidationResult::Process { is_new_best, announce, peer_id } + }, + Ok(Validation::Failure { disconnect }) => { + debug!( + target: LOG_TARGET, + "Block announcement validation failed: from {}, block {:?}. Disconnect: {}.", + peer_id, + hash, + disconnect, + ); + + BlockAnnounceValidationResult::Failure { peer_id, disconnect } + }, + Err(e) => { + debug!( + target: LOG_TARGET, + "💔 Ignoring block announcement validation from {} of block {:?} due to internal error: {}.", + peer_id, + hash, + e, + ); + + BlockAnnounceValidationResult::Skip { peer_id } + }, + } + } + .boxed(), + ); + } + + /// Checks if there is a slot for a block announce validation. + /// + /// The total number and the number per peer of concurrent block announce validations + /// is capped. + /// + /// Returns [`AllocateSlotForBlockAnnounceValidation`] to inform about the result. + /// + /// # Note + /// + /// It is *required* to call [`Self::deallocate_slot_for_block_announce_validation`] when the + /// validation is finished to clear the slot. + fn allocate_slot_for_block_announce_validation( + &mut self, + peer_id: &PeerId, + ) -> AllocateSlotForBlockAnnounceValidation { + if self.validations.len() >= MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS { + return AllocateSlotForBlockAnnounceValidation::TotalMaximumSlotsReached + } + + match self.validations_per_peer.entry(*peer_id) { + Entry::Vacant(entry) => { + entry.insert(1); + AllocateSlotForBlockAnnounceValidation::Allocated + }, + Entry::Occupied(mut entry) => { + if *entry.get() < MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS_PER_PEER { + *entry.get_mut() += 1; + AllocateSlotForBlockAnnounceValidation::Allocated + } else { + AllocateSlotForBlockAnnounceValidation::MaximumPeerSlotsReached + } + }, + } + } + + /// Should be called when a block announce validation is finished, to update the slots + /// of the peer that send the block announce. + fn deallocate_slot_for_block_announce_validation(&mut self, peer_id: &PeerId) { + match self.validations_per_peer.entry(*peer_id) { + Entry::Vacant(_) => { + error!( + target: LOG_TARGET, + "💔 Block announcement validation from peer {} finished for a slot that was not allocated!", + peer_id, + ); + }, + Entry::Occupied(mut entry) => match entry.get().checked_sub(1) { + Some(value) => + if value == 0 { + entry.remove(); + } else { + *entry.get_mut() = value; + }, + None => { + entry.remove(); + + error!( + target: LOG_TARGET, + "Invalid (zero) block announce validation slot counter for peer {peer_id}.", + ); + debug_assert!( + false, + "Invalid (zero) block announce validation slot counter for peer {peer_id}.", + ); + }, + }, + } + } +} + +impl Stream for BlockAnnounceValidator { + type Item = BlockAnnounceValidationResult; + + /// Poll for finished block announce validations. The stream never terminates. + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let validation = futures::ready!(self.validations.poll_next_unpin(cx)) + .expect("`FuturesStream` never terminates; qed"); + self.deallocate_slot_for_block_announce_validation(validation.peer_id()); + + Poll::Ready(Some(validation)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::block_announce_validator::AllocateSlotForBlockAnnounceValidation; + use libp2p::PeerId; + use sp_consensus::block_validation::DefaultBlockAnnounceValidator; + use substrate_test_runtime_client::runtime::Block; + + #[test] + fn allocate_one_validation_slot() { + let mut validator = + BlockAnnounceValidator::::new(Box::new(DefaultBlockAnnounceValidator {})); + let peer_id = PeerId::random(); + + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::Allocated, + )); + } + + #[test] + fn allocate_validation_slots_for_two_peers() { + let mut validator = + BlockAnnounceValidator::::new(Box::new(DefaultBlockAnnounceValidator {})); + let peer_id_1 = PeerId::random(); + let peer_id_2 = PeerId::random(); + + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id_1), + AllocateSlotForBlockAnnounceValidation::Allocated, + )); + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id_2), + AllocateSlotForBlockAnnounceValidation::Allocated, + )); + } + + #[test] + fn maximum_validation_slots_per_peer() { + let mut validator = + BlockAnnounceValidator::::new(Box::new(DefaultBlockAnnounceValidator {})); + let peer_id = PeerId::random(); + + for _ in 0..MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS_PER_PEER { + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::Allocated, + )); + } + + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::MaximumPeerSlotsReached, + )); + } + + #[test] + fn validation_slots_per_peer_deallocated() { + let mut validator = + BlockAnnounceValidator::::new(Box::new(DefaultBlockAnnounceValidator {})); + let peer_id = PeerId::random(); + + for _ in 0..MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS_PER_PEER { + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::Allocated, + )); + } + + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::MaximumPeerSlotsReached, + )); + + validator.deallocate_slot_for_block_announce_validation(&peer_id); + + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::Allocated, + )); + } + + #[test] + fn maximum_validation_slots_for_all_peers() { + let mut validator = + BlockAnnounceValidator::::new(Box::new(DefaultBlockAnnounceValidator {})); + + for _ in 0..MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS { + validator.validations.push( + futures::future::ready(BlockAnnounceValidationResult::Skip { + peer_id: PeerId::random(), + }) + .boxed(), + ); + } + + let peer_id = PeerId::random(); + assert!(matches!( + validator.allocate_slot_for_block_announce_validation(&peer_id), + AllocateSlotForBlockAnnounceValidation::TotalMaximumSlotsReached, + )); + } +} diff --git a/substrate/client/network/sync/src/engine.rs b/substrate/client/network/sync/src/engine.rs index 65bd56a28958..9b97bf2b7c34 100644 --- a/substrate/client/network/sync/src/engine.rs +++ b/substrate/client/network/sync/src/engine.rs @@ -20,6 +20,9 @@ //! to tip and keep the blockchain up to date with network updates. use crate::{ + block_announce_validator::{ + BlockAnnounceValidationResult, BlockAnnounceValidator as BlockAnnounceValidatorStream, + }, service::{self, chain_sync::ToServiceCommand}, ChainSync, ClientError, SyncingService, }; @@ -45,7 +48,7 @@ use sc_network_common::{ sync::{ message::{BlockAnnounce, BlockAnnouncesHandshake, BlockState}, warp::WarpSyncParams, - BadPeer, ChainSync as ChainSyncT, ExtendedPeerInfo, PollBlockAnnounceValidation, SyncEvent, + BadPeer, ChainSync as ChainSyncT, ExtendedPeerInfo, SyncEvent, }, }; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; @@ -239,6 +242,9 @@ pub struct SyncingEngine { /// Number of inbound peers accepted so far. num_in_peers: usize, + /// Async processor of block announce validations. + block_announce_validator: BlockAnnounceValidatorStream, + /// A cache for the data that was associated to a block announcement. block_announce_data_cache: LruMap>, @@ -352,7 +358,6 @@ where protocol_id, fork_id, roles, - block_announce_validator, max_parallel_downloads, max_blocks_per_request, warp_sync_params, @@ -389,6 +394,9 @@ where peers: HashMap::new(), block_announce_data_cache: LruMap::new(ByLength::new(cache_capacity)), block_announce_protocol_name, + block_announce_validator: BlockAnnounceValidatorStream::new( + block_announce_validator, + ), num_connected: num_connected.clone(), is_major_syncing: is_major_syncing.clone(), service_rx, @@ -453,9 +461,9 @@ where } } - fn update_peer_info(&mut self, who: &PeerId) { - if let Some(info) = self.chain_sync.peer_info(who) { - if let Some(ref mut peer) = self.peers.get_mut(who) { + fn update_peer_info(&mut self, peer_id: &PeerId) { + if let Some(info) = self.chain_sync.peer_info(peer_id) { + if let Some(ref mut peer) = self.peers.get_mut(peer_id) { peer.info.best_hash = info.best_hash; peer.info.best_number = info.best_number; } @@ -463,14 +471,16 @@ where } /// Process the result of the block announce validation. - pub fn process_block_announce_validation_result( + fn process_block_announce_validation_result( &mut self, - validation_result: PollBlockAnnounceValidation, + validation_result: BlockAnnounceValidationResult, ) { match validation_result { - PollBlockAnnounceValidation::Skip => {}, - PollBlockAnnounceValidation::Nothing { is_best: _, who, announce } => { - self.update_peer_info(&who); + BlockAnnounceValidationResult::Skip { peer_id: _ } => {}, + BlockAnnounceValidationResult::Process { is_new_best, peer_id, announce } => { + self.chain_sync.on_validated_block_announce(is_new_best, peer_id, &announce); + + self.update_peer_info(&peer_id); if let Some(data) = announce.data { if !data.is_empty() { @@ -478,41 +488,29 @@ where } } }, - PollBlockAnnounceValidation::Failure { who, disconnect } => { + BlockAnnounceValidationResult::Failure { peer_id, disconnect } => { if disconnect { self.network_service - .disconnect_peer(who, self.block_announce_protocol_name.clone()); + .disconnect_peer(peer_id, self.block_announce_protocol_name.clone()); } - self.network_service.report_peer(who, rep::BAD_BLOCK_ANNOUNCEMENT); + self.network_service.report_peer(peer_id, rep::BAD_BLOCK_ANNOUNCEMENT); }, } } /// Push a block announce validation. - /// - /// It is required that [`ChainSync::poll_block_announce_validation`] is - /// called later to check for finished validations. The result of the validation - /// needs to be passed to [`SyncingEngine::process_block_announce_validation_result`] - /// to finish the processing. - /// - /// # Note - /// - /// This will internally create a future, but this future will not be registered - /// in the task before being polled once. So, it is required to call - /// [`ChainSync::poll_block_announce_validation`] to ensure that the future is - /// registered properly and will wake up the task when being ready. pub fn push_block_announce_validation( &mut self, - who: PeerId, + peer_id: PeerId, announce: BlockAnnounce, ) { let hash = announce.header.hash(); - let peer = match self.peers.get_mut(&who) { + let peer = match self.peers.get_mut(&peer_id) { Some(p) => p, None => { - log::error!(target: "sync", "Received block announce from disconnected peer {}", who); + log::error!(target: "sync", "Received block announce from disconnected peer {}", peer_id); debug_assert!(false); return }, @@ -525,7 +523,8 @@ where BlockState::Normal => false, }; - self.chain_sync.push_block_announce_validation(who, hash, announce, is_best); + self.block_announce_validator + .push_block_announce_validation(peer_id, hash, announce, is_best); } } @@ -558,10 +557,10 @@ where .or_else(|| self.block_announce_data_cache.get(&hash).cloned()) .unwrap_or_default(); - for (who, ref mut peer) in self.peers.iter_mut() { + for (peer_id, ref mut peer) in self.peers.iter_mut() { let inserted = peer.known_blocks.insert(hash); if inserted { - log::trace!(target: "sync", "Announcing block {:?} to {}", hash, who); + log::trace!(target: "sync", "Announcing block {:?} to {}", hash, peer_id); let message = BlockAnnounce { header: header.clone(), state: if is_best { Some(BlockState::Best) } else { Some(BlockState::Normal) }, @@ -656,14 +655,14 @@ where } } }, - ToServiceCommand::JustificationImported(peer, hash, number, success) => { + ToServiceCommand::JustificationImported(peer_id, hash, number, success) => { self.chain_sync.on_justification_import(hash, number, success); if !success { - log::info!(target: "sync", "💔 Invalid justification provided by {} for #{}", peer, hash); + log::info!(target: "sync", "💔 Invalid justification provided by {} for #{}", peer_id, hash); self.network_service - .disconnect_peer(peer, self.block_announce_protocol_name.clone()); + .disconnect_peer(peer_id, self.block_announce_protocol_name.clone()); self.network_service.report_peer( - peer, + peer_id, ReputationChange::new_fatal("Invalid justification"), ); } @@ -698,8 +697,11 @@ where let _ = tx.send(self.chain_sync.num_sync_requests()); }, ToServiceCommand::PeersInfo(tx) => { - let peers_info = - self.peers.iter().map(|(id, peer)| (*id, peer.info.clone())).collect(); + let peers_info = self + .peers + .iter() + .map(|(peer_id, peer)| (*peer_id, peer.info.clone())) + .collect(); let _ = tx.send(peers_info); }, ToServiceCommand::OnBlockFinalized(hash, header) => @@ -742,14 +744,6 @@ where if let Ok(announce) = BlockAnnounce::decode(&mut message.as_ref()) { self.last_notification_io = Instant::now(); self.push_block_announce_validation(remote, announce); - - // Make sure that the newly added block announce validation future - // was polled once to be registered in the task. - if let Poll::Ready(res) = - self.chain_sync.poll_block_announce_validation(cx) - { - self.process_block_announce_validation_result(res) - } } else { log::warn!(target: "sub-libp2p", "Failed to decode block announce"); } @@ -770,10 +764,14 @@ where } } - // poll `ChainSync` last because of a block announcement was received through the - // event stream between `SyncingEngine` and `Protocol` and the validation finished - // right after it as queued, the resulting block request (if any) can be sent right away. - while let Poll::Ready(result) = self.chain_sync.poll(cx) { + // Drive `ChainSync`. + while let Poll::Ready(()) = self.chain_sync.poll(cx) {} + + // Poll block announce validations last, because if a block announcement was received + // through the event stream between `SyncingEngine` and `Protocol` and the validation + // finished right after it is queued, the resulting block request (if any) can be sent + // right away. + while let Poll::Ready(Some(result)) = self.block_announce_validator.poll_next_unpin(cx) { self.process_block_announce_validation_result(result); } @@ -783,15 +781,15 @@ where /// Called by peer when it is disconnecting. /// /// Returns a result if the handshake of this peer was indeed accepted. - pub fn on_sync_peer_disconnected(&mut self, peer: PeerId) -> Result<(), ()> { - if let Some(info) = self.peers.remove(&peer) { - if self.important_peers.contains(&peer) { - log::warn!(target: "sync", "Reserved peer {} disconnected", peer); + pub fn on_sync_peer_disconnected(&mut self, peer_id: PeerId) -> Result<(), ()> { + if let Some(info) = self.peers.remove(&peer_id) { + if self.important_peers.contains(&peer_id) { + log::warn!(target: "sync", "Reserved peer {} disconnected", peer_id); } else { - log::debug!(target: "sync", "{} disconnected", peer); + log::debug!(target: "sync", "{} disconnected", peer_id); } - if !self.default_peers_set_no_slot_connected_peers.remove(&peer) && + if !self.default_peers_set_no_slot_connected_peers.remove(&peer_id) && info.inbound && info.info.roles.is_full() { match self.num_in_peers.checked_sub(1) { @@ -808,9 +806,10 @@ where } } - self.chain_sync.peer_disconnected(&peer); - self.event_streams - .retain(|stream| stream.unbounded_send(SyncEvent::PeerDisconnected(peer)).is_ok()); + self.chain_sync.peer_disconnected(&peer_id); + self.event_streams.retain(|stream| { + stream.unbounded_send(SyncEvent::PeerDisconnected(peer_id)).is_ok() + }); Ok(()) } else { Err(()) @@ -824,35 +823,35 @@ where /// from. pub fn on_sync_peer_connected( &mut self, - who: PeerId, + peer_id: PeerId, status: &BlockAnnouncesHandshake, sink: NotificationsSink, inbound: bool, ) -> Result<(), ()> { - log::trace!(target: "sync", "New peer {} {:?}", who, status); + log::trace!(target: "sync", "New peer {} {:?}", peer_id, status); - if self.peers.contains_key(&who) { - log::error!(target: "sync", "Called on_sync_peer_connected with already connected peer {}", who); + if self.peers.contains_key(&peer_id) { + log::error!(target: "sync", "Called on_sync_peer_connected with already connected peer {}", peer_id); debug_assert!(false); return Err(()) } if status.genesis_hash != self.genesis_hash { - self.network_service.report_peer(who, rep::GENESIS_MISMATCH); + self.network_service.report_peer(peer_id, rep::GENESIS_MISMATCH); - if self.important_peers.contains(&who) { + if self.important_peers.contains(&peer_id) { log::error!( target: "sync", "Reserved peer id `{}` is on a different chain (our genesis: {} theirs: {})", - who, + peer_id, self.genesis_hash, status.genesis_hash, ); - } else if self.boot_node_ids.contains(&who) { + } else if self.boot_node_ids.contains(&peer_id) { log::error!( target: "sync", "Bootnode with peer id `{}` is on a different chain (our genesis: {} theirs: {})", - who, + peer_id, self.genesis_hash, status.genesis_hash, ); @@ -867,7 +866,7 @@ where return Err(()) } - let no_slot_peer = self.default_peers_set_no_slot_peers.contains(&who); + let no_slot_peer = self.default_peers_set_no_slot_peers.contains(&peer_id); let this_peer_reserved_slot: usize = if no_slot_peer { 1 } else { 0 }; // make sure to accept no more than `--in-peers` many full nodes @@ -875,7 +874,7 @@ where status.roles.is_full() && inbound && self.num_in_peers == self.max_in_peers { - log::debug!(target: "sync", "All inbound slots have been consumed, rejecting {who}"); + log::debug!(target: "sync", "All inbound slots have been consumed, rejecting {peer_id}"); return Err(()) } @@ -885,7 +884,7 @@ where self.default_peers_set_no_slot_connected_peers.len() + this_peer_reserved_slot { - log::debug!(target: "sync", "Too many full nodes, rejecting {}", who); + log::debug!(target: "sync", "Too many full nodes, rejecting {}", peer_id); return Err(()) } @@ -893,7 +892,7 @@ where (self.peers.len() - self.chain_sync.num_peers()) >= self.default_peers_set_num_light { // Make sure that not all slots are occupied by light clients. - log::debug!(target: "sync", "Too many light nodes, rejecting {}", who); + log::debug!(target: "sync", "Too many light nodes, rejecting {}", peer_id); return Err(()) } @@ -911,7 +910,7 @@ where }; let req = if peer.info.roles.is_full() { - match self.chain_sync.new_peer(who, peer.info.best_hash, peer.info.best_number) { + match self.chain_sync.new_peer(peer_id, peer.info.best_hash, peer.info.best_number) { Ok(req) => req, Err(BadPeer(id, repu)) => { self.network_service.report_peer(id, repu); @@ -922,22 +921,22 @@ where None }; - log::debug!(target: "sync", "Connected {}", who); + log::debug!(target: "sync", "Connected {}", peer_id); - self.peers.insert(who, peer); + self.peers.insert(peer_id, peer); if no_slot_peer { - self.default_peers_set_no_slot_connected_peers.insert(who); + self.default_peers_set_no_slot_connected_peers.insert(peer_id); } else if inbound && status.roles.is_full() { self.num_in_peers += 1; } if let Some(req) = req { - self.chain_sync.send_block_request(who, req); + self.chain_sync.send_block_request(peer_id, req); } self.event_streams - .retain(|stream| stream.unbounded_send(SyncEvent::PeerConnected(who)).is_ok()); + .retain(|stream| stream.unbounded_send(SyncEvent::PeerConnected(peer_id)).is_ok()); Ok(()) } diff --git a/substrate/client/network/sync/src/futures_stream.rs b/substrate/client/network/sync/src/futures_stream.rs new file mode 100644 index 000000000000..c33d582345b6 --- /dev/null +++ b/substrate/client/network/sync/src/futures_stream.rs @@ -0,0 +1,134 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 . + +//! A wrapper for [`FuturesUnordered`] that wakes the task up once a new future is pushed +//! for it to be polled automatically. It's [`Stream`] never terminates. + +use futures::{stream::FuturesUnordered, Future, Stream, StreamExt}; +use std::{ + pin::Pin, + task::{Context, Poll, Waker}, +}; + +/// Wrapper around [`FuturesUnordered`] that wakes a task up automatically. +pub struct FuturesStream { + futures: FuturesUnordered, + waker: Option, +} + +/// Surprizingly, `#[derive(Default)]` doesn't work on [`FuturesStream`]. +impl Default for FuturesStream { + fn default() -> FuturesStream { + FuturesStream { futures: Default::default(), waker: None } + } +} + +impl FuturesStream { + /// Push a future for processing. + pub fn push(&mut self, future: F) { + self.futures.push(future); + + if let Some(waker) = self.waker.take() { + waker.wake(); + } + } + + /// The number of futures in the stream. + pub fn len(&self) -> usize { + self.futures.len() + } +} + +impl Stream for FuturesStream { + type Item = ::Output; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let Poll::Ready(Some(result)) = self.futures.poll_next_unpin(cx) else { + self.waker = Some(cx.waker().clone()); + + return Poll::Pending + }; + + Poll::Ready(Some(result)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::future::{BoxFuture, FutureExt}; + + /// [`Stream`] implementation for [`FuturesStream`] relies on the undocumented + /// feature that [`FuturesUnordered`] can be polled and repeatedly yield + /// `Poll::Ready(None)` before any futures are added into it. + #[tokio::test] + async fn empty_futures_unordered_can_be_polled() { + let mut unordered = FuturesUnordered::>::default(); + + futures::future::poll_fn(|cx| { + assert_eq!(unordered.poll_next_unpin(cx), Poll::Ready(None)); + assert_eq!(unordered.poll_next_unpin(cx), Poll::Ready(None)); + + Poll::Ready(()) + }) + .await; + } + + /// [`Stream`] implementation for [`FuturesStream`] relies on the undocumented + /// feature that [`FuturesUnordered`] can be polled and repeatedly yield + /// `Poll::Ready(None)` after all the futures in it have resolved. + #[tokio::test] + async fn deplenished_futures_unordered_can_be_polled() { + let mut unordered = FuturesUnordered::>::default(); + + unordered.push(futures::future::ready(()).boxed()); + assert_eq!(unordered.next().await, Some(())); + + futures::future::poll_fn(|cx| { + assert_eq!(unordered.poll_next_unpin(cx), Poll::Ready(None)); + assert_eq!(unordered.poll_next_unpin(cx), Poll::Ready(None)); + + Poll::Ready(()) + }) + .await; + } + + #[tokio::test] + async fn empty_futures_stream_yields_pending() { + let mut stream = FuturesStream::>::default(); + + futures::future::poll_fn(|cx| { + assert_eq!(stream.poll_next_unpin(cx), Poll::Pending); + Poll::Ready(()) + }) + .await; + } + + #[tokio::test] + async fn futures_stream_resolves_futures_and_yields_pending() { + let mut stream = FuturesStream::default(); + stream.push(futures::future::ready(17)); + + futures::future::poll_fn(|cx| { + assert_eq!(stream.poll_next_unpin(cx), Poll::Ready(Some(17))); + assert_eq!(stream.poll_next_unpin(cx), Poll::Pending); + Poll::Ready(()) + }) + .await; + } +} diff --git a/substrate/client/network/sync/src/lib.rs b/substrate/client/network/sync/src/lib.rs index 175c1c43f46f..0c2013b14977 100644 --- a/substrate/client/network/sync/src/lib.rs +++ b/substrate/client/network/sync/src/lib.rs @@ -37,9 +37,7 @@ use crate::{ use codec::{Decode, DecodeAll, Encode}; use extra_requests::ExtraRequests; -use futures::{ - channel::oneshot, stream::FuturesUnordered, task::Poll, Future, FutureExt, StreamExt, -}; +use futures::{channel::oneshot, task::Poll, Future, FutureExt}; use libp2p::{request_response::OutboundFailure, PeerId}; use log::{debug, error, info, trace, warn}; use prost::Message; @@ -66,16 +64,12 @@ use sc_network_common::{ warp::{EncodedProof, WarpProofRequest, WarpSyncParams, WarpSyncPhase, WarpSyncProgress}, BadPeer, ChainSync as ChainSyncT, ImportResult, Metrics, OnBlockData, OnBlockJustification, OnStateData, OpaqueBlockRequest, OpaqueBlockResponse, OpaqueStateRequest, - OpaqueStateResponse, PeerInfo, PeerRequest, PollBlockAnnounceValidation, SyncMode, - SyncState, SyncStatus, + OpaqueStateResponse, PeerInfo, PeerRequest, SyncMode, SyncState, SyncStatus, }, }; use sp_arithmetic::traits::Saturating; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata}; -use sp_consensus::{ - block_validation::{BlockAnnounceValidator, Validation}, - BlockOrigin, BlockStatus, -}; +use sp_consensus::{BlockOrigin, BlockStatus}; use sp_runtime::{ traits::{ Block as BlockT, CheckedSub, Hash, HashingFor, Header as HeaderT, NumberFor, One, @@ -85,7 +79,7 @@ use sp_runtime::{ }; use std::{ - collections::{hash_map::Entry, HashMap, HashSet}, + collections::{HashMap, HashSet}, iter, ops::Range, pin::Pin, @@ -94,7 +88,9 @@ use std::{ pub use service::chain_sync::SyncingService; +mod block_announce_validator; mod extra_requests; +mod futures_stream; mod schema; pub mod block_request_handler; @@ -117,17 +113,6 @@ const MAX_DOWNLOAD_AHEAD: u32 = 2048; /// common block of a node. const MAX_BLOCKS_TO_LOOK_BACKWARDS: u32 = MAX_DOWNLOAD_AHEAD / 2; -/// Maximum number of concurrent block announce validations. -/// -/// If the queue reaches the maximum, we drop any new block -/// announcements. -const MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS: usize = 256; - -/// Maximum number of concurrent block announce validations per peer. -/// -/// See [`MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS`] for more information. -const MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS_PER_PEER: usize = 4; - /// Pick the state to sync as the latest finalized number minus this. const STATE_SYNC_FINALITY_THRESHOLD: u32 = 8; @@ -307,19 +292,12 @@ pub struct ChainSync { fork_targets: HashMap>, /// A set of peers for which there might be potential block requests allowed_requests: AllowedRequests, - /// A type to check incoming block announcements. - block_announce_validator: Box + Send>, /// Maximum number of peers to ask the same blocks in parallel. max_parallel_downloads: u32, /// Maximum blocks per request. max_blocks_per_request: u32, /// Total number of downloaded blocks. downloaded_blocks: usize, - /// All block announcement that are currently being validated. - block_announce_validation: - FuturesUnordered> + Send>>>, - /// Stats per peer about the number of concurrent block announce validations. - block_announce_validation_per_peer_stats: HashMap, /// State sync in progress, if any. state_sync: Option>, /// Warp sync in progress, if any. @@ -424,51 +402,6 @@ impl PeerSyncState { } } -/// Result of [`ChainSync::block_announce_validation`]. -#[derive(Debug, Clone, PartialEq, Eq)] -enum PreValidateBlockAnnounce { - /// The announcement failed at validation. - /// - /// The peer reputation should be decreased. - Failure { - /// Who sent the processed block announcement? - who: PeerId, - /// Should the peer be disconnected? - disconnect: bool, - }, - /// The pre-validation was sucessful and the announcement should be - /// further processed. - Process { - /// Is this the new best block of the peer? - is_new_best: bool, - /// The id of the peer that send us the announcement. - who: PeerId, - /// The announcement. - announce: BlockAnnounce, - }, - /// The announcement validation returned an error. - /// - /// An error means that *this* node failed to validate it because some internal error happened. - /// If the block announcement was invalid, [`Self::Failure`] is the correct variant to express - /// this. - Error { who: PeerId }, - /// The block announcement should be skipped. - /// - /// This should *only* be returned when there wasn't a slot registered - /// for this block announcement validation. - Skip, -} - -/// Result of [`ChainSync::has_slot_for_block_announce_validation`]. -enum HasSlotForBlockAnnounceValidation { - /// Yes, there is a slot for the block announce validation. - Yes, - /// We reached the total maximum number of validation slots. - TotalMaximumSlotsReached, - /// We reached the maximum number of validation slots for the given peer. - MaximumPeerSlotsReached, -} - impl ChainSyncT for ChainSync where B: BlockT, @@ -692,7 +625,7 @@ where self.extra_justifications.reset(); } - // The implementation is similar to on_block_announce with unknown parent hash. + // The implementation is similar to `on_validated_block_announce` with unknown parent hash. fn set_sync_fork_request( &mut self, mut peers: Vec, @@ -1107,119 +1040,88 @@ where } } - fn push_block_announce_validation( + fn on_validated_block_announce( &mut self, - who: PeerId, - hash: B::Hash, - announce: BlockAnnounce, is_best: bool, + who: PeerId, + announce: &BlockAnnounce, ) { - let header = &announce.header; - let number = *header.number(); - debug!( - target: "sync", - "Pre-validating received block announcement {:?} with number {:?} from {}", - hash, - number, - who, - ); + let number = *announce.header.number(); + let hash = announce.header.hash(); + let parent_status = + self.block_status(announce.header.parent_hash()).unwrap_or(BlockStatus::Unknown); + let known_parent = parent_status != BlockStatus::Unknown; + let ancient_parent = parent_status == BlockStatus::InChainPruned; - if number.is_zero() { - self.block_announce_validation.push( - async move { - warn!( - target: "sync", - "💔 Ignored genesis block (#0) announcement from {}: {}", - who, - hash, - ); - PreValidateBlockAnnounce::Skip - } - .boxed(), - ); + let known = self.is_known(&hash); + let peer = if let Some(peer) = self.peers.get_mut(&who) { + peer + } else { + error!(target: "sync", "💔 Called `on_validated_block_announce` with a bad peer ID"); + return + }; + + if let PeerSyncState::AncestorSearch { .. } = peer.state { + trace!(target: "sync", "Peer {} is in the ancestor search state.", who); return } - // Check if there is a slot for this block announce validation. - match self.has_slot_for_block_announce_validation(&who) { - HasSlotForBlockAnnounceValidation::Yes => {}, - HasSlotForBlockAnnounceValidation::TotalMaximumSlotsReached => { - self.block_announce_validation.push( - async move { - warn!( - target: "sync", - "💔 Ignored block (#{} -- {}) announcement from {} because all validation slots are occupied.", - number, - hash, - who, - ); - PreValidateBlockAnnounce::Skip - } - .boxed(), - ); - return - }, - HasSlotForBlockAnnounceValidation::MaximumPeerSlotsReached => { - self.block_announce_validation.push(async move { - warn!( - target: "sync", - "💔 Ignored block (#{} -- {}) announcement from {} because all validation slots for this peer are occupied.", - number, - hash, - who, - ); - PreValidateBlockAnnounce::Skip - }.boxed()); - return - }, + if is_best { + // update their best block + peer.best_number = number; + peer.best_hash = hash; } - // Let external validator check the block announcement. - let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice()); - let future = self.block_announce_validator.validate(header, assoc_data); + // If the announced block is the best they have and is not ahead of us, our common number + // is either one further ahead or it's the one they just announced, if we know about it. + if is_best { + if known && self.best_queued_number >= number { + self.update_peer_common_number(&who, number); + } else if announce.header.parent_hash() == &self.best_queued_hash || + known_parent && self.best_queued_number >= number + { + self.update_peer_common_number(&who, number.saturating_sub(One::one())); + } + } + self.allowed_requests.add(&who); - self.block_announce_validation.push( - async move { - match future.await { - Ok(Validation::Success { is_new_best }) => PreValidateBlockAnnounce::Process { - is_new_best: is_new_best || is_best, - announce, - who, - }, - Ok(Validation::Failure { disconnect }) => { - debug!( - target: "sync", - "Block announcement validation of block {:?} from {} failed", - hash, - who, - ); - PreValidateBlockAnnounce::Failure { who, disconnect } - }, - Err(e) => { - debug!( - target: "sync", - "💔 Block announcement validation of block {:?} errored: {}", - hash, - e, - ); - PreValidateBlockAnnounce::Error { who } - }, - } + // known block case + if known || self.is_already_downloading(&hash) { + trace!(target: "sync", "Known block announce from {}: {}", who, hash); + if let Some(target) = self.fork_targets.get_mut(&hash) { + target.peers.insert(who); } - .boxed(), - ); - } + return + } - fn poll_block_announce_validation( - &mut self, - cx: &mut std::task::Context, - ) -> Poll> { - match self.block_announce_validation.poll_next_unpin(cx) { - Poll::Ready(Some(res)) => { - self.peer_block_announce_validation_finished(&res); - Poll::Ready(self.finish_block_announce_validation(res)) - }, - _ => Poll::Pending, + if ancient_parent { + trace!( + target: "sync", + "Ignored ancient block announced from {}: {} {:?}", + who, + hash, + announce.header, + ); + return + } + + if self.status().state == SyncState::Idle { + trace!( + target: "sync", + "Added sync target for block announced from {}: {} {:?}", + who, + hash, + announce.summary(), + ); + self.fork_targets + .entry(hash) + .or_insert_with(|| ForkTarget { + number, + parent_hash: Some(*announce.header.parent_hash()), + peers: Default::default(), + }) + .peers + .insert(who); } } @@ -1319,10 +1221,7 @@ where .map_err(|error: codec::Error| error.to_string()) } - fn poll( - &mut self, - cx: &mut std::task::Context, - ) -> Poll> { + fn poll(&mut self, cx: &mut std::task::Context) -> Poll<()> { // Should be called before `process_outbound_requests` to ensure // that a potential target block is directly leading to requests. if let Some(warp_sync) = &mut self.warp_sync { @@ -1339,10 +1238,6 @@ where } } - if let Poll::Ready(announce) = self.poll_block_announce_validation(cx) { - return Poll::Ready(announce) - } - Poll::Pending } @@ -1395,7 +1290,6 @@ where protocol_id: ProtocolId, fork_id: &Option, roles: Roles, - block_announce_validator: Box + Send>, max_parallel_downloads: u32, max_blocks_per_request: u32, warp_sync_params: Option>, @@ -1430,12 +1324,9 @@ where queue_blocks: Default::default(), fork_targets: Default::default(), allowed_requests: Default::default(), - block_announce_validator, max_parallel_downloads, max_blocks_per_request, downloaded_blocks: 0, - block_announce_validation: Default::default(), - block_announce_validation_per_peer_stats: Default::default(), state_sync: None, warp_sync: None, import_existing: false, @@ -1586,186 +1477,6 @@ where self.allowed_requests.set_all(); } - /// Checks if there is a slot for a block announce validation. - /// - /// The total number and the number per peer of concurrent block announce validations - /// is capped. - /// - /// Returns [`HasSlotForBlockAnnounceValidation`] to inform about the result. - /// - /// # Note - /// - /// It is *required* to call [`Self::peer_block_announce_validation_finished`] when the - /// validation is finished to clear the slot. - fn has_slot_for_block_announce_validation( - &mut self, - peer: &PeerId, - ) -> HasSlotForBlockAnnounceValidation { - if self.block_announce_validation.len() >= MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS { - return HasSlotForBlockAnnounceValidation::TotalMaximumSlotsReached - } - - match self.block_announce_validation_per_peer_stats.entry(*peer) { - Entry::Vacant(entry) => { - entry.insert(1); - HasSlotForBlockAnnounceValidation::Yes - }, - Entry::Occupied(mut entry) => { - if *entry.get() < MAX_CONCURRENT_BLOCK_ANNOUNCE_VALIDATIONS_PER_PEER { - *entry.get_mut() += 1; - HasSlotForBlockAnnounceValidation::Yes - } else { - HasSlotForBlockAnnounceValidation::MaximumPeerSlotsReached - } - }, - } - } - - /// Should be called when a block announce validation is finished, to update the slots - /// of the peer that send the block announce. - fn peer_block_announce_validation_finished( - &mut self, - res: &PreValidateBlockAnnounce, - ) { - let peer = match res { - PreValidateBlockAnnounce::Failure { who, .. } | - PreValidateBlockAnnounce::Process { who, .. } | - PreValidateBlockAnnounce::Error { who } => who, - PreValidateBlockAnnounce::Skip => return, - }; - - match self.block_announce_validation_per_peer_stats.entry(*peer) { - Entry::Vacant(_) => { - error!( - target: "sync", - "💔 Block announcement validation from peer {} finished for that no slot was allocated!", - peer, - ); - }, - Entry::Occupied(mut entry) => { - *entry.get_mut() = entry.get().saturating_sub(1); - if *entry.get() == 0 { - entry.remove(); - } - }, - } - } - - /// This will finish processing of the block announcement. - fn finish_block_announce_validation( - &mut self, - pre_validation_result: PreValidateBlockAnnounce, - ) -> PollBlockAnnounceValidation { - let (announce, is_best, who) = match pre_validation_result { - PreValidateBlockAnnounce::Failure { who, disconnect } => { - debug!( - target: "sync", - "Failed announce validation: {:?}, disconnect: {}", - who, - disconnect, - ); - return PollBlockAnnounceValidation::Failure { who, disconnect } - }, - PreValidateBlockAnnounce::Process { announce, is_new_best, who } => - (announce, is_new_best, who), - PreValidateBlockAnnounce::Error { .. } | PreValidateBlockAnnounce::Skip => { - debug!( - target: "sync", - "Ignored announce validation", - ); - return PollBlockAnnounceValidation::Skip - }, - }; - - trace!( - target: "sync", - "Finished block announce validation: from {:?}: {:?}. local_best={}", - who, - announce.summary(), - is_best, - ); - - let number = *announce.header.number(); - let hash = announce.header.hash(); - let parent_status = - self.block_status(announce.header.parent_hash()).unwrap_or(BlockStatus::Unknown); - let known_parent = parent_status != BlockStatus::Unknown; - let ancient_parent = parent_status == BlockStatus::InChainPruned; - - let known = self.is_known(&hash); - let peer = if let Some(peer) = self.peers.get_mut(&who) { - peer - } else { - error!(target: "sync", "💔 Called on_block_announce with a bad peer ID"); - return PollBlockAnnounceValidation::Nothing { is_best, who, announce } - }; - - if let PeerSyncState::AncestorSearch { .. } = peer.state { - trace!(target: "sync", "Peer state is ancestor search."); - return PollBlockAnnounceValidation::Nothing { is_best, who, announce } - } - - if is_best { - // update their best block - peer.best_number = number; - peer.best_hash = hash; - } - - // If the announced block is the best they have and is not ahead of us, our common number - // is either one further ahead or it's the one they just announced, if we know about it. - if is_best { - if known && self.best_queued_number >= number { - self.update_peer_common_number(&who, number); - } else if announce.header.parent_hash() == &self.best_queued_hash || - known_parent && self.best_queued_number >= number - { - self.update_peer_common_number(&who, number - One::one()); - } - } - self.allowed_requests.add(&who); - - // known block case - if known || self.is_already_downloading(&hash) { - trace!(target: "sync", "Known block announce from {}: {}", who, hash); - if let Some(target) = self.fork_targets.get_mut(&hash) { - target.peers.insert(who); - } - return PollBlockAnnounceValidation::Nothing { is_best, who, announce } - } - - if ancient_parent { - trace!( - target: "sync", - "Ignored ancient block announced from {}: {} {:?}", - who, - hash, - announce.header, - ); - return PollBlockAnnounceValidation::Nothing { is_best, who, announce } - } - - if self.status().state == SyncState::Idle { - trace!( - target: "sync", - "Added sync target for block announced from {}: {} {:?}", - who, - hash, - announce.summary(), - ); - self.fork_targets - .entry(hash) - .or_insert_with(|| ForkTarget { - number, - parent_hash: Some(*announce.header.parent_hash()), - peers: Default::default(), - }) - .peers - .insert(who); - } - - PollBlockAnnounceValidation::Nothing { is_best, who, announce } - } - /// Restart the sync process. This will reset all pending block requests and return an iterator /// of new block requests to make to peers. Peers that were downloading finality data (i.e. /// their state was `DownloadingJustification`) are unaffected and will stay in the same state. @@ -3162,14 +2873,13 @@ fn validate_blocks( mod test { use super::*; use crate::service::network::NetworkServiceProvider; - use futures::{executor::block_on, future::poll_fn}; + use futures::executor::block_on; use sc_block_builder::BlockBuilderProvider; use sc_network_common::{ role::Role, - sync::message::{BlockData, BlockState, FromBlock}, + sync::message::{BlockAnnounce, BlockData, BlockState, FromBlock}, }; use sp_blockchain::HeaderBackend; - use sp_consensus::block_validation::DefaultBlockAnnounceValidator; use substrate_test_runtime_client::{ runtime::{Block, Hash, Header}, BlockBuilderExt, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt, TestClient, @@ -3183,7 +2893,6 @@ mod test { // internally we should process the response as the justification not being available. let client = Arc::new(TestClientBuilder::new().build()); - let block_announce_validator = Box::new(DefaultBlockAnnounceValidator); let peer_id = PeerId::random(); let import_queue = Box::new(sc_consensus::import_queue::mock::MockImportQueueHandle::new()); @@ -3195,7 +2904,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - block_announce_validator, 1, 64, None, @@ -3262,7 +2970,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 1, 64, None, @@ -3344,23 +3051,16 @@ mod test { /// Send a block annoucnement for the given `header`. fn send_block_announce( header: Header, - peer_id: &PeerId, + peer_id: PeerId, sync: &mut ChainSync, ) { - let block_annnounce = BlockAnnounce { + let announce = BlockAnnounce { header: header.clone(), state: Some(BlockState::Best), data: Some(Vec::new()), }; - sync.push_block_announce_validation(*peer_id, header.hash(), block_annnounce, true); - - // Poll until we have procssed the block announcement - block_on(poll_fn(|cx| loop { - if sync.poll_block_announce_validation(cx).is_pending() { - break Poll::Ready(()) - } - })) + sync.on_validated_block_announce(true, peer_id, &announce); } /// Create a block response from the given `blocks`. @@ -3444,7 +3144,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 5, 64, None, @@ -3491,7 +3190,7 @@ mod test { assert!(sync.block_requests().is_empty()); // Let peer2 announce a fork of block 3 - send_block_announce(block3_fork.header().clone(), &peer_id2, &mut sync); + send_block_announce(block3_fork.header().clone(), peer_id2, &mut sync); // Import and tell sync that we now have the fork. block_on(client.import(BlockOrigin::Own, block3_fork.clone())).unwrap(); @@ -3500,13 +3199,13 @@ mod test { let block4 = build_block_at(block3_fork.hash(), false); // Let peer2 announce block 4 and check that sync wants to get the block. - send_block_announce(block4.header().clone(), &peer_id2, &mut sync); + send_block_announce(block4.header().clone(), peer_id2, &mut sync); let request = get_block_request(&mut sync, FromBlock::Hash(block4.hash()), 2, &peer_id2); // Peer1 announces the same block, but as the common block is still `1`, sync will request // block 2 again. - send_block_announce(block4.header().clone(), &peer_id1, &mut sync); + send_block_announce(block4.header().clone(), peer_id1, &mut sync); let request2 = get_block_request(&mut sync, FromBlock::Number(2), 1, &peer_id1); @@ -3571,7 +3270,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 5, 64, None, @@ -3647,7 +3345,7 @@ mod test { sync.queue_blocks.clear(); // Let peer2 announce that it finished syncing - send_block_announce(best_block.header().clone(), &peer_id2, &mut sync); + send_block_announce(best_block.header().clone(), peer_id2, &mut sync); let (peer1_req, peer2_req) = sync.block_requests().into_iter().fold((None, None), |res, req| { @@ -3729,7 +3427,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 5, 64, None, @@ -3754,7 +3451,7 @@ mod test { sync.new_peer(peer_id1, common_block.hash(), *common_block.header().number()) .unwrap(); - send_block_announce(fork_blocks.last().unwrap().header().clone(), &peer_id1, &mut sync); + send_block_announce(fork_blocks.last().unwrap().header().clone(), peer_id1, &mut sync); let mut request = get_block_request(&mut sync, FromBlock::Number(info.best_number), 1, &peer_id1); @@ -3872,7 +3569,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 5, 64, None, @@ -3897,7 +3593,7 @@ mod test { sync.new_peer(peer_id1, common_block.hash(), *common_block.header().number()) .unwrap(); - send_block_announce(fork_blocks.last().unwrap().header().clone(), &peer_id1, &mut sync); + send_block_announce(fork_blocks.last().unwrap().header().clone(), peer_id1, &mut sync); let mut request = get_block_request(&mut sync, FromBlock::Number(info.best_number), 1, &peer_id1); @@ -4017,7 +3713,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 1, 64, None, @@ -4039,7 +3734,7 @@ mod test { // Create a "new" header and announce it let mut header = blocks[0].header().clone(); header.number = 4; - send_block_announce(header, &peer_id1, &mut sync); + send_block_announce(header, peer_id1, &mut sync); assert!(sync.fork_targets.len() == 1); sync.peer_disconnected(&peer_id1); @@ -4063,7 +3758,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - Box::new(DefaultBlockAnnounceValidator), 1, 64, None, @@ -4107,7 +3801,6 @@ mod test { #[test] fn sync_restart_removes_block_but_not_justification_requests() { let mut client = Arc::new(TestClientBuilder::new().build()); - let block_announce_validator = Box::new(DefaultBlockAnnounceValidator); let import_queue = Box::new(sc_consensus::import_queue::mock::MockImportQueueHandle::new()); let (_chain_sync_network_provider, chain_sync_network_handle) = NetworkServiceProvider::new(); @@ -4117,7 +3810,6 @@ mod test { ProtocolId::from("test-protocol-name"), &Some(String::from("test-fork-id")), Roles::from(&Role::Full), - block_announce_validator, 1, 64, None, diff --git a/substrate/client/network/sync/src/mock.rs b/substrate/client/network/sync/src/mock.rs index 838c6cf7667a..d37095c17d2c 100644 --- a/substrate/client/network/sync/src/mock.rs +++ b/substrate/client/network/sync/src/mock.rs @@ -24,7 +24,7 @@ use libp2p::PeerId; use sc_network_common::sync::{ message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse}, BadPeer, ChainSync as ChainSyncT, Metrics, OnBlockData, OnBlockJustification, - OpaqueBlockResponse, PeerInfo, PollBlockAnnounceValidation, SyncStatus, + OpaqueBlockResponse, PeerInfo, SyncStatus, }; use sp_runtime::traits::{Block as BlockT, NumberFor}; @@ -71,17 +71,12 @@ mockall::mock! { success: bool, ); fn on_block_finalized(&mut self, hash: &Block::Hash, number: NumberFor); - fn push_block_announce_validation( + fn on_validated_block_announce( &mut self, - who: PeerId, - hash: Block::Hash, - announce: BlockAnnounce, is_best: bool, + who: PeerId, + announce: &BlockAnnounce, ); - fn poll_block_announce_validation<'a>( - &mut self, - cx: &mut std::task::Context<'a>, - ) -> Poll>; fn peer_disconnected(&mut self, who: &PeerId); fn metrics(&self) -> Metrics; fn block_response_into_blocks( @@ -92,7 +87,7 @@ mockall::mock! { fn poll<'a>( &mut self, cx: &mut std::task::Context<'a>, - ) -> Poll>; + ) -> Poll<()>; fn send_block_request( &mut self, who: PeerId, diff --git a/substrate/client/utils/src/mpsc.rs b/substrate/client/utils/src/mpsc.rs index 36e44be5e295..039e03f9e618 100644 --- a/substrate/client/utils/src/mpsc.rs +++ b/substrate/client/utils/src/mpsc.rs @@ -123,6 +123,11 @@ impl TracingUnboundedSender { s }) } + + /// The number of elements in the channel (proxy function to [`async_channel::Sender`]). + pub fn len(&self) -> usize { + self.inner.len() + } } impl TracingUnboundedReceiver { @@ -139,6 +144,11 @@ impl TracingUnboundedReceiver { s }) } + + /// The number of elements in the channel (proxy function to [`async_channel::Receiver`]). + pub fn len(&self) -> usize { + self.inner.len() + } } impl Drop for TracingUnboundedReceiver { From 8e484a88644123ca9199a3b1a0301f25a6feffc2 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Mon, 4 Sep 2023 21:33:20 +0200 Subject: [PATCH 022/103] Contracts: Update read_sandbox (#1390) * Update runtime.rs * Fix * Revert "Update runtime.rs" This reverts commit 808f026a835b1f2707f640799454a50fd3a8be7b. * nit mono-repo fixes --- substrate/frame/contracts/build.rs | 2 +- substrate/frame/contracts/src/tests.rs | 4 +++- substrate/frame/contracts/src/wasm/runtime.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/substrate/frame/contracts/build.rs b/substrate/frame/contracts/build.rs index 7817ace9c98e..42bc45d563d3 100644 --- a/substrate/frame/contracts/build.rs +++ b/substrate/frame/contracts/build.rs @@ -53,7 +53,7 @@ fn get_latest_version() -> u16 { fn main() -> Result<(), Box> { let out_dir = std::env::var("OUT_DIR")?; let path = std::path::Path::new(&out_dir).join("migration_codegen.rs"); - let mut f = std::fs::File::create(&path)?; + let mut f = std::fs::File::create(path)?; let version = get_latest_version(); write!( f, diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 0c0a2f7f9327..8d6c5c5ac728 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -564,7 +564,9 @@ where { let fixture_path = [ // When `CARGO_MANIFEST_DIR` is not set, Rust resolves relative paths from the root folder - std::env::var("CARGO_MANIFEST_DIR").as_deref().unwrap_or("frame/contracts"), + std::env::var("CARGO_MANIFEST_DIR") + .as_deref() + .unwrap_or("substrate/frame/contracts"), "/fixtures/", fixture_name, ".wat", diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index 4bc00388f726..4fd52b471a0c 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -608,7 +608,7 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { let mut bound_checked = memory .get(ptr..ptr + D::max_encoded_len() as usize) .ok_or_else(|| Error::::OutOfBounds)?; - let decoded = D::decode_all_with_depth_limit(MAX_DECODE_NESTING, &mut bound_checked) + let decoded = D::decode_with_depth_limit(MAX_DECODE_NESTING, &mut bound_checked) .map_err(|_| DispatchError::from(Error::::DecodingFailed))?; Ok(decoded) } From b5433ff5de5148599de7306393c4c040bfb7e1c4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 5 Sep 2023 12:31:57 +1000 Subject: [PATCH 023/103] rust docs: add simple analytics (#1377) * inject simple analytics * comments * fix chown * comments * doc features --- .gitlab/pipeline/build.yml | 21 ++++++++++++++++++++- substrate/.maintain/rustdocs-release.sh | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index 636f7e47afad..20fed5df3dfd 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -114,11 +114,30 @@ build-rustdoc: script: # FIXME: it fails with `RUSTDOCFLAGS="-Dwarnings"` and `--all-features` # FIXME: return to stable when https://github.com/rust-lang/rust/issues/96937 gets into stable - - time cargo doc --workspace --no-deps + - time cargo doc --features try-runtime,experimental --workspace --no-deps - rm -f ./target/doc/.lock - mv ./target/doc ./crate-docs # FIXME: remove me after CI image gets nonroot - chown -R nonroot:nonroot ./crate-docs + # Inject Simple Analytics (https://www.simpleanalytics.com/) privacy preserving tracker into + # all .html files + - | + inject_simple_analytics() { + local path="$1" + local script_content="" + + # Function that inject script into the head of an html file using sed. + process_file() { + local file="$1" + echo "Adding Simple Analytics script to $file" + sed -i "s||$script_content|" "$file" + } + export -f process_file + + # Modify .html files in parallel using xargs, otherwise it can take a long time. + find "$path" -name '*.html' | xargs -I {} -P "$(nproc)" bash -c 'process_file "$@"' _ {} + } + inject_simple_analytics "./crate-docs" - echo "" > ./crate-docs/index.html build-implementers-guide: diff --git a/substrate/.maintain/rustdocs-release.sh b/substrate/.maintain/rustdocs-release.sh index 2a1e141e63ad..091f9289e4e3 100755 --- a/substrate/.maintain/rustdocs-release.sh +++ b/substrate/.maintain/rustdocs-release.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # set -x -# This script manages the deployment of Substrate rustdocs to https://paritytech.github.io/substrate/. +# This script used to manage the deployment of Substrate rustdocs to https://paritytech.github.io/substrate/. +# It is no longer used anywhere, and only here for historical/demonstration purposes. # - With `deploy` sub-command, it will checkout the passed-in branch/tag ref, build the rustdocs # locally (this takes some time), update the `index.html` index page, and push it to remote # `gh-pages` branch. So users running this command need to have write access to the remote From b1a32234ce4dd3e82665390c97c08dba95c4e2c5 Mon Sep 17 00:00:00 2001 From: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Date: Tue, 5 Sep 2023 08:13:19 +0200 Subject: [PATCH 024/103] Move Relay-Specific Shared Code to One Place (#1193) * add common libs * asset hubs * add westend * bridge hubs * collectives * contracts * emulated tests * parachain bin * delete collectives constants and update docs * integration tests should have apache license (some missing, some needed changing) * propagate features * fmt --- Cargo.lock | 6 + cumulus/parachains/common/Cargo.toml | 11 ++ .../src/constants.rs => common/src/kusama.rs} | 31 ++--- cumulus/parachains/common/src/lib.rs | 4 + .../constants.rs => common/src/polkadot.rs} | 34 ++--- .../src/constants.rs => common/src/rococo.rs} | 4 +- .../constants.rs => common/src/westend.rs} | 4 +- .../assets/asset-hub-kusama/Cargo.toml | 1 + .../assets/asset-hub-kusama/src/lib.rs | 25 ++-- .../src/tests/hrmp_channels.rs | 27 ++-- .../assets/asset-hub-kusama/src/tests/mod.rs | 25 ++-- .../src/tests/reserve_transfer.rs | 27 ++-- .../assets/asset-hub-kusama/src/tests/send.rs | 27 ++-- .../src/tests/set_xcm_versions.rs | 25 ++-- .../assets/asset-hub-kusama/src/tests/swap.rs | 37 +++--- .../asset-hub-kusama/src/tests/teleport.rs | 25 ++-- .../assets/asset-hub-polkadot/Cargo.toml | 1 + .../assets/asset-hub-polkadot/src/lib.rs | 25 ++-- .../src/tests/hrmp_channels.rs | 27 ++-- .../asset-hub-polkadot/src/tests/mod.rs | 25 ++-- .../src/tests/reserve_transfer.rs | 27 ++-- .../asset-hub-polkadot/src/tests/send.rs | 27 ++-- .../src/tests/set_xcm_versions.rs | 25 ++-- .../asset-hub-polkadot/src/tests/teleport.rs | 25 ++-- .../assets/asset-hub-westend/Cargo.toml | 1 + .../assets/asset-hub-westend/src/lib.rs | 25 ++-- .../assets/asset-hub-westend/src/tests/mod.rs | 25 ++-- .../src/tests/reserve_transfer.rs | 27 ++-- .../asset-hub-westend/src/tests/send.rs | 27 ++-- .../src/tests/set_xcm_versions.rs | 25 ++-- .../asset-hub-westend/src/tests/swap.rs | 35 +++--- .../asset-hub-westend/src/tests/teleport.rs | 25 ++-- .../bridges/bridge-hub-rococo/Cargo.toml | 1 + .../bridges/bridge-hub-rococo/src/lib.rs | 25 ++-- .../bridge-hub-rococo/src/tests/example.rs | 25 ++-- .../bridge-hub-rococo/src/tests/mod.rs | 25 ++-- .../collectives-polkadot/Cargo.toml | 1 + .../collectives-polkadot/src/lib.rs | 25 ++-- .../src/tests/fellowship.rs | 25 ++-- .../collectives-polkadot/src/tests/mod.rs | 25 ++-- .../emulated/common/Cargo.toml | 1 + .../emulated/common/src/constants.rs | 39 +++--- .../emulated/common/src/impls.rs | 27 ++-- .../emulated/common/src/lib.rs | 25 ++-- .../assets/asset-hub-kusama/src/constants.rs | 118 ----------------- .../assets/asset-hub-kusama/src/lib.rs | 11 +- .../assets/asset-hub-kusama/tests/tests.rs | 5 +- .../asset-hub-polkadot/src/constants.rs | 119 ------------------ .../assets/asset-hub-polkadot/src/lib.rs | 6 +- .../assets/asset-hub-polkadot/tests/tests.rs | 10 +- .../assets/asset-hub-westend/src/lib.rs | 8 +- .../assets/asset-hub-westend/tests/tests.rs | 17 +-- .../bridge-hub-kusama/src/constants.rs | 117 ----------------- .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 8 +- .../bridge-hub-kusama/tests/tests.rs | 6 +- .../bridge-hub-polkadot/src/constants.rs | 117 ----------------- .../bridge-hub-polkadot/src/lib.rs | 8 +- .../bridge-hub-polkadot/tests/tests.rs | 6 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 9 +- .../bridge-hub-rococo/tests/tests.rs | 3 +- .../src/fellowship/mod.rs | 5 +- .../collectives-polkadot/src/lib.rs | 10 +- .../contracts-rococo/src/contracts.rs | 6 +- .../contracts/contracts-rococo/src/lib.rs | 9 +- .../src/chain_spec/asset_hubs.rs | 6 +- .../src/chain_spec/bridge_hubs.rs | 6 +- .../src/chain_spec/collectives.rs | 2 +- .../src/chain_spec/contracts.rs | 2 +- 68 files changed, 534 insertions(+), 1009 deletions(-) rename cumulus/parachains/{runtimes/contracts/contracts-rococo/src/constants.rs => common/src/kusama.rs} (95%) rename cumulus/parachains/{runtimes/collectives/collectives-polkadot/src/constants.rs => common/src/polkadot.rs} (94%) rename cumulus/parachains/{runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs => common/src/rococo.rs} (96%) rename cumulus/parachains/{runtimes/assets/asset-hub-westend/src/constants.rs => common/src/westend.rs} (96%) delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-kusama/src/constants.rs delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/constants.rs delete mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs delete mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs diff --git a/Cargo.lock b/Cargo.lock index 8af7f4f87217..38d0a3388d33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10978,6 +10978,7 @@ dependencies = [ "cumulus-primitives-utility", "frame-support", "frame-system", + "kusama-runtime-constants", "log", "num-traits", "pallet-asset-tx-payment", @@ -10986,8 +10987,12 @@ dependencies = [ "pallet-balances", "pallet-collator-selection", "parity-scale-codec", + "polkadot-core-primitives", "polkadot-primitives", + "polkadot-runtime-constants", + "rococo-runtime-constants", "scale-info", + "smallvec", "sp-consensus-aura", "sp-core", "sp-io", @@ -10997,6 +11002,7 @@ dependencies = [ "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", + "westend-runtime-constants", ] [[package]] diff --git a/cumulus/parachains/common/Cargo.toml b/cumulus/parachains/common/Cargo.toml index 0c863b7295b4..18cafde0d303 100644 --- a/cumulus/parachains/common/Cargo.toml +++ b/cumulus/parachains/common/Cargo.toml @@ -13,6 +13,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive log = { version = "0.4.19", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } num-traits = { version = "0.2", default-features = false} +smallvec = "1.11.0" # Substrate frame-support = { path = "../../../substrate/frame/support", default-features = false } @@ -28,6 +29,11 @@ sp-runtime = { path = "../../../substrate/primitives/runtime", default-features sp-std = { path = "../../../substrate/primitives/std", default-features = false } # Polkadot +kusama-runtime-constants = { path = "../../../polkadot/runtime/kusama/constants", default-features = false} +polkadot-runtime-constants = { path = "../../../polkadot/runtime/polkadot/constants", default-features = false} +rococo-runtime-constants = { path = "../../../polkadot/runtime/rococo/constants", default-features = false} +westend-runtime-constants = { path = "../../../polkadot/runtime/westend/constants", default-features = false} +polkadot-core-primitives = { path = "../../../polkadot/core-primitives", default-features = false} polkadot-primitives = { path = "../../../polkadot/primitives", default-features = false} xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false} xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false} @@ -52,18 +58,23 @@ std = [ "cumulus-primitives-utility/std", "frame-support/std", "frame-system/std", + "kusama-runtime-constants/std", "log/std", "pallet-asset-tx-payment/std", "pallet-assets/std", "pallet-authorship/std", "pallet-balances/std", "pallet-collator-selection/std", + "polkadot-core-primitives/std", "polkadot-primitives/std", + "polkadot-runtime-constants/std", + "rococo-runtime-constants/std", "sp-consensus-aura/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", + "westend-runtime-constants/std", "xcm-builder/std", "xcm-executor/std", "xcm/std", diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/constants.rs b/cumulus/parachains/common/src/kusama.rs similarity index 95% rename from cumulus/parachains/runtimes/contracts/contracts-rococo/src/constants.rs rename to cumulus/parachains/common/src/kusama.rs index 9b0fe5182a25..308f7d081ced 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/constants.rs +++ b/cumulus/parachains/common/src/kusama.rs @@ -13,6 +13,19 @@ // See the License for the specific language governing permissions and // limitations under the License. +/// Consensus-related. +pub mod consensus { + /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included + /// into the relay chain. + pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; + /// How many parachain blocks are processed by the relay chain per parent. Limits the + /// number of blocks authored per slot. + pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; + /// Relay chain slot duration, in milliseconds. + pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; +} + +/// Constants relating to KSM. pub mod currency { use kusama_runtime_constants as constants; use polkadot_core_primitives::Balance; @@ -31,7 +44,7 @@ pub mod currency { } } -/// Fee-related. +/// Constants related to Kusama fee payment. pub mod fee { use frame_support::{ pallet_prelude::Weight, @@ -75,8 +88,8 @@ pub mod fee { impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Rococo Contracts, we map to 1/10 of that, or 1/100 CENT + // In Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // The standard system parachain configuration is 1/10 of that, as in 1/100 CENT. let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); @@ -107,15 +120,3 @@ pub mod fee { } } } - -/// Consensus-related. -pub mod consensus { - /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included - /// into the relay chain. - pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; - /// How many parachain blocks are processed by the relay chain per parent. Limits the - /// number of blocks authored per slot. - pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; - /// Relay chain slot duration, in milliseconds. - pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; -} diff --git a/cumulus/parachains/common/src/lib.rs b/cumulus/parachains/common/src/lib.rs index 797010d49a07..cb2ac1a1e3e4 100644 --- a/cumulus/parachains/common/src/lib.rs +++ b/cumulus/parachains/common/src/lib.rs @@ -16,6 +16,10 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod impls; +pub mod kusama; +pub mod polkadot; +pub mod rococo; +pub mod westend; pub mod xcm_config; pub use constants::*; pub use opaque::*; diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs b/cumulus/parachains/common/src/polkadot.rs similarity index 94% rename from cumulus/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs rename to cumulus/parachains/common/src/polkadot.rs index 46b562ea4de7..52cee939224c 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs +++ b/cumulus/parachains/common/src/polkadot.rs @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +/// Universally recognized accounts. pub mod account { use frame_support::PalletId; @@ -28,6 +29,19 @@ pub mod account { pub const REFERENDA_PALLET_ID: PalletId = PalletId(*b"py/refer"); } +/// Consensus-related. +pub mod consensus { + /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included + /// into the relay chain. + pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; + /// How many parachain blocks are processed by the relay chain per parent. Limits the + /// number of blocks authored per slot. + pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; + /// Relay chain slot duration, in milliseconds. + pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; +} + +/// Constants relating to DOT. pub mod currency { use polkadot_core_primitives::Balance; use polkadot_runtime_constants as constants; @@ -41,12 +55,12 @@ pub mod currency { pub const MILLICENTS: Balance = constants::currency::MILLICENTS; pub const fn deposit(items: u32, bytes: u32) -> Balance { - // 1/100 of Polkadot. + // 1/100 of Polkadot constants::currency::deposit(items, bytes) / 100 } } -/// Fee-related. +/// Constants related to Polkadot fee payment. pub mod fee { use frame_support::{ pallet_prelude::Weight, @@ -90,8 +104,8 @@ pub mod fee { impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in a parachain, we map to 1/10 of that, or 1/100 CENT + // In Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // The standard system parachain configuration is 1/10 of that, as in 1/100 CENT. let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); @@ -122,15 +136,3 @@ pub mod fee { } } } - -/// Consensus-related. -pub mod consensus { - /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included - /// into the relay chain. - pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; - /// How many parachain blocks are processed by the relay chain per parent. Limits the - /// number of blocks authored per slot. - pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; - /// Relay chain slot duration, in milliseconds. - pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs b/cumulus/parachains/common/src/rococo.rs similarity index 96% rename from cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs rename to cumulus/parachains/common/src/rococo.rs index 80620feaedc6..6e31def4b55b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs +++ b/cumulus/parachains/common/src/rococo.rs @@ -73,8 +73,8 @@ pub mod fee { impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Bridge Hub, we map to 1/10 of that, or 1/100 CENT + // In Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // The standard system parachain configuration is 1/10 of that, as in 1/100 CENT. let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/constants.rs b/cumulus/parachains/common/src/westend.rs similarity index 96% rename from cumulus/parachains/runtimes/assets/asset-hub-westend/src/constants.rs rename to cumulus/parachains/common/src/westend.rs index b2629ef10fcc..9d3e0bd1a0e2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/constants.rs +++ b/cumulus/parachains/common/src/westend.rs @@ -75,8 +75,8 @@ pub mod fee { impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Westend, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Asset Hub, we map to 1/10 of that, or 1/100 CENT + // In Westend, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // The standard system parachain configuration is 1/10 of that, as in 1/100 CENT. let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/Cargo.toml index d45a201a4d05..4f17b1ac55b5 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/Cargo.toml @@ -3,6 +3,7 @@ name = "asset-hub-kusama-integration-tests" version = "1.0.0" authors.workspace = true edition.workspace = true +license = "Apache-2.0" description = "Asset Hub Kusama runtime integration tests with xcm-emulator" publish = false diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs index 9325ca54b068..ad74aa2301fc 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use codec::Encode; pub use frame_support::{ diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/hrmp_channels.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/hrmp_channels.rs index 8647c1aa0081..623b3ff599c8 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/hrmp_channels.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/hrmp_channels.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/mod.rs index 41d840658193..b3089a3b3826 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/mod.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod hrmp_channels; mod reserve_transfer; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/reserve_transfer.rs index 26b3cdf68b1b..645dca5035b1 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/reserve_transfer.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs index d633c25b7324..5891b694c8e4 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/send.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/set_xcm_versions.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/set_xcm_versions.rs index 155ada2ec2f3..a7af96096cdd 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/set_xcm_versions.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/set_xcm_versions.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/swap.rs index aad93db9922e..3a67b5435828 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/swap.rs @@ -1,22 +1,21 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; -use asset_hub_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT; use frame_support::{instances::Instance2, BoundedVec}; +use parachains_common::kusama::currency::EXISTENTIAL_DEPOSIT; use sp_runtime::{DispatchError, ModuleError}; #[test] @@ -183,11 +182,9 @@ fn swap_locally_on_chain_using_foreign_assets() { .encode() .into(); - let buy_execution_fee_amount = - asset_hub_kusama_runtime::constants::fee::WeightToFee::weight_to_fee(&Weight::from_parts( - 10_100_000_000_000, - 300_000, - )); + let buy_execution_fee_amount = parachains_common::kusama::fee::WeightToFee::weight_to_fee( + &Weight::from_parts(10_100_000_000_000, 300_000), + ); let buy_execution_fee = MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), fun: Fungible(buy_execution_fee_amount), diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/teleport.rs index b671fd5b4448..f69878f35435 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/tests/teleport.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(dead_code)] // diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/Cargo.toml index 3d5d23e99636..ed383207228c 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/Cargo.toml @@ -3,6 +3,7 @@ name = "asset-hub-polkadot-integration-tests" version = "1.0.0" authors.workspace = true edition.workspace = true +license = "Apache-2.0" description = "Asset Hub Polkadot runtime integration tests with xcm-emulator" publish = false diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs index 6cbf6ab1ccb0..e8ba8e44f25c 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use codec::Encode; pub use frame_support::{ diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/hrmp_channels.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/hrmp_channels.rs index 337e4ba6113a..a1423f2ea90b 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/hrmp_channels.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/hrmp_channels.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/mod.rs index 547b59deadcb..c22de4f1c3eb 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/mod.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod hrmp_channels; mod reserve_transfer; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs index e6722d585bc0..e53693d85d2b 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs index 143ab06b4e99..244b428a7523 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/send.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/set_xcm_versions.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/set_xcm_versions.rs index 287bfa35ae9c..e121c4167993 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/set_xcm_versions.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/set_xcm_versions.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs index f0fbcf37fccf..644c51d75b66 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/tests/teleport.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(dead_code)] // diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml index 34d34009ebd0..0c60a30a0b92 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml @@ -3,6 +3,7 @@ name = "asset-hub-westend-integration-tests" version = "1.0.0" authors.workspace = true edition.workspace = true +license = "Apache-2.0" description = "Asset Hub Westend runtime integration tests with xcm-emulator" publish = false diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs index 2c89c0f9dd46..6e0f3434aedf 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use codec::Encode; pub use frame_support::{ diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/mod.rs index e2a60e0b3004..b3841af0e6c3 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/mod.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod reserve_transfer; mod send; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 67fc53a826aa..51fac43be125 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs index fcaffdabc4cf..424d222bef38 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/send.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/set_xcm_versions.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/set_xcm_versions.rs index 576325271745..2720095aac00 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/set_xcm_versions.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/set_xcm_versions.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs index 1c4dd9d76837..7d1615c9e291 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; @@ -171,11 +170,9 @@ fn swap_locally_on_chain_using_foreign_assets() { .encode() .into(); - let buy_execution_fee_amount = - asset_hub_westend_runtime::constants::fee::WeightToFee::weight_to_fee(&Weight::from_parts( - 10_100_000_000_000, - 300_000, - )); + let buy_execution_fee_amount = parachains_common::westend::fee::WeightToFee::weight_to_fee( + &Weight::from_parts(10_100_000_000_000, 300_000), + ); let buy_execution_fee = MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), fun: Fungible(buy_execution_fee_amount), diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs index 233dc32b13b5..8de73a7420c6 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(dead_code)] // diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml index 12a2ed51591f..ee6896855549 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml @@ -3,6 +3,7 @@ name = "bridge-hub-rococo-integration-tests" version = "1.0.0" authors.workspace = true edition.workspace = true +license = "Apache-2.0" description = "Bridge Hub Rococo runtime integration tests with xcm-emulator" publish = false diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs index 0a923ec04de7..122d65461159 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use bp_messages::LaneId; pub use frame_support::assert_ok; diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs index 777acd2aa972..f24e13bb71b8 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs index 6e11743aecbf..48347557ae77 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -1,17 +1,16 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod example; diff --git a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml index ee0e254befc5..5a28b1274151 100644 --- a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml @@ -3,6 +3,7 @@ name = "collectives-polkadot-integration-tests" version = "0.1.0" authors.workspace = true edition.workspace = true +license = "Apache-2.0" description = "Polkadot Collectives parachain runtime integration tests based on xcm-emulator" publish = false diff --git a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/lib.rs b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/lib.rs index ad2b5a501117..aa716c7c9485 100644 --- a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/lib.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use codec::Encode; pub use frame_support::{assert_ok, sp_runtime::AccountId32}; diff --git a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs index 82e998f5a76c..c08a660205f6 100644 --- a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs +++ b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/fellowship.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests concerning the Fellowship. diff --git a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/mod.rs index a9445ac8ec7e..fb3e235a25cd 100644 --- a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/src/tests/mod.rs @@ -1,17 +1,16 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod fellowship; diff --git a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml index a8002158dbc1..ac1e650d5de7 100644 --- a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml @@ -3,6 +3,7 @@ name = "integration-tests-common" version = "1.0.0" authors.workspace = true edition.workspace = true +license = "Apache-2.0" description = "Common resources for integration testing with xcm-emulator" publish = false diff --git a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs index fedc46fabfff..8725ebd140b9 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Substrate use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId; @@ -632,7 +631,7 @@ pub mod rococo { pub mod asset_hub_polkadot { use super::*; pub const PARA_ID: u32 = 1000; - pub const ED: Balance = asset_hub_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::polkadot::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = asset_hub_polkadot_runtime::RuntimeGenesisConfig { @@ -689,7 +688,7 @@ pub mod asset_hub_polkadot { pub mod asset_hub_westend { use super::*; pub const PARA_ID: u32 = 1000; - pub const ED: Balance = asset_hub_westend_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::westend::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = asset_hub_westend_runtime::RuntimeGenesisConfig { @@ -746,7 +745,7 @@ pub mod asset_hub_westend { pub mod asset_hub_kusama { use super::*; pub const PARA_ID: u32 = 1000; - pub const ED: Balance = asset_hub_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::kusama::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = asset_hub_kusama_runtime::RuntimeGenesisConfig { @@ -864,7 +863,7 @@ pub mod penpal { pub mod collectives { use super::*; pub const PARA_ID: u32 = 1001; - pub const ED: Balance = collectives_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::polkadot::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = collectives_polkadot_runtime::RuntimeGenesisConfig { @@ -921,7 +920,7 @@ pub mod collectives { pub mod bridge_hub_kusama { use super::*; pub const PARA_ID: u32 = 1002; - pub const ED: Balance = bridge_hub_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::kusama::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = bridge_hub_kusama_runtime::RuntimeGenesisConfig { @@ -978,7 +977,7 @@ pub mod bridge_hub_kusama { pub mod bridge_hub_polkadot { use super::*; pub const PARA_ID: u32 = 1002; - pub const ED: Balance = bridge_hub_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::polkadot::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = bridge_hub_polkadot_runtime::RuntimeGenesisConfig { @@ -1035,7 +1034,7 @@ pub mod bridge_hub_polkadot { pub mod bridge_hub_rococo { use super::*; pub const PARA_ID: u32 = 1013; - pub const ED: Balance = bridge_hub_rococo_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + pub const ED: Balance = parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT; pub fn genesis() -> Storage { let genesis_config = bridge_hub_rococo_runtime::RuntimeGenesisConfig { diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index f13da0016205..eed61d941711 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use codec::{Decode, Encode}; pub use paste; diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 49751136f7ba..7461165f2a19 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -1,18 +1,17 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// SPDX-License-Identifier: Apache-2.0 -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub mod constants; pub mod impls; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/constants.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/constants.rs deleted file mode 100644 index 8daf8fda4b4a..000000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/constants.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub mod currency { - use kusama_runtime_constants as constants; - use polkadot_core_primitives::Balance; - - /// The existential deposit. Set to 1/10 of its parent Relay Chain. - pub const EXISTENTIAL_DEPOSIT: Balance = constants::currency::EXISTENTIAL_DEPOSIT / 10; - - pub const UNITS: Balance = constants::currency::UNITS; - pub const CENTS: Balance = constants::currency::CENTS; - pub const GRAND: Balance = constants::currency::GRAND; - pub const MILLICENTS: Balance = constants::currency::MILLICENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - // map to 1/100 of what the kusama relay chain charges (v9020) - constants::currency::deposit(items, bytes) / 100 - } -} - -/// Fee-related. -pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, FeePolynomial, Weight, WeightToFeeCoefficient, - WeightToFeeCoefficients, WeightToFeePolynomial, - }; - use polkadot_core_primitives::Balance; - use smallvec::smallvec; - pub use sp_runtime::Perbill; - - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the - /// node's balance type. - /// - /// This should typically create a mapping between the following ranges: - /// - [0, MAXIMUM_BLOCK_WEIGHT] - /// - [Balance::min, Balance::max] - /// - /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: - /// - Setting it to `0` will essentially disable the weight fee. - /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. - pub struct WeightToFee; - impl frame_support::weights::WeightToFee for WeightToFee { - type Balance = Balance; - - fn weight_to_fee(weight: &Weight) -> Self::Balance { - let time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); - let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); - - // Take the maximum instead of the sum to charge by the more scarce resource. - time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) - } - } - - /// Maps the reference time component of `Weight` to a fee. - pub struct RefTimeToFee; - impl WeightToFeePolynomial for RefTimeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Asset Hub, we map to 1/10 of that, or 1/100 CENT - let p = super::currency::CENTS; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - /// Maps the proof size component of `Weight` to a fee. - pub struct ProofSizeToFee; - impl WeightToFeePolynomial for ProofSizeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // Map 10kb proof to 1 CENT. - let p = super::currency::CENTS; - let q = 10_000; - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } -} - -/// Consensus-related. -pub mod consensus { - /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included - /// into the relay chain. - pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; - /// How many parachain blocks are processed by the relay chain per parent. Limits the - /// number of blocks authored per slot. - pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; - /// Relay chain slot duration, in milliseconds. - pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index afccc5c068b5..828d1b4750a3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -24,7 +24,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod weights; pub mod xcm_config; @@ -50,7 +49,6 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use codec::{Decode, Encode, MaxEncodedLen}; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -70,8 +68,10 @@ use pallet_asset_conversion_tx_payment::AssetConversionAdapter; use pallet_nfts::PalletFeatures; pub use parachains_common as common; use parachains_common::{ - impls::DealWithFees, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, - Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, + impls::DealWithFees, + kusama::{consensus::*, currency::*, fee::WeightToFee}, + AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, Hash, Header, Nonce, + Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; use sp_runtime::RuntimeDebug; @@ -1395,8 +1395,9 @@ fn ensure_key_ss58() { #[cfg(test)] mod tests { - use super::{constants::fee, *}; + use super::*; use crate::{CENTS, MILLICENTS}; + use parachains_common::kusama::fee; use sp_runtime::traits::Zero; use sp_weights::WeightToFee; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index 6d9eccdf3744..7d49b56e461a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -21,7 +21,6 @@ use asset_hub_kusama_runtime::xcm_config::{ AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, TrustBackedAssetsPalletLocation, }; pub use asset_hub_kusama_runtime::{ - constants::fee::WeightToFee, xcm_config::{CheckingAccount, ForeignCreatorsSovereignAccountOf, XcmConfig}, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, @@ -35,7 +34,9 @@ use frame_support::{ traits::fungibles::InspectEnumerable, weights::{Weight, WeightToFee as WeightToFeeT}, }; -use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; +use parachains_common::{ + kusama::fee::WeightToFee, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, +}; use sp_runtime::traits::MaybeEquivalence; use xcm::latest::prelude::*; use xcm_executor::traits::{Identity, JustTry, WeightTrader}; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/constants.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/constants.rs deleted file mode 100644 index d430e38f1af1..000000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/constants.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub mod currency { - use polkadot_core_primitives::Balance; - use polkadot_runtime_constants as constants; - - /// The existential deposit. Set to 1/10 of its parent Relay Chain. - pub const EXISTENTIAL_DEPOSIT: Balance = constants::currency::EXISTENTIAL_DEPOSIT / 10; - - pub const UNITS: Balance = constants::currency::UNITS; - pub const DOLLARS: Balance = constants::currency::DOLLARS; - pub const CENTS: Balance = constants::currency::CENTS; - pub const MILLICENTS: Balance = constants::currency::MILLICENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - // 1/100 of Polkadot - constants::currency::deposit(items, bytes) / 100 - } -} - -/// Fee-related. -pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, - WeightToFeeCoefficients, WeightToFeePolynomial, - }; - use polkadot_core_primitives::Balance; - use smallvec::smallvec; - pub use sp_runtime::Perbill; - use sp_weights::Weight; - - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the - /// node's balance type. - /// - /// This should typically create a mapping between the following ranges: - /// - [0, MAXIMUM_BLOCK_WEIGHT] - /// - [Balance::min, Balance::max] - /// - /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: - /// - Setting it to `0` will essentially disable the weight fee. - /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. - pub struct WeightToFee; - impl frame_support::weights::WeightToFee for WeightToFee { - type Balance = Balance; - - fn weight_to_fee(weight: &Weight) -> Self::Balance { - let time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); - let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); - - // Take the maximum instead of the sum to charge by the more scarce resource. - time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) - } - } - - /// Maps the reference time component of `Weight` to a fee. - pub struct RefTimeToFee; - impl WeightToFeePolynomial for RefTimeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Asset Hub, we map to 1/10 of that, or 1/100 CENT - let p = super::currency::CENTS; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - /// Maps the proof size component of `Weight` to a fee. - pub struct ProofSizeToFee; - impl WeightToFeePolynomial for ProofSizeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // Map 10kb proof to 1 CENT. - let p = super::currency::CENTS; - let q = 10_000; - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } -} - -/// Consensus-related. -pub mod consensus { - /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included - /// into the relay chain. - pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; - /// How many parachain blocks are processed by the relay chain per parent. Limits the - /// number of blocks authored per slot. - pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; - /// Relay chain slot duration, in milliseconds. - pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index 7275209802f1..0051af21f9a3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -59,7 +59,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod weights; pub mod xcm_config; @@ -82,7 +81,6 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use codec::{Decode, Encode, MaxEncodedLen}; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -102,6 +100,7 @@ use pallet_nfts::PalletFeatures; pub use parachains_common as common; use parachains_common::{ impls::{AssetsToBlockAuthor, DealWithFees}, + polkadot::{consensus::*, currency::*, fee::WeightToFee}, AccountId, AssetHubPolkadotAuraId as AuraId, AssetIdForTrustBackedAssets, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, @@ -1228,8 +1227,9 @@ cumulus_pallet_parachain_system::register_validate_block! { #[cfg(test)] mod tests { - use super::{constants::fee, *}; + use super::*; use crate::{CENTS, MILLICENTS}; + use parachains_common::polkadot::fee; use sp_runtime::traits::Zero; use sp_weights::WeightToFee; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index 3eab6723ec20..7200ebc16a28 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -22,10 +22,9 @@ use asset_hub_polkadot_runtime::xcm_config::{ ForeignCreatorsSovereignAccountOf, TrustBackedAssetsPalletLocation, XcmConfig, }; pub use asset_hub_polkadot_runtime::{ - constants::fee::WeightToFee, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, - ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, - MetadataDepositPerByte, ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, - System, TrustBackedAssetsInstance, + AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, + ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, + RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, }; use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; @@ -36,7 +35,8 @@ use frame_support::{ weights::{Weight, WeightToFee as WeightToFeeT}, }; use parachains_common::{ - AccountId, AssetHubPolkadotAuraId as AuraId, AssetIdForTrustBackedAssets, Balance, + polkadot::fee::WeightToFee, AccountId, AssetHubPolkadotAuraId as AuraId, + AssetIdForTrustBackedAssets, Balance, }; use sp_runtime::traits::MaybeEquivalence; use xcm::latest::prelude::*; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index b5f33e4e0145..4887fce1b0a4 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -24,7 +24,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod weights; pub mod xcm_config; @@ -36,7 +35,6 @@ use assets_common::{ AssetIdForTrustBackedAssetsConvert, }; use codec::{Decode, Encode, MaxEncodedLen}; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ construct_runtime, @@ -57,8 +55,10 @@ use pallet_asset_conversion_tx_payment::AssetConversionAdapter; use pallet_nfts::PalletFeatures; pub use parachains_common as common; use parachains_common::{ - impls::DealWithFees, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, - Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, + impls::DealWithFees, + westend::{consensus::*, currency::*, fee::WeightToFee}, + AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, Hash, Header, Nonce, + Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; use sp_api::impl_runtime_apis; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index b2bb511182eb..599ff90e254a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -17,13 +17,6 @@ //! Tests for the Westmint (Westend Assets Hub) chain. -pub use asset_hub_westend_runtime::{ - constants::fee::WeightToFee, - xcm_config::{CheckingAccount, TrustBackedAssetsPalletLocation, XcmConfig}, - AllowMultiAssetPools, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, - ForeignAssetsInstance, ParachainSystem, Runtime, SessionKeys, System, - TrustBackedAssetsInstance, -}; use asset_hub_westend_runtime::{ xcm_config::{ AssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf, @@ -32,6 +25,12 @@ use asset_hub_westend_runtime::{ AllPalletsWithoutSystem, MetadataDepositBase, MetadataDepositPerByte, RuntimeCall, RuntimeEvent, }; +pub use asset_hub_westend_runtime::{ + xcm_config::{CheckingAccount, TrustBackedAssetsPalletLocation, XcmConfig}, + AllowMultiAssetPools, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, + ForeignAssetsInstance, ParachainSystem, Runtime, SessionKeys, System, + TrustBackedAssetsInstance, +}; use asset_test_utils::{CollatorSessionKeys, ExtBuilder, XcmReceivedFrom}; use codec::{Decode, DecodeLimit, Encode}; use cumulus_primitives_utility::ChargeWeightInFungibles; @@ -40,7 +39,9 @@ use frame_support::{ traits::fungibles::InspectEnumerable, weights::{Weight, WeightToFee as WeightToFeeT}, }; -use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; +use parachains_common::{ + westend::fee::WeightToFee, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, +}; use sp_io; use sp_runtime::traits::MaybeEquivalence; use std::convert::Into; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs deleted file mode 100644 index 760bf7fb6d1f..000000000000 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub mod currency { - use kusama_runtime_constants as constants; - use polkadot_core_primitives::Balance; - - /// The existential deposit. Set to 1/10 of its parent Relay Chain. - pub const EXISTENTIAL_DEPOSIT: Balance = constants::currency::EXISTENTIAL_DEPOSIT / 10; - - pub const UNITS: Balance = constants::currency::UNITS; - pub const CENTS: Balance = constants::currency::CENTS; - pub const MILLICENTS: Balance = constants::currency::MILLICENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - // map to 1/100 of what the kusama relay chain charges (v9020) - constants::currency::deposit(items, bytes) / 100 - } -} - -/// Fee-related. -pub mod fee { - use frame_support::{ - pallet_prelude::Weight, - weights::{ - constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, - WeightToFeeCoefficients, WeightToFeePolynomial, - }, - }; - use polkadot_core_primitives::Balance; - use smallvec::smallvec; - pub use sp_runtime::Perbill; - - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the - /// node's balance type. - /// - /// This should typically create a mapping between the following ranges: - /// - [0, MAXIMUM_BLOCK_WEIGHT] - /// - [Balance::min, Balance::max] - /// - /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: - /// - Setting it to `0` will essentially disable the weight fee. - /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. - pub struct WeightToFee; - impl frame_support::weights::WeightToFee for WeightToFee { - type Balance = Balance; - - fn weight_to_fee(weight: &Weight) -> Self::Balance { - let time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); - let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); - - // Take the maximum instead of the sum to charge by the more scarce resource. - time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) - } - } - - /// Maps the reference time component of `Weight` to a fee. - pub struct RefTimeToFee; - impl WeightToFeePolynomial for RefTimeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Bridge Hub, we map to 1/10 of that, or 1/100 CENT - let p = super::currency::CENTS; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - /// Maps the proof size component of `Weight` to a fee. - pub struct ProofSizeToFee; - impl WeightToFeePolynomial for ProofSizeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // Map 10kb proof to 1 CENT. - let p = super::currency::CENTS; - let q = 10_000; - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } -} - -/// Consensus-related. -pub mod consensus { - /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included - /// into the relay chain. - pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; - /// How many parachain blocks are processed by the relay chain per parent. Limits the - /// number of blocks authored per slot. - pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; - /// Relay chain slot duration, in milliseconds. - pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs index 044ff845fe66..54b15e6b327b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs @@ -22,7 +22,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod weights; pub mod xcm_config; @@ -41,7 +40,6 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -69,8 +67,10 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; use parachains_common::{ - impls::DealWithFees, AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, - AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, + kusama::{consensus::*, currency::*, fee::WeightToFee}, + AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, + HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; // XCM Imports diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs index 5418e36bd120..893524e12f66 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs @@ -15,12 +15,12 @@ // along with Cumulus. If not, see . pub use bridge_hub_kusama_runtime::{ - constants::fee::WeightToFee, xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, - ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, + xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, ExistentialDeposit, ParachainSystem, + PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, }; use codec::Decode; use frame_support::parameter_types; -use parachains_common::{AccountId, AuraId}; +use parachains_common::{kusama::fee::WeightToFee, AccountId, AuraId}; const ALICE: [u8; 32] = [1u8; 32]; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs deleted file mode 100644 index 3bab7bd1eb33..000000000000 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub mod currency { - use polkadot_core_primitives::Balance; - use polkadot_runtime_constants as constants; - - /// The existential deposit. Set to 1/10 of its parent Relay Chain. - pub const EXISTENTIAL_DEPOSIT: Balance = constants::currency::EXISTENTIAL_DEPOSIT / 10; - - pub const UNITS: Balance = constants::currency::UNITS; - pub const CENTS: Balance = constants::currency::CENTS; - pub const MILLICENTS: Balance = constants::currency::MILLICENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - // 1/100 of Polkadot - constants::currency::deposit(items, bytes) / 100 - } -} - -/// Fee-related. -pub mod fee { - use frame_support::{ - pallet_prelude::Weight, - weights::{ - constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, - WeightToFeeCoefficients, WeightToFeePolynomial, - }, - }; - use polkadot_core_primitives::Balance; - use smallvec::smallvec; - pub use sp_runtime::Perbill; - - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the - /// node's balance type. - /// - /// This should typically create a mapping between the following ranges: - /// - [0, MAXIMUM_BLOCK_WEIGHT] - /// - [Balance::min, Balance::max] - /// - /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: - /// - Setting it to `0` will essentially disable the weight fee. - /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. - pub struct WeightToFee; - impl frame_support::weights::WeightToFee for WeightToFee { - type Balance = Balance; - - fn weight_to_fee(weight: &Weight) -> Self::Balance { - let time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); - let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); - - // Take the maximum instead of the sum to charge by the more scarce resource. - time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) - } - } - - /// Maps the reference time component of `Weight` to a fee. - pub struct RefTimeToFee; - impl WeightToFeePolynomial for RefTimeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Bridge Hub, we map to 1/10 of that, or 1/100 CENT - let p = super::currency::CENTS; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - /// Maps the proof size component of `Weight` to a fee. - pub struct ProofSizeToFee; - impl WeightToFeePolynomial for ProofSizeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // Map 10kb proof to 1 CENT. - let p = super::currency::CENTS; - let q = 10_000; - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } -} - -/// Consensus-related. -pub mod consensus { - /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included - /// into the relay chain. - pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; - /// How many parachain blocks are processed by the relay chain per parent. Limits the - /// number of blocks authored per slot. - pub const BLOCK_PROCESSING_VELOCITY: u32 = 1; - /// Relay chain slot duration, in milliseconds. - pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs index f735858a9340..dbfdc249a3cd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs @@ -22,7 +22,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod weights; pub mod xcm_config; @@ -41,7 +40,6 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -70,8 +68,10 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; use parachains_common::{ - impls::DealWithFees, AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, - AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, + polkadot::{consensus::*, currency::*, fee::WeightToFee}, + AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, + HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; // XCM Imports use xcm::latest::prelude::BodyId; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs index 03b23cdd7ac2..0be87bd46fac 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs @@ -15,12 +15,12 @@ // along with Cumulus. If not, see . pub use bridge_hub_polkadot_runtime::{ - constants::fee::WeightToFee, xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, - ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, + xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, ExistentialDeposit, ParachainSystem, + PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, }; use codec::Decode; use frame_support::parameter_types; -use parachains_common::{AccountId, AuraId}; +use parachains_common::{polkadot::fee::WeightToFee, AccountId, AuraId}; const ALICE: [u8; 32] = [1u8; 32]; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index a872e2327303..4311a6a629f9 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -24,11 +24,9 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod bridge_hub_rococo_config; pub mod bridge_hub_wococo_config; -pub mod constants; mod weights; pub mod xcm_config; -use constants::{consensus::*, currency::*}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -79,7 +77,6 @@ use crate::{ BridgeRefundBridgeHubRococoMessages, OnBridgeHubWococoBlobDispatcher, WithBridgeHubRococoMessageBridge, }, - constants::fee::WeightToFee, xcm_config::XcmRouter, }; use bridge_runtime_common::{ @@ -87,8 +84,10 @@ use bridge_runtime_common::{ messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatch}, }; use parachains_common::{ - impls::DealWithFees, AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, - AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, + rococo::{consensus::*, currency::*, fee::WeightToFee}, + AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, + HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; use xcm_executor::XcmExecutor; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index 77e7e0382d31..e5fe67f2a8e5 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -19,7 +19,6 @@ use bp_polkadot_core::Signature; use bridge_hub_rococo_runtime::{ bridge_hub_rococo_config, bridge_hub_wococo_config, - constants::fee::WeightToFee, xcm_config::{RelayNetwork, XcmConfig}, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, DeliveryRewardInBalance, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, RequiredStakeForStakeAndSlash, @@ -28,7 +27,7 @@ use bridge_hub_rococo_runtime::{ use codec::{Decode, Encode}; use frame_support::parameter_types; use frame_system::pallet_prelude::HeaderFor; -use parachains_common::{AccountId, AuraId, Balance}; +use parachains_common::{rococo::fee::WeightToFee, AccountId, AuraId, Balance}; use sp_keyring::AccountKeyring::Alice; use sp_runtime::{ generic::{Era, SignedPayload}, diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs index 9b8675331295..b97e44dda1be 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs @@ -20,7 +20,7 @@ pub(crate) mod migration; mod origins; mod tracks; use crate::{ - constants, impls::ToParentTreasury, weights, AccountId, Balance, Balances, FellowshipReferenda, + impls::ToParentTreasury, weights, AccountId, Balance, Balances, FellowshipReferenda, GovernanceLocation, PolkadotTreasuryAccount, Preimage, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, DAYS, }; @@ -36,6 +36,7 @@ pub use origins::{ }; use pallet_ranked_collective::EnsureOfRank; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +use parachains_common::polkadot::account; use polkadot_runtime_constants::{time::HOURS, xcm::body::FELLOWSHIP_ADMIN_INDEX}; use sp_core::{ConstU128, ConstU32}; use sp_runtime::traits::{AccountIdConversion, ConstU16, ConvertToValue, Replace, TakeFirst}; @@ -62,7 +63,7 @@ pub mod ranks { parameter_types! { // Referenda pallet account, used to temporarily deposit slashed imbalance before teleporting. - pub ReferendaPalletAccount: AccountId = constants::account::REFERENDA_PALLET_ID.into_account_truncating(); + pub ReferendaPalletAccount: AccountId = account::REFERENDA_PALLET_ID.into_account_truncating(); pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX); } diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs index 5033a2d8beb1..238db08a0c9e 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs @@ -36,7 +36,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; pub mod impls; mod weights; pub mod xcm_config; @@ -64,7 +63,6 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use codec::{Decode, Encode, MaxEncodedLen}; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -79,7 +77,9 @@ use frame_system::{ }; pub use parachains_common as common; use parachains_common::{ - impls::DealWithFees, AccountId, AuraId, Balance, BlockNumber, Hash, Header, Nonce, Signature, + impls::DealWithFees, + polkadot::{account::*, consensus::*, currency::*, fee::WeightToFee}, + AccountId, AuraId, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; @@ -484,8 +484,8 @@ parameter_types! { pub const AllyDeposit: Balance = 1_000 * UNITS; // 1,000 DOT bond to join as an Ally // The Alliance pallet account, used as a temporary place to deposit a slashed imbalance // before the teleport to the Treasury. - pub AlliancePalletAccount: AccountId = constants::account::ALLIANCE_PALLET_ID.into_account_truncating(); - pub PolkadotTreasuryAccount: AccountId = constants::account::POLKADOT_TREASURY_PALLET_ID.into_account_truncating(); + pub AlliancePalletAccount: AccountId = ALLIANCE_PALLET_ID.into_account_truncating(); + pub PolkadotTreasuryAccount: AccountId = POLKADOT_TREASURY_PALLET_ID.into_account_truncating(); // The number of blocks a member must wait between giving a retirement notice and retiring. // Supposed to be greater than time required to `kick_member` with alliance motion. pub const AllianceRetirementPeriod: BlockNumber = (90 * DAYS) + ALLIANCE_MOTION_DURATION; diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs index 6598fd3fae0a..1c99393d5e52 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs @@ -14,8 +14,8 @@ // limitations under the License. use crate::{ - constants::currency::deposit, Balance, Balances, RandomnessCollectiveFlip, Runtime, - RuntimeCall, RuntimeEvent, RuntimeHoldReason, Timestamp, + Balance, Balances, RandomnessCollectiveFlip, Runtime, RuntimeCall, RuntimeEvent, + RuntimeHoldReason, Timestamp, }; use frame_support::{ parameter_types, @@ -28,7 +28,7 @@ use pallet_contracts::{ }; use sp_runtime::Perbill; -pub use parachains_common::AVERAGE_ON_INITIALIZE_RATIO; +pub use parachains_common::{rococo::currency::deposit, AVERAGE_ON_INITIALIZE_RATIO}; // Prints debug output of the `contracts` pallet to stdout if the node is // started with `-lruntime::contracts=debug`. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index b5815ab057e6..399ada1be2c7 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -25,7 +25,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod contracts; mod weights; mod xcm_config; @@ -45,7 +44,6 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use constants::{consensus::*, currency::*, fee::WeightToFee}; use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -57,9 +55,10 @@ use frame_support::{ use frame_system::limits::{BlockLength, BlockWeights}; pub use parachains_common as common; use parachains_common::{ - impls::DealWithFees, AccountId, BlockNumber, Hash, Header, Nonce, Signature, - AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, - SLOT_DURATION, + impls::DealWithFees, + rococo::{consensus::*, currency::*, fee::WeightToFee}, + AccountId, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, + MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; pub use parachains_common::{AuraId, Balance}; use xcm_config::CollatorSelectionUpdateOrigin; diff --git a/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs index c1fb60374aef..c1edeb98cd0a 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs @@ -32,11 +32,11 @@ pub type AssetHubWestendChainSpec = sc_service::GenericChainSpec; const ASSET_HUB_POLKADOT_ED: AssetHubBalance = - asset_hub_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::polkadot::currency::EXISTENTIAL_DEPOSIT; const ASSET_HUB_KUSAMA_ED: AssetHubBalance = - asset_hub_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::kusama::currency::EXISTENTIAL_DEPOSIT; const ASSET_HUB_WESTEND_ED: AssetHubBalance = - asset_hub_westend_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::westend::currency::EXISTENTIAL_DEPOSIT; /// Generate the session keys from individual elements. /// diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index 4cb81f57081a..5de4a49f8275 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -192,7 +192,7 @@ pub mod rococo { pub(crate) const BRIDGE_HUB_ROCOCO_LOCAL: &str = "bridge-hub-rococo-local"; pub(crate) const BRIDGE_HUB_ROCOCO_DEVELOPMENT: &str = "bridge-hub-rococo-dev"; const BRIDGE_HUB_ROCOCO_ED: BridgeHubBalance = - bridge_hub_rococo_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT; /// Specialized `ChainSpec` for the normal parachain runtime. pub type BridgeHubChainSpec = @@ -372,7 +372,7 @@ pub mod kusama { pub(crate) const BRIDGE_HUB_KUSAMA_LOCAL: &str = "bridge-hub-kusama-local"; pub(crate) const BRIDGE_HUB_KUSAMA_DEVELOPMENT: &str = "bridge-hub-kusama-dev"; const BRIDGE_HUB_KUSAMA_ED: BridgeHubBalance = - bridge_hub_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::kusama::currency::EXISTENTIAL_DEPOSIT; /// Specialized `ChainSpec` for the normal parachain runtime. pub type BridgeHubChainSpec = @@ -509,7 +509,7 @@ pub mod polkadot { pub(crate) const BRIDGE_HUB_POLKADOT_LOCAL: &str = "bridge-hub-polkadot-local"; pub(crate) const BRIDGE_HUB_POLKADOT_DEVELOPMENT: &str = "bridge-hub-polkadot-dev"; const BRIDGE_HUB_POLKADOT_ED: BridgeHubBalance = - bridge_hub_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::polkadot::currency::EXISTENTIAL_DEPOSIT; /// Specialized `ChainSpec` for the normal parachain runtime. pub type BridgeHubChainSpec = diff --git a/cumulus/polkadot-parachain/src/chain_spec/collectives.rs b/cumulus/polkadot-parachain/src/chain_spec/collectives.rs index 6126fbb114f0..fbf49b9535a4 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/collectives.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/collectives.rs @@ -26,7 +26,7 @@ pub type CollectivesPolkadotChainSpec = sc_service::GenericChainSpec; const COLLECTIVES_POLKADOT_ED: CollectivesBalance = - collectives_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::polkadot::currency::EXISTENTIAL_DEPOSIT; /// Generate the session keys from individual elements. /// diff --git a/cumulus/polkadot-parachain/src/chain_spec/contracts.rs b/cumulus/polkadot-parachain/src/chain_spec/contracts.rs index bf318e448f0e..0d5012858edc 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/contracts.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/contracts.rs @@ -31,7 +31,7 @@ const CONTRACTS_PARACHAIN_ID: u32 = 1002; /// The existential deposit is determined by the runtime "contracts-rococo". const CONTRACTS_ROCOCO_ED: contracts_rococo_runtime::Balance = - contracts_rococo_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT; pub fn contracts_rococo_development_config() -> ContractsRococoChainSpec { let mut properties = sc_chain_spec::Properties::new(); From 5bec4976c582ed033a9047d6864d1a5065f2ffd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 09:27:19 +0200 Subject: [PATCH 025/103] Bump thiserror from 1.0.47 to 1.0.48 (#1396) Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.47 to 1.0.48. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.47...1.0.48) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Liam Aharon --- Cargo.lock | 8 ++++---- cumulus/client/consensus/proposer/Cargo.toml | 2 +- cumulus/client/relay-chain-interface/Cargo.toml | 2 +- cumulus/client/relay-chain-rpc-interface/Cargo.toml | 2 +- polkadot/cli/Cargo.toml | 2 +- polkadot/erasure-coding/Cargo.toml | 2 +- polkadot/node/collation-generation/Cargo.toml | 2 +- polkadot/node/core/approval-voting/Cargo.toml | 2 +- polkadot/node/core/av-store/Cargo.toml | 2 +- polkadot/node/core/backing/Cargo.toml | 2 +- polkadot/node/core/bitfield-signing/Cargo.toml | 2 +- polkadot/node/core/chain-selection/Cargo.toml | 2 +- polkadot/node/core/dispute-coordinator/Cargo.toml | 2 +- polkadot/node/core/parachains-inherent/Cargo.toml | 2 +- polkadot/node/core/prospective-parachains/Cargo.toml | 2 +- polkadot/node/core/provisioner/Cargo.toml | 2 +- polkadot/node/core/pvf-checker/Cargo.toml | 2 +- polkadot/node/jaeger/Cargo.toml | 2 +- .../node/network/availability-distribution/Cargo.toml | 2 +- polkadot/node/network/availability-recovery/Cargo.toml | 2 +- polkadot/node/network/collator-protocol/Cargo.toml | 2 +- polkadot/node/network/dispute-distribution/Cargo.toml | 2 +- polkadot/node/network/protocol/Cargo.toml | 2 +- polkadot/node/network/statement-distribution/Cargo.toml | 2 +- polkadot/node/primitives/Cargo.toml | 2 +- polkadot/node/service/Cargo.toml | 2 +- polkadot/node/subsystem-types/Cargo.toml | 2 +- polkadot/node/subsystem-util/Cargo.toml | 2 +- polkadot/node/test/performance-test/Cargo.toml | 2 +- polkadot/node/zombienet-backchannel/Cargo.toml | 2 +- polkadot/utils/staking-miner/Cargo.toml | 2 +- substrate/client/allocator/Cargo.toml | 2 +- substrate/client/api/Cargo.toml | 2 +- substrate/client/cli/Cargo.toml | 2 +- substrate/client/consensus/common/Cargo.toml | 2 +- substrate/client/executor/common/Cargo.toml | 2 +- substrate/client/service/Cargo.toml | 2 +- substrate/client/storage-monitor/Cargo.toml | 2 +- substrate/client/sync-state-rpc/Cargo.toml | 2 +- substrate/client/telemetry/Cargo.toml | 2 +- substrate/client/tracing/Cargo.toml | 2 +- substrate/client/transaction-pool/Cargo.toml | 2 +- substrate/client/transaction-pool/api/Cargo.toml | 2 +- substrate/primitives/api/Cargo.toml | 2 +- substrate/primitives/blockchain/Cargo.toml | 2 +- substrate/primitives/consensus/common/Cargo.toml | 2 +- substrate/primitives/core/Cargo.toml | 2 +- substrate/primitives/inherents/Cargo.toml | 2 +- substrate/primitives/state-machine/Cargo.toml | 2 +- substrate/primitives/timestamp/Cargo.toml | 2 +- substrate/primitives/trie/Cargo.toml | 2 +- substrate/primitives/version/Cargo.toml | 2 +- substrate/utils/frame/benchmarking-cli/Cargo.toml | 2 +- 53 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38d0a3388d33..c254302517f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18661,9 +18661,9 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] @@ -18690,9 +18690,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", diff --git a/cumulus/client/consensus/proposer/Cargo.toml b/cumulus/client/consensus/proposer/Cargo.toml index f7edbc695e38..29720a8f4791 100644 --- a/cumulus/client/consensus/proposer/Cargo.toml +++ b/cumulus/client/consensus/proposer/Cargo.toml @@ -8,7 +8,7 @@ edition.workspace = true [dependencies] anyhow = "1.0" async-trait = "0.1.73" -thiserror = "1.0.47" +thiserror = "1.0.48" # Substrate sp-consensus = { path = "../../../../substrate/primitives/consensus/common" } diff --git a/cumulus/client/relay-chain-interface/Cargo.toml b/cumulus/client/relay-chain-interface/Cargo.toml index b81cc1b47807..3da7ab0b0e82 100644 --- a/cumulus/client/relay-chain-interface/Cargo.toml +++ b/cumulus/client/relay-chain-interface/Cargo.toml @@ -16,6 +16,6 @@ sc-client-api = { path = "../../../substrate/client/api" } futures = "0.3.28" async-trait = "0.1.73" -thiserror = "1.0.47" +thiserror = "1.0.48" jsonrpsee-core = "0.16.2" parity-scale-codec = "3.6.4" diff --git a/cumulus/client/relay-chain-rpc-interface/Cargo.toml b/cumulus/client/relay-chain-rpc-interface/Cargo.toml index 9797c512505c..305ab82b064c 100644 --- a/cumulus/client/relay-chain-rpc-interface/Cargo.toml +++ b/cumulus/client/relay-chain-rpc-interface/Cargo.toml @@ -38,6 +38,6 @@ schnellru = "0.2.1" smoldot = { version = "0.11.0", default_features = false, features = ["std"]} smoldot-light = { version = "0.9.0", default_features = false, features = ["std"] } either = "1.8.1" -thiserror = "1.0.38" +thiserror = "1.0.48" rand = "0.8.5" pin-project = "1.1.3" diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index bcb4f2ac1308..c8c3f91f9835 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -17,7 +17,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] clap = { version = "4.4.2", features = ["derive"], optional = true } log = "0.4.17" -thiserror = "1.0.31" +thiserror = "1.0.48" futures = "0.3.21" pyro = { package = "pyroscope", version = "0.5.3", optional = true } pyroscope_pprofrs = { version = "0.2", optional = true } diff --git a/polkadot/erasure-coding/Cargo.toml b/polkadot/erasure-coding/Cargo.toml index f74a88038825..d07b77ec4ddf 100644 --- a/polkadot/erasure-coding/Cargo.toml +++ b/polkadot/erasure-coding/Cargo.toml @@ -12,7 +12,7 @@ novelpoly = { package = "reed-solomon-novelpoly", version = "1.0.0" } parity-scale-codec = { version = "3.6.1", default-features = false, features = ["std", "derive"] } sp-core = { path = "../../substrate/primitives/core" } sp-trie = { path = "../../substrate/primitives/trie" } -thiserror = "1.0.31" +thiserror = "1.0.48" [dev-dependencies] criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support"] } diff --git a/polkadot/node/collation-generation/Cargo.toml b/polkadot/node/collation-generation/Cargo.toml index e2870dc2cc8a..b110540140f9 100644 --- a/polkadot/node/collation-generation/Cargo.toml +++ b/polkadot/node/collation-generation/Cargo.toml @@ -15,7 +15,7 @@ polkadot-node-subsystem-util = { path = "../subsystem-util" } polkadot-primitives = { path = "../../primitives" } sp-core = { path = "../../../substrate/primitives/core" } sp-maybe-compressed-blob = { path = "../../../substrate/primitives/maybe-compressed-blob" } -thiserror = "1.0.31" +thiserror = "1.0.48" parity-scale-codec = { version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } [dev-dependencies] diff --git a/polkadot/node/core/approval-voting/Cargo.toml b/polkadot/node/core/approval-voting/Cargo.toml index 307d9947a961..acad0d1fa4e4 100644 --- a/polkadot/node/core/approval-voting/Cargo.toml +++ b/polkadot/node/core/approval-voting/Cargo.toml @@ -16,7 +16,7 @@ merlin = "2.0" schnorrkel = "0.9.1" kvdb = "0.13.0" derive_more = "0.99.17" -thiserror = "1.0.31" +thiserror = "1.0.48" polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } diff --git a/polkadot/node/core/av-store/Cargo.toml b/polkadot/node/core/av-store/Cargo.toml index efbbb27754e2..955fe37d7c39 100644 --- a/polkadot/node/core/av-store/Cargo.toml +++ b/polkadot/node/core/av-store/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true futures = "0.3.21" futures-timer = "3.0.2" kvdb = "0.13.0" -thiserror = "1.0.31" +thiserror = "1.0.48" gum = { package = "tracing-gum", path = "../../gum" } bitvec = "1.0.0" diff --git a/polkadot/node/core/backing/Cargo.toml b/polkadot/node/core/backing/Cargo.toml index 0005f6f6a30d..e7e6358e8a46 100644 --- a/polkadot/node/core/backing/Cargo.toml +++ b/polkadot/node/core/backing/Cargo.toml @@ -16,7 +16,7 @@ erasure-coding = { package = "polkadot-erasure-coding", path = "../../../erasure statement-table = { package = "polkadot-statement-table", path = "../../../statement-table" } bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } gum = { package = "tracing-gum", path = "../../gum" } -thiserror = "1.0.31" +thiserror = "1.0.48" fatality = "0.0.6" [dev-dependencies] diff --git a/polkadot/node/core/bitfield-signing/Cargo.toml b/polkadot/node/core/bitfield-signing/Cargo.toml index c2df6cc709e6..de38d18d9706 100644 --- a/polkadot/node/core/bitfield-signing/Cargo.toml +++ b/polkadot/node/core/bitfield-signing/Cargo.toml @@ -13,7 +13,7 @@ polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } sp-keystore = { path = "../../../../substrate/primitives/keystore" } wasm-timer = "0.2.5" -thiserror = "1.0.31" +thiserror = "1.0.48" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/polkadot/node/core/chain-selection/Cargo.toml b/polkadot/node/core/chain-selection/Cargo.toml index 57ba7908315b..7678379870e0 100644 --- a/polkadot/node/core/chain-selection/Cargo.toml +++ b/polkadot/node/core/chain-selection/Cargo.toml @@ -15,7 +15,7 @@ polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } kvdb = "0.13.0" -thiserror = "1.0.31" +thiserror = "1.0.48" parity-scale-codec = "3.6.1" [dev-dependencies] diff --git a/polkadot/node/core/dispute-coordinator/Cargo.toml b/polkadot/node/core/dispute-coordinator/Cargo.toml index c49bd507127d..6061c52b7e81 100644 --- a/polkadot/node/core/dispute-coordinator/Cargo.toml +++ b/polkadot/node/core/dispute-coordinator/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } parity-scale-codec = "3.6.1" kvdb = "0.13.0" -thiserror = "1.0.31" +thiserror = "1.0.48" schnellru = "0.2.1" fatality = "0.0.6" diff --git a/polkadot/node/core/parachains-inherent/Cargo.toml b/polkadot/node/core/parachains-inherent/Cargo.toml index 515d70dad827..18d91dcfb565 100644 --- a/polkadot/node/core/parachains-inherent/Cargo.toml +++ b/polkadot/node/core/parachains-inherent/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true futures = "0.3.21" futures-timer = "3.0.2" gum = { package = "tracing-gum", path = "../../gum" } -thiserror = "1.0.31" +thiserror = "1.0.48" async-trait = "0.1.57" polkadot-node-subsystem = { path = "../../subsystem" } polkadot-overseer = { path = "../../overseer" } diff --git a/polkadot/node/core/prospective-parachains/Cargo.toml b/polkadot/node/core/prospective-parachains/Cargo.toml index 9fa17ec0c154..77a59d87f3fa 100644 --- a/polkadot/node/core/prospective-parachains/Cargo.toml +++ b/polkadot/node/core/prospective-parachains/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true futures = "0.3.19" gum = { package = "tracing-gum", path = "../../gum" } parity-scale-codec = "3.6.4" -thiserror = "1.0.30" +thiserror = "1.0.48" fatality = "0.0.6" bitvec = "1" diff --git a/polkadot/node/core/provisioner/Cargo.toml b/polkadot/node/core/provisioner/Cargo.toml index dc7914171668..05ea92caa976 100644 --- a/polkadot/node/core/provisioner/Cargo.toml +++ b/polkadot/node/core/provisioner/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } -thiserror = "1.0.31" +thiserror = "1.0.48" polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } diff --git a/polkadot/node/core/pvf-checker/Cargo.toml b/polkadot/node/core/pvf-checker/Cargo.toml index 783ac19009a3..0326a20e5a52 100644 --- a/polkadot/node/core/pvf-checker/Cargo.toml +++ b/polkadot/node/core/pvf-checker/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true [dependencies] futures = "0.3.21" -thiserror = "1.0.31" +thiserror = "1.0.48" gum = { package = "tracing-gum", path = "../../gum" } polkadot-node-primitives = { path = "../../primitives" } diff --git a/polkadot/node/jaeger/Cargo.toml b/polkadot/node/jaeger/Cargo.toml index 7b4b5e1c8bce..fcfbbaec611e 100644 --- a/polkadot/node/jaeger/Cargo.toml +++ b/polkadot/node/jaeger/Cargo.toml @@ -14,7 +14,7 @@ polkadot-primitives = { path = "../../primitives" } polkadot-node-primitives = { path = "../primitives" } sc-network = { path = "../../../substrate/client/network" } sp-core = { path = "../../../substrate/primitives/core" } -thiserror = "1.0.31" +thiserror = "1.0.48" tokio = "1.24.2" log = "0.4.17" parity-scale-codec = { version = "3.6.1", default-features = false } diff --git a/polkadot/node/network/availability-distribution/Cargo.toml b/polkadot/node/network/availability-distribution/Cargo.toml index 581192e9560f..c3c7aa4e0ea5 100644 --- a/polkadot/node/network/availability-distribution/Cargo.toml +++ b/polkadot/node/network/availability-distribution/Cargo.toml @@ -17,7 +17,7 @@ polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-primitives = { path = "../../primitives" } sp-core = { path = "../../../../substrate/primitives/core", features = ["std"] } sp-keystore = { path = "../../../../substrate/primitives/keystore" } -thiserror = "1.0.31" +thiserror = "1.0.48" rand = "0.8.5" derive_more = "0.99.17" schnellru = "0.2.1" diff --git a/polkadot/node/network/availability-recovery/Cargo.toml b/polkadot/node/network/availability-recovery/Cargo.toml index bf95fb1e9f4c..07ff09c7e70e 100644 --- a/polkadot/node/network/availability-recovery/Cargo.toml +++ b/polkadot/node/network/availability-recovery/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.21" schnellru = "0.2.1" rand = "0.8.5" fatality = "0.0.6" -thiserror = "1.0.31" +thiserror = "1.0.48" gum = { package = "tracing-gum", path = "../../gum" } polkadot-erasure-coding = { path = "../../../erasure-coding" } diff --git a/polkadot/node/network/collator-protocol/Cargo.toml b/polkadot/node/network/collator-protocol/Cargo.toml index ac6284b305bd..e5328cf16629 100644 --- a/polkadot/node/network/collator-protocol/Cargo.toml +++ b/polkadot/node/network/collator-protocol/Cargo.toml @@ -21,7 +21,7 @@ polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-subsystem = { path = "../../subsystem" } fatality = "0.0.6" -thiserror = "1.0.31" +thiserror = "1.0.48" tokio-util = "0.7.1" [dev-dependencies] diff --git a/polkadot/node/network/dispute-distribution/Cargo.toml b/polkadot/node/network/dispute-distribution/Cargo.toml index ece89f34c88d..5d8e245d289a 100644 --- a/polkadot/node/network/dispute-distribution/Cargo.toml +++ b/polkadot/node/network/dispute-distribution/Cargo.toml @@ -20,7 +20,7 @@ polkadot-node-primitives = { path = "../../primitives" } sc-network = { path = "../../../../substrate/client/network" } sp-application-crypto = { path = "../../../../substrate/primitives/application-crypto" } sp-keystore = { path = "../../../../substrate/primitives/keystore" } -thiserror = "1.0.31" +thiserror = "1.0.48" fatality = "0.0.6" schnellru = "0.2.1" indexmap = "1.9.1" diff --git a/polkadot/node/network/protocol/Cargo.toml b/polkadot/node/network/protocol/Cargo.toml index 2a56f197b854..c33b9eae3252 100644 --- a/polkadot/node/network/protocol/Cargo.toml +++ b/polkadot/node/network/protocol/Cargo.toml @@ -18,7 +18,7 @@ sc-network = { path = "../../../../substrate/client/network" } sc-authority-discovery = { path = "../../../../substrate/client/authority-discovery" } strum = { version = "0.24", features = ["derive"] } futures = "0.3.21" -thiserror = "1.0.31" +thiserror = "1.0.48" fatality = "0.0.6" rand = "0.8" derive_more = "0.99" diff --git a/polkadot/node/network/statement-distribution/Cargo.toml b/polkadot/node/network/statement-distribution/Cargo.toml index 5ff1ba9de02b..bf516e7b7ba9 100644 --- a/polkadot/node/network/statement-distribution/Cargo.toml +++ b/polkadot/node/network/statement-distribution/Cargo.toml @@ -21,7 +21,7 @@ polkadot-node-network-protocol = { path = "../protocol" } arrayvec = "0.7.4" indexmap = "1.9.1" parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } -thiserror = "1.0.31" +thiserror = "1.0.48" fatality = "0.0.6" bitvec = "1" diff --git a/polkadot/node/primitives/Cargo.toml b/polkadot/node/primitives/Cargo.toml index ef03c02f7bc6..55dfa6738709 100644 --- a/polkadot/node/primitives/Cargo.toml +++ b/polkadot/node/primitives/Cargo.toml @@ -19,7 +19,7 @@ sp-maybe-compressed-blob = { path = "../../../substrate/primitives/maybe-compres sp-runtime = { path = "../../../substrate/primitives/runtime" } polkadot-parachain-primitives = { path = "../../parachain", default-features = false } schnorrkel = "0.9.1" -thiserror = "1.0.31" +thiserror = "1.0.48" serde = { version = "1.0.188", features = ["derive"] } [target.'cfg(not(target_os = "unknown"))'.dependencies] diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index 90881aa051a0..03814af19cd2 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -79,7 +79,7 @@ hex-literal = "0.4.1" gum = { package = "tracing-gum", path = "../gum" } serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.96" -thiserror = "1.0.31" +thiserror = "1.0.48" kvdb = "0.13.0" kvdb-rocksdb = { version = "0.19.0", optional = true } parity-db = { version = "0.4.8", optional = true } diff --git a/polkadot/node/subsystem-types/Cargo.toml b/polkadot/node/subsystem-types/Cargo.toml index 7ca3a0faf31a..317b079a316c 100644 --- a/polkadot/node/subsystem-types/Cargo.toml +++ b/polkadot/node/subsystem-types/Cargo.toml @@ -22,5 +22,5 @@ sp-authority-discovery = { path = "../../../substrate/primitives/authority-disco sc-transaction-pool-api = { path = "../../../substrate/client/transaction-pool/api" } smallvec = "1.8.0" substrate-prometheus-endpoint = { path = "../../../substrate/utils/prometheus" } -thiserror = "1.0.31" +thiserror = "1.0.48" async-trait = "0.1.57" diff --git a/polkadot/node/subsystem-util/Cargo.toml b/polkadot/node/subsystem-util/Cargo.toml index d243a90a2bd6..204df0dad117 100644 --- a/polkadot/node/subsystem-util/Cargo.toml +++ b/polkadot/node/subsystem-util/Cargo.toml @@ -15,7 +15,7 @@ parity-scale-codec = { version = "3.6.1", default-features = false, features = [ parking_lot = "0.11.2" pin-project = "1.0.9" rand = "0.8.5" -thiserror = "1.0.31" +thiserror = "1.0.48" fatality = "0.0.6" gum = { package = "tracing-gum", path = "../gum" } derive_more = "0.99.17" diff --git a/polkadot/node/test/performance-test/Cargo.toml b/polkadot/node/test/performance-test/Cargo.toml index 98b67615a6f2..5747ac88b1e4 100644 --- a/polkadot/node/test/performance-test/Cargo.toml +++ b/polkadot/node/test/performance-test/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true license.workspace = true [dependencies] -thiserror = "1.0.31" +thiserror = "1.0.48" quote = "1.0.28" env_logger = "0.9" log = "0.4" diff --git a/polkadot/node/zombienet-backchannel/Cargo.toml b/polkadot/node/zombienet-backchannel/Cargo.toml index 3d59a4a3cddc..9bf56b550bbc 100644 --- a/polkadot/node/zombienet-backchannel/Cargo.toml +++ b/polkadot/node/zombienet-backchannel/Cargo.toml @@ -16,7 +16,7 @@ futures-util = "0.3.23" lazy_static = "1.4.0" parity-scale-codec = { version = "3.6.1", features = ["derive"] } reqwest = { version = "0.11", features = ["rustls-tls"], default-features = false } -thiserror = "1.0.31" +thiserror = "1.0.48" gum = { package = "tracing-gum", path = "../gum" } serde = { version = "1.0", features = ["derive"] } serde_json = "1" diff --git a/polkadot/utils/staking-miner/Cargo.toml b/polkadot/utils/staking-miner/Cargo.toml index 09e73bc10f2d..4b012e3ac73f 100644 --- a/polkadot/utils/staking-miner/Cargo.toml +++ b/polkadot/utils/staking-miner/Cargo.toml @@ -19,7 +19,7 @@ log = "0.4.17" paste = "1.0.7" serde = "1.0.188" serde_json = "1.0" -thiserror = "1.0.31" +thiserror = "1.0.48" tokio = { version = "1.24.2", features = ["macros", "rt-multi-thread", "sync"] } remote-externalities = { package = "frame-remote-externalities" , path = "../../../substrate/utils/frame/remote-externalities" } signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } diff --git a/substrate/client/allocator/Cargo.toml b/substrate/client/allocator/Cargo.toml index ffbfe14e86c2..31c714180ce5 100644 --- a/substrate/client/allocator/Cargo.toml +++ b/substrate/client/allocator/Cargo.toml @@ -15,6 +15,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.17" -thiserror = "1.0.30" +thiserror = "1.0.48" sp-core = { path = "../../primitives/core" } sp-wasm-interface = { path = "../../primitives/wasm-interface" } diff --git a/substrate/client/api/Cargo.toml b/substrate/client/api/Cargo.toml index 43545095c0ea..b59149424ed3 100644 --- a/substrate/client/api/Cargo.toml +++ b/substrate/client/api/Cargo.toml @@ -37,6 +37,6 @@ sp-statement-store = { path = "../../primitives/statement-store" } sp-storage = { path = "../../primitives/storage" } [dev-dependencies] -thiserror = "1.0.30" +thiserror = "1.0.48" sp-test-primitives = { path = "../../primitives/test-primitives" } substrate-test-runtime = { path = "../../test-utils/runtime" } diff --git a/substrate/client/cli/Cargo.toml b/substrate/client/cli/Cargo.toml index 917cdc04d1d9..06967a890931 100644 --- a/substrate/client/cli/Cargo.toml +++ b/substrate/client/cli/Cargo.toml @@ -27,7 +27,7 @@ regex = "1.6.0" rpassword = "7.0.0" serde = "1.0.188" serde_json = "1.0.85" -thiserror = "1.0.30" +thiserror = "1.0.48" tiny-bip39 = "1.0.0" tokio = { version = "1.22.0", features = ["signal", "rt-multi-thread", "parking_lot"] } sc-client-api = { path = "../api" } diff --git a/substrate/client/consensus/common/Cargo.toml b/substrate/client/consensus/common/Cargo.toml index c9b3f221ecc0..f269e3752d43 100644 --- a/substrate/client/consensus/common/Cargo.toml +++ b/substrate/client/consensus/common/Cargo.toml @@ -21,7 +21,7 @@ log = "0.4.17" mockall = "0.11.3" parking_lot = "0.12.1" serde = { version = "1.0", features = ["derive"] } -thiserror = "1.0.30" +thiserror = "1.0.48" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus" } sc-client-api = { path = "../../api" } sc-utils = { path = "../../utils" } diff --git a/substrate/client/executor/common/Cargo.toml b/substrate/client/executor/common/Cargo.toml index e84b9f9c85b8..5118279b43b4 100644 --- a/substrate/client/executor/common/Cargo.toml +++ b/substrate/client/executor/common/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -thiserror = "1.0.30" +thiserror = "1.0.48" wasm-instrument = "0.3" sc-allocator = { path = "../../allocator" } sp-maybe-compressed-blob = { path = "../../../primitives/maybe-compressed-blob" } diff --git a/substrate/client/service/Cargo.toml b/substrate/client/service/Cargo.toml index 6f794d93fed3..87b341fe3123 100644 --- a/substrate/client/service/Cargo.toml +++ b/substrate/client/service/Cargo.toml @@ -26,7 +26,7 @@ runtime-benchmarks = [ [dependencies] jsonrpsee = { version = "0.16.2", features = ["server"] } -thiserror = "1.0.30" +thiserror = "1.0.48" futures = "0.3.21" rand = "0.8.5" parking_lot = "0.12.1" diff --git a/substrate/client/storage-monitor/Cargo.toml b/substrate/client/storage-monitor/Cargo.toml index c5b71260f97e..5354819e3a38 100644 --- a/substrate/client/storage-monitor/Cargo.toml +++ b/substrate/client/storage-monitor/Cargo.toml @@ -15,4 +15,4 @@ fs4 = "0.6.3" sc-client-db = { path = "../db", default-features = false} sp-core = { path = "../../primitives/core" } tokio = "1.22.0" -thiserror = "1.0.30" +thiserror = "1.0.48" diff --git a/substrate/client/sync-state-rpc/Cargo.toml b/substrate/client/sync-state-rpc/Cargo.toml index 59cc6ba40481..88d268cc93d9 100644 --- a/substrate/client/sync-state-rpc/Cargo.toml +++ b/substrate/client/sync-state-rpc/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1" } jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.85" -thiserror = "1.0.30" +thiserror = "1.0.48" sc-chain-spec = { path = "../chain-spec" } sc-client-api = { path = "../api" } sc-consensus-babe = { path = "../consensus/babe" } diff --git a/substrate/client/telemetry/Cargo.toml b/substrate/client/telemetry/Cargo.toml index 153629129091..2be5ad5c1435 100644 --- a/substrate/client/telemetry/Cargo.toml +++ b/substrate/client/telemetry/Cargo.toml @@ -24,5 +24,5 @@ sc-utils = { path = "../utils" } rand = "0.8.5" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.85" -thiserror = "1.0.30" +thiserror = "1.0.48" wasm-timer = "0.2.5" diff --git a/substrate/client/tracing/Cargo.toml b/substrate/client/tracing/Cargo.toml index c9cd6ca313cd..ffcbf0749083 100644 --- a/substrate/client/tracing/Cargo.toml +++ b/substrate/client/tracing/Cargo.toml @@ -23,7 +23,7 @@ parking_lot = "0.12.1" regex = "1.6.0" rustc-hash = "1.1.0" serde = "1.0.188" -thiserror = "1.0.30" +thiserror = "1.0.48" tracing = "0.1.29" tracing-log = "0.1.3" tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } diff --git a/substrate/client/transaction-pool/Cargo.toml b/substrate/client/transaction-pool/Cargo.toml index 0e502cb39fba..b893dc839edd 100644 --- a/substrate/client/transaction-pool/Cargo.toml +++ b/substrate/client/transaction-pool/Cargo.toml @@ -21,7 +21,7 @@ linked-hash-map = "0.5.4" log = "0.4.17" parking_lot = "0.12.1" serde = { version = "1.0.188", features = ["derive"] } -thiserror = "1.0.30" +thiserror = "1.0.48" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } sc-client-api = { path = "../api" } sc-transaction-pool-api = { path = "api" } diff --git a/substrate/client/transaction-pool/api/Cargo.toml b/substrate/client/transaction-pool/api/Cargo.toml index edab1304e01c..5ff5a4149ca9 100644 --- a/substrate/client/transaction-pool/api/Cargo.toml +++ b/substrate/client/transaction-pool/api/Cargo.toml @@ -14,7 +14,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1" } futures = "0.3.21" log = "0.4.17" serde = { version = "1.0.188", features = ["derive"] } -thiserror = "1.0.30" +thiserror = "1.0.48" sp-blockchain = { path = "../../../primitives/blockchain" } sp-core = { path = "../../../primitives/core", default-features = false} sp-runtime = { path = "../../../primitives/runtime", default-features = false} diff --git a/substrate/primitives/api/Cargo.toml b/substrate/primitives/api/Cargo.toml index c5611b22017c..95b5dde37139 100644 --- a/substrate/primitives/api/Cargo.toml +++ b/substrate/primitives/api/Cargo.toml @@ -23,7 +23,7 @@ sp-version = { path = "../version", default-features = false} sp-state-machine = { path = "../state-machine", default-features = false, optional = true} sp-trie = { path = "../trie", default-features = false, optional = true} hash-db = { version = "0.16.0", optional = true } -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } sp-metadata-ir = { path = "../metadata-ir", default-features = false, optional = true} log = { version = "0.4.17", default-features = false } diff --git a/substrate/primitives/blockchain/Cargo.toml b/substrate/primitives/blockchain/Cargo.toml index 418f94589857..33db09ce0ac2 100644 --- a/substrate/primitives/blockchain/Cargo.toml +++ b/substrate/primitives/blockchain/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.21" log = "0.4.17" parking_lot = "0.12.1" schnellru = "0.2.1" -thiserror = "1.0.30" +thiserror = "1.0.48" sp-api = { path = "../api" } sp-consensus = { path = "../consensus/common" } sp-database = { path = "../database" } diff --git a/substrate/primitives/consensus/common/Cargo.toml b/substrate/primitives/consensus/common/Cargo.toml index 284e00b272e6..e8f6b806f8c6 100644 --- a/substrate/primitives/consensus/common/Cargo.toml +++ b/substrate/primitives/consensus/common/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] async-trait = "0.1.57" futures = { version = "0.3.21", features = ["thread-pool"] } log = "0.4.17" -thiserror = "1.0.30" +thiserror = "1.0.48" sp-core = { path = "../../core" } sp-inherents = { path = "../../inherents" } sp-runtime = { path = "../../runtime" } diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index efcaad1a6f61..4e5186f16878 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -39,7 +39,7 @@ sp-storage = { path = "../storage", default-features = false} sp-externalities = { path = "../externalities", optional = true} futures = { version = "0.3.21", optional = true } dyn-clonable = { version = "0.9.0", optional = true } -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } tracing = { version = "0.1.29", optional = true } bitflags = "1.3" paste = "1.0.7" diff --git a/substrate/primitives/inherents/Cargo.toml b/substrate/primitives/inherents/Cargo.toml index d3ac94aa5fb3..aa0aa95b3f8d 100644 --- a/substrate/primitives/inherents/Cargo.toml +++ b/substrate/primitives/inherents/Cargo.toml @@ -18,7 +18,7 @@ async-trait = { version = "0.1.57", optional = true } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2.2" -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } sp-runtime = { path = "../runtime", default-features = false, optional = true} sp-std = { path = "../std", default-features = false} diff --git a/substrate/primitives/state-machine/Cargo.toml b/substrate/primitives/state-machine/Cargo.toml index 3ab21308c3c8..8546345e5cae 100644 --- a/substrate/primitives/state-machine/Cargo.toml +++ b/substrate/primitives/state-machine/Cargo.toml @@ -20,7 +20,7 @@ log = { version = "0.4.17", default-features = false } parking_lot = { version = "0.12.1", optional = true } rand = { version = "0.8.5", optional = true } smallvec = "1.11.0" -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } tracing = { version = "0.1.29", optional = true } sp-core = { path = "../core", default-features = false} sp-externalities = { path = "../externalities", default-features = false} diff --git a/substrate/primitives/timestamp/Cargo.toml b/substrate/primitives/timestamp/Cargo.toml index 7de2a7d904d0..44b0fdd831c0 100644 --- a/substrate/primitives/timestamp/Cargo.toml +++ b/substrate/primitives/timestamp/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = { version = "0.1.57", optional = true } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } sp-inherents = { path = "../inherents", default-features = false} sp-runtime = { path = "../runtime", default-features = false} sp-std = { path = "../std", default-features = false} diff --git a/substrate/primitives/trie/Cargo.toml b/substrate/primitives/trie/Cargo.toml index 31eb009328c1..0bce597414b1 100644 --- a/substrate/primitives/trie/Cargo.toml +++ b/substrate/primitives/trie/Cargo.toml @@ -27,7 +27,7 @@ memory-db = { version = "0.32.0", default-features = false } nohash-hasher = { version = "0.2.0", optional = true } parking_lot = { version = "0.12.1", optional = true } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } tracing = { version = "0.1.29", optional = true } trie-db = { version = "0.27.0", default-features = false } trie-root = { version = "0.18.0", default-features = false } diff --git a/substrate/primitives/version/Cargo.toml b/substrate/primitives/version/Cargo.toml index 3002566f74ff..1ab51a08bbe3 100644 --- a/substrate/primitives/version/Cargo.toml +++ b/substrate/primitives/version/Cargo.toml @@ -19,7 +19,7 @@ impl-serde = { version = "0.4.0", default-features = false, optional = true } parity-wasm = { version = "0.45", optional = true } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0.188", default-features = false, features = ["derive", "alloc"], optional = true } -thiserror = { version = "1.0.30", optional = true } +thiserror = { version = "1.0.48", optional = true } sp-core-hashing-proc-macro = { path = "../core/hashing/proc-macro" } sp-runtime = { path = "../runtime", default-features = false} sp-std = { path = "../std", default-features = false} diff --git a/substrate/utils/frame/benchmarking-cli/Cargo.toml b/substrate/utils/frame/benchmarking-cli/Cargo.toml index 096e4be82d4b..85be451fa60c 100644 --- a/substrate/utils/frame/benchmarking-cli/Cargo.toml +++ b/substrate/utils/frame/benchmarking-cli/Cargo.toml @@ -28,7 +28,7 @@ rand = { version = "0.8.4", features = ["small_rng"] } rand_pcg = "0.3.1" serde = "1.0.188" serde_json = "1.0.85" -thiserror = "1.0.30" +thiserror = "1.0.48" thousands = "0.2.0" frame-benchmarking = { path = "../../../frame/benchmarking" } frame-support = { path = "../../../frame/support" } From 25f30b8d4fadc3ff1ee7737473910b0905ce38d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:47:08 +0300 Subject: [PATCH 026/103] Bump actions/checkout from 3 to 4 (#1398) * Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update fmt-check.yml * Update .github/workflows/check-licenses.yml Co-authored-by: Chevdor * Update .github/workflows/check-markdown.yml Co-authored-by: Chevdor * Update .github/workflows/fmt-check.yml Co-authored-by: Chevdor --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sergejs Kostjucenko <85877331+sergejparity@users.noreply.github.com> Co-authored-by: Chevdor --- .github/workflows/check-licenses.yml | 2 +- .github/workflows/check-markdown.yml | 2 +- .github/workflows/fmt-check.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-licenses.yml b/.github/workflows/check-licenses.yml index 3da699a354f6..4d0afefc47aa 100644 --- a/.github/workflows/check-licenses.yml +++ b/.github/workflows/check-licenses.yml @@ -14,7 +14,7 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout sources - uses: actions/checkout@v3 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - uses: actions/setup-node@v3.8.1 with: node-version: "18.x" diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml index b386fd6d1b1e..f1e46ca27351 100644 --- a/.github/workflows/check-markdown.yml +++ b/.github/workflows/check-markdown.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v3 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - uses: actions/setup-node@v3.8.1 with: diff --git a/.github/workflows/fmt-check.yml b/.github/workflows/fmt-check.yml index fd4b72061b92..df785404036e 100644 --- a/.github/workflows/fmt-check.yml +++ b/.github/workflows/fmt-check.yml @@ -16,7 +16,7 @@ jobs: container: image: paritytech/ci-unified:bullseye-1.70.0-2023-05-23-v20230706 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Cargo fmt run: cargo +nightly fmt --all -- --check From d5565d3d4b795042823f18974a640f43d7267262 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 5 Sep 2023 12:34:50 +0300 Subject: [PATCH 027/103] Get rid of polling in `WarpSync` (#1265) --- polkadot/node/service/src/lib.rs | 2 +- substrate/bin/node/cli/src/service.rs | 3 +- .../client/network/common/src/sync/warp.rs | 13 +- substrate/client/network/sync/src/engine.rs | 118 ++++-- substrate/client/network/sync/src/lib.rs | 335 ++++++++++-------- substrate/client/network/sync/src/warp.rs | 95 +++-- substrate/client/network/test/src/lib.rs | 5 +- substrate/client/service/src/builder.rs | 5 +- substrate/client/service/src/lib.rs | 2 +- 9 files changed, 344 insertions(+), 234 deletions(-) diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index 95c887947c98..7f4eadaba7f8 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -732,7 +732,7 @@ pub fn new_full( }: NewFullParams, ) -> Result { use polkadot_node_network_protocol::request_response::IncomingRequest; - use sc_network_common::sync::warp::WarpSyncParams; + use sc_network_sync::warp::WarpSyncParams; let is_offchain_indexing_enabled = config.offchain_worker.indexing_enabled; let role = config.role.clone(); diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index ecca5c60db51..e49c60fe2fb7 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -32,8 +32,7 @@ use sc_client_api::{Backend, BlockBackend}; use sc_consensus_babe::{self, SlotProportion}; use sc_executor::NativeElseWasmExecutor; use sc_network::{event::Event, NetworkEventStream, NetworkService}; -use sc_network_common::sync::warp::WarpSyncParams; -use sc_network_sync::SyncingService; +use sc_network_sync::{warp::WarpSyncParams, SyncingService}; use sc_service::{config::Configuration, error::Error as ServiceError, RpcHandlers, TaskManager}; use sc_statement_store::Store as StatementStore; use sc_telemetry::{Telemetry, TelemetryWorker}; diff --git a/substrate/client/network/common/src/sync/warp.rs b/substrate/client/network/common/src/sync/warp.rs index 91d6c4151a42..f4e39f438512 100644 --- a/substrate/client/network/common/src/sync/warp.rs +++ b/substrate/client/network/common/src/sync/warp.rs @@ -15,10 +15,9 @@ // along with Substrate. If not, see . use codec::{Decode, Encode}; -use futures::channel::oneshot; pub use sp_consensus_grandpa::{AuthorityList, SetId}; use sp_runtime::traits::{Block as BlockT, NumberFor}; -use std::{fmt, sync::Arc}; +use std::fmt; /// Scale-encoded warp sync proof response. pub struct EncodedProof(pub Vec); @@ -30,16 +29,6 @@ pub struct WarpProofRequest { pub begin: B::Hash, } -/// The different types of warp syncing. -pub enum WarpSyncParams { - /// Standard warp sync for the chain. - WithProvider(Arc>), - /// Skip downloading proofs and wait for a header of the state that should be downloaded. - /// - /// It is expected that the header provider ensures that the header is trusted. - WaitForTarget(oneshot::Receiver<::Header>), -} - /// Proof verification result. pub enum VerificationResult { /// Proof is valid, but the target was not reached. diff --git a/substrate/client/network/sync/src/engine.rs b/substrate/client/network/sync/src/engine.rs index 9b97bf2b7c34..23847d16c972 100644 --- a/substrate/client/network/sync/src/engine.rs +++ b/substrate/client/network/sync/src/engine.rs @@ -24,11 +24,16 @@ use crate::{ BlockAnnounceValidationResult, BlockAnnounceValidator as BlockAnnounceValidatorStream, }, service::{self, chain_sync::ToServiceCommand}, + warp::WarpSyncParams, ChainSync, ClientError, SyncingService, }; use codec::{Decode, Encode}; -use futures::{FutureExt, StreamExt}; +use futures::{ + channel::oneshot, + future::{BoxFuture, Fuse}, + FutureExt, StreamExt, +}; use futures_timer::Delay; use libp2p::PeerId; use prometheus_endpoint::{ @@ -47,7 +52,6 @@ use sc_network_common::{ role::Roles, sync::{ message::{BlockAnnounce, BlockAnnouncesHandshake, BlockState}, - warp::WarpSyncParams, BadPeer, ChainSync as ChainSyncT, ExtendedPeerInfo, SyncEvent, }, }; @@ -67,6 +71,9 @@ use std::{ time::{Duration, Instant}, }; +/// Log target for this file. +const LOG_TARGET: &'static str = "sync"; + /// Interval at which we perform time based maintenance const TICK_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(1100); @@ -251,6 +258,10 @@ pub struct SyncingEngine { /// The `PeerId`'s of all boot nodes. boot_node_ids: HashSet, + /// A channel to get target block header if we skip over proofs downloading during warp sync. + warp_sync_target_block_header_rx: + Fuse>>, + /// Protocol name used for block announcements block_announce_protocol_name: ProtocolName, @@ -299,7 +310,11 @@ where let max_blocks_per_request = if net_config.network_config.max_blocks_per_request > crate::MAX_BLOCKS_IN_RESPONSE as u32 { - log::info!(target: "sync", "clamping maximum blocks per request to {}", crate::MAX_BLOCKS_IN_RESPONSE); + log::info!( + target: LOG_TARGET, + "clamping maximum blocks per request to {}", + crate::MAX_BLOCKS_IN_RESPONSE, + ); crate::MAX_BLOCKS_IN_RESPONSE as u32 } else { net_config.network_config.max_blocks_per_request @@ -352,6 +367,19 @@ where total.saturating_sub(net_config.network_config.default_peers_set_num_full) as usize }; + // Split warp sync params into warp sync config and a channel to retreive target block + // header. + let (warp_sync_config, warp_sync_target_block_header_rx) = + warp_sync_params.map_or((None, None), |params| { + let (config, target_block_rx) = params.split(); + (Some(config), target_block_rx) + }); + + // Make sure polling of the target block channel is a no-op if there is no block to + // retrieve. + let warp_sync_target_block_header_rx = warp_sync_target_block_header_rx + .map_or(futures::future::pending().boxed().fuse(), |rx| rx.boxed().fuse()); + let (chain_sync, block_announce_config) = ChainSync::new( mode, client.clone(), @@ -360,7 +388,7 @@ where roles, max_parallel_downloads, max_blocks_per_request, - warp_sync_params, + warp_sync_config, metrics_registry, network_service.clone(), import_queue, @@ -404,6 +432,7 @@ where genesis_hash, important_peers, default_peers_set_no_slot_connected_peers: HashSet::new(), + warp_sync_target_block_header_rx, boot_node_ids, default_peers_set_no_slot_peers, default_peers_set_num_full, @@ -418,7 +447,7 @@ where match Metrics::register(r, is_major_syncing.clone()) { Ok(metrics) => Some(metrics), Err(err) => { - log::error!(target: "sync", "Failed to register metrics {err:?}"); + log::error!(target: LOG_TARGET, "Failed to register metrics {err:?}"); None }, } @@ -510,7 +539,10 @@ where let peer = match self.peers.get_mut(&peer_id) { Some(p) => p, None => { - log::error!(target: "sync", "Received block announce from disconnected peer {}", peer_id); + log::error!( + target: LOG_TARGET, + "Received block announce from disconnected peer {peer_id}", + ); debug_assert!(false); return }, @@ -536,11 +568,11 @@ where let header = match self.client.header(hash) { Ok(Some(header)) => header, Ok(None) => { - log::warn!(target: "sync", "Trying to announce unknown block: {}", hash); + log::warn!(target: LOG_TARGET, "Trying to announce unknown block: {hash}"); return }, Err(e) => { - log::warn!(target: "sync", "Error reading block header {}: {}", hash, e); + log::warn!(target: LOG_TARGET, "Error reading block header {hash}: {e}"); return }, }; @@ -551,7 +583,7 @@ where } let is_best = self.client.info().best_hash == hash; - log::debug!(target: "sync", "Reannouncing block {:?} is_best: {}", hash, is_best); + log::debug!(target: LOG_TARGET, "Reannouncing block {hash:?} is_best: {is_best}"); let data = data .or_else(|| self.block_announce_data_cache.get(&hash).cloned()) @@ -560,7 +592,7 @@ where for (peer_id, ref mut peer) in self.peers.iter_mut() { let inserted = peer.known_blocks.insert(hash); if inserted { - log::trace!(target: "sync", "Announcing block {:?} to {}", hash, peer_id); + log::trace!(target: LOG_TARGET, "Announcing block {hash:?} to {peer_id}"); let message = BlockAnnounce { header: header.clone(), state: if is_best { Some(BlockState::Best) } else { Some(BlockState::Normal) }, @@ -575,7 +607,7 @@ where /// Inform sync about new best imported block. pub fn new_best_block_imported(&mut self, hash: B::Hash, number: NumberFor) { - log::debug!(target: "sync", "New best block imported {:?}/#{}", hash, number); + log::debug!(target: LOG_TARGET, "New best block imported {hash:?}/#{number}"); self.chain_sync.update_chain_info(&hash, number); self.network_service.set_notification_handshake( @@ -619,7 +651,10 @@ where // consider it connected or are also all stalled. In order to unstall the node, // disconnect all peers and allow `ProtocolController` to establish new connections. if self.last_notification_io.elapsed() > INACTIVITY_EVICT_THRESHOLD { - log::debug!(target: "sync", "syncing has halted due to inactivity, evicting all peers"); + log::debug!( + target: LOG_TARGET, + "syncing has halted due to inactivity, evicting all peers", + ); for peer in self.peers.keys() { self.network_service.report_peer(*peer, rep::INACTIVE_SUBSTREAM); @@ -658,7 +693,10 @@ where ToServiceCommand::JustificationImported(peer_id, hash, number, success) => { self.chain_sync.on_justification_import(hash, number, success); if !success { - log::info!(target: "sync", "💔 Invalid justification provided by {} for #{}", peer_id, hash); + log::info!( + target: LOG_TARGET, + "💔 Invalid justification provided by {peer_id} for #{hash}", + ); self.network_service .disconnect_peer(peer_id, self.block_announce_protocol_name.clone()); self.network_service.report_peer( @@ -723,7 +761,7 @@ where }, Err(()) => { log::debug!( - target: "sync", + target: LOG_TARGET, "Failed to register peer {remote:?}: {received_handshake:?}", ); let _ = tx.send(false); @@ -732,7 +770,7 @@ where sc_network::SyncEvent::NotificationStreamClosed { remote } => { if self.on_sync_peer_disconnected(remote).is_err() { log::trace!( - target: "sync", + target: LOG_TARGET, "Disconnected peer which had earlier been refused by on_sync_peer_connected {}", remote ); @@ -749,9 +787,8 @@ where } } else { log::trace!( - target: "sync", - "Received sync for peer earlier refused by sync layer: {}", - remote + target: LOG_TARGET, + "Received sync for peer earlier refused by sync layer: {remote}", ); } } @@ -764,6 +801,21 @@ where } } + // Retreive warp sync target block header just before polling `ChainSync` + // to make progress as soon as we receive it. + match self.warp_sync_target_block_header_rx.poll_unpin(cx) { + Poll::Ready(Ok(target)) => { + self.chain_sync.set_warp_sync_target_block(target); + }, + Poll::Ready(Err(err)) => { + log::error!( + target: LOG_TARGET, + "Failed to get target block for warp sync. Error: {err:?}", + ); + }, + Poll::Pending => {}, + } + // Drive `ChainSync`. while let Poll::Ready(()) = self.chain_sync.poll(cx) {} @@ -784,9 +836,9 @@ where pub fn on_sync_peer_disconnected(&mut self, peer_id: PeerId) -> Result<(), ()> { if let Some(info) = self.peers.remove(&peer_id) { if self.important_peers.contains(&peer_id) { - log::warn!(target: "sync", "Reserved peer {} disconnected", peer_id); + log::warn!(target: LOG_TARGET, "Reserved peer {peer_id} disconnected"); } else { - log::debug!(target: "sync", "{} disconnected", peer_id); + log::debug!(target: LOG_TARGET, "{peer_id} disconnected"); } if !self.default_peers_set_no_slot_connected_peers.remove(&peer_id) && @@ -798,7 +850,7 @@ where }, None => { log::error!( - target: "sync", + target: LOG_TARGET, "trying to disconnect an inbound node which is not counted as inbound" ); debug_assert!(false); @@ -828,10 +880,13 @@ where sink: NotificationsSink, inbound: bool, ) -> Result<(), ()> { - log::trace!(target: "sync", "New peer {} {:?}", peer_id, status); + log::trace!(target: LOG_TARGET, "New peer {peer_id} {status:?}"); if self.peers.contains_key(&peer_id) { - log::error!(target: "sync", "Called on_sync_peer_connected with already connected peer {}", peer_id); + log::error!( + target: LOG_TARGET, + "Called on_sync_peer_connected with already connected peer {peer_id}", + ); debug_assert!(false); return Err(()) } @@ -841,7 +896,7 @@ where if self.important_peers.contains(&peer_id) { log::error!( - target: "sync", + target: LOG_TARGET, "Reserved peer id `{}` is on a different chain (our genesis: {} theirs: {})", peer_id, self.genesis_hash, @@ -849,7 +904,7 @@ where ); } else if self.boot_node_ids.contains(&peer_id) { log::error!( - target: "sync", + target: LOG_TARGET, "Bootnode with peer id `{}` is on a different chain (our genesis: {} theirs: {})", peer_id, self.genesis_hash, @@ -857,7 +912,7 @@ where ); } else { log::debug!( - target: "sync", + target: LOG_TARGET, "Peer is on different chain (our genesis: {} theirs: {})", self.genesis_hash, status.genesis_hash ); @@ -874,7 +929,10 @@ where status.roles.is_full() && inbound && self.num_in_peers == self.max_in_peers { - log::debug!(target: "sync", "All inbound slots have been consumed, rejecting {peer_id}"); + log::debug!( + target: LOG_TARGET, + "All inbound slots have been consumed, rejecting {peer_id}", + ); return Err(()) } @@ -884,7 +942,7 @@ where self.default_peers_set_no_slot_connected_peers.len() + this_peer_reserved_slot { - log::debug!(target: "sync", "Too many full nodes, rejecting {}", peer_id); + log::debug!(target: LOG_TARGET, "Too many full nodes, rejecting {peer_id}"); return Err(()) } @@ -892,7 +950,7 @@ where (self.peers.len() - self.chain_sync.num_peers()) >= self.default_peers_set_num_light { // Make sure that not all slots are occupied by light clients. - log::debug!(target: "sync", "Too many light nodes, rejecting {}", peer_id); + log::debug!(target: LOG_TARGET, "Too many light nodes, rejecting {peer_id}"); return Err(()) } @@ -921,7 +979,7 @@ where None }; - log::debug!(target: "sync", "Connected {}", peer_id); + log::debug!(target: LOG_TARGET, "Connected {peer_id}"); self.peers.insert(peer_id, peer); diff --git a/substrate/client/network/sync/src/lib.rs b/substrate/client/network/sync/src/lib.rs index 0c2013b14977..df0ed2c45410 100644 --- a/substrate/client/network/sync/src/lib.rs +++ b/substrate/client/network/sync/src/lib.rs @@ -32,7 +32,7 @@ use crate::{ blocks::BlockCollection, schema::v1::{StateRequest, StateResponse}, state::StateSync, - warp::{WarpProofImportResult, WarpSync}, + warp::{WarpProofImportResult, WarpSync, WarpSyncConfig}, }; use codec::{Decode, DecodeAll, Encode}; @@ -61,7 +61,7 @@ use sc_network_common::{ BlockAnnounce, BlockAnnouncesHandshake, BlockAttributes, BlockData, BlockRequest, BlockResponse, Direction, FromBlock, }, - warp::{EncodedProof, WarpProofRequest, WarpSyncParams, WarpSyncPhase, WarpSyncProgress}, + warp::{EncodedProof, WarpProofRequest, WarpSyncPhase, WarpSyncProgress}, BadPeer, ChainSync as ChainSyncT, ImportResult, Metrics, OnBlockData, OnBlockJustification, OnStateData, OpaqueBlockRequest, OpaqueBlockResponse, OpaqueStateRequest, OpaqueStateResponse, PeerInfo, PeerRequest, SyncMode, SyncState, SyncStatus, @@ -103,6 +103,9 @@ pub mod state_request_handler; pub mod warp; pub mod warp_request_handler; +/// Log target for this file. +const LOG_TARGET: &'static str = "sync"; + /// Maximum blocks to store in the import queue. const MAX_IMPORTING_BLOCKS: usize = 2048; @@ -302,10 +305,12 @@ pub struct ChainSync { state_sync: Option>, /// Warp sync in progress, if any. warp_sync: Option>, - /// Warp sync params. + /// Warp sync configuration. /// /// Will be `None` after `self.warp_sync` is `Some(_)`. - warp_sync_params: Option>, + warp_sync_config: Option>, + /// A temporary storage for warp sync target block until warp sync is initialized. + warp_sync_target_block_header: Option, /// Enable importing existing blocks. This is used used after the state download to /// catch up to the latest state while re-importing blocks. import_existing: bool, @@ -351,7 +356,7 @@ impl PeerSync { fn update_common_number(&mut self, new_common: NumberFor) { if self.common_number < new_common { trace!( - target: "sync", + target: LOG_TARGET, "Updating peer {} common number from={} => to={}.", self.peer_id, self.common_number, @@ -497,7 +502,7 @@ where // There is nothing sync can get from the node that has no blockchain data. match self.block_status(&best_hash) { Err(e) => { - debug!(target:"sync", "Error reading blockchain: {}", e); + debug!(target:LOG_TARGET, "Error reading blockchain: {e}"); Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR)) }, Ok(BlockStatus::KnownBad) => { @@ -515,7 +520,7 @@ where // an ancestor search, which is what we do in the next match case below. if self.queue_blocks.len() > MAJOR_SYNC_BLOCKS.into() { debug!( - target:"sync", + target:LOG_TARGET, "New peer with unknown best hash {} ({}), assuming common block.", self.best_queued_hash, self.best_queued_number @@ -536,10 +541,8 @@ where // If we are at genesis, just start downloading. let (state, req) = if self.best_queued_number.is_zero() { debug!( - target:"sync", - "New peer with best hash {} ({}).", - best_hash, - best_number, + target:LOG_TARGET, + "New peer with best hash {best_hash} ({best_number}).", ); (PeerSyncState::Available, None) @@ -547,7 +550,7 @@ where let common_best = std::cmp::min(self.best_queued_number, best_number); debug!( - target:"sync", + target:LOG_TARGET, "New peer with unknown best hash {} ({}), searching for common ancestor.", best_hash, best_number @@ -578,9 +581,14 @@ where if let SyncMode::Warp = self.mode { if self.peers.len() >= MIN_PEERS_TO_START_WARP_SYNC && self.warp_sync.is_none() { - log::debug!(target: "sync", "Starting warp state sync."); - if let Some(params) = self.warp_sync_params.take() { - self.warp_sync = Some(WarpSync::new(self.client.clone(), params)); + log::debug!(target: LOG_TARGET, "Starting warp state sync."); + + if let Some(config) = self.warp_sync_config.take() { + let mut warp_sync = WarpSync::new(self.client.clone(), config); + if let Some(header) = self.warp_sync_target_block_header.take() { + warp_sync.set_target_block(header); + } + self.warp_sync = Some(warp_sync); } } } @@ -590,10 +598,8 @@ where Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) => { debug!( - target: "sync", - "New peer with known best hash {} ({}).", - best_hash, - best_number, + target: LOG_TARGET, + "New peer with known best hash {best_hash} ({best_number}).", ); self.peers.insert( who, @@ -642,21 +648,23 @@ where .collect(); debug!( - target: "sync", - "Explicit sync request for block {:?} with no peers specified. \ - Syncing from these peers {:?} instead.", - hash, peers, + target: LOG_TARGET, + "Explicit sync request for block {hash:?} with no peers specified. \ + Syncing from these peers {peers:?} instead.", ); } else { - debug!(target: "sync", "Explicit sync request for block {:?} with {:?}", hash, peers); + debug!( + target: LOG_TARGET, + "Explicit sync request for block {hash:?} with {peers:?}", + ); } if self.is_known(hash) { - debug!(target: "sync", "Refusing to sync known hash {:?}", hash); + debug!(target: LOG_TARGET, "Refusing to sync known hash {hash:?}"); return } - trace!(target: "sync", "Downloading requested old fork {:?}", hash); + trace!(target: LOG_TARGET, "Downloading requested old fork {hash:?}"); for peer_id in &peers { if let Some(peer) = self.peers.get_mut(peer_id) { if let PeerSyncState::AncestorSearch { .. } = peer.state { @@ -689,7 +697,7 @@ where let new_blocks: Vec> = if let Some(peer) = self.peers.get_mut(who) { let mut blocks = response.blocks; if request.as_ref().map_or(false, |r| r.direction == Direction::Descending) { - trace!(target: "sync", "Reversing incoming block list"); + trace!(target: LOG_TARGET, "Reversing incoming block list"); blocks.reverse() } self.allowed_requests.add(who); @@ -740,17 +748,22 @@ where } }) .collect(); - debug!(target: "sync", "Drained {} gap blocks from {}", blocks.len(), gap_sync.best_queued_number); + debug!( + target: LOG_TARGET, + "Drained {} gap blocks from {}", + blocks.len(), + gap_sync.best_queued_number, + ); blocks } else { - debug!(target: "sync", "Unexpected gap block response from {}", who); + debug!(target: LOG_TARGET, "Unexpected gap block response from {who}"); return Err(BadPeer(*who, rep::NO_BLOCK)) } }, PeerSyncState::DownloadingStale(_) => { peer.state = PeerSyncState::Available; if blocks.is_empty() { - debug!(target: "sync", "Empty block response from {}", who); + debug!(target: LOG_TARGET, "Empty block response from {who}"); return Err(BadPeer(*who, rep::NO_BLOCK)) } validate_blocks::(&blocks, who, Some(request))?; @@ -779,7 +792,7 @@ where let matching_hash = match (blocks.get(0), self.client.hash(*current)) { (Some(block), Ok(maybe_our_block_hash)) => { trace!( - target: "sync", + target: LOG_TARGET, "Got ancestry block #{} ({}) from peer {}", current, block.hash, @@ -789,17 +802,15 @@ where }, (None, _) => { debug!( - target: "sync", - "Invalid response when searching for ancestor from {}", - who, + target: LOG_TARGET, + "Invalid response when searching for ancestor from {who}", ); return Err(BadPeer(*who, rep::UNKNOWN_ANCESTOR)) }, (_, Err(e)) => { info!( - target: "sync", - "❌ Error answering legitimate blockchain query: {}", - e, + target: LOG_TARGET, + "❌ Error answering legitimate blockchain query: {e}", ); return Err(BadPeer(*who, rep::BLOCKCHAIN_READ_ERROR)) }, @@ -817,7 +828,10 @@ where } } if matching_hash.is_none() && current.is_zero() { - trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); + trace!( + target:LOG_TARGET, + "Ancestry search: genesis mismatch for peer {who}", + ); return Err(BadPeer(*who, rep::GENESIS_MISMATCH)) } if let Some((next_state, next_num)) = @@ -833,7 +847,7 @@ where // Ancestry search is complete. Check if peer is on a stale fork unknown // to us and add it to sync targets if necessary. trace!( - target: "sync", + target: LOG_TARGET, "Ancestry search complete. Ours={} ({}), Theirs={} ({}), Common={:?} ({})", self.best_queued_hash, self.best_queued_number, @@ -846,7 +860,7 @@ where peer.best_number < self.best_queued_number { trace!( - target: "sync", + target: LOG_TARGET, "Added fork target {} for {}", peer.best_hash, who, @@ -879,11 +893,11 @@ where return Err(BadPeer(*who, rep::VERIFICATION_FAIL)), } } else if blocks.is_empty() { - debug!(target: "sync", "Empty block response from {}", who); + debug!(target: LOG_TARGET, "Empty block response from {who}"); return Err(BadPeer(*who, rep::NO_BLOCK)) } else { debug!( - target: "sync", + target: LOG_TARGET, "Too many blocks ({}) in warp target block response from {}", blocks.len(), who, @@ -892,7 +906,7 @@ where } } else { debug!( - target: "sync", + target: LOG_TARGET, "Logic error: we think we are downloading warp target block from {}, but no warp sync is happening.", who, ); @@ -944,7 +958,10 @@ where let peer = if let Some(peer) = self.peers.get_mut(&who) { peer } else { - error!(target: "sync", "💔 Called on_block_justification with a peer ID of an unknown peer"); + error!( + target: LOG_TARGET, + "💔 Called on_block_justification with a peer ID of an unknown peer", + ); return Ok(OnBlockJustification::Nothing) }; @@ -956,7 +973,7 @@ where let justification = if let Some(block) = response.blocks.into_iter().next() { if hash != block.hash { warn!( - target: "sync", + target: LOG_TARGET, "💔 Invalid block justification provided by {}: requested: {:?} got: {:?}", who, hash, @@ -972,10 +989,8 @@ where // we might have asked the peer for a justification on a block that we assumed it // had but didn't (regardless of whether it had a justification for it or not). trace!( - target: "sync", - "Peer {:?} provided empty response for justification request {:?}", - who, - hash, + target: LOG_TARGET, + "Peer {who:?} provided empty response for justification request {hash:?}", ); None @@ -1013,10 +1028,8 @@ where if number + STATE_SYNC_FINALITY_THRESHOLD.saturated_into() >= median { if let Ok(Some(header)) = self.client.header(*hash) { log::debug!( - target: "sync", - "Starting state sync for #{} ({})", - number, - hash, + target: LOG_TARGET, + "Starting state sync for #{number} ({hash})", ); self.state_sync = Some(StateSync::new( self.client.clone(), @@ -1033,9 +1046,8 @@ where if let Err(err) = r { warn!( - target: "sync", - "💔 Error cleaning up pending extra justification data requests: {}", - err, + target: LOG_TARGET, + "💔 Error cleaning up pending extra justification data requests: {err}", ); } } @@ -1057,12 +1069,12 @@ where let peer = if let Some(peer) = self.peers.get_mut(&who) { peer } else { - error!(target: "sync", "💔 Called `on_validated_block_announce` with a bad peer ID"); + error!(target: LOG_TARGET, "💔 Called `on_validated_block_announce` with a bad peer ID"); return }; if let PeerSyncState::AncestorSearch { .. } = peer.state { - trace!(target: "sync", "Peer {} is in the ancestor search state.", who); + trace!(target: LOG_TARGET, "Peer {} is in the ancestor search state.", who); return } @@ -1222,12 +1234,6 @@ where } fn poll(&mut self, cx: &mut std::task::Context) -> Poll<()> { - // Should be called before `process_outbound_requests` to ensure - // that a potential target block is directly leading to requests. - if let Some(warp_sync) = &mut self.warp_sync { - let _ = warp_sync.poll(cx); - } - self.process_outbound_requests(); while let Poll::Ready(result) = self.poll_pending_responses(cx) { @@ -1262,9 +1268,8 @@ where }, Err(err) => { log::warn!( - target: "sync", - "Failed to encode block request {:?}: {:?}", - opaque_req, err + target: LOG_TARGET, + "Failed to encode block request {opaque_req:?}: {err:?}", ); }, } @@ -1292,7 +1297,7 @@ where roles: Roles, max_parallel_downloads: u32, max_blocks_per_request: u32, - warp_sync_params: Option>, + warp_sync_config: Option>, metrics_registry: Option<&Registry>, network_service: service::network::NetworkServiceHandle, import_queue: Box>, @@ -1334,7 +1339,8 @@ where network_service, block_request_protocol_name, state_request_protocol_name, - warp_sync_params, + warp_sync_config, + warp_sync_target_block_header: None, warp_sync_protocol_name, block_announce_protocol_name: block_announce_config .notifications_protocol @@ -1346,7 +1352,10 @@ where match SyncingMetrics::register(r) { Ok(metrics) => Some(metrics), Err(err) => { - error!(target: "sync", "Failed to register metrics for ChainSync: {err:?}"); + error!( + target: LOG_TARGET, + "Failed to register metrics for ChainSync: {err:?}", + ); None }, } @@ -1403,7 +1412,7 @@ where new_blocks.retain(|b| !self.queue_blocks.contains(&b.hash)); if new_blocks.len() != orig_len { debug!( - target: "sync", + target: LOG_TARGET, "Ignoring {} blocks that are already queued", orig_len - new_blocks.len(), ); @@ -1420,7 +1429,7 @@ where .and_then(|b| b.header.as_ref().map(|h| (&b.hash, *h.number()))) { trace!( - target:"sync", + target:LOG_TARGET, "Accepted {} blocks ({:?}) with origin {:?}", new_blocks.len(), h, @@ -1444,7 +1453,7 @@ where /// through all peers to update our view of their state as well. fn on_block_queued(&mut self, hash: &B::Hash, number: NumberFor) { if self.fork_targets.remove(hash).is_some() { - trace!(target: "sync", "Completed fork sync {:?}", hash); + trace!(target: LOG_TARGET, "Completed fork sync {hash:?}"); } if let Some(gap_sync) = &mut self.gap_sync { if number > gap_sync.best_queued_number && number <= gap_sync.target { @@ -1463,7 +1472,7 @@ where let new_common_number = if peer.best_number >= number { number } else { peer.best_number }; trace!( - target: "sync", + target: LOG_TARGET, "Updating peer {} info, ours={}, common={}->{}, their best={}", n, number, @@ -1483,10 +1492,15 @@ where fn restart(&mut self) -> impl Iterator), BadPeer>> + '_ { self.blocks.clear(); if let Err(e) = self.reset_sync_start_point() { - warn!(target: "sync", "💔 Unable to restart sync: {}", e); + warn!(target: LOG_TARGET, "💔 Unable to restart sync: {e}"); } self.allowed_requests.set_all(); - debug!(target:"sync", "Restarted with {} ({})", self.best_queued_number, self.best_queued_hash); + debug!( + target: LOG_TARGET, + "Restarted with {} ({})", + self.best_queued_number, + self.best_queued_hash, + ); let old_peers = std::mem::take(&mut self.peers); old_peers.into_iter().filter_map(move |(id, mut p)| { @@ -1517,14 +1531,14 @@ where let info = self.client.info(); if matches!(self.mode, SyncMode::LightState { .. }) && info.finalized_state.is_some() { warn!( - target: "sync", + target: LOG_TARGET, "Can't use fast sync mode with a partially synced database. Reverting to full sync mode." ); self.mode = SyncMode::Full; } if matches!(self.mode, SyncMode::Warp) && info.finalized_state.is_some() { warn!( - target: "sync", + target: LOG_TARGET, "Can't use warp sync mode with a partially synced database. Reverting to full sync mode." ); self.mode = SyncMode::Full; @@ -1539,25 +1553,30 @@ where self.import_existing = true; // Latest state is missing, start with the last finalized state or genesis instead. if let Some((hash, number)) = info.finalized_state { - debug!(target: "sync", "Starting from finalized state #{}", number); + debug!(target: LOG_TARGET, "Starting from finalized state #{number}"); self.best_queued_hash = hash; self.best_queued_number = number; } else { - debug!(target: "sync", "Restarting from genesis"); + debug!(target: LOG_TARGET, "Restarting from genesis"); self.best_queued_hash = Default::default(); self.best_queued_number = Zero::zero(); } } if let Some((start, end)) = info.block_gap { - debug!(target: "sync", "Starting gap sync #{} - #{}", start, end); + debug!(target: LOG_TARGET, "Starting gap sync #{start} - #{end}"); self.gap_sync = Some(GapSync { best_queued_number: start - One::one(), target: end, blocks: BlockCollection::new(), }); } - trace!(target: "sync", "Restarted sync at #{} ({:?})", self.best_queued_number, self.best_queued_hash); + trace!( + target: LOG_TARGET, + "Restarted sync at #{} ({:?})", + self.best_queued_number, + self.best_queued_hash, + ); Ok(()) } @@ -1607,6 +1626,15 @@ where .collect() } + /// Set warp sync target block externally in case we skip warp proof downloading. + pub fn set_warp_sync_target_block(&mut self, header: B::Header) { + if let Some(ref mut warp_sync) = self.warp_sync { + warp_sync.set_target_block(header); + } else { + self.warp_sync_target_block_header = Some(header); + } + } + /// Generate block request for downloading of the target block body during warp sync. fn warp_target_block_request(&mut self) -> Option<(PeerId, BlockRequest)> { let sync = &self.warp_sync.as_ref()?; @@ -1625,7 +1653,7 @@ where // Find a random peer that has a block with the target number. for (id, peer) in self.peers.iter_mut() { if peer.state.is_available() && peer.best_number >= target_number { - trace!(target: "sync", "New warp target block request for {}", id); + trace!(target: LOG_TARGET, "New warp target block request for {id}"); peer.state = PeerSyncState::DownloadingWarpTargetBlock; self.allowed_requests.clear(); return Some((*id, request)) @@ -1716,9 +1744,8 @@ where }, Err(err) => { log::warn!( - target: "sync", - "Failed to encode state request {:?}: {:?}", - request, err + target: LOG_TARGET, + "Failed to encode state request {request:?}: {err:?}", ); }, } @@ -1742,9 +1769,8 @@ where ), None => { log::warn!( - target: "sync", - "Trying to send warp sync request when no protocol is configured {:?}", - request, + target: LOG_TARGET, + "Trying to send warp sync request when no protocol is configured {request:?}", ); }, } @@ -1759,7 +1785,12 @@ where let blocks = match self.block_response_into_blocks(&request, response) { Ok(blocks) => blocks, Err(err) => { - debug!(target: "sync", "Failed to decode block response from {}: {}", peer_id, err); + debug!( + target: LOG_TARGET, + "Failed to decode block response from {}: {}", + peer_id, + err, + ); self.network_service.report_peer(peer_id, rep::BAD_MESSAGE); return None }, @@ -1779,7 +1810,7 @@ where _ => Default::default(), }; trace!( - target: "sync", + target: LOG_TARGET, "BlockResponse {} from {} with {} blocks {}", block_response.id, peer_id, @@ -1888,10 +1919,8 @@ where Ok(proto) => proto, Err(e) => { debug!( - target: "sync", - "Failed to decode block response from peer {:?}: {:?}.", - id, - e + target: LOG_TARGET, + "Failed to decode block response from peer {id:?}: {e:?}.", ); self.network_service.report_peer(id, rep::BAD_MESSAGE); self.network_service @@ -1909,10 +1938,8 @@ where Ok(proto) => proto, Err(e) => { debug!( - target: "sync", - "Failed to decode state response from peer {:?}: {:?}.", - id, - e + target: LOG_TARGET, + "Failed to decode state response from peer {id:?}: {e:?}.", ); self.network_service.report_peer(id, rep::BAD_MESSAGE); self.network_service @@ -1930,7 +1957,7 @@ where }, }, Ok(Err(e)) => { - debug!(target: "sync", "Request to peer {:?} failed: {:?}.", id, e); + debug!(target: LOG_TARGET, "Request to peer {id:?} failed: {e:?}."); match e { RequestFailure::Network(OutboundFailure::Timeout) => { @@ -1971,9 +1998,8 @@ where }, Err(oneshot::Canceled) => { trace!( - target: "sync", - "Request to peer {:?} failed due to oneshot being canceled.", - id, + target: LOG_TARGET, + "Request to peer {id:?} failed due to oneshot being canceled.", ); self.network_service .disconnect_peer(id, self.block_announce_protocol_name.clone()); @@ -2058,7 +2084,7 @@ where } if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { - trace!(target: "sync", "Too many blocks in the queue."); + trace!(target: LOG_TARGET, "Too many blocks in the queue."); return Vec::new() } let is_major_syncing = self.status().state.is_major_syncing(); @@ -2093,7 +2119,7 @@ where queue.len() <= MAJOR_SYNC_BLOCKS.into() { trace!( - target: "sync", + target: LOG_TARGET, "Peer {:?} common block {} too far behind of our best {}. Starting ancestry search.", id, peer.common_number, @@ -2118,7 +2144,7 @@ where ) { peer.state = PeerSyncState::DownloadingNew(range.start); trace!( - target: "sync", + target: LOG_TARGET, "New block request for {}, (best:{}, common:{}) {:?}", id, peer.best_number, @@ -2141,7 +2167,7 @@ where }, max_blocks_per_request, ) { - trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); + trace!(target: LOG_TARGET, "Downloading fork {hash:?} from {id}"); peer.state = PeerSyncState::DownloadingStale(hash); Some((id, req)) } else if let Some((range, req)) = gap_sync.as_mut().and_then(|sync| { @@ -2157,7 +2183,7 @@ where }) { peer.state = PeerSyncState::DownloadingGap(range.start); trace!( - target: "sync", + target: LOG_TARGET, "New gap block request for {}, (best:{}, common:{}) {:?}", id, peer.best_number, @@ -2192,7 +2218,7 @@ where if peer.state.is_available() && peer.common_number >= sync.target_block_num() { peer.state = PeerSyncState::DownloadingState; let request = sync.next_request(); - trace!(target: "sync", "New StateRequest for {}: {:?}", id, request); + trace!(target: LOG_TARGET, "New StateRequest for {}: {:?}", id, request); self.allowed_requests.clear(); return Some((*id, OpaqueStateRequest(Box::new(request)))) } @@ -2207,7 +2233,7 @@ where { for (id, peer) in self.peers.iter_mut() { if peer.state.is_available() && peer.best_number >= target { - trace!(target: "sync", "New StateRequest for {}: {:?}", id, request); + trace!(target: LOG_TARGET, "New StateRequest for {id}: {request:?}"); peer.state = PeerSyncState::DownloadingState; self.allowed_requests.clear(); return Some((*id, OpaqueStateRequest(Box::new(request)))) @@ -2237,7 +2263,7 @@ where // Find a random peer that is synced as much as peer majority. for (id, peer) in self.peers.iter_mut() { if peer.state.is_available() && peer.best_number >= median { - trace!(target: "sync", "New WarpProofRequest for {}", id); + trace!(target: LOG_TARGET, "New WarpProofRequest for {id}"); peer.state = PeerSyncState::DownloadingWarpProof; self.allowed_requests.clear(); return Some((*id, request)) @@ -2256,7 +2282,7 @@ where ) -> Result, BadPeer> { let response: Box = response.0.downcast().map_err(|_error| { error!( - target: "sync", + target: LOG_TARGET, "Failed to downcast opaque state response, this is an implementation bug." ); @@ -2271,7 +2297,7 @@ where } let import_result = if let Some(sync) = &mut self.state_sync { debug!( - target: "sync", + target: LOG_TARGET, "Importing state data from {} with {} keys, {} proof nodes.", who, response.entries.len(), @@ -2280,7 +2306,7 @@ where sync.import(*response) } else if let Some(sync) = &mut self.warp_sync { debug!( - target: "sync", + target: LOG_TARGET, "Importing state data from {} with {} keys, {} proof nodes.", who, response.entries.len(), @@ -2288,7 +2314,7 @@ where ); sync.import_state(*response) } else { - debug!(target: "sync", "Ignored obsolete state response from {}", who); + debug!(target: LOG_TARGET, "Ignored obsolete state response from {who}"); return Err(BadPeer(*who, rep::NOT_REQUESTED)) }; @@ -2307,12 +2333,12 @@ where skip_execution: self.skip_execution(), state: Some(state), }; - debug!(target: "sync", "State download is complete. Import is queued"); + debug!(target: LOG_TARGET, "State download is complete. Import is queued"); Ok(OnStateData::Import(origin, block)) }, state::ImportResult::Continue => Ok(OnStateData::Continue), state::ImportResult::BadResponse => { - debug!(target: "sync", "Bad state data received from {}", who); + debug!(target: LOG_TARGET, "Bad state data received from {who}"); Err(BadPeer(*who, rep::BAD_BLOCK)) }, } @@ -2327,21 +2353,21 @@ where } let import_result = if let Some(sync) = &mut self.warp_sync { debug!( - target: "sync", + target: LOG_TARGET, "Importing warp proof data from {}, {} bytes.", who, response.0.len(), ); sync.import_warp_proof(response) } else { - debug!(target: "sync", "Ignored obsolete warp sync response from {}", who); + debug!(target: LOG_TARGET, "Ignored obsolete warp sync response from {who}"); return Err(BadPeer(*who, rep::NOT_REQUESTED)) }; match import_result { WarpProofImportResult::Success => Ok(()), WarpProofImportResult::BadResponse => { - debug!(target: "sync", "Bad proof data received from {}", who); + debug!(target: LOG_TARGET, "Bad proof data received from {who}"); Err(BadPeer(*who, rep::BAD_BLOCK)) }, } @@ -2379,7 +2405,7 @@ where count: usize, results: Vec<(Result>, BlockImportError>, B::Hash)>, ) -> Box), BadPeer>>> { - trace!(target: "sync", "Imported {} of {}", imported, count); + trace!(target: LOG_TARGET, "Imported {imported} of {count}"); let mut output = Vec::new(); @@ -2406,7 +2432,7 @@ where Ok(BlockImportStatus::ImportedUnknown(number, aux, who)) => { if aux.clear_justification_requests { trace!( - target: "sync", + target: LOG_TARGET, "Block imported clears all pending justification requests {number}: {hash:?}", ); self.clear_justification_requests(); @@ -2414,7 +2440,7 @@ where if aux.needs_justification { trace!( - target: "sync", + target: LOG_TARGET, "Block imported but requires justification {number}: {hash:?}", ); self.request_justification(&hash, number); @@ -2434,7 +2460,7 @@ where self.state_sync.as_ref().map_or(false, |s| s.target() == hash); if state_sync_complete { info!( - target: "sync", + target: LOG_TARGET, "State sync is complete ({} MiB), restarting block sync.", self.state_sync.as_ref().map_or(0, |s| s.progress().size / (1024 * 1024)), ); @@ -2448,7 +2474,7 @@ where .map_or(false, |s| s.target_block_hash() == Some(hash)); if warp_sync_complete { info!( - target: "sync", + target: LOG_TARGET, "Warp sync is complete ({} MiB), restarting block sync.", self.warp_sync.as_ref().map_or(0, |s| s.progress().total_bytes / (1024 * 1024)), ); @@ -2460,7 +2486,7 @@ where self.gap_sync.as_ref().map_or(false, |s| s.target == number); if gap_sync_complete { info!( - target: "sync", + target: LOG_TARGET, "Block history download is complete." ); self.gap_sync = None; @@ -2469,7 +2495,7 @@ where Err(BlockImportError::IncompleteHeader(who)) => if let Some(peer) = who { warn!( - target: "sync", + target: LOG_TARGET, "💔 Peer sent block with incomplete header to import", ); output.push(Err(BadPeer(peer, rep::INCOMPLETE_HEADER))); @@ -2480,7 +2506,7 @@ where who.map_or_else(|| "".into(), |peer| format!(" received from ({peer})")); warn!( - target: "sync", + target: LOG_TARGET, "💔 Verification failed for block {hash:?}{extra_message}: {e:?}", ); @@ -2493,7 +2519,7 @@ where Err(BlockImportError::BadBlock(who)) => if let Some(peer) = who { warn!( - target: "sync", + target: LOG_TARGET, "💔 Block {hash:?} received from peer {peer} has been blacklisted", ); output.push(Err(BadPeer(peer, rep::BAD_BLOCK))); @@ -2502,10 +2528,10 @@ where // This may happen if the chain we were requesting upon has been discarded // in the meantime because other chain has been finalized. // Don't mark it as bad as it still may be synced if explicitly requested. - trace!(target: "sync", "Obsolete block {hash:?}"); + trace!(target: LOG_TARGET, "Obsolete block {hash:?}"); }, e @ Err(BlockImportError::UnknownParent) | e @ Err(BlockImportError::Other(_)) => { - warn!(target: "sync", "💔 Error importing block {hash:?}: {}", e.unwrap_err()); + warn!(target: LOG_TARGET, "💔 Error importing block {hash:?}: {}", e.unwrap_err()); self.state_sync = None; self.warp_sync = None; output.extend(self.restart()); @@ -2625,7 +2651,7 @@ fn peer_block_request( return None } else if peer.common_number < finalized { trace!( - target: "sync", + target: LOG_TARGET, "Requesting pre-finalized chain from {:?}, common={}, finalized={}, peer best={}, our best={}", id, peer.common_number, finalized, peer.best_number, best_num, ); @@ -2704,11 +2730,21 @@ fn fork_sync_request( ) -> Option<(B::Hash, BlockRequest)> { targets.retain(|hash, r| { if r.number <= finalized { - trace!(target: "sync", "Removed expired fork sync request {:?} (#{})", hash, r.number); + trace!( + target: LOG_TARGET, + "Removed expired fork sync request {:?} (#{})", + hash, + r.number, + ); return false } if check_block(hash) != BlockStatus::Unknown { - trace!(target: "sync", "Removed obsolete fork sync request {:?} (#{})", hash, r.number); + trace!( + target: LOG_TARGET, + "Removed obsolete fork sync request {:?} (#{})", + hash, + r.number, + ); return false } true @@ -2729,7 +2765,10 @@ fn fork_sync_request( // request only single block 1 }; - trace!(target: "sync", "Downloading requested fork {:?} from {}, {} blocks", hash, id, count); + trace!( + target: LOG_TARGET, + "Downloading requested fork {hash:?} from {id}, {count} blocks", + ); return Some(( *hash, BlockRequest:: { @@ -2741,7 +2780,7 @@ fn fork_sync_request( }, )) } else { - trace!(target: "sync", "Fork too far in the future: {:?} (#{})", hash, r.number); + trace!(target: LOG_TARGET, "Fork too far in the future: {:?} (#{})", hash, r.number); } } None @@ -2778,7 +2817,7 @@ fn validate_blocks( if let Some(request) = request { if Some(blocks.len() as _) > request.max { debug!( - target: "sync", + target: LOG_TARGET, "Received more blocks than requested from {}. Expected in maximum {:?}, got {}.", who, request.max, @@ -2799,7 +2838,7 @@ fn validate_blocks( if !expected_block { debug!( - target: "sync", + target: LOG_TARGET, "Received block that was not requested. Requested {:?}, got {:?}.", request.from, block_header, @@ -2812,9 +2851,8 @@ fn validate_blocks( blocks.iter().any(|b| b.header.is_none()) { trace!( - target: "sync", - "Missing requested header for a block in response from {}.", - who, + target: LOG_TARGET, + "Missing requested header for a block in response from {who}.", ); return Err(BadPeer(*who, rep::BAD_RESPONSE)) @@ -2823,9 +2861,8 @@ fn validate_blocks( if request.fields.contains(BlockAttributes::BODY) && blocks.iter().any(|b| b.body.is_none()) { trace!( - target: "sync", - "Missing requested body for a block in response from {}.", - who, + target: LOG_TARGET, + "Missing requested body for a block in response from {who}.", ); return Err(BadPeer(*who, rep::BAD_RESPONSE)) @@ -2837,7 +2874,7 @@ fn validate_blocks( let hash = header.hash(); if hash != b.hash { debug!( - target:"sync", + target:LOG_TARGET, "Bad header received from {}. Expected hash {:?}, got {:?}", who, b.hash, @@ -2854,7 +2891,7 @@ fn validate_blocks( ); if expected != got { debug!( - target:"sync", + target:LOG_TARGET, "Bad extrinsic root for a block {} received from {}. Expected {:?}, got {:?}", b.hash, who, @@ -3092,7 +3129,7 @@ mod test { ) -> BlockRequest { let requests = sync.block_requests(); - log::trace!(target: "sync", "Requests: {:?}", requests); + log::trace!(target: LOG_TARGET, "Requests: {requests:?}"); assert_eq!(1, requests.len()); assert_eq!(*peer, requests[0].0); @@ -3469,7 +3506,7 @@ mod test { break }; - log::trace!(target: "sync", "Request: {:?}", request); + log::trace!(target: LOG_TARGET, "Request: {request:?}"); } // Now request and import the fork. @@ -3611,7 +3648,7 @@ mod test { break }; - log::trace!(target: "sync", "Request: {:?}", request); + log::trace!(target: LOG_TARGET, "Request: {request:?}"); } // Now request and import the fork. diff --git a/substrate/client/network/sync/src/warp.rs b/substrate/client/network/sync/src/warp.rs index 912ad78dfdd0..74835a6e015e 100644 --- a/substrate/client/network/sync/src/warp.rs +++ b/substrate/client/network/sync/src/warp.rs @@ -19,36 +19,75 @@ //! Warp sync support. use crate::{ - oneshot, schema::v1::{StateRequest, StateResponse}, state::{ImportResult, StateSync}, }; -use futures::FutureExt; +use futures::channel::oneshot; use log::error; use sc_client_api::ProofProvider; use sc_network_common::sync::{ message::{BlockAttributes, BlockData, BlockRequest, Direction, FromBlock}, warp::{ - EncodedProof, VerificationResult, WarpProofRequest, WarpSyncParams, WarpSyncPhase, - WarpSyncProgress, WarpSyncProvider, + EncodedProof, VerificationResult, WarpProofRequest, WarpSyncPhase, WarpSyncProgress, + WarpSyncProvider, }, }; use sp_blockchain::HeaderBackend; use sp_consensus_grandpa::{AuthorityList, SetId}; use sp_runtime::traits::{Block as BlockT, Header, NumberFor, Zero}; -use std::{sync::Arc, task::Poll}; +use std::sync::Arc; +/// Log target for this file. +const LOG_TARGET: &'static str = "sync"; + +/// The different types of warp syncing, passed to `build_network`. +pub enum WarpSyncParams { + /// Standard warp sync for the chain. + WithProvider(Arc>), + /// Skip downloading proofs and wait for a header of the state that should be downloaded. + /// + /// It is expected that the header provider ensures that the header is trusted. + WaitForTarget(oneshot::Receiver<::Header>), +} + +/// Warp sync configuration as accepted by [`WarpSync`]. +pub enum WarpSyncConfig { + /// Standard warp sync for the chain. + WithProvider(Arc>), + /// Skip downloading proofs and wait for a header of the state that should be downloaded. + /// + /// It is expected that the header provider ensures that the header is trusted. + WaitForTarget, +} + +impl WarpSyncParams { + /// Split `WarpSyncParams` into `WarpSyncConfig` and warp sync target block header receiver. + pub fn split( + self, + ) -> (WarpSyncConfig, Option::Header>>) { + match self { + WarpSyncParams::WithProvider(provider) => + (WarpSyncConfig::WithProvider(provider), None), + WarpSyncParams::WaitForTarget(rx) => (WarpSyncConfig::WaitForTarget, Some(rx)), + } + } +} + +/// Warp sync phase. enum Phase { + /// Downloading warp proofs. WarpProof { set_id: SetId, authorities: AuthorityList, last_hash: B::Hash, warp_sync_provider: Arc>, }, - PendingTargetBlock { - target_block: Option>, - }, + /// Waiting for target block to be set externally if we skip warp proofs downloading, + /// and start straight from the target block (used by parachains warp sync). + PendingTargetBlock, + /// Downloading target block. TargetBlock(B::Header), + /// Downloading state. State(StateSync), } @@ -83,10 +122,10 @@ where /// Create a new instance. When passing a warp sync provider we will be checking for proof and /// authorities. Alternatively we can pass a target block when we want to skip downloading /// proofs, in this case we will continue polling until the target block is known. - pub fn new(client: Arc, warp_sync_params: WarpSyncParams) -> Self { + pub fn new(client: Arc, warp_sync_config: WarpSyncConfig) -> Self { let last_hash = client.hash(Zero::zero()).unwrap().expect("Genesis header always exists"); - match warp_sync_params { - WarpSyncParams::WithProvider(warp_sync_provider) => { + match warp_sync_config { + WarpSyncConfig::WithProvider(warp_sync_provider) => { let phase = Phase::WarpProof { set_id: 0, authorities: warp_sync_provider.current_authorities(), @@ -95,35 +134,23 @@ where }; Self { client, phase, total_proof_bytes: 0 } }, - WarpSyncParams::WaitForTarget(block) => Self { - client, - phase: Phase::PendingTargetBlock { target_block: Some(block) }, - total_proof_bytes: 0, - }, + WarpSyncConfig::WaitForTarget => + Self { client, phase: Phase::PendingTargetBlock, total_proof_bytes: 0 }, } } - /// Poll to make progress. - /// - /// This only makes progress when `phase = Phase::PendingTargetBlock` and the pending block was - /// sent. - pub fn poll(&mut self, cx: &mut std::task::Context) { - let new_phase = if let Phase::PendingTargetBlock { target_block: Some(target_block) } = - &mut self.phase - { - match target_block.poll_unpin(cx) { - Poll::Ready(Ok(target)) => Phase::TargetBlock(target), - Poll::Ready(Err(e)) => { - error!(target: "sync", "Failed to get target block. Error: {:?}",e); - Phase::PendingTargetBlock { target_block: None } - }, - _ => return, - } - } else { + /// Set target block externally in case we skip warp proof downloading. + pub fn set_target_block(&mut self, header: B::Header) { + let Phase::PendingTargetBlock = self.phase else { + error!( + target: LOG_TARGET, + "Attempt to set warp sync target block in invalid phase.", + ); + debug_assert!(false); return }; - self.phase = new_phase; + self.phase = Phase::TargetBlock(header); } /// Validate and import a state response. diff --git a/substrate/client/network/test/src/lib.rs b/substrate/client/network/test/src/lib.rs index 2a20da5a556b..d350b0e54ae1 100644 --- a/substrate/client/network/test/src/lib.rs +++ b/substrate/client/network/test/src/lib.rs @@ -62,15 +62,14 @@ use sc_network::{ }; use sc_network_common::{ role::Roles, - sync::warp::{ - AuthorityList, EncodedProof, SetId, VerificationResult, WarpSyncParams, WarpSyncProvider, - }, + sync::warp::{AuthorityList, EncodedProof, SetId, VerificationResult, WarpSyncProvider}, }; use sc_network_light::light_client_requests::handler::LightClientRequestHandler; use sc_network_sync::{ block_request_handler::BlockRequestHandler, service::{chain_sync::SyncingService, network::NetworkServiceProvider}, state_request_handler::StateRequestHandler, + warp::WarpSyncParams, warp_request_handler, }; use sc_service::client::Client; diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index fe18d1d002d5..917b3be8dc7c 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -47,12 +47,13 @@ use sc_network::{ NetworkService, NetworkStateInfo, NetworkStatusProvider, }; use sc_network_bitswap::BitswapRequestHandler; -use sc_network_common::{role::Roles, sync::warp::WarpSyncParams}; +use sc_network_common::role::Roles; use sc_network_light::light_client_requests::handler::LightClientRequestHandler; use sc_network_sync::{ block_request_handler::BlockRequestHandler, engine::SyncingEngine, service::network::NetworkServiceProvider, state_request_handler::StateRequestHandler, - warp_request_handler::RequestHandler as WarpSyncRequestHandler, SyncingService, + warp::WarpSyncParams, warp_request_handler::RequestHandler as WarpSyncRequestHandler, + SyncingService, }; use sc_rpc::{ author::AuthorApiServer, diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index 0961967f9ca2..cd720e1c1e09 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -79,7 +79,7 @@ pub use sc_chain_spec::{ pub use sc_consensus::ImportQueue; pub use sc_executor::NativeExecutionDispatch; -pub use sc_network_common::sync::warp::WarpSyncParams; +pub use sc_network_sync::warp::WarpSyncParams; #[doc(hidden)] pub use sc_network_transactions::config::{TransactionImport, TransactionImportFuture}; pub use sc_rpc::{ From 23926b7ac93bbb5eeb96579e4b505afc3dd3af01 Mon Sep 17 00:00:00 2001 From: Marcin S Date: Tue, 5 Sep 2023 12:11:30 +0200 Subject: [PATCH 028/103] Remove redundant calls to `borrow()` (#1393) Co-authored-by: Keith Yeung Co-authored-by: Francisco Aguirre --- substrate/client/api/src/lib.rs | 5 +---- substrate/frame/message-queue/src/lib.rs | 4 ++-- substrate/frame/support/src/storage/generator/map.rs | 5 ++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/substrate/client/api/src/lib.rs b/substrate/client/api/src/lib.rs index faadf3663a59..f614a1e30b48 100644 --- a/substrate/client/api/src/lib.rs +++ b/substrate/client/api/src/lib.rs @@ -49,7 +49,6 @@ pub trait UsageProvider { pub mod utils { use sp_blockchain::{Error, HeaderBackend, HeaderMetadata}; use sp_runtime::traits::Block as BlockT; - use std::borrow::Borrow; /// Returns a function for checking block ancestry, the returned function will /// return `true` if the given hash (second parameter) is a descendent of the @@ -69,10 +68,8 @@ pub mod utils { return Ok(false) } - let current = current.as_ref().map(|(c, p)| (c.borrow(), p.borrow())); - let mut hash = hash; - if let Some((current_hash, current_parent_hash)) = current { + if let Some((current_hash, current_parent_hash)) = ¤t { if base == current_hash { return Ok(false) } diff --git a/substrate/frame/message-queue/src/lib.rs b/substrate/frame/message-queue/src/lib.rs index 9ded84bb035c..7c38dec4b080 100644 --- a/substrate/frame/message-queue/src/lib.rs +++ b/substrate/frame/message-queue/src/lib.rs @@ -1092,7 +1092,7 @@ impl Pallet { origin.clone(), page_index, page.first_index, - payload.deref(), + payload, weight, overweight_limit, ) { @@ -1242,7 +1242,7 @@ impl Pallet { if let Some((_, processed, message)) = page.peek_index(i.try_into().expect("std-only code")) { - let msg = String::from_utf8_lossy(message.deref()); + let msg = String::from_utf8_lossy(message); if processed { page_info.push('*'); } diff --git a/substrate/frame/support/src/storage/generator/map.rs b/substrate/frame/support/src/storage/generator/map.rs index 90fac4b41c75..1d2511e324dc 100644 --- a/substrate/frame/support/src/storage/generator/map.rs +++ b/substrate/frame/support/src/storage/generator/map.rs @@ -21,7 +21,6 @@ use crate::{ Never, }; use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode}; -use sp_std::borrow::Borrow; #[cfg(not(feature = "std"))] use sp_std::prelude::*; @@ -297,7 +296,7 @@ impl> storage::StorageMap let ret = f(&mut val); if ret.is_ok() { match G::from_query_to_optional_value(val) { - Some(ref val) => unhashed::put(final_key.as_ref(), &val.borrow()), + Some(ref val) => unhashed::put(final_key.as_ref(), &val), None => unhashed::kill(final_key.as_ref()), } } @@ -314,7 +313,7 @@ impl> storage::StorageMap let ret = f(&mut val); if ret.is_ok() { match val { - Some(ref val) => unhashed::put(final_key.as_ref(), &val.borrow()), + Some(ref val) => unhashed::put(final_key.as_ref(), &val), None => unhashed::kill(final_key.as_ref()), } } From c29202143f5bcbbdc535eb6e9b6e6e59a9d4b011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 5 Sep 2023 13:24:19 +0200 Subject: [PATCH 029/103] Remove dynamic dispatch using `Ext` (#1399) --- substrate/frame/contracts/src/exec.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs index 894667280b71..fdb30310ef70 100644 --- a/substrate/frame/contracts/src/exec.rs +++ b/substrate/frame/contracts/src/exec.rs @@ -1625,13 +1625,13 @@ mod tests { } struct MockCtx<'a> { - ext: &'a mut dyn Ext, + ext: &'a mut MockStack<'a>, input_data: Vec, } #[derive(Clone)] struct MockExecutable { - func: Rc ExecResult + 'static>, + func: Rc Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>, func_type: ExportedFunction, code_hash: CodeHash, code_info: CodeInfo, @@ -1724,6 +1724,16 @@ mod tests { if let &Constructor = function { Self::increment_refcount(self.code_hash).unwrap(); } + // # Safety + // + // We know that we **always** call execute with a `MockStack` in this test. + // + // # Note + // + // The transmute is necessary because `execute` has to be generic over all + // `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would + // constitute a cycle. + let ext = unsafe { std::mem::transmute(ext) }; if function == &self.func_type { (self.func)(MockCtx { ext, input_data }, &self) } else { From d12936329cd7e5cb1af4b97bbaa70ce992b2c3c0 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 5 Sep 2023 18:56:32 -0300 Subject: [PATCH 030/103] Enforce a decoding limit in MultiAssets (#1395) * Enforce a decoding limit in MultiAssets * ".git/.scripts/commands/fmt/fmt.sh" * Update polkadot/xcm/src/v3/multiasset.rs Co-authored-by: Keith Yeung * Just use a BoundedVec * Conflicts --------- Co-authored-by: command-bot <> Co-authored-by: Keith Yeung --- polkadot/xcm/src/v3/multiasset.rs | 38 +++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs index 1668d1b870dc..a5a74368289d 100644 --- a/polkadot/xcm/src/v3/multiasset.rs +++ b/polkadot/xcm/src/v3/multiasset.rs @@ -40,6 +40,7 @@ use core::{ }; use parity_scale_codec::{self as codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; +use bounded_collections::{BoundedVec, ConstU32}; /// A general identifier for an instance of a non-fungible asset class. #[derive( @@ -506,9 +507,8 @@ impl TryFrom for MultiAsset { #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct MultiAssets(Vec); -/// Maximum number of items we expect in a single `MultiAssets` value. Note this is not (yet) -/// enforced, and just serves to provide a sensible `max_encoded_len` for `MultiAssets`. -const MAX_ITEMS_IN_MULTIASSETS: usize = 20; +/// Maximum number of items in a single `MultiAssets` value that can be decoded. +pub const MAX_ITEMS_IN_MULTIASSETS: usize = 20; impl MaxEncodedLen for MultiAssets { fn max_encoded_len() -> usize { @@ -517,8 +517,9 @@ impl MaxEncodedLen for MultiAssets { } impl Decode for MultiAssets { - fn decode(input: &mut I) -> Result { - Self::from_sorted_and_deduplicated(Vec::::decode(input)?) + fn decode(input: &mut I) -> Result { + let bounded_instructions = BoundedVec::>::decode(input)?; + Self::from_sorted_and_deduplicated(bounded_instructions.into_inner()) .map_err(|()| "Out of order".into()) } } @@ -974,4 +975,31 @@ mod tests { let r = MultiAssets::from_sorted_and_deduplicated(mixed_bad); assert!(r.is_err()); } + + #[test] + fn decoding_respects_limit() { + use super::*; + + // Having lots of one asset will work since they are deduplicated + let lots_of_one_asset: MultiAssets = + vec![(GeneralIndex(1), 1u128).into(); MAX_ITEMS_IN_MULTIASSETS + 1].into(); + let encoded = lots_of_one_asset.encode(); + assert!(MultiAssets::decode(&mut &encoded[..]).is_ok()); + + // Fewer assets than the limit works + let mut few_assets: MultiAssets = Vec::new().into(); + for i in 0..MAX_ITEMS_IN_MULTIASSETS { + few_assets.push((GeneralIndex(i as u128), 1u128).into()); + } + let encoded = few_assets.encode(); + assert!(MultiAssets::decode(&mut &encoded[..]).is_ok()); + + // Having lots of different assets will not work + let mut too_many_different_assets: MultiAssets = Vec::new().into(); + for i in 0..MAX_ITEMS_IN_MULTIASSETS + 1 { + too_many_different_assets.push((GeneralIndex(i as u128), 1u128).into()); + } + let encoded = too_many_different_assets.encode(); + assert!(MultiAssets::decode(&mut &encoded[..]).is_err()); + } } From 3e4576f752daa14a5f8e762c76d3e57e648ad105 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Wed, 6 Sep 2023 10:12:55 +0200 Subject: [PATCH 031/103] fmt fixes (#1413) --- polkadot/xcm/src/v3/multiasset.rs | 5 +++-- substrate/frame/broker/src/dispatchable_impls.rs | 8 ++------ substrate/frame/broker/src/tick_impls.rs | 8 ++------ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs index a5a74368289d..188555318c8c 100644 --- a/polkadot/xcm/src/v3/multiasset.rs +++ b/polkadot/xcm/src/v3/multiasset.rs @@ -34,13 +34,13 @@ use crate::v2::{ WildMultiAsset as OldWildMultiAsset, }; use alloc::{vec, vec::Vec}; +use bounded_collections::{BoundedVec, ConstU32}; use core::{ cmp::Ordering, convert::{TryFrom, TryInto}, }; use parity_scale_codec::{self as codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use bounded_collections::{BoundedVec, ConstU32}; /// A general identifier for an instance of a non-fungible asset class. #[derive( @@ -518,7 +518,8 @@ impl MaxEncodedLen for MultiAssets { impl Decode for MultiAssets { fn decode(input: &mut I) -> Result { - let bounded_instructions = BoundedVec::>::decode(input)?; + let bounded_instructions = + BoundedVec::>::decode(input)?; Self::from_sorted_and_deduplicated(bounded_instructions.into_inner()) .map_err(|()| "Out of order".into()) } diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs index 8dc0c9de393e..54cf5d71dcad 100644 --- a/substrate/frame/broker/src/dispatchable_impls.rs +++ b/substrate/frame/broker/src/dispatchable_impls.rs @@ -333,12 +333,8 @@ impl Pallet { region.begin = r + 1; contribution.length.saturating_dec(); - let Some(mut pool_record) = InstaPoolHistory::::get(r) else { - continue - }; - let Some(total_payout) = pool_record.maybe_payout else { - break - }; + let Some(mut pool_record) = InstaPoolHistory::::get(r) else { continue }; + let Some(total_payout) = pool_record.maybe_payout else { break }; let p = total_payout .saturating_mul(contributed_parts.into()) .checked_div(&pool_record.private_contributions.into()) diff --git a/substrate/frame/broker/src/tick_impls.rs b/substrate/frame/broker/src/tick_impls.rs index 909af6caf734..a1a50a61908d 100644 --- a/substrate/frame/broker/src/tick_impls.rs +++ b/substrate/frame/broker/src/tick_impls.rs @@ -95,9 +95,7 @@ impl Pallet { } pub(crate) fn process_revenue() -> bool { - let Some((until, amount)) = T::Coretime::check_notify_revenue_info() else { - return false - }; + let Some((until, amount)) = T::Coretime::check_notify_revenue_info() else { return false }; let when: Timeslice = (until / T::TimeslicePeriod::get()).saturating_sub(One::one()).saturated_into(); let mut revenue = T::ConvertBalance::convert_back(amount); @@ -289,9 +287,7 @@ impl Pallet { rc_begin: RelayBlockNumberOf, core: CoreIndex, ) { - let Some(workplan) = Workplan::::take((timeslice, core)) else { - return - }; + let Some(workplan) = Workplan::::take((timeslice, core)) else { return }; let workload = Workload::::get(core); let parts_used = workplan.iter().map(|i| i.mask).fold(CoreMask::void(), |a, i| a | i); let mut workplan = workplan.into_inner(); From 37161ee5507fe95275b660cecaf921d3f7fe5328 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Wed, 6 Sep 2023 10:25:47 +0200 Subject: [PATCH 032/103] Add PRdoc check (#1408) * Add test prdoc * Prepare for the check * Escape PR number * Fix conditional step * Add checkout and actual check * Cleanup * Minor fixes * Add doumentation * Add more doc --- .github/workflows/check-prdoc.yml | 51 ++++++++++++++++++++++++++ cumulus/scripts/ci/changelog/README.md | 2 +- docs/CONTRIBUTING.md | 32 ++++++++++++---- prdoc/.gitkeep | 0 prdoc/pr_1408_prodc-introduction.prdoc | 19 ++++++++++ 5 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/check-prdoc.yml create mode 100644 prdoc/.gitkeep create mode 100644 prdoc/pr_1408_prodc-introduction.prdoc diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml new file mode 100644 index 000000000000..e677ded8d6cc --- /dev/null +++ b/.github/workflows/check-prdoc.yml @@ -0,0 +1,51 @@ +name: Check PRdoc + +on: + pull_request: + types: [labeled, opened, synchronize, unlabeled] + +env: + # todo: switch to paritytech/prdoc once the container is built & published + # see https://github.com/paritytech/scripts/pull/595 + IMAGE: chevdor/prdoc:v0.0.4 + API_BASE: https://api.github.com/repos + REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR: ${{ github.event.pull_request.number }} + MOUNT: /prdoc + ENGINE: docker + +jobs: + check-prdoc: + runs-on: ubuntu-latest + steps: + - name: Pull image + run: | + echo "Pulling $IMAGE" + docker pull $IMAGE + docker run --rm $IMAGE --version + + - name: Check if PRdoc is required + id: get-labels + run: | + # Fetch the labels for the PR under test + echo "Fetch the labels for $API_BASE/${REPO}/pulls/${GITHUB_PR}" + labels=$( curl -H "Authorization: token ${GITHUB_TOKEN}" -s "$API_BASE/${REPO}/pulls/${GITHUB_PR}" | jq '.labels | .[] | .name' | tr "\n" ",") + echo "Labels: ${labels}" + echo "labels=${labels}" >> "$GITHUB_OUTPUT" + + - name: No PRdoc required + if: ${{ contains(steps.get-labels.outputs.labels, 'R0') }} + run: | + echo "PR detected as silent, no PRdoc is required, exiting..." + exit 0 + + - name: Checkout repo + if: ${{ !contains(steps.get-labels.outputs.labels, 'R0') }} + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac #v4.0.0 + + - name: PRdoc check for PR#${{ github.event.pull_request.number }} + if: ${{ !contains(steps.get-labels.outputs.labels, 'R0') }} + run: | + echo "Checking for PR#$GITHUB_PR in $MOUNT" + $ENGINE run --rm -v $PWD/prdoc:/doc $IMAGE check -n 1408 diff --git a/cumulus/scripts/ci/changelog/README.md b/cumulus/scripts/ci/changelog/README.md index e274b4919473..5c8ee9c9b914 100644 --- a/cumulus/scripts/ci/changelog/README.md +++ b/cumulus/scripts/ci/changelog/README.md @@ -61,7 +61,7 @@ all the labels that are used, search for `meta` in the templates. Currently, the Note that labels with the same letter are mutually exclusive. A PR should not have both `B0` and `B5`, or both `C1` and `C9`. In case of conflicts, the template will decide which label will be considered. -## Dev and debuggin +## Dev and debugging ### Hot Reload diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 20fa1d3a768b..d134188e25df 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -80,18 +80,36 @@ Reviews should finish with approval unless there are issues that would result in The reviewers are also responsible to check: -a) if a changelog is necessary and attached - -b) the quality of information in the changelog file - -c) the PR has an impact on docs - -d) that the docs team was included in the review process of a docs update +1. if a changelog is necessary and attached +1. the quality of information in the changelog file +1. the PR has an impact on docs +1. that the docs team was included in the review process of a docs update **Reviews may not be used as an effective veto for a PR because**: 1. There exists a somewhat cleaner/better/faster way of accomplishing the same feature/fix. 2. It does not fit well with some other contributors' longer-term vision for the project. +## Documentation + +All Pull Requests must contain proper title & description. + +Some Pull Requests can be exempt of `prdoc` documentation, those +must be labelled with +[`R0-silent`](https://github.com/paritytech/labels/blob/main/ruled_labels/specs_polkadot-sdk.yaml#L89-L91). + +Non "silent" PRs must come with documentation in the form of a `.prdoc` file. +A `.prdoc` documentation is made of a text file (YAML) named `/prdoc/pr_NNNN.prdoc` where `NNNN` is the PR number. +For convenience, those file can also contain a short description/title: `/prdoc/pr_NNNN_pr-foobar.prdoc`. + +The CI automation checks for the presence and validity of a `prdoc` in the `/prdoc` folder. +Those files need to comply with a specific [schema](https://github.com/paritytech/prdoc/blob/master/schema_user.json). It +is highly recommended to [make your editor aware](https://github.com/paritytech/prdoc#schemas) of the schema as it is +self-described and will assist you in writing correct content. + +This schema is also embedded in the +[prdoc](https://github.com/paritytech/prdoc) utility that can also be used to generate and check the validity of a +`prdoc` locally. + ## Helping out We use [labels](https://github.com/paritytech/polkadot-sdk/labels) to manage PRs and issues and communicate diff --git a/prdoc/.gitkeep b/prdoc/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/prdoc/pr_1408_prodc-introduction.prdoc b/prdoc/pr_1408_prodc-introduction.prdoc new file mode 100644 index 000000000000..4b10e0fe2e81 --- /dev/null +++ b/prdoc/pr_1408_prodc-introduction.prdoc @@ -0,0 +1,19 @@ +# This PR does not need a prdoc but it is provided in order to test +title: PRdoc check + +doc: + - audience: Core Dev + description: | + This PRdoc is an **example**. + + This PR brings support and automated checks for documentation in the form of a + [`prdoc`](https://github.com/paritytech/prdoc/) file. + +migrations: + db: [] + + runtime: [] + +crates: [] + +host_functions: [] From a27e24e86b7e30b079d18df7e87efc8268f5b507 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 6 Sep 2023 21:09:07 +1200 Subject: [PATCH 033/103] RFC 14: Improve locking mechanism for parachains (#1290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rfc14 * Update polkadot/runtime/common/src/paras_registrar/mod.rs Co-authored-by: Bastian Köcher * Update polkadot/runtime/common/src/paras_registrar/mod.rs Co-authored-by: Bastian Köcher * Update polkadot/runtime/common/src/paras_registrar/mod.rs Co-authored-by: Bastian Köcher * fmt * fix * Update polkadot/runtime/common/src/paras_registrar/migration.rs Co-authored-by: Oliver Tale-Yazdi * fmt * 2224 is unlocked * update migration list * update comment * use VersionedMigration --------- Co-authored-by: Bastian Köcher Co-authored-by: Oliver Tale-Yazdi --- Cargo.lock | 1 + .../runtime/common/src/assigned_slots/mod.rs | 1 + polkadot/runtime/common/src/crowdloan/mod.rs | 2 - .../runtime/common/src/integration_tests.rs | 1 + .../common/src/paras_registrar/migration.rs | 71 +++++++++++++++++++ .../mod.rs} | 61 ++++++++++++---- polkadot/runtime/kusama/Cargo.toml | 2 +- polkadot/runtime/kusama/src/lib.rs | 16 +++++ polkadot/runtime/parachains/Cargo.toml | 1 + polkadot/runtime/parachains/src/mock.rs | 1 + polkadot/runtime/parachains/src/paras/mod.rs | 27 ++++++- polkadot/runtime/polkadot/Cargo.toml | 2 +- polkadot/runtime/polkadot/src/lib.rs | 20 +++++- polkadot/runtime/rococo/Cargo.toml | 2 +- polkadot/runtime/rococo/src/lib.rs | 2 + polkadot/runtime/test-runtime/src/lib.rs | 1 + polkadot/runtime/westend/Cargo.toml | 2 +- polkadot/runtime/westend/src/lib.rs | 2 + 18 files changed, 191 insertions(+), 24 deletions(-) create mode 100644 polkadot/runtime/common/src/paras_registrar/migration.rs rename polkadot/runtime/common/src/{paras_registrar.rs => paras_registrar/mod.rs} (97%) diff --git a/Cargo.lock b/Cargo.lock index c254302517f0..918426ce5c0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12780,6 +12780,7 @@ dependencies = [ "frame-system", "futures", "hex-literal 0.4.1", + "impl-trait-for-tuples", "log", "pallet-authority-discovery", "pallet-authorship", diff --git a/polkadot/runtime/common/src/assigned_slots/mod.rs b/polkadot/runtime/common/src/assigned_slots/mod.rs index 3683cfc210fa..cc8ec339c118 100644 --- a/polkadot/runtime/common/src/assigned_slots/mod.rs +++ b/polkadot/runtime/common/src/assigned_slots/mod.rs @@ -739,6 +739,7 @@ mod tests { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = (); type NextSessionRotation = crate::mock::TestNextSessionRotation; + type OnNewHead = (); } impl parachains_shared::Config for Test {} diff --git a/polkadot/runtime/common/src/crowdloan/mod.rs b/polkadot/runtime/common/src/crowdloan/mod.rs index 0303808e0747..5a2939145925 100644 --- a/polkadot/runtime/common/src/crowdloan/mod.rs +++ b/polkadot/runtime/common/src/crowdloan/mod.rs @@ -441,8 +441,6 @@ pub mod pallet { ); NextFundIndex::::put(new_fund_index); - // Add a lock to the para so that the configuration cannot be changed. - T::Registrar::apply_lock(index); Self::deposit_event(Event::::Created { para_id: index }); Ok(()) diff --git a/polkadot/runtime/common/src/integration_tests.rs b/polkadot/runtime/common/src/integration_tests.rs index f78347dedd8c..f14db68267d5 100644 --- a/polkadot/runtime/common/src/integration_tests.rs +++ b/polkadot/runtime/common/src/integration_tests.rs @@ -204,6 +204,7 @@ impl paras::Config for Test { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = (); type NextSessionRotation = crate::mock::TestNextSessionRotation; + type OnNewHead = (); } parameter_types! { diff --git a/polkadot/runtime/common/src/paras_registrar/migration.rs b/polkadot/runtime/common/src/paras_registrar/migration.rs new file mode 100644 index 000000000000..7d3dda54e0ed --- /dev/null +++ b/polkadot/runtime/common/src/paras_registrar/migration.rs @@ -0,0 +1,71 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use super::*; +use frame_support::traits::{Contains, OnRuntimeUpgrade}; + +#[derive(Encode, Decode)] +pub struct ParaInfoV1 { + manager: Account, + deposit: Balance, + locked: bool, +} + +pub struct VersionUncheckedMigrateToV1( + sp_std::marker::PhantomData<(T, UnlockParaIds)>, +); +impl> OnRuntimeUpgrade + for VersionUncheckedMigrateToV1 +{ + fn on_runtime_upgrade() -> Weight { + let mut count = 0u64; + Paras::::translate::>, _>(|key, v1| { + count.saturating_inc(); + Some(ParaInfo { + manager: v1.manager, + deposit: v1.deposit, + locked: if UnlockParaIds::contains(&key) { None } else { Some(v1.locked) }, + }) + }); + + log::info!(target: "runtime::registrar", "Upgraded {} storages to version 1", count); + T::DbWeight::get().reads_writes(count, count) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + Ok((Paras::::iter_keys().count() as u32).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + let old_count = u32::decode(&mut &state[..]).expect("Known good"); + let new_count = Paras::::iter_values().count() as u32; + + ensure!(old_count == new_count, "Paras count should not change"); + Ok(()) + } +} + +#[cfg(feature = "experimental")] +pub type VersionCheckedMigrateToV1 = + frame_support::migrations::VersionedMigration< + 0, + 1, + VersionUncheckedMigrateToV1, + super::Pallet, + ::DbWeight, + >; diff --git a/polkadot/runtime/common/src/paras_registrar.rs b/polkadot/runtime/common/src/paras_registrar/mod.rs similarity index 97% rename from polkadot/runtime/common/src/paras_registrar.rs rename to polkadot/runtime/common/src/paras_registrar/mod.rs index 3f5a8e1a5f93..f2751803a413 100644 --- a/polkadot/runtime/common/src/paras_registrar.rs +++ b/polkadot/runtime/common/src/paras_registrar/mod.rs @@ -17,6 +17,8 @@ //! Pallet to handle parachain registration and related fund management. //! In essence this is a simple wrapper around `paras`. +pub mod migration; + use frame_support::{ dispatch::DispatchResult, ensure, @@ -35,7 +37,7 @@ use sp_std::{prelude::*, result}; use crate::traits::{OnSwap, Registrar}; pub use pallet::*; use parity_scale_codec::{Decode, Encode}; -use runtime_parachains::paras::ParaKind; +use runtime_parachains::paras::{OnNewHead, ParaKind}; use scale_info::TypeInfo; use sp_runtime::{ traits::{CheckedSub, Saturating}, @@ -49,7 +51,15 @@ pub struct ParaInfo { /// The amount reserved by the `manager` account for the registration. deposit: Balance, /// Whether the para registration should be locked from being controlled by the manager. - locked: bool, + /// None means the lock had not been explicitly set, and should be treated as false. + locked: Option, +} + +impl ParaInfo { + /// Returns if the para is locked. + pub fn is_locked(&self) -> bool { + self.locked.unwrap_or(false) + } } type BalanceOf = @@ -96,8 +106,12 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + #[pallet::pallet] #[pallet::without_storage_info] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); #[pallet::config] @@ -446,12 +460,12 @@ impl Registrar for Pallet { // Apply a lock to the parachain. fn apply_lock(id: ParaId) { - Paras::::mutate(id, |x| x.as_mut().map(|info| info.locked = true)); + Paras::::mutate(id, |x| x.as_mut().map(|info| info.locked = Some(true))); } // Remove a lock from the parachain. fn remove_lock(id: ParaId) { - Paras::::mutate(id, |x| x.as_mut().map(|info| info.locked = false)); + Paras::::mutate(id, |x| x.as_mut().map(|info| info.locked = Some(false))); } // Register a Para ID under control of `manager`. @@ -481,9 +495,7 @@ impl Registrar for Pallet { ); runtime_parachains::schedule_parathread_upgrade::(id) .map_err(|_| Error::::CannotUpgrade)?; - // Once a para has upgraded to a parachain, it can no longer be managed by the owner. - // Intentionally, the flag stays with the para even after downgrade. - Self::apply_lock(id); + Ok(()) } @@ -533,7 +545,7 @@ impl Pallet { .map_err(|e| e.into()) .and_then(|who| -> DispatchResult { let para_info = Paras::::get(id).ok_or(Error::::NotRegistered)?; - ensure!(!para_info.locked, Error::::ParaLocked); + ensure!(!para_info.is_locked(), Error::::ParaLocked); ensure!(para_info.manager == who, Error::::NotOwner); Ok(()) }) @@ -566,7 +578,7 @@ impl Pallet { let deposit = deposit_override.unwrap_or_else(T::ParaDeposit::get); ::Currency::reserve(&who, deposit)?; - let info = ParaInfo { manager: who.clone(), deposit, locked: false }; + let info = ParaInfo { manager: who.clone(), deposit, locked: None }; Paras::::insert(id, info); Self::deposit_event(Event::::Reserved { para_id: id, who }); @@ -585,7 +597,7 @@ impl Pallet { ) -> DispatchResult { let deposited = if let Some(para_data) = Paras::::get(id) { ensure!(para_data.manager == who, Error::::NotOwner); - ensure!(!para_data.locked, Error::::ParaLocked); + ensure!(!para_data.is_locked(), Error::::ParaLocked); para_data.deposit } else { ensure!(!ensure_reserved, Error::::NotReserved); @@ -601,7 +613,7 @@ impl Pallet { } else if let Some(rebate) = deposited.checked_sub(&deposit) { ::Currency::unreserve(&who, rebate); }; - let info = ParaInfo { manager: who.clone(), deposit, locked: false }; + let info = ParaInfo { manager: who.clone(), deposit, locked: None }; Paras::::insert(id, info); // We check above that para has no lifecycle, so this should not fail. @@ -665,6 +677,21 @@ impl Pallet { } } +impl OnNewHead for Pallet { + fn on_new_head(id: ParaId, _head: &HeadData) -> Weight { + // mark the parachain locked if the locked value is not already set + let mut writes = 0; + if let Some(mut info) = Paras::::get(id) { + if info.locked.is_none() { + info.locked = Some(true); + Paras::::insert(id, info); + writes += 1; + } + } + T::DbWeight::get().reads_writes(1, writes) + } +} + #[cfg(test)] mod tests { use super::*; @@ -784,6 +811,7 @@ mod tests { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = (); type NextSessionRotation = crate::mock::TestNextSessionRotation; + type OnNewHead = (); } impl configuration::Config for Test { @@ -1270,8 +1298,10 @@ mod tests { )); assert_noop!(Registrar::add_lock(RuntimeOrigin::signed(2), para_id), BadOrigin); - // Once they begin onboarding, we lock them in. - assert_ok!(Registrar::add_lock(RuntimeOrigin::signed(1), para_id)); + + // Once they produces new block, we lock them in. + Registrar::on_new_head(para_id, &Default::default()); + // Owner cannot pass origin check when checking lock assert_noop!( Registrar::ensure_root_para_or_owner(RuntimeOrigin::signed(1), para_id), @@ -1283,6 +1313,11 @@ mod tests { assert_ok!(Registrar::remove_lock(para_origin(para_id), para_id)); // Owner can pass origin check again assert_ok!(Registrar::ensure_root_para_or_owner(RuntimeOrigin::signed(1), para_id)); + + // Won't lock again after it is unlocked + Registrar::on_new_head(para_id, &Default::default()); + + assert_ok!(Registrar::ensure_root_para_or_owner(RuntimeOrigin::signed(1), para_id)); }); } diff --git a/polkadot/runtime/kusama/Cargo.toml b/polkadot/runtime/kusama/Cargo.toml index 8b0f59516c6d..6b0370633f0b 100644 --- a/polkadot/runtime/kusama/Cargo.toml +++ b/polkadot/runtime/kusama/Cargo.toml @@ -103,7 +103,7 @@ frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarki pallet-election-provider-support-benchmarking = { path = "../../../substrate/frame/election-provider-support/benchmarking", default-features = false, optional = true } hex-literal = "0.4.1" -runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } +runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false, features = ["experimental"] } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index 94af807fb5de..659a7052d2b7 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -1215,6 +1215,7 @@ impl parachains_paras::Config for Runtime { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = ParaInclusion; type NextSessionRotation = Babe; + type OnNewHead = Registrar; } parameter_types! { @@ -1710,6 +1711,19 @@ pub mod migrations { } } + pub struct ParachainsToUnlock; + impl Contains for ParachainsToUnlock { + fn contains(id: &ParaId) -> bool { + let id: u32 = (*id).into(); + // ksuama parachains/parathreads that are locked and never produced block + match id { + 2003 | 2008 | 2018 | 2077 | 2089 | 2111 | 2112 | 2120 | 2126 | 2127 | 2130 | + 2226 | 2227 | 2231 | 2233 | 2237 | 2256 | 2257 | 2261 | 2268 | 2275 => true, + _ => false, + } + } + } + /// Unreleased migrations. Add new ones here: pub type Unreleased = ( init_state_migration::InitMigrate, @@ -1741,6 +1755,8 @@ pub mod migrations { UpgradeSessionKeys, parachains_configuration::migration::v9::MigrateToV9, + // Migrate parachain info format + paras_registrar::migration::VersionCheckedMigrateToV1, ); } diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 9a8bd5017e07..0e2f6aa1aa24 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -6,6 +6,7 @@ edition.workspace = true license.workspace = true [dependencies] +impl-trait-for-tuples = "0.2.2" bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } log = { version = "0.4.17", default-features = false } diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs index f978b6c3360e..ded7de08e4fa 100644 --- a/polkadot/runtime/parachains/src/mock.rs +++ b/polkadot/runtime/parachains/src/mock.rs @@ -214,6 +214,7 @@ impl crate::paras::Config for Test { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = ParaInclusion; type NextSessionRotation = TestNextSessionRotation; + type OnNewHead = (); } impl crate::dmp::Config for Test {} diff --git a/polkadot/runtime/parachains/src/paras/mod.rs b/polkadot/runtime/parachains/src/paras/mod.rs index 95b89a1ca2c3..2f370b5bfe47 100644 --- a/polkadot/runtime/parachains/src/paras/mod.rs +++ b/polkadot/runtime/parachains/src/paras/mod.rs @@ -481,6 +481,22 @@ impl PvfCheckActiveVoteState { } } +/// Runtime hook for when a parachain head is updated. +pub trait OnNewHead { + /// Called when a parachain head is updated. + /// Returns the weight consumed by this function. + fn on_new_head(id: ParaId, head: &HeadData) -> Weight; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl OnNewHead for Tuple { + fn on_new_head(id: ParaId, head: &HeadData) -> Weight { + let mut weight: Weight = Default::default(); + for_tuples!( #( weight.saturating_accrue(Tuple::on_new_head(id, head)); )* ); + weight + } +} + pub trait WeightInfo { fn force_set_current_code(c: u32) -> Weight; fn force_set_current_head(s: u32) -> Weight; @@ -575,6 +591,9 @@ pub mod pallet { /// be set to the `ParaInclusion` pallet. type QueueFootprinter: QueueFootprinter; + /// Runtime hook for when a parachain head is updated. + type OnNewHead: OnNewHead; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -1962,10 +1981,10 @@ impl Pallet { new_head: HeadData, execution_context: BlockNumberFor, ) -> Weight { - Heads::::insert(&id, new_head); + Heads::::insert(&id, &new_head); MostRecentContext::::insert(&id, execution_context); - if let Some(expected_at) = FutureCodeUpgrades::::get(&id) { + let weight = if let Some(expected_at) = FutureCodeUpgrades::::get(&id) { if expected_at <= execution_context { FutureCodeUpgrades::::remove(&id); UpgradeGoAheadSignal::::remove(&id); @@ -2005,7 +2024,9 @@ impl Pallet { // the `Abort` signal. UpgradeGoAheadSignal::::remove(&id); T::DbWeight::get().reads_writes(1, 2) - } + }; + + weight.saturating_add(T::OnNewHead::on_new_head(id, &new_head)) } /// Returns the list of PVFs (aka validation code) that require casting a vote by a validator in diff --git a/polkadot/runtime/polkadot/Cargo.toml b/polkadot/runtime/polkadot/Cargo.toml index d185677ab8d2..0b9498347ca4 100644 --- a/polkadot/runtime/polkadot/Cargo.toml +++ b/polkadot/runtime/polkadot/Cargo.toml @@ -94,7 +94,7 @@ pallet-session-benchmarking = { path = "../../../substrate/frame/session/benchma pallet-nomination-pools-benchmarking = { path = "../../../substrate/frame/nomination-pools/benchmarking", default-features = false, optional = true } hex-literal = { version = "0.4.1", optional = true } -runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } +runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false, features = ["experimental"] } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index b71e0f726c55..45ea561b33fa 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -47,8 +47,8 @@ use frame_election_provider_support::{ use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU32, EitherOf, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem, PrivilegeCmp, - ProcessMessage, ProcessMessageError, WithdrawReasons, + ConstU32, Contains, EitherOf, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem, + PrivilegeCmp, ProcessMessage, ProcessMessageError, WithdrawReasons, }, weights::{ConstantMultiplier, WeightMeter}, PalletId, @@ -1091,6 +1091,7 @@ impl parachains_paras::Config for Runtime { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = ParaInclusion; type NextSessionRotation = Babe; + type OnNewHead = Registrar; } parameter_types! { @@ -1503,6 +1504,19 @@ pub mod migrations { type PalletName = TipsPalletName; } + pub struct ParachainsToUnlock; + impl Contains for ParachainsToUnlock { + fn contains(id: &ParaId) -> bool { + let id: u32 = (*id).into(); + // polkadot parachains/parathreads that are locked and never produced block + match id { + 2003 | 2015 | 2017 | 2018 | 2025 | 2028 | 2036 | 2038 | 2053 | 2055 | 2090 | + 2097 | 2106 | 3336 | 3338 | 3342 => true, + _ => false, + } + } + } + /// Unreleased migrations. Add new ones here: pub type Unreleased = ( pallet_im_online::migration::v1::Migration, @@ -1525,6 +1539,8 @@ pub mod migrations { frame_support::migrations::RemovePallet::DbWeight>, parachains_configuration::migration::v9::MigrateToV9, + // Migrate parachain info format + paras_registrar::migration::VersionCheckedMigrateToV1, ); } diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 6af9407a5879..a181250cfa37 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -84,7 +84,7 @@ frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-fea frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } hex-literal = { version = "0.4.1" } -runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false, features=["experimental"] } +runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false, features = ["experimental"] } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } polkadot-parachain-primitives = { path = "../../parachain", default-features = false } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index a80f45c340d9..e043852901f1 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1031,6 +1031,7 @@ impl parachains_paras::Config for Runtime { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = ParaInclusion; type NextSessionRotation = Babe; + type OnNewHead = Registrar; } parameter_types! { @@ -1550,6 +1551,7 @@ pub mod migrations { parachains_scheduler::migration::v1::MigrateToV1, parachains_configuration::migration::v8::MigrateToV8, parachains_configuration::migration::v9::MigrateToV9, + paras_registrar::migration::VersionCheckedMigrateToV1, ); } diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index b2397299430d..94852ad39f5a 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -540,6 +540,7 @@ impl parachains_paras::Config for Runtime { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = ParaInclusion; type NextSessionRotation = Babe; + type OnNewHead = (); } impl parachains_dmp::Config for Runtime {} diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index 5a47288297be..de561c8ac68b 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -95,7 +95,7 @@ pallet-offences-benchmarking = { path = "../../../substrate/frame/offences/bench pallet-session-benchmarking = { path = "../../../substrate/frame/session/benchmarking", default-features = false, optional = true } hex-literal = { version = "0.4.1", optional = true } -runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false, features=["experimental"] } +runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false, features = ["experimental"] } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } polkadot-parachain-primitives = { path = "../../parachain", default-features = false } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 73aa4980151e..7dfc781d2467 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1044,6 +1044,7 @@ impl parachains_paras::Config for Runtime { type UnsignedPriority = ParasUnsignedPriority; type QueueFootprinter = ParaInclusion; type NextSessionRotation = Babe; + type OnNewHead = (); } parameter_types! { @@ -1425,6 +1426,7 @@ pub mod migrations { parachains_configuration::migration::v8::MigrateToV8, UpgradeSessionKeys, parachains_configuration::migration::v9::MigrateToV9, + paras_registrar::migration::VersionCheckedMigrateToV1, ); } From 425a72d72079e36c59a356afbd8034ac6589f613 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:30:54 +0300 Subject: [PATCH 034/103] Bump enumn from 0.1.11 to 0.1.12 (#1412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [enumn](https://github.com/dtolnay/enumn) from 0.1.11 to 0.1.12. - [Release notes](https://github.com/dtolnay/enumn/releases) - [Commits](https://github.com/dtolnay/enumn/compare/0.1.11...0.1.12) --- updated-dependencies: - dependency-name: enumn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bastian Köcher --- Cargo.lock | 4 ++-- polkadot/runtime/common/slot_range_helper/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 918426ce5c0f..0d08c175bde5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4733,9 +4733,9 @@ dependencies = [ [[package]] name = "enumn" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" +checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", diff --git a/polkadot/runtime/common/slot_range_helper/Cargo.toml b/polkadot/runtime/common/slot_range_helper/Cargo.toml index 30d5dc84e9dc..f65717519d5e 100644 --- a/polkadot/runtime/common/slot_range_helper/Cargo.toml +++ b/polkadot/runtime/common/slot_range_helper/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true [dependencies] paste = "1.0" -enumn = "0.1.8" +enumn = "0.1.12" parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } sp-std = { package = "sp-std", path = "../../../../substrate/primitives/std", default-features = false } sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false } From 7520e043109ad007c0f4f13288319083d0790067 Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Wed, 6 Sep 2023 13:02:33 +0300 Subject: [PATCH 035/103] Fix the wasm runtime substitute caching bug (#1416) --- substrate/client/service/src/client/wasm_substitutes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/client/service/src/client/wasm_substitutes.rs b/substrate/client/service/src/client/wasm_substitutes.rs index a792ab87e771..70db0ef20f5a 100644 --- a/substrate/client/service/src/client/wasm_substitutes.rs +++ b/substrate/client/service/src/client/wasm_substitutes.rs @@ -126,7 +126,7 @@ where let runtime_code = RuntimeCode { code_fetcher: &WrappedRuntimeCode((&code).into()), heap_pages: None, - hash: Vec::new(), + hash: make_hash(&code), }; let version = Self::runtime_version(&executor, &runtime_code)?; let spec_version = version.spec_version; From a317ef94ca86cc85324145ac4b7db647e4069729 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Wed, 6 Sep 2023 13:58:53 +0200 Subject: [PATCH 036/103] Fix PRdoc check (#1419) --- .github/workflows/check-prdoc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml index e677ded8d6cc..219952fdbfba 100644 --- a/.github/workflows/check-prdoc.yml +++ b/.github/workflows/check-prdoc.yml @@ -47,5 +47,5 @@ jobs: - name: PRdoc check for PR#${{ github.event.pull_request.number }} if: ${{ !contains(steps.get-labels.outputs.labels, 'R0') }} run: | - echo "Checking for PR#$GITHUB_PR in $MOUNT" - $ENGINE run --rm -v $PWD/prdoc:/doc $IMAGE check -n 1408 + echo "Checking for PR#${GITHUB_PR} in $MOUNT" + $ENGINE run --rm -v $PWD/prdoc:/doc $IMAGE check -n ${GITHUB_PR} From c725bbe2cfa5bb5f2966eb60de069cc94f9fc1e6 Mon Sep 17 00:00:00 2001 From: Juan Date: Wed, 6 Sep 2023 15:06:47 +0200 Subject: [PATCH 037/103] Remove deprecated `pallet_balances`'s `set_balance_deprecated` and `transfer` dispatchables (#1226) * remove deprecated dispatchables * update test * update tests * update tests * add prdocs * add prdoc * Update docs/prdoc/pr_1226.prdoc Co-authored-by: Chevdor * move prdoc file --------- Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Keith Yeung Co-authored-by: Chevdor --- prdoc/pr_1226.prdoc | 17 +++++ substrate/frame/asset-conversion/src/tests.rs | 6 +- substrate/frame/balances/src/lib.rs | 63 ------------------- substrate/frame/safe-mode/src/mock.rs | 5 +- substrate/frame/safe-mode/src/tests.rs | 2 +- substrate/frame/tx-pause/src/mock.rs | 5 +- substrate/frame/tx-pause/src/tests.rs | 18 +++--- 7 files changed, 40 insertions(+), 76 deletions(-) create mode 100644 prdoc/pr_1226.prdoc diff --git a/prdoc/pr_1226.prdoc b/prdoc/pr_1226.prdoc new file mode 100644 index 000000000000..df7a425b5384 --- /dev/null +++ b/prdoc/pr_1226.prdoc @@ -0,0 +1,17 @@ +title: Removed deprecated `Balances::transfer` and `Balances::set_balance_deprecated` functions. + +doc: + - audience: Builder + description: The Balances pallet's dispatchables `set_balance_deprecated` and `transfer` were deprecated in [paritytech/substrate#12951](https://github.com/paritytech/substrate/pull/12951) and have now been removed. + notes: + - Use `set_balance_deprecated` instead `force_set_balance` and `transfer_allow_death` instead of `transfer`. + +migrations: + db: [] + + runtime: [] + +crates: + - name: pallet-balances + +host_functions: [] diff --git a/substrate/frame/asset-conversion/src/tests.rs b/substrate/frame/asset-conversion/src/tests.rs index 190e4fb62147..3af7500a6f30 100644 --- a/substrate/frame/asset-conversion/src/tests.rs +++ b/substrate/frame/asset-conversion/src/tests.rs @@ -1389,7 +1389,11 @@ fn cannot_block_pool_creation() { let pool_account = AssetConversion::get_pool_account(&AssetConversion::get_pool_id(token_2, token_1)); // And transfers the ED to that pool account - assert_ok!(Balances::transfer(RuntimeOrigin::signed(attacker), pool_account, ed)); + assert_ok!(Balances::transfer_allow_death( + RuntimeOrigin::signed(attacker), + pool_account, + ed + )); // Then, the attacker creates 14 tokens and sends one of each to the pool account for i in 10..25 { create_tokens(attacker, vec![NativeOrAssetId::Asset(i)]); diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs index f94b3230b917..5da6600d8796 100644 --- a/substrate/frame/balances/src/lib.rs +++ b/substrate/frame/balances/src/lib.rs @@ -563,53 +563,6 @@ pub mod pallet { Ok(()) } - /// Set the regular balance of a given account; it also takes a reserved balance but this - /// must be the same as the account's current reserved balance. - /// - /// The dispatch origin for this call is `root`. - /// - /// WARNING: This call is DEPRECATED! Use `force_set_balance` instead. - #[pallet::call_index(1)] - #[pallet::weight( - T::WeightInfo::force_set_balance_creating() // Creates a new account. - .max(T::WeightInfo::force_set_balance_killing()) // Kills an existing account. - )] - pub fn set_balance_deprecated( - origin: OriginFor, - who: AccountIdLookupOf, - #[pallet::compact] new_free: T::Balance, - #[pallet::compact] old_reserved: T::Balance, - ) -> DispatchResult { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - let existential_deposit = Self::ed(); - - let wipeout = new_free < existential_deposit; - let new_free = if wipeout { Zero::zero() } else { new_free }; - - // First we try to modify the account's balance to the forced balance. - let old_free = Self::try_mutate_account_handling_dust( - &who, - |account, _is_new| -> Result { - let old_free = account.free; - ensure!(account.reserved == old_reserved, TokenError::Unsupported); - account.free = new_free; - Ok(old_free) - }, - )?; - - // This will adjust the total issuance, which was not done by the `mutate_account` - // above. - if new_free > old_free { - mem::drop(PositiveImbalance::::new(new_free - old_free)); - } else if new_free < old_free { - mem::drop(NegativeImbalance::::new(old_free - new_free)); - } - - Self::deposit_event(Event::BalanceSet { who, free: new_free }); - Ok(()) - } - /// Exactly as `transfer_allow_death`, except the origin must be root and the source account /// may be specified. #[pallet::call_index(2)] @@ -730,22 +683,6 @@ pub mod pallet { } } - /// Alias for `transfer_allow_death`, provided only for name-wise compatibility. - /// - /// WARNING: DEPRECATED! Will be released in approximately 3 months. - #[pallet::call_index(7)] - #[pallet::weight(T::WeightInfo::transfer_allow_death())] - pub fn transfer( - origin: OriginFor, - dest: AccountIdLookupOf, - #[pallet::compact] value: T::Balance, - ) -> DispatchResult { - let source = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value, Expendable)?; - Ok(()) - } - /// Set the regular balance of a given account. /// /// The dispatch origin for this call is `root`. diff --git a/substrate/frame/safe-mode/src/mock.rs b/substrate/frame/safe-mode/src/mock.rs index 337b6076f84b..635ee0cfedc0 100644 --- a/substrate/frame/safe-mode/src/mock.rs +++ b/substrate/frame/safe-mode/src/mock.rs @@ -122,7 +122,10 @@ impl InstanceFilter for ProxyType { match self { ProxyType::Any => true, ProxyType::JustTransfer => { - matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) + matches!( + c, + RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) + ) }, ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), } diff --git a/substrate/frame/safe-mode/src/tests.rs b/substrate/frame/safe-mode/src/tests.rs index 1e2eb343aa2f..ca1d7eb1d934 100644 --- a/substrate/frame/safe-mode/src/tests.rs +++ b/substrate/frame/safe-mode/src/tests.rs @@ -605,7 +605,7 @@ fn fails_when_explicit_origin_required() { } fn call_transfer() -> RuntimeCall { - RuntimeCall::Balances(pallet_balances::Call::transfer { dest: 1, value: 1 }) + RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: 1, value: 1 }) } fn signed(who: u64) -> RuntimeOrigin { diff --git a/substrate/frame/tx-pause/src/mock.rs b/substrate/frame/tx-pause/src/mock.rs index 706b0a558ba7..60c5fc1eced5 100644 --- a/substrate/frame/tx-pause/src/mock.rs +++ b/substrate/frame/tx-pause/src/mock.rs @@ -120,7 +120,10 @@ impl InstanceFilter for ProxyType { match self { ProxyType::Any => true, ProxyType::JustTransfer => { - matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) + matches!( + c, + RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) + ) }, ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), } diff --git a/substrate/frame/tx-pause/src/tests.rs b/substrate/frame/tx-pause/src/tests.rs index 48b70f71ccb0..a71ff3439d90 100644 --- a/substrate/frame/tx-pause/src/tests.rs +++ b/substrate/frame/tx-pause/src/tests.rs @@ -32,7 +32,7 @@ fn can_pause_specific_call() { assert_ok!(TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer") + full_name::(b"Balances", b"transfer_allow_death") )); assert_err!( @@ -69,7 +69,7 @@ fn can_unpause_specific_call() { new_test_ext().execute_with(|| { assert_ok!(TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), )); assert_err!( call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), @@ -78,7 +78,7 @@ fn can_unpause_specific_call() { assert_ok!(TxPause::unpause( RuntimeOrigin::signed(mock::UnpauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), )); assert_ok!(call_transfer(4, 1).dispatch(RuntimeOrigin::signed(0))); }); @@ -92,7 +92,7 @@ fn can_filter_balance_in_batch_when_paused() { assert_ok!(TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), )); assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); @@ -111,7 +111,7 @@ fn can_filter_balance_in_proxy_when_paused() { new_test_ext().execute_with(|| { assert_ok!(TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), )); assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); @@ -152,7 +152,7 @@ fn fails_to_pause_unpausable_call_when_other_call_is_paused() { assert_ok!(TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), )); assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); @@ -181,13 +181,13 @@ fn fails_to_pause_already_paused_pallet() { new_test_ext().execute_with(|| { assert_ok!(TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), )); assert_noop!( TxPause::pause( RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", b"transfer"), + full_name::(b"Balances", b"transfer_allow_death"), ), Error::::IsPaused ); @@ -208,7 +208,7 @@ fn fails_to_unpause_not_paused_pallet() { } pub fn call_transfer(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(pallet_balances::Call::transfer { dest, value }) + RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest, value }) } pub fn call_transfer_keep_alive(dest: u64, value: u64) -> RuntimeCall { From 5e56b1acccd6c6fa321521a6a871bf808a47f75c Mon Sep 17 00:00:00 2001 From: Squirrel Date: Wed, 6 Sep 2023 15:00:53 +0100 Subject: [PATCH 038/103] pallet asset-conversion additional quote tests (#1371) * added identity quote test (only possible if fees are not included in quote) * add tests that compare quoted price to actual execution --- substrate/frame/asset-conversion/src/tests.rs | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) diff --git a/substrate/frame/asset-conversion/src/tests.rs b/substrate/frame/asset-conversion/src/tests.rs index 3af7500a6f30..1c1267ab87b3 100644 --- a/substrate/frame/asset-conversion/src/tests.rs +++ b/substrate/frame/asset-conversion/src/tests.rs @@ -569,6 +569,16 @@ fn can_quote_price() { ), Some(60) ); + // including fee so should get less out... + assert_eq!( + AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + 3000, + true, + ), + Some(46) + ); // Check it still gives same price: // (if the above accidentally exchanged then it would not give same quote as before) assert_eq!( @@ -580,6 +590,16 @@ fn can_quote_price() { ), Some(60) ); + // including fee so should get less out... + assert_eq!( + AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + 3000, + true, + ), + Some(46) + ); // Check inverse: assert_eq!( @@ -591,6 +611,247 @@ fn can_quote_price() { ), Some(3000) ); + // including fee so should get less out... + assert_eq!( + AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + 60, + true, + ), + Some(2302) + ); + + // + // same tests as above but for quote_price_tokens_for_exact_tokens: + // + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + 60, + false, + ), + Some(3000) + ); + // including fee so should need to put more in... + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + 60, + true, + ), + Some(4299) + ); + // Check it still gives same price: + // (if the above accidentally exchanged then it would not give same quote as before) + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + 60, + false, + ), + Some(3000) + ); + // including fee so should need to put more in... + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + 60, + true, + ), + Some(4299) + ); + + // Check inverse: + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + 3000, + false, + ), + Some(60) + ); + // including fee so should need to put more in... + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + 3000, + true, + ), + Some(86) + ); + + // + // roundtrip: Without fees one should get the original number + // + let amount_in = 100; + + assert_eq!( + AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + amount_in, + false, + ) + .and_then(|amount| AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + amount, + false, + )), + Some(amount_in) + ); + assert_eq!( + AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + amount_in, + false, + ) + .and_then(|amount| AssetConversion::quote_price_exact_tokens_for_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + amount, + false, + )), + Some(amount_in) + ); + + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + amount_in, + false, + ) + .and_then(|amount| AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + amount, + false, + )), + Some(amount_in) + ); + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Native, + NativeOrAssetId::Asset(2), + amount_in, + false, + ) + .and_then(|amount| AssetConversion::quote_price_tokens_for_exact_tokens( + NativeOrAssetId::Asset(2), + NativeOrAssetId::Native, + amount, + false, + )), + Some(amount_in) + ); + }); +} + +#[test] +fn quote_price_exact_tokens_for_tokens_matches_execution() { + new_test_ext().execute_with(|| { + let user = 1; + let user2 = 2; + let token_1 = NativeOrAssetId::Native; + let token_2 = NativeOrAssetId::Asset(2); + + create_tokens(user, vec![token_2]); + assert_ok!(AssetConversion::create_pool(RuntimeOrigin::signed(user), token_1, token_2)); + + assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), user, 100000)); + assert_ok!(Assets::mint(RuntimeOrigin::signed(user), 2, user, 1000)); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(user), + token_1, + token_2, + 10000, + 200, + 1, + 1, + user, + )); + + let amount = 1; + let quoted_price = 49; + assert_eq!( + AssetConversion::quote_price_exact_tokens_for_tokens(token_2, token_1, amount, true,), + Some(quoted_price) + ); + + assert_ok!(Assets::mint(RuntimeOrigin::signed(user), 2, user2, amount)); + let prior_dot_balance = 20000; + assert_eq!(prior_dot_balance, balance(user2, token_1)); + assert_ok!(AssetConversion::swap_exact_tokens_for_tokens( + RuntimeOrigin::signed(user2), + bvec![token_2, token_1], + amount, + 1, + user2, + false, + )); + + assert_eq!(prior_dot_balance + quoted_price, balance(user2, token_1)); + }); +} + +#[test] +fn quote_price_tokens_for_exact_tokens_matches_execution() { + new_test_ext().execute_with(|| { + let user = 1; + let user2 = 2; + let token_1 = NativeOrAssetId::Native; + let token_2 = NativeOrAssetId::Asset(2); + + create_tokens(user, vec![token_2]); + assert_ok!(AssetConversion::create_pool(RuntimeOrigin::signed(user), token_1, token_2)); + + assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), user, 100000)); + assert_ok!(Assets::mint(RuntimeOrigin::signed(user), 2, user, 1000)); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(user), + token_1, + token_2, + 10000, + 200, + 1, + 1, + user, + )); + + let amount = 49; + let quoted_price = 1; + assert_eq!( + AssetConversion::quote_price_tokens_for_exact_tokens(token_2, token_1, amount, true,), + Some(quoted_price) + ); + + assert_ok!(Assets::mint(RuntimeOrigin::signed(user), 2, user2, amount)); + let prior_dot_balance = 20000; + assert_eq!(prior_dot_balance, balance(user2, token_1)); + let prior_asset_balance = 49; + assert_eq!(prior_asset_balance, balance(user2, token_2)); + assert_ok!(AssetConversion::swap_tokens_for_exact_tokens( + RuntimeOrigin::signed(user2), + bvec![token_2, token_1], + amount, + 1, + user2, + false, + )); + + assert_eq!(prior_dot_balance + amount, balance(user2, token_1)); + assert_eq!(prior_asset_balance - quoted_price, balance(user2, token_2)); }); } From 1be427e0290fa078e9dca8926a6d05fd3c123eff Mon Sep 17 00:00:00 2001 From: Egor_P Date: Wed, 6 Sep 2023 16:11:10 +0200 Subject: [PATCH 039/103] GHW for building and publishing docker images (#1391) * add ghw and scripts for docker image deployment * debug * add permissions for content * fix path to the bin folder * add tags * rename env * fix path to docker file * make polkadot-parachain executable * fix typo * fix more typos * test * revert back use of working directory * mke bin executable in the artifacts folder * use cd instead of working directory * change path to cash * fix path to cash * change cache key * delete old flows * addressed PR comments * fix path * reorg docker files --- {.gitlab => .github/scripts}/common/lib.sh | 73 ++++++++- .../workflows/release-50_publish-docker.yml | 148 +++++++++--------- .gitlab/pipeline/build.yml | 2 +- .gitlab/pipeline/publish.yml | 18 +-- .gitlab/test_deterministic_wasm.sh | 2 +- cumulus/docker/parachain-registrar.dockerfile | 27 ---- ...rachain-debug_unsigned_injected.Dockerfile | 49 ------ .../polkadot-parachain_builder.Containerfile | 36 ----- .../docker/test-parachain-collator.dockerfile | 46 ------ .../docker/test-parachain_injected.Dockerfile | 49 ------ docker/docker-compose.yml | 129 --------------- docker/dockerfiles/binary_injected.Dockerfile | 48 ++++++ .../collator_injected.Dockerfile | 2 +- .../dockerfiles}/docker-compose.yml | 8 +- .../malus_injected.Dockerfile | 0 .../parachain-registrar.dockerfile | 2 +- ...rachain-debug_unsigned_injected.Dockerfile | 2 +- .../polkadot-parachain_builder.Containerfile | 4 +- .../polkadot-parachain_injected.Dockerfile | 10 +- docker/dockerfiles/polkadot/README.md | 9 ++ .../polkadot/docker-compose-local.yml | 50 ++++++ .../dockerfiles/polkadot/docker-compose.yml | 22 +++ .../polkadot/polkadot_Dockerfile.README.md | 7 + .../polkadot/polkadot_builder.Dockerfile | 36 +++++ .../polkadot_injected_debian.Dockerfile | 53 +++++++ .../polkadot_injected_debug.Dockerfile | 2 +- .../polkadot_injected_release.Dockerfile | 2 +- .../staking-miner_builder.Dockerfile | 0 .../staking-miner_injected.Dockerfile | 0 .../substrate_injected.Dockerfile | 0 .../test-parachain-collator.dockerfile | 2 +- .../test-parachain_injected.Dockerfile | 2 +- docker/injected.Dockerfile | 51 ------ .../scripts/adder-collator/build-injected.sh | 13 ++ docker/scripts/adder-collator/test-build.sh | 23 +++ docker/scripts/build-injected.sh | 100 ++++++++++++ docker/scripts/entrypoint.sh | 18 +++ docker/scripts/malus/build-injected.sh | 14 ++ docker/scripts/malus/test-build.sh | 19 +++ .../polkadot-parachain/build-injected.sh | 15 ++ .../scripts/polkadot-parachain/test-build.sh | 19 +++ ...polkadot-parachain_build-injected-image.sh | 2 +- docker/scripts/polkadot/build-injected.sh | 13 ++ docker/scripts/polkadot/test-build.sh | 18 +++ docker/scripts/staking-miner/README.md | 37 +++++ .../scripts/staking-miner/build-injected.sh | 13 ++ docker/scripts/staking-miner/build.sh | 13 ++ .../staking-miner_Dockerfile.README.md | 3 + .../staking-miner_builder.Dockerfile | 43 +++++ docker/scripts/staking-miner/test-build.sh | 18 +++ {cumulus/docs => docs}/container.md | 2 +- {polkadot/doc => docs}/docker.md | 2 +- .../workflows/release-40_publish-rc-image.yml | 132 ---------------- .../release-51_publish-docker-manual.yml | 51 ------ polkadot/utils/staking-miner/README.md | 2 +- 55 files changed, 784 insertions(+), 677 deletions(-) rename {.gitlab => .github/scripts}/common/lib.sh (76%) rename {cumulus/.github => .github}/workflows/release-50_publish-docker.yml (59%) delete mode 100644 cumulus/docker/parachain-registrar.dockerfile delete mode 100644 cumulus/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile delete mode 100644 cumulus/docker/polkadot-parachain_builder.Containerfile delete mode 100644 cumulus/docker/test-parachain-collator.dockerfile delete mode 100644 cumulus/docker/test-parachain_injected.Dockerfile delete mode 100644 docker/docker-compose.yml create mode 100644 docker/dockerfiles/binary_injected.Dockerfile rename docker/{ => dockerfiles}/collator_injected.Dockerfile (95%) rename {cumulus/docker => docker/dockerfiles}/docker-compose.yml (89%) rename docker/{ => dockerfiles}/malus_injected.Dockerfile (100%) rename docker/{ => dockerfiles}/parachain-registrar.dockerfile (89%) rename docker/{ => dockerfiles/polkadot-parachain}/polkadot-parachain-debug_unsigned_injected.Dockerfile (93%) rename docker/{ => dockerfiles/polkadot-parachain}/polkadot-parachain_builder.Containerfile (89%) rename cumulus/docker/injected.Dockerfile => docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile (68%) create mode 100644 docker/dockerfiles/polkadot/README.md create mode 100644 docker/dockerfiles/polkadot/docker-compose-local.yml create mode 100644 docker/dockerfiles/polkadot/docker-compose.yml create mode 100644 docker/dockerfiles/polkadot/polkadot_Dockerfile.README.md create mode 100644 docker/dockerfiles/polkadot/polkadot_builder.Dockerfile create mode 100644 docker/dockerfiles/polkadot/polkadot_injected_debian.Dockerfile rename docker/{ => dockerfiles/polkadot}/polkadot_injected_debug.Dockerfile (94%) rename docker/{ => dockerfiles/polkadot}/polkadot_injected_release.Dockerfile (95%) rename docker/{ => dockerfiles}/staking-miner/staking-miner_builder.Dockerfile (100%) rename docker/{ => dockerfiles}/staking-miner/staking-miner_injected.Dockerfile (100%) rename docker/{ => dockerfiles}/substrate_injected.Dockerfile (100%) rename docker/{ => dockerfiles}/test-parachain-collator.dockerfile (96%) rename docker/{ => dockerfiles}/test-parachain_injected.Dockerfile (95%) delete mode 100644 docker/injected.Dockerfile create mode 100755 docker/scripts/adder-collator/build-injected.sh create mode 100755 docker/scripts/adder-collator/test-build.sh create mode 100755 docker/scripts/build-injected.sh create mode 100755 docker/scripts/entrypoint.sh create mode 100755 docker/scripts/malus/build-injected.sh create mode 100755 docker/scripts/malus/test-build.sh create mode 100755 docker/scripts/polkadot-parachain/build-injected.sh create mode 100755 docker/scripts/polkadot-parachain/test-build.sh rename cumulus/docker/scripts/build-injected-image.sh => docker/scripts/polkadot-parachain_build-injected-image.sh (70%) create mode 100755 docker/scripts/polkadot/build-injected.sh create mode 100755 docker/scripts/polkadot/test-build.sh create mode 100644 docker/scripts/staking-miner/README.md create mode 100755 docker/scripts/staking-miner/build-injected.sh create mode 100755 docker/scripts/staking-miner/build.sh create mode 100644 docker/scripts/staking-miner/staking-miner_Dockerfile.README.md create mode 100644 docker/scripts/staking-miner/staking-miner_builder.Dockerfile create mode 100755 docker/scripts/staking-miner/test-build.sh rename {cumulus/docs => docs}/container.md (96%) rename {polkadot/doc => docs}/docker.md (98%) delete mode 100644 polkadot/.github/workflows/release-40_publish-rc-image.yml delete mode 100644 polkadot/.github/workflows/release-51_publish-docker-manual.yml diff --git a/.gitlab/common/lib.sh b/.github/scripts/common/lib.sh similarity index 76% rename from .gitlab/common/lib.sh rename to .github/scripts/common/lib.sh index ba5b17148728..b0f9cb32063a 100755 --- a/.gitlab/common/lib.sh +++ b/.github/scripts/common/lib.sh @@ -96,7 +96,7 @@ structure_message() { # access_token: see https://matrix.org/docs/guides/client-server-api/ # Usage: send_message $body (json formatted) $room_id $access_token send_message() { -curl -XPOST -d "$1" "https://matrix.parity.io/_matrix/client/r0/rooms/$2/send/m.room.message?access_token=$3" + curl -XPOST -d "$1" "https://m.parity.io/_matrix/client/r0/rooms/$2/send/m.room.message?access_token=$3" } # Pretty-printing functions @@ -193,3 +193,74 @@ check_bootnode(){ echo " Bootnode appears unreachable" return 1 } + +# Assumes the ENV are set: +# - RELEASE_ID +# - GITHUB_TOKEN +# - REPO in the form paritytech/polkadot +fetch_release_artifacts() { + echo "Release ID : $RELEASE_ID" + echo "Repo : $REPO" + echo "Binary : $BINARY" + + curl -L -s \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${REPO}/releases/${RELEASE_ID} > release.json + + # Get Asset ids + ids=($(jq -r '.assets[].id' < release.json )) + count=$(jq '.assets|length' < release.json ) + + # Fetch artifacts + mkdir -p "./release-artifacts/${BINARY}" + pushd "./release-artifacts/${BINARY}" > /dev/null + + iter=1 + for id in "${ids[@]}" + do + echo " - $iter/$count: downloading asset id: $id..." + curl -s -OJ -L -H "Accept: application/octet-stream" \ + -H "Authorization: Token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/${REPO}/releases/assets/$id" + iter=$((iter + 1)) + done + + pwd + ls -al --color + popd > /dev/null +} + +# Check the checksum for a given binary +function check_sha256() { + echo "Checking SHA256 for $1" + shasum -qc $1.sha256 +} + +# Import GPG keys of the release team members +# This is done in parallel as it can take a while sometimes +function import_gpg_keys() { + GPG_KEYSERVER=${GPG_KEYSERVER:-"keyserver.ubuntu.com"} + SEC="9D4B2B6EB8F97156D19669A9FF0812D491B96798" + WILL="2835EAF92072BC01D188AF2C4A092B93E97CE1E2" + EGOR="E6FC4D4782EB0FA64A4903CCDB7D3555DD3932D3" + MARA="533C920F40E73A21EEB7E9EBF27AEA7E7594C9CF" + MORGAN="2E92A9D8B15D7891363D1AE8AF9E6C43F7F8C4CF" + + echo "Importing GPG keys from $GPG_KEYSERVER in parallel" + for key in $SEC $WILL $EGOR $MARA $MORGAN; do + ( + echo "Importing GPG key $key" + gpg --no-tty --quiet --keyserver $GPG_KEYSERVER --recv-keys $key + echo -e "5\ny\n" | gpg --no-tty --command-fd 0 --expert --edit-key $key trust; + ) & + done + wait +} + +# Check the GPG signature for a given binary +function check_gpg() { + echo "Checking GPG Signature for $1" + gpg --no-tty --verify -q $1.asc $1 +} diff --git a/cumulus/.github/workflows/release-50_publish-docker.yml b/.github/workflows/release-50_publish-docker.yml similarity index 59% rename from cumulus/.github/workflows/release-50_publish-docker.yml rename to .github/workflows/release-50_publish-docker.yml index 6ad943c3903c..0e466f26891c 100644 --- a/cumulus/.github/workflows/release-50_publish-docker.yml +++ b/.github/workflows/release-50_publish-docker.yml @@ -7,9 +7,10 @@ name: Release - Publish Docker Image # image and publishes it. on: - release: - types: - - published + #TODO: activate automated run later + # release: + # types: + # - published workflow_dispatch: inputs: release_id: @@ -39,6 +40,18 @@ on: required: true type: string default: parity + binary: + description: Binary to be published + required: true + default: polkadot + type: choice + options: + - polkadot + - staking-miner + - polkadot-parachain + +permissions: + contents: write env: RELEASE_ID: ${{ inputs.release_id }} @@ -47,8 +60,8 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCKER_OWNER: ${{ inputs.owner || github.repository_owner }} REPO: ${{ github.repository }} - BINARY: polkadot-parachain - EVENT_ACTION: ${{ github.event.action }} + BINARY: ${{ inputs.binary }} + # EVENT_ACTION: ${{ github.event.action }} EVENT_NAME: ${{ github.event_name }} IMAGE_TYPE: ${{ inputs.image_type }} @@ -58,59 +71,36 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Prepare temp folder - run: | - TMP=$(mktemp -d) - echo "TMP=$TMP" >> "$GITHUB_ENV" - pwd - ls -al "$TMP" + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - - name: Fetch lib.sh from polkadot repo - working-directory: ${{ env.TMP }} - run: | - curl -O -L \ - -H "Accept: application/vnd.github.v3.raw" \ - https://raw.githubusercontent.com/paritytech/polkadot/master/scripts/ci/common/lib.sh - - chmod a+x lib.sh - ls -al - - - name: Fetch release artifacts based on final release tag + #TODO: this step will be needed when automated triggering will work #this step runs only if the workflow is triggered automatically when new release is published - if: ${{ env.EVENT_NAME == 'release' && env.EVENT_ACTION != '' && env.EVENT_ACTION == 'published' }} - run: | - mkdir -p release-artifacts && cd release-artifacts - - for f in $BINARY $BINARY.asc $BINARY.sha256; do - URL="https://github.com/${{ github.event.repository.full_name }}/releases/download/${{ github.event.release.tag_name }}/$f" - echo " - Fetching $f from $URL" - wget "$URL" -O "$f" - done - chmod a+x $BINARY - cp -f ${TMP}/lib.sh . - ls -al + # if: ${{ env.EVENT_NAME == 'release' && env.EVENT_ACTION != '' && env.EVENT_ACTION == 'published' }} + # run: | + # mkdir -p release-artifacts && cd release-artifacts + + # for f in $BINARY $BINARY.asc $BINARY.sha256; do + # URL="https://github.com/${{ github.event.repository.full_name }}/releases/download/${{ github.event.release.tag_name }}/$f" + # echo " - Fetching $f from $URL" + # wget "$URL" -O "$f" + # done + # chmod a+x $BINARY + # ls -al - name: Fetch rc artifacts or release artifacts based on release id #this step runs only if the workflow is triggered manually if: ${{ env.EVENT_NAME == 'workflow_dispatch' }} run: | - . ${TMP}/lib.sh + . ./.github/scripts/common/lib.sh fetch_release_artifacts - chmod a+x release-artifacts/$BINARY - ls -al - - cp -f ${TMP}/lib.sh release-artifacts/ - - name: Cache the artifacts uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: - key: artifacts-${{ github.sha }} + key: artifacts-${{ env.BINARY }}-${{ github.sha }} path: | - ./release-artifacts/**/* + ./release-artifacts/${{ env.BINARY }}/**/* build-container: runs-on: ubuntu-latest @@ -118,40 +108,31 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Get artifacts from cache uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: - key: artifacts-${{ github.sha }} + key: artifacts-${{ env.BINARY }}-${{ github.sha }} fail-on-cache-miss: true path: | - ./release-artifacts/**/* + ./release-artifacts/${{ env.BINARY }}/**/* - name: Check sha256 ${{ env.BINARY }} - working-directory: ./release-artifacts + working-directory: ./release-artifacts/${{ env.BINARY }} run: | - . ./lib.sh + . ../../.github/scripts/common/lib.sh echo "Checking binary $BINARY" check_sha256 $BINARY && echo "OK" || echo "ERR" - name: Check GPG ${{ env.BINARY }} - working-directory: ./release-artifacts + working-directory: ./release-artifacts/${{ env.BINARY }} run: | - . ./lib.sh + . ../../.github/scripts/common/lib.sh import_gpg_keys check_gpg $BINARY - - name: Build Injected Container image for ${{ env.BINARY }} - env: - IMAGE_NAME: ${{ env.BINARY }} - OWNER: ${{ env.DOCKER_OWNER }} - run: | - ls -al - echo "Building container for $BINARY" - ./docker/scripts/build-injected-image.sh - - name: Fetch rc commit and tag if: ${{ env.IMAGE_TYPE == 'rc' }} id: fetch_rc_refs @@ -167,14 +148,43 @@ jobs: echo "No tag, doing without" - name: Fetch release tags - if: ${{ env.IMAGE_TYPE == 'release' || env.EVENT_NAME == 'release' && env.EVENT_ACTION != '' && env.EVENT_ACTION == 'published' }} + working-directory: ./release-artifacts/${{ env.BINARY }} + if: ${{ env.IMAGE_TYPE == 'release'}} id: fetch_release_refs run: | - VERSION=$(docker run --pull never --rm $DOCKER_OWNER/$BINARY --version | awk '{ print $2 }' ) + chmod a+rx $BINARY + VERSION=$(./$BINARY --version | awk '{ print $2 }' ) release=$( echo $VERSION | cut -f1 -d- ) echo "tag=latest" >> $GITHUB_OUTPUT echo "release=${release}" >> $GITHUB_OUTPUT + - name: Build Injected Container image for polkadot/staking-miner + if: ${{ env.BINARY == 'polkadot' || env.BINARY == 'staking-miner' }} + env: + ARTIFACTS_FOLDER: ./release-artifacts + IMAGE_NAME: ${{ env.BINARY }} + OWNER: ${{ env.DOCKER_OWNER }} + TAGS: ${{ join(steps.fetch_rc_refs.outputs.*, ',') || join(steps.fetch_release_refs.outputs.*, ',') }} + run: | + ls -al + echo "Building container for $BINARY" + ./docker/scripts/build-injected.sh + + - name: Build Injected Container image for polkadot-parachain + if: ${{ env.BINARY == 'polkadot-parachain' }} + env: + ARTIFACTS_FOLDER: ./release-artifacts + IMAGE_NAME: ${{ env.BINARY }} + OWNER: ${{ env.DOCKER_OWNER }} + DOCKERFILE: docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile + TAGS: ${{ join(steps.fetch_rc_refs.outputs.*, ',') || join(steps.fetch_release_refs.outputs.*, ',') }} + run: | + ls -al + mkdir -p $ARTIFACTS_FOLDER/specs + cp cumulus/parachains/chain-specs/*.json $ARTIFACTS_FOLDER/specs + + echo "Building container for $BINARY" + ./docker/scripts/build-injected.sh - name: Login to Dockerhub uses: docker/login-action@v2 @@ -182,21 +192,11 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Tag and Push Container image for ${{ env.BINARY }} + - name: Push Container image for ${{ env.BINARY }} id: docker_push - env: - TAGS: ${{ join(steps.fetch_rc_refs.outputs.*, ',') || join(steps.fetch_release_refs.outputs.*, ',') }} run: | - TAGS=${TAGS[@]:-latest} - IFS=',' read -r -a TAG_ARRAY <<< "$TAGS" - - echo "The image ${BINARY} will be tagged with ${TAG_ARRAY[*]}" - for TAG in "${TAG_ARRAY[@]}"; do - $ENGINE tag ${DOCKER_OWNER}/${BINARY} ${DOCKER_OWNER}/${BINARY}:${TAG} - $ENGINE push ${DOCKER_OWNER}/${BINARY}:${TAG} - done - $ENGINE images | grep ${BINARY} + $ENGINE push --all-tags ${REGISTRY}/${DOCKER_OWNER}/${BINARY} - name: Check version for the published image for ${{ env.BINARY }} env: diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index 20fed5df3dfd..2d74187cadfa 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -328,7 +328,7 @@ build-linux-substrate: cut -d ' ' -f 2 | tee ./artifacts/substrate/VERSION; fi - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 - - cp -r ./docker/substrate_injected.Dockerfile ./artifacts/substrate/ + - cp -r ./docker/dockerfiles/substrate_injected.Dockerfile ./artifacts/substrate/ # - printf '\n# building node-template\n\n' # - ./scripts/ci/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz diff --git a/.gitlab/pipeline/publish.yml b/.gitlab/pipeline/publish.yml index ed18082344f0..341d3ac2a862 100644 --- a/.gitlab/pipeline/publish.yml +++ b/.gitlab/pipeline/publish.yml @@ -35,7 +35,7 @@ build-push-image-polkadot-parachain-debug: - job: build-linux-stable-cumulus artifacts: true variables: - DOCKERFILE: "docker/polkadot-parachain-debug_unsigned_injected.Dockerfile" + DOCKERFILE: "docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile" IMAGE_NAME: "docker.io/paritypr/polkadot-parachain-debug" build-push-image-test-parachain: @@ -48,7 +48,7 @@ build-push-image-test-parachain: - job: build-test-parachain artifacts: true variables: - DOCKERFILE: "docker/test-parachain_injected.Dockerfile" + DOCKERFILE: "docker/dockerfiles/test-parachain_injected.Dockerfile" IMAGE_NAME: "docker.io/paritypr/test-parachain" # publish-s3: # stage: publish @@ -114,7 +114,7 @@ build-push-image-polkadot-debug: - job: build-linux-stable artifacts: true variables: - DOCKERFILE: "docker/polkadot_injected_debug.Dockerfile" + DOCKERFILE: "docker/dockerfiles/polkadot/polkadot_injected_debug.Dockerfile" IMAGE_NAME: "docker.io/paritypr/polkadot-debug" build-push-image-colander: @@ -127,7 +127,7 @@ build-push-image-colander: - job: build-test-collators artifacts: true variables: - DOCKERFILE: "docker/collator_injected.Dockerfile" + DOCKERFILE: "docker/dockerfiles/collator_injected.Dockerfile" IMAGE_NAME: "docker.io/paritypr/colander" build-push-image-malus: @@ -140,7 +140,7 @@ build-push-image-malus: - job: build-malus artifacts: true variables: - DOCKERFILE: "docker/malus_injected.Dockerfile" + DOCKERFILE: "docker/dockerfiles/malus_injected.Dockerfile" IMAGE_NAME: "docker.io/paritypr/malus" build-push-image-substrate-pr: @@ -153,7 +153,7 @@ build-push-image-substrate-pr: - job: build-linux-substrate artifacts: true variables: - DOCKERFILE: "docker/substrate_injected.Dockerfile" + DOCKERFILE: "docker/dockerfiles/substrate_injected.Dockerfile" IMAGE_NAME: "docker.io/paritypr/substrate" # old way @@ -201,7 +201,7 @@ build-push-image-substrate-pr: # GIT_STRATEGY: none # DOCKER_USER: ${PARITYPR_USER} # DOCKER_PASS: ${PARITYPR_PASS} -# # scripts/ci/dockerfiles/polkadot_injected_debug.Dockerfile +# # docker/dockerfiles/polkadot/polkadot_injected_debug.Dockerfile # DOCKERFILE: polkadot_injected_debug.Dockerfile # IMAGE_NAME: docker.io/paritypr/polkadot-debug # needs: @@ -230,7 +230,7 @@ build-push-image-substrate-pr: # GIT_STRATEGY: none # DOCKER_USER: ${PARITYPR_USER} # DOCKER_PASS: ${PARITYPR_PASS} -# # scripts/ci/dockerfiles/collator_injected.Dockerfile +# # docker/dockerfiles/collator_injected.Dockerfile # DOCKERFILE: collator_injected.Dockerfile # IMAGE_NAME: docker.io/paritypr/colander # needs: @@ -258,7 +258,7 @@ build-push-image-substrate-pr: # GIT_STRATEGY: none # DOCKER_USER: ${PARITYPR_USER} # DOCKER_PASS: ${PARITYPR_PASS} -# # scripts/ci/dockerfiles/malus_injected.Dockerfile +# # docker/dockerfiles/malus_injected.Dockerfile # DOCKERFILE: malus_injected.Dockerfile # IMAGE_NAME: docker.io/paritypr/malus # needs: diff --git a/.gitlab/test_deterministic_wasm.sh b/.gitlab/test_deterministic_wasm.sh index 4f1d2981ff2b..fac28fce1f64 100755 --- a/.gitlab/test_deterministic_wasm.sh +++ b/.gitlab/test_deterministic_wasm.sh @@ -2,7 +2,7 @@ set -e #shellcheck source=../common/lib.sh -source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/common/lib.sh" +source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/../.github/scripts/common/lib.sh" # build runtime WASM_BUILD_NO_COLOR=1 cargo build -q --locked --release -p staging-kusama-runtime -p polkadot-runtime -p westend-runtime diff --git a/cumulus/docker/parachain-registrar.dockerfile b/cumulus/docker/parachain-registrar.dockerfile deleted file mode 100644 index f7d77454a2b9..000000000000 --- a/cumulus/docker/parachain-registrar.dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM node:latest AS pjs - -# It would be great to depend on a more stable tag, but we need some -# as-yet-unreleased features. -RUN yarn global add @polkadot/api-cli@0.10.0-beta.14 - -ENTRYPOINT [ "polkadot-js-api" ] -CMD [ "--version" ] - -# To use the pjs build stage to access the blockchain from the host machine: -# -# docker build -f docker/parachain-registrar.dockerfile --target pjs -t parachain-registrar:pjs . -# alias pjs='docker run --rm --net cumulus_testing_net parachain-registrar:pjs --ws ws://172.28.1.1:9944' -# -# Then, as long as the chain is running, you can use the polkadot-js-api CLI like: -# -# pjs query.sudo.key - -FROM pjs -RUN apt-get update && apt-get install curl netcat -y && \ - curl -sSo /wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && \ - chmod +x /wait-for-it.sh -# the only thing left to do is to actually run the transaction. -COPY ./docker/scripts/register_para.sh /usr/bin -# unset the previous stage's entrypoint -ENTRYPOINT [] -CMD [ "/usr/bin/register_para.sh" ] diff --git a/cumulus/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile b/cumulus/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile deleted file mode 100644 index a2e32049f5bb..000000000000 --- a/cumulus/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -FROM docker.io/library/ubuntu:20.04 - -# metadata -ARG VCS_REF -ARG BUILD_DATE -ARG IMAGE_NAME - -LABEL io.parity.image.authors="devops-team@parity.io" \ - io.parity.image.vendor="Parity Technologies" \ - io.parity.image.title="${IMAGE_NAME}" \ - io.parity.image.description="Cumulus, the Polkadot collator." \ - io.parity.image.source="https://github.com/paritytech/cumulus/blob/${VCS_REF}/scripts/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile" \ - io.parity.image.revision="${VCS_REF}" \ - io.parity.image.created="${BUILD_DATE}" \ - io.parity.image.documentation="https://github.com/paritytech/cumulus/" - -# show backtraces -ENV RUST_BACKTRACE 1 - -# install tools and dependencies -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y \ - libssl1.1 \ - ca-certificates \ - curl && \ - # apt cleanup - apt-get autoremove -y && \ - apt-get clean && \ - find /var/lib/apt/lists/ -type f -not -name lock -delete; \ - # add user and link ~/.local/share/polkadot-parachain to /data - useradd -m -u 10000 -U -s /bin/sh -d /polkadot-parachain polkadot-parachain && \ - mkdir -p /data /polkadot-parachain/.local/share && \ - chown -R polkadot-parachain:polkadot-parachain /data && \ - ln -s /data /polkadot-parachain/.local/share/polkadot-parachain && \ - mkdir -p /specs - -# add polkadot-parachain binary to the docker image -COPY ./artifacts/polkadot-parachain /usr/local/bin -COPY ./parachains/chain-specs/*.json /specs/ - -USER polkadot-parachain - -# check if executable works in this container -RUN /usr/local/bin/polkadot-parachain --version - -EXPOSE 30333 9933 9944 -VOLUME ["/polkadot-parachain"] - -ENTRYPOINT ["/usr/local/bin/polkadot-parachain"] diff --git a/cumulus/docker/polkadot-parachain_builder.Containerfile b/cumulus/docker/polkadot-parachain_builder.Containerfile deleted file mode 100644 index 159bcb323693..000000000000 --- a/cumulus/docker/polkadot-parachain_builder.Containerfile +++ /dev/null @@ -1,36 +0,0 @@ -# This file is sourced from https://github.com/paritytech/polkadot/blob/master/scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile -# This is the build stage for polkadot-parachain. Here we create the binary in a temporary image. -FROM docker.io/paritytech/ci-linux:production as builder - -WORKDIR /cumulus -COPY . /cumulus - -RUN cargo build --release --locked -p polkadot-parachain - -# This is the 2nd stage: a very small image where we copy the Polkadot binary." -FROM docker.io/library/ubuntu:20.04 - -LABEL io.parity.image.type="builder" \ - io.parity.image.authors="devops-team@parity.io" \ - io.parity.image.vendor="Parity Technologies" \ - io.parity.image.description="Multistage Docker image for polkadot-parachain" \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/polkadot/polkadot-parachain_builder.Dockerfile" \ - io.parity.image.documentation="https://github.com/paritytech/cumulus" - -COPY --from=builder /cumulus/target/release/polkadot-parachain /usr/local/bin - -RUN useradd -m -u 1000 -U -s /bin/sh -d /cumulus polkadot-parachain && \ - mkdir -p /data /cumulus/.local/share && \ - chown -R polkadot-parachain:polkadot-parachain /data && \ - ln -s /data /cumulus/.local/share/polkadot-parachain && \ -# unclutter and minimize the attack surface - rm -rf /usr/bin /usr/sbin && \ -# check if executable works in this container - /usr/local/bin/polkadot-parachain --version - -USER polkadot-parachain - -EXPOSE 30333 9933 9944 9615 -VOLUME ["/data"] - -ENTRYPOINT ["/usr/local/bin/polkadot-parachain"] diff --git a/cumulus/docker/test-parachain-collator.dockerfile b/cumulus/docker/test-parachain-collator.dockerfile deleted file mode 100644 index 9c2d8fbe5818..000000000000 --- a/cumulus/docker/test-parachain-collator.dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# This file is sourced from https://github.com/paritytech/polkadot/blob/master/scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile -FROM docker.io/paritytech/ci-linux:production as builder - -WORKDIR /cumulus -COPY . /cumulus - -RUN cargo build --release --locked -p polkadot-parachain - -# the collator stage is normally built once, cached, and then ignored, but can -# be specified with the --target build flag. This adds some extra tooling to the -# image, which is required for a launcher script. The script simply adds two -# arguments to the list passed in: -# -# --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/PEER_ID -# -# with the appropriate ip and ID for both Alice and Bob -FROM debian:buster-slim as collator -RUN apt-get update && apt-get install jq curl bash -y && \ - curl -sSo /wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && \ - chmod +x /wait-for-it.sh && \ - curl -sL https://deb.nodesource.com/setup_12.x | bash - && \ - apt-get install -y nodejs && \ - npm install --global yarn && \ - yarn global add @polkadot/api-cli@0.10.0-beta.14 -COPY --from=builder \ - /paritytech/cumulus/target/release/polkadot-parachain /usr/bin -COPY ./docker/scripts/inject_bootnodes.sh /usr/bin -CMD ["/usr/bin/inject_bootnodes.sh"] -COPY ./docker/scripts/healthcheck.sh /usr/bin/ -HEALTHCHECK --interval=300s --timeout=75s --start-period=30s --retries=3 \ - CMD ["/usr/bin/healthcheck.sh"] - -# the runtime stage is normally built once, cached, and ignored, but can be -# specified with the --target build flag. This just preserves one of the builder's -# outputs, which can then be moved into a volume at runtime -FROM debian:buster-slim as runtime -COPY --from=builder \ - /paritytech/cumulus/target/release/wbuild/cumulus-test-parachain-runtime/cumulus_test_parachain_runtime.compact.wasm \ - /var/opt/ -CMD ["cp", "-v", "/var/opt/cumulus_test_parachain_runtime.compact.wasm", "/runtime/"] - -FROM debian:buster-slim -COPY --from=builder \ - /paritytech/cumulus/target/release/polkadot-parachain /usr/bin - -CMD ["/usr/bin/polkadot-parachain"] diff --git a/cumulus/docker/test-parachain_injected.Dockerfile b/cumulus/docker/test-parachain_injected.Dockerfile deleted file mode 100644 index 6056c504604e..000000000000 --- a/cumulus/docker/test-parachain_injected.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -FROM docker.io/library/ubuntu:20.04 - -# metadata -ARG VCS_REF -ARG BUILD_DATE -ARG IMAGE_NAME - -LABEL io.parity.image.authors="devops-team@parity.io" \ - io.parity.image.vendor="Parity Technologies" \ - io.parity.image.title="${IMAGE_NAME}" \ - io.parity.image.description="Test parachain for Zombienet" \ - io.parity.image.source="https://github.com/paritytech/cumulus/blob/${VCS_REF}/docker/test-parachain_injected.Dockerfile" \ - io.parity.image.revision="${VCS_REF}" \ - io.parity.image.created="${BUILD_DATE}" \ - io.parity.image.documentation="https://github.com/paritytech/cumulus/" - -# show backtraces -ENV RUST_BACKTRACE 1 - -# install tools and dependencies -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y \ - libssl1.1 \ - ca-certificates \ - curl && \ - # apt cleanup - apt-get autoremove -y && \ - apt-get clean && \ - find /var/lib/apt/lists/ -type f -not -name lock -delete; \ - # add user and link ~/.local/share/test-parachain to /data - useradd -m -u 10000 -U -s /bin/sh -d /test-parachain test-parachain && \ - mkdir -p /data /test-parachain/.local/share && \ - chown -R test-parachain:test-parachain /data && \ - ln -s /data /test-parachain/.local/share/test-parachain && \ - mkdir -p /specs - -# add test-parachain binary to the docker image -COPY ./artifacts/test-parachain /usr/local/bin -COPY ./parachains/chain-specs/*.json /specs/ - -USER test-parachain - -# check if executable works in this container -RUN /usr/local/bin/test-parachain --version - -EXPOSE 30333 9933 9944 -VOLUME ["/test-parachain"] - -ENTRYPOINT ["/usr/local/bin/test-parachain"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index 8344ad43bb4c..000000000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,129 +0,0 @@ -version: '3.7' -services: - node_alice: - image: "polkadot:${BRANCH:-cumulus-branch}" - ports: - - "30333:30333" - - "9933:9933" - - "9944:9944" - volumes: - - "polkadot-data-alice:/data" - - type: bind - source: ./test/parachain/chain-specs/polkadot_chainspec.json - target: /chainspec.json - read_only: true - command: > - polkadot - --chain=/chainspec.json - --base-path=/data - --port 30333 - --rpc-port 9933 - --ws-port 9944 - --rpc-external - --rpc-cors all - --ws-external - --alice - networks: - testing_net: - ipv4_address: 172.28.1.1 - aliases: - - alice - - node_bob: - image: "polkadot:${BRANCH:-cumulus-branch}" - ports: - - "30344:30333" - - "9935:9933" - - "9945:9944" - volumes: - - "polkadot-data-bob:/data" - - type: bind - source: ./test/parachain/chain-specs/polkadot_chainspec.json - target: /chainspec.json - read_only: true - command: > - polkadot - --chain=/chainspec.json - --base-path=/data - --port 30333 - --rpc-port 9933 - --ws-port 9944 - --rpc-external - --ws-external - --rpc-cors all - --bob - networks: - testing_net: - ipv4_address: 172.28.1.2 - aliases: - - bob - - genesis_state: - build: - context: . - dockerfile: ./docker/test-parachain-collator.dockerfile - image: "ctpc:latest" - volumes: - - "genesis-state:/data" - command: > - polkadot-parachain - export-genesis-state - /data/genesis-state - - collator: - build: - context: . - dockerfile: ./docker/test-parachain-collator.dockerfile - target: collator - image: "ctpc:collator" - volumes: - - "collator-data:/data" - depends_on: - - node_alice - - node_bob - command: > - inject_bootnodes.sh - --base-path=/data - networks: - testing_net: - - runtime: - build: - context: . - dockerfile: ./docker/test-parachain-collator.dockerfile - target: runtime - image: "ctpc:runtime" - volumes: - - "parachain-runtime:/runtime" - - - registrar: - build: - context: . - dockerfile: ./docker/parachain-registrar.dockerfile - image: para-reg:latest - volumes: - - "genesis-state:/genesis" - - "parachain-runtime:/runtime" - depends_on: - - node_alice - - runtime - - genesis_state - networks: - testing_net: - - -volumes: - polkadot-data-alice: - polkadot-data-bob: - collator-data: - genesis-state: - parachain-runtime: - - -networks: - testing_net: - ipam: - driver: default - config: - - subnet: 172.28.0.0/16 diff --git a/docker/dockerfiles/binary_injected.Dockerfile b/docker/dockerfiles/binary_injected.Dockerfile new file mode 100644 index 000000000000..ac1fd5317c67 --- /dev/null +++ b/docker/dockerfiles/binary_injected.Dockerfile @@ -0,0 +1,48 @@ +FROM docker.io/parity/base-bin + +# This file allows building a Generic container image +# based on one or multiple pre-built Linux binaries. +# Some defaults are set to polkadot but all can be overriden. + +SHELL ["/bin/bash", "-c"] + +# metadata +ARG VCS_REF +ARG BUILD_DATE +ARG IMAGE_NAME + +# That can be a single one or a comma separated list +ARG BINARY=polkadot + +ARG BIN_FOLDER=. +ARG DOC_URL=https://github.com/paritytech/polkadot-sdk +ARG DESCRIPTION="Polkadot: a platform for web3" +ARG AUTHORS="devops-team@parity.io" +ARG VENDOR="Parity Technologies" + +LABEL io.parity.image.authors=${AUTHORS} \ + io.parity.image.vendor="${VENDOR}" \ + io.parity.image.revision="${VCS_REF}" \ + io.parity.image.title="${IMAGE_NAME}" \ + io.parity.image.created="${BUILD_DATE}" \ + io.parity.image.documentation="${DOC_URL}" \ + io.parity.image.description="${DESCRIPTION}" \ + io.parity.image.source="https://github.com/paritytech/polkadot-sdk/blob/${VCS_REF}/docker/dockerfiles/binary_injected.Dockerfile" + +USER root +WORKDIR /app + +# add polkadot binary to docker image +# sample for polkadot: COPY ./polkadot ./polkadot-*-worker /usr/local/bin/ +COPY entrypoint.sh . +COPY "bin/*" "/usr/local/bin/" +RUN chmod -R a+rx "/usr/local/bin" + +USER parity +ENV BINARY=${BINARY} + +# ENTRYPOINT +ENTRYPOINT ["/app/entrypoint.sh"] + +# We call the help by default +CMD ["--help"] diff --git a/docker/collator_injected.Dockerfile b/docker/dockerfiles/collator_injected.Dockerfile similarity index 95% rename from docker/collator_injected.Dockerfile rename to docker/dockerfiles/collator_injected.Dockerfile index 6472c240f332..0c9ea1e0ca83 100644 --- a/docker/collator_injected.Dockerfile +++ b/docker/dockerfiles/collator_injected.Dockerfile @@ -10,7 +10,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="${IMAGE_NAME}" \ io.parity.image.description="Injected adder-collator Docker image" \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/collator_injected.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/docker/dockerfiles/collator_injected.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/polkadot/" diff --git a/cumulus/docker/docker-compose.yml b/docker/dockerfiles/docker-compose.yml similarity index 89% rename from cumulus/docker/docker-compose.yml rename to docker/dockerfiles/docker-compose.yml index 8344ad43bb4c..8dc8540353fe 100644 --- a/cumulus/docker/docker-compose.yml +++ b/docker/dockerfiles/docker-compose.yml @@ -61,7 +61,7 @@ services: genesis_state: build: context: . - dockerfile: ./docker/test-parachain-collator.dockerfile + dockerfile: ./docker/dockerfiles/test-parachain-collator.dockerfile image: "ctpc:latest" volumes: - "genesis-state:/data" @@ -73,7 +73,7 @@ services: collator: build: context: . - dockerfile: ./docker/test-parachain-collator.dockerfile + dockerfile: ./docker/dockerfiles/test-parachain-collator.dockerfile target: collator image: "ctpc:collator" volumes: @@ -90,7 +90,7 @@ services: runtime: build: context: . - dockerfile: ./docker/test-parachain-collator.dockerfile + dockerfile: ./docker/dockerfiles/test-parachain-collator.dockerfile target: runtime image: "ctpc:runtime" volumes: @@ -100,7 +100,7 @@ services: registrar: build: context: . - dockerfile: ./docker/parachain-registrar.dockerfile + dockerfile: ./docker/dockerfiles/parachain-registrar.dockerfile image: para-reg:latest volumes: - "genesis-state:/genesis" diff --git a/docker/malus_injected.Dockerfile b/docker/dockerfiles/malus_injected.Dockerfile similarity index 100% rename from docker/malus_injected.Dockerfile rename to docker/dockerfiles/malus_injected.Dockerfile diff --git a/docker/parachain-registrar.dockerfile b/docker/dockerfiles/parachain-registrar.dockerfile similarity index 89% rename from docker/parachain-registrar.dockerfile rename to docker/dockerfiles/parachain-registrar.dockerfile index f7d77454a2b9..00908395101f 100644 --- a/docker/parachain-registrar.dockerfile +++ b/docker/dockerfiles/parachain-registrar.dockerfile @@ -9,7 +9,7 @@ CMD [ "--version" ] # To use the pjs build stage to access the blockchain from the host machine: # -# docker build -f docker/parachain-registrar.dockerfile --target pjs -t parachain-registrar:pjs . +# docker build -f docker/dockerfiles/parachain-registrar.dockerfile --target pjs -t parachain-registrar:pjs . # alias pjs='docker run --rm --net cumulus_testing_net parachain-registrar:pjs --ws ws://172.28.1.1:9944' # # Then, as long as the chain is running, you can use the polkadot-js-api CLI like: diff --git a/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile b/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile similarity index 93% rename from docker/polkadot-parachain-debug_unsigned_injected.Dockerfile rename to docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile index e77563b8ebf2..7a2202d9c52b 100644 --- a/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile +++ b/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile @@ -9,7 +9,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="${IMAGE_NAME}" \ io.parity.image.description="Cumulus, the Polkadot collator." \ - io.parity.image.source="https://github.com/paritytech/cumulus/blob/${VCS_REF}/scripts/docker/polkadot-parachain-debug_unsigned_injected.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/cumulus/blob/${VCS_REF}/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/cumulus/" diff --git a/docker/polkadot-parachain_builder.Containerfile b/docker/dockerfiles/polkadot-parachain/polkadot-parachain_builder.Containerfile similarity index 89% rename from docker/polkadot-parachain_builder.Containerfile rename to docker/dockerfiles/polkadot-parachain/polkadot-parachain_builder.Containerfile index 159bcb323693..4d110d6af472 100644 --- a/docker/polkadot-parachain_builder.Containerfile +++ b/docker/dockerfiles/polkadot-parachain/polkadot-parachain_builder.Containerfile @@ -1,4 +1,4 @@ -# This file is sourced from https://github.com/paritytech/polkadot/blob/master/scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile +# This file is sourced from https://github.com/paritytech/polkadot/blob/master/docker/dockerfiles/polkadot/polkadot_builder.Dockerfile # This is the build stage for polkadot-parachain. Here we create the binary in a temporary image. FROM docker.io/paritytech/ci-linux:production as builder @@ -14,7 +14,7 @@ LABEL io.parity.image.type="builder" \ io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.description="Multistage Docker image for polkadot-parachain" \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/polkadot/polkadot-parachain_builder.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/docker/dockerfiles/polkadot-parachain/polkadot-parachain_builder.Dockerfile" \ io.parity.image.documentation="https://github.com/paritytech/cumulus" COPY --from=builder /cumulus/target/release/polkadot-parachain /usr/local/bin diff --git a/cumulus/docker/injected.Dockerfile b/docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile similarity index 68% rename from cumulus/docker/injected.Dockerfile rename to docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile index f9b11f022e75..16bd0f4cf3c5 100644 --- a/cumulus/docker/injected.Dockerfile +++ b/docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile @@ -9,10 +9,10 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="${IMAGE_NAME}" \ io.parity.image.description="Cumulus, the Polkadot collator." \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/docker/Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/polkadot-sdk/blob/${VCS_REF}/docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ - io.parity.image.documentation="https://github.com/paritytech/cumulus/" + io.parity.image.documentation="https://github.com/paritytech/polkadot-sdk/" # show backtraces ENV RUST_BACKTRACE 1 @@ -22,8 +22,10 @@ USER root RUN mkdir -p /specs # add polkadot-parachain binary to the docker image -COPY ./release-artifacts/* /usr/local/bin -COPY ./parachains/chain-specs/*.json /specs/ +COPY bin/* /usr/local/bin/ +COPY specs/* /specs/ + +RUN chmod -R a+rx "/usr/local/bin" USER parity diff --git a/docker/dockerfiles/polkadot/README.md b/docker/dockerfiles/polkadot/README.md new file mode 100644 index 000000000000..e331d8984c2c --- /dev/null +++ b/docker/dockerfiles/polkadot/README.md @@ -0,0 +1,9 @@ +# Self built Docker image + +The Polkadot repo contains several options to build Docker images for Polkadot. + +This folder contains a self-contained image that does not require a Linux pre-built binary. + +Instead, building the image is possible on any host having docker installed and will +build Polkadot inside Docker. That also means that no Rust toolchain is required on the host +machine for the build to succeed. diff --git a/docker/dockerfiles/polkadot/docker-compose-local.yml b/docker/dockerfiles/polkadot/docker-compose-local.yml new file mode 100644 index 000000000000..1ff3a1ccaac2 --- /dev/null +++ b/docker/dockerfiles/polkadot/docker-compose-local.yml @@ -0,0 +1,50 @@ +version: '3' +services: + node_alice: + ports: + - "30333:30333" + - "9933:9933" + - "9944:9944" + - "9615:9615" + image: parity/polkadot:latest + volumes: + - "polkadot-data-alice:/data" + command: | + --chain=polkadot-local + --alice + -d /data + --node-key 0000000000000000000000000000000000000000000000000000000000000001 + networks: + testing_net: + ipv4_address: 172.28.1.1 + + node_bob: + ports: + - "30344:30333" + - "9935:9933" + - "9945:9944" + - "29615:9615" + image: parity/polkadot:latest + volumes: + - "polkadot-data-bob:/data" + links: + - "node_alice:alice" + command: | + --chain=polkadot-local + --bob + -d /data + --bootnodes '/ip4/172.28.1.1/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR' + networks: + testing_net: + ipv4_address: 172.28.1.2 + +volumes: + polkadot-data-alice: + polkadot-data-bob: + +networks: + testing_net: + ipam: + driver: default + config: + - subnet: 172.28.0.0/16 diff --git a/docker/dockerfiles/polkadot/docker-compose.yml b/docker/dockerfiles/polkadot/docker-compose.yml new file mode 100644 index 000000000000..524b1164796a --- /dev/null +++ b/docker/dockerfiles/polkadot/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3' +services: + polkadot: + image: parity/polkadot:latest + + ports: + - "127.0.0.1:30333:30333/tcp" + - "127.0.0.1:9933:9933/tcp" + - "127.0.0.1:9944:9944/tcp" + - "127.0.0.1:9615:9615/tcp" + + volumes: + - "polkadot-data:/data" + + command: | + --unsafe-rpc-external + --unsafe-ws-external + --rpc-cors all + --prometheus-external + +volumes: + polkadot-data: diff --git a/docker/dockerfiles/polkadot/polkadot_Dockerfile.README.md b/docker/dockerfiles/polkadot/polkadot_Dockerfile.README.md new file mode 100644 index 000000000000..7e89cb55f3de --- /dev/null +++ b/docker/dockerfiles/polkadot/polkadot_Dockerfile.README.md @@ -0,0 +1,7 @@ +# Polkadot official Docker image + +## [Polkadot](https://polkadot.network/) + +## [GitHub](https://github.com/paritytech/polkadot) + +## [Polkadot Wiki](https://wiki.polkadot.network/) diff --git a/docker/dockerfiles/polkadot/polkadot_builder.Dockerfile b/docker/dockerfiles/polkadot/polkadot_builder.Dockerfile new file mode 100644 index 000000000000..f8dc374a14aa --- /dev/null +++ b/docker/dockerfiles/polkadot/polkadot_builder.Dockerfile @@ -0,0 +1,36 @@ +# This is the build stage for Polkadot. Here we create the binary in a temporary image. +FROM docker.io/paritytech/ci-linux:production as builder + +WORKDIR /polkadot +COPY . /polkadot + +RUN cargo build --locked --release + +# This is the 2nd stage: a very small image where we copy the Polkadot binary." +FROM docker.io/parity/base-bin:latest + +LABEL description="Multistage Docker image for Polkadot: a platform for web3" \ + io.parity.image.type="builder" \ + io.parity.image.authors="chevdor@gmail.com, devops-team@parity.io" \ + io.parity.image.vendor="Parity Technologies" \ + io.parity.image.description="Polkadot: a platform for web3" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/docker/dockerfiles/polkadot/polkadot_builder.Dockerfile" \ + io.parity.image.documentation="https://github.com/paritytech/polkadot/" + +COPY --from=builder /polkadot/target/release/polkadot /usr/local/bin + +RUN useradd -m -u 1000 -U -s /bin/sh -d /polkadot polkadot && \ + mkdir -p /data /polkadot/.local/share && \ + chown -R polkadot:polkadot /data && \ + ln -s /data /polkadot/.local/share/polkadot && \ +# unclutter and minimize the attack surface + rm -rf /usr/bin /usr/sbin && \ +# check if executable works in this container + /usr/local/bin/polkadot --version + +USER polkadot + +EXPOSE 30333 9933 9944 9615 +VOLUME ["/data"] + +ENTRYPOINT ["/usr/local/bin/polkadot"] diff --git a/docker/dockerfiles/polkadot/polkadot_injected_debian.Dockerfile b/docker/dockerfiles/polkadot/polkadot_injected_debian.Dockerfile new file mode 100644 index 000000000000..e2c72dcfe2e9 --- /dev/null +++ b/docker/dockerfiles/polkadot/polkadot_injected_debian.Dockerfile @@ -0,0 +1,53 @@ +FROM docker.io/library/ubuntu:20.04 + +# metadata +ARG VCS_REF +ARG BUILD_DATE +ARG POLKADOT_VERSION +ARG POLKADOT_GPGKEY=9D4B2B6EB8F97156D19669A9FF0812D491B96798 +ARG GPG_KEYSERVER="keyserver.ubuntu.com" + +LABEL io.parity.image.authors="devops-team@parity.io" \ + io.parity.image.vendor="Parity Technologies" \ + io.parity.image.title="parity/polkadot" \ + io.parity.image.description="Polkadot: a platform for web3. This is the official Parity image with an injected binary." \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/polkadot/polkadot_injected_debian.Dockerfile" \ + io.parity.image.revision="${VCS_REF}" \ + io.parity.image.created="${BUILD_DATE}" \ + io.parity.image.documentation="https://github.com/paritytech/polkadot/" + +# show backtraces +ENV RUST_BACKTRACE 1 + +# install tools and dependencies +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libssl1.1 \ + ca-certificates \ + gnupg && \ + useradd -m -u 1000 -U -s /bin/sh -d /polkadot polkadot && \ +# add repo's gpg keys and install the published polkadot binary + gpg --keyserver ${GPG_KEYSERVER} --recv-keys ${POLKADOT_GPGKEY} && \ + gpg --export ${POLKADOT_GPGKEY} > /usr/share/keyrings/parity.gpg && \ + echo 'deb [signed-by=/usr/share/keyrings/parity.gpg] https://releases.parity.io/deb release main' > /etc/apt/sources.list.d/parity.list && \ + apt-get update && \ + apt-get install -y --no-install-recommends polkadot=${POLKADOT_VERSION#?} && \ +# apt cleanup + apt-get autoremove -y && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* ; \ + mkdir -p /data /polkadot/.local/share && \ + chown -R polkadot:polkadot /data && \ + ln -s /data /polkadot/.local/share/polkadot + +USER polkadot + +# check if executable works in this container +RUN /usr/bin/polkadot --version +RUN /usr/bin/polkadot-execute-worker --version +RUN /usr/bin/polkadot-prepare-worker --version + +EXPOSE 30333 9933 9944 +VOLUME ["/polkadot"] + +ENTRYPOINT ["/usr/bin/polkadot"] diff --git a/docker/polkadot_injected_debug.Dockerfile b/docker/dockerfiles/polkadot/polkadot_injected_debug.Dockerfile similarity index 94% rename from docker/polkadot_injected_debug.Dockerfile rename to docker/dockerfiles/polkadot/polkadot_injected_debug.Dockerfile index f7f764d335a2..80ce82589873 100644 --- a/docker/polkadot_injected_debug.Dockerfile +++ b/docker/dockerfiles/polkadot/polkadot_injected_debug.Dockerfile @@ -9,7 +9,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="${IMAGE_NAME}" \ io.parity.image.description="Polkadot: a platform for web3" \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/polkadot_injected_debug.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/docker/dockerfiles/polkadot/polkadot_injected_debug.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/polkadot/" diff --git a/docker/polkadot_injected_release.Dockerfile b/docker/dockerfiles/polkadot/polkadot_injected_release.Dockerfile similarity index 95% rename from docker/polkadot_injected_release.Dockerfile rename to docker/dockerfiles/polkadot/polkadot_injected_release.Dockerfile index 87ae7ac27dc0..c13f2db982a1 100644 --- a/docker/polkadot_injected_release.Dockerfile +++ b/docker/dockerfiles/polkadot/polkadot_injected_release.Dockerfile @@ -11,7 +11,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="parity/polkadot" \ io.parity.image.description="Polkadot: a platform for web3. This is the official Parity image with an injected binary." \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/polkadot_injected_release.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/docker/dockerfiles/polkadot/polkadot_injected_release.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/polkadot/" diff --git a/docker/staking-miner/staking-miner_builder.Dockerfile b/docker/dockerfiles/staking-miner/staking-miner_builder.Dockerfile similarity index 100% rename from docker/staking-miner/staking-miner_builder.Dockerfile rename to docker/dockerfiles/staking-miner/staking-miner_builder.Dockerfile diff --git a/docker/staking-miner/staking-miner_injected.Dockerfile b/docker/dockerfiles/staking-miner/staking-miner_injected.Dockerfile similarity index 100% rename from docker/staking-miner/staking-miner_injected.Dockerfile rename to docker/dockerfiles/staking-miner/staking-miner_injected.Dockerfile diff --git a/docker/substrate_injected.Dockerfile b/docker/dockerfiles/substrate_injected.Dockerfile similarity index 100% rename from docker/substrate_injected.Dockerfile rename to docker/dockerfiles/substrate_injected.Dockerfile diff --git a/docker/test-parachain-collator.dockerfile b/docker/dockerfiles/test-parachain-collator.dockerfile similarity index 96% rename from docker/test-parachain-collator.dockerfile rename to docker/dockerfiles/test-parachain-collator.dockerfile index 9c2d8fbe5818..0d56949152e2 100644 --- a/docker/test-parachain-collator.dockerfile +++ b/docker/dockerfiles/test-parachain-collator.dockerfile @@ -1,4 +1,4 @@ -# This file is sourced from https://github.com/paritytech/polkadot/blob/master/scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile +# This file is sourced from https://github.com/paritytech/polkadot/blob/master/docker/dockerfiles/polkadot/polkadot_builder.Dockerfile FROM docker.io/paritytech/ci-linux:production as builder WORKDIR /cumulus diff --git a/docker/test-parachain_injected.Dockerfile b/docker/dockerfiles/test-parachain_injected.Dockerfile similarity index 95% rename from docker/test-parachain_injected.Dockerfile rename to docker/dockerfiles/test-parachain_injected.Dockerfile index 0b345e16e4af..e5d0df7aad67 100644 --- a/docker/test-parachain_injected.Dockerfile +++ b/docker/dockerfiles/test-parachain_injected.Dockerfile @@ -9,7 +9,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="${IMAGE_NAME}" \ io.parity.image.description="Test parachain for Zombienet" \ - io.parity.image.source="https://github.com/paritytech/cumulus/blob/${VCS_REF}/docker/test-parachain_injected.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/cumulus/blob/${VCS_REF}/docker/dockerfiles/test-parachain_injected.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/cumulus/" diff --git a/docker/injected.Dockerfile b/docker/injected.Dockerfile deleted file mode 100644 index 93d0561ca877..000000000000 --- a/docker/injected.Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -FROM docker.io/library/ubuntu:20.04 - -# metadata -ARG VCS_REF -ARG BUILD_DATE -ARG IMAGE_NAME - -LABEL io.parity.image.authors="devops-team@parity.io" \ - io.parity.image.vendor="Parity Technologies" \ - io.parity.image.title="${IMAGE_NAME}" \ - io.parity.image.description="Cumulus, the Polkadot collator." \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/docker/Dockerfile" \ - io.parity.image.revision="${VCS_REF}" \ - io.parity.image.created="${BUILD_DATE}" \ - io.parity.image.documentation="https://github.com/paritytech/cumulus/" - -# show backtraces -ENV RUST_BACKTRACE 1 - -# install tools and dependencies -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y \ - libssl1.1 \ - ca-certificates \ - curl && \ -# apt cleanup - apt-get autoremove -y && \ - apt-get clean && \ - find /var/lib/apt/lists/ -type f -not -name lock -delete; \ -# add user and link ~/.local/share/polkadot to /data - useradd -m -u 1000 -U -s /bin/sh -d /polkadot polkadot && \ - mkdir -p /data /polkadot/.local/share && \ - chown -R polkadot:polkadot /data && \ - ln -s /data /polkadot/.local/share/polkadot && \ - mkdir -p /specs - -# add polkadot-parachain binary to the docker image -COPY ./target/release/polkadot-parachain /usr/local/bin -COPY ./target/release/polkadot-parachain.asc /usr/local/bin -COPY ./target/release/polkadot-parachain.sha256 /usr/local/bin -COPY ./parachains/chain-specs/*.json /specs/ - -USER polkadot - -# check if executable works in this container -RUN /usr/local/bin/polkadot-parachain --version - -EXPOSE 30333 9933 9944 -VOLUME ["/polkadot"] - -ENTRYPOINT ["/usr/local/bin/polkadot-parachain"] diff --git a/docker/scripts/adder-collator/build-injected.sh b/docker/scripts/adder-collator/build-injected.sh new file mode 100755 index 000000000000..3a2d49741374 --- /dev/null +++ b/docker/scripts/adder-collator/build-injected.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Sample call: +# $0 /path/to/folder_with_binary +# This script replace the former dedicated Dockerfile +# and shows how to use the generic binary_injected.dockerfile + +PROJECT_ROOT=`git rev-parse --show-toplevel` + +export BINARY=adder-collator,undying-collator +export ARTIFACTS_FOLDER=$1 + +$PROJECT_ROOT/docker/scripts/build-injected.sh diff --git a/docker/scripts/adder-collator/test-build.sh b/docker/scripts/adder-collator/test-build.sh new file mode 100755 index 000000000000..171e0309f807 --- /dev/null +++ b/docker/scripts/adder-collator/test-build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +TMP=$(mktemp -d) +ENGINE=${ENGINE:-podman} + +# TODO: Switch to /bin/bash when the image is built from parity/base-bin + +# Fetch some binaries +$ENGINE run --user root --rm -i \ + --pull always \ + -v "$TMP:/export" \ + --entrypoint /usr/bin/bash \ + paritypr/colander:master -c \ + 'cp "$(which adder-collator)" /export' + +$ENGINE run --user root --rm -i \ + --pull always \ + -v "$TMP:/export" \ + --entrypoint /usr/bin/bash \ + paritypr/colander:master -c \ + 'cp "$(which undying-collator)" /export' + +./build-injected.sh $TMP diff --git a/docker/scripts/build-injected.sh b/docker/scripts/build-injected.sh new file mode 100755 index 000000000000..f415cf43c0ee --- /dev/null +++ b/docker/scripts/build-injected.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +#set -e + +# This script allows building a Container Image from a Linux +# binary that is injected into a base-image. + +ENGINE=${ENGINE:-podman} + +if [ "$ENGINE" == "podman" ]; then + PODMAN_FLAGS="--format docker" +else + PODMAN_FLAGS="" +fi + +CONTEXT=$(mktemp -d) +REGISTRY=${REGISTRY:-docker.io} + +# The following line ensure we know the project root +PROJECT_ROOT=${PROJECT_ROOT:-$(git rev-parse --show-toplevel)} +DOCKERFILE=${DOCKERFILE:-docker/dockerfiles/binary_injected.Dockerfile} +VERSION_TOML=$(grep "^version " $PROJECT_ROOT/Cargo.toml | grep -oE "([0-9\.]+-?[0-9]+)") + +#n The following VAR have default that can be overriden +DOCKER_OWNER=${DOCKER_OWNER:-parity} + +# We may get 1..n binaries, comma separated +BINARY=${BINARY:-polkadot} +IFS=',' read -r -a BINARIES <<< "$BINARY" + +VERSION=${VERSION:-$VERSION_TOML} +ARTIFACTS_FOLDER=${ARTIFACTS_FOLDER:-.} + +IMAGE=${IMAGE:-${REGISTRY}/${DOCKER_OWNER}/${BINARIES[0]}} +DESCRIPTION_DEFAULT="Injected Container image built for ${BINARY}" +DESCRIPTION=${DESCRIPTION:-$DESCRIPTION_DEFAULT} + +VCS_REF=${VCS_REF:-01234567} + +# Build the image +echo "Using engine: $ENGINE" +echo "Using Dockerfile: $DOCKERFILE" +echo "Using context: $CONTEXT" +echo "Building ${IMAGE}:latest container image for ${BINARY} v${VERSION} from ${ARTIFACTS_FOLDER} hang on!" +echo "ARTIFACTS_FOLDER=$ARTIFACTS_FOLDER" +echo "CONTEXT=$CONTEXT" + +# We need all binaries and resources available in the Container build "CONTEXT" +mkdir -p $CONTEXT/bin +for bin in "${BINARIES[@]}" +do + echo "Copying $ARTIFACTS_FOLDER/$bin to context: $CONTEXT/bin" + ls -al "$ARTIFACTS_FOLDER/$bin" + cp -r "$ARTIFACTS_FOLDER/$bin" "$CONTEXT/bin" +done + +cp "$PROJECT_ROOT/docker/scripts/entrypoint.sh" "$CONTEXT" + +if [[ "$BINARY" == "polkadot-parachain" ]]; then + mkdir -p "$CONTEXT/specs" + echo "Copying parachains chain-specs from $ARTIFACTS_FOLDER/specs to context: $CONTEXT/specs" + ls -al "$ARTIFACTS_FOLDER/specs" + cp -r "$ARTIFACTS_FOLDER/specs" "$CONTEXT/specs" +fi + +echo "Building image: ${IMAGE}" + +TAGS=${TAGS[@]:-latest} +IFS=',' read -r -a TAG_ARRAY <<< "$TAGS" +TAG_ARGS=" " + +echo "The image ${IMAGE} will be tagged with ${TAG_ARRAY[*]}" +for tag in "${TAG_ARRAY[@]}"; do + TAG_ARGS+="--tag ${IMAGE}:${tag} " +done + +echo "$TAG_ARGS" + +# time \ +$ENGINE build \ + ${PODMAN_FLAGS} \ + --build-arg VCS_REF="${VCS_REF}" \ + --build-arg BUILD_DATE=$(date -u '+%Y-%m-%dT%H:%M:%SZ') \ + --build-arg IMAGE_NAME="${IMAGE}" \ + --build-arg BINARY="${BINARY}" \ + --build-arg ARTIFACTS_FOLDER="${ARTIFACTS_FOLDER}" \ + --build-arg DESCRIPTION="${DESCRIPTION}" \ + ${TAG_ARGS} \ + -f "${PROJECT_ROOT}/${DOCKERFILE}" \ + ${CONTEXT} + +echo "Your Container image for ${IMAGE} is ready" +$ENGINE images + +if [[ -z "${SKIP_IMAGE_VALIDATION}" ]]; then + echo "Check the image ${IMAGE}:${TAG_ARRAY[0]}" + $ENGINE run --rm -i "${IMAGE}:${TAG_ARRAY[0]}" --version + + echo "Query binaries" + $ENGINE run --rm -i --entrypoint /bin/bash "${IMAGE}:${TAG_ARRAY[0]}" -c "echo BINARY: ${BINARY}" +fi diff --git a/docker/scripts/entrypoint.sh b/docker/scripts/entrypoint.sh new file mode 100755 index 000000000000..eaa815faf6a4 --- /dev/null +++ b/docker/scripts/entrypoint.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Sanity check +if [ -z "$BINARY" ] +then + echo "BINARY ENV not defined, this should never be the case. Aborting..." + exit 1 +fi + +# If the user built the image with multiple binaries, +# we consider the first one to be the canonical one +# To start with another binary, the user can either: +# - use the --entrypoint option +# - pass the ENV BINARY with a single binary +IFS=',' read -r -a BINARIES <<< "$BINARY" +BIN0=${BINARIES[0]} +echo "Starting binary $BIN0" +$BIN0 $@ diff --git a/docker/scripts/malus/build-injected.sh b/docker/scripts/malus/build-injected.sh new file mode 100755 index 000000000000..83e30e178500 --- /dev/null +++ b/docker/scripts/malus/build-injected.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Sample call: +# $0 /path/to/folder_with_binary +# This script replace the former dedicated Dockerfile +# and shows how to use the generic binary_injected.dockerfile + +PROJECT_ROOT=`git rev-parse --show-toplevel` + +export BINARY=malus,polkadot-execute-worker,polkadot-prepare-worker +export ARTIFACTS_FOLDER=$1 +# export TAGS=... + +$PROJECT_ROOT/docker/scripts/build-injected.sh diff --git a/docker/scripts/malus/test-build.sh b/docker/scripts/malus/test-build.sh new file mode 100755 index 000000000000..3114e9e2adf1 --- /dev/null +++ b/docker/scripts/malus/test-build.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +TMP=$(mktemp -d) +ENGINE=${ENGINE:-podman} + +export TAGS=latest,beta,7777,1.0.2-rc23 + +# Fetch some binaries +$ENGINE run --user root --rm -i \ + --pull always \ + -v "$TMP:/export" \ + --entrypoint /bin/bash \ + paritypr/malus:7217 -c \ + 'cp "$(which malus)" /export' + +echo "Checking binaries we got:" +ls -al $TMP + +./build-injected.sh $TMP diff --git a/docker/scripts/polkadot-parachain/build-injected.sh b/docker/scripts/polkadot-parachain/build-injected.sh new file mode 100755 index 000000000000..f5c86a035177 --- /dev/null +++ b/docker/scripts/polkadot-parachain/build-injected.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# Sample call: +# $0 /path/to/folder_with_binary +# This script replace the former dedicated Dockerfile +# and shows how to use the generic binary_injected.dockerfile + +PROJECT_ROOT=`git rev-parse --show-toplevel` + +export BINARY=polkadot-parachain +export ARTIFACTS_FOLDER=$1 +export DOCKERFILE="docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile" +# export TAGS=... + +$PROJECT_ROOT/docker/scripts/build-injected.sh diff --git a/docker/scripts/polkadot-parachain/test-build.sh b/docker/scripts/polkadot-parachain/test-build.sh new file mode 100755 index 000000000000..1dc53bd0d0b7 --- /dev/null +++ b/docker/scripts/polkadot-parachain/test-build.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +TMP=$(mktemp -d) +ENGINE=${ENGINE:-podman} + +export TAGS=latest,beta,7777,1.0.2-rc23 + +# Fetch some binaries +$ENGINE run --user root --rm -i \ + --pull always \ + -v "$TMP:/export" \ + --entrypoint /bin/bash \ + parity/polkadot-parachain:7217 -c \ + 'cp "$(which malus)" /export' + +echo "Checking binaries we got:" +ls -al $TMP + +./build-injected.sh $TMP diff --git a/cumulus/docker/scripts/build-injected-image.sh b/docker/scripts/polkadot-parachain_build-injected-image.sh similarity index 70% rename from cumulus/docker/scripts/build-injected-image.sh rename to docker/scripts/polkadot-parachain_build-injected-image.sh index b8bb0dd7dd2c..bb6909dd3b7b 100755 --- a/cumulus/docker/scripts/build-injected-image.sh +++ b/docker/scripts/polkadot-parachain_build-injected-image.sh @@ -6,5 +6,5 @@ IMAGE_NAME=${IMAGE_NAME:-polkadot-parachain} docker build --no-cache \ --build-arg IMAGE_NAME=$IMAGE_NAME \ -t $OWNER/$IMAGE_NAME \ - -f ./docker/injected.Dockerfile \ + -f ./docker/dockerfiles/polkadot-parachain/polkadot-parachain_injected.Dockerfile \ . && docker images diff --git a/docker/scripts/polkadot/build-injected.sh b/docker/scripts/polkadot/build-injected.sh new file mode 100755 index 000000000000..7cc6db43a54a --- /dev/null +++ b/docker/scripts/polkadot/build-injected.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Sample call: +# $0 /path/to/folder_with_binary +# This script replace the former dedicated Dockerfile +# and shows how to use the generic binary_injected.dockerfile + +PROJECT_ROOT=`git rev-parse --show-toplevel` + +export BINARY=polkadot,polkadot-execute-worker,polkadot-prepare-worker +export ARTIFACTS_FOLDER=$1 + +$PROJECT_ROOT/docker/scripts/build-injected.sh diff --git a/docker/scripts/polkadot/test-build.sh b/docker/scripts/polkadot/test-build.sh new file mode 100755 index 000000000000..d2d904561cb5 --- /dev/null +++ b/docker/scripts/polkadot/test-build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +TMP=$(mktemp -d) +ENGINE=${ENGINE:-podman} + +# You need to build an injected image first + +# Fetch some binaries +$ENGINE run --user root --rm -i \ + -v "$TMP:/export" \ + --entrypoint /bin/bash \ + parity/polkadot -c \ + 'cp "$(which polkadot)" /export' + +echo "Checking binaries we got:" +tree $TMP + +./build-injected.sh $TMP diff --git a/docker/scripts/staking-miner/README.md b/docker/scripts/staking-miner/README.md new file mode 100644 index 000000000000..3610e1130316 --- /dev/null +++ b/docker/scripts/staking-miner/README.md @@ -0,0 +1,37 @@ +# staking-miner container image + +## Build using the Builder + +``` +./build.sh +``` + +## Build the injected Image + +You first need a valid Linux binary to inject. Let's assume this binary is located in `BIN_FOLDER`. + +``` +./build-injected.sh "$BIN_FOLDER" +``` + +## Test + +Here is how to test the image. We can generate a valid seed but the staking-miner will quickly notice that our +account is not funded and "does not exist". + +You may pass any ENV supported by the binary and must provide at least a few such as `SEED` and `URI`: +``` +ENV SEED="" +ENV URI="wss://rpc.polkadot.io:443" +ENV RUST_LOG="info" +``` + +``` +export SEED=$(subkey generate -n polkadot --output-type json | jq -r .secretSeed) +podman run --rm -it \ + -e URI="wss://rpc.polkadot.io:443" \ + -e RUST_LOG="info" \ + -e SEED \ + localhost/parity/staking-miner \ + dry-run seq-phragmen +``` diff --git a/docker/scripts/staking-miner/build-injected.sh b/docker/scripts/staking-miner/build-injected.sh new file mode 100755 index 000000000000..efe323b5fed8 --- /dev/null +++ b/docker/scripts/staking-miner/build-injected.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Sample call: +# $0 /path/to/folder_with_staking-miner_binary +# This script replace the former dedicated staking-miner "injected" Dockerfile +# and shows how to use the generic binary_injected.dockerfile + +PROJECT_ROOT=`git rev-parse --show-toplevel` + +export BINARY=staking-miner +export ARTIFACTS_FOLDER=$1 + +$PROJECT_ROOT/docker/scripts/build-injected.sh diff --git a/docker/scripts/staking-miner/build.sh b/docker/scripts/staking-miner/build.sh new file mode 100755 index 000000000000..c2b6ab77e531 --- /dev/null +++ b/docker/scripts/staking-miner/build.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Sample call: +# $0 /path/to/folder_with_staking-miner_binary +# This script replace the former dedicated staking-miner "injected" Dockerfile +# and shows how to use the generic binary_injected.dockerfile + +PROJECT_ROOT=`git rev-parse --show-toplevel` +ENGINE=podman + +echo "Building the staking-miner using the Builder image" +echo "PROJECT_ROOT=$PROJECT_ROOT" +$ENGINE build -t staking-miner -f "${PROJECT_ROOT}/docker/dockerfiles/staking-miner/staking-miner_builder.Dockerfile" "$PROJECT_ROOT" diff --git a/docker/scripts/staking-miner/staking-miner_Dockerfile.README.md b/docker/scripts/staking-miner/staking-miner_Dockerfile.README.md new file mode 100644 index 000000000000..ce424c42f479 --- /dev/null +++ b/docker/scripts/staking-miner/staking-miner_Dockerfile.README.md @@ -0,0 +1,3 @@ +# Staking-miner Docker image + +## [GitHub](https://github.com/paritytech/polkadot/tree/master/utils/staking-miner) diff --git a/docker/scripts/staking-miner/staking-miner_builder.Dockerfile b/docker/scripts/staking-miner/staking-miner_builder.Dockerfile new file mode 100644 index 000000000000..0ae77f36c79d --- /dev/null +++ b/docker/scripts/staking-miner/staking-miner_builder.Dockerfile @@ -0,0 +1,43 @@ +FROM paritytech/ci-linux:production as builder + +# metadata +ARG VCS_REF +ARG BUILD_DATE +ARG IMAGE_NAME="staking-miner" +ARG PROFILE=production + +LABEL description="This is the build stage. Here we create the binary." + +WORKDIR /app +COPY . /app +RUN cargo build --locked --profile $PROFILE --package staking-miner + +# ===== SECOND STAGE ====== + +FROM docker.io/parity/base-bin:latest +LABEL description="This is the 2nd stage: a very small image where we copy the binary." +LABEL io.parity.image.authors="devops-team@parity.io" \ + io.parity.image.vendor="Parity Technologies" \ + io.parity.image.title="${IMAGE_NAME}" \ + io.parity.image.description="${IMAGE_NAME} for substrate based chains" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/${IMAGE_NAME}/${IMAGE_NAME}_builder.Dockerfile" \ + io.parity.image.revision="${VCS_REF}" \ + io.parity.image.created="${BUILD_DATE}" \ + io.parity.image.documentation="https://github.com/paritytech/polkadot/" + +ARG PROFILE=release +COPY --from=builder /app/target/$PROFILE/staking-miner /usr/local/bin + +# show backtraces +ENV RUST_BACKTRACE 1 + +USER parity + +ENV SEED="" +ENV URI="wss://rpc.polkadot.io" +ENV RUST_LOG="info" + +# check if the binary works in this container +RUN /usr/local/bin/staking-miner --version + +ENTRYPOINT [ "/usr/local/bin/staking-miner" ] diff --git a/docker/scripts/staking-miner/test-build.sh b/docker/scripts/staking-miner/test-build.sh new file mode 100755 index 000000000000..0ce74e2df296 --- /dev/null +++ b/docker/scripts/staking-miner/test-build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +TMP=$(mktemp -d) +ENGINE=${ENGINE:-podman} + +# You need to build an injected image first + +# Fetch some binaries +$ENGINE run --user root --rm -i \ + -v "$TMP:/export" \ + --entrypoint /bin/bash \ + parity/staking-miner -c \ + 'cp "$(which staking-miner)" /export' + +echo "Checking binaries we got:" +tree $TMP + +./build-injected.sh $TMP diff --git a/cumulus/docs/container.md b/docs/container.md similarity index 96% rename from cumulus/docs/container.md rename to docs/container.md index ef7c52a44fab..afd3b27957c2 100644 --- a/cumulus/docs/container.md +++ b/docs/container.md @@ -52,7 +52,7 @@ anyone to get a working container image without requiring any of the Rust toolch ```bash docker build \ --tag $OWNER/$IMAGE_NAME \ - --file ./docker/polkadot-parachain_builder.Containerfile . + --file ./docker/dockerfiles/polkadot-parachain/polkadot-parachain_builder.Containerfile . ``` You may then run your new container: diff --git a/polkadot/doc/docker.md b/docs/docker.md similarity index 98% rename from polkadot/doc/docker.md rename to docs/docker.md index dc679908ec61..53619ca1a971 100644 --- a/polkadot/doc/docker.md +++ b/docs/docker.md @@ -144,7 +144,7 @@ There are 3 options to build a Polkadot container image: To get up and running with the smallest footprint on your system, you may use an existing Polkadot Container image. You may also build a Polkadot container image yourself (it takes a while...) using the container specs -`scripts/ci/dockerfiles/polkadot/polkadot_builder.Dockerfile`. +`docker/dockerfiles/polkadot/polkadot_builder.Dockerfile`. ### Debian injected diff --git a/polkadot/.github/workflows/release-40_publish-rc-image.yml b/polkadot/.github/workflows/release-40_publish-rc-image.yml deleted file mode 100644 index 3d91c5b8c682..000000000000 --- a/polkadot/.github/workflows/release-40_publish-rc-image.yml +++ /dev/null @@ -1,132 +0,0 @@ -name: Release - Publish RC Container image -# see https://github.com/paritytech/release-engineering/issues/97#issuecomment-1651372277 - -on: - workflow_dispatch: - inputs: - release_id: - description: | - Release ID. - You can find it using the command: - curl -s \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" https://api.github.com/repos/$OWNER/$REPO/releases | \ - jq '.[] | { name: .name, id: .id }' - required: true - type: string - registry: - description: "Container registry" - required: true - type: string - default: docker.io - owner: - description: Owner of the container image repo - required: true - type: string - default: parity - -env: - RELEASE_ID: ${{ inputs.release_id }} - ENGINE: docker - REGISTRY: ${{ inputs.registry }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DOCKER_OWNER: ${{ inputs.owner || github.repository_owner }} - REPO: ${{ github.repository }} - -jobs: - fetch-artifacts: - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Fetch all artifacts - run: | - . ./scripts/ci/common/lib.sh - fetch_release_artifacts - - - name: Cache the artifacts - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - key: artifacts-${{ github.sha }} - path: | - ./release-artifacts/**/* - - build-container: - runs-on: ubuntu-latest - needs: fetch-artifacts - - strategy: - matrix: - binary: ["polkadot", "staking-miner"] - - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Get artifacts from cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - key: artifacts-${{ github.sha }} - fail-on-cache-miss: true - path: | - ./release-artifacts/**/* - - - name: Check sha256 ${{ matrix.binary }} - working-directory: ./release-artifacts - run: | - . ../scripts/ci/common/lib.sh - - echo "Checking binary ${{ matrix.binary }}" - check_sha256 ${{ matrix.binary }} && echo "OK" || echo "ERR" - - - name: Check GPG ${{ matrix.binary }} - working-directory: ./release-artifacts - run: | - . ../scripts/ci/common/lib.sh - import_gpg_keys - check_gpg ${{ matrix.binary }} - - - name: Fetch commit and tag - id: fetch_refs - run: | - release=release-${{ inputs.release_id }} && \ - echo "release=${release}" >> $GITHUB_OUTPUT - - commit=$(git rev-parse --short HEAD) && \ - echo "commit=${commit}" >> $GITHUB_OUTPUT - - tag=$(git name-rev --tags --name-only $(git rev-parse HEAD)) && \ - [ "${tag}" != "undefined" ] && echo "tag=${tag}" >> $GITHUB_OUTPUT || \ - echo "No tag, doing without" - - - name: Build Injected Container image for ${{ matrix.binary }} - env: - BIN_FOLDER: ./release-artifacts - BINARY: ${{ matrix.binary }} - TAGS: ${{join(steps.fetch_refs.outputs.*, ',')}} - run: | - echo "Building container for ${{ matrix.binary }}" - ./scripts/ci/dockerfiles/build-injected.sh - - - name: Login to Dockerhub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Push Container image for ${{ matrix.binary }} - id: docker_push - env: - BINARY: ${{ matrix.binary }} - run: | - $ENGINE images | grep ${BINARY} - $ENGINE push --all-tags ${REGISTRY}/${DOCKER_OWNER}/${BINARY} - - - name: Check version for the published image for ${{ matrix.binary }} - env: - BINARY: ${{ matrix.binary }} - RELEASE_TAG: ${{ steps.fetch_refs.outputs.release }} - run: | - echo "Checking tag ${RELEASE_TAG} for image ${REGISTRY}/${DOCKER_OWNER}/${BINARY}" - $ENGINE run -i ${REGISTRY}/${DOCKER_OWNER}/${BINARY}:${RELEASE_TAG} --version diff --git a/polkadot/.github/workflows/release-51_publish-docker-manual.yml b/polkadot/.github/workflows/release-51_publish-docker-manual.yml deleted file mode 100644 index 919769f8700d..000000000000 --- a/polkadot/.github/workflows/release-51_publish-docker-manual.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Release - Publish Docker image (manual dispatch) - -on: - workflow_dispatch: - inputs: - version: - description: version to build/release - default: v0.9.18 - required: true - date: - description: release date of version - default: "2022-02-23T19:11:58Z" - required: true - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@95cb08cb2672c73d4ffd2f422e6d11953d2a9c70 # v2.1.0 - - name: Cache Docker layers - uses: actions/cache@v3 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- - - name: Login to Dockerhub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push - id: docker_build - uses: docker/build-push-action@v4 - with: - push: true - file: scripts/ci/dockerfiles/polkadot/polkadot_injected_debian.Dockerfile - tags: | - parity/polkadot:latest - parity/polkadot:${{ github.event.inputs.version }} - build-args: | - POLKADOT_VERSION=${{ github.event.inputs.version }} - VCS_REF=${{ github.ref }} - BUILD_DATE=${{ github.event.inputs.date }} - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache - - name: Image digest - run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/polkadot/utils/staking-miner/README.md b/polkadot/utils/staking-miner/README.md index 8fec746e6eea..90a00eeac089 100644 --- a/polkadot/utils/staking-miner/README.md +++ b/polkadot/utils/staking-miner/README.md @@ -51,7 +51,7 @@ to be installed. The trade-off however is that it takes a little longer to build tasks. You may build the multi-stage image the root of the Polkadot repository with: ``` TODO: UPDATE THAT -docker build -t staking-miner -f scripts/ci/dockerfiles/staking-miner/staking-miner_builder.Dockerfile . +docker build -t staking-miner -f docker/dockerfiles/staking-miner/staking-miner_builder.Dockerfile . ``` ### Running From 2f31a4c0e989c907ef0c96932605455482d13c94 Mon Sep 17 00:00:00 2001 From: eskimor Date: Wed, 6 Sep 2023 18:19:21 +0200 Subject: [PATCH 040/103] Fix nothing scheduled on session boundary (#1403) * Fix scheduled state at session boundaries. * Cleanup + better docs. * More cleanup and fixes. * Remove 12s hack. * Add dep. * Make clippy happy --------- Co-authored-by: eskimor --- Cargo.lock | 1 + polkadot/primitives/src/lib.rs | 4 +- polkadot/primitives/src/v5/mod.rs | 54 ---- polkadot/runtime/parachains/Cargo.toml | 1 + polkadot/runtime/parachains/src/assigner.rs | 4 +- .../parachains/src/assigner_on_demand/mod.rs | 5 +- .../src/assigner_on_demand/tests.rs | 6 +- .../parachains/src/assigner_parachains.rs | 6 +- polkadot/runtime/parachains/src/builder.rs | 14 +- .../runtime/parachains/src/configuration.rs | 17 +- .../runtime/parachains/src/inclusion/mod.rs | 208 ++++++------- .../runtime/parachains/src/inclusion/tests.rs | 129 +++----- .../parachains/src/paras_inherent/mod.rs | 32 +- .../parachains/src/paras_inherent/tests.rs | 22 +- .../parachains/src/runtime_api_impl/v5.rs | 66 ++-- polkadot/runtime/parachains/src/scheduler.rs | 281 +++++++++++------- .../parachains/src/scheduler/common.rs | 50 +--- .../parachains/src/scheduler/migration.rs | 1 - .../runtime/parachains/src/scheduler/tests.rs | 237 ++++++--------- 19 files changed, 492 insertions(+), 646 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d08c175bde5..2fff57879891 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12792,6 +12792,7 @@ dependencies = [ "pallet-timestamp", "pallet-vesting", "parity-scale-codec", + "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-primitives-test-helpers", diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index 729908cc12ba..9121b3790858 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -41,8 +41,8 @@ pub use v5::{ BackedCandidate, Balance, BlakeTwo256, Block, BlockId, BlockNumber, CandidateCommitments, CandidateDescriptor, CandidateEvent, CandidateHash, CandidateIndex, CandidateReceipt, CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet, CollatorId, CollatorSignature, - CommittedCandidateReceipt, CompactStatement, ConsensusLog, CoreIndex, CoreOccupied, CoreState, - DisputeState, DisputeStatement, DisputeStatementSet, DownwardMessage, EncodeAs, ExecutorParam, + CommittedCandidateReceipt, CompactStatement, ConsensusLog, CoreIndex, CoreState, DisputeState, + DisputeStatement, DisputeStatementSet, DownwardMessage, EncodeAs, ExecutorParam, ExecutorParams, ExecutorParamsHash, ExplicitDisputeStatement, GroupIndex, GroupRotationInfo, Hash, HashT, HeadData, Header, HrmpChannelId, Id, InboundDownwardMessage, InboundHrmpMessage, IndexedVec, InherentData, InvalidDisputeStatementKind, Moment, MultiDisputeStatementSet, Nonce, diff --git a/polkadot/primitives/src/v5/mod.rs b/polkadot/primitives/src/v5/mod.rs index eed4cc2b36ba..30782f95611f 100644 --- a/polkadot/primitives/src/v5/mod.rs +++ b/polkadot/primitives/src/v5/mod.rs @@ -830,60 +830,6 @@ pub struct ParathreadEntry { pub retries: u32, } -/// An assignment for a parachain scheduled to be backed and included in a relay chain block. -#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebug)] -pub struct Assignment { - /// Assignment's ParaId - pub para_id: Id, -} - -impl Assignment { - /// Create a new `Assignment`. - pub fn new(para_id: Id) -> Self { - Self { para_id } - } -} - -/// An entry tracking a paras -#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, RuntimeDebug)] -pub struct ParasEntry { - /// The `Assignment` - pub assignment: Assignment, - /// The number of times the entry has timed out in availability. - pub availability_timeouts: u32, - /// The block height where this entry becomes invalid. - pub ttl: N, -} - -impl ParasEntry { - /// Return `Id` from the underlying `Assignment`. - pub fn para_id(&self) -> Id { - self.assignment.para_id - } - - /// Create a new `ParasEntry`. - pub fn new(assignment: Assignment, now: N) -> Self { - ParasEntry { assignment, availability_timeouts: 0, ttl: now } - } -} - -/// What is occupying a specific availability core. -#[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq))] -pub enum CoreOccupied { - /// The core is not occupied. - Free, - /// A paras. - Paras(ParasEntry), -} - -impl CoreOccupied { - /// Is core free? - pub fn is_free(&self) -> bool { - matches!(self, Self::Free) - } -} - /// A helper data-type for tracking validator-group rotations. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] #[cfg_attr(feature = "std", derive(PartialEq))] diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 0e2f6aa1aa24..77eba0bc10ba 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -50,6 +50,7 @@ rand_chacha = { version = "0.3.1", default-features = false } static_assertions = { version = "1.1.0", optional = true } polkadot-parachain-primitives = { path = "../../parachain", default-features = false } polkadot-runtime-metrics = { path = "../metrics", default-features = false} +polkadot-core-primitives = { path = "../../core-primitives", default-features = false } [dev-dependencies] futures = "0.3.21" diff --git a/polkadot/runtime/parachains/src/assigner.rs b/polkadot/runtime/parachains/src/assigner.rs index 55434da11f30..b21e857a4713 100644 --- a/polkadot/runtime/parachains/src/assigner.rs +++ b/polkadot/runtime/parachains/src/assigner.rs @@ -17,11 +17,11 @@ //! The Polkadot multiplexing assignment provider. //! Provides blockspace assignments for both bulk and on demand parachains. use frame_system::pallet_prelude::BlockNumberFor; -use primitives::{v5::Assignment, CoreIndex, Id as ParaId}; +use primitives::{CoreIndex, Id as ParaId}; use crate::{ configuration, paras, - scheduler::common::{AssignmentProvider, AssignmentProviderConfig}, + scheduler::common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, }; pub use pallet::*; diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs index 0c9813d144f3..75c29bd6fbe4 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs @@ -34,7 +34,7 @@ mod tests; use crate::{ configuration, paras, - scheduler::common::{AssignmentProvider, AssignmentProviderConfig}, + scheduler::common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, }; use frame_support::{ @@ -46,7 +46,7 @@ use frame_support::{ }, }; use frame_system::pallet_prelude::*; -use primitives::{v5::Assignment, CoreIndex, Id as ParaId}; +use primitives::{CoreIndex, Id as ParaId}; use sp_runtime::{ traits::{One, SaturatedConversion}, FixedPointNumber, FixedPointOperand, FixedU128, Perbill, Saturating, @@ -606,7 +606,6 @@ impl AssignmentProvider> for Pallet { fn get_provider_config(_core_idx: CoreIndex) -> AssignmentProviderConfig> { let config = >::config(); AssignmentProviderConfig { - availability_period: config.paras_availability_period, max_availability_timeouts: config.on_demand_retries, ttl: config.on_demand_ttl, } diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs b/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs index 8041179cd90c..fe9a4e52bd07 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs @@ -24,13 +24,11 @@ use crate::{ System, Test, }, paras::{ParaGenesisArgs, ParaKind}, + scheduler::common::Assignment, }; use frame_support::{assert_noop, assert_ok, error::BadOrigin}; use pallet_balances::Error as BalancesError; -use primitives::{ - v5::{Assignment, ValidationCode}, - BlockNumber, SessionIndex, -}; +use primitives::{v5::ValidationCode, BlockNumber, SessionIndex}; use sp_std::collections::btree_map::BTreeMap; fn schedule_blank_para(id: ParaId, parakind: ParaKind) { diff --git a/polkadot/runtime/parachains/src/assigner_parachains.rs b/polkadot/runtime/parachains/src/assigner_parachains.rs index 9a6b970597d5..d605d8660515 100644 --- a/polkadot/runtime/parachains/src/assigner_parachains.rs +++ b/polkadot/runtime/parachains/src/assigner_parachains.rs @@ -19,11 +19,11 @@ use crate::{ configuration, paras, - scheduler::common::{AssignmentProvider, AssignmentProviderConfig}, + scheduler::common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, }; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; -use primitives::{v5::Assignment, CoreIndex, Id as ParaId}; +use primitives::{CoreIndex, Id as ParaId}; #[frame_support::pallet] pub mod pallet { @@ -57,9 +57,7 @@ impl AssignmentProvider> for Pallet { fn push_assignment_for_core(_: CoreIndex, _: Assignment) {} fn get_provider_config(_core_idx: CoreIndex) -> AssignmentProviderConfig> { - let config = >::config(); AssignmentProviderConfig { - availability_period: config.paras_availability_period, // The next assignment already goes to the same [`ParaId`], no timeout tracking needed. max_availability_timeouts: 0, // The next assignment already goes to the same [`ParaId`], this can be any number diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 4921af5bedda..dced24df0aec 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -18,18 +18,20 @@ use crate::{ configuration, inclusion, initializer, paras, paras::ParaKind, paras_inherent, - scheduler::{self, common::AssignmentProviderConfig}, + scheduler::{ + self, + common::{Assignment, AssignmentProviderConfig}, + CoreOccupied, ParasEntry, + }, session_info, shared, }; use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use primitives::{ - collator_signature_payload, - v5::{Assignment, ParasEntry}, - AvailabilityBitfield, BackedCandidate, CandidateCommitments, CandidateDescriptor, - CandidateHash, CollatorId, CollatorSignature, CommittedCandidateReceipt, CompactStatement, - CoreIndex, CoreOccupied, DisputeStatement, DisputeStatementSet, GroupIndex, HeadData, + collator_signature_payload, AvailabilityBitfield, BackedCandidate, CandidateCommitments, + CandidateDescriptor, CandidateHash, CollatorId, CollatorSignature, CommittedCandidateReceipt, + CompactStatement, CoreIndex, DisputeStatement, DisputeStatementSet, GroupIndex, HeadData, Id as ParaId, IndexedVec, InherentData as ParachainsInherentData, InvalidDisputeStatementKind, PersistedValidationData, SessionIndex, SigningContext, UncheckedSigned, ValidDisputeStatementKind, ValidationCode, ValidatorId, ValidatorIndex, ValidityAttestation, diff --git a/polkadot/runtime/parachains/src/configuration.rs b/polkadot/runtime/parachains/src/configuration.rs index 0c66bb5bdf96..33039cd08ca4 100644 --- a/polkadot/runtime/parachains/src/configuration.rs +++ b/polkadot/runtime/parachains/src/configuration.rs @@ -190,11 +190,20 @@ pub struct HostConfiguration { /// /// Must be non-zero. pub group_rotation_frequency: BlockNumber, - /// The availability period, in blocks. This is the amount of blocks - /// after inclusion that validators have to make the block available and signal its - /// availability to the chain. + /// The minimum availability period, in blocks. /// - /// Must be at least 1. + /// This is the minimum amount of blocks after a core became occupied that validators have time + /// to make the block available. + /// + /// This value only has effect on group rotations. If backers backed something at the end of + /// their rotation, the occupied core affects the backing group that comes afterwards. We limit + /// the effect one backing group can have on the next to `paras_availability_period` blocks. + /// + /// Within a group rotation there is no timeout as backers are only affecting themselves. + /// + /// Must be at least 1. With a value of 1, the previous group will not be able to negatively + /// affect the following group at the expense of a tight availability timeline at group + /// rotation boundaries. pub paras_availability_period: BlockNumber, /// The amount of blocks ahead to schedule paras. pub scheduling_lookahead: u32, diff --git a/polkadot/runtime/parachains/src/inclusion/mod.rs b/polkadot/runtime/parachains/src/inclusion/mod.rs index a9ee2d1b9612..bb16c804150d 100644 --- a/polkadot/runtime/parachains/src/inclusion/mod.rs +++ b/polkadot/runtime/parachains/src/inclusion/mod.rs @@ -22,7 +22,7 @@ use crate::{ configuration::{self, HostConfiguration}, disputes, dmp, hrmp, paras, - scheduler::{self, common::CoreAssignment}, + scheduler::{self, AvailabilityTimeoutStatus}, shared::{self, AllowedRelayParentsTracker}, }; use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; @@ -46,7 +46,10 @@ use scale_info::TypeInfo; use sp_runtime::{traits::One, DispatchError, SaturatedConversion, Saturating}; #[cfg(feature = "std")] use sp_std::fmt; -use sp_std::{collections::btree_set::BTreeSet, prelude::*}; +use sp_std::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + prelude::*, +}; pub use pallet::*; @@ -597,7 +600,7 @@ impl Pallet { pub(crate) fn process_candidates( allowed_relay_parents: &AllowedRelayParentsTracker>, candidates: Vec>, - scheduled: Vec>>, + scheduled: &BTreeMap, group_validators: GV, ) -> Result, DispatchError> where @@ -620,20 +623,18 @@ impl Pallet { // Do all checks before writing storage. let core_indices_and_backers = { - let mut skip = 0; let mut core_indices_and_backers = Vec::with_capacity(candidates.len()); let mut last_core = None; - let mut check_assignment_in_order = - |assignment: &CoreAssignment>| -> DispatchResult { - ensure!( - last_core.map_or(true, |core| assignment.core > core), - Error::::ScheduledOutOfOrder, - ); + let mut check_assignment_in_order = |core_idx| -> DispatchResult { + ensure!( + last_core.map_or(true, |core| core_idx > core), + Error::::ScheduledOutOfOrder, + ); - last_core = Some(assignment.core); - Ok(()) - }; + last_core = Some(core_idx); + Ok(()) + }; // We combine an outer loop over candidates with an inner loop over the scheduled, // where each iteration of the outer loop picks up at the position @@ -645,9 +646,7 @@ impl Pallet { // // In the meantime, we do certain sanity checks on the candidates and on the scheduled // list. - 'next_backed_candidate: for (candidate_idx, backed_candidate) in - candidates.iter().enumerate() - { + for (candidate_idx, backed_candidate) in candidates.iter().enumerate() { let relay_parent_hash = backed_candidate.descriptor().relay_parent; let para_id = backed_candidate.descriptor().para_id; @@ -681,108 +680,89 @@ impl Pallet { let para_id = backed_candidate.descriptor().para_id; let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()]; - for (i, core_assignment) in scheduled[skip..].iter().enumerate() { - check_assignment_in_order(core_assignment)?; + let core_idx = *scheduled.get(¶_id).ok_or(Error::::UnscheduledCandidate)?; + check_assignment_in_order(core_idx)?; + ensure!( + >::get(¶_id).is_none() && + >::get(¶_id).is_none(), + Error::::CandidateScheduledBeforeParaFree, + ); - if para_id == core_assignment.paras_entry.para_id() { - ensure!( - >::get(¶_id).is_none() && - >::get(¶_id).is_none(), - Error::::CandidateScheduledBeforeParaFree, - ); + // The candidate based upon relay parent `N` should be backed by a group + // assigned to core at block `N + 1`. Thus, `relay_parent_number + 1` + // will always land in the current session. + let group_idx = >::group_assigned_to_core( + core_idx, + relay_parent_number + One::one(), + ) + .ok_or_else(|| { + log::warn!( + target: LOG_TARGET, + "Failed to compute group index for candidate {}", + candidate_idx + ); + Error::::InvalidAssignment + })?; + let group_vals = + group_validators(group_idx).ok_or_else(|| Error::::InvalidGroupIndex)?; - // account for already skipped, and then skip this one. - skip = i + skip + 1; - - // The candidate based upon relay parent `N` should be backed by a group - // assigned to core at block `N + 1`. Thus, `relay_parent_number + 1` - // will always land in the current session. - let group_idx = >::group_assigned_to_core( - core_assignment.core, - relay_parent_number + One::one(), - ) - .ok_or_else(|| { - log::warn!( - target: LOG_TARGET, - "Failed to compute group index for candidate {}", - candidate_idx - ); - Error::::InvalidAssignment - })?; - let group_vals = group_validators(group_idx) - .ok_or_else(|| Error::::InvalidGroupIndex)?; - - // check the signatures in the backing and that it is a majority. - { - let maybe_amount_validated = primitives::check_candidate_backing( - &backed_candidate, - &signing_context, - group_vals.len(), - |intra_group_vi| { - group_vals - .get(intra_group_vi) - .and_then(|vi| validators.get(vi.0 as usize)) - .map(|v| v.clone()) - }, - ); - - match maybe_amount_validated { - Ok(amount_validated) => ensure!( - amount_validated >= - effective_minimum_backing_votes( - group_vals.len(), - minimum_backing_votes - ), - Error::::InsufficientBacking, + // check the signatures in the backing and that it is a majority. + { + let maybe_amount_validated = primitives::check_candidate_backing( + &backed_candidate, + &signing_context, + group_vals.len(), + |intra_group_vi| { + group_vals + .get(intra_group_vi) + .and_then(|vi| validators.get(vi.0 as usize)) + .map(|v| v.clone()) + }, + ); + + match maybe_amount_validated { + Ok(amount_validated) => ensure!( + amount_validated >= + effective_minimum_backing_votes( + group_vals.len(), + minimum_backing_votes ), - Err(()) => { - Err(Error::::InvalidBacking)?; - }, - } - - let mut backer_idx_and_attestation = - Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity( - backed_candidate.validator_indices.count_ones(), - ); - let candidate_receipt = backed_candidate.receipt(); - - for ((bit_idx, _), attestation) in backed_candidate - .validator_indices - .iter() - .enumerate() - .filter(|(_, signed)| **signed) - .zip(backed_candidate.validity_votes.iter().cloned()) - { - let val_idx = group_vals - .get(bit_idx) - .expect("this query succeeded above; qed"); - backer_idx_and_attestation.push((*val_idx, attestation)); - - backers.set(val_idx.0 as _, true); - } - candidate_receipt_with_backing_validator_indices - .push((candidate_receipt, backer_idx_and_attestation)); - } - - core_indices_and_backers.push(( - (core_assignment.core, core_assignment.paras_entry.para_id()), - backers, - group_idx, - relay_parent_number, - )); - continue 'next_backed_candidate + Error::::InsufficientBacking, + ), + Err(()) => { + Err(Error::::InvalidBacking)?; + }, } - } - // end of loop reached means that the candidate didn't appear in the non-traversed - // section of the `scheduled` slice. either it was not scheduled or didn't appear in - // `candidates` in the correct order. - ensure!(false, Error::::UnscheduledCandidate); - } + let mut backer_idx_and_attestation = + Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity( + backed_candidate.validator_indices.count_ones(), + ); + let candidate_receipt = backed_candidate.receipt(); + + for ((bit_idx, _), attestation) in backed_candidate + .validator_indices + .iter() + .enumerate() + .filter(|(_, signed)| **signed) + .zip(backed_candidate.validity_votes.iter().cloned()) + { + let val_idx = + group_vals.get(bit_idx).expect("this query succeeded above; qed"); + backer_idx_and_attestation.push((*val_idx, attestation)); + + backers.set(val_idx.0 as _, true); + } + candidate_receipt_with_backing_validator_indices + .push((candidate_receipt, backer_idx_and_attestation)); + } - // check remainder of scheduled cores, if any. - for assignment in scheduled[skip..].iter() { - check_assignment_in_order(assignment)?; + core_indices_and_backers.push(( + (core_idx, para_id), + backers, + group_idx, + relay_parent_number, + )); } core_indices_and_backers @@ -1043,13 +1023,13 @@ impl Pallet { /// /// Returns a vector of cleaned-up core IDs. pub(crate) fn collect_pending( - pred: impl Fn(CoreIndex, BlockNumberFor) -> bool, + pred: impl Fn(BlockNumberFor) -> AvailabilityTimeoutStatus>, ) -> Vec { let mut cleaned_up_ids = Vec::new(); let mut cleaned_up_cores = Vec::new(); for (para_id, pending_record) in >::iter() { - if pred(pending_record.core, pending_record.backed_in_number) { + if pred(pending_record.backed_in_number).timed_out { cleaned_up_ids.push(para_id); cleaned_up_cores.push(pending_record.core); } diff --git a/polkadot/runtime/parachains/src/inclusion/tests.rs b/polkadot/runtime/parachains/src/inclusion/tests.rs index 70c5e959038a..7677108d73de 100644 --- a/polkadot/runtime/parachains/src/inclusion/tests.rs +++ b/polkadot/runtime/parachains/src/inclusion/tests.rs @@ -36,7 +36,6 @@ use frame_support::assert_noop; use keyring::Sr25519Keyring; use parity_scale_codec::DecodeAll; use primitives::{ - v5::{Assignment, ParasEntry}, BlockNumber, CandidateCommitments, CandidateDescriptor, CollatorId, CompactStatement as Statement, Hash, SignedAvailabilityBitfield, SignedStatement, ValidationCode, ValidatorId, ValidityAttestation, PARACHAIN_KEY_TYPE_ID, @@ -380,7 +379,9 @@ fn collect_pending_cleans_up_pending() { (chain_b, ParaKind::Parachain), (thread_a, ParaKind::Parathread), ]; - new_test_ext(genesis_config(paras)).execute_with(|| { + let mut config = genesis_config(paras); + config.configuration.config.group_rotation_frequency = 3; + new_test_ext(config).execute_with(|| { let default_candidate = TestCandidateBuilder::default().build(); >::insert( chain_a, @@ -408,7 +409,7 @@ fn collect_pending_cleans_up_pending() { descriptor: default_candidate.descriptor, availability_votes: default_availability_votes(), relay_parent_number: 0, - backed_in_number: 0, + backed_in_number: 5, backers: default_backing_bitfield(), backing_group: GroupIndex::from(1), }, @@ -422,7 +423,7 @@ fn collect_pending_cleans_up_pending() { assert!(>::get(&chain_a).is_some()); assert!(>::get(&chain_b).is_some()); - ParaInclusion::collect_pending(|core, _since| core == CoreIndex::from(0)); + ParaInclusion::collect_pending(Scheduler::availability_timeout_predicate()); assert!(>::get(&chain_a).is_none()); assert!(>::get(&chain_b).is_some()); @@ -910,23 +911,12 @@ fn candidate_checks() { ]; Scheduler::set_validator_groups(validator_groups); - let entry_ttl = 10_000; let thread_collator: CollatorId = Sr25519Keyring::Two.public().into(); - let chain_a_assignment = CoreAssignment { - core: CoreIndex::from(0), - paras_entry: ParasEntry::new(Assignment::new(chain_a), entry_ttl), - }; - - let chain_b_assignment = CoreAssignment { - core: CoreIndex::from(1), - paras_entry: ParasEntry::new(Assignment::new(chain_b), entry_ttl), - }; + let chain_a_assignment = (chain_a, CoreIndex::from(0)); - let thread_a_assignment = CoreAssignment { - core: CoreIndex::from(2), - paras_entry: ParasEntry::new(Assignment::new(thread_a), entry_ttl), - }; + let chain_b_assignment = (chain_b, CoreIndex::from(1)); + let thread_a_assignment = (thread_a, CoreIndex::from(2)); let allowed_relay_parents = default_allowed_relay_parent_tracker(); // unscheduled candidate. @@ -955,7 +945,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_b_assignment.clone()], + &[chain_b_assignment].into_iter().collect(), &group_validators, ), Error::::UnscheduledCandidate @@ -1010,10 +1000,10 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed_b, backed_a], - vec![chain_a_assignment.clone(), chain_b_assignment.clone()], + &[chain_a_assignment, chain_b_assignment].into_iter().collect(), &group_validators, ), - Error::::UnscheduledCandidate + Error::::ScheduledOutOfOrder ); } @@ -1043,7 +1033,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Error::::InsufficientBacking @@ -1100,7 +1090,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed_b, backed_a], - vec![chain_a_assignment.clone(), chain_b_assignment.clone()], + &[chain_a_assignment, chain_b_assignment].into_iter().collect(), &group_validators, ), Error::::DisallowedRelayParent @@ -1138,7 +1128,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![thread_a_assignment.clone()], + &[thread_a_assignment].into_iter().collect(), &group_validators, ), Error::::NotCollatorSigned @@ -1188,7 +1178,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Error::::CandidateScheduledBeforeParaFree @@ -1228,7 +1218,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Error::::CandidateScheduledBeforeParaFree @@ -1272,7 +1262,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Error::::PrematureCodeUpgrade @@ -1306,7 +1296,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Err(Error::::ValidationDataHashMismatch.into()), @@ -1341,7 +1331,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Error::::InvalidValidationCodeHash @@ -1376,7 +1366,7 @@ fn candidate_checks() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ), Error::::ParaHeadMismatch @@ -1446,21 +1436,9 @@ fn backing_works() { let allowed_relay_parents = default_allowed_relay_parent_tracker(); - let entry_ttl = 10_000; - let chain_a_assignment = CoreAssignment { - core: CoreIndex::from(0), - paras_entry: ParasEntry::new(Assignment::new(chain_a), entry_ttl), - }; - - let chain_b_assignment = CoreAssignment { - core: CoreIndex::from(1), - paras_entry: ParasEntry::new(Assignment::new(chain_b), entry_ttl), - }; - - let thread_a_assignment = CoreAssignment { - core: CoreIndex::from(2), - paras_entry: ParasEntry::new(Assignment::new(thread_a), entry_ttl), - }; + let chain_a_assignment = (chain_a, CoreIndex::from(0)); + let chain_b_assignment = (chain_b, CoreIndex::from(1)); + let thread_a_assignment = (thread_a, CoreIndex::from(2)); let mut candidate_a = TestCandidateBuilder { para_id: chain_a, @@ -1548,11 +1526,9 @@ fn backing_works() { } = ParaInclusion::process_candidates( &allowed_relay_parents, backed_candidates.clone(), - vec![ - chain_a_assignment.clone(), - chain_b_assignment.clone(), - thread_a_assignment.clone(), - ], + &[chain_a_assignment, chain_b_assignment, thread_a_assignment] + .into_iter() + .collect(), &group_validators, ) .expect("candidates scheduled, in order, and backed"); @@ -1738,12 +1714,7 @@ fn can_include_candidate_with_ok_code_upgrade() { Scheduler::set_validator_groups(validator_groups); let allowed_relay_parents = default_allowed_relay_parent_tracker(); - let entry_ttl = 10_000; - let chain_a_assignment = CoreAssignment { - core: CoreIndex::from(0), - paras_entry: ParasEntry::new(Assignment::new(chain_a), entry_ttl), - }; - + let chain_a_assignment = (chain_a, CoreIndex::from(0)); let mut candidate_a = TestCandidateBuilder { para_id: chain_a, relay_parent: System::parent_hash(), @@ -1769,7 +1740,7 @@ fn can_include_candidate_with_ok_code_upgrade() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed_a], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ) .expect("candidates scheduled, in order, and backed"); @@ -1895,28 +1866,10 @@ fn check_allowed_relay_parents() { max_ancestry_len, ); - let chain_a_assignment = CoreAssignment { - core: CoreIndex::from(0), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_a }, - availability_timeouts: 0, - ttl: 5, - }, - }; + let chain_a_assignment = (chain_a, CoreIndex::from(0)); - let chain_b_assignment = CoreAssignment { - core: CoreIndex::from(1), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_b }, - availability_timeouts: 0, - ttl: 5, - }, - }; - - let thread_a_assignment = CoreAssignment { - core: CoreIndex::from(2), - paras_entry: ParasEntry::new(Assignment::new(thread_a), 5), - }; + let chain_b_assignment = (chain_b, CoreIndex::from(1)); + let thread_a_assignment = (thread_a, CoreIndex::from(2)); let mut candidate_a = TestCandidateBuilder { para_id: chain_a, @@ -1998,11 +1951,9 @@ fn check_allowed_relay_parents() { ParaInclusion::process_candidates( &allowed_relay_parents, backed_candidates.clone(), - vec![ - chain_a_assignment.clone(), - chain_b_assignment.clone(), - thread_a_assignment.clone(), - ], + &[chain_a_assignment, chain_b_assignment, thread_a_assignment] + .into_iter() + .collect(), &group_validators, ) .expect("candidates scheduled, in order, and backed"); @@ -2212,15 +2163,7 @@ fn para_upgrade_delay_scheduled_from_inclusion() { let allowed_relay_parents = default_allowed_relay_parent_tracker(); - let chain_a_assignment = CoreAssignment { - core: CoreIndex::from(0), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_a }, - availability_timeouts: 0, - ttl: 5, - }, - }; - + let chain_a_assignment = (chain_a, CoreIndex::from(0)); let mut candidate_a = TestCandidateBuilder { para_id: chain_a, relay_parent: System::parent_hash(), @@ -2246,7 +2189,7 @@ fn para_upgrade_delay_scheduled_from_inclusion() { ParaInclusion::process_candidates( &allowed_relay_parents, vec![backed_a], - vec![chain_a_assignment.clone()], + &[chain_a_assignment].into_iter().collect(), &group_validators, ) .expect("candidates scheduled, in order, and backed"); diff --git a/polkadot/runtime/parachains/src/paras_inherent/mod.rs b/polkadot/runtime/parachains/src/paras_inherent/mod.rs index 6244f44e434b..8e918d35d5ff 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/mod.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/mod.rs @@ -29,10 +29,7 @@ use crate::{ initializer, metrics::METRICS, paras, - scheduler::{ - self, - common::{CoreAssignment, FreedReason}, - }, + scheduler::{self, FreedReason}, shared, ParaId, }; use bitvec::prelude::BitVec; @@ -245,8 +242,8 @@ pub mod pallet { T: Config, { // Handle timeouts for any availability core work. - let availability_pred = >::availability_timeout_predicate(); - let freed_timeout = if let Some(pred) = availability_pred { + let freed_timeout = if >::availability_timeout_check_required() { + let pred = >::availability_timeout_predicate(); >::collect_pending(pred) } else { Vec::new() @@ -320,7 +317,7 @@ impl Pallet { /// /// When called from `create_inherent` the `context` must be set to /// `ProcessInherentDataContext::ProvideInherent` so it guarantees the invariant that inherent - /// is not overweight. + /// is not overweight. /// It is **mandatory** that calls from `enter` set `context` to /// `ProcessInherentDataContext::Enter` to ensure the weight invariant is checked. /// @@ -583,7 +580,10 @@ impl Pallet { let freed = collect_all_freed_cores::(freed_concluded.iter().cloned()); - let scheduled = >::update_claimqueue(freed, now); + >::update_claimqueue(freed, now); + let scheduled = >::scheduled_paras() + .map(|(core_idx, para_id)| (para_id, core_idx)) + .collect(); METRICS.on_candidates_processed_total(backed_candidates.len() as u64); @@ -608,7 +608,7 @@ impl Pallet { .verify_backed_candidate(&allowed_relay_parents, candidate_idx, backed_candidate) .is_err() }, - &scheduled[..], + &scheduled, ); METRICS.on_candidates_sanitized(backed_candidates.len() as u64); @@ -620,7 +620,7 @@ impl Pallet { } = >::process_candidates( &allowed_relay_parents, backed_candidates.clone(), - scheduled, + &scheduled, >::group_validators, )?; // Note which of the scheduled cores were actually occupied by a backed candidate. @@ -917,7 +917,7 @@ fn sanitize_backed_candidates< >( mut backed_candidates: Vec>, mut candidate_has_concluded_invalid_dispute_or_is_invalid: F, - scheduled: &[CoreAssignment>], + scheduled: &BTreeMap, ) -> Vec> { // Remove any candidates that were concluded invalid. // This does not assume sorting. @@ -925,11 +925,6 @@ fn sanitize_backed_candidates< !candidate_has_concluded_invalid_dispute_or_is_invalid(candidate_idx, backed_candidate) }); - let scheduled_paras_to_core_idx = scheduled - .into_iter() - .map(|core_assignment| (core_assignment.paras_entry.para_id(), core_assignment.core)) - .collect::>(); - // Assure the backed candidate's `ParaId`'s core is free. // This holds under the assumption that `Scheduler::schedule` is called _before_. // We don't check the relay-parent because this is done in the closure when @@ -938,7 +933,7 @@ fn sanitize_backed_candidates< backed_candidates.retain(|backed_candidate| { let desc = backed_candidate.descriptor(); - scheduled_paras_to_core_idx.get(&desc.para_id).is_some() + scheduled.get(&desc.para_id).is_some() }); // Sort the `Vec` last, once there is a guarantee that these @@ -948,8 +943,7 @@ fn sanitize_backed_candidates< // but also allows this to be done in place. backed_candidates.sort_by(|x, y| { // Never panics, since we filtered all panic arguments out in the previous `fn retain`. - scheduled_paras_to_core_idx[&x.descriptor().para_id] - .cmp(&scheduled_paras_to_core_idx[&y.descriptor().para_id]) + scheduled[&x.descriptor().para_id].cmp(&scheduled[&y.descriptor().para_id]) }); backed_candidates diff --git a/polkadot/runtime/parachains/src/paras_inherent/tests.rs b/polkadot/runtime/parachains/src/paras_inherent/tests.rs index ab515cb37565..7c70fcea1943 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/tests.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/tests.rs @@ -963,10 +963,7 @@ mod sanitizers { use crate::mock::Test; use keyring::Sr25519Keyring; - use primitives::{ - v5::{Assignment, ParasEntry}, - PARACHAIN_KEY_TYPE_ID, - }; + use primitives::PARACHAIN_KEY_TYPE_ID; use sc_keystore::LocalKeystore; use sp_keystore::{Keystore, KeystorePtr}; use std::sync::Arc; @@ -1239,21 +1236,10 @@ mod sanitizers { let has_concluded_invalid = |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; - let entry_ttl = 10_000; let scheduled = (0_usize..2) .into_iter() - .map(|idx| { - let core_idx = CoreIndex::from(idx as u32); - let ca = CoreAssignment { - paras_entry: ParasEntry::new( - Assignment::new(ParaId::from(1_u32 + idx as u32)), - entry_ttl, - ), - core: core_idx, - }; - ca - }) - .collect::>(); + .map(|idx| (ParaId::from(1_u32 + idx as u32), CoreIndex::from(idx as u32))) + .collect::>(); let group_validators = |group_index: GroupIndex| { match group_index { @@ -1304,7 +1290,7 @@ mod sanitizers { // nothing is scheduled, so no paraids match, thus all backed candidates are skipped { - let scheduled = &Vec::new(); + let scheduled = &BTreeMap::new(); assert!(sanitize_backed_candidates::( backed_candidates.clone(), has_concluded_invalid, diff --git a/polkadot/runtime/parachains/src/runtime_api_impl/v5.rs b/polkadot/runtime/parachains/src/runtime_api_impl/v5.rs index bac1268f53bd..46a609e0368d 100644 --- a/polkadot/runtime/parachains/src/runtime_api_impl/v5.rs +++ b/polkadot/runtime/parachains/src/runtime_api_impl/v5.rs @@ -18,17 +18,17 @@ //! functions. use crate::{ - configuration, disputes, dmp, hrmp, inclusion, initializer, paras, paras_inherent, scheduler, + disputes, dmp, hrmp, inclusion, initializer, paras, paras_inherent, + scheduler::{self, CoreOccupied}, session_info, shared, }; use frame_system::pallet_prelude::*; use primitives::{ slashing, AuthorityDiscoveryId, CandidateEvent, CandidateHash, CommittedCandidateReceipt, - CoreIndex, CoreOccupied, CoreState, DisputeState, ExecutorParams, GroupIndex, - GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, - OccupiedCore, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, - ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, - ValidatorId, ValidatorIndex, ValidatorSignature, + CoreIndex, CoreState, DisputeState, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, + Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, OccupiedCore, OccupiedCoreAssumption, + PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, + ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }; use sp_runtime::traits::One; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; @@ -52,29 +52,15 @@ pub fn validator_groups( /// Implementation for the `availability_cores` function of the runtime API. pub fn availability_cores() -> Vec>> { let cores = >::availability_cores(); - let config = >::config(); let now = >::block_number() + One::one(); - let rotation_info = >::group_rotation_info(now); - let time_out_at = |backed_in_number, availability_period| { - let time_out_at = backed_in_number + availability_period; - - let current_window = rotation_info.last_rotation_at() + availability_period; - let next_rotation = rotation_info.next_rotation_at(); - - // If we are within `period` blocks of rotation, timeouts are being checked - // actively. We could even time out this block. - if time_out_at < current_window { - time_out_at - } else if time_out_at <= next_rotation { - // Otherwise, it will time out at the sooner of the next rotation - next_rotation - } else { - // or the scheduled time-out. This is by definition within `period` blocks - // of `next_rotation` and is thus a valid timeout block. - time_out_at - } - }; + // This explicit update is only strictly required for session boundaries: + // + // At the end of a session we clear the claim queues: Without this update call, nothing would be + // scheduled to the client. + >::update_claimqueue(Vec::new(), now); + + let time_out_for = >::availability_timeout_predicate(); let group_responsible_for = |backed_in_number, core_index| match >::group_assigned_to_core( @@ -93,7 +79,9 @@ pub fn availability_cores() -> Vec = cores + let scheduled: BTreeMap<_, _> = >::scheduled_paras().collect(); + + cores .into_iter() .enumerate() .map(|(i, core)| match core { @@ -108,7 +96,7 @@ pub fn availability_cores() -> Vec>::next_up_on_time_out(CoreIndex( i as u32, )), @@ -121,19 +109,15 @@ pub fn availability_cores() -> Vec CoreState::Free, + CoreOccupied::Free => { + if let Some(para_id) = scheduled.get(&CoreIndex(i as _)).cloned() { + CoreState::Scheduled(primitives::ScheduledCore { para_id, collator: None }) + } else { + CoreState::Free + } + }, }) - .collect(); - - // This will overwrite only `Free` cores if the scheduler module is working as intended. - for scheduled in >::scheduled_claimqueue() { - core_states[scheduled.core.0 as usize] = CoreState::Scheduled(primitives::ScheduledCore { - para_id: scheduled.paras_entry.para_id(), - collator: None, - }); - } - - core_states + .collect() } /// Returns current block number being processed and the corresponding root hash. diff --git a/polkadot/runtime/parachains/src/scheduler.rs b/polkadot/runtime/parachains/src/scheduler.rs index 577bcd153b5b..60b2a9254600 100644 --- a/polkadot/runtime/parachains/src/scheduler.rs +++ b/polkadot/runtime/parachains/src/scheduler.rs @@ -39,11 +39,11 @@ use crate::{configuration, initializer::SessionChangeNotification, paras}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::BlockNumberFor; +pub use polkadot_core_primitives::v2::BlockNumber; use primitives::{ - v5::ParasEntry, CoreIndex, CoreOccupied, GroupIndex, GroupRotationInfo, Id as ParaId, - ScheduledCore, ValidatorIndex, + CoreIndex, GroupIndex, GroupRotationInfo, Id as ParaId, ScheduledCore, ValidatorIndex, }; -use sp_runtime::traits::{One, Saturating}; +use sp_runtime::traits::One; use sp_std::{ collections::{btree_map::BTreeMap, vec_deque::VecDeque}, prelude::*, @@ -51,7 +51,7 @@ use sp_std::{ pub mod common; -use common::{AssignmentProvider, AssignmentProviderConfig, CoreAssignment, FreedReason}; +use common::{Assignment, AssignmentProvider, AssignmentProviderConfig}; pub use pallet::*; @@ -101,6 +101,36 @@ pub mod pallet { pub(crate) type AvailabilityCores = StorageValue<_, Vec>>, ValueQuery>; + /// Representation of a core in `AvailabilityCores`. + /// + /// This is not to be confused with `CoreState` which is an enriched variant of this and exposed + /// to the node side. It also provides information about scheduled/upcoming assignments for + /// example and is computed on the fly in the `availability_cores` runtime call. + #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] + #[cfg_attr(feature = "std", derive(PartialEq))] + pub enum CoreOccupied { + /// No candidate is waiting availability on this core right now (the core is not occupied). + Free, + /// A para is currently waiting for availability/inclusion on this core. + Paras(ParasEntry), + } + + impl CoreOccupied { + /// Is core free? + pub fn is_free(&self) -> bool { + matches!(self, Self::Free) + } + } + + /// Reasons a core might be freed. + #[derive(Clone, Copy)] + pub enum FreedReason { + /// The core's work concluded and the parablock assigned to it is considered available. + Concluded, + /// The core's work timed out. + TimedOut, + } + /// The block number where the session start occurred. Used to track how many group rotations /// have occurred. /// @@ -124,6 +154,68 @@ pub mod pallet { BTreeMap>>>>, ValueQuery, >; + + /// Assignments as tracked in the claim queue. + #[derive(Clone, Encode, Decode, TypeInfo, PartialEq, RuntimeDebug)] + pub struct ParasEntry { + /// The underlying `Assignment` + pub assignment: Assignment, + /// The number of times the entry has timed out in availability already. + pub availability_timeouts: u32, + /// The block height until this entry needs to be backed. + /// + /// If missed the entry will be removed from the claim queue without ever having occupied + /// the core. + pub ttl: N, + } + + impl ParasEntry { + /// Return `Id` from the underlying `Assignment`. + pub fn para_id(&self) -> ParaId { + self.assignment.para_id + } + + /// Create a new `ParasEntry`. + pub fn new(assignment: Assignment, now: N) -> Self { + ParasEntry { assignment, availability_timeouts: 0, ttl: now } + } + } + + /// How a core is mapped to a backing group and a `ParaId` + #[derive(Clone, Encode, Decode, PartialEq, TypeInfo)] + #[cfg_attr(feature = "std", derive(Debug))] + pub struct CoreAssignment { + /// The core that is assigned. + pub core: CoreIndex, + /// The para id and accompanying information needed to collate and back a parablock. + pub paras_entry: ParasEntry, + } + + impl CoreAssignment { + /// Returns the [`ParaId`] of the assignment. + pub fn para_id(&self) -> ParaId { + self.paras_entry.para_id() + } + + /// Returns the inner [`ParasEntry`] of the assignment. + pub fn to_paras_entry(self) -> ParasEntry { + self.paras_entry + } + } + + /// Availability timeout status of a core. + pub(crate) struct AvailabilityTimeoutStatus { + /// Is the core already timed out? + /// + /// If this is true the core will be freed at this block. + pub timed_out: bool, + + /// When does this core timeout. + /// + /// The block number the core times out. If `timed_out` is true, this will correspond to + /// now (current block number). + pub live_until: BlockNumber, + } } type PositionInClaimqueue = u32; @@ -368,50 +460,47 @@ impl Pallet { Some(GroupIndex(group_idx as u32)) } - /// Returns an optional predicate that should be used for timing out occupied cores. - /// - /// If `None`, no timing-out should be done. The predicate accepts the index of the core, and - /// the block number since which it has been occupied, and the respective parachain timeouts, - /// i.e. only within `config.paras_availability_period` of the last rotation would this return - /// `Some`, unless there are no rotations. + /// Returns a predicate that should be used for timing out occupied cores. /// - /// The timeout used to depend, but does not depend any more on group rotations. First of all - /// it only matters if a para got another chance (a retry). If there is a retry and it happens - /// still within the same group rotation a censoring backing group would need to censor again - /// and lose out again on backing rewards. This is bad for the censoring backing group, it does - /// not matter for the parachain as long as it is retried often enough (so it eventually gets a - /// try on another backing group) - the effect is similar to having a prolonged timeout. It - /// should also be noted that for both malicious and offline backing groups it is actually more - /// realistic that the candidate will not be backed to begin with, instead of getting backed - /// and then not made available. + /// This only ever times out cores that have been occupied across a group rotation boundary. pub(crate) fn availability_timeout_predicate( - ) -> Option) -> bool> { - let now = >::block_number(); + ) -> impl Fn(BlockNumberFor) -> AvailabilityTimeoutStatus> { let config = >::config(); - let session_start = >::get(); + let now = >::block_number(); + let rotation_info = Self::group_rotation_info(now); - let blocks_since_session_start = now.saturating_sub(session_start); - let blocks_since_last_rotation = - blocks_since_session_start % config.group_rotation_frequency.max(1u8.into()); + let next_rotation = rotation_info.next_rotation_at(); - if blocks_since_last_rotation >= config.paras_availability_period { - None - } else { - Some(|core_index: CoreIndex, pending_since| { - let availability_cores = AvailabilityCores::::get(); - let AssignmentProviderConfig { availability_period, .. } = - T::AssignmentProvider::get_provider_config(core_index); - let now = >::block_number(); - match availability_cores.get(core_index.0 as usize) { - None => true, // out-of-bounds, doesn't really matter what is returned. - Some(CoreOccupied::Free) => true, // core free, still doesn't matter. - Some(CoreOccupied::Paras(_)) => - now.saturating_sub(pending_since) >= availability_period, - } - }) + let times_out = Self::availability_timeout_check_required(); + + move |pending_since| { + let time_out_at = if times_out { + // We are at the beginning of the rotation, here availability period is relevant. + // Note: blocks backed in this rotation will never time out here as backed_in + + // config.paras_availability_period will always be > now for these blocks, as + // otherwise above condition would not be true. + pending_since + config.paras_availability_period + } else { + next_rotation + config.paras_availability_period + }; + + AvailabilityTimeoutStatus { timed_out: time_out_at <= now, live_until: time_out_at } } } + /// Is evaluation of `availability_timeout_predicate` necessary at the current block? + /// + /// This can be used to avoid calling `availability_timeout_predicate` for each core in case + /// this function returns false. + pub(crate) fn availability_timeout_check_required() -> bool { + let config = >::config(); + let now = >::block_number() + One::one(); + let rotation_info = Self::group_rotation_info(now); + + let current_window = rotation_info.last_rotation_at() + config.paras_availability_period; + now < current_window + } + /// Returns a helper for determining group rotation. pub(crate) fn group_rotation_info( now: BlockNumberFor, @@ -508,7 +597,7 @@ impl Pallet { pub(crate) fn update_claimqueue( just_freed_cores: impl IntoIterator, now: BlockNumberFor, - ) -> Vec>> { + ) { Self::move_claimqueue_forward(); Self::free_cores_and_fill_claimqueue(just_freed_cores, now) } @@ -534,61 +623,58 @@ impl Pallet { fn free_cores_and_fill_claimqueue( just_freed_cores: impl IntoIterator, now: BlockNumberFor, - ) -> Vec>> { + ) { let (mut concluded_paras, mut timedout_paras) = Self::free_cores(just_freed_cores); // This can only happen on new sessions at which we move all assignments back to the // provider. Hence, there's nothing we need to do here. if ValidatorGroups::::get().is_empty() { - vec![] - } else { - let n_lookahead = Self::claimqueue_lookahead(); - let n_session_cores = T::AssignmentProvider::session_core_count(); - let cq = ClaimQueue::::get(); - let ttl = >::config().on_demand_ttl; - - for core_idx in 0..n_session_cores { - let core_idx = CoreIndex::from(core_idx); - - // add previously timedout paras back into the queue - if let Some(mut entry) = timedout_paras.remove(&core_idx) { - let AssignmentProviderConfig { max_availability_timeouts, .. } = - T::AssignmentProvider::get_provider_config(core_idx); - if entry.availability_timeouts < max_availability_timeouts { - // Increment the timeout counter. - entry.availability_timeouts += 1; - // Reset the ttl so that a timed out assignment. - entry.ttl = now + ttl; - Self::add_to_claimqueue(core_idx, entry); - // The claim has been added back into the claimqueue. - // Do not pop another assignment for the core. - continue - } else { - // Consider timed out assignments for on demand parachains as concluded for - // the assignment provider - let ret = concluded_paras.insert(core_idx, entry.para_id()); - debug_assert!(ret.is_none()); - } + return + } + let n_lookahead = Self::claimqueue_lookahead(); + let n_session_cores = T::AssignmentProvider::session_core_count(); + let cq = ClaimQueue::::get(); + let ttl = >::config().on_demand_ttl; + + for core_idx in 0..n_session_cores { + let core_idx = CoreIndex::from(core_idx); + + // add previously timedout paras back into the queue + if let Some(mut entry) = timedout_paras.remove(&core_idx) { + let AssignmentProviderConfig { max_availability_timeouts, .. } = + T::AssignmentProvider::get_provider_config(core_idx); + if entry.availability_timeouts < max_availability_timeouts { + // Increment the timeout counter. + entry.availability_timeouts += 1; + // Reset the ttl so that a timed out assignment. + entry.ttl = now + ttl; + Self::add_to_claimqueue(core_idx, entry); + // The claim has been added back into the claimqueue. + // Do not pop another assignment for the core. + continue + } else { + // Consider timed out assignments for on demand parachains as concluded for + // the assignment provider + let ret = concluded_paras.insert(core_idx, entry.para_id()); + debug_assert!(ret.is_none()); } + } - // We consider occupied cores to be part of the claimqueue - let n_lookahead_used = cq.get(&core_idx).map_or(0, |v| v.len() as u32) + - if Self::is_core_occupied(core_idx) { 1 } else { 0 }; - for _ in n_lookahead_used..n_lookahead { - let concluded_para = concluded_paras.remove(&core_idx); - if let Some(assignment) = - T::AssignmentProvider::pop_assignment_for_core(core_idx, concluded_para) - { - Self::add_to_claimqueue(core_idx, ParasEntry::new(assignment, now + ttl)); - } + // We consider occupied cores to be part of the claimqueue + let n_lookahead_used = cq.get(&core_idx).map_or(0, |v| v.len() as u32) + + if Self::is_core_occupied(core_idx) { 1 } else { 0 }; + for _ in n_lookahead_used..n_lookahead { + let concluded_para = concluded_paras.remove(&core_idx); + if let Some(assignment) = + T::AssignmentProvider::pop_assignment_for_core(core_idx, concluded_para) + { + Self::add_to_claimqueue(core_idx, ParasEntry::new(assignment, now + ttl)); } } - - debug_assert!(timedout_paras.is_empty()); - debug_assert!(concluded_paras.is_empty()); - - Self::scheduled_claimqueue() } + + debug_assert!(timedout_paras.is_empty()); + debug_assert!(concluded_paras.is_empty()); } fn is_core_occupied(core_idx: CoreIndex) -> bool { @@ -623,29 +709,22 @@ impl Pallet { .ok_or("remove returned None")? .ok_or("Element in Claimqueue was None.")?; - // Since the core is now occupied, the next entry in the claimqueue in order to achieve - // 12 second block times needs to be None - if core_claims.front() != Some(&None) { - core_claims.push_front(None); - } Ok((pos as u32, pe)) }) } - // TODO: Temporary to imitate the old schedule() call. Will be adjusted when we make the - // scheduler AB ready - pub(crate) fn scheduled_claimqueue() -> Vec>> { + /// Paras scheduled next in the claim queue. + pub(crate) fn scheduled_paras() -> impl Iterator { + Self::scheduled_entries().map(|(core_idx, e)| (core_idx, e.assignment.para_id)) + } + + /// Internal access to entries at the top of the claim queue. + fn scheduled_entries() -> impl Iterator>)> { let claimqueue = ClaimQueue::::get(); claimqueue .into_iter() - .flat_map(|(core_idx, v)| { - v.front() - .cloned() - .flatten() - .map(|pe| CoreAssignment { core: core_idx, paras_entry: pe }) - }) - .collect() + .filter_map(|(core_idx, v)| v.front().cloned().flatten().map(|e| (core_idx, e))) } #[cfg(any(feature = "runtime-benchmarks", test))] diff --git a/polkadot/runtime/parachains/src/scheduler/common.rs b/polkadot/runtime/parachains/src/scheduler/common.rs index 0e8e8338b17b..316e8e3b760c 100644 --- a/polkadot/runtime/parachains/src/scheduler/common.rs +++ b/polkadot/runtime/parachains/src/scheduler/common.rs @@ -17,10 +17,7 @@ //! Common traits and types used by the scheduler and assignment providers. use frame_support::pallet_prelude::*; -use primitives::{ - v5::{Assignment, ParasEntry}, - CoreIndex, Id as ParaId, -}; +use primitives::{CoreIndex, Id as ParaId}; use scale_info::TypeInfo; use sp_std::prelude::*; @@ -28,21 +25,22 @@ use sp_std::prelude::*; #[allow(unused)] use crate::configuration::HostConfiguration; -/// Reasons a core might be freed -#[derive(Clone, Copy)] -pub enum FreedReason { - /// The core's work concluded and the parablock assigned to it is considered available. - Concluded, - /// The core's work timed out. - TimedOut, +/// An assignment for a parachain scheduled to be backed and included in a relay chain block. +#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebug)] +pub struct Assignment { + /// Assignment's ParaId + pub para_id: ParaId, +} + +impl Assignment { + /// Create a new `Assignment`. + pub fn new(para_id: ParaId) -> Self { + Self { para_id } + } } /// A set of variables required by the scheduler in order to operate. pub struct AssignmentProviderConfig { - /// The availability period specified by the implementation. - /// See [`HostConfiguration::paras_availability_period`] for more information. - pub availability_period: BlockNumber, - /// How many times a collation can time out on availability. /// Zero timeouts still means that a collation can be provided as per the slot auction /// assignment provider. @@ -72,25 +70,3 @@ pub trait AssignmentProvider { /// Returns a set of variables needed by the scheduler fn get_provider_config(core_idx: CoreIndex) -> AssignmentProviderConfig; } - -/// How a core is mapped to a backing group and a `ParaId` -#[derive(Clone, Encode, Decode, PartialEq, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct CoreAssignment { - /// The core that is assigned. - pub core: CoreIndex, - /// The para id and accompanying information needed to collate and back a parablock. - pub paras_entry: ParasEntry, -} - -impl CoreAssignment { - /// Returns the [`ParaId`] of the assignment. - pub fn para_id(&self) -> ParaId { - self.paras_entry.para_id() - } - - /// Returns the inner [`ParasEntry`] of the assignment. - pub fn to_paras_entry(self) -> ParasEntry { - self.paras_entry - } -} diff --git a/polkadot/runtime/parachains/src/scheduler/migration.rs b/polkadot/runtime/parachains/src/scheduler/migration.rs index 32ac9deaf68f..accff7016ed1 100644 --- a/polkadot/runtime/parachains/src/scheduler/migration.rs +++ b/polkadot/runtime/parachains/src/scheduler/migration.rs @@ -20,7 +20,6 @@ use super::*; use frame_support::{ pallet_prelude::ValueQuery, storage_alias, traits::OnRuntimeUpgrade, weights::Weight, }; -use primitives::vstaging::Assignment; mod v0 { use super::*; diff --git a/polkadot/runtime/parachains/src/scheduler/tests.rs b/polkadot/runtime/parachains/src/scheduler/tests.rs index e203531ca49d..108f365d6b5c 100644 --- a/polkadot/runtime/parachains/src/scheduler/tests.rs +++ b/polkadot/runtime/parachains/src/scheduler/tests.rs @@ -18,7 +18,7 @@ use super::*; use frame_support::assert_ok; use keyring::Sr25519Keyring; -use primitives::{v5::Assignment, BlockNumber, SessionIndex, ValidationCode, ValidatorId}; +use primitives::{BlockNumber, SessionIndex, ValidationCode, ValidatorId}; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; use crate::{ @@ -427,33 +427,27 @@ fn fill_claimqueue_fills() { { assert_eq!(Scheduler::claimqueue_len(), 2 * lookahead); - let scheduled = Scheduler::scheduled_claimqueue(); + let scheduled: BTreeMap<_, _> = Scheduler::scheduled_entries().collect(); // Cannot assert on indices anymore as they depend on the assignment providers assert!(claimqueue_contains_para_ids::(vec![chain_a, chain_b])); assert_eq!( - scheduled[0], - CoreAssignment { - core: CoreIndex(0), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_a }, - availability_timeouts: 0, - ttl: 6 - }, - } + scheduled.get(&CoreIndex(0)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: chain_a }, + availability_timeouts: 0, + ttl: 6 + }, ); assert_eq!( - scheduled[1], - CoreAssignment { - core: CoreIndex(1), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_b }, - availability_timeouts: 0, - ttl: 6 - }, - } + scheduled.get(&CoreIndex(1)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: chain_b }, + availability_timeouts: 0, + ttl: 6 + }, ); } @@ -481,42 +475,33 @@ fn fill_claimqueue_fills() { { assert_eq!(Scheduler::claimqueue_len(), 5); - let scheduled = Scheduler::scheduled_claimqueue(); + let scheduled: BTreeMap<_, _> = Scheduler::scheduled_entries().collect(); assert_eq!( - scheduled[0], - CoreAssignment { - core: CoreIndex(0), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_a }, - availability_timeouts: 0, - ttl: 6 - }, - } + scheduled.get(&CoreIndex(0)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: chain_a }, + availability_timeouts: 0, + ttl: 6 + }, ); assert_eq!( - scheduled[1], - CoreAssignment { - core: CoreIndex(1), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_b }, - availability_timeouts: 0, - ttl: 6 - }, - } + scheduled.get(&CoreIndex(1)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: chain_b }, + availability_timeouts: 0, + ttl: 6 + }, ); // Was added a block later, note the TTL. assert_eq!( - scheduled[2], - CoreAssignment { - core: CoreIndex(2), - paras_entry: ParasEntry { - assignment: Assignment { para_id: thread_a }, - availability_timeouts: 0, - ttl: 7 - }, - } + scheduled.get(&CoreIndex(2)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: thread_a }, + availability_timeouts: 0, + ttl: 7 + }, ); // Sits on the same core as `thread_a` assert_eq!( @@ -528,15 +513,12 @@ fn fill_claimqueue_fills() { }) ); assert_eq!( - scheduled[3], - CoreAssignment { - core: CoreIndex(3), - paras_entry: ParasEntry { - assignment: Assignment { para_id: thread_c }, - availability_timeouts: 0, - ttl: 7 - }, - } + scheduled.get(&CoreIndex(3)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: thread_c }, + availability_timeouts: 0, + ttl: 7 + }, ); } }); @@ -608,7 +590,7 @@ fn schedule_schedules_including_just_freed() { let mut now = 2; run_to_block(now, |_| None); - assert_eq!(Scheduler::scheduled_claimqueue().len(), 4); + assert_eq!(Scheduler::scheduled_paras().collect::>().len(), 4); // cores 0, 1, 2, and 3 should be occupied. mark them as such. let mut occupied_map: BTreeMap = BTreeMap::new(); @@ -630,7 +612,7 @@ fn schedule_schedules_including_just_freed() { // core 4 is free assert!(cores[4] == CoreOccupied::Free); - assert!(Scheduler::scheduled_claimqueue().is_empty()); + assert!(Scheduler::scheduled_paras().collect::>().is_empty()); // All core index entries in the claimqueue should have `None` in them. Scheduler::claimqueue().iter().for_each(|(_core_idx, core_queue)| { @@ -657,21 +639,18 @@ fn schedule_schedules_including_just_freed() { run_to_block(now, |_| None); { - let scheduled = Scheduler::scheduled_claimqueue(); + let scheduled: BTreeMap<_, _> = Scheduler::scheduled_entries().collect(); // cores 0 and 1 are occupied by lease holding parachains. cores 2 and 3 are occupied by // on-demand parachain claims. core 4 was free. assert_eq!(scheduled.len(), 1); assert_eq!( - scheduled[0], - CoreAssignment { - core: CoreIndex(4), - paras_entry: ParasEntry { - assignment: Assignment { para_id: thread_b }, - availability_timeouts: 0, - ttl: 8 - }, - } + scheduled.get(&CoreIndex(4)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: thread_b }, + availability_timeouts: 0, + ttl: 8 + }, ); } @@ -686,54 +665,42 @@ fn schedule_schedules_including_just_freed() { Scheduler::update_claimqueue(just_updated, now); { - let scheduled = Scheduler::scheduled_claimqueue(); + let scheduled: BTreeMap<_, _> = Scheduler::scheduled_entries().collect(); // 1 thing scheduled before, + 3 cores freed. assert_eq!(scheduled.len(), 4); assert_eq!( - scheduled[0], - CoreAssignment { - core: CoreIndex(0), - paras_entry: ParasEntry { - assignment: Assignment { para_id: chain_a }, - availability_timeouts: 0, - ttl: 8 - }, - } + scheduled.get(&CoreIndex(0)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: chain_a }, + availability_timeouts: 0, + ttl: 8 + }, ); assert_eq!( - scheduled[1], - CoreAssignment { - core: CoreIndex(2), - paras_entry: ParasEntry { - assignment: Assignment { para_id: thread_d }, - availability_timeouts: 0, - ttl: 8 - }, - } + scheduled.get(&CoreIndex(2)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: thread_d }, + availability_timeouts: 0, + ttl: 8 + }, ); // Although C was descheduled, the core `4` was occupied so C goes back to the queue. assert_eq!( - scheduled[2], - CoreAssignment { - core: CoreIndex(3), - paras_entry: ParasEntry { - assignment: Assignment { para_id: thread_c }, - availability_timeouts: 1, - ttl: 8 - }, - } + scheduled.get(&CoreIndex(3)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: thread_c }, + availability_timeouts: 1, + ttl: 8 + }, ); assert_eq!( - scheduled[3], - CoreAssignment { - core: CoreIndex(4), - paras_entry: ParasEntry { - assignment: Assignment { para_id: thread_b }, - availability_timeouts: 0, - ttl: 8 - }, - } + scheduled.get(&CoreIndex(4)).unwrap(), + &ParasEntry { + assignment: Assignment { para_id: thread_b }, + availability_timeouts: 0, + ttl: 8 + }, ); // The only assignment yet to be popped on to the claim queue is `thread_e`. @@ -900,14 +867,14 @@ fn schedule_rotates_groups() { run_to_block(now, |_| None); let assert_groups_rotated = |rotations: u32, now: &BlockNumberFor| { - let scheduled = Scheduler::scheduled_claimqueue(); + let scheduled: BTreeMap<_, _> = Scheduler::scheduled_paras().collect(); assert_eq!(scheduled.len(), 2); assert_eq!( - Scheduler::group_assigned_to_core(scheduled[0].core, *now).unwrap(), + Scheduler::group_assigned_to_core(CoreIndex(0), *now).unwrap(), GroupIndex((0u32 + rotations) % on_demand_cores) ); assert_eq!( - Scheduler::group_assigned_to_core(scheduled[1].core, *now).unwrap(), + Scheduler::group_assigned_to_core(CoreIndex(1), *now).unwrap(), GroupIndex((1u32 + rotations) % on_demand_cores) ); }; @@ -999,7 +966,7 @@ fn on_demand_claims_are_pruned_after_timing_out() { ] .into_iter() .collect(); - let core_assignments = Scheduler::update_claimqueue(just_updated, now); + Scheduler::update_claimqueue(just_updated, now); // ParaId a exists in the claim queue until max_retries is reached. if n < max_retries + now { @@ -1008,13 +975,9 @@ fn on_demand_claims_are_pruned_after_timing_out() { assert!(!claimqueue_contains_para_ids::(vec![thread_a])); } - // Occupy the cores based on the output of update_claimqueue. - Scheduler::occupied( - core_assignments - .iter() - .map(|core_assignment| (core_assignment.core, core_assignment.para_id())) - .collect(), - ); + let core_assignments = Scheduler::scheduled_paras().collect(); + // Occupy the cores based on the result of update_claimqueue. + Scheduler::occupied(core_assignments); } // ParaId a does not exist in the claimqueue/availability_cores after @@ -1054,7 +1017,7 @@ fn on_demand_claims_are_pruned_after_timing_out() { } } - let core_assignments = Scheduler::update_claimqueue(just_updated, now); + Scheduler::update_claimqueue(just_updated, now); // ParaId a exists in the claim queue until groups are rotated. if n < 31 { @@ -1063,13 +1026,9 @@ fn on_demand_claims_are_pruned_after_timing_out() { assert!(!claimqueue_contains_para_ids::(vec![thread_a])); } - // Occupy the cores based on the output of update_claimqueue. - Scheduler::occupied( - core_assignments - .iter() - .map(|core_assignment| (core_assignment.core, core_assignment.para_id())) - .collect(), - ); + let core_assignments = Scheduler::scheduled_paras().collect(); + // Occupy the cores based on the result of update_claimqueue. + Scheduler::occupied(core_assignments); } // ParaId a does not exist in the claimqueue/availability_cores after @@ -1124,33 +1083,25 @@ fn availability_predicate_works() { run_to_block(1 + paras_availability_period, |_| None); - assert!(Scheduler::availability_timeout_predicate().is_none()); + assert!(!Scheduler::availability_timeout_check_required()); run_to_block(1 + group_rotation_frequency, |_| None); { - let pred = Scheduler::availability_timeout_predicate() - .expect("predicate exists recently after rotation"); - let now = System::block_number(); - let would_be_timed_out = now - paras_availability_period; - for i in 0..AvailabilityCores::::get().len() { - // returns true for unoccupied cores. - // And can time out paras at this stage. - assert!(pred(CoreIndex(i as u32), would_be_timed_out)); - } + assert!(Scheduler::availability_timeout_check_required()); + let pred = Scheduler::availability_timeout_predicate(); + let last_rotation = Scheduler::group_rotation_info(now).last_rotation_at(); - assert!(!pred(CoreIndex(0), now)); - assert!(!pred(CoreIndex(1), now)); - assert!(pred(CoreIndex(2), now)); + let would_be_timed_out = now - paras_availability_period; + let should_not_be_timed_out = last_rotation; - // check the tight bound. - assert!(pred(CoreIndex(0), now - paras_availability_period)); - assert!(pred(CoreIndex(1), now - paras_availability_period)); + assert!(pred(would_be_timed_out).timed_out); + assert!(!pred(should_not_be_timed_out).timed_out); + assert!(!pred(now).timed_out); // check the threshold is exact. - assert!(!pred(CoreIndex(0), now - paras_availability_period + 1)); - assert!(!pred(CoreIndex(1), now - paras_availability_period + 1)); + assert!(!pred(would_be_timed_out + 1).timed_out); } run_to_block(1 + group_rotation_frequency + paras_availability_period, |_| None); From 43d7a8c07a7fc190056558cf59bc24a72b4b6998 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Wed, 6 Sep 2023 19:34:41 +0200 Subject: [PATCH 041/103] Prevent a fail prdoc check to block (#1433) --- .github/workflows/check-prdoc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml index 219952fdbfba..323be1d4e06e 100644 --- a/.github/workflows/check-prdoc.yml +++ b/.github/workflows/check-prdoc.yml @@ -48,4 +48,4 @@ jobs: if: ${{ !contains(steps.get-labels.outputs.labels, 'R0') }} run: | echo "Checking for PR#${GITHUB_PR} in $MOUNT" - $ENGINE run --rm -v $PWD/prdoc:/doc $IMAGE check -n ${GITHUB_PR} + $ENGINE run --rm -v $PWD/prdoc:/doc $IMAGE check -n ${GITHUB_PR} || true From 433bc9d36689959660223663cdf5b81b4bcd5c0d Mon Sep 17 00:00:00 2001 From: ordian Date: Wed, 6 Sep 2023 20:39:42 +0200 Subject: [PATCH 042/103] zombienet: use another collator image for the slashing test (#1386) * zombienet: use test-parachain image for the slashing test * use the right image * try polkadot-parachain image * try naming collator alice :see_no_evil: * add needed job for the pipeline * fix user id in polkadot-parachain-debug image * small tweaks to the test * another small tweak * yet another small tweak * bump zombienet version --------- Co-authored-by: Javier Viola --- .gitlab-ci.yml | 2 +- .gitlab/pipeline/zombienet/polkadot.yml | 4 ++++ .../polkadot-parachain-debug_unsigned_injected.Dockerfile | 2 +- .../functional/0005-parachains-disputes-past-session.toml | 7 +++---- .../functional/0005-parachains-disputes-past-session.zndsl | 6 +++--- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2e0465ba1eb1..748db808de69 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,7 +30,7 @@ variables: RUSTY_CACHIER_COMPRESSION_METHOD: zstd NEXTEST_FAILURE_OUTPUT: immediate-final NEXTEST_SUCCESS_OUTPUT: final - ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.65" + ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.67" DOCKER_IMAGES_VERSION: "${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}" default: diff --git a/.gitlab/pipeline/zombienet/polkadot.yml b/.gitlab/pipeline/zombienet/polkadot.yml index 87b821742c67..349807a610d4 100644 --- a/.gitlab/pipeline/zombienet/polkadot.yml +++ b/.gitlab/pipeline/zombienet/polkadot.yml @@ -9,6 +9,7 @@ - export ZOMBIENET_INTEGRATION_TEST_IMAGE="${POLKADOT_IMAGE}":${PIPELINE_IMAGE_TAG} - export ZOMBIENET_INTEGRATION_TEST_SECONDARY_IMAGE="docker.io/parity/polkadot:${BUILD_RELEASE_VERSION}" - export COL_IMAGE="${COLANDER_IMAGE}":${PIPELINE_IMAGE_TAG} + - export CUMULUS_IMAGE="docker.io/paritypr/polkadot-parachain-debug:${DOCKER_IMAGES_VERSION}" - export MALUS_IMAGE="${MALUS_IMAGE}":${PIPELINE_IMAGE_TAG} - echo "Zombienet Tests Config" - echo "gh-dir ${GH_DIR}" @@ -16,6 +17,7 @@ - echo "polkadot image ${ZOMBIENET_INTEGRATION_TEST_IMAGE}" - echo "polkadot secondary image ${ZOMBIENET_INTEGRATION_TEST_SECONDARY_IMAGE}" - echo "colander image ${COL_IMAGE}" + - echo "cumulus image ${CUMULUS_IMAGE}" - echo "malus image ${MALUS_IMAGE}" stage: zombienet image: "${ZOMBIENET_IMAGE}" @@ -28,6 +30,8 @@ artifacts: true - job: build-push-image-colander artifacts: true + - job: build-push-image-polkadot-parachain-debug + artifacts: true extends: - .kubernetes-env - .zombienet-refs diff --git a/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile b/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile index 7a2202d9c52b..75cc2b9e629d 100644 --- a/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile +++ b/docker/dockerfiles/polkadot-parachain/polkadot-parachain-debug_unsigned_injected.Dockerfile @@ -28,7 +28,7 @@ RUN apt-get update && \ apt-get clean && \ find /var/lib/apt/lists/ -type f -not -name lock -delete; \ # add user and link ~/.local/share/polkadot-parachain to /data - useradd -m -u 10000 -U -s /bin/sh -d /polkadot-parachain polkadot-parachain && \ + useradd -m -u 1000 -U -s /bin/sh -d /polkadot-parachain polkadot-parachain && \ mkdir -p /data /polkadot-parachain/.local/share && \ chown -R polkadot-parachain:polkadot-parachain /data && \ ln -s /data /polkadot-parachain/.local/share/polkadot-parachain && \ diff --git a/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml b/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml index 50c465950f72..25d922bb6827 100644 --- a/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml +++ b/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml @@ -5,7 +5,7 @@ bootnode = true [relaychain.genesis.runtime.configuration.config] max_validators_per_core = 1 needed_approvals = 2 - group_rotation_frequency = 3 + group_rotation_frequency = 2 [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" @@ -39,8 +39,7 @@ id = 1000 cumulus_based = true [parachains.collator] - name = "collator" + name = "alice" command = "polkadot-parachain" - image = "docker.io/parity/polkadot-parachain:latest" - # image = "{{COL_IMAGE}}" + image = "{{CUMULUS_IMAGE}}" args = ["-lparachain=debug"] diff --git a/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.zndsl b/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.zndsl index bc3674f4f53d..a3f1f0669ac9 100644 --- a/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.zndsl +++ b/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.zndsl @@ -21,18 +21,18 @@ malus-validator: resume malus-validator: log line matches "Suggesting malicious candidate" within 200 seconds # Pause first flaky node -# Availability and finality will continue with 3/4 nodes online (incl. malus) +# Availability will continue with 3/4 nodes online (incl. malus) honest-flaky-validator-0: pause # Wait for the dispute -honest-flaky-validator-1: reports parachain_candidate_disputes_total is at least 1 within 40 seconds +honest-flaky-validator-1: reports parachain_candidate_disputes_total is at least 1 within 60 seconds # Pause second flaky node so that we do not revert blocks due to f+1 invalid votes # Availability and finality will stop honest-flaky-validator-1: pause # Wait for 1 full session to pass after the last unconcluded dispute. -sleep 120 seconds +sleep 110 seconds # Now resume flaky validators honest-flaky-validator: resume From c6f1b9f9cf9877dd6cf7227fffc28cbc65bdd370 Mon Sep 17 00:00:00 2001 From: gupnik <17176722+gupnik@users.noreply.github.com> Date: Thu, 7 Sep 2023 08:05:31 +0530 Subject: [PATCH 043/103] Adds base benchmark for do_tick in broker pallet (#1235) * Adds base benchmark for do_tick * ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_broker * Update substrate/frame/broker/src/benchmarking.rs Co-authored-by: Oliver Tale-Yazdi * Update substrate/frame/broker/src/benchmarking.rs * ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_broker * Addresses review comment --------- Co-authored-by: command-bot <> Co-authored-by: Oliver Tale-Yazdi --- substrate/frame/broker/src/benchmarking.rs | 21 ++ substrate/frame/broker/src/tick_impls.rs | 7 +- substrate/frame/broker/src/weights.rs | 367 ++++++++++++--------- 3 files changed, 239 insertions(+), 156 deletions(-) diff --git a/substrate/frame/broker/src/benchmarking.rs b/substrate/frame/broker/src/benchmarking.rs index 663bf2f466cf..d22f3936c3e2 100644 --- a/substrate/frame/broker/src/benchmarking.rs +++ b/substrate/frame/broker/src/benchmarking.rs @@ -852,6 +852,27 @@ mod benches { } } + #[benchmark] + fn do_tick_base() -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + + advance_to::(5); + + let mut status = Status::::get().unwrap(); + status.last_committed_timeslice = 3; + Status::::put(&status); + + #[block] + { + Broker::::do_tick(); + } + + let updated_status = Status::::get().unwrap(); + assert_eq!(status, updated_status); + + Ok(()) + } + // Implements a test for each benchmark. Execute with: // `cargo test -p pallet-broker --features runtime-benchmarks`. impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/substrate/frame/broker/src/tick_impls.rs b/substrate/frame/broker/src/tick_impls.rs index a1a50a61908d..7df8bd39d42f 100644 --- a/substrate/frame/broker/src/tick_impls.rs +++ b/substrate/frame/broker/src/tick_impls.rs @@ -36,13 +36,14 @@ impl Pallet { /// - Request revenue information for a previous timeslice /// - Initialize an instantaneous core pool historical revenue record pub(crate) fn do_tick() -> Weight { + let mut meter = WeightMeter::new(); + meter.consume(T::WeightInfo::do_tick_base()); + let (mut status, config) = match (Status::::get(), Configuration::::get()) { (Some(s), Some(c)) => (s, c), - _ => return Weight::zero(), + _ => return meter.consumed(), }; - let mut meter = WeightMeter::new(); - if Self::process_core_count(&mut status) { meter.consume(T::WeightInfo::process_core_count(status.core_count.into())); } diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs index 93b568bf2a03..b3a151c6062c 100644 --- a/substrate/frame/broker/src/weights.rs +++ b/substrate/frame/broker/src/weights.rs @@ -18,10 +18,10 @@ //! Autogenerated weights for `pallet_broker` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-09-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-pzhd7p6z-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: // target/production/substrate-node @@ -32,12 +32,12 @@ // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=pallet_broker // --chain=dev -// --header=./HEADER-APACHE2 -// --output=./frame/broker/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/broker/src/weights.rs +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -74,6 +74,7 @@ pub trait WeightInfo { fn process_pool() -> Weight; fn process_core_schedule() -> Weight; fn request_revenue_info_at() -> Weight; + fn do_tick_base() -> Weight; } /// Weights for `pallet_broker` using the Substrate node and recommended hardware. @@ -85,8 +86,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_448_000 picoseconds. - Weight::from_parts(3_729_000, 0) + // Minimum execution time: 3_040_000 picoseconds. + Weight::from_parts(3_344_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -95,8 +96,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 22_537_000 picoseconds. - Weight::from_parts(23_335_000, 7496) + // Minimum execution time: 21_259_000 picoseconds. + Weight::from_parts(22_110_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -106,8 +107,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 21_668_000 picoseconds. - Weight::from_parts(22_442_000, 7496) + // Minimum execution time: 20_330_000 picoseconds. + Weight::from_parts(20_826_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -117,8 +118,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 13_606_000 picoseconds. - Weight::from_parts(14_104_000, 1526) + // Minimum execution time: 13_411_000 picoseconds. + Weight::from_parts(13_960_000, 1526) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -137,12 +138,14 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(_n: u32, ) -> Weight { + fn start_sales(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 64_012_000 picoseconds. - Weight::from_parts(67_819_922, 8499) + // Minimum execution time: 57_770_000 picoseconds. + Weight::from_parts(61_047_512, 8499) + // Standard Error: 165 + .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(16_u64)) } @@ -160,8 +163,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `568` // Estimated: `2053` - // Minimum execution time: 48_110_000 picoseconds. - Weight::from_parts(49_234_000, 2053) + // Minimum execution time: 51_196_000 picoseconds. + Weight::from_parts(52_382_000, 2053) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -183,8 +186,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `686` // Estimated: `4698` - // Minimum execution time: 69_580_000 picoseconds. - Weight::from_parts(70_914_000, 4698) + // Minimum execution time: 71_636_000 picoseconds. + Weight::from_parts(73_679_000, 4698) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -194,8 +197,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 17_687_000 picoseconds. - Weight::from_parts(18_573_000, 3550) + // Minimum execution time: 19_182_000 picoseconds. + Weight::from_parts(19_775_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -205,8 +208,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_675_000 picoseconds. - Weight::from_parts(20_234_000, 3550) + // Minimum execution time: 20_688_000 picoseconds. + Weight::from_parts(21_557_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -216,8 +219,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_426_000 picoseconds. - Weight::from_parts(20_414_000, 3550) + // Minimum execution time: 21_190_000 picoseconds. + Weight::from_parts(22_215_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -233,8 +236,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 31_751_000 picoseconds. - Weight::from_parts(32_966_000, 4681) + // Minimum execution time: 34_591_000 picoseconds. + Weight::from_parts(36_227_000, 4681) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -252,8 +255,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 36_709_000 picoseconds. - Weight::from_parts(38_930_000, 5996) + // Minimum execution time: 40_346_000 picoseconds. + Weight::from_parts(41_951_000, 5996) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -261,20 +264,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Broker::InstaPoolHistory` (r:3 w:1) /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:0) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `m` is `[1, 3]`. fn claim_revenue(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `720` + // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 55_510_000 picoseconds. - Weight::from_parts(56_665_061, 6196) - // Standard Error: 61_729 - .saturating_add(Weight::from_parts(1_724_824, 0).saturating_mul(m.into())) + // Minimum execution time: 75_734_000 picoseconds. + Weight::from_parts(78_168_395, 6196) + // Standard Error: 63_180 + .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(m.into())) } /// Storage: `System::Account` (r:1 w:1) @@ -283,8 +286,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 44_992_000 picoseconds. - Weight::from_parts(46_225_000, 3593) + // Minimum execution time: 46_383_000 picoseconds. + Weight::from_parts(47_405_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -296,8 +299,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 28_207_000 picoseconds. - Weight::from_parts(28_707_000, 3550) + // Minimum execution time: 30_994_000 picoseconds. + Weight::from_parts(31_979_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -311,8 +314,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 31_813_000 picoseconds. - Weight::from_parts(32_612_000, 3533) + // Minimum execution time: 37_584_000 picoseconds. + Weight::from_parts(44_010_000, 3533) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -326,10 +329,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `829` + // Measured: `830` // Estimated: `3593` - // Minimum execution time: 38_571_000 picoseconds. - Weight::from_parts(39_493_000, 3593) + // Minimum execution time: 45_266_000 picoseconds. + Weight::from_parts(48_000_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -341,42 +344,53 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `525` // Estimated: `4698` - // Minimum execution time: 24_714_000 picoseconds. - Weight::from_parts(25_288_000, 4698) + // Minimum execution time: 25_365_000 picoseconds. + Weight::from_parts(26_920_000, 4698) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) /// The range of component `n` is `[0, 1000]`. - fn request_core_count(_n: u32, ) -> Weight { + fn request_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_258_000 picoseconds. - Weight::from_parts(7_925_570, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 6_519_000 picoseconds. + Weight::from_parts(7_098_698, 0) + // Standard Error: 20 + .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) /// The range of component `n` is `[0, 1000]`. - fn process_core_count(_n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `97` - // Estimated: `3562` - // Minimum execution time: 7_136_000 picoseconds. - Weight::from_parts(7_788_194, 3562) + fn process_core_count(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `98` + // Estimated: `3563` + // Minimum execution time: 7_608_000 picoseconds. + Weight::from_parts(8_157_815, 3563) + // Standard Error: 26 + .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Broker::InstaPoolHistory` (r:0 w:1) + /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + /// Storage: `Broker::InstaPoolHistory` (r:1 w:1) /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_049_000 picoseconds. - Weight::from_parts(6_311_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `905` + // Estimated: `4370` + // Minimum execution time: 59_993_000 picoseconds. + Weight::from_parts(61_752_000, 4370) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Broker::InstaPoolIo` (r:3 w:3) /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) @@ -393,10 +407,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 47_504_000 picoseconds. - Weight::from_parts(49_778_098, 8499) - // Standard Error: 109 - .saturating_add(Weight::from_parts(427, 0).saturating_mul(n.into())) + // Minimum execution time: 41_863_000 picoseconds. + Weight::from_parts(44_033_031, 8499) + // Standard Error: 116 + .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -408,8 +422,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 9_573_000 picoseconds. - Weight::from_parts(10_034_000, 3493) + // Minimum execution time: 9_588_000 picoseconds. + Weight::from_parts(9_925_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -421,8 +435,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 21_331_000 picoseconds. - Weight::from_parts(22_235_000, 4681) + // Minimum execution time: 19_308_000 picoseconds. + Weight::from_parts(20_482_000, 4681) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -430,8 +444,25 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 191_000 picoseconds. - Weight::from_parts(234_000, 0) + // Minimum execution time: 147_000 picoseconds. + Weight::from_parts(184_000, 0) + } + /// Storage: `Broker::Status` (r:1 w:1) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + fn do_tick_base() -> Weight { + // Proof Size summary in bytes: + // Measured: `699` + // Estimated: `4164` + // Minimum execution time: 19_824_000 picoseconds. + Weight::from_parts(20_983_000, 4164) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } } @@ -443,8 +474,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_448_000 picoseconds. - Weight::from_parts(3_729_000, 0) + // Minimum execution time: 3_040_000 picoseconds. + Weight::from_parts(3_344_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -453,8 +484,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 22_537_000 picoseconds. - Weight::from_parts(23_335_000, 7496) + // Minimum execution time: 21_259_000 picoseconds. + Weight::from_parts(22_110_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -464,8 +495,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 21_668_000 picoseconds. - Weight::from_parts(22_442_000, 7496) + // Minimum execution time: 20_330_000 picoseconds. + Weight::from_parts(20_826_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -475,8 +506,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 13_606_000 picoseconds. - Weight::from_parts(14_104_000, 1526) + // Minimum execution time: 13_411_000 picoseconds. + Weight::from_parts(13_960_000, 1526) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -495,12 +526,14 @@ impl WeightInfo for () { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(_n: u32, ) -> Weight { + fn start_sales(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 64_012_000 picoseconds. - Weight::from_parts(67_819_922, 8499) + // Minimum execution time: 57_770_000 picoseconds. + Weight::from_parts(61_047_512, 8499) + // Standard Error: 165 + .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(16_u64)) } @@ -518,8 +551,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `568` // Estimated: `2053` - // Minimum execution time: 48_110_000 picoseconds. - Weight::from_parts(49_234_000, 2053) + // Minimum execution time: 51_196_000 picoseconds. + Weight::from_parts(52_382_000, 2053) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -541,8 +574,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `686` // Estimated: `4698` - // Minimum execution time: 69_580_000 picoseconds. - Weight::from_parts(70_914_000, 4698) + // Minimum execution time: 71_636_000 picoseconds. + Weight::from_parts(73_679_000, 4698) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -552,8 +585,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 17_687_000 picoseconds. - Weight::from_parts(18_573_000, 3550) + // Minimum execution time: 19_182_000 picoseconds. + Weight::from_parts(19_775_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -563,8 +596,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_675_000 picoseconds. - Weight::from_parts(20_234_000, 3550) + // Minimum execution time: 20_688_000 picoseconds. + Weight::from_parts(21_557_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -574,8 +607,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_426_000 picoseconds. - Weight::from_parts(20_414_000, 3550) + // Minimum execution time: 21_190_000 picoseconds. + Weight::from_parts(22_215_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -591,8 +624,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 31_751_000 picoseconds. - Weight::from_parts(32_966_000, 4681) + // Minimum execution time: 34_591_000 picoseconds. + Weight::from_parts(36_227_000, 4681) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -610,8 +643,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 36_709_000 picoseconds. - Weight::from_parts(38_930_000, 5996) + // Minimum execution time: 40_346_000 picoseconds. + Weight::from_parts(41_951_000, 5996) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -619,20 +652,20 @@ impl WeightInfo for () { /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Broker::InstaPoolHistory` (r:3 w:1) /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:0) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `m` is `[1, 3]`. fn claim_revenue(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `720` + // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 55_510_000 picoseconds. - Weight::from_parts(56_665_061, 6196) - // Standard Error: 61_729 - .saturating_add(Weight::from_parts(1_724_824, 0).saturating_mul(m.into())) + // Minimum execution time: 75_734_000 picoseconds. + Weight::from_parts(78_168_395, 6196) + // Standard Error: 63_180 + .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(m.into())) } /// Storage: `System::Account` (r:1 w:1) @@ -641,8 +674,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 44_992_000 picoseconds. - Weight::from_parts(46_225_000, 3593) + // Minimum execution time: 46_383_000 picoseconds. + Weight::from_parts(47_405_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -654,8 +687,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 28_207_000 picoseconds. - Weight::from_parts(28_707_000, 3550) + // Minimum execution time: 30_994_000 picoseconds. + Weight::from_parts(31_979_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -669,8 +702,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 31_813_000 picoseconds. - Weight::from_parts(32_612_000, 3533) + // Minimum execution time: 37_584_000 picoseconds. + Weight::from_parts(44_010_000, 3533) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -684,10 +717,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `829` + // Measured: `830` // Estimated: `3593` - // Minimum execution time: 38_571_000 picoseconds. - Weight::from_parts(39_493_000, 3593) + // Minimum execution time: 45_266_000 picoseconds. + Weight::from_parts(48_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -699,42 +732,53 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `525` // Estimated: `4698` - // Minimum execution time: 24_714_000 picoseconds. - Weight::from_parts(25_288_000, 4698) + // Minimum execution time: 25_365_000 picoseconds. + Weight::from_parts(26_920_000, 4698) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) /// The range of component `n` is `[0, 1000]`. - fn request_core_count(_n: u32, ) -> Weight { + fn request_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_258_000 picoseconds. - Weight::from_parts(7_925_570, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 6_519_000 picoseconds. + Weight::from_parts(7_098_698, 0) + // Standard Error: 20 + .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) /// The range of component `n` is `[0, 1000]`. - fn process_core_count(_n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `97` - // Estimated: `3562` - // Minimum execution time: 7_136_000 picoseconds. - Weight::from_parts(7_788_194, 3562) + fn process_core_count(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `98` + // Estimated: `3563` + // Minimum execution time: 7_608_000 picoseconds. + Weight::from_parts(8_157_815, 3563) + // Standard Error: 26 + .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Broker::InstaPoolHistory` (r:0 w:1) + /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + /// Storage: `Broker::InstaPoolHistory` (r:1 w:1) /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_049_000 picoseconds. - Weight::from_parts(6_311_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `905` + // Estimated: `4370` + // Minimum execution time: 59_993_000 picoseconds. + Weight::from_parts(61_752_000, 4370) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Broker::InstaPoolIo` (r:3 w:3) /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) @@ -751,10 +795,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 47_504_000 picoseconds. - Weight::from_parts(49_778_098, 8499) - // Standard Error: 109 - .saturating_add(Weight::from_parts(427, 0).saturating_mul(n.into())) + // Minimum execution time: 41_863_000 picoseconds. + Weight::from_parts(44_033_031, 8499) + // Standard Error: 116 + .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(15_u64)) } @@ -766,8 +810,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 9_573_000 picoseconds. - Weight::from_parts(10_034_000, 3493) + // Minimum execution time: 9_588_000 picoseconds. + Weight::from_parts(9_925_000, 3493) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -779,8 +823,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 21_331_000 picoseconds. - Weight::from_parts(22_235_000, 4681) + // Minimum execution time: 19_308_000 picoseconds. + Weight::from_parts(20_482_000, 4681) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -788,7 +832,24 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 191_000 picoseconds. - Weight::from_parts(234_000, 0) + // Minimum execution time: 147_000 picoseconds. + Weight::from_parts(184_000, 0) + } + /// Storage: `Broker::Status` (r:1 w:1) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) + fn do_tick_base() -> Weight { + // Proof Size summary in bytes: + // Measured: `699` + // Estimated: `4164` + // Minimum execution time: 19_824_000 picoseconds. + Weight::from_parts(20_983_000, 4164) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } } From 7f2ae6ef3b0de788affecd5336e71fdf4879b960 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 7 Sep 2023 10:34:53 +0200 Subject: [PATCH 044/103] Forgotten `polkadot-core-primitives/std` (#1440) * Forgotten `polkadot-core-primitives/std` * Reorder --- polkadot/runtime/parachains/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 77eba0bc10ba..550c0ef75346 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -84,6 +84,7 @@ std = [ "pallet-timestamp/std", "pallet-vesting/std", "parity-scale-codec/std", + "polkadot-core-primitives/std", "polkadot-parachain-primitives/std", "polkadot-runtime-metrics/std", "primitives/std", From 024210ba7e37f7cd45d53bb5c101dbf95bf7ea33 Mon Sep 17 00:00:00 2001 From: yjh Date: Thu, 7 Sep 2023 17:01:55 +0800 Subject: [PATCH 045/103] remove unused `keystore_uri` (#1421) --- substrate/client/cli/src/params/keystore_params.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/substrate/client/cli/src/params/keystore_params.rs b/substrate/client/cli/src/params/keystore_params.rs index a2fdd6b2218c..87210c3390ca 100644 --- a/substrate/client/cli/src/params/keystore_params.rs +++ b/substrate/client/cli/src/params/keystore_params.rs @@ -31,10 +31,6 @@ const DEFAULT_KEYSTORE_CONFIG_PATH: &str = "keystore"; /// Parameters of the keystore #[derive(Debug, Clone, Args)] pub struct KeystoreParams { - /// Specify custom URIs to connect to for keystore-services - #[arg(long)] - pub keystore_uri: Option, - /// Specify custom keystore path. #[arg(long, value_name = "PATH")] pub keystore_path: Option, From 3ff561f33c815ab59666e4e0de8daa15d3749212 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:31:18 +0200 Subject: [PATCH 046/103] [ci] Enable flacky collector for tests (#1439) --- .github/pr-custom-review.yml | 2 +- .gitlab/pipeline/test.yml | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/pr-custom-review.yml b/.github/pr-custom-review.yml index d37ea4cf0958..0d691e7aa2f8 100644 --- a/.github/pr-custom-review.yml +++ b/.github/pr-custom-review.yml @@ -19,7 +19,7 @@ rules: condition: include: .* # excluding files from 'Runtime files' and 'CI files' rules - exclude: ^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/assets/(asset-hub-kusama|asset-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/bridge-hubs/(bridge-hub-kusama|bridge-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/collectives/collectives-polkadot/src/[^/]+\.rs$|^cumulus/parachains/common/src/[^/]+\.rs$|^substrate/frame/(?!.*(nfts/.*|uniques/.*|babe/.*|grandpa/.*|beefy|merkle-mountain-range/.*|contracts/.*|election|nomination-pools/.*|staking/.*|aura/.*))|^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^\.gitlab-ci\.yml|^(?!.*\.dic$|.*spellcheck\.toml$)scripts/ci/.*|^\.github/.* + exclude: ^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/assets/(asset-hub-kusama|asset-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/bridge-hubs/(bridge-hub-kusama|bridge-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/collectives/collectives-polkadot/src/[^/]+\.rs$|^cumulus/parachains/common/src/[^/]+\.rs$|^substrate/frame/(?!.*(nfts/.*|uniques/.*|babe/.*|grandpa/.*|beefy|merkle-mountain-range/.*|contracts/.*|election|nomination-pools/.*|staking/.*|aura/.*))|^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^\.github/.* min_approvals: 2 teams: - core-devs diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index d128cb099021..cbb5a023272f 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -36,9 +36,23 @@ test-linux-stable: --no-fail-fast \ --features try-runtime,experimental \ --partition count:${CI_NODE_INDEX}/${CI_NODE_TOTAL} + # Upload tests results to Elasticsearch + - echo "Upload test results to Elasticsearch" + - cat target/nextest/default/junit.xml | xq . > target/nextest/default/junit.json + - | + curl -v -XPOST --http1.1 \ + -u ${ELASTIC_USERNAME}:${ELASTIC_PASSWORD} \ + https://elasticsearch.parity-build.parity.io/unit-tests/_doc/${CI_JOB_ID} \ + -H 'Content-Type: application/json' \ + -d @target/nextest/default/junit.json || echo "failed to upload junit report" # run runtime-api tests with `enable-staging-api` feature on the 1st node - if [ ${CI_NODE_INDEX} == 1 ]; then time cargo nextest run -p sp-api-test --features enable-staging-api; fi - # todo: add flacky-test collector + artifacts: + when: always + paths: + - target/nextest/default/junit.xml + reports: + junit: target/nextest/default/junit.xml test-linux-oldkernel-stable: extends: test-linux-stable From 329df0491d346d0cce34c36bf86a25f61e93672c Mon Sep 17 00:00:00 2001 From: ordian Date: Thu, 7 Sep 2023 12:24:40 +0200 Subject: [PATCH 047/103] polkadot: pin one block per session (#1220) * polkadot: propagate UnpinHandle to ActiveLeafUpdate Also extract the leaf creation for tests into a common function. * dispute-coordinator: try pinned blocks for slashin * apparently 1.72 is smarter than 1.70 * address nits * rename fresh_leaf to new_leaf --- Cargo.lock | 7 +- .../src/collator_overseer.rs | 18 +- .../node/core/approval-voting/src/tests.rs | 10 +- polkadot/node/core/av-store/src/tests.rs | 49 ++--- polkadot/node/core/backing/src/tests/mod.rs | 11 +- .../src/tests/prospective_parachains.rs | 72 ++------ .../node/core/chain-selection/src/tests.rs | 23 +-- .../dispute-coordinator/src/initialized.rs | 20 ++- .../src/participation/tests.rs | 12 +- .../dispute-coordinator/src/scraping/tests.rs | 15 +- .../core/dispute-coordinator/src/tests.rs | 19 +- .../core/prospective-parachains/src/tests.rs | 37 +--- .../disputes/prioritized_selection/tests.rs | 10 +- polkadot/node/core/pvf-checker/src/tests.rs | 14 +- .../src/requester/tests.rs | 47 +---- .../src/tests/state.rs | 17 +- .../availability-recovery/src/tests.rs | 168 +++++++----------- polkadot/node/network/bridge/src/rx/tests.rs | 71 ++------ .../src/collator_side/tests/mod.rs | 13 +- .../dispute-distribution/src/tests/mod.rs | 13 +- .../node/network/gossip-support/src/tests.rs | 17 +- .../src/legacy_v1/tests.rs | 47 +---- .../src/vstaging/tests/mod.rs | 9 +- polkadot/node/overseer/Cargo.toml | 2 +- polkadot/node/overseer/src/lib.rs | 25 ++- polkadot/node/overseer/src/tests.rs | 163 ++++++++++------- .../node/subsystem-test-helpers/Cargo.toml | 5 +- .../node/subsystem-test-helpers/src/lib.rs | 36 ---- .../node/subsystem-test-helpers/src/mock.rs | 22 ++- polkadot/node/subsystem-types/Cargo.toml | 1 + polkadot/node/subsystem-types/src/lib.rs | 15 +- polkadot/node/subsystem-util/Cargo.toml | 2 + .../node/subsystem-util/src/runtime/mod.rs | 17 ++ 33 files changed, 387 insertions(+), 620 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fff57879891..a95a7e2561d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12303,9 +12303,10 @@ dependencies = [ "parking_lot 0.12.1", "polkadot-node-subsystem", "polkadot-node-subsystem-util", - "polkadot-overseer", "polkadot-primitives", + "sc-client-api", "sc-keystore", + "sc-utils", "sp-application-crypto", "sp-core", "sp-keyring", @@ -12325,6 +12326,7 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "polkadot-statement-table", + "sc-client-api", "sc-network", "sc-transaction-pool-api", "smallvec", @@ -12362,11 +12364,13 @@ dependencies = [ "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-test-helpers", + "polkadot-node-subsystem-types", "polkadot-overseer", "polkadot-primitives", "polkadot-primitives-test-helpers", "prioritized-metered-channel", "rand 0.8.5", + "sc-client-api", "schnellru", "sp-application-crypto", "sp-core", @@ -12390,6 +12394,7 @@ dependencies = [ "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", + "polkadot-node-subsystem-test-helpers", "polkadot-node-subsystem-types", "polkadot-primitives", "polkadot-primitives-test-helpers", diff --git a/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs b/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs index 491758c1329a..bea2fc330a24 100644 --- a/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs +++ b/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs @@ -36,13 +36,14 @@ use polkadot_node_network_protocol::{ use polkadot_node_subsystem_util::metrics::{prometheus::Registry, Metrics}; use polkadot_overseer::{ BlockInfo, DummySubsystem, Handle, Overseer, OverseerConnector, OverseerHandle, SpawnGlue, - KNOWN_LEAVES_CACHE_SIZE, + UnpinHandle, KNOWN_LEAVES_CACHE_SIZE, }; use polkadot_primitives::CollatorPair; use sc_authority_discovery::Service as AuthorityDiscoveryService; use sc_network::NetworkStateInfo; use sc_service::TaskManager; +use sc_utils::mpsc::tracing_unbounded; use sp_runtime::traits::Block as BlockT; use cumulus_primitives_core::relay_chain::{Block, Hash as PHash}; @@ -221,20 +222,25 @@ async fn forward_collator_events( ) -> Result<(), RelayChainError> { let mut finality = client.finality_notification_stream().await?.fuse(); let mut imports = client.import_notification_stream().await?.fuse(); + // Collators do no need to pin any specific blocks + let (dummy_sink, _) = tracing_unbounded("does-not-matter", 42); + let dummy_unpin_handle = UnpinHandle::new(Default::default(), dummy_sink); loop { select! { f = finality.next() => { match f { Some(header) => { + let hash = header.hash(); tracing::info!( target: "minimal-polkadot-node", "Received finalized block via RPC: #{} ({} -> {})", header.number, header.parent_hash, - header.hash() + hash, ); - let block_info = BlockInfo { hash: header.hash(), parent_hash: header.parent_hash, number: header.number }; + let unpin_handle = dummy_unpin_handle.clone(); + let block_info = BlockInfo { hash, parent_hash: header.parent_hash, number: header.number, unpin_handle }; handle.block_finalized(block_info).await; } None => return Err(RelayChainError::GenericError("Relay chain finality stream ended.".to_string())), @@ -243,14 +249,16 @@ async fn forward_collator_events( i = imports.next() => { match i { Some(header) => { + let hash = header.hash(); tracing::info!( target: "minimal-polkadot-node", "Received imported block via RPC: #{} ({} -> {})", header.number, header.parent_hash, - header.hash() + hash, ); - let block_info = BlockInfo { hash: header.hash(), parent_hash: header.parent_hash, number: header.number }; + let unpin_handle = dummy_unpin_handle.clone(); + let block_info = BlockInfo { hash, parent_hash: header.parent_hash, number: header.number, unpin_handle }; handle.block_imported(block_info).await; } None => return Err(RelayChainError::GenericError("Relay chain import stream ended.".to_string())), diff --git a/polkadot/node/core/approval-voting/src/tests.rs b/polkadot/node/core/approval-voting/src/tests.rs index 3c7b74b26fbe..0b98f28fbbf0 100644 --- a/polkadot/node/core/approval-voting/src/tests.rs +++ b/polkadot/node/core/approval-voting/src/tests.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use self::test_helpers::mock::new_leaf; use super::*; use polkadot_node_primitives::{ approval::{ @@ -26,7 +27,7 @@ use polkadot_node_subsystem::{ messages::{ AllMessages, ApprovalVotingMessage, AssignmentCheckResult, AvailabilityRecoveryMessage, }, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, + ActiveLeavesUpdate, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt; @@ -777,12 +778,7 @@ async fn import_block( overseer_send( overseer, FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work( - ActivatedLeaf { - hash: *new_head, - number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }, + new_leaf(*new_head, number), ))), ) .await; diff --git a/polkadot/node/core/av-store/src/tests.rs b/polkadot/node/core/av-store/src/tests.rs index dbccf1401582..652bf2a3fda4 100644 --- a/polkadot/node/core/av-store/src/tests.rs +++ b/polkadot/node/core/av-store/src/tests.rs @@ -19,14 +19,14 @@ use super::*; use assert_matches::assert_matches; use futures::{channel::oneshot, executor, future, Future}; +use self::test_helpers::mock::new_leaf; use ::test_helpers::TestCandidateBuilder; use parking_lot::Mutex; use polkadot_node_primitives::{AvailableData, BlockData, PoV, Proof}; use polkadot_node_subsystem::{ errors::RuntimeApiError, - jaeger, messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, + ActiveLeavesUpdate, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{database::Database, TimeoutExt}; @@ -219,16 +219,11 @@ fn runtime_api_error_does_not_stop_the_subsystem() { let store = test_store(); test_harness(TestState::default(), store, |mut virtual_overseer| async move { - let new_leaf = Hash::repeat_byte(0x01); + let a_leaf = Hash::repeat_byte(0x01); overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: new_leaf, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf(a_leaf, 1))), ) .await; @@ -246,7 +241,7 @@ fn runtime_api_error_does_not_stop_the_subsystem() { relay_parent, tx, )) => { - assert_eq!(relay_parent, new_leaf); + assert_eq!(relay_parent, a_leaf); tx.send(Ok(Some(header))).unwrap(); } ); @@ -258,7 +253,7 @@ fn runtime_api_error_does_not_stop_the_subsystem() { relay_parent, RuntimeApiRequest::CandidateEvents(tx), )) => { - assert_eq!(relay_parent, new_leaf); + assert_eq!(relay_parent, a_leaf); #[derive(Debug)] struct FauxError; impl std::error::Error for FauxError {} @@ -741,7 +736,7 @@ fn stored_data_kept_until_finalized() { available_data, ); - let new_leaf = import_leaf( + let a_leaf = import_leaf( &mut virtual_overseer, parent, block_number, @@ -764,7 +759,7 @@ fn stored_data_kept_until_finalized() { overseer_signal( &mut virtual_overseer, - OverseerSignal::BlockFinalized(new_leaf, block_number), + OverseerSignal::BlockFinalized(a_leaf, block_number), ) .await; @@ -849,16 +844,11 @@ fn we_dont_miss_anything_if_import_notifications_are_missed() { extrinsics_root: Hash::zero(), digest: Default::default(), }; - let new_leaf = Hash::repeat_byte(4); + let a_leaf = Hash::repeat_byte(4); overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: new_leaf, - number: 4, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf(a_leaf, 4))), ) .await; @@ -868,7 +858,7 @@ fn we_dont_miss_anything_if_import_notifications_are_missed() { relay_parent, tx, )) => { - assert_eq!(relay_parent, new_leaf); + assert_eq!(relay_parent, a_leaf); tx.send(Ok(Some(header))).unwrap(); } ); @@ -886,7 +876,7 @@ fn we_dont_miss_anything_if_import_notifications_are_missed() { k, response_channel: tx, }) => { - assert_eq!(hash, new_leaf); + assert_eq!(hash, a_leaf); assert_eq!(k, 2); let _ = tx.send(Ok(vec![ Hash::repeat_byte(3), @@ -1166,16 +1156,11 @@ async fn import_leaf( extrinsics_root: Hash::zero(), digest: Default::default(), }; - let new_leaf = header.hash(); + let a_leaf = header.hash(); overseer_signal( virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: new_leaf, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf(a_leaf, 1))), ) .await; @@ -1185,7 +1170,7 @@ async fn import_leaf( relay_parent, tx, )) => { - assert_eq!(relay_parent, new_leaf); + assert_eq!(relay_parent, a_leaf); tx.send(Ok(Some(header))).unwrap(); } ); @@ -1196,7 +1181,7 @@ async fn import_leaf( relay_parent, RuntimeApiRequest::CandidateEvents(tx), )) => { - assert_eq!(relay_parent, new_leaf); + assert_eq!(relay_parent, a_leaf); tx.send(Ok(events)).unwrap(); } ); @@ -1212,7 +1197,7 @@ async fn import_leaf( } ); - new_leaf + a_leaf } #[test] diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index f5ea827d254c..a981487db445 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use self::test_helpers::mock::new_leaf; use super::*; use ::test_helpers::{ dummy_candidate_receipt_bad_sig, dummy_collator, dummy_collator_signature, @@ -24,12 +25,11 @@ use futures::{future, Future}; use polkadot_node_primitives::{BlockData, InvalidCandidate, SignedFullStatement, Statement}; use polkadot_node_subsystem::{ errors::RuntimeApiError, - jaeger, messages::{ AllMessages, CollatorProtocolMessage, RuntimeApiMessage, RuntimeApiRequest, ValidationFailed, }, - ActivatedLeaf, ActiveLeavesUpdate, FromOrchestra, LeafStatus, OverseerSignal, TimeoutExt, + ActiveLeavesUpdate, FromOrchestra, OverseerSignal, TimeoutExt, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ @@ -234,12 +234,7 @@ async fn test_startup(virtual_overseer: &mut VirtualOverseer, test_state: &TestS // Start work on some new parent. virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work( - ActivatedLeaf { - hash: test_state.relay_parent, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }, + new_leaf(test_state.relay_parent, 1), )))) .await; diff --git a/polkadot/node/core/backing/src/tests/prospective_parachains.rs b/polkadot/node/core/backing/src/tests/prospective_parachains.rs index 07e2a3a89bb6..d6e93fb04d34 100644 --- a/polkadot/node/core/backing/src/tests/prospective_parachains.rs +++ b/polkadot/node/core/backing/src/tests/prospective_parachains.rs @@ -18,7 +18,7 @@ use polkadot_node_subsystem::{ messages::{ChainApiMessage, FragmentTreeMembership}, - TimeoutExt, + ActivatedLeaf, TimeoutExt, }; use polkadot_primitives::{vstaging as vstaging_primitives, BlockNumber, Header, OccupiedCore}; @@ -346,12 +346,7 @@ fn seconding_sanity_check_allowed() { // `a` is grandparent of `b`. let leaf_a_hash = Hash::from_low_u64_be(130); let leaf_a_parent = get_parent_hash(leaf_a_hash); - let activated = ActivatedLeaf { - hash: leaf_a_hash, - number: LEAF_A_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_a_hash, LEAF_A_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; @@ -359,12 +354,7 @@ fn seconding_sanity_check_allowed() { const LEAF_B_ANCESTRY_LEN: BlockNumber = 4; let leaf_b_hash = Hash::from_low_u64_be(128); - let activated = ActivatedLeaf { - hash: leaf_b_hash, - number: LEAF_B_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_b_hash, LEAF_B_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_B_BLOCK_NUMBER - LEAF_B_ANCESTRY_LEN)]; let test_leaf_b = TestLeaf { activated, min_relay_parents }; @@ -503,24 +493,14 @@ fn seconding_sanity_check_disallowed() { // `a` is grandparent of `b`. let leaf_a_hash = Hash::from_low_u64_be(130); let leaf_a_parent = get_parent_hash(leaf_a_hash); - let activated = ActivatedLeaf { - hash: leaf_a_hash, - number: LEAF_A_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_a_hash, LEAF_A_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; const LEAF_B_BLOCK_NUMBER: BlockNumber = LEAF_A_BLOCK_NUMBER + 2; const LEAF_B_ANCESTRY_LEN: BlockNumber = 4; - let activated = ActivatedLeaf { - hash: leaf_b_hash, - number: LEAF_B_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_b_hash, LEAF_B_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_B_BLOCK_NUMBER - LEAF_B_ANCESTRY_LEN)]; let test_leaf_b = TestLeaf { activated, min_relay_parents }; @@ -722,12 +702,7 @@ fn prospective_parachains_reject_candidate() { let leaf_a_hash = Hash::from_low_u64_be(130); let leaf_a_parent = get_parent_hash(leaf_a_hash); - let activated = ActivatedLeaf { - hash: leaf_a_hash, - number: LEAF_A_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_a_hash, LEAF_A_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; @@ -905,12 +880,7 @@ fn second_multiple_candidates_per_relay_parent() { let leaf_hash = Hash::from_low_u64_be(130); let leaf_parent = get_parent_hash(leaf_hash); let leaf_grandparent = get_parent_hash(leaf_parent); - let activated = ActivatedLeaf { - hash: leaf_hash, - number: LEAF_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_hash, LEAF_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; @@ -1046,12 +1016,7 @@ fn backing_works() { let leaf_hash = Hash::from_low_u64_be(130); let leaf_parent = get_parent_hash(leaf_hash); - let activated = ActivatedLeaf { - hash: leaf_hash, - number: LEAF_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_hash, LEAF_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; @@ -1212,12 +1177,7 @@ fn concurrent_dependent_candidates() { let leaf_hash = Hash::from_low_u64_be(130); let leaf_parent = get_parent_hash(leaf_hash); let leaf_grandparent = get_parent_hash(leaf_parent); - let activated = ActivatedLeaf { - hash: leaf_hash, - number: LEAF_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_hash, LEAF_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; @@ -1458,12 +1418,7 @@ fn seconding_sanity_check_occupy_same_depth() { let leaf_hash = Hash::from_low_u64_be(130); let leaf_parent = get_parent_hash(leaf_hash); - let activated = ActivatedLeaf { - hash: leaf_hash, - number: LEAF_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_hash, LEAF_BLOCK_NUMBER); let min_block_number = LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN; let min_relay_parents = vec![(para_id_a, min_block_number), (para_id_b, min_block_number)]; @@ -1617,12 +1572,7 @@ fn occupied_core_assignment() { let leaf_a_hash = Hash::from_low_u64_be(130); let leaf_a_parent = get_parent_hash(leaf_a_hash); - let activated = ActivatedLeaf { - hash: leaf_a_hash, - number: LEAF_A_BLOCK_NUMBER, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf_a_hash, LEAF_A_BLOCK_NUMBER); let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; diff --git a/polkadot/node/core/chain-selection/src/tests.rs b/polkadot/node/core/chain-selection/src/tests.rs index c04f9aaf6606..cf021c0efeb0 100644 --- a/polkadot/node/core/chain-selection/src/tests.rs +++ b/polkadot/node/core/chain-selection/src/tests.rs @@ -35,11 +35,10 @@ use parity_scale_codec::Encode; use parking_lot::Mutex; use sp_core::testing::TaskExecutor; -use polkadot_node_subsystem::{ - jaeger, messages::AllMessages, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, -}; +use polkadot_node_subsystem::{messages::AllMessages, ActiveLeavesUpdate}; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{BlakeTwo256, ConsensusLog, HashT}; +use test_helpers::mock::new_leaf; #[derive(Default)] struct TestBackendInner { @@ -367,12 +366,10 @@ async fn import_blocks_into( let hash = header.hash(); virtual_overseer .send( - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( hash, - number: header.number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })) + header.number, + ))) .into(), ) .await; @@ -425,12 +422,10 @@ async fn import_all_blocks_into( let (_, write_rx) = backend.await_next_write(); virtual_overseer .send( - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: head_hash, - number: head.number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })) + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + head_hash, + head.number, + ))) .into(), ) .await; diff --git a/polkadot/node/core/dispute-coordinator/src/initialized.rs b/polkadot/node/core/dispute-coordinator/src/initialized.rs index 2d8e15064e47..9bfca2d81a04 100644 --- a/polkadot/node/core/dispute-coordinator/src/initialized.rs +++ b/polkadot/node/core/dispute-coordinator/src/initialized.rs @@ -308,6 +308,8 @@ impl Initialized { Ok(session_idx) if self.gaps_in_cache || session_idx > self.highest_session_seen => { + // Pin the block from the new session. + self.runtime_info.pin_block(session_idx, new_leaf.unpin_handle); // Fetch the last `DISPUTE_WINDOW` number of sessions unless there are no gaps // in cache and we are not missing too many `SessionInfo`s let mut lower_bound = session_idx.saturating_sub(DISPUTE_WINDOW.get() - 1); @@ -387,26 +389,28 @@ impl Initialized { "Processing unapplied validator slashes", ); + let pinned_hash = self.runtime_info.get_block_in_session(session_index); let inclusions = self.scraper.get_blocks_including_candidate(&candidate_hash); - if inclusions.is_empty() { + if pinned_hash.is_none() && inclusions.is_empty() { gum::info!( target: LOG_TARGET, - "Couldn't find inclusion parent for an unapplied slash", + ?session_index, + "Couldn't find blocks in the session for an unapplied slash", ); return } - // Find the first inclusion parent that we can use + // Find a relay block that we can use // to generate key ownership proof on. - // We use inclusion parents because of the proper session index. + // We use inclusion parents as a fallback. let mut key_ownership_proofs = Vec::new(); let mut dispute_proofs = Vec::new(); - for (_height, inclusion_parent) in inclusions { + let blocks_in_the_session = + pinned_hash.into_iter().chain(inclusions.into_iter().map(|(_n, h)| h)); + for hash in blocks_in_the_session { for (validator_index, validator_id) in pending.keys.iter() { - let res = - key_ownership_proof(ctx.sender(), inclusion_parent, validator_id.clone()) - .await; + let res = key_ownership_proof(ctx.sender(), hash, validator_id.clone()).await; match res { Ok(Some(key_ownership_proof)) => { diff --git a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs index a2e8e88cb674..ee6b950720e5 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs @@ -28,15 +28,14 @@ use ::test_helpers::{ use parity_scale_codec::Encode; use polkadot_node_primitives::{AvailableData, BlockData, InvalidCandidate, PoV}; use polkadot_node_subsystem::{ - jaeger, messages::{ AllMessages, ChainApiMessage, DisputeCoordinatorMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, SpawnGlue, + ActiveLeavesUpdate, SpawnGlue, }; use polkadot_node_subsystem_test_helpers::{ - make_subsystem_context, TestSubsystemContext, TestSubsystemContextHandle, + make_subsystem_context, mock::new_leaf, TestSubsystemContext, TestSubsystemContextHandle, }; use polkadot_primitives::{ BlakeTwo256, CandidateCommitments, HashT, Header, PersistedValidationData, ValidationCode, @@ -100,12 +99,7 @@ async fn activate_leaf( participation .process_active_leaves_update( ctx, - &ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: block_hash, - span: Arc::new(jaeger::Span::Disabled), - number: block_number, - status: LeafStatus::Fresh, - }), + &ActiveLeavesUpdate::start_work(new_leaf(block_hash, block_number)), ) .await } diff --git a/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs b/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs index 3dd58a060d70..ae722fcb1b47 100644 --- a/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::{sync::Arc, time::Duration}; +use std::time::Duration; use assert_matches::assert_matches; @@ -25,15 +25,15 @@ use sp_core::testing::TaskExecutor; use ::test_helpers::{dummy_collator, dummy_collator_signature, dummy_hash}; use polkadot_node_primitives::DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION; use polkadot_node_subsystem::{ - jaeger, messages::{ AllMessages, ChainApiMessage, DisputeCoordinatorMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, SpawnGlue, + ActivatedLeaf, ActiveLeavesUpdate, SpawnGlue, }; use polkadot_node_subsystem_test_helpers::{ - make_subsystem_context, TestSubsystemContext, TestSubsystemContextHandle, TestSubsystemSender, + make_subsystem_context, mock::new_leaf, TestSubsystemContext, TestSubsystemContextHandle, + TestSubsystemSender, }; use polkadot_node_subsystem_util::{reexports::SubsystemContext, TimeoutExt}; use polkadot_primitives::{ @@ -141,12 +141,7 @@ fn make_candidate_receipt(relay_parent: Hash) -> CandidateReceipt { /// Get a dummy `ActivatedLeaf` for a given block number. fn get_activated_leaf(n: BlockNumber) -> ActivatedLeaf { - ActivatedLeaf { - hash: get_block_number_hash(n), - number: n, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - } + new_leaf(get_block_number_hash(n), n) } /// Get a dummy relay parent hash for dummy block number. diff --git a/polkadot/node/core/dispute-coordinator/src/tests.rs b/polkadot/node/core/dispute-coordinator/src/tests.rs index 8d6a2e103962..9254c2a851ce 100644 --- a/polkadot/node/core/dispute-coordinator/src/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/tests.rs @@ -54,12 +54,11 @@ use sp_keystore::{Keystore, KeystorePtr}; use ::test_helpers::{dummy_candidate_receipt_bad_sig, dummy_digest, dummy_hash}; use polkadot_node_primitives::{Timestamp, ACTIVE_DURATION_SECS}; use polkadot_node_subsystem::{ - jaeger, messages::{AllMessages, BlockDescription, RuntimeApiMessage, RuntimeApiRequest}, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, + ActiveLeavesUpdate, }; use polkadot_node_subsystem_test_helpers::{ - make_buffered_subsystem_context, TestSubsystemContextHandle, + make_buffered_subsystem_context, mock::new_leaf, TestSubsystemContextHandle, }; use polkadot_primitives::{ ApprovalVote, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, @@ -276,12 +275,7 @@ impl TestState { gum::debug!(?block_number, "Activating block in activate_leaf_at_session."); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: block_hash, - span: Arc::new(jaeger::Span::Disabled), - number: block_number, - status: LeafStatus::Fresh, - }), + ActiveLeavesUpdate::start_work(new_leaf(block_hash, block_number)), ))) .await; @@ -449,12 +443,7 @@ impl TestState { ); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: *leaf, - number: n as u32, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }), + ActiveLeavesUpdate::start_work(new_leaf(*leaf, n as u32)), ))) .await; diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index 9fc77624b979..eb12ea4537f7 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -24,7 +24,6 @@ use polkadot_node_subsystem::{ }, }; use polkadot_node_subsystem_test_helpers as test_helpers; -use polkadot_node_subsystem_types::{jaeger, ActivatedLeaf, LeafStatus}; use polkadot_primitives::{ vstaging::{AsyncBackingParams, BackingState, Constraints, InboundHrmpLimitations}, CommittedCandidateReceipt, HeadData, Header, PersistedValidationData, ScheduledCore, @@ -32,6 +31,7 @@ use polkadot_primitives::{ }; use polkadot_primitives_test_helpers::make_candidate; use std::sync::Arc; +use test_helpers::mock::new_leaf; const ALLOWED_ANCESTRY_LEN: u32 = 3; const ASYNC_BACKING_PARAMETERS: AsyncBackingParams = @@ -197,12 +197,7 @@ async fn activate_leaf_with_params( ) { let TestLeaf { number, hash, .. } = leaf; - let activated = ActivatedLeaf { - hash: *hash, - number: *number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(*hash, *number); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work( @@ -497,12 +492,7 @@ fn should_do_no_work_if_async_backing_disabled_for_leaf() { // Start work on some new parent. virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash, 1)), ))) .await; @@ -1318,12 +1308,7 @@ fn correctly_updates_leaves() { .await; // Activate a leaf and remove one at the same time. - let activated = ActivatedLeaf { - hash: leaf_c.hash, - number: leaf_c.number, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }; + let activated = new_leaf(leaf_c.hash, leaf_c.number); let update = ActiveLeavesUpdate { activated: Some(activated), deactivated: [leaf_b.hash][..].into(), @@ -1349,12 +1334,7 @@ fn correctly_updates_leaves() { .await; // Activate and deactivate the same leaf. - let activated = ActivatedLeaf { - hash: leaf_a.hash, - number: leaf_a.number, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }; + let activated = new_leaf(leaf_a.hash, leaf_a.number); let update = ActiveLeavesUpdate { activated: Some(activated), deactivated: [leaf_a.hash][..].into(), @@ -1578,12 +1558,7 @@ fn uses_ancestry_only_within_session() { vec![Hash::repeat_byte(4), Hash::repeat_byte(3), Hash::repeat_byte(2)]; let session_change_hash = Hash::repeat_byte(3); - let activated = ActivatedLeaf { - hash, - number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(hash, number); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( diff --git a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs index 2fdeadb2f4f0..f6c49e52eeb9 100644 --- a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs +++ b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs @@ -24,12 +24,11 @@ use polkadot_node_primitives::{CandidateVotes, DisputeStatus, ACTIVE_DURATION_SE use polkadot_node_subsystem::messages::{ AllMessages, DisputeCoordinatorMessage, RuntimeApiMessage, RuntimeApiRequest, }; -use polkadot_node_subsystem_test_helpers::TestSubsystemSender; +use polkadot_node_subsystem_test_helpers::{mock::new_leaf, TestSubsystemSender}; use polkadot_primitives::{ CandidateHash, DisputeState, InvalidDisputeStatementKind, SessionIndex, ValidDisputeStatementKind, ValidatorSignature, }; -use std::sync::Arc; use test_helpers; // @@ -353,12 +352,7 @@ async fn mock_overseer( } fn leaf() -> ActivatedLeaf { - ActivatedLeaf { - hash: Hash::repeat_byte(0xAA), - number: 0xAA, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - } + new_leaf(Hash::repeat_byte(0xAA), 0xAA) } struct TestDisputes { diff --git a/polkadot/node/core/pvf-checker/src/tests.rs b/polkadot/node/core/pvf-checker/src/tests.rs index d1daa7a58135..bd8817000aeb 100644 --- a/polkadot/node/core/pvf-checker/src/tests.rs +++ b/polkadot/node/core/pvf-checker/src/tests.rs @@ -17,14 +17,15 @@ use ::test_helpers::{dummy_digest, dummy_hash}; use futures::{channel::oneshot, future::BoxFuture, prelude::*}; use polkadot_node_subsystem::{ - jaeger, messages::{ AllMessages, CandidateValidationMessage, PreCheckOutcome, PvfCheckerMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, ActiveLeavesUpdate, FromOrchestra, LeafStatus, OverseerSignal, RuntimeApiError, + ActiveLeavesUpdate, FromOrchestra, OverseerSignal, RuntimeApiError, +}; +use polkadot_node_subsystem_test_helpers::{ + make_subsystem_context, mock::new_leaf, TestSubsystemContextHandle, }; -use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle}; use polkadot_primitives::{ BlockNumber, Hash, Header, PvfCheckStatement, SessionIndex, ValidationCode, ValidationCodeHash, ValidatorId, @@ -195,12 +196,7 @@ impl TestState { }, ); - Some(ActivatedLeaf { - hash: activated_leaf.block_hash, - span: Arc::new(jaeger::Span::Disabled), - number: activated_leaf.block_number, - status: LeafStatus::Fresh, - }) + Some(new_leaf(activated_leaf.block_hash, activated_leaf.block_number)) } else { None }; diff --git a/polkadot/node/network/availability-distribution/src/requester/tests.rs b/polkadot/node/network/availability-distribution/src/requester/tests.rs index 5f7e4c36f063..c4252b4e439e 100644 --- a/polkadot/node/network/availability-distribution/src/requester/tests.rs +++ b/polkadot/node/network/availability-distribution/src/requester/tests.rs @@ -16,12 +16,13 @@ use std::collections::HashMap; -use std::{future::Future, sync::Arc}; +use std::future::Future; use futures::FutureExt; use polkadot_node_network_protocol::jaeger; use polkadot_node_primitives::{BlockData, ErasureChunk, PoV}; +use polkadot_node_subsystem_test_helpers::mock::new_leaf; use polkadot_node_subsystem_util::runtime::RuntimeInfo; use polkadot_primitives::{ BlockNumber, CoreState, ExecutorParams, GroupIndex, Hash, Id as ParaId, ScheduledCore, @@ -34,7 +35,7 @@ use polkadot_node_subsystem::{ AllMessages, AvailabilityDistributionMessage, AvailabilityStoreMessage, ChainApiMessage, NetworkBridgeTxMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, SpawnGlue, + ActiveLeavesUpdate, SpawnGlue, }; use polkadot_node_subsystem_test_helpers::{ make_subsystem_context, mock::make_ferdie_keystore, TestSubsystemContext, @@ -205,12 +206,7 @@ fn check_ancestry_lookup_in_same_session() { let spans: HashMap = HashMap::new(); let block_number = 1; let update = ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: chain[block_number], - number: block_number as u32, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(chain[block_number], block_number as u32)), deactivated: Vec::new().into(), }; @@ -225,12 +221,7 @@ fn check_ancestry_lookup_in_same_session() { let block_number = 2; let update = ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: chain[block_number], - number: block_number as u32, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(chain[block_number], block_number as u32)), deactivated: Vec::new().into(), }; @@ -252,12 +243,7 @@ fn check_ancestry_lookup_in_same_session() { // part of ancestry. let block_number = 2 + Requester::LEAF_ANCESTRY_LEN_WITHIN_SESSION; let update = ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: test_state.relay_chain[block_number], - number: block_number as u32, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(chain[block_number], block_number as u32)), deactivated: vec![chain[1], chain[2]].into(), }; requester @@ -292,12 +278,7 @@ fn check_ancestry_lookup_in_different_sessions() { let spans: HashMap = HashMap::new(); let block_number = 3; let update = ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: chain[block_number], - number: block_number as u32, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(chain[block_number], block_number as u32)), deactivated: Vec::new().into(), }; @@ -310,12 +291,7 @@ fn check_ancestry_lookup_in_different_sessions() { let block_number = 4; let update = ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: chain[block_number], - number: block_number as u32, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(chain[block_number], block_number as u32)), deactivated: vec![chain[1], chain[2], chain[3]].into(), }; @@ -328,12 +304,7 @@ fn check_ancestry_lookup_in_different_sessions() { let block_number = 5; let update = ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: chain[block_number], - number: block_number as u32, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(chain[block_number], block_number as u32)), deactivated: vec![chain[4]].into(), }; diff --git a/polkadot/node/network/availability-distribution/src/tests/state.rs b/polkadot/node/network/availability-distribution/src/tests/state.rs index ecde44788c25..101d917c0db5 100644 --- a/polkadot/node/network/availability-distribution/src/tests/state.rs +++ b/polkadot/node/network/availability-distribution/src/tests/state.rs @@ -16,7 +16,6 @@ use std::{ collections::{HashMap, HashSet}, - sync::Arc, time::Duration, }; @@ -34,9 +33,8 @@ use sc_network::{config as netconfig, config::RequestResponseConfig, IfDisconnec use sp_core::{testing::TaskExecutor, traits::SpawnNamed}; use sp_keystore::KeystorePtr; -use polkadot_node_network_protocol::{ - jaeger, - request_response::{v1, IncomingRequest, OutgoingRequest, Requests}, +use polkadot_node_network_protocol::request_response::{ + v1, IncomingRequest, OutgoingRequest, Requests, }; use polkadot_node_primitives::ErasureChunk; use polkadot_node_subsystem::{ @@ -44,14 +42,14 @@ use polkadot_node_subsystem::{ AllMessages, AvailabilityDistributionMessage, AvailabilityStoreMessage, ChainApiMessage, NetworkBridgeTxMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, ActiveLeavesUpdate, FromOrchestra, LeafStatus, OverseerSignal, + ActiveLeavesUpdate, FromOrchestra, OverseerSignal, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ CandidateHash, CoreState, ExecutorParams, GroupIndex, Hash, Id as ParaId, ScheduledCore, SessionInfo, ValidatorIndex, }; -use test_helpers::mock::make_ferdie_keystore; +use test_helpers::mock::{make_ferdie_keystore, new_leaf}; use super::mock::{make_session_info, OccupiedCoreBuilder}; use crate::LOG_TARGET; @@ -175,12 +173,7 @@ impl TestState { .iter() .zip(advanced) .map(|(old, new)| ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: *new, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + activated: Some(new_leaf(*new, 1)), deactivated: vec![*old].into(), }) .collect::>() diff --git a/polkadot/node/network/availability-recovery/src/tests.rs b/polkadot/node/network/availability-recovery/src/tests.rs index de923f5967e5..60c2d38ab31b 100644 --- a/polkadot/node/network/availability-recovery/src/tests.rs +++ b/polkadot/node/network/availability-recovery/src/tests.rs @@ -29,12 +29,10 @@ use sc_network::config::RequestResponseConfig; use polkadot_erasure_coding::{branches, obtain_chunks_v1 as obtain_chunks}; use polkadot_node_primitives::{BlockData, PoV, Proof}; -use polkadot_node_subsystem::{ - jaeger, - messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}, - ActivatedLeaf, LeafStatus, +use polkadot_node_subsystem::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}; +use polkadot_node_subsystem_test_helpers::{ + make_subsystem_context, mock::new_leaf, TestSubsystemContextHandle, }; -use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle}; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ AuthorityDiscoveryId, Hash, HeadData, IndexedVec, PersistedValidationData, ValidatorId, @@ -561,12 +559,10 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() { test_harness_fast_path(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -647,12 +643,10 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -733,12 +727,10 @@ fn bad_merkle_path_leads_to_recovery_error() { test_harness_fast_path(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -791,12 +783,10 @@ fn wrong_chunk_index_leads_to_recovery_error() { test_harness_fast_path(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -865,12 +855,10 @@ fn invalid_erasure_coding_leads_to_invalid_error() { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -914,12 +902,10 @@ fn fast_path_backing_group_recovers() { test_harness_fast_path(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -964,12 +950,10 @@ fn recovers_from_only_chunks_if_pov_large() { test_harness_chunks_if_pov_large(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1068,12 +1052,10 @@ fn fast_path_backing_group_recovers_if_pov_small() { test_harness_chunks_if_pov_large(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1127,12 +1109,10 @@ fn no_answers_in_fast_path_causes_chunk_requests() { test_harness_fast_path(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1189,12 +1169,10 @@ fn task_canceled_when_receivers_dropped() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1231,12 +1209,10 @@ fn chunks_retry_until_all_nodes_respond() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1292,12 +1268,10 @@ fn not_returning_requests_wont_stall_retrieval() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1364,12 +1338,10 @@ fn all_not_returning_requests_still_recovers_on_return() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1441,12 +1413,10 @@ fn returns_early_if_we_have_the_data() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1478,12 +1448,10 @@ fn does_not_query_local_validator() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; @@ -1537,12 +1505,10 @@ fn invalid_local_chunk_is_ignored() { test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move { overseer_signal( &mut virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.current, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), ) .await; diff --git a/polkadot/node/network/bridge/src/rx/tests.rs b/polkadot/node/network/bridge/src/rx/tests.rs index 88a4b247fdc6..127f46e0fa37 100644 --- a/polkadot/node/network/bridge/src/rx/tests.rs +++ b/polkadot/node/network/bridge/src/rx/tests.rs @@ -16,8 +16,9 @@ use super::*; use futures::{channel::oneshot, executor, stream::BoxStream}; +use overseer::jaeger; use polkadot_node_network_protocol::{self as net_protocol, OurView}; -use polkadot_node_subsystem::{messages::NetworkBridgeEvent, ActivatedLeaf}; +use polkadot_node_subsystem::messages::NetworkBridgeEvent; use assert_matches::assert_matches; use async_trait::async_trait; @@ -36,15 +37,14 @@ use polkadot_node_network_protocol::{ view, ObservedRole, Versioned, }; use polkadot_node_subsystem::{ - jaeger, messages::{ AllMessages, ApprovalDistributionMessage, BitfieldDistributionMessage, GossipSupportMessage, StatementDistributionMessage, }, - ActiveLeavesUpdate, FromOrchestra, LeafStatus, OverseerSignal, + ActiveLeavesUpdate, FromOrchestra, OverseerSignal, }; use polkadot_node_subsystem_test_helpers::{ - SingleItemSink, SingleItemStream, TestSubsystemContextHandle, + mock::new_leaf, SingleItemSink, SingleItemStream, TestSubsystemContextHandle, }; use polkadot_node_subsystem_util::metered; use polkadot_primitives::{AuthorityDiscoveryId, CandidateHash, Hash}; @@ -427,12 +427,7 @@ fn send_our_view_upon_connection() { let head = Hash::repeat_byte(1); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: head, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(head, 1)), ))) .await; @@ -514,12 +509,7 @@ fn sends_view_updates_to_peers() { virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -585,12 +575,7 @@ fn do_not_send_view_update_until_synced() { virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -601,12 +586,7 @@ fn do_not_send_view_update_until_synced() { virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_b, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_b, 1)), ))) .await; @@ -672,12 +652,7 @@ fn do_not_send_view_update_when_only_finalized_block_changed() { // This should trigger the view update to our peers. virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -895,12 +870,7 @@ fn peer_disconnect_from_just_one_peerset() { virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -1132,12 +1102,7 @@ fn sent_views_include_finalized_number_update() { .await; virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_b, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_b, 1)), ))) .await; @@ -1211,12 +1176,7 @@ fn our_view_updates_decreasing_order_and_limited_to_max() { // get the correct view. virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash, - number: i as _, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash, i as _)), ))) .await; } @@ -1265,12 +1225,7 @@ fn network_protocol_versioning_view_update() { let head = Hash::repeat_byte(1); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: head, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(head, 1)), ))) .await; diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs index 8b28730c9012..b452c84c2cd8 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs @@ -40,7 +40,7 @@ use polkadot_node_subsystem::{ errors::RuntimeApiError, jaeger, messages::{AllMessages, ReportPeerMessage, RuntimeApiMessage, RuntimeApiRequest}, - ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, + ActiveLeavesUpdate, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{reputation::add_reputation, TimeoutExt}; @@ -49,6 +49,7 @@ use polkadot_primitives::{ ScheduledCore, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, }; use polkadot_primitives_test_helpers::TestCandidateBuilder; +use test_helpers::mock::new_leaf; mod prospective_parachains; @@ -310,12 +311,10 @@ async fn setup_system(virtual_overseer: &mut VirtualOverseer, test_state: &TestS overseer_signal( virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: test_state.relay_parent, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.relay_parent, + 1, + ))), ) .await; diff --git a/polkadot/node/network/dispute-distribution/src/tests/mod.rs b/polkadot/node/network/dispute-distribution/src/tests/mod.rs index f53b9c0dd4b5..96f045cbf769 100644 --- a/polkadot/node/network/dispute-distribution/src/tests/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/tests/mod.rs @@ -19,7 +19,6 @@ use std::{ collections::HashSet, - sync::Arc, task::Poll, time::{Duration, Instant}, }; @@ -51,10 +50,11 @@ use polkadot_node_subsystem::{ AllMessages, DisputeCoordinatorMessage, DisputeDistributionMessage, ImportStatementsResult, NetworkBridgeTxMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, ActiveLeavesUpdate, FromOrchestra, LeafStatus, OverseerSignal, Span, + ActiveLeavesUpdate, FromOrchestra, OverseerSignal, }; use polkadot_node_subsystem_test_helpers::{ - mock::make_ferdie_keystore, subsystem_test_harness, TestSubsystemContextHandle, + mock::{make_ferdie_keystore, new_leaf}, + subsystem_test_harness, TestSubsystemContextHandle, }; use polkadot_primitives::{ AuthorityDiscoveryId, CandidateHash, CandidateReceipt, ExecutorParams, Hash, SessionIndex, @@ -735,12 +735,7 @@ async fn activate_leaf( ) { handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: activate, - number: 10, - status: LeafStatus::Fresh, - span: Arc::new(Span::Disabled), - }), + activated: Some(new_leaf(activate, 10)), deactivated: deactivate.into_iter().collect(), }))) .await; diff --git a/polkadot/node/network/gossip-support/src/tests.rs b/polkadot/node/network/gossip-support/src/tests.rs index 20f550514157..2e909bb0a674 100644 --- a/polkadot/node/network/gossip-support/src/tests.rs +++ b/polkadot/node/network/gossip-support/src/tests.rs @@ -16,7 +16,7 @@ //! Unit tests for Gossip Support Subsystem. -use std::{collections::HashSet, sync::Arc, time::Duration}; +use std::{collections::HashSet, time::Duration}; use assert_matches::assert_matches; use async_trait::async_trait; @@ -30,15 +30,11 @@ use sp_core::crypto::Pair as PairT; use sp_keyring::Sr25519Keyring; use polkadot_node_network_protocol::grid_topology::{SessionGridTopology, TopologyPeerInfo}; -use polkadot_node_subsystem::{ - jaeger, - messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}, - ActivatedLeaf, LeafStatus, -}; +use polkadot_node_subsystem::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt as _; use polkadot_primitives::{GroupIndex, IndexedVec}; -use test_helpers::mock::make_ferdie_keystore; +use test_helpers::mock::{make_ferdie_keystore, new_leaf}; use super::*; @@ -196,12 +192,7 @@ fn test_harness, AD: AuthorityDiscovery>( const TIMEOUT: Duration = Duration::from_millis(100); async fn overseer_signal_active_leaves(overseer: &mut VirtualOverseer, leaf: Hash) { - let leaf = ActivatedLeaf { - hash: leaf, - number: 0xdeadcafe, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let leaf = new_leaf(leaf, 0xdeadcafe); overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work( leaf, diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs index 63ac1febde56..17a66a9ff792 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs @@ -36,13 +36,12 @@ use polkadot_node_primitives::{ SignedFullStatementWithPVD, Statement, UncheckedSignedFullStatement, }; use polkadot_node_subsystem::{ - jaeger, messages::{ network_bridge_event, AllMessages, ReportPeerMessage, RuntimeApiMessage, RuntimeApiRequest, }, - ActivatedLeaf, LeafStatus, RuntimeApiError, + RuntimeApiError, }; -use polkadot_node_subsystem_test_helpers::mock::make_ferdie_keystore; +use polkadot_node_subsystem_test_helpers::mock::{make_ferdie_keystore, new_leaf}; use polkadot_primitives::{ ExecutorParams, GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, SessionInfo, ValidationCode, @@ -787,12 +786,7 @@ fn receiving_from_one_sends_to_another_and_to_candidate_backing() { // register our active heads. handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -1032,12 +1026,7 @@ fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing( // register our active heads. handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -1567,12 +1556,7 @@ fn delay_reputation_changes() { // register our active heads. handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -2052,12 +2036,7 @@ fn share_prioritizes_backing_group() { // register our active heads. handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -2379,12 +2358,7 @@ fn peer_cant_flood_with_large_statements() { // register our active heads. handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), ))) .await; @@ -2609,12 +2583,7 @@ fn handle_multiple_seconded_statements() { // register our active heads. handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: relay_parent_hash, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), + ActiveLeavesUpdate::start_work(new_leaf(relay_parent_hash, 1)), ))) .await; diff --git a/polkadot/node/network/statement-distribution/src/vstaging/tests/mod.rs b/polkadot/node/network/statement-distribution/src/vstaging/tests/mod.rs index c5a4d14d2c7a..48ceebb1949b 100644 --- a/polkadot/node/network/statement-distribution/src/vstaging/tests/mod.rs +++ b/polkadot/node/network/statement-distribution/src/vstaging/tests/mod.rs @@ -30,7 +30,6 @@ use polkadot_node_subsystem::messages::{ RuntimeApiMessage, RuntimeApiRequest, }; use polkadot_node_subsystem_test_helpers as test_helpers; -use polkadot_node_subsystem_types::{jaeger, ActivatedLeaf, LeafStatus}; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::vstaging::{ AssignmentPair, AsyncBackingParams, BlockNumber, CommittedCandidateReceipt, CoreState, @@ -46,6 +45,7 @@ use assert_matches::assert_matches; use futures::Future; use parity_scale_codec::Encode; use rand::{Rng, SeedableRng}; +use test_helpers::mock::new_leaf; use std::sync::Arc; @@ -358,12 +358,7 @@ async fn activate_leaf( test_state: &TestState, is_new_session: bool, ) { - let activated = ActivatedLeaf { - hash: leaf.hash, - number: leaf.number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }; + let activated = new_leaf(leaf.hash, leaf.number); virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work( diff --git a/polkadot/node/overseer/Cargo.toml b/polkadot/node/overseer/Cargo.toml index 2ebe2e9e0743..0efd4d4c6ca8 100644 --- a/polkadot/node/overseer/Cargo.toml +++ b/polkadot/node/overseer/Cargo.toml @@ -25,12 +25,12 @@ tikv-jemalloc-ctl = { version = "0.5.0", optional = true } [dev-dependencies] metered = { package = "prioritized-metered-channel", version = "0.2.0" } - sp-core = { path = "../../../substrate/primitives/core" } futures = { version = "0.3.21", features = ["thread-pool"] } femme = "2.2.1" assert_matches = "1.4.0" test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../primitives/test-helpers" } +node-test-helpers = { package = "polkadot-node-subsystem-test-helpers", path = "../subsystem-test-helpers" } [target.'cfg(target_os = "linux")'.dependencies] tikv-jemalloc-ctl = "0.5.0" diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs index b8643982323c..7337f1e6be7c 100644 --- a/polkadot/node/overseer/src/lib.rs +++ b/polkadot/node/overseer/src/lib.rs @@ -87,7 +87,7 @@ use polkadot_node_subsystem_types::messages::{ pub use polkadot_node_subsystem_types::{ errors::{SubsystemError, SubsystemResult}, jaeger, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, OverseerSignal, - RuntimeApiSubsystemClient, + RuntimeApiSubsystemClient, UnpinHandle, }; pub mod metrics; @@ -245,23 +245,35 @@ impl Handle { /// `HeaderBackend::block_number_from_id()`. #[derive(Debug, Clone)] pub struct BlockInfo { - /// hash of the block. + /// Hash of the block. pub hash: Hash, - /// hash of the parent block. + /// Hash of the parent block. pub parent_hash: Hash, - /// block's number. + /// Block's number. pub number: BlockNumber, + /// A handle to unpin the block on drop. + pub unpin_handle: UnpinHandle, } impl From> for BlockInfo { fn from(n: BlockImportNotification) -> Self { - BlockInfo { hash: n.hash, parent_hash: n.header.parent_hash, number: n.header.number } + let hash = n.hash; + let parent_hash = n.header.parent_hash; + let number = n.header.number; + let unpin_handle = n.into_unpin_handle(); + + BlockInfo { hash, parent_hash, number, unpin_handle } } } impl From> for BlockInfo { fn from(n: FinalityNotification) -> Self { - BlockInfo { hash: n.hash, parent_hash: n.header.parent_hash, number: n.header.number } + let hash = n.hash; + let parent_hash = n.header.parent_hash; + let number = n.header.number; + let unpin_handle = n.into_unpin_handle(); + + BlockInfo { hash, parent_hash, number, unpin_handle } } } @@ -792,6 +804,7 @@ where hash: block.hash, number: block.number, status, + unpin_handle: block.unpin_handle, span, }), None => ActiveLeavesUpdate::default(), diff --git a/polkadot/node/overseer/src/tests.rs b/polkadot/node/overseer/src/tests.rs index 22d9bf0a708d..298783f41805 100644 --- a/polkadot/node/overseer/src/tests.rs +++ b/polkadot/node/overseer/src/tests.rs @@ -19,15 +19,14 @@ use futures::{executor, pending, pin_mut, poll, select, stream, FutureExt}; use std::{collections::HashMap, sync::atomic, task::Poll}; use ::test_helpers::{dummy_candidate_descriptor, dummy_candidate_receipt, dummy_hash}; +use node_test_helpers::mock::{dummy_unpin_handle, new_leaf}; use polkadot_node_network_protocol::{PeerId, UnifiedReputationChange}; use polkadot_node_primitives::{ BlockData, CollationGenerationConfig, CollationResult, DisputeMessage, InvalidDisputeVote, PoV, UncheckedDisputeMessage, ValidDisputeVote, }; -use polkadot_node_subsystem_types::{ - jaeger, - messages::{NetworkBridgeEvent, ReportPeerMessage, RuntimeApiRequest}, - ActivatedLeaf, LeafStatus, +use polkadot_node_subsystem_types::messages::{ + NetworkBridgeEvent, ReportPeerMessage, RuntimeApiRequest, }; use polkadot_primitives::{ CandidateHash, CandidateReceipt, CollatorPair, Id as ParaId, InvalidDisputeStatementKind, @@ -99,7 +98,7 @@ where if c < 10 { let candidate_receipt = CandidateReceipt { descriptor: dummy_candidate_descriptor(dummy_hash()), - commitments_hash: Hash::zero(), + commitments_hash: dummy_hash(), }; let (tx, _) = oneshot::channel(); @@ -216,11 +215,20 @@ fn overseer_metrics_work() { executor::block_on(async move { let first_block_hash = [1; 32].into(); let second_block_hash = [2; 32].into(); + let unpin_handle = dummy_unpin_handle(dummy_hash()); - let first_block = - BlockInfo { hash: first_block_hash, parent_hash: [0; 32].into(), number: 1 }; - let second_block = - BlockInfo { hash: second_block_hash, parent_hash: first_block_hash, number: 2 }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: first_block_hash, + number: 2, + unpin_handle: unpin_handle.clone(), + }; let registry = prometheus::Registry::new(); let (overseer, handle) = @@ -368,11 +376,20 @@ fn overseer_start_stop_works() { executor::block_on(async move { let first_block_hash = [1; 32].into(); let second_block_hash = [2; 32].into(); + let unpin_handle = dummy_unpin_handle(dummy_hash()); - let first_block = - BlockInfo { hash: first_block_hash, parent_hash: [0; 32].into(), number: 1 }; - let second_block = - BlockInfo { hash: second_block_hash, parent_hash: first_block_hash, number: 2 }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: first_block_hash, + number: 2, + unpin_handle: unpin_handle.clone(), + }; let (tx_5, mut rx_5) = metered::channel(64); let (tx_6, mut rx_6) = metered::channel(64); @@ -396,21 +413,11 @@ fn overseer_start_stop_works() { let expected_heartbeats = vec![ OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: first_block_hash, - number: 1, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }), + activated: Some(new_leaf(first_block_hash, 1)), deactivated: Default::default(), }), OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: second_block_hash, - number: 2, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }), + activated: Some(new_leaf(second_block_hash, 2)), deactivated: [first_block_hash].as_ref().into(), }), ]; @@ -456,13 +463,26 @@ fn overseer_finalize_works() { let first_block_hash = [1; 32].into(); let second_block_hash = [2; 32].into(); let third_block_hash = [3; 32].into(); + let unpin_handle = dummy_unpin_handle(dummy_hash()); - let first_block = - BlockInfo { hash: first_block_hash, parent_hash: [0; 32].into(), number: 1 }; - let second_block = - BlockInfo { hash: second_block_hash, parent_hash: [42; 32].into(), number: 2 }; - let third_block = - BlockInfo { hash: third_block_hash, parent_hash: second_block_hash, number: 3 }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: [42; 32].into(), + number: 2, + unpin_handle: unpin_handle.clone(), + }; + let third_block = BlockInfo { + hash: third_block_hash, + parent_hash: second_block_hash, + number: 3, + unpin_handle: unpin_handle.clone(), + }; let (tx_5, mut rx_5) = metered::channel(64); let (tx_6, mut rx_6) = metered::channel(64); @@ -492,21 +512,11 @@ fn overseer_finalize_works() { let expected_heartbeats = vec![ OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: first_block_hash, - number: 1, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }), + activated: Some(new_leaf(first_block_hash, 1)), deactivated: Default::default(), }), OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: Some(ActivatedLeaf { - hash: second_block_hash, - number: 2, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - }), + activated: Some(new_leaf(second_block_hash, 2)), deactivated: Default::default(), }), OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { @@ -563,11 +573,20 @@ fn overseer_finalize_leaf_preserves_it() { executor::block_on(async move { let first_block_hash = [1; 32].into(); let second_block_hash = [2; 32].into(); + let unpin_handle = dummy_unpin_handle(dummy_hash()); - let first_block = - BlockInfo { hash: first_block_hash, parent_hash: [0; 32].into(), number: 1 }; - let second_block = - BlockInfo { hash: second_block_hash, parent_hash: [42; 32].into(), number: 1 }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: [42; 32].into(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; let (tx_5, mut rx_5) = metered::channel(64); let (tx_6, mut rx_6) = metered::channel(64); @@ -595,18 +614,14 @@ fn overseer_finalize_leaf_preserves_it() { handle.block_finalized(first_block).await; let expected_heartbeats = vec![ - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: first_block_hash, - number: 1, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - })), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: second_block_hash, - number: 1, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + first_block_hash, + 1, + ))), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + second_block_hash, + 2, + ))), OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { deactivated: [second_block_hash].as_ref().into(), ..Default::default() @@ -657,11 +672,21 @@ fn do_not_send_empty_leaves_update_on_block_finalization() { let spawner = sp_core::testing::TaskExecutor::new(); executor::block_on(async move { - let imported_block = - BlockInfo { hash: Hash::random(), parent_hash: Hash::random(), number: 1 }; + let unpin_handle = dummy_unpin_handle(dummy_hash()); - let finalized_block = - BlockInfo { hash: Hash::random(), parent_hash: Hash::random(), number: 1 }; + let imported_block = BlockInfo { + hash: Hash::random(), + parent_hash: Hash::random(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; + + let finalized_block = BlockInfo { + hash: Hash::random(), + parent_hash: Hash::random(), + number: 1, + unpin_handle: unpin_handle.clone(), + }; let (tx_5, mut rx_5) = metered::channel(64); @@ -682,12 +707,10 @@ fn do_not_send_empty_leaves_update_on_block_finalization() { handle.block_imported(imported_block.clone()).await; let expected_heartbeats = vec![ - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: imported_block.hash, - number: imported_block.number, - span: Arc::new(jaeger::Span::Disabled), - status: LeafStatus::Fresh, - })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + imported_block.hash, + imported_block.number, + ))), OverseerSignal::BlockFinalized(finalized_block.hash, 1), ]; @@ -952,11 +975,13 @@ fn overseer_all_subsystems_receive_signals_and_messages() { pin_mut!(overseer_fut); // send a signal to each subsystem + let unpin_handle = dummy_unpin_handle(dummy_hash()); handle .block_imported(BlockInfo { hash: Default::default(), parent_hash: Default::default(), number: Default::default(), + unpin_handle: unpin_handle.clone(), }) .await; diff --git a/polkadot/node/subsystem-test-helpers/Cargo.toml b/polkadot/node/subsystem-test-helpers/Cargo.toml index 98b0d182a611..9087ca11f5d2 100644 --- a/polkadot/node/subsystem-test-helpers/Cargo.toml +++ b/polkadot/node/subsystem-test-helpers/Cargo.toml @@ -14,11 +14,10 @@ parking_lot = "0.12.0" polkadot-node-subsystem = { path = "../subsystem" } polkadot-node-subsystem-util = { path = "../subsystem-util" } polkadot-primitives = { path = "../../primitives" } +sc-client-api = { path = "../../../substrate/client/api" } +sc-utils = { path = "../../../substrate/client/utils" } sp-core = { path = "../../../substrate/primitives/core" } sp-keystore = { path = "../../../substrate/primitives/keystore" } sc-keystore = { path = "../../../substrate/client/keystore" } sp-keyring = { path = "../../../substrate/primitives/keyring" } sp-application-crypto = { path = "../../../substrate/primitives/application-crypto" } - -[dev-dependencies] -polkadot-overseer = { path = "../overseer" } diff --git a/polkadot/node/subsystem-test-helpers/src/lib.rs b/polkadot/node/subsystem-test-helpers/src/lib.rs index 6f0c3016c7ae..fe6b106bf46e 100644 --- a/polkadot/node/subsystem-test-helpers/src/lib.rs +++ b/polkadot/node/subsystem-test-helpers/src/lib.rs @@ -435,42 +435,6 @@ impl Future for Yield { #[cfg(test)] mod tests { use super::*; - use futures::executor::block_on; - use polkadot_node_subsystem::messages::CollatorProtocolMessage; - use polkadot_overseer::{dummy::dummy_overseer_builder, Handle, HeadSupportsParachains}; - use polkadot_primitives::Hash; - use sp_core::traits::SpawnNamed; - - struct AlwaysSupportsParachains; - - #[async_trait::async_trait] - impl HeadSupportsParachains for AlwaysSupportsParachains { - async fn head_supports_parachains(&self, _head: &Hash) -> bool { - true - } - } - - #[test] - fn forward_subsystem_works() { - let spawner = sp_core::testing::TaskExecutor::new(); - let (tx, rx) = mpsc::channel(2); - let (overseer, handle) = - dummy_overseer_builder(spawner.clone(), AlwaysSupportsParachains, None) - .unwrap() - .replace_collator_protocol(|_| ForwardSubsystem(tx)) - .build() - .unwrap(); - - let mut handle = Handle::new(handle); - - spawner.spawn("overseer", None, overseer.run().then(|_| async { () }).boxed()); - - block_on(handle.send_msg_anon(CollatorProtocolMessage::CollateOn(Default::default()))); - assert!(matches!( - block_on(rx.into_future()).0.unwrap(), - CollatorProtocolMessage::CollateOn(_) - )); - } #[test] fn macro_arbitrary_order() { diff --git a/polkadot/node/subsystem-test-helpers/src/mock.rs b/polkadot/node/subsystem-test-helpers/src/mock.rs index 04695983d1d5..35d74e27c9c1 100644 --- a/polkadot/node/subsystem-test-helpers/src/mock.rs +++ b/polkadot/node/subsystem-test-helpers/src/mock.rs @@ -16,12 +16,15 @@ use std::sync::Arc; +use polkadot_node_subsystem::{jaeger, ActivatedLeaf, LeafStatus}; +use sc_client_api::UnpinHandle; use sc_keystore::LocalKeystore; +use sc_utils::mpsc::tracing_unbounded; use sp_application_crypto::AppCrypto; use sp_keyring::Sr25519Keyring; use sp_keystore::{Keystore, KeystorePtr}; -use polkadot_primitives::{AuthorityDiscoveryId, ValidatorId}; +use polkadot_primitives::{AuthorityDiscoveryId, Block, BlockNumber, Hash, ValidatorId}; /// Get mock keystore with `Ferdie` key. pub fn make_ferdie_keystore() -> KeystorePtr { @@ -40,3 +43,20 @@ pub fn make_ferdie_keystore() -> KeystorePtr { .expect("Insert key into keystore"); keystore } + +/// Create a meaningless unpin handle for a block. +pub fn dummy_unpin_handle(block: Hash) -> UnpinHandle { + let (dummy_sink, _) = tracing_unbounded("Expect Chaos", 69); + UnpinHandle::new(block, dummy_sink) +} + +/// Create a new leaf with the given hash and number. +pub fn new_leaf(hash: Hash, number: BlockNumber) -> ActivatedLeaf { + ActivatedLeaf { + hash, + number, + status: LeafStatus::Fresh, + unpin_handle: dummy_unpin_handle(hash), + span: Arc::new(jaeger::Span::Disabled), + } +} diff --git a/polkadot/node/subsystem-types/Cargo.toml b/polkadot/node/subsystem-types/Cargo.toml index 317b079a316c..f6965cf647c3 100644 --- a/polkadot/node/subsystem-types/Cargo.toml +++ b/polkadot/node/subsystem-types/Cargo.toml @@ -19,6 +19,7 @@ sc-network = { path = "../../../substrate/client/network" } sp-api = { path = "../../../substrate/primitives/api" } sp-consensus-babe = { path = "../../../substrate/primitives/consensus/babe" } sp-authority-discovery = { path = "../../../substrate/primitives/authority-discovery" } +sc-client-api = { path = "../../../substrate/client/api" } sc-transaction-pool-api = { path = "../../../substrate/client/transaction-pool/api" } smallvec = "1.8.0" substrate-prometheus-endpoint = { path = "../../../substrate/utils/prometheus" } diff --git a/polkadot/node/subsystem-types/src/lib.rs b/polkadot/node/subsystem-types/src/lib.rs index f438a09592c1..02651ace1e5b 100644 --- a/polkadot/node/subsystem-types/src/lib.rs +++ b/polkadot/node/subsystem-types/src/lib.rs @@ -22,10 +22,19 @@ #![warn(missing_docs)] +use smallvec::SmallVec; use std::{fmt, sync::Arc}; -pub use polkadot_primitives::{BlockNumber, Hash}; -use smallvec::SmallVec; +pub use polkadot_primitives::{Block, BlockNumber, Hash}; + +/// Keeps the state of a specific block pinned in memory while the handle is alive. +/// +/// The handle is reference counted and once the last is dropped, the +/// block is unpinned. +/// +/// This is useful for runtime API calls to blocks that are +/// racing against finality, e.g. for slashing purposes. +pub type UnpinHandle = sc_client_api::UnpinHandle; pub mod errors; pub mod messages; @@ -80,6 +89,8 @@ pub struct ActivatedLeaf { pub number: BlockNumber, /// The status of the leaf. pub status: LeafStatus, + /// A handle to unpin the block on drop. + pub unpin_handle: UnpinHandle, /// An associated [`jaeger::Span`]. /// /// NOTE: Each span should only be kept active as long as the leaf is considered active and diff --git a/polkadot/node/subsystem-util/Cargo.toml b/polkadot/node/subsystem-util/Cargo.toml index 204df0dad117..0d5ae7a0e8e6 100644 --- a/polkadot/node/subsystem-util/Cargo.toml +++ b/polkadot/node/subsystem-util/Cargo.toml @@ -22,6 +22,7 @@ derive_more = "0.99.17" schnellru = "0.2.1" polkadot-node-subsystem = { path = "../subsystem" } +polkadot-node-subsystem-types = { path = "../subsystem-types" } polkadot-node-jaeger = { path = "../jaeger" } polkadot-node-metrics = { path = "../metrics" } polkadot-node-network-protocol = { path = "../network/protocol" } @@ -33,6 +34,7 @@ metered = { package = "prioritized-metered-channel", version = "0.2.0" } sp-core = { path = "../../../substrate/primitives/core" } sp-application-crypto = { path = "../../../substrate/primitives/application-crypto" } sp-keystore = { path = "../../../substrate/primitives/keystore" } +sc-client-api = { path = "../../../substrate/client/api" } kvdb = "0.13.0" parity-db = { version = "0.4.8"} diff --git a/polkadot/node/subsystem-util/src/runtime/mod.rs b/polkadot/node/subsystem-util/src/runtime/mod.rs index fc767faa763c..c078b17d2175 100644 --- a/polkadot/node/subsystem-util/src/runtime/mod.rs +++ b/polkadot/node/subsystem-util/src/runtime/mod.rs @@ -28,6 +28,7 @@ use polkadot_node_subsystem::{ messages::{RuntimeApiMessage, RuntimeApiRequest}, overseer, SubsystemSender, }; +use polkadot_node_subsystem_types::UnpinHandle; use polkadot_primitives::{ vstaging, CandidateEvent, CandidateHash, CoreState, EncodeAs, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, IndexedVec, OccupiedCore, ScrapedOnChainVotes, SessionIndex, @@ -75,6 +76,10 @@ pub struct RuntimeInfo { /// Look up cached sessions by `SessionIndex`. session_info_cache: LruMap, + /// Unpin handle of *some* block in the session. + /// Only blocks pinned explicitly by `pin_block` are stored here. + pinned_blocks: LruMap, + /// Key store for determining whether we are a validator and what `ValidatorIndex` we have. keystore: Option, } @@ -120,6 +125,7 @@ impl RuntimeInfo { Self { session_index_cache: LruMap::new(ByLength::new(cfg.session_cache_lru_size.max(10))), session_info_cache: LruMap::new(ByLength::new(cfg.session_cache_lru_size)), + pinned_blocks: LruMap::new(ByLength::new(cfg.session_cache_lru_size)), keystore: cfg.keystore, } } @@ -145,6 +151,17 @@ impl RuntimeInfo { } } + /// Pin a given block in the given session if none are pinned in that session. + /// Unpinning will happen automatically when LRU cache grows over the limit. + pub fn pin_block(&mut self, session_index: SessionIndex, unpin_handle: UnpinHandle) { + self.pinned_blocks.get_or_insert(session_index, || unpin_handle); + } + + /// Get the hash of a pinned block for the given session index, if any. + pub fn get_block_in_session(&self, session_index: SessionIndex) -> Option { + self.pinned_blocks.peek(&session_index).map(|h| h.hash()) + } + /// Get `ExtendedSessionInfo` by relay parent hash. pub async fn get_session_info<'a, Sender>( &'a mut self, From 5fb02e775047ff385a5e7454a5f292f7de3ac77b Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Thu, 7 Sep 2023 12:39:53 +0200 Subject: [PATCH 048/103] [ci] Return publish-rustdoc (#1402) * [WIP][ci] Return publish-rustdoc * rm files * fix ref * add build doc * add comment * move test-deterministic-wasm to test stage * rm test-deterministic-wasm from root * test publish * enable pipeline * add test_deterministic_wasm.sh for resolving conflicts * rm unused bash script --- .github/pr-custom-review.yml | 2 +- .gitlab-ci.yml | 5 +-- .gitlab/pipeline/build.yml | 14 ++++---- .gitlab/pipeline/check.yml | 1 - .gitlab/pipeline/publish.yml | 54 ++++++++++++++++++++++++++++++ .gitlab/pipeline/test.yml | 12 +++++-- .gitlab/test_deterministic_wasm.sh | 17 ---------- 7 files changed, 71 insertions(+), 34 deletions(-) delete mode 100755 .gitlab/test_deterministic_wasm.sh diff --git a/.github/pr-custom-review.yml b/.github/pr-custom-review.yml index 0d691e7aa2f8..bc9a3cfb8d25 100644 --- a/.github/pr-custom-review.yml +++ b/.github/pr-custom-review.yml @@ -19,7 +19,7 @@ rules: condition: include: .* # excluding files from 'Runtime files' and 'CI files' rules - exclude: ^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/assets/(asset-hub-kusama|asset-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/bridge-hubs/(bridge-hub-kusama|bridge-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/collectives/collectives-polkadot/src/[^/]+\.rs$|^cumulus/parachains/common/src/[^/]+\.rs$|^substrate/frame/(?!.*(nfts/.*|uniques/.*|babe/.*|grandpa/.*|beefy|merkle-mountain-range/.*|contracts/.*|election|nomination-pools/.*|staking/.*|aura/.*))|^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^\.github/.* + exclude: ^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/assets/(asset-hub-kusama|asset-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/bridge-hubs/(bridge-hub-kusama|bridge-hub-polkadot)/src/[^/]+\.rs$|^cumulus/parachains/runtimes/collectives/collectives-polkadot/src/[^/]+\.rs$|^cumulus/parachains/common/src/[^/]+\.rs$|^substrate/frame/(?!.*(nfts/.*|uniques/.*|babe/.*|grandpa/.*|beefy|merkle-mountain-range/.*|contracts/.*|election|nomination-pools/.*|staking/.*|aura/.*))|^polkadot/runtime/(kusama|polkadot)/src/[^/]+\.rs$|^\.gitlab-ci\.yml|^docker/.*|^\.github/.*|^\.gitlab/.*|^\.config/nextest.toml|^\.cargo/.* min_approvals: 2 teams: - core-devs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 748db808de69..99381fae9ecd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -197,8 +197,6 @@ default: extends: .build-refs include: - # weights jobs - # - gitlab/pipeline/weights.yml # check jobs - .gitlab/pipeline/check.yml # test jobs @@ -211,11 +209,10 @@ include: - .gitlab/pipeline/publish.yml # zombienet jobs - .gitlab/pipeline/zombienet.yml - # # timestamp handler + # timestamp handler - project: parity/infrastructure/ci_cd/shared ref: v0.2 file: /common/timestamp.yml - # This job cancels the whole pipeline if any of provided jobs fail. # In a DAG, every jobs chain is executed independently of others. The `fail_fast` principle suggests # to fail the pipeline as soon as possible to shorten the feedback loop. diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index 2d74187cadfa..e34dd40e0814 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -105,20 +105,18 @@ build-rustdoc: - .run-immediately variables: SKIP_WASM_BUILD: 1 - # artifacts: - # name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}-doc" - # when: on_success - # expire_in: 1 days - # paths: - # - ./crate-docs/ + artifacts: + name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}-doc" + when: on_success + expire_in: 1 days + paths: + - ./crate-docs/ script: # FIXME: it fails with `RUSTDOCFLAGS="-Dwarnings"` and `--all-features` # FIXME: return to stable when https://github.com/rust-lang/rust/issues/96937 gets into stable - time cargo doc --features try-runtime,experimental --workspace --no-deps - rm -f ./target/doc/.lock - mv ./target/doc ./crate-docs - # FIXME: remove me after CI image gets nonroot - - chown -R nonroot:nonroot ./crate-docs # Inject Simple Analytics (https://www.simpleanalytics.com/) privacy preserving tracker into # all .html files - | diff --git a/.gitlab/pipeline/check.yml b/.gitlab/pipeline/check.yml index f88f5808637b..446f5dde12e8 100644 --- a/.gitlab/pipeline/check.yml +++ b/.gitlab/pipeline/check.yml @@ -103,7 +103,6 @@ test-rust-feature-propagation: - zepter lint propagate-feature --feature try-runtime --left-side-feature-missing=ignore --workspace --feature-enables-dep="try-runtime:frame-try-runtime" --locked - zepter lint propagate-feature --feature runtime-benchmarks --left-side-feature-missing=ignore --workspace --feature-enables-dep="runtime-benchmarks:frame-benchmarking" --locked - zepter lint propagate-feature --feature std --left-side-feature-missing=ignore --workspace --locked - allow_failure: true # Experimental # More info can be found here: https://github.com/paritytech/polkadot/pull/5865 .check-runtime-migration: diff --git a/.gitlab/pipeline/publish.yml b/.gitlab/pipeline/publish.yml index 341d3ac2a862..1a513e5970d5 100644 --- a/.gitlab/pipeline/publish.yml +++ b/.gitlab/pipeline/publish.yml @@ -1,6 +1,60 @@ # This file is part of .gitlab-ci.yml # Here are all jobs that are executed during "publish" stage +publish-rustdoc: + stage: publish + extends: .kubernetes-env + variables: + CI_IMAGE: node:18 + GIT_DEPTH: 100 + RUSTDOCS_DEPLOY_REFS: "master" + rules: + - if: $CI_PIPELINE_SOURCE == "pipeline" + when: never + - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_REF_NAME == "master" + - if: $CI_COMMIT_REF_NAME == "master" + needs: + - job: build-rustdoc + artifacts: true + script: + # If $CI_COMMIT_REF_NAME doesn't match one of $RUSTDOCS_DEPLOY_REFS space-separated values, we + # exit immediately. + # Putting spaces at the front and back to ensure we are not matching just any substring, but the + # whole space-separated value. + # setup ssh + - eval $(ssh-agent) + - ssh-add - <<< ${GITHUB_SSH_PRIV_KEY} + - mkdir ~/.ssh && touch ~/.ssh/known_hosts + - ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts + # Set git config + - git config user.email "devops-team@parity.io" + - git config user.name "${GITHUB_USER}" + - git config remote.origin.url "git@github.com:/paritytech/${CI_PROJECT_NAME}.git" + - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + - git fetch origin gh-pages + # Save README and docs + - cp -r ./crate-docs/ /tmp/doc/ + - cp README.md /tmp/doc/ + # we don't need to commit changes because we copy docs to /tmp + - git checkout gh-pages --force + # Install `index-tpl-crud` and generate index.html based on RUSTDOCS_DEPLOY_REFS + - which index-tpl-crud &> /dev/null || yarn global add @substrate/index-tpl-crud + - index-tpl-crud upsert ./index.html ${CI_COMMIT_REF_NAME} + # Ensure the destination dir doesn't exist. + - rm -rf ${CI_COMMIT_REF_NAME} + - mv -f /tmp/doc ${CI_COMMIT_REF_NAME} + # Upload files + - git add --all + # `git commit` has an exit code of > 0 if there is nothing to commit. + # This causes GitLab to exit immediately and marks this job failed. + # We don't want to mark the entire job failed if there's nothing to + # publish though, hence the `|| true`. + - git commit -m "___Updated docs for ${CI_COMMIT_REF_NAME}___" || + echo "___Nothing to commit___" + - git push origin gh-pages --force + after_script: + - rm -rf .git/ ./* + # cumulus .build-push-image: diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index cbb5a023272f..406c87923ccb 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -231,8 +231,6 @@ test-node-metrics: - time cargo test --profile testnet --locked --features=runtime-metrics -p polkadot-node-metrics > artifacts/log.txt - # FIXME! - allow_failure: true test-deterministic-wasm: stage: test @@ -244,7 +242,15 @@ test-deterministic-wasm: - job: test-frame-ui artifacts: false script: - - .gitlab/test_deterministic_wasm.sh + # build runtime + - WASM_BUILD_NO_COLOR=1 cargo build -q --locked --release -p staging-kusama-runtime -p polkadot-runtime -p westend-runtime + # make checksum + - sha256sum target/release/wbuild/*-runtime/target/wasm32-unknown-unknown/release/*.wasm > checksum.sha256 + - cargo clean + # build again + - WASM_BUILD_NO_COLOR=1 cargo build -q --locked --release -p staging-kusama-runtime -p polkadot-runtime -p westend-runtime + # confirm checksum + - sha256sum -c checksum.sha256 cargo-check-benches: stage: test diff --git a/.gitlab/test_deterministic_wasm.sh b/.gitlab/test_deterministic_wasm.sh deleted file mode 100755 index fac28fce1f64..000000000000 --- a/.gitlab/test_deterministic_wasm.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -set -e - -#shellcheck source=../common/lib.sh -source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/../.github/scripts/common/lib.sh" - -# build runtime -WASM_BUILD_NO_COLOR=1 cargo build -q --locked --release -p staging-kusama-runtime -p polkadot-runtime -p westend-runtime -# make checksum -sha256sum target/release/wbuild/*-runtime/target/wasm32-unknown-unknown/release/*.wasm > checksum.sha256 - -cargo clean - -# build again -WASM_BUILD_NO_COLOR=1 cargo build -q --locked --release -p staging-kusama-runtime -p polkadot-runtime -p westend-runtime -# confirm checksum -sha256sum -c checksum.sha256 From 301c43828e43136a882911deb75c870c9df9fe26 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Thu, 7 Sep 2023 18:53:31 +0200 Subject: [PATCH 049/103] [ci] change image for prdoc gha (#1452) --- .github/workflows/check-prdoc.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml index 323be1d4e06e..a9b537682276 100644 --- a/.github/workflows/check-prdoc.yml +++ b/.github/workflows/check-prdoc.yml @@ -5,9 +5,7 @@ on: types: [labeled, opened, synchronize, unlabeled] env: - # todo: switch to paritytech/prdoc once the container is built & published - # see https://github.com/paritytech/scripts/pull/595 - IMAGE: chevdor/prdoc:v0.0.4 + IMAGE: paritytech/prdoc:v0.0.5 API_BASE: https://api.github.com/repos REPO: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -28,11 +26,11 @@ jobs: - name: Check if PRdoc is required id: get-labels run: | - # Fetch the labels for the PR under test - echo "Fetch the labels for $API_BASE/${REPO}/pulls/${GITHUB_PR}" - labels=$( curl -H "Authorization: token ${GITHUB_TOKEN}" -s "$API_BASE/${REPO}/pulls/${GITHUB_PR}" | jq '.labels | .[] | .name' | tr "\n" ",") - echo "Labels: ${labels}" - echo "labels=${labels}" >> "$GITHUB_OUTPUT" + # Fetch the labels for the PR under test + echo "Fetch the labels for $API_BASE/${REPO}/pulls/${GITHUB_PR}" + labels=$( curl -H "Authorization: token ${GITHUB_TOKEN}" -s "$API_BASE/${REPO}/pulls/${GITHUB_PR}" | jq '.labels | .[] | .name' | tr "\n" ",") + echo "Labels: ${labels}" + echo "labels=${labels}" >> "$GITHUB_OUTPUT" - name: No PRdoc required if: ${{ contains(steps.get-labels.outputs.labels, 'R0') }} From cbc1d0d3d247a50fd9374481fdb8eb53fc7bbed6 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 8 Sep 2023 11:43:04 +0200 Subject: [PATCH 050/103] Update Chrono to 0.4.30 (#1451) --- Cargo.lock | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a95a7e2561d6..16403dccf36b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -617,7 +617,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -633,7 +633,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -2345,15 +2345,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.27" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56b4c72906975ca04becb8a30e102dfecddd0c06181e3e95ddc444be28881f8" +checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time 0.1.45", "wasm-bindgen", "windows-targets 0.48.5", ] @@ -13803,7 +13802,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.27", + "time", "x509-parser 0.13.2", "yasna", ] @@ -13816,7 +13815,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.27", + "time", "yasna", ] @@ -18775,17 +18774,6 @@ dependencies = [ "tikv-jemalloc-sys", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.27" @@ -19656,12 +19644,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -20164,7 +20146,7 @@ dependencies = [ "sha2 0.10.7", "stun", "thiserror", - "time 0.3.27", + "time", "tokio", "turn", "url", @@ -20772,7 +20754,7 @@ dependencies = [ "ring 0.16.20", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -20790,7 +20772,7 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -20960,7 +20942,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.27", + "time", ] [[package]] From 1089fe82c1dbcffec62181035a4dd806d9b1e172 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 11:49:18 +0200 Subject: [PATCH 051/103] Bump actions/cache from 3.3.1 to 3.3.2 (#1456) Bumps [actions/cache](https://github.com/actions/cache) from 3.3.1 to 3.3.2. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8...704facf57e6136b1bc63b828d79edcd491f0ee84) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-50_publish-docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-50_publish-docker.yml b/.github/workflows/release-50_publish-docker.yml index 0e466f26891c..512b91aa6e55 100644 --- a/.github/workflows/release-50_publish-docker.yml +++ b/.github/workflows/release-50_publish-docker.yml @@ -96,7 +96,7 @@ jobs: fetch_release_artifacts - name: Cache the artifacts - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: key: artifacts-${{ env.BINARY }}-${{ github.sha }} path: | @@ -111,7 +111,7 @@ jobs: uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Get artifacts from cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: key: artifacts-${{ env.BINARY }}-${{ github.sha }} fail-on-cache-miss: true From 15898c34be46bbcf106e10889d63a55cf7311b08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 12:50:56 +0300 Subject: [PATCH 052/103] Bump hex-literal from 0.3.4 to 0.4.1 (#1438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [hex-literal](https://github.com/RustCrypto/utils) from 0.3.4 to 0.4.1. - [Commits](https://github.com/RustCrypto/utils/compare/hex-literal-v0.3.4...hex-literal-v0.4.1) --- updated-dependencies: - dependency-name: hex-literal dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bastian Köcher --- Cargo.lock | 64 ++++++++++++++----------------- polkadot/node/core/pvf/Cargo.toml | 2 +- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16403dccf36b..cd55371e601a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -737,7 +737,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime-constants", "log", "pallet-asset-conversion", @@ -833,7 +833,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -926,7 +926,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-asset-conversion", "pallet-asset-conversion-tx-payment", @@ -990,7 +990,7 @@ dependencies = [ "cumulus-test-relay-sproof-builder", "frame-support", "frame-system", - "hex-literal 0.4.1", + "hex-literal", "pallet-assets", "pallet-balances", "pallet-collator-selection", @@ -1636,7 +1636,7 @@ dependencies = [ "finality-grandpa", "frame-support", "hex", - "hex-literal 0.4.1", + "hex-literal", "parity-scale-codec", "scale-info", "serde", @@ -1666,7 +1666,7 @@ dependencies = [ "bp-runtime", "frame-support", "hex", - "hex-literal 0.4.1", + "hex-literal", "parity-scale-codec", "scale-info", "serde", @@ -1728,7 +1728,7 @@ dependencies = [ "bp-runtime", "frame-support", "hex", - "hex-literal 0.4.1", + "hex-literal", "parity-scale-codec", "scale-info", "sp-runtime", @@ -1754,7 +1754,7 @@ dependencies = [ "frame-support", "frame-system", "hash-db", - "hex-literal 0.4.1", + "hex-literal", "impl-trait-for-tuples", "log", "num-traits", @@ -1832,7 +1832,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime-constants", "log", "pallet-aura", @@ -1895,7 +1895,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-aura", "pallet-authorship", @@ -1990,7 +1990,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-aura", "pallet-authorship", @@ -2599,7 +2599,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-alliance", "pallet-aura", @@ -2814,7 +2814,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime-constants", "log", "pallet-aura", @@ -3544,7 +3544,7 @@ dependencies = [ "environmental", "frame-support", "frame-system", - "hex-literal 0.4.1", + "hex-literal", "impl-trait-for-tuples", "lazy_static", "log", @@ -6003,12 +6003,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - [[package]] name = "hex-literal" version = "0.4.1" @@ -10933,7 +10927,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-aura", "pallet-authorship", @@ -11017,7 +11011,7 @@ dependencies = [ "cumulus-test-relay-sproof-builder", "frame-support", "frame-system", - "hex-literal 0.4.1", + "hex-literal", "pallet-assets", "pallet-balances", "pallet-collator-selection", @@ -11262,7 +11256,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -12060,7 +12054,7 @@ dependencies = [ "assert_matches", "futures", "futures-timer", - "hex-literal 0.3.4", + "hex-literal", "libc", "parity-scale-codec", "pin-project", @@ -12436,7 +12430,7 @@ dependencies = [ "frame-benchmarking-cli", "futures", "glutton-runtime", - "hex-literal 0.4.1", + "hex-literal", "jsonrpsee", "log", "nix 0.26.2", @@ -12527,7 +12521,7 @@ name = "polkadot-primitives" version = "1.0.0" dependencies = [ "bitvec", - "hex-literal 0.4.1", + "hex-literal", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain-primitives", @@ -12604,7 +12598,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -12704,7 +12698,7 @@ dependencies = [ "frame-support", "frame-support-test", "frame-system", - "hex-literal 0.4.1", + "hex-literal", "impl-trait-for-tuples", "libsecp256k1", "log", @@ -12783,7 +12777,7 @@ dependencies = [ "frame-support-test", "frame-system", "futures", - "hex-literal 0.4.1", + "hex-literal", "impl-trait-for-tuples", "log", "pallet-authority-discovery", @@ -12839,7 +12833,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "futures", - "hex-literal 0.4.1", + "hex-literal", "is_executable", "kusama-runtime-constants", "kvdb", @@ -13068,7 +13062,7 @@ dependencies = [ "frame-support", "frame-system", "frame-system-rpc-runtime-api", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -14142,7 +14136,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -17737,7 +17731,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime-constants", "log", "pallet-authority-discovery", @@ -17884,7 +17878,7 @@ dependencies = [ "derivative", "environmental", "hex", - "hex-literal 0.4.1", + "hex-literal", "impl-trait-for-tuples", "log", "parity-scale-codec", @@ -20343,7 +20337,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", diff --git a/polkadot/node/core/pvf/Cargo.toml b/polkadot/node/core/pvf/Cargo.toml index a265139d95c0..ad9120295d22 100644 --- a/polkadot/node/core/pvf/Cargo.toml +++ b/polkadot/node/core/pvf/Cargo.toml @@ -44,7 +44,7 @@ substrate-build-script-utils = { path = "../../../../substrate/utils/build-scrip [dev-dependencies] assert_matches = "1.4.0" -hex-literal = "0.3.4" +hex-literal = "0.4.1" polkadot-node-core-pvf-common = { path = "common", features = ["test-utils"] } # For the puppet worker, depend on ourselves with the test-utils feature. polkadot-node-core-pvf = { path = ".", features = ["test-utils"] } From eae53d58ea4bbb547f69deaac565683a854f4799 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 8 Sep 2023 12:14:57 +0200 Subject: [PATCH 053/103] Update ed25519-dalek to v2 (#1446) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update to ed25519-dalek v2 * Update Cargo.lock * Remove default features * Update cumulus/bridges/primitives/test-utils/src/keyring.rs Co-authored-by: Bastian Köcher --------- Co-authored-by: Bastian Köcher --- Cargo.lock | 35 ++++--------------- .../bridges/primitives/test-utils/Cargo.toml | 2 +- .../primitives/test-utils/src/keyring.rs | 24 +++---------- substrate/primitives/io/Cargo.toml | 2 +- 4 files changed, 13 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd55371e601a..3ba7edafbda1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1778,7 +1778,7 @@ dependencies = [ "bp-parachains", "bp-polkadot-core", "bp-runtime", - "ed25519-dalek 1.0.1", + "ed25519-dalek", "finality-grandpa", "parity-scale-codec", "sp-application-crypto", @@ -4560,15 +4560,6 @@ dependencies = [ "spki 0.7.2", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature 1.6.4", -] - [[package]] name = "ed25519" version = "2.2.2" @@ -4579,20 +4570,6 @@ dependencies = [ "signature 2.1.0", ] -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.0", - "ed25519 1.5.3", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", -] - [[package]] name = "ed25519-dalek" version = "2.0.0" @@ -4600,7 +4577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" dependencies = [ "curve25519-dalek 4.0.0", - "ed25519 2.2.2", + "ed25519", "rand_core 0.6.4", "serde", "sha2 0.10.7", @@ -4628,7 +4605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e83e509bcd060ca4b54b72bde5bb306cb2088cb01e14797ebae90a24f70f5f7" dependencies = [ "curve25519-dalek 4.0.0", - "ed25519 2.2.2", + "ed25519", "hashbrown 0.14.0", "hex", "rand_core 0.6.4", @@ -7123,7 +7100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "bs58 0.4.0", - "ed25519-dalek 2.0.0", + "ed25519-dalek", "log", "multiaddr", "multihash", @@ -17194,7 +17171,7 @@ name = "sp-io" version = "23.0.0" dependencies = [ "bytes", - "ed25519-dalek 2.0.0", + "ed25519-dalek", "libsecp256k1", "log", "parity-scale-codec", @@ -17481,7 +17458,7 @@ version = "4.0.0-dev" dependencies = [ "aes-gcm 0.10.2", "curve25519-dalek 4.0.0", - "ed25519-dalek 2.0.0", + "ed25519-dalek", "hkdf", "parity-scale-codec", "rand 0.8.5", diff --git a/cumulus/bridges/primitives/test-utils/Cargo.toml b/cumulus/bridges/primitives/test-utils/Cargo.toml index fc6e5859141e..f6e8533705e0 100644 --- a/cumulus/bridges/primitives/test-utils/Cargo.toml +++ b/cumulus/bridges/primitives/test-utils/Cargo.toml @@ -12,7 +12,7 @@ bp-parachains = { path = "../parachains", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } +ed25519-dalek = { version = "2.0", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { path = "../../../../substrate/primitives/application-crypto", default-features = false } sp-consensus-grandpa = { path = "../../../../substrate/primitives/consensus/grandpa", default-features = false } diff --git a/cumulus/bridges/primitives/test-utils/src/keyring.rs b/cumulus/bridges/primitives/test-utils/src/keyring.rs index b99132de3ec3..eabf9c784eb8 100644 --- a/cumulus/bridges/primitives/test-utils/src/keyring.rs +++ b/cumulus/bridges/primitives/test-utils/src/keyring.rs @@ -18,7 +18,7 @@ use bp_header_chain::{justification::JustificationVerificationContext, AuthoritySet}; use codec::Encode; -use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; +use ed25519_dalek::{Signature, SigningKey, VerifyingKey}; use finality_grandpa::voter_set::VoterSet; use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; use sp_runtime::RuntimeDebug; @@ -37,29 +37,15 @@ pub const FERDIE: Account = Account(5); pub struct Account(pub u16); impl Account { - pub fn public(&self) -> PublicKey { - (&self.secret()).into() + pub fn public(&self) -> VerifyingKey { + self.pair().verifying_key() } - pub fn secret(&self) -> SecretKey { + pub fn pair(&self) -> SigningKey { let data = self.0.encode(); let mut bytes = [0_u8; 32]; bytes[0..data.len()].copy_from_slice(&data); - SecretKey::from_bytes(&bytes) - .expect("A static array of the correct length is a known good.") - } - - pub fn pair(&self) -> Keypair { - let mut pair: [u8; 64] = [0; 64]; - - let secret = self.secret(); - pair[..32].copy_from_slice(&secret.to_bytes()); - - let public = self.public(); - pair[32..].copy_from_slice(&public.to_bytes()); - - Keypair::from_bytes(&pair) - .expect("We expect the SecretKey to be good, so this must also be good.") + SigningKey::from_bytes(&bytes) } pub fn sign(&self, msg: &[u8]) -> Signature { diff --git a/substrate/primitives/io/Cargo.toml b/substrate/primitives/io/Cargo.toml index 4793938617e0..ab9d26ec26f4 100644 --- a/substrate/primitives/io/Cargo.toml +++ b/substrate/primitives/io/Cargo.toml @@ -33,7 +33,7 @@ tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.28", default-features = false} # Required for backwards compatibility reason, but only used for verifying when `UseDalekExt` is set. -ed25519-dalek = { version = "2.0.0", default-features = false, optional = true } +ed25519-dalek = { version = "2.0", default-features = false, optional = true } [build-dependencies] rustversion = "1.0.6" From f5d911a31e0b976fd3d1c97b2056b2e3096f0a30 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 8 Sep 2023 13:45:54 +0200 Subject: [PATCH 054/103] Switch prdoc to the latest image (#1460) --- .github/workflows/check-prdoc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml index a9b537682276..d153184941ac 100644 --- a/.github/workflows/check-prdoc.yml +++ b/.github/workflows/check-prdoc.yml @@ -5,7 +5,7 @@ on: types: [labeled, opened, synchronize, unlabeled] env: - IMAGE: paritytech/prdoc:v0.0.5 + IMAGE: paritytech/prdoc:latest API_BASE: https://api.github.com/repos REPO: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 675e7da0c12308bb3e4ec540acde86f4bc78ab2d Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 8 Sep 2023 18:59:19 +0200 Subject: [PATCH 055/103] does not compile as balance is not serializable and used in genesis config --- substrate/frame/nomination-pools/src/lib.rs | 65 ++++++++++++------- .../frame/nomination-pools/src/migration.rs | 4 +- 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 44e8b0c422ca..bf9614945a4a 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -357,13 +357,14 @@ use frame_support::{ pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ - Currency, Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, - ExistenceRequirement, Get, + fungible::{Inspect as FungibleInspect, Mutate as FungibleMutate}, + tokens::Preservation, Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, }, DefaultNoBound, PalletError, }; use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; +use frame_support::traits::tokens::Fortitude; use sp_core::U256; use sp_runtime::{ traits::{ @@ -405,7 +406,7 @@ pub use weights::WeightInfo; /// The balance type used by the currency system. pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; + <::Currency as FungibleInspect<::AccountId>>::Balance; /// Type used for unique identifier of each pool. pub type PoolId = u32; @@ -1008,7 +1009,7 @@ impl BondedPool { /// The pools balance that is transferrable. fn transferrable_balance(&self) -> BalanceOf { let account = self.bonded_account(); - T::Currency::free_balance(&account) + T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite) .saturating_sub(T::Staking::active_stake(&account).unwrap_or_default()) } @@ -1201,8 +1202,8 @@ impl BondedPool { &bonded_account, amount, match ty { - BondType::Create => ExistenceRequirement::AllowDeath, - BondType::Later => ExistenceRequirement::KeepAlive, + BondType::Create => Preservation::Expendable, + BondType::Later => Preservation::Preserve, }, )?; // We must calculate the points issued *before* we bond who's funds, else points:balance @@ -1389,7 +1390,7 @@ impl RewardPool { /// /// This is sum of all the rewards that are claimable by pool members. fn current_balance(id: PoolId) -> BalanceOf { - T::Currency::free_balance(&Pallet::::create_reward_account(id)) + T::Currency::reducible_balance(&Pallet::::create_reward_account(id), Preservation::Expendable, Fortitude::Polite) .saturating_sub(T::Currency::minimum_balance()) } } @@ -1509,7 +1510,8 @@ impl Get for TotalUnbondingPools { #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::traits::StorageVersion; + use frame_support::traits::{fungible, StorageVersion}; + use frame_support::traits::tokens::Fortitude; use frame_system::{ensure_signed, pallet_prelude::*}; use sp_runtime::Perbill; @@ -1529,7 +1531,11 @@ pub mod pallet { type WeightInfo: weights::WeightInfo; /// The nominating balance. - type Currency: Currency; + // FIXME(ank4n) + type Currency: FungibleInspect + FungibleMutate + + fungible::MutateFreeze; + + type RuntimeFreezeReason: From; /// The type that is used for reward counter. /// @@ -1882,6 +1888,15 @@ pub mod pallet { } } + /// A reason for freezing funds. + #[pallet::composite_enum] + pub enum FreezeReason { + /// The Pallet has locked funds for maintaining the Existential Deposit of a + /// NominationPool. + #[codec(index = 0)] + PoolMinimumBalance, + } + #[pallet::call] impl Pallet { /// Stake funds with a pool. The amount to bond is transferred from the member to the @@ -2195,7 +2210,7 @@ pub mod pallet { &bonded_pool.bonded_account(), &member_account, balance_to_unbond, - ExistenceRequirement::AllowDeath, + Preservation::Expendable, ) .defensive()?; @@ -2660,7 +2675,7 @@ pub mod pallet { #[pallet::compact] max_transfer: BalanceOf, ) -> DispatchResult { let who = ensure_signed(origin)?; - let caller_balance = T::Currency::free_balance(&who); + let caller_balance = T::Currency::reducible_balance(&who, Preservation::Expendable, Fortitude::Polite); Self::do_top_up_reward_deficit(who, pool_id, max_transfer.min(caller_balance)) } } @@ -2729,12 +2744,12 @@ impl Pallet { // This shouldn't fail, but if it does we don't really care. Remaining balance can consist // of unclaimed pending commission, errorneous transfers to the reward account, etc. - let reward_pool_remaining = T::Currency::free_balance(&reward_account); + let reward_pool_remaining = T::Currency::reducible_balance(&reward_account, Preservation::Expendable, Fortitude::Polite); let _ = T::Currency::transfer( &reward_account, &bonded_pool.roles.depositor, reward_pool_remaining, - ExistenceRequirement::AllowDeath, + Preservation::Expendable, ); // NOTE: this is purely defensive. @@ -2868,9 +2883,8 @@ impl Pallet { &bonded_pool.reward_account(), member_account, pending_rewards, - // defensive: the depositor has put existential deposit into the pool and it stays - // untouched, reward account shall not die. - ExistenceRequirement::KeepAlive, + // defensive: the depositor has put existential deposit into the pool and it stays::Preservation + // untouched, reward account shall not die.::Preserve, )?; Self::deposit_event(Event::::PaidOut { @@ -2878,7 +2892,6 @@ impl Pallet { pool_id: member.pool_id, payout: pending_rewards, }); - Ok(pending_rewards) } @@ -2913,11 +2926,17 @@ impl Pallet { bonded_pool.try_inc_members()?; let points = bonded_pool.try_bond_funds(&who, amount, BondType::Create)?; + // lock the minimum balance for the reward account. T::Currency::transfer( &who, &bonded_pool.reward_account(), T::Currency::minimum_balance(), - ExistenceRequirement::AllowDeath, + Preservation::Expendable, + )?; + T::Currency::set_freeze( + &FreezeReason::PoolMinimumBalance.into(), + &bonded_pool.reward_account(), + T::Currency::minimum_balance(), )?; PoolMembers::::insert( @@ -3030,8 +3049,7 @@ impl Pallet { T::Currency::transfer( &bonded_pool.reward_account(), &payee, - commission, - ExistenceRequirement::KeepAlive, + commission,Preservation::Preserve, )?; // Add pending commission to total claimed counter. @@ -3039,7 +3057,6 @@ impl Pallet { reward_pool.total_commission_claimed.saturating_add(commission); // Reset total pending commission counter to zero. reward_pool.total_commission_pending = Zero::zero(); - // Commit reward pool updates RewardPools::::insert(pool_id, reward_pool); Self::deposit_event(Event::::PoolCommissionClaimed { pool_id, commission }); @@ -3095,7 +3112,7 @@ impl Pallet { &who, &Self::create_reward_account(pool), top_up_amount, - ExistenceRequirement::KeepAlive, + Preservation::Preserve, )?; // The topped up amount should not be claimable by delegators. @@ -3182,14 +3199,14 @@ impl Pallet { for id in reward_pools { let account = Self::create_reward_account(id); - if T::Currency::free_balance(&account) < T::Currency::minimum_balance() { + if T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite) < T::Currency::minimum_balance() { log!( warn, "reward pool of {:?}: {:?} (ed = {:?}), should only happen because ED has \ changed recently. Pool operators should be notified to top up the reward \ account", id, - T::Currency::free_balance(&account), + T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite), T::Currency::minimum_balance(), ) } diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 2ae4cd1b8685..4bd23af29f82 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -279,7 +279,7 @@ pub mod v2 { &reward_account, &who, last_claim, - ExistenceRequirement::KeepAlive, + Preservation::Preserve, ); if let Err(reason) = outcome { @@ -304,7 +304,7 @@ pub mod v2 { &reward_account, &bonded_pool.roles.depositor, leftover, - ExistenceRequirement::KeepAlive, + Preservation::Preserve ); log!(warn, "paying {:?} leftover to the depositor: {:?}", leftover, o); } From f3e8a4fb50fce8c79d09cb178367b0d1e346d570 Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 8 Sep 2023 19:32:42 +0200 Subject: [PATCH 056/103] remove balance dependency in genesis config altogether --- substrate/frame/nomination-pools/src/lib.rs | 11 ++++----- substrate/frame/nomination-pools/src/mock.rs | 24 ++++++++++++++++++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index bf9614945a4a..29e51236010e 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1532,7 +1532,7 @@ pub mod pallet { /// The nominating balance. // FIXME(ank4n) - type Currency: FungibleInspect + FungibleMutate + type Currency: FungibleMutate + fungible::MutateFreeze; type RuntimeFreezeReason: From; @@ -1675,8 +1675,8 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { - pub min_join_bond: BalanceOf, - pub min_create_bond: BalanceOf, + #[serde(skip)] + pub _config: sp_std::marker::PhantomData, pub max_pools: Option, pub max_members_per_pool: Option, pub max_members: Option, @@ -1686,8 +1686,7 @@ pub mod pallet { impl Default for GenesisConfig { fn default() -> Self { Self { - min_join_bond: Zero::zero(), - min_create_bond: Zero::zero(), + _config: Default::default(), max_pools: Some(16), max_members_per_pool: Some(32), max_members: Some(16 * 32), @@ -1699,8 +1698,6 @@ pub mod pallet { #[pallet::genesis_build] impl BuildGenesisConfig for GenesisConfig { fn build(&self) { - MinJoinBond::::put(self.min_join_bond); - MinCreateBond::::put(self.min_create_bond); if let Some(max_pools) = self.max_pools { MaxPools::::put(max_pools); } diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index e2198f6f0308..61e3ac2c92dd 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -40,6 +40,25 @@ pub fn default_reward_account() -> AccountId { Pools::create_reward_account(1) } +#[derive( +Encode, +Decode, +Copy, +Clone, +Eq, +PartialEq, +Ord, +PartialOrd, +MaxEncodedLen, +TypeInfo, +RuntimeDebug, +)] +pub enum TestId { + Foo, + Bar, + Baz, +} + parameter_types! { pub static MinJoinBondConfig: Balance = 2; pub static CurrentEra: EraIndex = 0; @@ -51,8 +70,8 @@ parameter_types! { pub static StakingMinBond: Balance = 10; pub storage Nominations: Option> = None; } - pub struct StakingMock; + impl StakingMock { pub(crate) fn set_bonded_balance(who: AccountId, bonded: Balance) { let mut x = BondedBalanceMap::get(); @@ -221,7 +240,7 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type FreezeIdentifier = (); + type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); @@ -251,6 +270,7 @@ impl pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = RewardCounter; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; From 8a3891eecfd7854488d4e7441780d0d87b1095ab Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 19:18:52 +0200 Subject: [PATCH 057/103] compiles --- substrate/frame/nomination-pools/src/lib.rs | 75 ++++++---- .../frame/nomination-pools/src/migration.rs | 2 +- substrate/frame/nomination-pools/src/mock.rs | 36 +++-- substrate/frame/nomination-pools/src/tests.rs | 132 +++++++++--------- 4 files changed, 137 insertions(+), 108 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 29e51236010e..5ac0b1b57aa0 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -357,14 +357,14 @@ use frame_support::{ pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ - fungible::{Inspect as FungibleInspect, Mutate as FungibleMutate}, - tokens::Preservation, Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, + fungible::{Inspect as FunInspect, Mutate as FunMutate, MutateHold as FunMutateHold}, + tokens::{Fortitude, Preservation}, + Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, }, DefaultNoBound, PalletError, }; use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; -use frame_support::traits::tokens::Fortitude; use sp_core::U256; use sp_runtime::{ traits::{ @@ -406,7 +406,7 @@ pub use weights::WeightInfo; /// The balance type used by the currency system. pub type BalanceOf = - <::Currency as FungibleInspect<::AccountId>>::Balance; + <::Currency as FunInspect<::AccountId>>::Balance; /// Type used for unique identifier of each pool. pub type PoolId = u32; @@ -1390,8 +1390,12 @@ impl RewardPool { /// /// This is sum of all the rewards that are claimable by pool members. fn current_balance(id: PoolId) -> BalanceOf { - T::Currency::reducible_balance(&Pallet::::create_reward_account(id), Preservation::Expendable, Fortitude::Polite) - .saturating_sub(T::Currency::minimum_balance()) + T::Currency::reducible_balance( + &Pallet::::create_reward_account(id), + Preservation::Expendable, + Fortitude::Polite, + ) + .saturating_sub(T::Currency::minimum_balance()) } } @@ -1510,8 +1514,7 @@ impl Get for TotalUnbondingPools { #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::traits::{fungible, StorageVersion}; - use frame_support::traits::tokens::Fortitude; + use frame_support::traits::{tokens::Fortitude, StorageVersion}; use frame_system::{ensure_signed, pallet_prelude::*}; use sp_runtime::Perbill; @@ -1530,12 +1533,13 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: weights::WeightInfo; - /// The nominating balance. - // FIXME(ank4n) - type Currency: FungibleMutate - + fungible::MutateFreeze; + /// The currency type used for nomination pool. + type Currency: FunMutate + + FunMutateHold; + - type RuntimeFreezeReason: From; + /// The reason to Hold the currency. + type RuntimeHoldReason: From; /// The type that is used for reward counter. /// @@ -1676,7 +1680,7 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { #[serde(skip)] - pub _config: sp_std::marker::PhantomData, + pub _config: PhantomData, pub max_pools: Option, pub max_members_per_pool: Option, pub max_members: Option, @@ -1885,11 +1889,10 @@ pub mod pallet { } } - /// A reason for freezing funds. + /// A reason for holding funds. #[pallet::composite_enum] - pub enum FreezeReason { - /// The Pallet has locked funds for maintaining the Existential Deposit of a - /// NominationPool. + pub enum HoldReason { + /// The Pallet has held funds for maintaining the Existential Deposit of a NominationPool. #[codec(index = 0)] PoolMinimumBalance, } @@ -2672,7 +2675,8 @@ pub mod pallet { #[pallet::compact] max_transfer: BalanceOf, ) -> DispatchResult { let who = ensure_signed(origin)?; - let caller_balance = T::Currency::reducible_balance(&who, Preservation::Expendable, Fortitude::Polite); + let caller_balance = + T::Currency::reducible_balance(&who, Preservation::Expendable, Fortitude::Polite); Self::do_top_up_reward_deficit(who, pool_id, max_transfer.min(caller_balance)) } } @@ -2741,7 +2745,11 @@ impl Pallet { // This shouldn't fail, but if it does we don't really care. Remaining balance can consist // of unclaimed pending commission, errorneous transfers to the reward account, etc. - let reward_pool_remaining = T::Currency::reducible_balance(&reward_account, Preservation::Expendable, Fortitude::Polite); + let reward_pool_remaining = T::Currency::reducible_balance( + &reward_account, + Preservation::Expendable, + Fortitude::Polite, + ); let _ = T::Currency::transfer( &reward_account, &bonded_pool.roles.depositor, @@ -2750,8 +2758,8 @@ impl Pallet { ); // NOTE: this is purely defensive. - T::Currency::make_free_balance_be(&reward_account, Zero::zero()); - T::Currency::make_free_balance_be(&bonded_pool.bonded_account(), Zero::zero()); + T::Currency::set_balance(&reward_account, Zero::zero()); + T::Currency::set_balance(&bonded_pool.bonded_account(), Zero::zero()); Self::deposit_event(Event::::Destroyed { pool_id: bonded_pool.id }); // Remove bonded pool metadata. @@ -2881,7 +2889,8 @@ impl Pallet { member_account, pending_rewards, // defensive: the depositor has put existential deposit into the pool and it stays::Preservation - // untouched, reward account shall not die.::Preserve, + // untouched, reward account shall not die. + Preservation::Preserve, )?; Self::deposit_event(Event::::PaidOut { @@ -2930,11 +2939,12 @@ impl Pallet { T::Currency::minimum_balance(), Preservation::Expendable, )?; - T::Currency::set_freeze( - &FreezeReason::PoolMinimumBalance.into(), + + let outcome = T::Currency::hold( + &HoldReason::PoolMinimumBalance.into(), &bonded_pool.reward_account(), T::Currency::minimum_balance(), - )?; + ); PoolMembers::::insert( who.clone(), @@ -3046,7 +3056,8 @@ impl Pallet { T::Currency::transfer( &bonded_pool.reward_account(), &payee, - commission,Preservation::Preserve, + commission, + Preservation::Preserve, )?; // Add pending commission to total claimed counter. @@ -3196,14 +3207,20 @@ impl Pallet { for id in reward_pools { let account = Self::create_reward_account(id); - if T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite) < T::Currency::minimum_balance() { + if T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite) < + T::Currency::minimum_balance() + { log!( warn, "reward pool of {:?}: {:?} (ed = {:?}), should only happen because ED has \ changed recently. Pool operators should be notified to top up the reward \ account", id, - T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite), + T::Currency::reducible_balance( + &account, + Preservation::Expendable, + Fortitude::Polite + ), T::Currency::minimum_balance(), ) } diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 4bd23af29f82..123c11f08ff5 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -127,7 +127,7 @@ pub mod v2 { use crate::mock::*; ExtBuilder::default().build_and_execute(|| { let join = |x| { - Balances::make_free_balance_be(&x, Balances::minimum_balance() + 10); + Currency::set_balance(&x, Balances::minimum_balance() + 10); frame_support::assert_ok!(Pools::join(RuntimeOrigin::signed(x), 10, 1)); }; diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 61e3ac2c92dd..17c65d89adaa 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -17,7 +17,7 @@ use super::*; use crate::{self as pools}; -use frame_support::{assert_ok, parameter_types, PalletId}; +use frame_support::{assert_ok, parameter_types, PalletId, traits::fungible::Mutate}; use frame_system::RawOrigin; use sp_runtime::{BuildStorage, FixedU128}; use sp_staking::Stake; @@ -29,6 +29,7 @@ pub type RewardCounter = FixedU128; // This sneaky little hack allows us to write code exactly as we would do in the pallet in the tests // as well, e.g. `StorageItem::::get()`. pub type T = Runtime; +pub type Currency = ::Currency; // Ext builder creates a pool with id 1. pub fn default_bonded_account() -> AccountId { @@ -60,7 +61,6 @@ pub enum TestId { } parameter_types! { - pub static MinJoinBondConfig: Balance = 2; pub static CurrentEra: EraIndex = 0; pub static BondingDuration: EraIndex = 3; pub storage BondedBalanceMap: BTreeMap = Default::default(); @@ -240,9 +240,9 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type FreezeIdentifier = RuntimeFreezeReason; + type FreezeIdentifier = (); type MaxFreezes = (); - type RuntimeHoldReason = (); + type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = (); } @@ -270,7 +270,7 @@ impl pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; - type RuntimeFreezeReason = RuntimeFreezeReason; + type RuntimeHoldReason = RuntimeHoldReason; type RewardCounter = RewardCounter; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -288,7 +288,7 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Storage, Event, Config}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Pools: pools::{Pallet, Call, Storage, Event}, + Pools: pools::{Pallet, Call, Storage, Event, HoldReason}, } ); @@ -297,6 +297,8 @@ pub struct ExtBuilder { max_members: Option, max_members_per_pool: Option, global_max_commission: Option, + min_join_bond: Option, + min_create_bond: Option, } impl Default for ExtBuilder { @@ -306,6 +308,8 @@ impl Default for ExtBuilder { max_members: Some(4), max_members_per_pool: Some(3), global_max_commission: Some(Perbill::from_percent(90)), + min_join_bond: Some(2), + min_create_bond: Some(2), } } } @@ -328,8 +332,13 @@ impl ExtBuilder { self } - pub fn min_join_bond(self, min: Balance) -> Self { - MinJoinBondConfig::set(min); + pub fn min_join_bond(mut self, min: Balance) -> Self { + self.min_join_bond = Some(min); + self + } + + pub fn min_create_bond(mut self, min: Balance) -> Self { + self.min_create_bond = Some(min); self } @@ -359,8 +368,7 @@ impl ExtBuilder { frame_system::GenesisConfig::::default().build_storage().unwrap(); let _ = crate::GenesisConfig:: { - min_join_bond: MinJoinBondConfig::get(), - min_create_bond: 2, + _config: Default::default(), max_pools: Some(2), max_members_per_pool: self.max_members_per_pool, max_members: self.max_members, @@ -374,14 +382,18 @@ impl ExtBuilder { // for events to be deposited. frame_system::Pallet::::set_block_number(1); + // Default min join and create bond to 2. + MinJoinBond::::put(self.min_join_bond.unwrap_or(2)); + MinCreateBond::::put(self.min_create_bond.unwrap_or(2)); + // make a pool let amount_to_bond = Pools::depositor_min_bond(); - Balances::make_free_balance_be(&10, amount_to_bond * 5); + ::Currency::set_balance(&10, amount_to_bond * 5); assert_ok!(Pools::create(RawOrigin::Signed(10).into(), amount_to_bond, 900, 901, 902)); assert_ok!(Pools::set_metadata(RuntimeOrigin::signed(900), 1, vec![1, 1])); let last_pool = LastPoolId::::get(); for (account_id, bonded) in self.members { - Balances::make_free_balance_be(&account_id, bonded * 2); + ::Currency::set_balance(&account_id, bonded * 2); assert_ok!(Pools::join(RawOrigin::Signed(account_id).into(), bonded, last_pool)); } }); diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 8f56a2d8d4e5..f61f6fc2dc5e 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -41,12 +41,12 @@ pub const DEFAULT_ROLES: PoolRoles = fn deposit_rewards(r: u128) { let b = Balances::free_balance(&default_reward_account()).checked_add(r).unwrap(); - Balances::make_free_balance_be(&default_reward_account(), b); + Currency::set_balance(&default_reward_account(), b); } fn remove_rewards(r: u128) { let b = Balances::free_balance(&default_reward_account()).checked_sub(r).unwrap(); - Balances::make_free_balance_be(&default_reward_account(), b); + Currency::set_balance(&default_reward_account(), b); } #[test] @@ -313,13 +313,13 @@ mod reward_pool { assert_eq!(RewardPool::::current_balance(2), 0); // Given - Balances::make_free_balance_be(&reward_account, Balances::minimum_balance()); + Currency::set_balance(&reward_account, Balances::minimum_balance()); // Then assert_eq!(RewardPool::::current_balance(2), 0); // Given - Balances::make_free_balance_be(&reward_account, Balances::minimum_balance() + 1); + Currency::set_balance(&reward_account, Balances::minimum_balance() + 1); // Then assert_eq!(RewardPool::::current_balance(2), 1); @@ -333,7 +333,7 @@ mod reward_pool { ExistentialDeposit::set(5); // 11 joins the pool - Balances::make_free_balance_be(&11, 500); + Currency::set_balance(&11, 500); assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); // new delegator does not have any pending rewards @@ -348,7 +348,7 @@ mod reward_pool { assert_eq!(reward_imbalance(1), Surplus(0)); // 12 joins the pool. - Balances::make_free_balance_be(&12, 500); + Currency::set_balance(&12, 500); assert_ok!(Pools::join(RuntimeOrigin::signed(12), 100, 1)); // Current reward balance is committed to last recorded reward counter of @@ -373,7 +373,7 @@ mod reward_pool { assert_eq!(reward_imbalance(1), Deficit(45)); // 13 joins the pool which commits the reward counter to reward pool. - Balances::make_free_balance_be(&13, 500); + Currency::set_balance(&13, 500); assert_ok!(Pools::join(RuntimeOrigin::signed(13), 100, 1)); // still a deficit @@ -408,14 +408,14 @@ mod reward_pool { ExistentialDeposit::set(5); // 11 joins the pool - Balances::make_free_balance_be(&11, 500); + Currency::set_balance(&11, 500); assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); // Pool some rewards deposit_rewards(100); // 12 joins the pool. - Balances::make_free_balance_be(&12, 500); + Currency::set_balance(&12, 500); assert_ok!(Pools::join(RuntimeOrigin::signed(12), 10, 1)); // When: pool ends up in reward deficit @@ -428,7 +428,7 @@ mod reward_pool { pool_events_since_last_call(); // Then: top up reduces the deficit - Balances::make_free_balance_be(&99, 1000); + Currency::set_balance(&99, 1000); // caller can set safe ceiling for top up. let max_top_up: Balance = 20; assert_ok!(Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, max_top_up)); @@ -463,7 +463,7 @@ mod reward_pool { fn topping_up_does_not_work_for_pools_with_no_deficit() { ExtBuilder::default().max_members_per_pool(Some(5)).build_and_execute(|| { // 11 joins the pool - Balances::make_free_balance_be(&11, 500); + Currency::set_balance(&11, 500); assert_ok!(Pools::join(RuntimeOrigin::signed(11), 90, 1)); // Pool some rewards @@ -650,7 +650,7 @@ mod join { }; ExtBuilder::default().with_check(0).build_and_execute(|| { // Given - Balances::make_free_balance_be(&11, ExistentialDeposit::get() + 2); + Currency::set_balance(&11, ExistentialDeposit::get() + 2); assert!(!PoolMembers::::contains_key(11)); // When @@ -678,7 +678,7 @@ mod join { StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 6); // And - Balances::make_free_balance_be(&12, ExistentialDeposit::get() + 12); + Currency::set_balance(&12, ExistentialDeposit::get() + 12); assert!(!PoolMembers::::contains_key(12)); // When @@ -814,12 +814,12 @@ mod join { assert_eq!(MaxPoolMembersPerPool::::get(), Some(3)); for i in 1..3 { let account = i + 100; - Balances::make_free_balance_be(&account, 100 + Balances::minimum_balance()); + Currency::set_balance(&account, 100 + Balances::minimum_balance()); assert_ok!(Pools::join(RuntimeOrigin::signed(account), 100, 1)); } - Balances::make_free_balance_be(&103, 100 + Balances::minimum_balance()); + Currency::set_balance(&103, 100 + Balances::minimum_balance()); // Then assert_eq!( @@ -841,7 +841,7 @@ mod join { assert_eq!(PoolMembers::::count(), 3); assert_eq!(MaxPoolMembers::::get(), Some(4)); - Balances::make_free_balance_be(&104, 100 + Balances::minimum_balance()); + Currency::set_balance(&104, 100 + Balances::minimum_balance()); assert_ok!(Pools::create(RuntimeOrigin::signed(104), 100, 104, 104, 104)); let pool_account = BondedPools::::iter() @@ -907,9 +907,9 @@ mod claim_payout { .add_members(vec![(40, 40), (50, 50)]) .build_and_execute(|| { // Given each member currently has a free balance of - Balances::make_free_balance_be(&10, 0); - Balances::make_free_balance_be(&40, 0); - Balances::make_free_balance_be(&50, 0); + Currency::set_balance(&10, 0); + Currency::set_balance(&40, 0); + Currency::set_balance(&50, 0); let ed = Balances::minimum_balance(); // and the reward pool has earned 100 in rewards @@ -1113,7 +1113,7 @@ mod claim_payout { Pools::get_member_with_pools(&10).unwrap(); // top up commission payee account to existential deposit - let _ = Balances::deposit_creating(&2, 5); + let _ = Currency::set_balance(&2, 5); // Set a commission pool 1 to 75%, with a payee set to `2` assert_ok!(Pools::set_commission( @@ -1213,7 +1213,7 @@ mod claim_payout { assert_eq!(member, del(1.5)); // Given the pool has earned no new rewards - Balances::make_free_balance_be(&default_reward_account(), ed); + Currency::set_balance(&default_reward_account(), ed); // When let payout = @@ -1420,7 +1420,7 @@ mod claim_payout { deposit_rewards(10); // 20 joins afterwards. - Balances::make_free_balance_be(&20, Balances::minimum_balance() + 10); + Currency::set_balance(&20, Balances::minimum_balance() + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); // reward by another 20 @@ -1463,7 +1463,7 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { deposit_rewards(3); - Balances::make_free_balance_be(&20, Balances::minimum_balance() + 10); + Currency::set_balance(&20, Balances::minimum_balance() + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); deposit_rewards(6); @@ -1520,12 +1520,12 @@ mod claim_payout { deposit_rewards(30); - Balances::make_free_balance_be(&20, ed + 10); + Currency::set_balance(&20, ed + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); deposit_rewards(100); - Balances::make_free_balance_be(&30, ed + 10); + Currency::set_balance(&30, ed + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(30), 10, 1)); deposit_rewards(60); @@ -1576,7 +1576,7 @@ mod claim_payout { assert_eq!(Pools::api_pending_rewards(10), Some(30)); assert_eq!(Pools::api_pending_rewards(20), None); - Balances::make_free_balance_be(&20, ed + 10); + Currency::set_balance(&20, ed + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); assert_eq!(Pools::api_pending_rewards(10), Some(30)); @@ -1588,7 +1588,7 @@ mod claim_payout { assert_eq!(Pools::api_pending_rewards(20), Some(50)); assert_eq!(Pools::api_pending_rewards(30), None); - Balances::make_free_balance_be(&30, ed + 10); + Currency::set_balance(&30, ed + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(30), 10, 1)); assert_eq!(Pools::api_pending_rewards(10), Some(30 + 50)); @@ -1624,9 +1624,9 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { let ed = Balances::minimum_balance(); - Balances::make_free_balance_be(&20, ed + 20); + Currency::set_balance(&20, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); - Balances::make_free_balance_be(&30, ed + 20); + Currency::set_balance(&30, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(30), 10, 1)); deposit_rewards(40); @@ -1676,7 +1676,7 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { let ed = Balances::minimum_balance(); - Balances::make_free_balance_be(&20, ed + 20); + Currency::set_balance(&20, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); deposit_rewards(30); @@ -1721,9 +1721,9 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { let ed = Balances::minimum_balance(); - Balances::make_free_balance_be(&20, ed + 20); + Currency::set_balance(&20, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); - Balances::make_free_balance_be(&30, ed + 20); + Currency::set_balance(&30, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(30), 10, 1)); // 10 gets 10, 20 gets 20, 30 gets 10 @@ -1790,7 +1790,7 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { let ed = Balances::minimum_balance(); - Balances::make_free_balance_be(&20, ed + 200); + Currency::set_balance(&20, ed + 200); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); // 10 gets 10, 20 gets 20, 30 gets 10 @@ -1863,7 +1863,7 @@ mod claim_payout { deposit_rewards(60); // create pool 2 - Balances::make_free_balance_be(&20, 100); + Currency::set_balance(&20, 100); assert_ok!(Pools::create(RuntimeOrigin::signed(20), 10, 20, 20, 20)); // has no impact -- initial @@ -1876,10 +1876,10 @@ mod claim_payout { assert_eq!(member_20.last_recorded_reward_counter, 0.into()); // pre-fund the reward account of pool id 3 with some funds. - Balances::make_free_balance_be(&Pools::create_reward_account(3), 10); + Currency::set_balance(&Pools::create_reward_account(3), 10); // create pool 3 - Balances::make_free_balance_be(&30, 100); + Currency::set_balance(&30, 100); assert_ok!(Pools::create(RuntimeOrigin::signed(30), 10, 30, 30, 30)); // reward counter is still the same. @@ -1919,7 +1919,7 @@ mod claim_payout { MaxPoolMembers::::set(None); MaxPoolMembersPerPool::::set(None); let join = |x, y| { - Balances::make_free_balance_be(&x, y + Balances::minimum_balance()); + Currency::set_balance(&x, y + Balances::minimum_balance()); assert_ok!(Pools::join(RuntimeOrigin::signed(x), y, 1)); }; @@ -1997,8 +1997,8 @@ mod claim_payout { assert_eq!(member_10.last_recorded_reward_counter, 0.into()); } - Balances::make_free_balance_be(&10, 100); - Balances::make_free_balance_be(&20, 100); + Currency::set_balance(&10, 100); + Currency::set_balance(&20, 100); // 10 bonds extra without any rewards. { @@ -2333,7 +2333,7 @@ mod claim_payout { #[test] fn claim_payout_other_works() { ExtBuilder::default().add_members(vec![(20, 20)]).build_and_execute(|| { - Balances::make_free_balance_be(&default_reward_account(), 8); + Currency::set_balance(&default_reward_account(), 8); // ... of which only 3 are claimable to make sure the reward account does not die. let claimable_reward = 8 - ExistentialDeposit::get(); // NOTE: easier to read if we use 3, so let's use the number instead of variable. @@ -2687,7 +2687,7 @@ mod unbond { // Given a slash from 600 -> 100 StakingMock::set_bonded_balance(default_bonded_account(), 100); // and unclaimed rewards of 600. - Balances::make_free_balance_be(&default_reward_account(), ed + 600); + Currency::set_balance(&default_reward_account(), ed + 600); // When assert_ok!(fully_unbond_permissioned(40)); @@ -3330,7 +3330,7 @@ mod unbond { assert_eq!(initial_reward_account, Balances::minimum_balance()); assert_eq!(initial_reward_account, 5); - Balances::make_free_balance_be( + Currency::set_balance( &default_reward_account(), 4 * Balances::minimum_balance(), ); @@ -3349,7 +3349,7 @@ mod unbond { ); CurrentEra::set(1); - Balances::make_free_balance_be( + Currency::set_balance( &default_reward_account(), 4 * Balances::minimum_balance(), ); @@ -3365,7 +3365,7 @@ mod unbond { ); CurrentEra::set(2); - Balances::make_free_balance_be( + Currency::set_balance( &default_reward_account(), 4 * Balances::minimum_balance(), ); @@ -3446,7 +3446,7 @@ mod withdraw_unbonded { let mut x = UnbondingBalanceMap::get(); *x.get_mut(&default_bonded_account()).unwrap() /= 5; UnbondingBalanceMap::set(&x); - Balances::make_free_balance_be( + Currency::set_balance( &default_bonded_account(), Balances::free_balance(&default_bonded_account()) / 2, // 300 ); @@ -3576,7 +3576,7 @@ mod withdraw_unbonded { // Given // current bond is 600, we slash it all to 300. StakingMock::set_bonded_balance(default_bonded_account(), 300); - Balances::make_free_balance_be(&default_bonded_account(), 300); + Currency::set_balance(&default_bonded_account(), 300); assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(300)); assert_ok!(fully_unbond_permissioned(40)); @@ -3706,7 +3706,7 @@ mod withdraw_unbonded { assert_ok!(Pools::fully_unbond(RuntimeOrigin::signed(10), 10)); // Simulate a slash that is not accounted for in the sub pools. - Balances::make_free_balance_be(&default_bonded_account(), 5); + Currency::set_balance(&default_bonded_account(), 5); assert_eq!( SubPoolsStorage::::get(1).unwrap().with_era, //------------------------------balance decrease is not account for @@ -4424,7 +4424,7 @@ mod create { assert!(!PoolMembers::::contains_key(11)); assert_err!(StakingMock::active_stake(&next_pool_stash), "balance not found"); - Balances::make_free_balance_be(&11, StakingMock::minimum_nominator_bond() + ed); + Currency::set_balance(&11, StakingMock::minimum_nominator_bond() + ed); assert_ok!(Pools::create( RuntimeOrigin::signed(11), StakingMock::minimum_nominator_bond(), @@ -4533,7 +4533,7 @@ mod create { assert_eq!(PoolMembers::::count(), 1); MaxPools::::put(3); MaxPoolMembers::::put(1); - Balances::make_free_balance_be(&11, 5 + 20); + Currency::set_balance(&11, 5 + 20); // Then let create = RuntimeCall::Pools(crate::Call::::create { @@ -4554,7 +4554,7 @@ mod create { ExtBuilder::default().build_and_execute(|| { let ed = Balances::minimum_balance(); - Balances::make_free_balance_be(&11, StakingMock::minimum_nominator_bond() + ed); + Currency::set_balance(&11, StakingMock::minimum_nominator_bond() + ed); assert_ok!(Pools::create( RuntimeOrigin::signed(11), StakingMock::minimum_nominator_bond(), @@ -4592,7 +4592,7 @@ mod create { fn set_claimable_actor_works() { ExtBuilder::default().build_and_execute(|| { // Given - Balances::make_free_balance_be(&11, ExistentialDeposit::get() + 2); + Currency::set_balance(&11, ExistentialDeposit::get() + 2); assert!(!PoolMembers::::contains_key(11)); // When @@ -4722,7 +4722,7 @@ mod set_state { assert_eq!(BondedPool::::get(1).unwrap().state, PoolState::Destroying); // Given - Balances::make_free_balance_be(&default_bonded_account(), Balance::max_value() / 10); + Currency::set_balance(&default_bonded_account(), Balance::max_value() / 10); unsafe_set_state(1, PoolState::Open); // When assert_ok!(Pools::set_state(RuntimeOrigin::signed(11), 1, PoolState::Destroying)); @@ -4846,7 +4846,7 @@ mod bond_extra { fn bond_extra_from_free_balance_creator() { ExtBuilder::default().build_and_execute(|| { // 10 is the owner and a member in pool 1, give them some more funds. - Balances::make_free_balance_be(&10, 100); + Currency::set_balance(&10, 100); // given assert_eq!(PoolMembers::::get(10).unwrap().points, 10); @@ -4890,7 +4890,7 @@ mod bond_extra { ExtBuilder::default().build_and_execute(|| { // put some money in the reward account, all of which will belong to 10 as the only // member of the pool. - Balances::make_free_balance_be(&default_reward_account(), 7); + Currency::set_balance(&default_reward_account(), 7); // ... if which only 2 is claimable to make sure the reward account does not die. let claimable_reward = 7 - ExistentialDeposit::get(); @@ -4929,7 +4929,7 @@ mod bond_extra { ExtBuilder::default().add_members(vec![(20, 20)]).build_and_execute(|| { // put some money in the reward account, all of which will belong to 10 as the only // member of the pool. - Balances::make_free_balance_be(&default_reward_account(), 8); + Currency::set_balance(&default_reward_account(), 8); // ... if which only 3 is claimable to make sure the reward account does not die. let claimable_reward = 8 - ExistentialDeposit::get(); // NOTE: easier to read of we use 3, so let's use the number instead of variable. @@ -4980,7 +4980,7 @@ mod bond_extra { #[test] fn bond_extra_other() { ExtBuilder::default().add_members(vec![(20, 20)]).build_and_execute(|| { - Balances::make_free_balance_be(&default_reward_account(), 8); + Currency::set_balance(&default_reward_account(), 8); // ... of which only 3 are claimable to make sure the reward account does not die. let claimable_reward = 8 - ExistentialDeposit::get(); // NOTE: easier to read if we use 3, so let's use the number instead of variable. @@ -5260,7 +5260,7 @@ mod reward_counter_precision { ] ); - Balances::make_free_balance_be(&20, tiny_bond); + Currency::set_balance(&20, tiny_bond); assert_ok!(Pools::join(RuntimeOrigin::signed(20), tiny_bond / 2, 1)); // Suddenly, add a shit ton of rewards. @@ -5307,7 +5307,7 @@ mod reward_counter_precision { // some whale now joins with the other half ot the total issuance. This will bloat all // the calculation regarding current reward counter. - Balances::make_free_balance_be(&20, pool_bond * 2); + Currency::set_balance(&20, pool_bond * 2); assert_ok!(Pools::join(RuntimeOrigin::signed(20), pool_bond, 1)); assert_eq!( @@ -5329,7 +5329,7 @@ mod reward_counter_precision { ); // now let a small member join with 10 DOTs. - Balances::make_free_balance_be(&30, 20 * DOT); + Currency::set_balance(&30, 20 * DOT); assert_ok!(Pools::join(RuntimeOrigin::signed(30), 10 * DOT, 1)); // and give a reasonably small reward to the pool. @@ -5372,7 +5372,7 @@ mod reward_counter_precision { // overflow. This test is actually a bit too lenient because all the reward counters are // set to zero. In other tests that we want to assert a scenario won't fail, we should // also set the reward counters to some large value. - Balances::make_free_balance_be(&20, pool_bond * 2); + Currency::set_balance(&20, pool_bond * 2); assert_err!( Pools::join(RuntimeOrigin::signed(20), pool_bond, 1), Error::::OverflowRisk @@ -5401,7 +5401,7 @@ mod reward_counter_precision { ); // and have a tiny fish join the pool as well.. - Balances::make_free_balance_be(&20, 20 * DOT); + Currency::set_balance(&20, 20 * DOT); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10 * DOT, 1)); // earn some small rewards @@ -5469,7 +5469,7 @@ mod reward_counter_precision { ); // and have a tiny fish join the pool as well.. - Balances::make_free_balance_be(&20, 20 * DOT); + Currency::set_balance(&20, 20 * DOT); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10 * DOT, 1)); // earn some small rewards @@ -6505,7 +6505,7 @@ mod commission { let pool_id = 1; // top up commission payee account to existential deposit - let _ = Balances::deposit_creating(&2, 5); + let _ = Currency::set_balance(&2, 5); // Set a commission pool 1 to 33%, with a payee set to `2` assert_ok!(Pools::set_commission( @@ -6719,7 +6719,7 @@ mod commission { Pools::get_member_with_pools(&10).unwrap(); // top up commission payee account to existential deposit - let _ = Balances::deposit_creating(&2, 5); + let _ = Currency::set_balance(&2, 5); // Set a commission pool 1 to 100%, with a payee set to `2` assert_ok!(Pools::set_commission( @@ -6762,7 +6762,7 @@ mod commission { Pools::get_member_with_pools(&10).unwrap(); // top up the commission payee account to existential deposit - let _ = Balances::deposit_creating(&2, 5); + let _ = Currency::set_balance(&2, 5); // Set a commission pool 1 to 100% fails. assert_noop!( @@ -6820,7 +6820,7 @@ mod commission { ExtBuilder::default().build_and_execute(|| { let pool_id = 1; - let _ = Balances::deposit_creating(&900, 5); + let _ = Currency::set_balance(&900, 5); assert_ok!(Pools::set_commission( RuntimeOrigin::signed(900), pool_id, From 5848428a770757f1279cd95ebd1d48ee2b27d52b Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 19:37:01 +0200 Subject: [PATCH 058/103] allow 1 holds --- substrate/frame/nomination-pools/src/lib.rs | 4 ++-- substrate/frame/nomination-pools/src/mock.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 5ac0b1b57aa0..16db783f5a03 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2940,11 +2940,11 @@ impl Pallet { Preservation::Expendable, )?; - let outcome = T::Currency::hold( + T::Currency::hold( &HoldReason::PoolMinimumBalance.into(), &bonded_pool.reward_account(), T::Currency::minimum_balance(), - ); + )?; PoolMembers::::insert( who.clone(), diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 17c65d89adaa..d01ed58a956c 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -243,7 +243,7 @@ impl pallet_balances::Config for Runtime { type FreezeIdentifier = (); type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; - type MaxHolds = (); + type MaxHolds = ConstU32<1>; } pub struct BalanceToU256; From 84b6246f5043825b2fa78bfd95bf31485dddcc17 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 20:01:44 +0200 Subject: [PATCH 059/103] freezing currency is more appropriate here --- substrate/frame/nomination-pools/src/lib.rs | 36 ++++++++++++-------- substrate/frame/nomination-pools/src/mock.rs | 11 +++--- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 16db783f5a03..db967ac1731d 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -357,7 +357,7 @@ use frame_support::{ pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ - fungible::{Inspect as FunInspect, Mutate as FunMutate, MutateHold as FunMutateHold}, + fungible::{Inspect as FunInspect, Mutate as FunMutate, MutateFreeze as FunMutateFreeze}, tokens::{Fortitude, Preservation}, Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, }, @@ -381,7 +381,6 @@ use sp_runtime::TryRuntimeError; /// The log target of this pallet. pub const LOG_TARGET: &str = "runtime::nomination-pools"; - // syntactic sugar for logging. #[macro_export] macro_rules! log { @@ -1534,12 +1533,7 @@ pub mod pallet { type WeightInfo: weights::WeightInfo; /// The currency type used for nomination pool. - type Currency: FunMutate - + FunMutateHold; - - - /// The reason to Hold the currency. - type RuntimeHoldReason: From; + type Currency: FunMutate + FunMutateFreeze; /// The type that is used for reward counter. /// @@ -1889,10 +1883,22 @@ pub mod pallet { } } - /// A reason for holding funds. - #[pallet::composite_enum] - pub enum HoldReason { - /// The Pallet has held funds for maintaining the Existential Deposit of a NominationPool. + /// A reason for freezing funds. + #[derive( + Encode, + Decode, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + MaxEncodedLen, + TypeInfo, + RuntimeDebug, + )] + pub enum FreezeReason { + /// The Pallet has frozen funds for maintaining the Existential Deposit of a NominationPool. #[codec(index = 0)] PoolMinimumBalance, } @@ -2888,7 +2894,7 @@ impl Pallet { &bonded_pool.reward_account(), member_account, pending_rewards, - // defensive: the depositor has put existential deposit into the pool and it stays::Preservation + // defensive: the depositor has put existential deposit into the pool and it stays // untouched, reward account shall not die. Preservation::Preserve, )?; @@ -2940,8 +2946,8 @@ impl Pallet { Preservation::Expendable, )?; - T::Currency::hold( - &HoldReason::PoolMinimumBalance.into(), + T::Currency::set_freeze( + &FreezeReason::PoolMinimumBalance, &bonded_pool.reward_account(), T::Currency::minimum_balance(), )?; diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index d01ed58a956c..cbd27b4fed64 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -240,10 +240,10 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = RuntimeHoldReason; - type MaxHolds = ConstU32<1>; + type FreezeIdentifier = FreezeReason; + type MaxFreezes = ConstU32<1>; + type RuntimeHoldReason = (); + type MaxHolds = (); } pub struct BalanceToU256; @@ -270,7 +270,6 @@ impl pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; - type RuntimeHoldReason = RuntimeHoldReason; type RewardCounter = RewardCounter; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -288,7 +287,7 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Storage, Event, Config}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Pools: pools::{Pallet, Call, Storage, Event, HoldReason}, + Pools: pools::{Pallet, Call, Storage, Event}, } ); From 4d34b59ff51af1cd091160274dffa20f248cccf0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 20:28:23 +0200 Subject: [PATCH 060/103] all tests pass --- substrate/frame/nomination-pools/src/lib.rs | 6 +++- substrate/frame/nomination-pools/src/tests.rs | 31 +++---------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index db967ac1731d..25710fec45da 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1394,7 +1394,6 @@ impl RewardPool { Preservation::Expendable, Fortitude::Polite, ) - .saturating_sub(T::Currency::minimum_balance()) } } @@ -2734,6 +2733,11 @@ impl Pallet { ReversePoolIdLookup::::remove(&bonded_account); RewardPools::::remove(bonded_pool.id); SubPoolsStorage::::remove(bonded_pool.id); + // remove the frozen ED from the reward account. + let _ = T::Currency::thaw( + &FreezeReason::PoolMinimumBalance, + &bonded_pool.reward_account(), + ).defensive(); // Kill accounts from storage by making their balance go below ED. We assume that the // accounts have no references that would prevent destruction once we get to this point. We diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index f61f6fc2dc5e..75f2d6623626 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -301,31 +301,6 @@ mod reward_pool { use super::*; use crate::mock::RewardImbalance::{Deficit, Surplus}; - #[test] - fn current_balance_only_counts_balance_over_existential_deposit() { - ExtBuilder::default().build_and_execute(|| { - let reward_account = Pools::create_reward_account(2); - - // Given - assert_eq!(Balances::free_balance(&reward_account), 0); - - // Then - assert_eq!(RewardPool::::current_balance(2), 0); - - // Given - Currency::set_balance(&reward_account, Balances::minimum_balance()); - - // Then - assert_eq!(RewardPool::::current_balance(2), 0); - - // Given - Currency::set_balance(&reward_account, Balances::minimum_balance() + 1); - - // Then - assert_eq!(RewardPool::::current_balance(2), 1); - }); - } - #[test] fn ed_change_causes_reward_deficit() { ExtBuilder::default().max_members_per_pool(Some(5)).build_and_execute(|| { @@ -3493,7 +3468,7 @@ mod withdraw_unbonded { ); assert_eq!( balances_events_since_last_call(), - vec![BEvent::BalanceSet { who: default_bonded_account(), free: 300 }] + vec![BEvent::Burned { who: default_bonded_account(), amount: 300 }] ); // When @@ -3560,6 +3535,7 @@ mod withdraw_unbonded { balances_events_since_last_call(), vec![ BEvent::Transfer { from: default_bonded_account(), to: 10, amount: 5 }, + BEvent::Thawed { who: default_reward_account(), amount: 5 }, BEvent::Transfer { from: default_reward_account(), to: 10, amount: 5 } ] ); @@ -3607,7 +3583,7 @@ mod withdraw_unbonded { ); assert_eq!( balances_events_since_last_call(), - vec![BEvent::BalanceSet { who: default_bonded_account(), free: 300 },] + vec![BEvent::Burned { who: default_bonded_account(), amount: 300 },] ); CurrentEra::set(StakingMock::bonding_duration()); @@ -3689,6 +3665,7 @@ mod withdraw_unbonded { balances_events_since_last_call(), vec![ BEvent::Transfer { from: default_bonded_account(), to: 10, amount: 5 }, + BEvent::Thawed { who: default_reward_account(), amount: 5 }, BEvent::Transfer { from: default_reward_account(), to: 10, amount: 5 } ] ); From c5fc61d64ab56defe27b73884b1db02a93a362ba Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 20:58:52 +0200 Subject: [PATCH 061/103] use Currency trait to read free balance --- substrate/frame/nomination-pools/src/tests.rs | 204 +++++++++--------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 75f2d6623626..ec6a05d75e35 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -40,12 +40,12 @@ pub const DEFAULT_ROLES: PoolRoles = PoolRoles { depositor: 10, root: Some(900), nominator: Some(901), bouncer: Some(902) }; fn deposit_rewards(r: u128) { - let b = Balances::free_balance(&default_reward_account()).checked_add(r).unwrap(); + let b = Currency::free_balance(&default_reward_account()).checked_add(r).unwrap(); Currency::set_balance(&default_reward_account(), b); } fn remove_rewards(r: u128) { - let b = Balances::free_balance(&default_reward_account()).checked_sub(r).unwrap(); + let b = Currency::free_balance(&default_reward_account()).checked_sub(r).unwrap(); Currency::set_balance(&default_reward_account(), b); } @@ -99,7 +99,7 @@ fn test_setup_works() { assert!(Nominations::get().is_none()); // reward account should have an initial ED in it. - assert_eq!(Balances::free_balance(&reward_account), Balances::minimum_balance()); + assert_eq!(Currency::free_balance(&reward_account), Currency::minimum_balance()); }) } @@ -789,12 +789,12 @@ mod join { assert_eq!(MaxPoolMembersPerPool::::get(), Some(3)); for i in 1..3 { let account = i + 100; - Currency::set_balance(&account, 100 + Balances::minimum_balance()); + Currency::set_balance(&account, 100 + Currency::minimum_balance()); assert_ok!(Pools::join(RuntimeOrigin::signed(account), 100, 1)); } - Currency::set_balance(&103, 100 + Balances::minimum_balance()); + Currency::set_balance(&103, 100 + Currency::minimum_balance()); // Then assert_eq!( @@ -816,7 +816,7 @@ mod join { assert_eq!(PoolMembers::::count(), 3); assert_eq!(MaxPoolMembers::::get(), Some(4)); - Currency::set_balance(&104, 100 + Balances::minimum_balance()); + Currency::set_balance(&104, 100 + Currency::minimum_balance()); assert_ok!(Pools::create(RuntimeOrigin::signed(104), 100, 104, 104, 104)); let pool_account = BondedPools::::iter() @@ -885,10 +885,10 @@ mod claim_payout { Currency::set_balance(&10, 0); Currency::set_balance(&40, 0); Currency::set_balance(&50, 0); - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); // and the reward pool has earned 100 in rewards - assert_eq!(Balances::free_balance(default_reward_account()), ed); + assert_eq!(Currency::free_balance(&default_reward_account()), ed); deposit_rewards(100); let _ = pool_events_since_last_call(); @@ -906,8 +906,8 @@ mod claim_payout { // pool's 'last_recorded_reward_counter' and 'last_recorded_total_payouts' don't // really change unless if someone bonds/unbonds. assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 10)); - assert_eq!(Balances::free_balance(&10), 10); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 90); + assert_eq!(Currency::free_balance(&10), 10); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 90); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(40))); @@ -919,8 +919,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(40).unwrap(), del(40, 1)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 50)); - assert_eq!(Balances::free_balance(&40), 40); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 50); + assert_eq!(Currency::free_balance(&40), 40); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 50); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(50))); @@ -932,8 +932,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(50).unwrap(), del(50, 1)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 100)); - assert_eq!(Balances::free_balance(&50), 50); - assert_eq!(Balances::free_balance(&default_reward_account()), ed); + assert_eq!(Currency::free_balance(&50), 50); + assert_eq!(Currency::free_balance(&default_reward_account()), ed); // Given the reward pool has some new rewards deposit_rewards(50); @@ -948,8 +948,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(10).unwrap(), del_float(10, 1.5)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 105)); - assert_eq!(Balances::free_balance(&10), 10 + 5); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 45); + assert_eq!(Currency::free_balance(&10), 10 + 5); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 45); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(40))); @@ -961,12 +961,12 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(40).unwrap(), del_float(40, 1.5)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 125)); - assert_eq!(Balances::free_balance(&40), 40 + 20); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 25); + assert_eq!(Currency::free_balance(&40), 40 + 20); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 25); // Given del 50 hasn't claimed and the reward pools has just earned 50 deposit_rewards(50); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 75); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 75); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(50))); @@ -978,8 +978,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(50).unwrap(), del_float(50, 2.0)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 175)); - assert_eq!(Balances::free_balance(&50), 50 + 50); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 25); + assert_eq!(Currency::free_balance(&50), 50 + 50); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 25); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(10))); @@ -991,12 +991,12 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(10).unwrap(), del(10, 2)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 180)); - assert_eq!(Balances::free_balance(&10), 15 + 5); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 20); + assert_eq!(Currency::free_balance(&10), 15 + 5); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 20); // Given del 40 hasn't claimed and the reward pool has just earned 400 deposit_rewards(400); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 420); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 420); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(10))); @@ -1010,12 +1010,12 @@ mod claim_payout { // We expect a payout of 40 assert_eq!(PoolMembers::::get(10).unwrap(), del(10, 6)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 220)); - assert_eq!(Balances::free_balance(&10), 20 + 40); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 380); + assert_eq!(Currency::free_balance(&10), 20 + 40); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 380); // Given del 40 + del 50 haven't claimed and the reward pool has earned 20 deposit_rewards(20); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 400); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 400); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(10))); @@ -1027,8 +1027,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(10).unwrap(), del_float(10, 6.2)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 222)); - assert_eq!(Balances::free_balance(&10), 60 + 2); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 398); + assert_eq!(Currency::free_balance(&10), 60 + 2); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 398); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(40))); @@ -1040,8 +1040,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(40).unwrap(), del_float(40, 6.2)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 410)); - assert_eq!(Balances::free_balance(&40), 60 + 188); - assert_eq!(Balances::free_balance(&default_reward_account()), ed + 210); + assert_eq!(Currency::free_balance(&40), 60 + 188); + assert_eq!(Currency::free_balance(&default_reward_account()), ed + 210); // When assert_ok!(Pools::claim_payout(RuntimeOrigin::signed(50))); @@ -1053,8 +1053,8 @@ mod claim_payout { ); assert_eq!(PoolMembers::::get(50).unwrap(), del_float(50, 6.2)); assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 0, 620)); - assert_eq!(Balances::free_balance(&50), 100 + 210); - assert_eq!(Balances::free_balance(&default_reward_account()), ed); + assert_eq!(Currency::free_balance(&50), 100 + 210); + assert_eq!(Currency::free_balance(&default_reward_account()), ed); }); } @@ -1138,7 +1138,7 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { let (mut member, mut bonded_pool, mut reward_pool) = Pools::get_member_with_pools(&10).unwrap(); - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); let payout = Pools::do_reward_payout(&10, &mut member, &mut bonded_pool, &mut reward_pool) @@ -1395,7 +1395,7 @@ mod claim_payout { deposit_rewards(10); // 20 joins afterwards. - Currency::set_balance(&20, Balances::minimum_balance() + 10); + Currency::set_balance(&20, Currency::minimum_balance() + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); // reward by another 20 @@ -1438,7 +1438,7 @@ mod claim_payout { ExtBuilder::default().build_and_execute(|| { deposit_rewards(3); - Currency::set_balance(&20, Balances::minimum_balance() + 10); + Currency::set_balance(&20, Currency::minimum_balance() + 10); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); deposit_rewards(6); @@ -1491,7 +1491,7 @@ mod claim_payout { #[test] fn rewards_distribution_is_fair_3() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); deposit_rewards(30); @@ -1544,7 +1544,7 @@ mod claim_payout { #[test] fn pending_rewards_per_member_works() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); assert_eq!(Pools::api_pending_rewards(10), Some(0)); deposit_rewards(30); @@ -1597,7 +1597,7 @@ mod claim_payout { #[test] fn rewards_distribution_is_fair_bond_extra() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); Currency::set_balance(&20, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); @@ -1649,7 +1649,7 @@ mod claim_payout { #[test] fn rewards_distribution_is_fair_unbond() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); Currency::set_balance(&20, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); @@ -1694,7 +1694,7 @@ mod claim_payout { #[test] fn unclaimed_reward_is_safe() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); Currency::set_balance(&20, ed + 20); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); @@ -1763,7 +1763,7 @@ mod claim_payout { #[test] fn bond_extra_and_delayed_claim() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); Currency::set_balance(&20, ed + 200); assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); @@ -1860,8 +1860,8 @@ mod claim_payout { // reward counter is still the same. let (member_30, _, reward_pool_30) = Pools::get_member_with_pools(&30).unwrap(); assert_eq!( - Balances::free_balance(&Pools::create_reward_account(3)), - 10 + Balances::minimum_balance() + Currency::free_balance(&Pools::create_reward_account(3)), + 10 + Currency::minimum_balance() ); assert_eq!(reward_pool_30.last_recorded_total_payouts, 0); @@ -1894,7 +1894,7 @@ mod claim_payout { MaxPoolMembers::::set(None); MaxPoolMembersPerPool::::set(None); let join = |x, y| { - Currency::set_balance(&x, y + Balances::minimum_balance()); + Currency::set_balance(&x, y + Currency::minimum_balance()); assert_ok!(Pools::join(RuntimeOrigin::signed(x), y, 1)); }; @@ -2191,10 +2191,10 @@ mod claim_payout { ExtBuilder::default().add_members(vec![(20, 20)]).build_and_execute(|| { // initial balance of 10. - assert_eq!(Balances::free_balance(&10), 35); + assert_eq!(Currency::free_balance(&10), 35); assert_eq!( - Balances::free_balance(&default_reward_account()), - Balances::minimum_balance() + Currency::free_balance(&default_reward_account()), + Currency::minimum_balance() ); // some rewards come in. @@ -2243,7 +2243,7 @@ mod claim_payout { assert!(!Metadata::::contains_key(1)); // original ed + ed put into reward account + reward + bond + dust. - assert_eq!(Balances::free_balance(&10), 35 + 5 + 13 + 10 + 1); + assert_eq!(Currency::free_balance(&10), 35 + 5 + 13 + 10 + 1); }) } @@ -2259,7 +2259,7 @@ mod claim_payout { .add_members(vec![(20, 1500 * unit), (21, 2500 * unit), (22, 5000 * unit)]) .build_and_execute(|| { // some rewards come in. - assert_eq!(Balances::free_balance(&default_reward_account()), unit); + assert_eq!(Currency::free_balance(&default_reward_account()), unit); deposit_rewards(unit / 1000); // everyone claims @@ -2315,7 +2315,7 @@ mod claim_payout { assert_eq!(claimable_reward, 3, "test is correct if rewards are divisible by 3"); // given - assert_eq!(Balances::free_balance(10), 35); + assert_eq!(Currency::free_balance(&10), 35); // Permissioned by default assert_noop!( @@ -2330,8 +2330,8 @@ mod claim_payout { assert_ok!(Pools::claim_payout_other(RuntimeOrigin::signed(80), 10)); // then - assert_eq!(Balances::free_balance(10), 36); - assert_eq!(Balances::free_balance(&default_reward_account()), 7); + assert_eq!(Currency::free_balance(&10), 36); + assert_eq!(Currency::free_balance(&default_reward_account()), 7); }) } } @@ -2658,7 +2658,7 @@ mod unbond { ExtBuilder::default() .add_members(vec![(40, 40), (550, 550)]) .build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); // Given a slash from 600 -> 100 StakingMock::set_bonded_balance(default_bonded_account(), 100); // and unclaimed rewards of 600. @@ -2702,7 +2702,7 @@ mod unbond { PoolMembers::::get(40).unwrap().unbonding_eras, member_unbonding_eras!(3 => 6) ); - assert_eq!(Balances::free_balance(&40), 40 + 40); // We claim rewards when unbonding + assert_eq!(Currency::free_balance(&40), 40 + 40); // We claim rewards when unbonding // When unsafe_set_state(1, PoolState::Destroying); @@ -2731,7 +2731,7 @@ mod unbond { PoolMembers::::get(550).unwrap().unbonding_eras, member_unbonding_eras!(3 => 92) ); - assert_eq!(Balances::free_balance(&550), 550 + 550); + assert_eq!(Currency::free_balance(&550), 550 + 550); assert_eq!( pool_events_since_last_call(), vec![ @@ -2772,7 +2772,7 @@ mod unbond { ); assert_eq!(StakingMock::active_stake(&default_bonded_account()).unwrap(), 0); - assert_eq!(Balances::free_balance(&550), 550 + 550 + 92); + assert_eq!(Currency::free_balance(&550), 550 + 550 + 92); assert_eq!( pool_events_since_last_call(), vec![ @@ -3301,13 +3301,13 @@ mod unbond { #[test] fn every_unbonding_triggers_payout() { ExtBuilder::default().add_members(vec![(20, 20)]).build_and_execute(|| { - let initial_reward_account = Balances::free_balance(default_reward_account()); - assert_eq!(initial_reward_account, Balances::minimum_balance()); + let initial_reward_account = Currency::free_balance(&default_reward_account()); + assert_eq!(initial_reward_account, Currency::minimum_balance()); assert_eq!(initial_reward_account, 5); Currency::set_balance( &default_reward_account(), - 4 * Balances::minimum_balance(), + 4 * Currency::minimum_balance(), ); assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 2)); @@ -3326,7 +3326,7 @@ mod unbond { CurrentEra::set(1); Currency::set_balance( &default_reward_account(), - 4 * Balances::minimum_balance(), + 4 * Currency::minimum_balance(), ); assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 3)); @@ -3342,7 +3342,7 @@ mod unbond { CurrentEra::set(2); Currency::set_balance( &default_reward_account(), - 4 * Balances::minimum_balance(), + 4 * Currency::minimum_balance(), ); assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 5)); @@ -3368,12 +3368,12 @@ mod pool_withdraw_unbonded { #[test] fn pool_withdraw_unbonded_works() { ExtBuilder::default().build_and_execute(|| { - // Given 10 unbond'ed directly against the pool account + // Given 10 unbonded directly against the pool account assert_ok!(StakingMock::unbond(&default_bonded_account(), 5)); // and the pool account only has 10 balance assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(5)); assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(10)); - assert_eq!(Balances::free_balance(&default_bonded_account()), 10); + assert_eq!(Currency::free_balance(&default_bonded_account()), 10); // When assert_ok!(Pools::pool_withdraw_unbonded(RuntimeOrigin::signed(10), 1, 0)); @@ -3381,7 +3381,7 @@ mod pool_withdraw_unbonded { // Then there unbonding balance is no longer locked assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(5)); assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(5)); - assert_eq!(Balances::free_balance(&default_bonded_account()), 10); + assert_eq!(Currency::free_balance(&default_bonded_account()), 10); }); } } @@ -3402,7 +3402,7 @@ mod withdraw_unbonded { assert_eq!(StakingMock::bonding_duration(), 3); assert_ok!(Pools::fully_unbond(RuntimeOrigin::signed(550), 550)); assert_ok!(Pools::fully_unbond(RuntimeOrigin::signed(40), 40)); - assert_eq!(Balances::free_balance(&default_bonded_account()), 600); + assert_eq!(Currency::free_balance(&default_bonded_account()), 600); let mut current_era = 1; CurrentEra::set(current_era); @@ -3423,7 +3423,7 @@ mod withdraw_unbonded { UnbondingBalanceMap::set(&x); Currency::set_balance( &default_bonded_account(), - Balances::free_balance(&default_bonded_account()) / 2, // 300 + Currency::free_balance(&default_bonded_account()) / 2, // 300 ); StakingMock::set_bonded_balance( default_bonded_account(), @@ -3646,8 +3646,8 @@ mod withdraw_unbonded { assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 0)); // then - assert_eq!(Balances::free_balance(&10), 10 + 35); - assert_eq!(Balances::free_balance(&default_bonded_account()), 0); + assert_eq!(Currency::free_balance(&10), 10 + 35); + assert_eq!(Currency::free_balance(&default_bonded_account()), 0); // in this test 10 also gets a fair share of the slash, because the slash was // applied to the bonded account. @@ -3676,9 +3676,9 @@ mod withdraw_unbonded { fn withdraw_unbonded_handles_faulty_sub_pool_accounting() { ExtBuilder::default().build_and_execute(|| { // Given - assert_eq!(Balances::minimum_balance(), 5); - assert_eq!(Balances::free_balance(&10), 35); - assert_eq!(Balances::free_balance(&default_bonded_account()), 10); + assert_eq!(Currency::minimum_balance(), 5); + assert_eq!(Currency::free_balance(&10), 35); + assert_eq!(Currency::free_balance(&default_bonded_account()), 10); unsafe_set_state(1, PoolState::Destroying); assert_ok!(Pools::fully_unbond(RuntimeOrigin::signed(10), 10)); @@ -3696,8 +3696,8 @@ mod withdraw_unbonded { assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 0)); // Then - assert_eq!(Balances::free_balance(10), 10 + 35); - assert_eq!(Balances::free_balance(&default_bonded_account()), 0); + assert_eq!(Currency::free_balance(&10), 10 + 35); + assert_eq!(Currency::free_balance(&default_bonded_account()), 0); }); } @@ -3803,8 +3803,8 @@ mod withdraw_unbonded { // Can kick as bouncer assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(900), 200, 0)); - assert_eq!(Balances::free_balance(100), 100 + 100); - assert_eq!(Balances::free_balance(200), 200 + 200); + assert_eq!(Currency::free_balance(&100), 100 + 100); + assert_eq!(Currency::free_balance(&200), 200 + 200); assert!(!PoolMembers::::contains_key(100)); assert!(!PoolMembers::::contains_key(200)); assert_eq!(SubPoolsStorage::::get(1).unwrap(), Default::default()); @@ -3839,7 +3839,7 @@ mod withdraw_unbonded { } ); CurrentEra::set(StakingMock::bonding_duration()); - assert_eq!(Balances::free_balance(100), 100); + assert_eq!(Currency::free_balance(&100), 100); // Cannot permissionlessly withdraw assert_noop!( @@ -3850,11 +3850,11 @@ mod withdraw_unbonded { // Given unsafe_set_state(1, PoolState::Destroying); - // Can permissionlesly withdraw a member that is not the depositor + // Can permissionlessly withdraw a member that is not the depositor assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(420), 100, 0)); assert_eq!(SubPoolsStorage::::get(1).unwrap(), Default::default(),); - assert_eq!(Balances::free_balance(100), 100 + 100); + assert_eq!(Currency::free_balance(&100), 100 + 100); assert!(!PoolMembers::::contains_key(100)); assert_eq!( pool_events_since_last_call(), @@ -4394,7 +4394,7 @@ mod create { ExtBuilder::default().build_and_execute(|| { // next pool id is 2. let next_pool_stash = Pools::create_bonded_account(2); - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); assert!(!BondedPools::::contains_key(2)); assert!(!RewardPools::::contains_key(2)); @@ -4410,7 +4410,7 @@ mod create { 789 )); - assert_eq!(Balances::free_balance(&11), 0); + assert_eq!(Currency::free_balance(&11), 0); assert_eq!( PoolMembers::::get(11).unwrap(), PoolMember { @@ -4513,7 +4513,7 @@ mod create { Currency::set_balance(&11, 5 + 20); // Then - let create = RuntimeCall::Pools(crate::Call::::create { + let create = RuntimeCall::Pools(Call::::create { amount: 20, root: 11, nominator: 11, @@ -4529,7 +4529,7 @@ mod create { #[test] fn create_with_pool_id_works() { ExtBuilder::default().build_and_execute(|| { - let ed = Balances::minimum_balance(); + let ed = Currency::minimum_balance(); Currency::set_balance(&11, StakingMock::minimum_nominator_bond() + ed); assert_ok!(Pools::create( @@ -4540,7 +4540,7 @@ mod create { 789 )); - assert_eq!(Balances::free_balance(&11), 0); + assert_eq!(Currency::free_balance(&11), 0); // delete the initial pool created, then pool_Id `1` will be free assert_noop!( @@ -4699,7 +4699,7 @@ mod set_state { assert_eq!(BondedPool::::get(1).unwrap().state, PoolState::Destroying); // Given - Currency::set_balance(&default_bonded_account(), Balance::max_value() / 10); + Currency::set_balance(&default_bonded_account(), Balance::MAX / 10); unsafe_set_state(1, PoolState::Open); // When assert_ok!(Pools::set_state(RuntimeOrigin::signed(11), 1, PoolState::Destroying)); @@ -4828,13 +4828,13 @@ mod bond_extra { // given assert_eq!(PoolMembers::::get(10).unwrap().points, 10); assert_eq!(BondedPools::::get(1).unwrap().points, 10); - assert_eq!(Balances::free_balance(10), 100); + assert_eq!(Currency::free_balance(&10), 100); // when assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::FreeBalance(10))); // then - assert_eq!(Balances::free_balance(10), 90); + assert_eq!(Currency::free_balance(&10), 90); assert_eq!(PoolMembers::::get(10).unwrap().points, 20); assert_eq!(BondedPools::::get(1).unwrap().points, 20); @@ -4851,7 +4851,7 @@ mod bond_extra { assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::FreeBalance(20))); // then - assert_eq!(Balances::free_balance(10), 70); + assert_eq!(Currency::free_balance(&10), 70); assert_eq!(PoolMembers::::get(10).unwrap().points, 40); assert_eq!(BondedPools::::get(1).unwrap().points, 40); @@ -4874,13 +4874,13 @@ mod bond_extra { // given assert_eq!(PoolMembers::::get(10).unwrap().points, 10); assert_eq!(BondedPools::::get(1).unwrap().points, 10); - assert_eq!(Balances::free_balance(10), 35); + assert_eq!(Currency::free_balance(&10), 35); // when assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::Rewards)); // then - assert_eq!(Balances::free_balance(10), 35); + assert_eq!(Currency::free_balance(&10), 35); assert_eq!(PoolMembers::::get(10).unwrap().points, 10 + claimable_reward); assert_eq!(BondedPools::::get(1).unwrap().points, 10 + claimable_reward); @@ -4916,15 +4916,15 @@ mod bond_extra { assert_eq!(PoolMembers::::get(10).unwrap().points, 10); assert_eq!(PoolMembers::::get(20).unwrap().points, 20); assert_eq!(BondedPools::::get(1).unwrap().points, 30); - assert_eq!(Balances::free_balance(10), 35); - assert_eq!(Balances::free_balance(20), 20); + assert_eq!(Currency::free_balance(&10), 35); + assert_eq!(Currency::free_balance(&20), 20); // when assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::Rewards)); - assert_eq!(Balances::free_balance(&default_reward_account()), 7); + assert_eq!(Currency::free_balance(&default_reward_account()), 7); // then - assert_eq!(Balances::free_balance(10), 35); + assert_eq!(Currency::free_balance(&10), 35); // 10's share of the reward is 1/3, since they gave 10/30 of the total shares. assert_eq!(PoolMembers::::get(10).unwrap().points, 10 + 1); assert_eq!(BondedPools::::get(1).unwrap().points, 30 + 1); @@ -4933,7 +4933,7 @@ mod bond_extra { assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(20), BondExtra::Rewards)); // then - assert_eq!(Balances::free_balance(20), 20); + assert_eq!(Currency::free_balance(&20), 20); // 20's share of the rewards is the other 2/3 of the rewards, since they have 20/30 of // the shares assert_eq!(PoolMembers::::get(20).unwrap().points, 20 + 2); @@ -4967,8 +4967,8 @@ mod bond_extra { assert_eq!(PoolMembers::::get(10).unwrap().points, 10); assert_eq!(PoolMembers::::get(20).unwrap().points, 20); assert_eq!(BondedPools::::get(1).unwrap().points, 30); - assert_eq!(Balances::free_balance(10), 35); - assert_eq!(Balances::free_balance(20), 20); + assert_eq!(Currency::free_balance(&10), 35); + assert_eq!(Currency::free_balance(&20), 20); // Permissioned by default assert_noop!( @@ -4981,10 +4981,10 @@ mod bond_extra { ClaimPermission::PermissionlessAll )); assert_ok!(Pools::bond_extra_other(RuntimeOrigin::signed(50), 10, BondExtra::Rewards)); - assert_eq!(Balances::free_balance(&default_reward_account()), 7); + assert_eq!(Currency::free_balance(&default_reward_account()), 7); // then - assert_eq!(Balances::free_balance(10), 35); + assert_eq!(Currency::free_balance(&10), 35); assert_eq!(PoolMembers::::get(10).unwrap().points, 10 + 1); assert_eq!(BondedPools::::get(1).unwrap().points, 30 + 1); @@ -5002,8 +5002,8 @@ mod bond_extra { )); // then - assert_eq!(Balances::free_balance(20), 12); - assert_eq!(Balances::free_balance(&default_reward_account()), 5); + assert_eq!(Currency::free_balance(&20), 12); + assert_eq!(Currency::free_balance(&default_reward_account()), 5); assert_eq!(PoolMembers::::get(20).unwrap().points, 30); assert_eq!(BondedPools::::get(1).unwrap().points, 41); }) @@ -5732,7 +5732,7 @@ mod commission { let member = 10; // Set the pool commission to 10% to test commission shares. Pool is topped up 40 points - // and `member` immediately claims their pending rewards. Reward pooll should still have + // and `member` immediately claims their pending rewards. Reward pool should still have // 10% share. // Given: From 22fd5deb62239799f3d0f1fb1c720a5ae2ff0be9 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 21:06:16 +0200 Subject: [PATCH 062/103] verify ed is frozen --- substrate/frame/nomination-pools/src/tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index ec6a05d75e35..85a3bd70a200 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -4388,6 +4388,7 @@ mod withdraw_unbonded { mod create { use super::*; + use frame_support::traits::fungible::InspectFreeze; #[test] fn create_works() { @@ -4446,6 +4447,9 @@ mod create { RewardPool { ..Default::default() } ); + // make sure ED is frozen on pool creation. + assert_eq!(Currency::balance_frozen(&FreezeReason::PoolMinimumBalance, &default_reward_account()), Currency::minimum_balance()); + assert_eq!( pool_events_since_last_call(), vec![ From b535954921b1fd3f99c26331ef40c521c2fb74c2 Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 21:06:40 +0200 Subject: [PATCH 063/103] format --- substrate/frame/nomination-pools/src/tests.rs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 85a3bd70a200..9b02020a402a 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -3305,10 +3305,7 @@ mod unbond { assert_eq!(initial_reward_account, Currency::minimum_balance()); assert_eq!(initial_reward_account, 5); - Currency::set_balance( - &default_reward_account(), - 4 * Currency::minimum_balance(), - ); + Currency::set_balance(&default_reward_account(), 4 * Currency::minimum_balance()); assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 2)); assert_eq!( @@ -3324,10 +3321,7 @@ mod unbond { ); CurrentEra::set(1); - Currency::set_balance( - &default_reward_account(), - 4 * Currency::minimum_balance(), - ); + Currency::set_balance(&default_reward_account(), 4 * Currency::minimum_balance()); assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 3)); assert_eq!( @@ -3340,10 +3334,7 @@ mod unbond { ); CurrentEra::set(2); - Currency::set_balance( - &default_reward_account(), - 4 * Currency::minimum_balance(), - ); + Currency::set_balance(&default_reward_account(), 4 * Currency::minimum_balance()); assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 5)); assert_eq!( @@ -4448,7 +4439,13 @@ mod create { ); // make sure ED is frozen on pool creation. - assert_eq!(Currency::balance_frozen(&FreezeReason::PoolMinimumBalance, &default_reward_account()), Currency::minimum_balance()); + assert_eq!( + Currency::balance_frozen( + &FreezeReason::PoolMinimumBalance, + &default_reward_account() + ), + Currency::minimum_balance() + ); assert_eq!( pool_events_since_last_call(), From 4a3387be6b8da0757317da2c7d604ff486369d7e Mon Sep 17 00:00:00 2001 From: Ankan Date: Wed, 13 Sep 2023 22:07:43 +0200 Subject: [PATCH 064/103] impl for adjusting ED --- substrate/frame/nomination-pools/src/lib.rs | 185 +++++++++--------- substrate/frame/nomination-pools/src/tests.rs | 14 +- 2 files changed, 102 insertions(+), 97 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 25710fec45da..3b7953a396b3 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -357,7 +357,10 @@ use frame_support::{ pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ - fungible::{Inspect as FunInspect, Mutate as FunMutate, MutateFreeze as FunMutateFreeze}, + fungible::{ + Inspect as FunInspect, InspectFreeze, Mutate as FunMutate, + MutateFreeze as FunMutateFreeze, + }, tokens::{Fortitude, Preservation}, Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, }, @@ -1045,6 +1048,9 @@ impl BondedPool { self.is_root(who) } + fn is_depositor(&self, who: &T::AccountId) -> bool { + &self.roles.depositor == who + } fn is_destroying(&self) -> bool { matches!(self.state, PoolState::Destroying) } @@ -1512,7 +1518,7 @@ impl Get for TotalUnbondingPools { #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::traits::{tokens::Fortitude, StorageVersion}; + use frame_support::traits::StorageVersion; use frame_system::{ensure_signed, pallet_prelude::*}; use sp_runtime::Perbill; @@ -1532,7 +1538,8 @@ pub mod pallet { type WeightInfo: weights::WeightInfo; /// The currency type used for nomination pool. - type Currency: FunMutate + FunMutateFreeze; + type Currency: FunMutate + + FunMutateFreeze; /// The type that is used for reward counter. /// @@ -1857,8 +1864,8 @@ pub mod pallet { InvalidPoolId, /// Bonding extra is restricted to the exact pending reward amount. BondExtraRestricted, - /// No reward deficit to top up. - NoRewardDeficit, + /// No imbalance in the ED deposit for the pool. + NothingToAdjust, } #[derive(Encode, Decode, PartialEq, TypeInfo, PalletError, RuntimeDebug)] @@ -1883,23 +1890,24 @@ pub mod pallet { } /// A reason for freezing funds. - #[derive( - Encode, - Decode, - Copy, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - MaxEncodedLen, - TypeInfo, - RuntimeDebug, - )] + #[derive( + Encode, + Decode, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + MaxEncodedLen, + TypeInfo, + RuntimeDebug, + )] pub enum FreezeReason { - /// The Pallet has frozen funds for maintaining the Existential Deposit of a NominationPool. + /// The Pallet has frozen funds for maintaining the Existential Deposit of a + /// NominationPool. #[codec(index = 0)] - PoolMinimumBalance, + PoolMinBalance, } #[pallet::call] @@ -2666,23 +2674,19 @@ pub mod pallet { Self::do_claim_commission(who, pool_id) } - /// Top up the reward deficit of a pool permissionlessly. + /// Top up the deficit or withdraw the excess ED from the pool. /// - /// This can happen in situations where ED has increased from the time the pool was created. - /// The increased ED eats up from the available rewards of the pool, and the pool can end up - /// with a net deficit. + /// When a pool is created, the pool depositor transfers ED to the reward account of the + /// pool. ED is subject to change and over time, the deposit in the reward account may be + /// insufficient to cover the ED deficit of the pool or vice-versa where there is excess + /// deposit to the pool. This call allows the pool operator to adjust the ED deposit of the + /// pool. #[pallet::call_index(21)] // FIXME(ank4n): bench + tests #[pallet::weight(T::WeightInfo::claim_commission())] - pub fn top_up_reward_deficit( - origin: OriginFor, - pool_id: PoolId, - #[pallet::compact] max_transfer: BalanceOf, - ) -> DispatchResult { + pub fn adjust_ed_deposit(origin: OriginFor, pool_id: PoolId) -> DispatchResult { let who = ensure_signed(origin)?; - let caller_balance = - T::Currency::reducible_balance(&who, Preservation::Expendable, Fortitude::Polite); - Self::do_top_up_reward_deficit(who, pool_id, max_transfer.min(caller_balance)) + Self::do_adjust_ed_deposit(who, pool_id) } } @@ -2734,10 +2738,8 @@ impl Pallet { RewardPools::::remove(bonded_pool.id); SubPoolsStorage::::remove(bonded_pool.id); // remove the frozen ED from the reward account. - let _ = T::Currency::thaw( - &FreezeReason::PoolMinimumBalance, - &bonded_pool.reward_account(), - ).defensive(); + let _ = T::Currency::thaw(&FreezeReason::PoolMinBalance, &bonded_pool.reward_account()) + .defensive(); // Kill accounts from storage by making their balance go below ED. We assume that the // accounts have no references that would prevent destruction once we get to this point. We @@ -2942,7 +2944,7 @@ impl Pallet { bonded_pool.try_inc_members()?; let points = bonded_pool.try_bond_funds(&who, amount, BondType::Create)?; - // lock the minimum balance for the reward account. + // Transfer the minimum balance for the reward account. T::Currency::transfer( &who, &bonded_pool.reward_account(), @@ -2950,11 +2952,8 @@ impl Pallet { Preservation::Expendable, )?; - T::Currency::set_freeze( - &FreezeReason::PoolMinimumBalance, - &bonded_pool.reward_account(), - T::Currency::minimum_balance(), - )?; + // Restrict reward account balance from going below ED. + Self::freeze_min_balance(&bonded_pool.reward_account())?; PoolMembers::::insert( who.clone(), @@ -3096,62 +3095,50 @@ impl Pallet { Ok(()) } - fn pool_pending_rewards(pool: PoolId) -> Result, sp_runtime::DispatchError> { - let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; - let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; - - let current_rc = if !bonded_pool.points.is_zero() { - let commission = bonded_pool.commission.current(); - reward_pool.current_reward_counter(pool, bonded_pool.points, commission)?.0 - } else { - Default::default() - }; - - Ok(PoolMembers::::iter() - .filter(|(_, d)| d.pool_id == pool) - .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) - .fold(0u32.into(), |acc: BalanceOf, x| acc.saturating_add(x))) + fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { + T::Currency::set_freeze( + &FreezeReason::PoolMinBalance, + reward_acc, + T::Currency::minimum_balance(), + ) } + fn do_adjust_ed_deposit(who: T::AccountId, pool: PoolId) -> DispatchResult { + let bonded_pool = BondedPool::::get(pool).ok_or(Error::::PoolNotFound)?; + // only depositor can adjust ED deposit. + ensure!(bonded_pool.is_depositor(&who), Error::::DoesNotHavePermission); - fn do_top_up_reward_deficit( - who: T::AccountId, - pool: PoolId, - max_transfer: BalanceOf, - ) -> DispatchResult { - let pool_pending_rewards = Self::pool_pending_rewards(pool)?; - let reward_balance = RewardPool::::current_balance(pool); - let deficit = pool_pending_rewards.saturating_sub(reward_balance); + let reward_acc = &bonded_pool.reward_account(); + let pre_frozen_balance = + T::Currency::balance_frozen(&FreezeReason::PoolMinBalance, reward_acc); + let min_balance = T::Currency::minimum_balance(); - ensure!(!deficit.is_zero(), Error::::NoRewardDeficit); - - // do not top up beyond the max transfer amount desired by the caller. - let top_up_amount = deficit.min(max_transfer); - T::Currency::transfer( - &who, - &Self::create_reward_account(pool), - top_up_amount, - Preservation::Preserve, - )?; + if pre_frozen_balance == min_balance { + return Err(Error::::NothingToAdjust.into()) + } - // The topped up amount should not be claimable by delegators. - RewardPools::::mutate(pool, |maybe_reward_pool| { - if let Some(pool) = maybe_reward_pool { - pool.last_recorded_total_payouts.saturating_accrue(top_up_amount); - Ok(()) - } else { - Err(Error::::PoolNotFound) - } - })?; + // Update frozen amount with current ED. + Self::freeze_min_balance(reward_acc)?; - Self::deposit_event(Event::::PoolToppedUp { - pool_id: pool, - top_up_value: top_up_amount, - deficit: deficit.saturating_sub(top_up_amount), - }); + if pre_frozen_balance > min_balance { + // Transfer excess back to depositor. + T::Currency::transfer( + reward_acc, + &who, + pre_frozen_balance.saturating_sub(min_balance), + Preservation::Preserve, + )?; + } else { + // Transfer ED deficit from depositor to the pool + T::Currency::transfer( + &who, + reward_acc, + min_balance.saturating_sub(pre_frozen_balance), + Preservation::Expendable, + )?; + } Ok(()) } - /// Ensure the correctness of the state of this pallet. /// /// This should be valid before or after each state transition of this pallet. @@ -3344,6 +3331,24 @@ impl Pallet { let member_lookup = T::Lookup::unlookup(member); Self::unbond(origin, member_lookup, points) } + + #[cfg(test)] + fn pool_pending_rewards(pool: PoolId) -> Result, sp_runtime::DispatchError> { + let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; + let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; + + let current_rc = if !bonded_pool.points.is_zero() { + let commission = bonded_pool.commission.current(); + reward_pool.current_reward_counter(pool, bonded_pool.points, commission)?.0 + } else { + Default::default() + }; + + Ok(PoolMembers::::iter() + .filter(|(_, d)| d.pool_id == pool) + .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) + .fold(0u32.into(), |acc: BalanceOf, x| acc.saturating_add(x))) + } } impl Pallet { diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 9b02020a402a..94566b7fc060 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -406,7 +406,7 @@ mod reward_pool { Currency::set_balance(&99, 1000); // caller can set safe ceiling for top up. let max_top_up: Balance = 20; - assert_ok!(Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, max_top_up)); + assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1)); // only upto max_transfer is topped up. assert_eq!( pool_events_since_last_call(), @@ -419,7 +419,7 @@ mod reward_pool { assert_eq!(reward_imbalance(1), Deficit(25)); // Top up the remaining deficit - assert_ok!(Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, 1000)); + assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1)); assert_eq!( pool_events_since_last_call(), vec![Event::PoolToppedUp { pool_id: 1, top_up_value: 25, deficit: 0 },] @@ -428,8 +428,8 @@ mod reward_pool { // Trying to top up again does not work assert_err!( - Pools::top_up_reward_deficit(RuntimeOrigin::signed(99), 1, 1000), - Error::::NoRewardDeficit + Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1), + Error::::NothingToAdjust ); }); } @@ -447,8 +447,8 @@ mod reward_pool { // Topping up fails assert_err!( - Pools::top_up_reward_deficit(RuntimeOrigin::signed(11), 1, 100), - Error::::NoRewardDeficit + Pools::adjust_ed_deposit(RuntimeOrigin::signed(11), 1), + Error::::NothingToAdjust ); }); } @@ -4441,7 +4441,7 @@ mod create { // make sure ED is frozen on pool creation. assert_eq!( Currency::balance_frozen( - &FreezeReason::PoolMinimumBalance, + &FreezeReason::PoolMinBalance, &default_reward_account() ), Currency::minimum_balance() From 36a87a4f93bb0a92beb99ae9eb91e2033dfdb2d7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 14 Sep 2023 10:16:10 +0200 Subject: [PATCH 065/103] use Runtime Freeze Reason --- substrate/frame/nomination-pools/src/lib.rs | 23 +++++-------------- substrate/frame/nomination-pools/src/mock.rs | 5 ++-- substrate/frame/nomination-pools/src/tests.rs | 2 +- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 3b7953a396b3..26891bae31b6 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1539,8 +1539,9 @@ pub mod pallet { /// The currency type used for nomination pool. type Currency: FunMutate - + FunMutateFreeze; + + FunMutateFreeze; + type RuntimeFreezeReason: From; /// The type that is used for reward counter. /// /// The arithmetic of the reward counter might saturate based on the size of the @@ -1890,19 +1891,7 @@ pub mod pallet { } /// A reason for freezing funds. - #[derive( - Encode, - Decode, - Copy, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - MaxEncodedLen, - TypeInfo, - RuntimeDebug, - )] + #[pallet::composite_enum] pub enum FreezeReason { /// The Pallet has frozen funds for maintaining the Existential Deposit of a /// NominationPool. @@ -2738,7 +2727,7 @@ impl Pallet { RewardPools::::remove(bonded_pool.id); SubPoolsStorage::::remove(bonded_pool.id); // remove the frozen ED from the reward account. - let _ = T::Currency::thaw(&FreezeReason::PoolMinBalance, &bonded_pool.reward_account()) + let _ = T::Currency::thaw(&FreezeReason::PoolMinBalance.into(), &bonded_pool.reward_account()) .defensive(); // Kill accounts from storage by making their balance go below ED. We assume that the @@ -3097,7 +3086,7 @@ impl Pallet { fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { T::Currency::set_freeze( - &FreezeReason::PoolMinBalance, + &FreezeReason::PoolMinBalance.into(), reward_acc, T::Currency::minimum_balance(), ) @@ -3109,7 +3098,7 @@ impl Pallet { let reward_acc = &bonded_pool.reward_account(); let pre_frozen_balance = - T::Currency::balance_frozen(&FreezeReason::PoolMinBalance, reward_acc); + T::Currency::balance_frozen(&FreezeReason::PoolMinBalance.into(), reward_acc); let min_balance = T::Currency::minimum_balance(); if pre_frozen_balance == min_balance { diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index cbd27b4fed64..3cd8f3c73e37 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -240,7 +240,7 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type FreezeIdentifier = FreezeReason; + type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = (); type MaxHolds = (); @@ -270,6 +270,7 @@ impl pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = RewardCounter; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -287,7 +288,7 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Storage, Event, Config}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Pools: pools::{Pallet, Call, Storage, Event}, + Pools: pools::{Pallet, Call, Storage, Event, FreezeReason}, } ); diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 94566b7fc060..35431c299616 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -4441,7 +4441,7 @@ mod create { // make sure ED is frozen on pool creation. assert_eq!( Currency::balance_frozen( - &FreezeReason::PoolMinBalance, + &FreezeReason::PoolMinBalance.into(), &default_reward_account() ), Currency::minimum_balance() From de12c8f06f7a6857f84f946eee04318e6adf0c55 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 14 Sep 2023 15:20:46 +0200 Subject: [PATCH 066/103] add tests for adjusting ED --- substrate/frame/nomination-pools/src/lib.rs | 29 ++++----- substrate/frame/nomination-pools/src/mock.rs | 2 +- substrate/frame/nomination-pools/src/tests.rs | 63 ++++++++++++------- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 26891bae31b6..9fa14d0b04ad 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1788,8 +1788,10 @@ pub mod pallet { }, /// Pool commission has been claimed. PoolCommissionClaimed { pool_id: PoolId, commission: BalanceOf }, - /// Pool topped up in case of a reward deficit. - PoolToppedUp { pool_id: PoolId, top_up_value: BalanceOf, deficit: BalanceOf }, + /// Topped up deficit in frozen ED of the reward pool. + MinBalanceDeficitAdjusted { pool_id: PoolId, amount: BalanceOf }, + /// Claimed excess frozen ED of af the reward pool. + MinBalanceExcessAdjusted { pool_id: PoolId, amount: BalanceOf }, } #[pallet::error] @@ -2727,8 +2729,9 @@ impl Pallet { RewardPools::::remove(bonded_pool.id); SubPoolsStorage::::remove(bonded_pool.id); // remove the frozen ED from the reward account. - let _ = T::Currency::thaw(&FreezeReason::PoolMinBalance.into(), &bonded_pool.reward_account()) - .defensive(); + let _ = + T::Currency::thaw(&FreezeReason::PoolMinBalance.into(), &bonded_pool.reward_account()) + .defensive(); // Kill accounts from storage by making their balance go below ED. We assume that the // accounts have no references that would prevent destruction once we get to this point. We @@ -3110,20 +3113,14 @@ impl Pallet { if pre_frozen_balance > min_balance { // Transfer excess back to depositor. - T::Currency::transfer( - reward_acc, - &who, - pre_frozen_balance.saturating_sub(min_balance), - Preservation::Preserve, - )?; + let excess = pre_frozen_balance.saturating_sub(min_balance); + T::Currency::transfer(reward_acc, &who, excess, Preservation::Preserve)?; + Self::deposit_event(Event::::MinBalanceExcessAdjusted { pool_id: pool, amount: excess }); } else { // Transfer ED deficit from depositor to the pool - T::Currency::transfer( - &who, - reward_acc, - min_balance.saturating_sub(pre_frozen_balance), - Preservation::Expendable, - )?; + let deficit = min_balance.saturating_sub(pre_frozen_balance); + T::Currency::transfer(&who, reward_acc, deficit, Preservation::Expendable)?; + Self::deposit_event(Event::::MinBalanceDeficitAdjusted { pool_id: pool, amount: deficit }); } Ok(()) diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 3cd8f3c73e37..15954d112b74 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -388,7 +388,7 @@ impl ExtBuilder { // make a pool let amount_to_bond = Pools::depositor_min_bond(); - ::Currency::set_balance(&10, amount_to_bond * 5); + Currency::set_balance(&10, amount_to_bond * 5); assert_ok!(Pools::create(RawOrigin::Signed(10).into(), amount_to_bond, 900, 901, 902)); assert_ok!(Pools::set_metadata(RuntimeOrigin::signed(900), 1, vec![1, 1])); let last_pool = LastPoolId::::get(); diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 35431c299616..170ed8cbe0ca 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -375,7 +375,7 @@ mod reward_pool { } #[test] - fn top_up_fixes_reward_deficit() { + fn ed_adjust_fixes_reward_deficit() { ExtBuilder::default().max_members_per_pool(Some(5)).build_and_execute(|| { // Given: pool has a reward deficit @@ -394,7 +394,6 @@ mod reward_pool { assert_ok!(Pools::join(RuntimeOrigin::signed(12), 10, 1)); // When: pool ends up in reward deficit - // increase ED ExistentialDeposit::set(50); assert_eq!(reward_imbalance(1), Deficit(45)); @@ -402,35 +401,55 @@ mod reward_pool { // clear events pool_events_since_last_call(); - // Then: top up reduces the deficit - Currency::set_balance(&99, 1000); - // caller can set safe ceiling for top up. - let max_top_up: Balance = 20; - assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1)); - // only upto max_transfer is topped up. - assert_eq!( - pool_events_since_last_call(), - vec![Event::PoolToppedUp { - pool_id: 1, - top_up_value: max_top_up, - deficit: 45 - max_top_up - },] + // Then: + // Only depositor (10) can adjust ED deposit. Others do not have permission. + assert_ok!(Currency::mint_into(&99, 100)); + assert_err!( + Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1), + Error::::DoesNotHavePermission ); - assert_eq!(reward_imbalance(1), Deficit(25)); - // Top up the remaining deficit - assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1)); + // make sure depositor has enough funds.. + assert_ok!(Currency::mint_into(&10, 100)); + let pre_dep_balance = Currency::free_balance(&10); + // adjust ED + assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1)); + // depositor's balance should decrease by 45 + assert_eq!(Currency::free_balance(&10), pre_dep_balance - 45); + assert_eq!(reward_imbalance(1), Surplus(0)); + assert_eq!( pool_events_since_last_call(), - vec![Event::PoolToppedUp { pool_id: 1, top_up_value: 25, deficit: 0 },] + vec![Event::MinBalanceDeficitAdjusted { + pool_id: 1, + amount: 45, + },] ); - assert_eq!(reward_imbalance(1), Surplus(0)); // Trying to top up again does not work assert_err!( - Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1), + Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1), Error::::NothingToAdjust ); + + // When: ED is decreased and reward account has excess ED frozen + ExistentialDeposit::set(5); + + // And:: adjust ED deposit is called + assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1)); + + // Then: excess ED is transferred back to depositor + assert_eq!(Currency::free_balance(&10), pre_dep_balance); + + assert_eq!( + pool_events_since_last_call(), + vec![Event::MinBalanceExcessAdjusted { + pool_id: 1, + amount: 45, + },] + ); + + }); } @@ -447,7 +466,7 @@ mod reward_pool { // Topping up fails assert_err!( - Pools::adjust_ed_deposit(RuntimeOrigin::signed(11), 1), + Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1), Error::::NothingToAdjust ); }); From 138ecb202c103c795eeb21e248a2d61f0b71efda Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 14 Sep 2023 15:22:43 +0200 Subject: [PATCH 067/103] fmt --- substrate/frame/nomination-pools/src/lib.rs | 10 +++++++-- .../frame/nomination-pools/src/migration.rs | 2 +- substrate/frame/nomination-pools/src/mock.rs | 21 +------------------ substrate/frame/nomination-pools/src/tests.rs | 12 ++--------- 4 files changed, 12 insertions(+), 33 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 9fa14d0b04ad..2721531b6340 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3115,12 +3115,18 @@ impl Pallet { // Transfer excess back to depositor. let excess = pre_frozen_balance.saturating_sub(min_balance); T::Currency::transfer(reward_acc, &who, excess, Preservation::Preserve)?; - Self::deposit_event(Event::::MinBalanceExcessAdjusted { pool_id: pool, amount: excess }); + Self::deposit_event(Event::::MinBalanceExcessAdjusted { + pool_id: pool, + amount: excess, + }); } else { // Transfer ED deficit from depositor to the pool let deficit = min_balance.saturating_sub(pre_frozen_balance); T::Currency::transfer(&who, reward_acc, deficit, Preservation::Expendable)?; - Self::deposit_event(Event::::MinBalanceDeficitAdjusted { pool_id: pool, amount: deficit }); + Self::deposit_event(Event::::MinBalanceDeficitAdjusted { + pool_id: pool, + amount: deficit, + }); } Ok(()) diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 123c11f08ff5..12c35f1073df 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -304,7 +304,7 @@ pub mod v2 { &reward_account, &bonded_pool.roles.depositor, leftover, - Preservation::Preserve + Preservation::Preserve, ); log!(warn, "paying {:?} leftover to the depositor: {:?}", leftover, o); } diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 15954d112b74..0ac3f83a3a06 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -17,7 +17,7 @@ use super::*; use crate::{self as pools}; -use frame_support::{assert_ok, parameter_types, PalletId, traits::fungible::Mutate}; +use frame_support::{assert_ok, parameter_types, traits::fungible::Mutate, PalletId}; use frame_system::RawOrigin; use sp_runtime::{BuildStorage, FixedU128}; use sp_staking::Stake; @@ -41,25 +41,6 @@ pub fn default_reward_account() -> AccountId { Pools::create_reward_account(1) } -#[derive( -Encode, -Decode, -Copy, -Clone, -Eq, -PartialEq, -Ord, -PartialOrd, -MaxEncodedLen, -TypeInfo, -RuntimeDebug, -)] -pub enum TestId { - Foo, - Bar, - Baz, -} - parameter_types! { pub static CurrentEra: EraIndex = 0; pub static BondingDuration: EraIndex = 3; diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 170ed8cbe0ca..8dd0945e48cc 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -420,10 +420,7 @@ mod reward_pool { assert_eq!( pool_events_since_last_call(), - vec![Event::MinBalanceDeficitAdjusted { - pool_id: 1, - amount: 45, - },] + vec![Event::MinBalanceDeficitAdjusted { pool_id: 1, amount: 45 },] ); // Trying to top up again does not work @@ -443,13 +440,8 @@ mod reward_pool { assert_eq!( pool_events_since_last_call(), - vec![Event::MinBalanceExcessAdjusted { - pool_id: 1, - amount: 45, - },] + vec![Event::MinBalanceExcessAdjusted { pool_id: 1, amount: 45 },] ); - - }); } From a1c4970846254661867196440abf63fa6b6d066e Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 14 Sep 2023 16:00:13 +0200 Subject: [PATCH 068/103] added by mistake while merging, reverting --- docker/scripts/staking-miner/README.md | 37 ---------------- .../scripts/staking-miner/build-injected.sh | 13 ------ docker/scripts/staking-miner/build.sh | 13 ------ .../staking-miner_Dockerfile.README.md | 3 -- .../staking-miner_builder.Dockerfile | 43 ------------------- docker/scripts/staking-miner/test-build.sh | 18 -------- 6 files changed, 127 deletions(-) delete mode 100644 docker/scripts/staking-miner/README.md delete mode 100755 docker/scripts/staking-miner/build-injected.sh delete mode 100755 docker/scripts/staking-miner/build.sh delete mode 100644 docker/scripts/staking-miner/staking-miner_Dockerfile.README.md delete mode 100644 docker/scripts/staking-miner/staking-miner_builder.Dockerfile delete mode 100755 docker/scripts/staking-miner/test-build.sh diff --git a/docker/scripts/staking-miner/README.md b/docker/scripts/staking-miner/README.md deleted file mode 100644 index 3610e1130316..000000000000 --- a/docker/scripts/staking-miner/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# staking-miner container image - -## Build using the Builder - -``` -./build.sh -``` - -## Build the injected Image - -You first need a valid Linux binary to inject. Let's assume this binary is located in `BIN_FOLDER`. - -``` -./build-injected.sh "$BIN_FOLDER" -``` - -## Test - -Here is how to test the image. We can generate a valid seed but the staking-miner will quickly notice that our -account is not funded and "does not exist". - -You may pass any ENV supported by the binary and must provide at least a few such as `SEED` and `URI`: -``` -ENV SEED="" -ENV URI="wss://rpc.polkadot.io:443" -ENV RUST_LOG="info" -``` - -``` -export SEED=$(subkey generate -n polkadot --output-type json | jq -r .secretSeed) -podman run --rm -it \ - -e URI="wss://rpc.polkadot.io:443" \ - -e RUST_LOG="info" \ - -e SEED \ - localhost/parity/staking-miner \ - dry-run seq-phragmen -``` diff --git a/docker/scripts/staking-miner/build-injected.sh b/docker/scripts/staking-miner/build-injected.sh deleted file mode 100755 index efe323b5fed8..000000000000 --- a/docker/scripts/staking-miner/build-injected.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -# Sample call: -# $0 /path/to/folder_with_staking-miner_binary -# This script replace the former dedicated staking-miner "injected" Dockerfile -# and shows how to use the generic binary_injected.dockerfile - -PROJECT_ROOT=`git rev-parse --show-toplevel` - -export BINARY=staking-miner -export ARTIFACTS_FOLDER=$1 - -$PROJECT_ROOT/docker/scripts/build-injected.sh diff --git a/docker/scripts/staking-miner/build.sh b/docker/scripts/staking-miner/build.sh deleted file mode 100755 index c2b6ab77e531..000000000000 --- a/docker/scripts/staking-miner/build.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -# Sample call: -# $0 /path/to/folder_with_staking-miner_binary -# This script replace the former dedicated staking-miner "injected" Dockerfile -# and shows how to use the generic binary_injected.dockerfile - -PROJECT_ROOT=`git rev-parse --show-toplevel` -ENGINE=podman - -echo "Building the staking-miner using the Builder image" -echo "PROJECT_ROOT=$PROJECT_ROOT" -$ENGINE build -t staking-miner -f "${PROJECT_ROOT}/docker/dockerfiles/staking-miner/staking-miner_builder.Dockerfile" "$PROJECT_ROOT" diff --git a/docker/scripts/staking-miner/staking-miner_Dockerfile.README.md b/docker/scripts/staking-miner/staking-miner_Dockerfile.README.md deleted file mode 100644 index ce424c42f479..000000000000 --- a/docker/scripts/staking-miner/staking-miner_Dockerfile.README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Staking-miner Docker image - -## [GitHub](https://github.com/paritytech/polkadot/tree/master/utils/staking-miner) diff --git a/docker/scripts/staking-miner/staking-miner_builder.Dockerfile b/docker/scripts/staking-miner/staking-miner_builder.Dockerfile deleted file mode 100644 index 0ae77f36c79d..000000000000 --- a/docker/scripts/staking-miner/staking-miner_builder.Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -FROM paritytech/ci-linux:production as builder - -# metadata -ARG VCS_REF -ARG BUILD_DATE -ARG IMAGE_NAME="staking-miner" -ARG PROFILE=production - -LABEL description="This is the build stage. Here we create the binary." - -WORKDIR /app -COPY . /app -RUN cargo build --locked --profile $PROFILE --package staking-miner - -# ===== SECOND STAGE ====== - -FROM docker.io/parity/base-bin:latest -LABEL description="This is the 2nd stage: a very small image where we copy the binary." -LABEL io.parity.image.authors="devops-team@parity.io" \ - io.parity.image.vendor="Parity Technologies" \ - io.parity.image.title="${IMAGE_NAME}" \ - io.parity.image.description="${IMAGE_NAME} for substrate based chains" \ - io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/scripts/ci/dockerfiles/${IMAGE_NAME}/${IMAGE_NAME}_builder.Dockerfile" \ - io.parity.image.revision="${VCS_REF}" \ - io.parity.image.created="${BUILD_DATE}" \ - io.parity.image.documentation="https://github.com/paritytech/polkadot/" - -ARG PROFILE=release -COPY --from=builder /app/target/$PROFILE/staking-miner /usr/local/bin - -# show backtraces -ENV RUST_BACKTRACE 1 - -USER parity - -ENV SEED="" -ENV URI="wss://rpc.polkadot.io" -ENV RUST_LOG="info" - -# check if the binary works in this container -RUN /usr/local/bin/staking-miner --version - -ENTRYPOINT [ "/usr/local/bin/staking-miner" ] diff --git a/docker/scripts/staking-miner/test-build.sh b/docker/scripts/staking-miner/test-build.sh deleted file mode 100755 index 0ce74e2df296..000000000000 --- a/docker/scripts/staking-miner/test-build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -TMP=$(mktemp -d) -ENGINE=${ENGINE:-podman} - -# You need to build an injected image first - -# Fetch some binaries -$ENGINE run --user root --rm -i \ - -v "$TMP:/export" \ - --entrypoint /bin/bash \ - parity/staking-miner -c \ - 'cp "$(which staking-miner)" /export' - -echo "Checking binaries we got:" -tree $TMP - -./build-injected.sh $TMP From 29465b108fce3d299b2c4bc77cbab93ef14199dc Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 14 Sep 2023 22:08:45 +0200 Subject: [PATCH 069/103] basic migration --- polkadot/runtime/kusama/src/lib.rs | 5 +- polkadot/runtime/polkadot/src/lib.rs | 5 +- polkadot/runtime/westend/src/lib.rs | 5 +- substrate/frame/nomination-pools/src/lib.rs | 8 +- .../frame/nomination-pools/src/migration.rs | 753 ++++++++++-------- 5 files changed, 416 insertions(+), 360 deletions(-) diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index 659a7052d2b7..b268b9d97cf6 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -310,7 +310,7 @@ impl pallet_balances::Config for Runtime { type MaxReserves = MaxReserves; type ReserveIdentifier = [u8; 8]; type WeightInfo = weights::pallet_balances::WeightInfo; - type FreezeIdentifier = (); + type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = ConstU32<1>; @@ -1451,6 +1451,7 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_nomination_pools::WeightInfo; type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -1578,7 +1579,7 @@ construct_runtime! { VoterList: pallet_bags_list::::{Pallet, Call, Storage, Event} = 39, // nomination pools: extension to staking. - NominationPools: pallet_nomination_pools::{Pallet, Call, Storage, Event, Config} = 41, + NominationPools: pallet_nomination_pools::{Pallet, Call, Storage, Event, Config, FreezeReason} = 41, // Fast unstake pallet: extension to staking. FastUnstake: pallet_fast_unstake = 42, diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index 45ea561b33fa..f15eb0a7ccb8 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -296,7 +296,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type WeightInfo = weights::pallet_balances::WeightInfo; type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); + type FreezeIdentifier = RuntimeFreezeReason; type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; } @@ -1283,6 +1283,7 @@ parameter_types! { impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = runtime_common::BalanceToU256; type U256ToBalance = runtime_common::U256ToBalance; @@ -1382,7 +1383,7 @@ construct_runtime! { VoterList: pallet_bags_list::::{Pallet, Call, Storage, Event} = 37, // Nomination pools: extension to staking. - NominationPools: pallet_nomination_pools::{Pallet, Call, Storage, Event, Config} = 39, + NominationPools: pallet_nomination_pools::{Pallet, Call, Storage, Event, Config, FreezeReason} = 39, // Fast unstake pallet: extension to staking. FastUnstake: pallet_fast_unstake = 40, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 7dfc781d2467..938dde4ba9ee 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -267,7 +267,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type WeightInfo = weights::pallet_balances::WeightInfo; type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); + type FreezeIdentifier = RuntimeFreezeReason; type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; } @@ -1242,6 +1242,7 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_nomination_pools::WeightInfo; type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -1329,7 +1330,7 @@ construct_runtime! { VoterList: pallet_bags_list::::{Pallet, Call, Storage, Event} = 25, // Nomination pools for staking. - NominationPools: pallet_nomination_pools::{Pallet, Call, Storage, Event, Config} = 29, + NominationPools: pallet_nomination_pools::{Pallet, Call, Storage, Event, Config, FreezeReason} = 29, // Fast unstake pallet: extension to staking. FastUnstake: pallet_fast_unstake = 30, diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 03699a88da10..a15e1c2c2b79 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3087,7 +3087,7 @@ impl Pallet { Ok(()) } - fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { + pub(crate) fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { T::Currency::set_freeze( &FreezeReason::PoolMinBalance.into(), reward_acc, @@ -3324,8 +3324,10 @@ impl Pallet { Self::unbond(origin, member_lookup, points) } - #[cfg(test)] - fn pool_pending_rewards(pool: PoolId) -> Result, sp_runtime::DispatchError> { + #[cfg(any(feature = "runtime-benchmarks", test))] + pub(crate) fn pool_pending_rewards( + pool: PoolId, + ) -> Result, sp_runtime::DispatchError> { let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 12c35f1073df..07a91166ccd0 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -22,56 +22,240 @@ use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; +pub mod v6 { + use super::*; -pub mod v1 { + /// Wrapper over `MigrateToV6` with convenience version checks. + pub type VersionedMigrateV6 = frame_support::migrations::VersionedMigration< + 5, + 6, + MigrateToV6, + crate::pallet::Pallet, + ::DbWeight, + >; + + /// This migration would restrict reward account of pools to go below ED by doing a named + /// freeze on all the existing pools. + pub struct MigrateToV6(sp_std::marker::PhantomData); + + impl MigrateToV6 { + fn freeze_ed(pool_id: PoolId) -> Result<(), ()> { + let reward_acc = Pallet::::create_reward_account(pool_id); + Pallet::::freeze_min_balance(&reward_acc).map_err(|_| ()) + } + } + impl OnRuntimeUpgrade for MigrateToV6 { + fn on_runtime_upgrade() -> Weight { + let mut failed = 0; + let mut success = 0; + + BondedPools::::iter_keys().for_each(|p| { + if Self::freeze_ed(p).is_ok() { + success += 1; + } else { + failed += 1; + } + }); + + log!(info, "Freezing ED succeeded for {} pools, failed for {} pools", success, failed); + + // fixme(ank4n) + T::DbWeight::get().reads_writes(1, 1) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + Ok(().encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_data: Vec) -> Result<(), TryRuntimeError> { + Ok(()) + } + } +} +pub mod v5 { use super::*; #[derive(Decode)] - pub struct OldPoolRoles { - pub depositor: AccountId, - pub root: AccountId, - pub nominator: AccountId, - pub bouncer: AccountId, + pub struct OldRewardPool { + last_recorded_reward_counter: T::RewardCounter, + last_recorded_total_payouts: BalanceOf, + total_rewards_claimed: BalanceOf, } - impl OldPoolRoles { - fn migrate_to_v1(self) -> PoolRoles { - PoolRoles { - depositor: self.depositor, - root: Some(self.root), - nominator: Some(self.nominator), - bouncer: Some(self.bouncer), + impl OldRewardPool { + fn migrate_to_v5(self) -> RewardPool { + RewardPool { + last_recorded_reward_counter: self.last_recorded_reward_counter, + last_recorded_total_payouts: self.last_recorded_total_payouts, + total_rewards_claimed: self.total_rewards_claimed, + total_commission_pending: Zero::zero(), + total_commission_claimed: Zero::zero(), } } } + /// This migration adds `total_commission_pending` and `total_commission_claimed` field to every + /// `RewardPool`, if any. + pub struct MigrateToV5(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for MigrateToV5 { + 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 == 5 && onchain == 4 { + let mut translated = 0u64; + RewardPools::::translate::, _>(|_id, old_value| { + translated.saturating_inc(); + Some(old_value.migrate_to_v5()) + }); + + current.put::>(); + log!(info, "Upgraded {} pools, storage to version {:?}", translated, current); + + // reads: translated + onchain version. + // writes: translated + current.put. + T::DbWeight::get().reads_writes(translated + 1, translated + 1) + } else { + log!(info, "Migration did not execute. This probably should be removed"); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + let rpool_keys = RewardPools::::iter_keys().count(); + let rpool_values = RewardPools::::iter_values().count(); + if rpool_keys != rpool_values { + log!(info, "🔥 There are {} undecodable RewardPools in storage. This migration will try to correct them. keys: {}, values: {}", rpool_keys.saturating_sub(rpool_values), rpool_keys, rpool_values); + } + + ensure!( + PoolMembers::::iter_keys().count() == PoolMembers::::iter_values().count(), + "There are undecodable PoolMembers in storage. This migration will not fix that." + ); + ensure!( + BondedPools::::iter_keys().count() == BondedPools::::iter_values().count(), + "There are undecodable BondedPools in storage. This migration will not fix that." + ); + ensure!( + SubPoolsStorage::::iter_keys().count() == + SubPoolsStorage::::iter_values().count(), + "There are undecodable SubPools in storage. This migration will not fix that." + ); + ensure!( + Metadata::::iter_keys().count() == Metadata::::iter_values().count(), + "There are undecodable Metadata in storage. This migration will not fix that." + ); + + Ok((rpool_values as u64).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(data: Vec) -> Result<(), TryRuntimeError> { + let old_rpool_values: u64 = Decode::decode(&mut &data[..]).unwrap(); + let rpool_keys = RewardPools::::iter_keys().count() as u64; + let rpool_values = RewardPools::::iter_values().count() as u64; + ensure!( + rpool_keys == rpool_values, + "There are STILL undecodable RewardPools - migration failed" + ); + + if old_rpool_values != rpool_values { + log!( + info, + "🎉 Fixed {} undecodable RewardPools.", + rpool_values.saturating_sub(old_rpool_values) + ); + } + + // ensure all RewardPools items now contain `total_commission_pending` and + // `total_commission_claimed` field. + ensure!( + RewardPools::::iter().all(|(_, reward_pool)| reward_pool + .total_commission_pending >= + Zero::zero() && reward_pool + .total_commission_claimed >= + Zero::zero()), + "a commission value has been incorrectly set" + ); + ensure!( + Pallet::::on_chain_storage_version() >= 5, + "nomination-pools::migration::v5: wrong storage version" + ); + + // These should not have been touched - just in case. + ensure!( + PoolMembers::::iter_keys().count() == PoolMembers::::iter_values().count(), + "There are undecodable PoolMembers in storage." + ); + ensure!( + BondedPools::::iter_keys().count() == BondedPools::::iter_values().count(), + "There are undecodable BondedPools in storage." + ); + ensure!( + SubPoolsStorage::::iter_keys().count() == + SubPoolsStorage::::iter_values().count(), + "There are undecodable SubPools in storage." + ); + ensure!( + Metadata::::iter_keys().count() == Metadata::::iter_values().count(), + "There are undecodable Metadata in storage." + ); + + Ok(()) + } + } +} + +pub mod v4 { + use super::*; + #[derive(Decode)] pub struct OldBondedPoolInner { pub points: BalanceOf, pub state: PoolState, pub member_counter: u32, - pub roles: OldPoolRoles, + pub roles: PoolRoles, } impl OldBondedPoolInner { - fn migrate_to_v1(self) -> BondedPoolInner { - // Note: `commission` field not introduced to `BondedPoolInner` until - // migration 4. + fn migrate_to_v4(self) -> BondedPoolInner { BondedPoolInner { - points: self.points, commission: Commission::default(), member_counter: self.member_counter, + points: self.points, state: self.state, - roles: self.roles.migrate_to_v1(), + roles: self.roles, } } } - /// Trivial migration which makes the roles of each pool optional. + /// Migrates from `v3` directly to `v5` to avoid the broken `v4` migration. + #[allow(deprecated)] + pub type MigrateV3ToV5 = (v4::MigrateToV4, v5::MigrateToV5); + + /// # Warning /// - /// Note: The depositor is not optional since they can never change. - pub struct MigrateToV1(sp_std::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 { + /// To avoid mangled storage please use `MigrateV3ToV5` instead. + /// See: github.com/paritytech/substrate/pull/13715 + /// + /// This migration adds a `commission` field to every `BondedPoolInner`, if + /// any. + #[deprecated( + note = "To avoid mangled storage please use `MigrateV3ToV5` instead. See: github.com/paritytech/substrate/pull/13715" + )] + pub struct MigrateToV4(sp_std::marker::PhantomData<(T, U)>); + #[allow(deprecated)] + impl> OnRuntimeUpgrade for MigrateToV4 { fn on_runtime_upgrade() -> Weight { let current = Pallet::::current_storage_version(); let onchain = Pallet::::on_chain_storage_version(); @@ -83,33 +267,128 @@ pub mod v1 { onchain ); - if current == 1 && onchain == 0 { - // this is safe to execute on any runtime that has a bounded number of pools. + if onchain == 3 { + log!(warn, "Please run MigrateToV5 immediately after this migration. See github.com/paritytech/substrate/pull/13715"); + let initial_global_max_commission = U::get(); + GlobalMaxCommission::::set(Some(initial_global_max_commission)); + log!( + info, + "Set initial global max commission to {:?}.", + initial_global_max_commission + ); + let mut translated = 0u64; BondedPools::::translate::, _>(|_key, old_value| { translated.saturating_inc(); - Some(old_value.migrate_to_v1()) + Some(old_value.migrate_to_v4()) }); - current.put::>(); - + StorageVersion::new(4).put::>(); log!(info, "Upgraded {} pools, storage to version {:?}", translated, current); - T::DbWeight::get().reads_writes(translated + 1, translated + 1) + // reads: translated + onchain version. + // writes: translated + current.put + initial global commission. + T::DbWeight::get().reads_writes(translated + 1, translated + 2) } else { - log!(info, "Migration did not executed. This probably should be removed"); + log!(info, "Migration did not execute. This probably should be removed"); T::DbWeight::get().reads(1) } } + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + Ok(Vec::new()) + } + #[cfg(feature = "try-runtime")] fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - // new version must be set. + // ensure all BondedPools items now contain an `inner.commission: Commission` field. ensure!( - Pallet::::on_chain_storage_version() == 1, - "The onchain version must be updated after the migration." + BondedPools::::iter().all(|(_, inner)| + // Check current + (inner.commission.current.is_none() || + inner.commission.current.is_some()) && + // Check max + (inner.commission.max.is_none() || inner.commission.max.is_some()) && + // Check change_rate + (inner.commission.change_rate.is_none() || + inner.commission.change_rate.is_some()) && + // Check throttle_from + (inner.commission.throttle_from.is_none() || + inner.commission.throttle_from.is_some())), + "a commission value has not been set correctly" + ); + ensure!( + GlobalMaxCommission::::get() == Some(U::get()), + "global maximum commission error" + ); + ensure!( + Pallet::::on_chain_storage_version() >= 4, + "nomination-pools::migration::v4: wrong storage version" + ); + Ok(()) + } + } +} + +pub mod v3 { + use super::*; + + /// This migration removes stale bonded-pool metadata, if any. + pub struct MigrateToV3(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for MigrateToV3 { + fn on_runtime_upgrade() -> Weight { + let current = Pallet::::current_storage_version(); + let onchain = Pallet::::on_chain_storage_version(); + + if onchain == 2 { + log!( + info, + "Running migration with current storage version {:?} / onchain {:?}", + current, + onchain + ); + + let mut metadata_iterated = 0u64; + let mut metadata_removed = 0u64; + Metadata::::iter_keys() + .filter(|id| { + metadata_iterated += 1; + !BondedPools::::contains_key(&id) + }) + .collect::>() + .into_iter() + .for_each(|id| { + metadata_removed += 1; + Metadata::::remove(&id); + }); + StorageVersion::new(3).put::>(); + // metadata iterated + bonded pools read + a storage version read + let total_reads = metadata_iterated * 2 + 1; + // metadata removed + a storage version write + let total_writes = metadata_removed + 1; + T::DbWeight::get().reads_writes(total_reads, total_writes) + } else { + log!(info, "MigrateToV3 should be removed"); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + Ok(Vec::new()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { + ensure!( + Metadata::::iter_keys().all(|id| BondedPools::::contains_key(&id)), + "not all of the stale metadata has been removed" + ); + ensure!( + Pallet::::on_chain_storage_version() >= 3, + "nomination-pools::migration::v3: wrong storage version" ); - Pallet::::try_state(frame_system::Pallet::::block_number())?; Ok(()) } } @@ -330,185 +609,14 @@ pub mod v2 { total_value_locked, total_points_locked, current - ); - current.put::>(); - - T::DbWeight::get().reads_writes(members_translated + 1, reward_pools_translated + 1) - } - } - - impl OnRuntimeUpgrade for MigrateToV2 { - 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 == 2 && onchain == 1 { - Self::run(current) - } else { - log!(info, "MigrateToV2 did not executed. This probably should be removed"); - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - // all reward accounts must have more than ED. - RewardPools::::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> { - ensure!( - T::Currency::free_balance(&Pallet::::create_reward_account(id)) >= - T::Currency::minimum_balance(), - "Reward accounts must have greater balance than ED." - ); - Ok(()) - })?; - - Ok(Vec::new()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - // new version must be set. - ensure!( - Pallet::::on_chain_storage_version() == 2, - "The onchain version must be updated after the migration." - ); - - // no reward or bonded pool has been skipped. - ensure!( - RewardPools::::iter().count() as u32 == RewardPools::::count(), - "The count of reward pools must remain the same after the migration." - ); - ensure!( - BondedPools::::iter().count() as u32 == BondedPools::::count(), - "The count of reward pools must remain the same after the migration." - ); - - // all reward pools must have exactly ED in them. This means no reward can be claimed, - // and that setting reward counters all over the board to zero will work henceforth. - RewardPools::::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> { - ensure!( - RewardPool::::current_balance(id) == Zero::zero(), - "Reward pool balance must be zero.", - ); - Ok(()) - })?; - - log!(info, "post upgrade hook for MigrateToV2 executed."); - Ok(()) - } - } -} - -pub mod v3 { - use super::*; - - /// This migration removes stale bonded-pool metadata, if any. - pub struct MigrateToV3(sp_std::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV3 { - fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); - let onchain = Pallet::::on_chain_storage_version(); - - if onchain == 2 { - log!( - info, - "Running migration with current storage version {:?} / onchain {:?}", - current, - onchain - ); - - let mut metadata_iterated = 0u64; - let mut metadata_removed = 0u64; - Metadata::::iter_keys() - .filter(|id| { - metadata_iterated += 1; - !BondedPools::::contains_key(&id) - }) - .collect::>() - .into_iter() - .for_each(|id| { - metadata_removed += 1; - Metadata::::remove(&id); - }); - StorageVersion::new(3).put::>(); - // metadata iterated + bonded pools read + a storage version read - let total_reads = metadata_iterated * 2 + 1; - // metadata removed + a storage version write - let total_writes = metadata_removed + 1; - T::DbWeight::get().reads_writes(total_reads, total_writes) - } else { - log!(info, "MigrateToV3 should be removed"); - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - Ok(Vec::new()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - ensure!( - Metadata::::iter_keys().all(|id| BondedPools::::contains_key(&id)), - "not all of the stale metadata has been removed" - ); - ensure!( - Pallet::::on_chain_storage_version() >= 3, - "nomination-pools::migration::v3: wrong storage version" - ); - Ok(()) - } - } -} - -pub mod v4 { - use super::*; - - #[derive(Decode)] - pub struct OldBondedPoolInner { - pub points: BalanceOf, - pub state: PoolState, - pub member_counter: u32, - pub roles: PoolRoles, - } + ); + current.put::>(); - impl OldBondedPoolInner { - fn migrate_to_v4(self) -> BondedPoolInner { - BondedPoolInner { - commission: Commission::default(), - member_counter: self.member_counter, - points: self.points, - state: self.state, - roles: self.roles, - } + T::DbWeight::get().reads_writes(members_translated + 1, reward_pools_translated + 1) } } - /// Migrates from `v3` directly to `v5` to avoid the broken `v4` migration. - #[allow(deprecated)] - pub type MigrateV3ToV5 = (v4::MigrateToV4, v5::MigrateToV5); - - /// # Warning - /// - /// To avoid mangled storage please use `MigrateV3ToV5` instead. - /// See: github.com/paritytech/substrate/pull/13715 - /// - /// This migration adds a `commission` field to every `BondedPoolInner`, if - /// any. - #[deprecated( - note = "To avoid mangled storage please use `MigrateV3ToV5` instead. See: github.com/paritytech/substrate/pull/13715" - )] - pub struct MigrateToV4(sp_std::marker::PhantomData<(T, U)>); - #[allow(deprecated)] - impl> OnRuntimeUpgrade for MigrateToV4 { + impl OnRuntimeUpgrade for MigrateToV2 { fn on_runtime_upgrade() -> Weight { let current = Pallet::::current_storage_version(); let onchain = Pallet::::on_chain_storage_version(); @@ -520,96 +628,112 @@ pub mod v4 { onchain ); - if onchain == 3 { - log!(warn, "Please run MigrateToV5 immediately after this migration. See github.com/paritytech/substrate/pull/13715"); - let initial_global_max_commission = U::get(); - GlobalMaxCommission::::set(Some(initial_global_max_commission)); - log!( - info, - "Set initial global max commission to {:?}.", - initial_global_max_commission - ); - - let mut translated = 0u64; - BondedPools::::translate::, _>(|_key, old_value| { - translated.saturating_inc(); - Some(old_value.migrate_to_v4()) - }); - - StorageVersion::new(4).put::>(); - log!(info, "Upgraded {} pools, storage to version {:?}", translated, current); - - // reads: translated + onchain version. - // writes: translated + current.put + initial global commission. - T::DbWeight::get().reads_writes(translated + 1, translated + 2) + if current == 2 && onchain == 1 { + Self::run(current) } else { - log!(info, "Migration did not execute. This probably should be removed"); + log!(info, "MigrateToV2 did not executed. This probably should be removed"); T::DbWeight::get().reads(1) } } #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, TryRuntimeError> { + // all reward accounts must have more than ED. + RewardPools::::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> { + ensure!( + >::balance(&Pallet::::create_reward_account(id)) >= + T::Currency::minimum_balance(), + "Reward accounts must have greater balance than ED." + ); + Ok(()) + })?; + Ok(Vec::new()) } #[cfg(feature = "try-runtime")] fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - // ensure all BondedPools items now contain an `inner.commission: Commission` field. + // new version must be set. ensure!( - BondedPools::::iter().all(|(_, inner)| - // Check current - (inner.commission.current.is_none() || - inner.commission.current.is_some()) && - // Check max - (inner.commission.max.is_none() || inner.commission.max.is_some()) && - // Check change_rate - (inner.commission.change_rate.is_none() || - inner.commission.change_rate.is_some()) && - // Check throttle_from - (inner.commission.throttle_from.is_none() || - inner.commission.throttle_from.is_some())), - "a commission value has not been set correctly" + Pallet::::on_chain_storage_version() == 2, + "The onchain version must be updated after the migration." ); + + // no reward or bonded pool has been skipped. ensure!( - GlobalMaxCommission::::get() == Some(U::get()), - "global maximum commission error" + RewardPools::::iter().count() as u32 == RewardPools::::count(), + "The count of reward pools must remain the same after the migration." ); ensure!( - Pallet::::on_chain_storage_version() >= 4, - "nomination-pools::migration::v4: wrong storage version" + BondedPools::::iter().count() as u32 == BondedPools::::count(), + "The count of reward pools must remain the same after the migration." ); + + // all reward pools must have exactly ED in them. This means no reward can be claimed, + // and that setting reward counters all over the board to zero will work henceforth. + RewardPools::::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> { + ensure!( + RewardPool::::current_balance(id) == Zero::zero(), + "Reward pool balance must be zero.", + ); + Ok(()) + })?; + + log!(info, "post upgrade hook for MigrateToV2 executed."); Ok(()) } } } -pub mod v5 { +pub mod v1 { use super::*; #[derive(Decode)] - pub struct OldRewardPool { - last_recorded_reward_counter: T::RewardCounter, - last_recorded_total_payouts: BalanceOf, - total_rewards_claimed: BalanceOf, + pub struct OldPoolRoles { + pub depositor: AccountId, + pub root: AccountId, + pub nominator: AccountId, + pub bouncer: AccountId, } - impl OldRewardPool { - fn migrate_to_v5(self) -> RewardPool { - RewardPool { - last_recorded_reward_counter: self.last_recorded_reward_counter, - last_recorded_total_payouts: self.last_recorded_total_payouts, - total_rewards_claimed: self.total_rewards_claimed, - total_commission_pending: Zero::zero(), - total_commission_claimed: Zero::zero(), + impl OldPoolRoles { + fn migrate_to_v1(self) -> PoolRoles { + PoolRoles { + depositor: self.depositor, + root: Some(self.root), + nominator: Some(self.nominator), + bouncer: Some(self.bouncer), } } } - /// This migration adds `total_commission_pending` and `total_commission_claimed` field to every - /// `RewardPool`, if any. - pub struct MigrateToV5(sp_std::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV5 { + #[derive(Decode)] + pub struct OldBondedPoolInner { + pub points: BalanceOf, + pub state: PoolState, + pub member_counter: u32, + pub roles: OldPoolRoles, + } + + impl OldBondedPoolInner { + fn migrate_to_v1(self) -> BondedPoolInner { + // Note: `commission` field not introduced to `BondedPoolInner` until + // migration 4. + BondedPoolInner { + points: self.points, + commission: Commission::default(), + member_counter: self.member_counter, + state: self.state, + roles: self.roles.migrate_to_v1(), + } + } + } + + /// Trivial migration which makes the roles of each pool optional. + /// + /// Note: The depositor is not optional since they can never change. + pub struct MigrateToV1(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { let current = Pallet::::current_storage_version(); let onchain = Pallet::::on_chain_storage_version(); @@ -621,106 +745,33 @@ pub mod v5 { onchain ); - if current == 5 && onchain == 4 { + if current == 1 && onchain == 0 { + // this is safe to execute on any runtime that has a bounded number of pools. let mut translated = 0u64; - RewardPools::::translate::, _>(|_id, old_value| { + BondedPools::::translate::, _>(|_key, old_value| { translated.saturating_inc(); - Some(old_value.migrate_to_v5()) + Some(old_value.migrate_to_v1()) }); current.put::>(); + log!(info, "Upgraded {} pools, storage to version {:?}", translated, current); - // reads: translated + onchain version. - // writes: translated + current.put. T::DbWeight::get().reads_writes(translated + 1, translated + 1) } else { - log!(info, "Migration did not execute. This probably should be removed"); + log!(info, "Migration did not executed. This probably should be removed"); T::DbWeight::get().reads(1) } } #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - let rpool_keys = RewardPools::::iter_keys().count(); - let rpool_values = RewardPools::::iter_values().count(); - if rpool_keys != rpool_values { - log!(info, "🔥 There are {} undecodable RewardPools in storage. This migration will try to correct them. keys: {}, values: {}", rpool_keys.saturating_sub(rpool_values), rpool_keys, rpool_values); - } - - ensure!( - PoolMembers::::iter_keys().count() == PoolMembers::::iter_values().count(), - "There are undecodable PoolMembers in storage. This migration will not fix that." - ); - ensure!( - BondedPools::::iter_keys().count() == BondedPools::::iter_values().count(), - "There are undecodable BondedPools in storage. This migration will not fix that." - ); - ensure!( - SubPoolsStorage::::iter_keys().count() == - SubPoolsStorage::::iter_values().count(), - "There are undecodable SubPools in storage. This migration will not fix that." - ); - ensure!( - Metadata::::iter_keys().count() == Metadata::::iter_values().count(), - "There are undecodable Metadata in storage. This migration will not fix that." - ); - - Ok((rpool_values as u64).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(data: Vec) -> Result<(), TryRuntimeError> { - let old_rpool_values: u64 = Decode::decode(&mut &data[..]).unwrap(); - let rpool_keys = RewardPools::::iter_keys().count() as u64; - let rpool_values = RewardPools::::iter_values().count() as u64; - ensure!( - rpool_keys == rpool_values, - "There are STILL undecodable RewardPools - migration failed" - ); - - if old_rpool_values != rpool_values { - log!( - info, - "🎉 Fixed {} undecodable RewardPools.", - rpool_values.saturating_sub(old_rpool_values) - ); - } - - // ensure all RewardPools items now contain `total_commission_pending` and - // `total_commission_claimed` field. - ensure!( - RewardPools::::iter().all(|(_, reward_pool)| reward_pool - .total_commission_pending >= - Zero::zero() && reward_pool - .total_commission_claimed >= - Zero::zero()), - "a commission value has been incorrectly set" - ); - ensure!( - Pallet::::on_chain_storage_version() >= 5, - "nomination-pools::migration::v5: wrong storage version" - ); - - // These should not have been touched - just in case. - ensure!( - PoolMembers::::iter_keys().count() == PoolMembers::::iter_values().count(), - "There are undecodable PoolMembers in storage." - ); - ensure!( - BondedPools::::iter_keys().count() == BondedPools::::iter_values().count(), - "There are undecodable BondedPools in storage." - ); - ensure!( - SubPoolsStorage::::iter_keys().count() == - SubPoolsStorage::::iter_values().count(), - "There are undecodable SubPools in storage." - ); + fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { + // new version must be set. ensure!( - Metadata::::iter_keys().count() == Metadata::::iter_values().count(), - "There are undecodable Metadata in storage." + Pallet::::on_chain_storage_version() == 1, + "The onchain version must be updated after the migration." ); - + Pallet::::try_state(frame_system::Pallet::::block_number())?; Ok(()) } } From 05592c774634b97d82a48396d846ac2f8c19dc5d Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 15 Sep 2023 10:50:09 +0200 Subject: [PATCH 070/103] migrations --- polkadot/runtime/kusama/src/lib.rs | 4 ++- polkadot/runtime/polkadot/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/lib.rs | 28 ++++++++++++++++- .../frame/nomination-pools/src/migration.rs | 31 ++++++++++--------- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index b268b9d97cf6..ed73834baa80 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -311,7 +311,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type WeightInfo = weights::pallet_balances::WeightInfo; type FreezeIdentifier = RuntimeFreezeReason; - type MaxFreezes = (); + type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = ConstU32<1>; } @@ -1758,6 +1758,8 @@ pub mod migrations { parachains_configuration::migration::v9::MigrateToV9, // Migrate parachain info format paras_registrar::migration::VersionCheckedMigrateToV1, + // Migrate Nomination Pools + pallet_nomination_pools::migration::v6::VersionedMigrateV6, ); } diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index f15eb0a7ccb8..aa2c6dabba5a 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -298,7 +298,7 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = RuntimeFreezeReason; type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; + type MaxFreezes = ConstU32<1>; } parameter_types! { diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 938dde4ba9ee..da282835f06d 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -269,7 +269,7 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = RuntimeFreezeReason; type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; + type MaxFreezes = ConstU32<1>; } parameter_types! { diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index a15e1c2c2b79..7f69cba76eda 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1523,7 +1523,7 @@ pub mod pallet { use sp_runtime::Perbill; /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(6); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -3307,9 +3307,35 @@ impl Pallet { ); } + // Warn if any pool has incorrect ED frozen. We don't want to fail hard as this could be a + // result of an intentional ED change. + let _ = Self::check_ed_imbalance()?; + Ok(()) } + #[cfg(any(feature = "try-runtime", test))] + pub fn check_ed_imbalance() -> Result<(), TryRuntimeError> { + let mut failed: u32 = 0; + BondedPools::::iter_keys().for_each(|id| { + let reward_acc = Self::create_reward_account(id); + let frozen_balance = + T::Currency::balance_frozen(&FreezeReason::PoolMinBalance.into(), &reward_acc); + + let expected_frozen_balance = T::Currency::minimum_balance(); + if frozen_balance != expected_frozen_balance { + failed += 1; + log::warn!( + "pool {:?} has incorrect ED frozen that can result from change in ED. Expected = {:?}, Actual = {:?}", + id, + expected_frozen_balance, + frozen_balance, + ); + } + }); + + ensure!(failed == 0, "Some pools do not have correct ED frozen"); + } /// Fully unbond the shares of `member`, when executed from `origin`. /// /// This is useful for backwards compatibility with the majority of tests that only deal with diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 07a91166ccd0..ac8a880874a7 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -41,36 +41,37 @@ pub mod v6 { impl MigrateToV6 { fn freeze_ed(pool_id: PoolId) -> Result<(), ()> { let reward_acc = Pallet::::create_reward_account(pool_id); - Pallet::::freeze_min_balance(&reward_acc).map_err(|_| ()) + Pallet::::freeze_min_balance(&reward_acc).map_err(|e| { + log!(error, "Failed to freeze ED for pool {} with error: {:?}", pool_id, e); + () + }) } } impl OnRuntimeUpgrade for MigrateToV6 { fn on_runtime_upgrade() -> Weight { - let mut failed = 0; - let mut success = 0; + let mut success = 0u64; + let mut fail = 0u64; BondedPools::::iter_keys().for_each(|p| { if Self::freeze_ed(p).is_ok() { - success += 1; + success.saturating_inc(); } else { - failed += 1; + fail.saturating_inc(); } }); - log!(info, "Freezing ED succeeded for {} pools, failed for {} pools", success, failed); - - // fixme(ank4n) - T::DbWeight::get().reads_writes(1, 1) - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - Ok(().encode()) + log!(info, "Freezing ED succeeded for {} pools, and failed for {} pools", success, fail); + let total = success + fail; + // freeze_ed = r:2 w:2 + // reads: (freeze_ed + bonded pool key) * total + // writes: freeze_ed * total + T::DbWeight::get().reads_writes(3*total, 2*total) } #[cfg(feature = "try-runtime")] fn post_upgrade(_data: Vec) -> Result<(), TryRuntimeError> { - Ok(()) + // there should be no ED imbalances anymore.. + Pallet::::check_ed_imbalance() } } } From b147cfe5682ebf10f3e8fb358eab2d2dbd595aa2 Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 15 Sep 2023 11:39:40 +0200 Subject: [PATCH 071/103] add weights to new call --- .../src/weights/pallet_nomination_pools.rs | 4 ++++ .../src/weights/pallet_nomination_pools.rs | 4 ++++ .../src/weights/pallet_nomination_pools.rs | 4 ++++ .../nomination-pools/benchmarking/src/lib.rs | 19 +++++++++++++++++++ .../nomination-pools/benchmarking/src/mock.rs | 16 +++++++++++----- substrate/frame/nomination-pools/src/lib.rs | 8 ++++---- substrate/frame/nomination-pools/src/tests.rs | 4 ++++ .../frame/nomination-pools/src/weights.rs | 9 +++++++++ 8 files changed, 59 insertions(+), 9 deletions(-) diff --git a/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs index 65bb76860b30..caabde494af4 100644 --- a/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs @@ -600,4 +600,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + + fn adjust_ed_deposit() -> Weight { + Weight::default() + } } diff --git a/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs index 7273389a0805..2c169bd0c825 100644 --- a/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs @@ -598,4 +598,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + + fn adjust_ed_deposit() -> Weight { + Weight::default() + } } diff --git a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs index 9d43eb249892..9ba4397df828 100644 --- a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs @@ -598,4 +598,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + + fn adjust_ed_deposit() -> Weight { + Weight::default() + } } diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 45f0ca0ecfe6..2a0e14d4619d 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -800,6 +800,25 @@ frame_benchmarking::benchmarks! { ); } + adjust_ed_deposit { + let min_bond = Pools::::depositor_min_bond(); + + // Set ED to 0 so no balance is frozen + ExistentialDeposit::set(0); + + // Create a pool + let (depositor, _) = create_pool_account::(0, min_bond * 2u32.into(), None); + + // assert frozen 0 + // Restore ED + ExistentialDeposit::set(0); + + whitelist_account!(depositor); + }:_(RuntimeOrigin::Signed(depositor), 1) + verify { + // assert_eq!(Metadata::::get(&1), metadata); + } + impl_benchmark_test_suite!( Pallet, crate::mock::new_test_ext(), diff --git a/substrate/frame/nomination-pools/benchmarking/src/mock.rs b/substrate/frame/nomination-pools/benchmarking/src/mock.rs index 2d75df63b518..b6e80181e044 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/mock.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/mock.rs @@ -74,7 +74,7 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type FreezeIdentifier = (); + type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); @@ -160,6 +160,7 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; + type RuntimeFreezeReason = Self::RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -183,20 +184,25 @@ frame_support::construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Staking: pallet_staking::{Pallet, Call, Config, Storage, Event}, VoterList: pallet_bags_list::::{Pallet, Call, Storage, Event}, - Pools: pallet_nomination_pools::{Pallet, Call, Storage, Event}, + Pools: pallet_nomination_pools::{Pallet, Call, Storage, Event, FreezeReason}, } ); pub fn new_test_ext() -> sp_io::TestExternalities { let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); let _ = pallet_nomination_pools::GenesisConfig:: { - min_join_bond: 2, - min_create_bond: 2, + _config: Default::default(), max_pools: Some(3), max_members_per_pool: Some(3), max_members: Some(3 * 3), global_max_commission: Some(Perbill::from_percent(50)), } .assimilate_storage(&mut storage); - sp_io::TestExternalities::from(storage) + let mut ext = sp_io::TestExternalities::from(storage); + ext.execute_with(|| { + MinJoinBond::::put(2); + MinCreateBond::::put(2); + }); + + ext } diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 7f69cba76eda..9dd6cfedcf12 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2673,8 +2673,7 @@ pub mod pallet { /// deposit to the pool. This call allows the pool operator to adjust the ED deposit of the /// pool. #[pallet::call_index(21)] - // FIXME(ank4n): bench + tests - #[pallet::weight(T::WeightInfo::claim_commission())] + #[pallet::weight(T::WeightInfo::adjust_ed_deposit())] pub fn adjust_ed_deposit(origin: OriginFor, pool_id: PoolId) -> DispatchResult { let who = ensure_signed(origin)?; Self::do_adjust_ed_deposit(who, pool_id) @@ -3314,7 +3313,7 @@ impl Pallet { Ok(()) } - #[cfg(any(feature = "try-runtime", test))] + #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] pub fn check_ed_imbalance() -> Result<(), TryRuntimeError> { let mut failed: u32 = 0; BondedPools::::iter_keys().for_each(|id| { @@ -3335,6 +3334,7 @@ impl Pallet { }); ensure!(failed == 0, "Some pools do not have correct ED frozen"); + Ok(()) } /// Fully unbond the shares of `member`, when executed from `origin`. /// @@ -3350,7 +3350,7 @@ impl Pallet { Self::unbond(origin, member_lookup, points) } - #[cfg(any(feature = "runtime-benchmarks", test))] + #[cfg(test)] pub(crate) fn pool_pending_rewards( pool: PoolId, ) -> Result, sp_runtime::DispatchError> { diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 8dd0945e48cc..530a9ddc81a4 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -371,6 +371,10 @@ mod reward_pool { deposit_rewards(35); // No deficit anymore assert_eq!(reward_imbalance(1), Surplus(0)); + + // fix the ed deficit + assert_ok!(Currency::mint_into(&10, 45)); + assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1)); }); } diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index eb33c9adbbf9..c428dedac6b8 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -72,6 +72,7 @@ pub trait WeightInfo { fn set_commission_change_rate() -> Weight; fn set_claim_permission() -> Weight; fn claim_commission() -> Weight; + fn adjust_ed_deposit() -> Weight; } /// Weights for pallet_nomination_pools using the Substrate node and recommended hardware. @@ -605,6 +606,10 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } + + fn adjust_ed_deposit() -> Weight { + Weight::default() + } } // For backwards compatibility and tests @@ -1137,4 +1142,8 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } + + fn adjust_ed_deposit() -> Weight { + Weight::default() + } } From 8bfef289bfd2111fc3e86f7edeed654b8c0da614 Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 15 Sep 2023 16:04:55 +0200 Subject: [PATCH 072/103] use fungible traits in np bench --- .../nomination-pools/benchmarking/src/lib.rs | 55 +++++++++---------- .../nomination-pools/benchmarking/src/mock.rs | 8 +-- substrate/frame/nomination-pools/src/lib.rs | 5 +- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 2a0e14d4619d..a689dfc47deb 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -27,7 +27,11 @@ use frame_benchmarking::v1::{account, whitelist_account}; use frame_election_provider_support::SortedListProvider; use frame_support::{ assert_ok, ensure, - traits::{Currency, Get}, + traits::{ + fungible::{Inspect, Mutate, Unbalanced}, + tokens::{Preservation, Fortitude}, + Get, + }, }; use frame_system::RawOrigin as RuntimeOrigin; use pallet_nomination_pools::{ @@ -67,7 +71,7 @@ fn create_funded_user_with_balance( balance: BalanceOf, ) -> T::AccountId { let user = account(string, n, USER_SEED); - T::Currency::make_free_balance_be(&user, balance); + T::Currency::set_balance(&user, balance); user } @@ -148,8 +152,7 @@ impl ListScenario { ); // Burn the entire issuance. - let i = CurrencyOf::::burn(CurrencyOf::::total_issuance()); - sp_std::mem::forget(i); + CurrencyOf::::set_total_issuance(Zero::zero()); // Create accounts with the origin weight let (pool_creator1, pool_origin1) = @@ -206,7 +209,7 @@ impl ListScenario { let joiner: T::AccountId = account("joiner", USER_SEED, 0); self.origin1_member = Some(joiner.clone()); - CurrencyOf::::make_free_balance_be(&joiner, amount * 2u32.into()); + CurrencyOf::::set_balance(&joiner, amount * 2u32.into()); let original_bonded = T::Staking::active_stake(&self.origin1).unwrap(); @@ -254,7 +257,7 @@ frame_benchmarking::benchmarks! { whitelist_account!(joiner); }: _(RuntimeOrigin::Signed(joiner.clone()), max_additional, 1) verify { - assert_eq!(CurrencyOf::::free_balance(&joiner), joiner_free - max_additional); + assert_eq!(CurrencyOf::::balance(&joiner), joiner_free - max_additional); assert_eq!( T::Staking::active_stake(&scenario.origin1).unwrap(), scenario.dest_weight @@ -289,7 +292,7 @@ frame_benchmarking::benchmarks! { // transfer exactly `extra` to the depositor of the src pool (1), let reward_account1 = Pools::::create_reward_account(1); assert!(extra >= CurrencyOf::::minimum_balance()); - CurrencyOf::::deposit_creating(&reward_account1, extra); + let _ = CurrencyOf::::mint_into(&reward_account1, extra); }: _(RuntimeOrigin::Signed(claimer), T::Lookup::unlookup(scenario.creator1.clone()), BondExtra::Rewards) verify { @@ -309,7 +312,7 @@ frame_benchmarking::benchmarks! { let reward_account = Pools::::create_reward_account(1); // Send funds to the reward account of the pool - CurrencyOf::::make_free_balance_be(&reward_account, ed + origin_weight); + CurrencyOf::::set_balance(&reward_account, ed + origin_weight); // set claim preferences to `PermissionlessAll` so any account can claim rewards on member's // behalf. @@ -317,7 +320,7 @@ frame_benchmarking::benchmarks! { // Sanity check assert_eq!( - CurrencyOf::::free_balance(&depositor), + CurrencyOf::::balance(&depositor), origin_weight ); @@ -325,11 +328,11 @@ frame_benchmarking::benchmarks! { }:claim_payout_other(RuntimeOrigin::Signed(claimer), depositor.clone()) verify { assert_eq!( - CurrencyOf::::free_balance(&depositor), + CurrencyOf::::balance(&depositor), origin_weight + commission * origin_weight ); assert_eq!( - CurrencyOf::::free_balance(&reward_account), + CurrencyOf::::balance(&reward_account), ed + commission * origin_weight ); } @@ -383,7 +386,7 @@ frame_benchmarking::benchmarks! { T::Staking::active_stake(&pool_account).unwrap(), min_create_bond + min_join_bond ); - assert_eq!(CurrencyOf::::free_balance(&joiner), min_join_bond); + assert_eq!(CurrencyOf::::balance(&joiner), min_join_bond); // Unbond the new member Pools::::fully_unbond(RuntimeOrigin::Signed(joiner.clone()).into(), joiner.clone()).unwrap(); @@ -403,7 +406,7 @@ frame_benchmarking::benchmarks! { }: _(RuntimeOrigin::Signed(pool_account.clone()), 1, s) verify { // The joiners funds didn't change - assert_eq!(CurrencyOf::::free_balance(&joiner), min_join_bond); + assert_eq!(CurrencyOf::::balance(&joiner), min_join_bond); // The unlocking chunk was removed assert_eq!(pallet_staking::Ledger::::get(pool_account).unwrap().unlocking.len(), 0); } @@ -426,7 +429,7 @@ frame_benchmarking::benchmarks! { T::Staking::active_stake(&pool_account).unwrap(), min_create_bond + min_join_bond ); - assert_eq!(CurrencyOf::::free_balance(&joiner), min_join_bond); + assert_eq!(CurrencyOf::::balance(&joiner), min_join_bond); // Unbond the new member pallet_staking::CurrentEra::::put(0); @@ -447,7 +450,7 @@ frame_benchmarking::benchmarks! { }: withdraw_unbonded(RuntimeOrigin::Signed(joiner.clone()), joiner_lookup, s) verify { assert_eq!( - CurrencyOf::::free_balance(&joiner), + CurrencyOf::::reducible_balance(&joiner, Preservation::Expendable, Fortitude::Polite), min_join_bond * 2u32.into() ); // The unlocking chunk was removed @@ -485,7 +488,7 @@ frame_benchmarking::benchmarks! { Zero::zero() ); assert_eq!( - CurrencyOf::::free_balance(&pool_account), + CurrencyOf::::balance(&pool_account), min_create_bond ); assert_eq!(pallet_staking::Ledger::::get(&pool_account).unwrap().unlocking.len(), 1); @@ -515,7 +518,7 @@ frame_benchmarking::benchmarks! { // Funds where transferred back correctly assert_eq!( - CurrencyOf::::free_balance(&depositor), + CurrencyOf::::balance(&depositor), // gets bond back + rewards collecting when unbonding min_create_bond * 2u32.into() + CurrencyOf::::minimum_balance() ); @@ -527,7 +530,7 @@ frame_benchmarking::benchmarks! { let depositor_lookup = T::Lookup::unlookup(depositor.clone()); // Give the depositor some balance to bond - CurrencyOf::::make_free_balance_be(&depositor, min_create_bond * 2u32.into()); + CurrencyOf::::set_balance(&depositor, min_create_bond * 2u32.into()); // Make sure no Pools exist at a pre-condition for our verify checks assert_eq!(RewardPools::::count(), 0); @@ -782,7 +785,7 @@ frame_benchmarking::benchmarks! { let ed = CurrencyOf::::minimum_balance(); let (depositor, pool_account) = create_pool_account::(0, origin_weight, Some(commission)); let reward_account = Pools::::create_reward_account(1); - CurrencyOf::::make_free_balance_be(&reward_account, ed + origin_weight); + CurrencyOf::::set_balance(&reward_account, ed + origin_weight); // member claims a payout to make some commission available. let _ = Pools::::claim_payout(RuntimeOrigin::Signed(claimer).into()); @@ -791,27 +794,19 @@ frame_benchmarking::benchmarks! { }:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into()) verify { assert_eq!( - CurrencyOf::::free_balance(&depositor), + CurrencyOf::::balance(&depositor), origin_weight + commission * origin_weight ); assert_eq!( - CurrencyOf::::free_balance(&reward_account), + CurrencyOf::::balance(&reward_account), ed + commission * origin_weight ); } adjust_ed_deposit { - let min_bond = Pools::::depositor_min_bond(); - - // Set ED to 0 so no balance is frozen - ExistentialDeposit::set(0); - // Create a pool - let (depositor, _) = create_pool_account::(0, min_bond * 2u32.into(), None); + let (depositor, _) = create_pool_account::(0, Pools::::depositor_min_bond() * 2u32.into(), None); - // assert frozen 0 - // Restore ED - ExistentialDeposit::set(0); whitelist_account!(depositor); }:_(RuntimeOrigin::Signed(depositor), 1) diff --git a/substrate/frame/nomination-pools/benchmarking/src/mock.rs b/substrate/frame/nomination-pools/benchmarking/src/mock.rs index b6e80181e044..865395a25183 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/mock.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/mock.rs @@ -75,7 +75,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type WeightInfo = (); type FreezeIdentifier = RuntimeFreezeReason; - type MaxFreezes = (); + type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = (); type MaxHolds = (); } @@ -160,7 +160,7 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; - type RuntimeFreezeReason = Self::RuntimeFreezeReason; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -200,8 +200,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .assimilate_storage(&mut storage); let mut ext = sp_io::TestExternalities::from(storage); ext.execute_with(|| { - MinJoinBond::::put(2); - MinCreateBond::::put(2); + pallet_nomination_pools::MinJoinBond::::put(2); + pallet_nomination_pools::MinCreateBond::::put(2); }); ext diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 9dd6cfedcf12..e8918b1dbe56 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1011,7 +1011,10 @@ impl BondedPool { /// The pools balance that is transferrable. fn transferrable_balance(&self) -> BalanceOf { let account = self.bonded_account(); - T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite) + // fixme(ank4n): Since pooled account has a provider (staking pallet), the account + // is not expendable by Nomination Pallet. This means transferable balance is always + // after leaving the ED in the account. + T::Currency::balance(&account) .saturating_sub(T::Staking::active_stake(&account).unwrap_or_default()) } From e705898f5e884ef1ce114208a1ddb0c95711a298 Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 15 Sep 2023 18:30:51 +0200 Subject: [PATCH 073/103] bench for new instruction --- .../nomination-pools/benchmarking/src/lib.rs | 5 ++++- substrate/frame/nomination-pools/src/lib.rs | 22 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index a689dfc47deb..84976cd4bab6 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -807,11 +807,14 @@ frame_benchmarking::benchmarks! { // Create a pool let (depositor, _) = create_pool_account::(0, Pools::::depositor_min_bond() * 2u32.into(), None); + // Remove ed freeze to create a scenario where the ed deposit needs to be adjusted. + let _ = Pools::::remove_ed_freeze(1); + assert!(&Pools::::check_ed_imbalance().is_err()); whitelist_account!(depositor); }:_(RuntimeOrigin::Signed(depositor), 1) verify { - // assert_eq!(Metadata::::get(&1), metadata); + assert!(&Pools::::check_ed_imbalance().is_ok()); } impl_benchmark_test_suite!( diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index e8918b1dbe56..b03377bb3cf8 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3089,13 +3089,6 @@ impl Pallet { Ok(()) } - pub(crate) fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { - T::Currency::set_freeze( - &FreezeReason::PoolMinBalance.into(), - reward_acc, - T::Currency::minimum_balance(), - ) - } fn do_adjust_ed_deposit(who: T::AccountId, pool: PoolId) -> DispatchResult { let bonded_pool = BondedPool::::get(pool).ok_or(Error::::PoolNotFound)?; // only depositor can adjust ED deposit. @@ -3133,6 +3126,13 @@ impl Pallet { Ok(()) } + pub(crate) fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { + T::Currency::set_freeze( + &FreezeReason::PoolMinBalance.into(), + reward_acc, + T::Currency::minimum_balance(), + ) + } /// Ensure the correctness of the state of this pallet. /// /// This should be valid before or after each state transition of this pallet. @@ -3339,6 +3339,14 @@ impl Pallet { ensure!(failed == 0, "Some pools do not have correct ED frozen"); Ok(()) } + + #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] + pub fn remove_ed_freeze(pool_id: PoolId) { + let _ = T::Currency::thaw( + &FreezeReason::PoolMinBalance.into(), + &Self::create_reward_account(pool_id), + ); + } /// Fully unbond the shares of `member`, when executed from `origin`. /// /// This is useful for backwards compatibility with the majority of tests that only deal with From b0202e20c02814acad62fa5c5232c84e9e555630 Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 15 Sep 2023 19:47:08 +0200 Subject: [PATCH 074/103] allow fn with runtime benchmarks --- substrate/frame/nomination-pools/benchmarking/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/migration.rs | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 84976cd4bab6..a497e534bdd0 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{ assert_ok, ensure, traits::{ fungible::{Inspect, Mutate, Unbalanced}, - tokens::{Preservation, Fortitude}, + tokens::{Fortitude, Preservation}, Get, }, }; diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index b03377bb3cf8..26f2d50c1f8c 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3361,7 +3361,7 @@ impl Pallet { Self::unbond(origin, member_lookup, points) } - #[cfg(test)] + #[cfg(any(feature = "runtime-benchmarks", test))] pub(crate) fn pool_pending_rewards( pool: PoolId, ) -> Result, sp_runtime::DispatchError> { diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index ac8a880874a7..0dc72c456cae 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -60,12 +60,17 @@ pub mod v6 { } }); - log!(info, "Freezing ED succeeded for {} pools, and failed for {} pools", success, fail); + log!( + info, + "Freezing ED succeeded for {} pools, and failed for {} pools", + success, + fail + ); let total = success + fail; // freeze_ed = r:2 w:2 // reads: (freeze_ed + bonded pool key) * total // writes: freeze_ed * total - T::DbWeight::get().reads_writes(3*total, 2*total) + T::DbWeight::get().reads_writes(3 * total, 2 * total) } #[cfg(feature = "try-runtime")] From d432fbaf79b0cb119848e94bea9a420ae4026a96 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 10:01:51 +0200 Subject: [PATCH 075/103] pending rewards for pools --- substrate/frame/nomination-pools/src/mock.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 0ac3f83a3a06..f772e4fa72dc 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -453,10 +453,6 @@ pub fn fully_unbond_permissioned(member: AccountId) -> DispatchResult { Pools::unbond(RuntimeOrigin::signed(member), member, points) } -pub fn pending_rewards_for_pool(pool: PoolId) -> Balance { - Pools::pool_pending_rewards(pool).expect("pool should exist") -} - pub fn pending_rewards_for_delegator(delegator: AccountId) -> Balance { let member = PoolMembers::::get(delegator).unwrap(); let bonded_pool = BondedPools::::get(member.pool_id).unwrap(); @@ -482,7 +478,7 @@ pub enum RewardImbalance { } pub fn reward_imbalance(pool: PoolId) -> RewardImbalance { - let pending_rewards = pending_rewards_for_pool(pool); + let pending_rewards = Pools::pool_pending_rewards(pool).expect("pool should exist"); let current_balance = RewardPool::::current_balance(pool); if pending_rewards > current_balance { From d96058202ad655ab566abbcc1660479c7803cc18 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 10:16:30 +0200 Subject: [PATCH 076/103] add missing features --- substrate/frame/nomination-pools/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 26f2d50c1f8c..c8a8d3d79a8f 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3361,7 +3361,7 @@ impl Pallet { Self::unbond(origin, member_lookup, points) } - #[cfg(any(feature = "runtime-benchmarks", test))] + #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] pub(crate) fn pool_pending_rewards( pool: PoolId, ) -> Result, sp_runtime::DispatchError> { From d3d8ef4c72adbdceca52dee5cff2cd493acd5c9d Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 10:22:00 +0200 Subject: [PATCH 077/103] add a note about using Currency::balance() --- substrate/frame/nomination-pools/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index c8a8d3d79a8f..2cd4e90caacd 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1008,12 +1008,13 @@ impl BondedPool { self } - /// The pools balance that is transferrable. + /// The pools balance that is transferable provided it is expendable by staking pallet. fn transferrable_balance(&self) -> BalanceOf { let account = self.bonded_account(); - // fixme(ank4n): Since pooled account has a provider (staking pallet), the account - // is not expendable by Nomination Pallet. This means transferable balance is always - // after leaving the ED in the account. + // Note on why we can't use `Currency::reducible_balance`: Since pooled account has a + // provider (staking pallet), the account can not be set expendable by Nomination Pallet. + // This means reducible balance always returns balance preserving ED in the account. What + // we want though is transferable balance given the account can be dusted. T::Currency::balance(&account) .saturating_sub(T::Staking::active_stake(&account).unwrap_or_default()) } From bb00d8d95cfc97db1c323d49531c8df792a86851 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 10:24:03 +0200 Subject: [PATCH 078/103] rename misspelling in the function --- substrate/frame/nomination-pools/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 2cd4e90caacd..785da3e87811 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1009,7 +1009,7 @@ impl BondedPool { } /// The pools balance that is transferable provided it is expendable by staking pallet. - fn transferrable_balance(&self) -> BalanceOf { + fn transferable_balance(&self) -> BalanceOf { let account = self.bonded_account(); // Note on why we can't use `Currency::reducible_balance`: Since pooled account has a // provider (staking pallet), the account can not be set expendable by Nomination Pallet. @@ -2177,7 +2177,7 @@ pub mod pallet { ensure!(!withdrawn_points.is_empty(), Error::::CannotWithdrawAny); // Before calculating the `balance_to_unbond`, we call withdraw unbonded to ensure the - // `transferrable_balance` is correct. + // `transferable_balance` is correct. let stash_killed = T::Staking::withdraw_unbonded(bonded_pool.bonded_account(), num_slashing_spans)?; @@ -2212,7 +2212,7 @@ pub mod pallet { // don't exist. This check is also defensive in cases where the unbond pool does not // update its balance (e.g. a bug in the slashing hook.) We gracefully proceed in // order to ensure members can leave the pool and it can be destroyed. - .min(bonded_pool.transferrable_balance()); + .min(bonded_pool.transferable_balance()); T::Currency::transfer( &bonded_pool.bonded_account(), @@ -2274,7 +2274,7 @@ pub mod pallet { /// # Note /// /// In addition to `amount`, the caller will transfer the existential deposit; so the caller - /// needs at have at least `amount + existential_deposit` transferrable. + /// needs at have at least `amount + existential_deposit` transferable. #[pallet::call_index(6)] #[pallet::weight(T::WeightInfo::create())] pub fn create( From d4cd942d0ff7ea600c65083b625f232f884981ca Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 10:31:54 +0200 Subject: [PATCH 079/103] fix staking np integration test --- .../frame/nomination-pools/test-staking/src/mock.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/substrate/frame/nomination-pools/test-staking/src/mock.rs b/substrate/frame/nomination-pools/test-staking/src/mock.rs index 02c253e62c01..5a270da5f87e 100644 --- a/substrate/frame/nomination-pools/test-staking/src/mock.rs +++ b/substrate/frame/nomination-pools/test-staking/src/mock.rs @@ -85,8 +85,8 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = (); type MaxHolds = (); } @@ -174,6 +174,7 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; @@ -195,7 +196,7 @@ frame_support::construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Staking: pallet_staking::{Pallet, Call, Config, Storage, Event}, VoterList: pallet_bags_list::::{Pallet, Call, Storage, Event}, - Pools: pallet_nomination_pools::{Pallet, Call, Storage, Event}, + Pools: pallet_nomination_pools::{Pallet, Call, Storage, Event, FreezeReason}, } ); @@ -203,8 +204,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { sp_tracing::try_init_simple(); let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); let _ = pallet_nomination_pools::GenesisConfig:: { - min_join_bond: 2, - min_create_bond: 2, + _config: Default::default(), max_pools: Some(3), max_members_per_pool: Some(5), max_members: Some(3 * 5), From 51a44c766435cabe3f82c4d27233fb2a4a9248c8 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 10:56:08 +0200 Subject: [PATCH 080/103] fix unused warning --- substrate/frame/nomination-pools/src/lib.rs | 20 ------------------- substrate/frame/nomination-pools/src/mock.rs | 21 +++++++++++++++++++- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 785da3e87811..af64ccfa4523 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3361,26 +3361,6 @@ impl Pallet { let member_lookup = T::Lookup::unlookup(member); Self::unbond(origin, member_lookup, points) } - - #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] - pub(crate) fn pool_pending_rewards( - pool: PoolId, - ) -> Result, sp_runtime::DispatchError> { - let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; - let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; - - let current_rc = if !bonded_pool.points.is_zero() { - let commission = bonded_pool.commission.current(); - reward_pool.current_reward_counter(pool, bonded_pool.points, commission)?.0 - } else { - Default::default() - }; - - Ok(PoolMembers::::iter() - .filter(|(_, d)| d.pool_id == pool) - .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) - .fold(0u32.into(), |acc: BalanceOf, x| acc.saturating_add(x))) - } } impl Pallet { diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index f772e4fa72dc..8f22d9a7747f 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -477,8 +477,27 @@ pub enum RewardImbalance { Deficit(Balance), } +pub fn pool_pending_rewards( + pool: PoolId, +) -> Result, sp_runtime::DispatchError> { + let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; + let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; + + let current_rc = if !bonded_pool.points.is_zero() { + let commission = bonded_pool.commission.current(); + reward_pool.current_reward_counter(pool, bonded_pool.points, commission)?.0 + } else { + Default::default() + }; + + Ok(PoolMembers::::iter() + .filter(|(_, d)| d.pool_id == pool) + .map(|(_, d)| d.pending_rewards(current_rc).unwrap_or_default()) + .fold(0u32.into(), |acc: BalanceOf, x| acc.saturating_add(x))) +} + pub fn reward_imbalance(pool: PoolId) -> RewardImbalance { - let pending_rewards = Pools::pool_pending_rewards(pool).expect("pool should exist"); + let pending_rewards = pool_pending_rewards(pool).expect("pool should exist"); let current_balance = RewardPool::::current_balance(pool); if pending_rewards > current_balance { From 9b1042e8c70a29e3d0fb786d408006c89f1bcb40 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 11:07:27 +0200 Subject: [PATCH 081/103] fix kitchensink runtime --- substrate/bin/node/runtime/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 4f34e4ecd812..95f9561215ae 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -515,7 +515,7 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type WeightInfo = pallet_balances::weights::SubstrateWeight; - type FreezeIdentifier = (); + type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = ConstU32<2>; @@ -874,6 +874,7 @@ impl pallet_nomination_pools::Config for Runtime { type WeightInfo = (); type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; From d54f0292c4afe47e732a622795484840eeca33dc Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 11:17:40 +0200 Subject: [PATCH 082/103] use default config for node cli np chain spec --- substrate/bin/node/cli/src/chain_spec.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/substrate/bin/node/cli/src/chain_spec.rs b/substrate/bin/node/cli/src/chain_spec.rs index 51beaad03688..8bc5cfcf8862 100644 --- a/substrate/bin/node/cli/src/chain_spec.rs +++ b/substrate/bin/node/cli/src/chain_spec.rs @@ -361,11 +361,7 @@ pub fn testnet_genesis( safe_mode: Default::default(), tx_pause: Default::default(), alliance_motion: Default::default(), - nomination_pools: NominationPoolsConfig { - min_create_bond: 10 * DOLLARS, - min_join_bond: 1 * DOLLARS, - ..Default::default() - }, + nomination_pools: Default::default(), glutton: Default::default(), } } From 14d45309f150336bb071de942e27d40ad1f127a7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 11:22:30 +0200 Subject: [PATCH 083/103] fmt --- substrate/frame/nomination-pools/src/mock.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 8f22d9a7747f..dafcab570db8 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -477,9 +477,7 @@ pub enum RewardImbalance { Deficit(Balance), } -pub fn pool_pending_rewards( - pool: PoolId, -) -> Result, sp_runtime::DispatchError> { +pub fn pool_pending_rewards(pool: PoolId) -> Result, sp_runtime::DispatchError> { let bonded_pool = BondedPools::::get(pool).ok_or(Error::::PoolNotFound)?; let reward_pool = RewardPools::::get(pool).ok_or(Error::::PoolNotFound)?; From ca17f83a446d56660b68f41af1610e6527a0166d Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 11:36:43 +0200 Subject: [PATCH 084/103] remove unused imports --- substrate/bin/node/cli/src/chain_spec.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/bin/node/cli/src/chain_spec.rs b/substrate/bin/node/cli/src/chain_spec.rs index 8bc5cfcf8862..c689b5f7f291 100644 --- a/substrate/bin/node/cli/src/chain_spec.rs +++ b/substrate/bin/node/cli/src/chain_spec.rs @@ -21,9 +21,9 @@ use grandpa_primitives::AuthorityId as GrandpaId; use kitchensink_runtime::{ constants::currency::*, wasm_binary_unwrap, BabeConfig, BalancesConfig, Block, CouncilConfig, - DemocracyConfig, ElectionsConfig, ImOnlineConfig, IndicesConfig, MaxNominations, - NominationPoolsConfig, SessionConfig, SessionKeys, SocietyConfig, StakerStatus, StakingConfig, - SudoConfig, SystemConfig, TechnicalCommitteeConfig, + DemocracyConfig, ElectionsConfig, ImOnlineConfig, IndicesConfig, MaxNominations, SessionConfig, + SessionKeys, SocietyConfig, StakerStatus, StakingConfig, SudoConfig, SystemConfig, + TechnicalCommitteeConfig, }; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sc_chain_spec::ChainSpecExtension; From 88c8959fb54f7ef40acc6faa4e2db14b260d6481 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 13:31:46 +0200 Subject: [PATCH 085/103] fix feature scopes --- substrate/frame/nomination-pools/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index af64ccfa4523..3ea5ce37e961 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3317,7 +3317,7 @@ impl Pallet { Ok(()) } - #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] + #[cfg(any(feature = "try-runtime", feature = "runtime-benchmarks", test, debug_assertions))] pub fn check_ed_imbalance() -> Result<(), TryRuntimeError> { let mut failed: u32 = 0; BondedPools::::iter_keys().for_each(|id| { @@ -3341,7 +3341,7 @@ impl Pallet { Ok(()) } - #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] + #[cfg(any(feature = "runtime-benchmarks", test))] pub fn remove_ed_freeze(pool_id: PoolId) { let _ = T::Currency::thaw( &FreezeReason::PoolMinBalance.into(), From 3af90e9b9e0e78e79fb91b81acac75a3c0d0f2f7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 13:49:53 +0200 Subject: [PATCH 086/103] minor --- substrate/frame/nomination-pools/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 3ea5ce37e961..5dcd8e9101bd 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3318,7 +3318,7 @@ impl Pallet { } #[cfg(any(feature = "try-runtime", feature = "runtime-benchmarks", test, debug_assertions))] - pub fn check_ed_imbalance() -> Result<(), TryRuntimeError> { + pub fn check_ed_imbalance() -> Result<(), DispatchError> { let mut failed: u32 = 0; BondedPools::::iter_keys().for_each(|id| { let reward_acc = Self::create_reward_account(id); From 4303bb54ece64631ca94293f4f987f2db6874b50 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 17:33:06 +0200 Subject: [PATCH 087/103] make balances serde for genesis config --- substrate/bin/node/cli/src/chain_spec.rs | 12 +++++++---- .../nomination-pools/benchmarking/src/mock.rs | 11 +++------- substrate/frame/nomination-pools/src/lib.rs | 10 ++++++--- substrate/frame/nomination-pools/src/mock.rs | 21 +++++-------------- .../nomination-pools/test-staking/src/mock.rs | 3 ++- .../frame/support/src/traits/tokens/misc.rs | 7 ++++++- 6 files changed, 31 insertions(+), 33 deletions(-) diff --git a/substrate/bin/node/cli/src/chain_spec.rs b/substrate/bin/node/cli/src/chain_spec.rs index c689b5f7f291..51beaad03688 100644 --- a/substrate/bin/node/cli/src/chain_spec.rs +++ b/substrate/bin/node/cli/src/chain_spec.rs @@ -21,9 +21,9 @@ use grandpa_primitives::AuthorityId as GrandpaId; use kitchensink_runtime::{ constants::currency::*, wasm_binary_unwrap, BabeConfig, BalancesConfig, Block, CouncilConfig, - DemocracyConfig, ElectionsConfig, ImOnlineConfig, IndicesConfig, MaxNominations, SessionConfig, - SessionKeys, SocietyConfig, StakerStatus, StakingConfig, SudoConfig, SystemConfig, - TechnicalCommitteeConfig, + DemocracyConfig, ElectionsConfig, ImOnlineConfig, IndicesConfig, MaxNominations, + NominationPoolsConfig, SessionConfig, SessionKeys, SocietyConfig, StakerStatus, StakingConfig, + SudoConfig, SystemConfig, TechnicalCommitteeConfig, }; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sc_chain_spec::ChainSpecExtension; @@ -361,7 +361,11 @@ pub fn testnet_genesis( safe_mode: Default::default(), tx_pause: Default::default(), alliance_motion: Default::default(), - nomination_pools: Default::default(), + nomination_pools: NominationPoolsConfig { + min_create_bond: 10 * DOLLARS, + min_join_bond: 1 * DOLLARS, + ..Default::default() + }, glutton: Default::default(), } } diff --git a/substrate/frame/nomination-pools/benchmarking/src/mock.rs b/substrate/frame/nomination-pools/benchmarking/src/mock.rs index 865395a25183..1e6a5c249998 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/mock.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/mock.rs @@ -191,18 +191,13 @@ frame_support::construct_runtime!( pub fn new_test_ext() -> sp_io::TestExternalities { let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); let _ = pallet_nomination_pools::GenesisConfig:: { - _config: Default::default(), + min_join_bond: 2, + min_create_bond: 2, max_pools: Some(3), max_members_per_pool: Some(3), max_members: Some(3 * 3), global_max_commission: Some(Perbill::from_percent(50)), } .assimilate_storage(&mut storage); - let mut ext = sp_io::TestExternalities::from(storage); - ext.execute_with(|| { - pallet_nomination_pools::MinJoinBond::::put(2); - pallet_nomination_pools::MinCreateBond::::put(2); - }); - - ext + sp_io::TestExternalities::from(storage) } diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 5dcd8e9101bd..f38508cd6b13 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1684,8 +1684,8 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { - #[serde(skip)] - pub _config: PhantomData, + pub min_join_bond: BalanceOf, + pub min_create_bond: BalanceOf, pub max_pools: Option, pub max_members_per_pool: Option, pub max_members: Option, @@ -1695,7 +1695,8 @@ pub mod pallet { impl Default for GenesisConfig { fn default() -> Self { Self { - _config: Default::default(), + min_join_bond: Zero::zero(), + min_create_bond: Zero::zero(), max_pools: Some(16), max_members_per_pool: Some(32), max_members: Some(16 * 32), @@ -1707,6 +1708,9 @@ pub mod pallet { #[pallet::genesis_build] impl BuildGenesisConfig for GenesisConfig { fn build(&self) { + MinJoinBond::::put(self.min_join_bond); + MinCreateBond::::put(self.min_create_bond); + if let Some(max_pools) = self.max_pools { MaxPools::::put(max_pools); } diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index dafcab570db8..3884518a992b 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -42,6 +42,7 @@ pub fn default_reward_account() -> AccountId { } parameter_types! { + pub static MinJoinBondConfig: Balance = 2; pub static CurrentEra: EraIndex = 0; pub static BondingDuration: EraIndex = 3; pub storage BondedBalanceMap: BTreeMap = Default::default(); @@ -278,8 +279,6 @@ pub struct ExtBuilder { max_members: Option, max_members_per_pool: Option, global_max_commission: Option, - min_join_bond: Option, - min_create_bond: Option, } impl Default for ExtBuilder { @@ -289,8 +288,6 @@ impl Default for ExtBuilder { max_members: Some(4), max_members_per_pool: Some(3), global_max_commission: Some(Perbill::from_percent(90)), - min_join_bond: Some(2), - min_create_bond: Some(2), } } } @@ -313,13 +310,8 @@ impl ExtBuilder { self } - pub fn min_join_bond(mut self, min: Balance) -> Self { - self.min_join_bond = Some(min); - self - } - - pub fn min_create_bond(mut self, min: Balance) -> Self { - self.min_create_bond = Some(min); + pub fn min_join_bond(self, min: Balance) -> Self { + MinJoinBondConfig::set(min); self } @@ -349,7 +341,8 @@ impl ExtBuilder { frame_system::GenesisConfig::::default().build_storage().unwrap(); let _ = crate::GenesisConfig:: { - _config: Default::default(), + min_join_bond: MinJoinBondConfig::get(), + min_create_bond: 2, max_pools: Some(2), max_members_per_pool: self.max_members_per_pool, max_members: self.max_members, @@ -363,10 +356,6 @@ impl ExtBuilder { // for events to be deposited. frame_system::Pallet::::set_block_number(1); - // Default min join and create bond to 2. - MinJoinBond::::put(self.min_join_bond.unwrap_or(2)); - MinCreateBond::::put(self.min_create_bond.unwrap_or(2)); - // make a pool let amount_to_bond = Pools::depositor_min_bond(); Currency::set_balance(&10, amount_to_bond * 5); diff --git a/substrate/frame/nomination-pools/test-staking/src/mock.rs b/substrate/frame/nomination-pools/test-staking/src/mock.rs index 5a270da5f87e..54f578f861e8 100644 --- a/substrate/frame/nomination-pools/test-staking/src/mock.rs +++ b/substrate/frame/nomination-pools/test-staking/src/mock.rs @@ -204,7 +204,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities { sp_tracing::try_init_simple(); let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); let _ = pallet_nomination_pools::GenesisConfig:: { - _config: Default::default(), + min_join_bond: 2, + min_create_bond: 2, max_pools: Some(3), max_members_per_pool: Some(5), max_members: Some(3 * 5), diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs index 84bbe3e8d9c8..e8587be10179 100644 --- a/substrate/frame/support/src/traits/tokens/misc.rs +++ b/substrate/frame/support/src/traits/tokens/misc.rs @@ -20,7 +20,10 @@ use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; use sp_core::RuntimeDebug; -use sp_runtime::{traits::Convert, ArithmeticError, DispatchError, TokenError}; +use sp_runtime::{ + traits::{Convert, MaybeSerializeDeserialize}, + ArithmeticError, DispatchError, TokenError, +}; use sp_std::fmt::Debug; /// The origin of funds to be used for a deposit operation. @@ -240,6 +243,7 @@ pub trait Balance: + MaxEncodedLen + Send + Sync + + MaybeSerializeDeserialize + 'static { } @@ -253,6 +257,7 @@ impl< + MaxEncodedLen + Send + Sync + + MaybeSerializeDeserialize + 'static, > Balance for T { From 809236ec6eb1d0c1742241226eff25b992760ee5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 17:56:20 +0200 Subject: [PATCH 088/103] add migration for pools to all runtimes --- polkadot/runtime/kusama/src/lib.rs | 2 +- polkadot/runtime/polkadot/src/lib.rs | 2 ++ polkadot/runtime/westend/src/lib.rs | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index ed73834baa80..a5aa818253c6 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -1758,7 +1758,7 @@ pub mod migrations { parachains_configuration::migration::v9::MigrateToV9, // Migrate parachain info format paras_registrar::migration::VersionCheckedMigrateToV1, - // Migrate Nomination Pools + // Freeze ED Deposits for pools pallet_nomination_pools::migration::v6::VersionedMigrateV6, ); } diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index aa2c6dabba5a..9a61cfbb896e 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -1542,6 +1542,8 @@ pub mod migrations { parachains_configuration::migration::v9::MigrateToV9, // Migrate parachain info format paras_registrar::migration::VersionCheckedMigrateToV1, + // Freeze ED Deposits for pools + pallet_nomination_pools::migration::v6::VersionedMigrateV6, ); } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index da282835f06d..5935315950d9 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1428,6 +1428,7 @@ pub mod migrations { UpgradeSessionKeys, parachains_configuration::migration::v9::MigrateToV9, paras_registrar::migration::VersionCheckedMigrateToV1, + pallet_nomination_pools::migration::v6::VersionedMigrateV6, ); } From ba9e53c2dab30dc0a3454f06c56dbda9357e98d0 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 18:26:23 +0200 Subject: [PATCH 089/103] use balance everywhere in benchmark --- substrate/frame/nomination-pools/benchmarking/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index a497e534bdd0..9f5d22f4b417 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -29,7 +29,6 @@ use frame_support::{ assert_ok, ensure, traits::{ fungible::{Inspect, Mutate, Unbalanced}, - tokens::{Fortitude, Preservation}, Get, }, }; @@ -450,8 +449,7 @@ frame_benchmarking::benchmarks! { }: withdraw_unbonded(RuntimeOrigin::Signed(joiner.clone()), joiner_lookup, s) verify { assert_eq!( - CurrencyOf::::reducible_balance(&joiner, Preservation::Expendable, Fortitude::Polite), - min_join_bond * 2u32.into() + CurrencyOf::::balance(&joiner), min_join_bond * 2u32.into() ); // The unlocking chunk was removed assert_eq!(pallet_staking::Ledger::::get(&pool_account).unwrap().unlocking.len(), 0); From caac4e134aa4572ab6396b4cda657a7810758427 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sat, 16 Sep 2023 20:17:07 +0200 Subject: [PATCH 090/103] allow freezes in the kitchensink runtime --- substrate/bin/node/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 95f9561215ae..eed31ed945df 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -516,7 +516,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = frame_system::Pallet; type WeightInfo = pallet_balances::weights::SubstrateWeight; type FreezeIdentifier = RuntimeFreezeReason; - type MaxFreezes = (); + type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = ConstU32<2>; } From c138e17f35f6c4cfcb5fa15b01a2d60ad3e2e513 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 18 Sep 2023 12:42:05 +0200 Subject: [PATCH 091/103] add docs and minor refactor --- .../nomination-pools/benchmarking/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/lib.rs | 32 +++++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 9f5d22f4b417..0dd4232bc7c1 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -806,7 +806,7 @@ frame_benchmarking::benchmarks! { let (depositor, _) = create_pool_account::(0, Pools::::depositor_min_bond() * 2u32.into(), None); // Remove ed freeze to create a scenario where the ed deposit needs to be adjusted. - let _ = Pools::::remove_ed_freeze(1); + let _ = Pools::::remove_ed_freeze(&Pools::::create_reward_account(1)); assert!(&Pools::::check_ed_imbalance().is_err()); whitelist_account!(depositor); diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index f38508cd6b13..1d62ffbe366f 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1055,6 +1055,7 @@ impl BondedPool { fn is_depositor(&self, who: &T::AccountId) -> bool { &self.roles.depositor == who } + fn is_destroying(&self) -> bool { matches!(self.state, PoolState::Destroying) } @@ -1545,7 +1546,9 @@ pub mod pallet { type Currency: FunMutate + FunMutateFreeze; + /// The overarching freeze reason type RuntimeFreezeReason: From; + /// The type that is used for reward counter. /// /// The arithmetic of the reward counter might saturate based on the size of the @@ -1903,8 +1906,7 @@ pub mod pallet { /// A reason for freezing funds. #[pallet::composite_enum] pub enum FreezeReason { - /// The Pallet has frozen funds for maintaining the Existential Deposit of a - /// NominationPool. + /// Pool reward account is restricted from going below Existential Deposit. #[codec(index = 0)] PoolMinBalance, } @@ -2735,10 +2737,9 @@ impl Pallet { ReversePoolIdLookup::::remove(&bonded_account); RewardPools::::remove(bonded_pool.id); SubPoolsStorage::::remove(bonded_pool.id); - // remove the frozen ED from the reward account. - let _ = - T::Currency::thaw(&FreezeReason::PoolMinBalance.into(), &bonded_pool.reward_account()) - .defensive(); + + // remove the ED restriction from the pool reward account. + let _ = Self::remove_ed_freeze(&bonded_pool.reward_account()).defensive(); // Kill accounts from storage by making their balance go below ED. We assume that the // accounts have no references that would prevent destruction once we get to this point. We @@ -3131,6 +3132,8 @@ impl Pallet { Ok(()) } + + /// Apply freeze on reward account to restrict it from going below ED. pub(crate) fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { T::Currency::set_freeze( &FreezeReason::PoolMinBalance.into(), @@ -3138,6 +3141,12 @@ impl Pallet { T::Currency::minimum_balance(), ) } + + /// Removes the ED freeze on the reward account of `pool_id`. + pub fn remove_ed_freeze(reward_acc: &T::AccountId) -> DispatchResult { + T::Currency::thaw(&FreezeReason::PoolMinBalance.into(), reward_acc) + } + /// Ensure the correctness of the state of this pallet. /// /// This should be valid before or after each state transition of this pallet. @@ -3321,6 +3330,9 @@ impl Pallet { Ok(()) } + /// Check if any pool have an incorrect amount of ED frozen. + /// + /// This can happen if the ED has changed since the pool was created. #[cfg(any(feature = "try-runtime", feature = "runtime-benchmarks", test, debug_assertions))] pub fn check_ed_imbalance() -> Result<(), DispatchError> { let mut failed: u32 = 0; @@ -3344,14 +3356,6 @@ impl Pallet { ensure!(failed == 0, "Some pools do not have correct ED frozen"); Ok(()) } - - #[cfg(any(feature = "runtime-benchmarks", test))] - pub fn remove_ed_freeze(pool_id: PoolId) { - let _ = T::Currency::thaw( - &FreezeReason::PoolMinBalance.into(), - &Self::create_reward_account(pool_id), - ); - } /// Fully unbond the shares of `member`, when executed from `origin`. /// /// This is useful for backwards compatibility with the majority of tests that only deal with From 34541b220c33174dd2badb5720dd0603e20b4d15 Mon Sep 17 00:00:00 2001 From: Ankan Date: Mon, 18 Sep 2023 12:46:45 +0200 Subject: [PATCH 092/103] comment --- substrate/frame/nomination-pools/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 1d62ffbe366f..1c08e4a36021 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3259,9 +3259,8 @@ impl Pallet { let pending_rewards_lt_leftover_bal = RewardPool::::current_balance(id) >= pools_members_pending_rewards.get(&id).copied().unwrap_or_default(); - // this is currently broken in Kusama, a fix is being worked on in - // . until it is fixed, log a - // warning instead of panicing with an `ensure` statement. + // If this happens, this is most likely due to an old bug and not a recent code change. + // We warn about this in try-runtime checks but do not panic. if !pending_rewards_lt_leftover_bal { log::warn!( "pool {:?}, sum pending rewards = {:?}, remaining balance = {:?}", From d20138a82346c96e49e64012dba39e38634e1fc5 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 19 Sep 2023 09:35:47 +0000 Subject: [PATCH 093/103] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_nomination_pools --- .../frame/nomination-pools/src/weights.rs | 1649 +++++++++-------- 1 file changed, 838 insertions(+), 811 deletions(-) diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index c428dedac6b8..c37290155bf1 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -15,32 +15,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_nomination_pools +//! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-09-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-guclnr1q-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_nomination_pools -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/nomination-pools/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_nomination_pools +// --chain=dev +// --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/nomination-pools/src/weights.rs +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +47,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_nomination_pools. +/// Weight functions needed for `pallet_nomination_pools`. pub trait WeightInfo { fn join() -> Weight; fn bond_extra_transfer() -> Weight; @@ -75,1075 +72,1105 @@ pub trait WeightInfo { fn adjust_ed_deposit() -> Weight; } -/// Weights for pallet_nomination_pools using the Substrate node and recommended hardware. +/// Weights for `pallet_nomination_pools` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: NominationPools MinJoinBond (r:1 w:0) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:1 w:0) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn join() -> Weight { // Proof Size summary in bytes: - // Measured: `3300` + // Measured: `3388` // Estimated: `8877` - // Minimum execution time: 200_966_000 picoseconds. - Weight::from_parts(208_322_000, 8877) + // Minimum execution time: 203_377_000 picoseconds. + Weight::from_parts(206_359_000, 8877) .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().writes(12_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3310` + // Measured: `3398` // Estimated: `8877` - // Minimum execution time: 197_865_000 picoseconds. - Weight::from_parts(203_085_000, 8877) + // Minimum execution time: 199_792_000 picoseconds. + Weight::from_parts(206_871_000, 8877) .saturating_add(T::DbWeight::get().reads(16_u64)) .saturating_add(T::DbWeight::get().writes(12_u64)) } - /// Storage: NominationPools ClaimPermissions (r:1 w:0) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra_other() -> Weight { // Proof Size summary in bytes: - // Measured: `3375` + // Measured: `3463` // Estimated: `8877` - // Minimum execution time: 235_496_000 picoseconds. - Weight::from_parts(242_104_000, 8877) + // Minimum execution time: 246_362_000 picoseconds. + Weight::from_parts(253_587_000, 8877) .saturating_add(T::DbWeight::get().reads(17_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } - /// Storage: NominationPools ClaimPermissions (r:1 w:0) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn claim_payout() -> Weight { // Proof Size summary in bytes: // Measured: `1171` // Estimated: `3702` - // Minimum execution time: 81_813_000 picoseconds. - Weight::from_parts(83_277_000, 3702) + // Minimum execution time: 81_115_000 picoseconds. + Weight::from_parts(83_604_000, 3702) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(24382), added: 26857, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) - /// Proof: NominationPools CounterForSubPoolsStorage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `3586` + // Measured: `3674` // Estimated: `27847` - // Minimum execution time: 183_935_000 picoseconds. - Weight::from_parts(186_920_000, 27847) + // Minimum execution time: 187_210_000 picoseconds. + Weight::from_parts(189_477_000, 27847) .saturating_add(T::DbWeight::get().reads(20_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1687` + // Measured: `1743` // Estimated: `4764` - // Minimum execution time: 64_962_000 picoseconds. - Weight::from_parts(67_936_216, 4764) - // Standard Error: 1_780 - .saturating_add(Weight::from_parts(36_110, 0).saturating_mul(s.into())) + // Minimum execution time: 66_384_000 picoseconds. + Weight::from_parts(69_498_267, 4764) + // Standard Error: 2_566 + .saturating_add(Weight::from_parts(34_528, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(24382), added: 26857, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:0 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2115` + // Measured: `2171` // Estimated: `27847` - // Minimum execution time: 136_073_000 picoseconds. - Weight::from_parts(141_448_439, 27847) - // Standard Error: 2_472 - .saturating_add(Weight::from_parts(75_893, 0).saturating_mul(s.into())) + // Minimum execution time: 137_474_000 picoseconds. + Weight::from_parts(142_341_215, 27847) + // Standard Error: 3_468 + .saturating_add(Weight::from_parts(66_597, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(24382), added: 26857, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:0) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools ReversePoolIdLookup (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools CounterForReversePoolIdLookup (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForRewardPools (r:1 w:1) - /// Proof: NominationPools CounterForRewardPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) - /// Proof: NominationPools CounterForSubPoolsStorage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools Metadata (r:1 w:1) - /// Proof: NominationPools Metadata (max_values: None, max_size: Some(270), added: 2745, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForBondedPools (r:1 w:1) - /// Proof: NominationPools CounterForBondedPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:0 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::SlashingSpans` (r:1 w:0) + /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:2 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:2 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::Metadata` (r:1 w:1) + /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForBondedPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(_s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2470` + // Measured: `2526` // Estimated: `27847` - // Minimum execution time: 230_871_000 picoseconds. - Weight::from_parts(239_533_976, 27847) - .saturating_add(T::DbWeight::get().reads(21_u64)) - .saturating_add(T::DbWeight::get().writes(18_u64)) + // Minimum execution time: 249_135_000 picoseconds. + Weight::from_parts(263_632_571, 27847) + .saturating_add(T::DbWeight::get().reads(23_u64)) + .saturating_add(T::DbWeight::get().writes(19_u64)) } - /// Storage: NominationPools LastPoolId (r:1 w:1) - /// Proof: NominationPools LastPoolId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MinCreateBond (r:1 w:0) - /// Proof: NominationPools MinCreateBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MinJoinBond (r:1 w:0) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPools (r:1 w:0) - /// Proof: NominationPools MaxPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForBondedPools (r:1 w:1) - /// Proof: NominationPools CounterForBondedPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:1 w:0) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForRewardPools (r:1 w:1) - /// Proof: NominationPools CounterForRewardPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools ReversePoolIdLookup (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools CounterForReversePoolIdLookup (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `NominationPools::LastPoolId` (r:1 w:1) + /// Proof: `NominationPools::LastPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:1 w:0) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPools` (r:1 w:0) + /// Proof: `NominationPools::MaxPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForBondedPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:2 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:2 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `1289` - // Estimated: `6196` - // Minimum execution time: 194_272_000 picoseconds. - Weight::from_parts(197_933_000, 6196) - .saturating_add(T::DbWeight::get().reads(22_u64)) - .saturating_add(T::DbWeight::get().writes(15_u64)) + // Estimated: `8538` + // Minimum execution time: 214_207_000 picoseconds. + Weight::from_parts(221_588_000, 8538) + .saturating_add(T::DbWeight::get().reads(24_u64)) + .saturating_add(T::DbWeight::get().writes(16_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:17 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxNominatorsCount` (r:1 w:0) + /// Proof: `Staking::MaxNominatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:17 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1849` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 70_256_000 picoseconds. - Weight::from_parts(71_045_351, 4556) - // Standard Error: 9_898 - .saturating_add(Weight::from_parts(1_592_597, 0).saturating_mul(n.into())) + // Minimum execution time: 70_626_000 picoseconds. + Weight::from_parts(73_830_182, 4556) + // Standard Error: 24_496 + .saturating_add(Weight::from_parts(1_561_416, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(n.into())) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_state() -> Weight { // Proof Size summary in bytes: // Measured: `1438` // Estimated: `4556` - // Minimum execution time: 36_233_000 picoseconds. - Weight::from_parts(37_114_000, 4556) + // Minimum execution time: 36_542_000 picoseconds. + Weight::from_parts(37_644_000, 4556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools Metadata (r:1 w:1) - /// Proof: NominationPools Metadata (max_values: None, max_size: Some(270), added: 2745, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForMetadata (r:1 w:1) - /// Proof: NominationPools CounterForMetadata (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::Metadata` (r:1 w:1) + /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForMetadata` (r:1 w:1) + /// Proof: `NominationPools::CounterForMetadata` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 256]`. fn set_metadata(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `531` // Estimated: `3735` - // Minimum execution time: 14_494_000 picoseconds. - Weight::from_parts(15_445_658, 3735) - // Standard Error: 211 - .saturating_add(Weight::from_parts(1_523, 0).saturating_mul(n.into())) + // Minimum execution time: 15_130_000 picoseconds. + Weight::from_parts(16_319_671, 3735) + // Standard Error: 351 + .saturating_add(Weight::from_parts(2_024, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: NominationPools MinJoinBond (r:0 w:1) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:0 w:1) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:0 w:1) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MinCreateBond (r:0 w:1) - /// Proof: NominationPools MinCreateBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:0 w:1) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPools (r:0 w:1) - /// Proof: NominationPools MaxPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::MinJoinBond` (r:0 w:1) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:0 w:1) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:0 w:1) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:0 w:1) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:0 w:1) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPools` (r:0 w:1) + /// Proof: `NominationPools::MaxPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_configs() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_776_000 picoseconds. - Weight::from_parts(7_033_000, 0) + // Minimum execution time: 6_819_000 picoseconds. + Weight::from_parts(7_253_000, 0) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) fn update_roles() -> Weight { // Proof Size summary in bytes: // Measured: `531` // Estimated: `3685` - // Minimum execution time: 19_586_000 picoseconds. - Weight::from_parts(20_287_000, 3685) + // Minimum execution time: 19_596_000 picoseconds. + Weight::from_parts(20_828_000, 3685) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: // Measured: `2012` // Estimated: `4556` - // Minimum execution time: 68_086_000 picoseconds. - Weight::from_parts(70_784_000, 4556) + // Minimum execution time: 68_551_000 picoseconds. + Weight::from_parts(71_768_000, 4556) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn set_commission() -> Weight { // Proof Size summary in bytes: // Measured: `770` // Estimated: `3685` - // Minimum execution time: 33_353_000 picoseconds. - Weight::from_parts(34_519_000, 3685) + // Minimum execution time: 36_128_000 picoseconds. + Weight::from_parts(38_547_000, 3685) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_commission_max() -> Weight { // Proof Size summary in bytes: // Measured: `571` // Estimated: `3685` - // Minimum execution time: 19_020_000 picoseconds. - Weight::from_parts(19_630_000, 3685) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 20_067_000 picoseconds. + Weight::from_parts(21_044_000, 3685) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) fn set_commission_change_rate() -> Weight { // Proof Size summary in bytes: // Measured: `531` // Estimated: `3685` - // Minimum execution time: 19_693_000 picoseconds. - Weight::from_parts(20_114_000, 3685) + // Minimum execution time: 19_186_000 picoseconds. + Weight::from_parts(20_189_000, 3685) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:0) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:1 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) fn set_claim_permission() -> Weight { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_810_000 picoseconds. - Weight::from_parts(15_526_000, 3702) + // Minimum execution time: 15_275_000 picoseconds. + Weight::from_parts(15_932_000, 3702) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn claim_commission() -> Weight { // Proof Size summary in bytes: // Measured: `968` // Estimated: `3685` - // Minimum execution time: 66_400_000 picoseconds. - Weight::from_parts(67_707_000, 3685) + // Minimum execution time: 67_931_000 picoseconds. + Weight::from_parts(72_202_000, 3685) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn adjust_ed_deposit() -> Weight { - Weight::default() + // Proof Size summary in bytes: + // Measured: `900` + // Estimated: `4764` + // Minimum execution time: 72_783_000 picoseconds. + Weight::from_parts(75_841_000, 4764) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: NominationPools MinJoinBond (r:1 w:0) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:1 w:0) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn join() -> Weight { // Proof Size summary in bytes: - // Measured: `3300` + // Measured: `3388` // Estimated: `8877` - // Minimum execution time: 200_966_000 picoseconds. - Weight::from_parts(208_322_000, 8877) + // Minimum execution time: 203_377_000 picoseconds. + Weight::from_parts(206_359_000, 8877) .saturating_add(RocksDbWeight::get().reads(19_u64)) .saturating_add(RocksDbWeight::get().writes(12_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3310` + // Measured: `3398` // Estimated: `8877` - // Minimum execution time: 197_865_000 picoseconds. - Weight::from_parts(203_085_000, 8877) + // Minimum execution time: 199_792_000 picoseconds. + Weight::from_parts(206_871_000, 8877) .saturating_add(RocksDbWeight::get().reads(16_u64)) .saturating_add(RocksDbWeight::get().writes(12_u64)) } - /// Storage: NominationPools ClaimPermissions (r:1 w:0) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra_other() -> Weight { // Proof Size summary in bytes: - // Measured: `3375` + // Measured: `3463` // Estimated: `8877` - // Minimum execution time: 235_496_000 picoseconds. - Weight::from_parts(242_104_000, 8877) + // Minimum execution time: 246_362_000 picoseconds. + Weight::from_parts(253_587_000, 8877) .saturating_add(RocksDbWeight::get().reads(17_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } - /// Storage: NominationPools ClaimPermissions (r:1 w:0) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn claim_payout() -> Weight { // Proof Size summary in bytes: // Measured: `1171` // Estimated: `3702` - // Minimum execution time: 81_813_000 picoseconds. - Weight::from_parts(83_277_000, 3702) + // Minimum execution time: 81_115_000 picoseconds. + Weight::from_parts(83_604_000, 3702) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(24382), added: 26857, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) - /// Proof: NominationPools CounterForSubPoolsStorage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `3586` + // Measured: `3674` // Estimated: `27847` - // Minimum execution time: 183_935_000 picoseconds. - Weight::from_parts(186_920_000, 27847) + // Minimum execution time: 187_210_000 picoseconds. + Weight::from_parts(189_477_000, 27847) .saturating_add(RocksDbWeight::get().reads(20_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1687` + // Measured: `1743` // Estimated: `4764` - // Minimum execution time: 64_962_000 picoseconds. - Weight::from_parts(67_936_216, 4764) - // Standard Error: 1_780 - .saturating_add(Weight::from_parts(36_110, 0).saturating_mul(s.into())) + // Minimum execution time: 66_384_000 picoseconds. + Weight::from_parts(69_498_267, 4764) + // Standard Error: 2_566 + .saturating_add(Weight::from_parts(34_528, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(24382), added: 26857, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:0 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2115` + // Measured: `2171` // Estimated: `27847` - // Minimum execution time: 136_073_000 picoseconds. - Weight::from_parts(141_448_439, 27847) - // Standard Error: 2_472 - .saturating_add(Weight::from_parts(75_893, 0).saturating_mul(s.into())) + // Minimum execution time: 137_474_000 picoseconds. + Weight::from_parts(142_341_215, 27847) + // Standard Error: 3_468 + .saturating_add(Weight::from_parts(66_597, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(24382), added: 26857, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:0) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools ReversePoolIdLookup (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools CounterForReversePoolIdLookup (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForRewardPools (r:1 w:1) - /// Proof: NominationPools CounterForRewardPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) - /// Proof: NominationPools CounterForSubPoolsStorage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools Metadata (r:1 w:1) - /// Proof: NominationPools Metadata (max_values: None, max_size: Some(270), added: 2745, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForBondedPools (r:1 w:1) - /// Proof: NominationPools CounterForBondedPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:0 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::SlashingSpans` (r:1 w:0) + /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:2 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:2 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::Metadata` (r:1 w:1) + /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForBondedPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(_s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2470` + // Measured: `2526` // Estimated: `27847` - // Minimum execution time: 230_871_000 picoseconds. - Weight::from_parts(239_533_976, 27847) - .saturating_add(RocksDbWeight::get().reads(21_u64)) - .saturating_add(RocksDbWeight::get().writes(18_u64)) + // Minimum execution time: 249_135_000 picoseconds. + Weight::from_parts(263_632_571, 27847) + .saturating_add(RocksDbWeight::get().reads(23_u64)) + .saturating_add(RocksDbWeight::get().writes(19_u64)) } - /// Storage: NominationPools LastPoolId (r:1 w:1) - /// Proof: NominationPools LastPoolId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MinCreateBond (r:1 w:0) - /// Proof: NominationPools MinCreateBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MinJoinBond (r:1 w:0) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPools (r:1 w:0) - /// Proof: NominationPools MaxPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForBondedPools (r:1 w:1) - /// Proof: NominationPools CounterForBondedPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:1 w:0) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForRewardPools (r:1 w:1) - /// Proof: NominationPools CounterForRewardPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools ReversePoolIdLookup (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools CounterForReversePoolIdLookup (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `NominationPools::LastPoolId` (r:1 w:1) + /// Proof: `NominationPools::LastPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:1 w:0) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPools` (r:1 w:0) + /// Proof: `NominationPools::MaxPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForBondedPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:2 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:2 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `1289` - // Estimated: `6196` - // Minimum execution time: 194_272_000 picoseconds. - Weight::from_parts(197_933_000, 6196) - .saturating_add(RocksDbWeight::get().reads(22_u64)) - .saturating_add(RocksDbWeight::get().writes(15_u64)) + // Estimated: `8538` + // Minimum execution time: 214_207_000 picoseconds. + Weight::from_parts(221_588_000, 8538) + .saturating_add(RocksDbWeight::get().reads(24_u64)) + .saturating_add(RocksDbWeight::get().writes(16_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:17 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxNominatorsCount` (r:1 w:0) + /// Proof: `Staking::MaxNominatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:17 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1849` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 70_256_000 picoseconds. - Weight::from_parts(71_045_351, 4556) - // Standard Error: 9_898 - .saturating_add(Weight::from_parts(1_592_597, 0).saturating_mul(n.into())) + // Minimum execution time: 70_626_000 picoseconds. + Weight::from_parts(73_830_182, 4556) + // Standard Error: 24_496 + .saturating_add(Weight::from_parts(1_561_416, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(n.into())) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_state() -> Weight { // Proof Size summary in bytes: // Measured: `1438` // Estimated: `4556` - // Minimum execution time: 36_233_000 picoseconds. - Weight::from_parts(37_114_000, 4556) + // Minimum execution time: 36_542_000 picoseconds. + Weight::from_parts(37_644_000, 4556) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools Metadata (r:1 w:1) - /// Proof: NominationPools Metadata (max_values: None, max_size: Some(270), added: 2745, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForMetadata (r:1 w:1) - /// Proof: NominationPools CounterForMetadata (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::Metadata` (r:1 w:1) + /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForMetadata` (r:1 w:1) + /// Proof: `NominationPools::CounterForMetadata` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 256]`. fn set_metadata(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `531` // Estimated: `3735` - // Minimum execution time: 14_494_000 picoseconds. - Weight::from_parts(15_445_658, 3735) - // Standard Error: 211 - .saturating_add(Weight::from_parts(1_523, 0).saturating_mul(n.into())) + // Minimum execution time: 15_130_000 picoseconds. + Weight::from_parts(16_319_671, 3735) + // Standard Error: 351 + .saturating_add(Weight::from_parts(2_024, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: NominationPools MinJoinBond (r:0 w:1) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:0 w:1) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:0 w:1) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MinCreateBond (r:0 w:1) - /// Proof: NominationPools MinCreateBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:0 w:1) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPools (r:0 w:1) - /// Proof: NominationPools MaxPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::MinJoinBond` (r:0 w:1) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:0 w:1) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:0 w:1) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:0 w:1) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:0 w:1) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPools` (r:0 w:1) + /// Proof: `NominationPools::MaxPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_configs() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_776_000 picoseconds. - Weight::from_parts(7_033_000, 0) + // Minimum execution time: 6_819_000 picoseconds. + Weight::from_parts(7_253_000, 0) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) fn update_roles() -> Weight { // Proof Size summary in bytes: // Measured: `531` // Estimated: `3685` - // Minimum execution time: 19_586_000 picoseconds. - Weight::from_parts(20_287_000, 3685) + // Minimum execution time: 19_596_000 picoseconds. + Weight::from_parts(20_828_000, 3685) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: // Measured: `2012` // Estimated: `4556` - // Minimum execution time: 68_086_000 picoseconds. - Weight::from_parts(70_784_000, 4556) + // Minimum execution time: 68_551_000 picoseconds. + Weight::from_parts(71_768_000, 4556) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn set_commission() -> Weight { // Proof Size summary in bytes: // Measured: `770` // Estimated: `3685` - // Minimum execution time: 33_353_000 picoseconds. - Weight::from_parts(34_519_000, 3685) + // Minimum execution time: 36_128_000 picoseconds. + Weight::from_parts(38_547_000, 3685) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_commission_max() -> Weight { // Proof Size summary in bytes: // Measured: `571` // Estimated: `3685` - // Minimum execution time: 19_020_000 picoseconds. - Weight::from_parts(19_630_000, 3685) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Minimum execution time: 20_067_000 picoseconds. + Weight::from_parts(21_044_000, 3685) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) fn set_commission_change_rate() -> Weight { // Proof Size summary in bytes: // Measured: `531` // Estimated: `3685` - // Minimum execution time: 19_693_000 picoseconds. - Weight::from_parts(20_114_000, 3685) + // Minimum execution time: 19_186_000 picoseconds. + Weight::from_parts(20_189_000, 3685) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: NominationPools PoolMembers (r:1 w:0) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(237), added: 2712, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:1 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) fn set_claim_permission() -> Weight { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_810_000 picoseconds. - Weight::from_parts(15_526_000, 3702) + // Minimum execution time: 15_275_000 picoseconds. + Weight::from_parts(15_932_000, 3702) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn claim_commission() -> Weight { // Proof Size summary in bytes: // Measured: `968` // Estimated: `3685` - // Minimum execution time: 66_400_000 picoseconds. - Weight::from_parts(67_707_000, 3685) + // Minimum execution time: 67_931_000 picoseconds. + Weight::from_parts(72_202_000, 3685) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn adjust_ed_deposit() -> Weight { - Weight::default() + // Proof Size summary in bytes: + // Measured: `900` + // Estimated: `4764` + // Minimum execution time: 72_783_000 picoseconds. + Weight::from_parts(75_841_000, 4764) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } From 7de37d3e8f303c0c5390ee583d7a5e5fdf6ded11 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 19:40:07 +0200 Subject: [PATCH 094/103] PR comments --- substrate/frame/nomination-pools/src/lib.rs | 39 ++++++++++++++------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 1c08e4a36021..2fbfb2554351 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -353,7 +353,7 @@ use codec::Codec; use frame_support::{ - defensive, ensure, + defensive, defensive_assert, ensure, pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ @@ -1012,9 +1012,10 @@ impl BondedPool { fn transferable_balance(&self) -> BalanceOf { let account = self.bonded_account(); // Note on why we can't use `Currency::reducible_balance`: Since pooled account has a - // provider (staking pallet), the account can not be set expendable by Nomination Pallet. - // This means reducible balance always returns balance preserving ED in the account. What - // we want though is transferable balance given the account can be dusted. + // provider (staking pallet), the account can not be set expendable by + // `pallet-nomination-pool`. This means reducible balance always returns balance preserving + // ED in the account. What we want though is transferable balance given the account can be + // dusted. T::Currency::balance(&account) .saturating_sub(T::Staking::active_stake(&account).unwrap_or_default()) } @@ -1546,7 +1547,7 @@ pub mod pallet { type Currency: FunMutate + FunMutateFreeze; - /// The overarching freeze reason + /// The overarching freeze reason. type RuntimeFreezeReason: From; /// The type that is used for reward counter. @@ -2748,15 +2749,21 @@ impl Pallet { // consumers anyway. // 2. the bonded account should become a 'killed stash' in the staking system, and all of // its consumers removed. - debug_assert_eq!(frame_system::Pallet::::consumers(&reward_account), 0); - debug_assert_eq!(frame_system::Pallet::::consumers(&bonded_account), 0); - debug_assert_eq!( - T::Staking::total_stake(&bonded_account).unwrap_or_default(), - Zero::zero() + defensive_assert!( + frame_system::Pallet::::consumers(&reward_account) == 0, + "reward account of dissolving pool should have no consumers" + ); + defensive_assert!( + frame_system::Pallet::::consumers(&bonded_account) == 0, + "bonded account of dissolving pool should have no consumers" + ); + defensive_assert!( + T::Staking::total_stake(&bonded_account).unwrap_or_default() == Zero::zero(), + "dissolving pool should not have any stake in the staking pallet" ); // This shouldn't fail, but if it does we don't really care. Remaining balance can consist - // of unclaimed pending commission, errorneous transfers to the reward account, etc. + // of unclaimed pending commission, erroneous transfers to the reward account, etc. let reward_pool_remaining = T::Currency::reducible_balance( &reward_account, Preservation::Expendable, @@ -2769,7 +2776,15 @@ impl Pallet { Preservation::Expendable, ); - // NOTE: this is purely defensive. + defensive_assert!( + T::Currency::total_balance(&reward_account) == Zero::zero(), + "could not transfer all amount to depositor while dissolving pool" + ); + defensive_assert!( + T::Currency::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), + "dissolving pool should not have any balance" + ); + // NOTE: Defensively force set balance to zero. T::Currency::set_balance(&reward_account, Zero::zero()); T::Currency::set_balance(&bonded_pool.bonded_account(), Zero::zero()); From 7969fdf872da84b75a5f0a9512784ca363955b91 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 19:44:38 +0200 Subject: [PATCH 095/103] defensive assert while dissolving pool --- substrate/frame/nomination-pools/src/lib.rs | 40 ++++++--------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 2fbfb2554351..57bf0ad48b4b 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -352,20 +352,14 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Codec; -use frame_support::{ - defensive, defensive_assert, ensure, - pallet_prelude::{MaxEncodedLen, *}, - storage::bounded_btree_map::BoundedBTreeMap, - traits::{ - fungible::{ - Inspect as FunInspect, InspectFreeze, Mutate as FunMutate, - MutateFreeze as FunMutateFreeze, - }, - tokens::{Fortitude, Preservation}, - Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, +use frame_support::{defensive, ensure, pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ + fungible::{ + Inspect as FunInspect, InspectFreeze, Mutate as FunMutate, + MutateFreeze as FunMutateFreeze, }, - DefaultNoBound, PalletError, -}; + tokens::{Fortitude, Preservation}, + Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, +}, DefaultNoBound, PalletError, defensive_assert}; use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; use sp_core::U256; @@ -2749,14 +2743,8 @@ impl Pallet { // consumers anyway. // 2. the bonded account should become a 'killed stash' in the staking system, and all of // its consumers removed. - defensive_assert!( - frame_system::Pallet::::consumers(&reward_account) == 0, - "reward account of dissolving pool should have no consumers" - ); - defensive_assert!( - frame_system::Pallet::::consumers(&bonded_account) == 0, - "bonded account of dissolving pool should have no consumers" - ); + defensive_assert!(frame_system::Pallet::::consumers(&reward_account) == 0, "reward account of dissolving pool should have no consumers"); + defensive_assert!(frame_system::Pallet::::consumers(&bonded_account) == 0, "bonded account of dissolving pool should have no consumers"); defensive_assert!( T::Staking::total_stake(&bonded_account).unwrap_or_default() == Zero::zero(), "dissolving pool should not have any stake in the staking pallet" @@ -2776,14 +2764,8 @@ impl Pallet { Preservation::Expendable, ); - defensive_assert!( - T::Currency::total_balance(&reward_account) == Zero::zero(), - "could not transfer all amount to depositor while dissolving pool" - ); - defensive_assert!( - T::Currency::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), - "dissolving pool should not have any balance" - ); + defensive_assert!(T::Currency::total_balance(&reward_account) == Zero::zero(), "could not transfer all amount to depositor while dissolving pool"); + defensive_assert!(T::Currency::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), "dissolving pool should not have any balance"); // NOTE: Defensively force set balance to zero. T::Currency::set_balance(&reward_account, Zero::zero()); T::Currency::set_balance(&bonded_pool.bonded_account(), Zero::zero()); From 1e993eb260cad613e2306723a97f9f712013a70e Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 19:51:02 +0200 Subject: [PATCH 096/103] make unversioned migration private --- substrate/frame/nomination-pools/src/migration.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 0dc72c456cae..9abb651db258 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -22,17 +22,23 @@ use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; -pub mod v6 { + +/// Exports for versioned migration `type`s for this pallet. +pub mod versioned_migrations { use super::*; /// Wrapper over `MigrateToV6` with convenience version checks. pub type VersionedMigrateV6 = frame_support::migrations::VersionedMigration< 5, 6, - MigrateToV6, + v6::MigrateToV6, crate::pallet::Pallet, ::DbWeight, >; +} + +mod v6 { + use super::*; /// This migration would restrict reward account of pools to go below ED by doing a named /// freeze on all the existing pools. From a15af2b315d15f26c68edebe51f0564ab1edd5c5 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 19:53:15 +0200 Subject: [PATCH 097/103] fix migrations in runtime --- polkadot/runtime/kusama/src/lib.rs | 2 +- polkadot/runtime/polkadot/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/migration.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index 551039ee23b4..7c262dcb0426 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -1767,7 +1767,7 @@ pub mod migrations { // Migrate parachain info format paras_registrar::migration::VersionCheckedMigrateToV1, // Freeze ED Deposits for pools - pallet_nomination_pools::migration::v6::VersionedMigrateV6, + pallet_nomination_pools::migration::versioned_migrations::V5toV6, ); } diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index 1043b1a8b6d0..3fcf17665a00 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -1551,7 +1551,7 @@ pub mod migrations { // Migrate parachain info format paras_registrar::migration::VersionCheckedMigrateToV1, // Freeze ED Deposits for pools - pallet_nomination_pools::migration::v6::VersionedMigrateV6, + pallet_nomination_pools::migration::versioned_migrations::V5toV6, ); } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 745e1fd9f993..9e5daf6c1f22 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1434,7 +1434,7 @@ pub mod migrations { UpgradeSessionKeys, parachains_configuration::migration::v9::MigrateToV9, paras_registrar::migration::VersionCheckedMigrateToV1, - pallet_nomination_pools::migration::v6::VersionedMigrateV6, + pallet_nomination_pools::migration::versioned_migrations::V5toV6, ); } diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 9abb651db258..95575776ca73 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -28,7 +28,7 @@ pub mod versioned_migrations { use super::*; /// Wrapper over `MigrateToV6` with convenience version checks. - pub type VersionedMigrateV6 = frame_support::migrations::VersionedMigration< + pub type V5toV6 = frame_support::migrations::VersionedMigration< 5, 6, v6::MigrateToV6, From 58612c34d38279e62e582c9d305ee3c9b4079aca Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 19:59:39 +0200 Subject: [PATCH 098/103] migration fix and name the new call better --- .../src/weights/pallet_nomination_pools.rs | 2 +- .../src/weights/pallet_nomination_pools.rs | 2 +- .../src/weights/pallet_nomination_pools.rs | 2 +- .../nomination-pools/benchmarking/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/lib.rs | 8 ++++---- .../frame/nomination-pools/src/migration.rs | 16 ++++++++-------- substrate/frame/nomination-pools/src/tests.rs | 12 ++++++------ substrate/frame/nomination-pools/src/weights.rs | 6 +++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs index caabde494af4..5e3414b21fd5 100644 --- a/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/kusama/src/weights/pallet_nomination_pools.rs @@ -601,7 +601,7 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().writes(2)) } - fn adjust_ed_deposit() -> Weight { + fn adjust_pool_deposit() -> Weight { Weight::default() } } diff --git a/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs index 2c169bd0c825..7e02a19d8a19 100644 --- a/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/polkadot/src/weights/pallet_nomination_pools.rs @@ -599,7 +599,7 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().writes(2)) } - fn adjust_ed_deposit() -> Weight { + fn adjust_pool_deposit() -> Weight { Weight::default() } } diff --git a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs index 9ba4397df828..961e019ada38 100644 --- a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs @@ -599,7 +599,7 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().writes(2)) } - fn adjust_ed_deposit() -> Weight { + fn adjust_pool_deposit() -> Weight { Weight::default() } } diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 0dd4232bc7c1..129f98e0037e 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -801,7 +801,7 @@ frame_benchmarking::benchmarks! { ); } - adjust_ed_deposit { + adjust_pool_deposit { // Create a pool let (depositor, _) = create_pool_account::(0, Pools::::depositor_min_bond() * 2u32.into(), None); diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 57bf0ad48b4b..c7a4af7da07a 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2678,10 +2678,10 @@ pub mod pallet { /// deposit to the pool. This call allows the pool operator to adjust the ED deposit of the /// pool. #[pallet::call_index(21)] - #[pallet::weight(T::WeightInfo::adjust_ed_deposit())] - pub fn adjust_ed_deposit(origin: OriginFor, pool_id: PoolId) -> DispatchResult { + #[pallet::weight(T::WeightInfo::adjust_pool_deposit())] + pub fn adjust_pool_deposit(origin: OriginFor, pool_id: PoolId) -> DispatchResult { let who = ensure_signed(origin)?; - Self::do_adjust_ed_deposit(who, pool_id) + Self::do_adjust_pool_deposit(who, pool_id) } } @@ -3092,7 +3092,7 @@ impl Pallet { Ok(()) } - fn do_adjust_ed_deposit(who: T::AccountId, pool: PoolId) -> DispatchResult { + fn do_adjust_pool_deposit(who: T::AccountId, pool: PoolId) -> DispatchResult { let bonded_pool = BondedPool::::get(pool).ok_or(Error::::PoolNotFound)?; // only depositor can adjust ED deposit. ensure!(bonded_pool.is_depositor(&who), Error::::DoesNotHavePermission); diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 95575776ca73..115ef2c153fe 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -66,17 +66,17 @@ mod v6 { } }); - log!( - info, - "Freezing ED succeeded for {} pools, and failed for {} pools", - success, - fail - ); - let total = success + fail; + if fail > 0 { + log!(error, "Failed to freeze ED for {} pools", fail); + } else { + log!(info, "Freezing ED succeeded for {} pools", success); + } + + let total = success.saturating_add(fail); // freeze_ed = r:2 w:2 // reads: (freeze_ed + bonded pool key) * total // writes: freeze_ed * total - T::DbWeight::get().reads_writes(3 * total, 2 * total) + T::DbWeight::get().reads_writes(3u64.saturating_mul(total), 2u64.saturating_mul(total)) } #[cfg(feature = "try-runtime")] diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 530a9ddc81a4..346c135b29f8 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -374,7 +374,7 @@ mod reward_pool { // fix the ed deficit assert_ok!(Currency::mint_into(&10, 45)); - assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1)); + assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1)); }); } @@ -409,7 +409,7 @@ mod reward_pool { // Only depositor (10) can adjust ED deposit. Others do not have permission. assert_ok!(Currency::mint_into(&99, 100)); assert_err!( - Pools::adjust_ed_deposit(RuntimeOrigin::signed(99), 1), + Pools::adjust_pool_deposit(RuntimeOrigin::signed(99), 1), Error::::DoesNotHavePermission ); @@ -417,7 +417,7 @@ mod reward_pool { assert_ok!(Currency::mint_into(&10, 100)); let pre_dep_balance = Currency::free_balance(&10); // adjust ED - assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1)); + assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1)); // depositor's balance should decrease by 45 assert_eq!(Currency::free_balance(&10), pre_dep_balance - 45); assert_eq!(reward_imbalance(1), Surplus(0)); @@ -429,7 +429,7 @@ mod reward_pool { // Trying to top up again does not work assert_err!( - Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1), + Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1), Error::::NothingToAdjust ); @@ -437,7 +437,7 @@ mod reward_pool { ExistentialDeposit::set(5); // And:: adjust ED deposit is called - assert_ok!(Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1)); + assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1)); // Then: excess ED is transferred back to depositor assert_eq!(Currency::free_balance(&10), pre_dep_balance); @@ -462,7 +462,7 @@ mod reward_pool { // Topping up fails assert_err!( - Pools::adjust_ed_deposit(RuntimeOrigin::signed(10), 1), + Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1), Error::::NothingToAdjust ); }); diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index c37290155bf1..2cb414fc2a07 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -69,7 +69,7 @@ pub trait WeightInfo { fn set_commission_change_rate() -> Weight; fn set_claim_permission() -> Weight; fn claim_commission() -> Weight; - fn adjust_ed_deposit() -> Weight; + fn adjust_pool_deposit() -> Weight; } /// Weights for `pallet_nomination_pools` using the Substrate node and recommended hardware. @@ -613,7 +613,7 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:0) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - fn adjust_ed_deposit() -> Weight { + fn adjust_pool_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `900` // Estimated: `4764` @@ -1164,7 +1164,7 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:0) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - fn adjust_ed_deposit() -> Weight { + fn adjust_pool_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `900` // Estimated: `4764` From 04f89b76f021de215b279d0279da3b10a7ec8b3b Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 20:04:40 +0200 Subject: [PATCH 099/103] rename freeze unfreeze functions --- .../frame/nomination-pools/benchmarking/src/lib.rs | 2 +- substrate/frame/nomination-pools/src/lib.rs | 10 +++++----- substrate/frame/nomination-pools/src/migration.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 129f98e0037e..fc86a6f56c0b 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -806,7 +806,7 @@ frame_benchmarking::benchmarks! { let (depositor, _) = create_pool_account::(0, Pools::::depositor_min_bond() * 2u32.into(), None); // Remove ed freeze to create a scenario where the ed deposit needs to be adjusted. - let _ = Pools::::remove_ed_freeze(&Pools::::create_reward_account(1)); + let _ = Pools::::unfreeze_pool_deposit(&Pools::::create_reward_account(1)); assert!(&Pools::::check_ed_imbalance().is_err()); whitelist_account!(depositor); diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index c7a4af7da07a..27e7255a690e 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2734,7 +2734,7 @@ impl Pallet { SubPoolsStorage::::remove(bonded_pool.id); // remove the ED restriction from the pool reward account. - let _ = Self::remove_ed_freeze(&bonded_pool.reward_account()).defensive(); + let _ = Self::unfreeze_pool_deposit(&bonded_pool.reward_account()).defensive(); // Kill accounts from storage by making their balance go below ED. We assume that the // accounts have no references that would prevent destruction once we get to this point. We @@ -2950,7 +2950,7 @@ impl Pallet { )?; // Restrict reward account balance from going below ED. - Self::freeze_min_balance(&bonded_pool.reward_account())?; + Self::freeze_pool_deposit(&bonded_pool.reward_account())?; PoolMembers::::insert( who.clone(), @@ -3107,7 +3107,7 @@ impl Pallet { } // Update frozen amount with current ED. - Self::freeze_min_balance(reward_acc)?; + Self::freeze_pool_deposit(reward_acc)?; if pre_frozen_balance > min_balance { // Transfer excess back to depositor. @@ -3131,7 +3131,7 @@ impl Pallet { } /// Apply freeze on reward account to restrict it from going below ED. - pub(crate) fn freeze_min_balance(reward_acc: &T::AccountId) -> DispatchResult { + pub(crate) fn freeze_pool_deposit(reward_acc: &T::AccountId) -> DispatchResult { T::Currency::set_freeze( &FreezeReason::PoolMinBalance.into(), reward_acc, @@ -3140,7 +3140,7 @@ impl Pallet { } /// Removes the ED freeze on the reward account of `pool_id`. - pub fn remove_ed_freeze(reward_acc: &T::AccountId) -> DispatchResult { + pub fn unfreeze_pool_deposit(reward_acc: &T::AccountId) -> DispatchResult { T::Currency::thaw(&FreezeReason::PoolMinBalance.into(), reward_acc) } diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 115ef2c153fe..606123daa9c6 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -47,7 +47,7 @@ mod v6 { impl MigrateToV6 { fn freeze_ed(pool_id: PoolId) -> Result<(), ()> { let reward_acc = Pallet::::create_reward_account(pool_id); - Pallet::::freeze_min_balance(&reward_acc).map_err(|e| { + Pallet::::freeze_pool_deposit(&reward_acc).map_err(|e| { log!(error, "Failed to freeze ED for pool {} with error: {:?}", pool_id, e); () }) From be4a86cf2ee4c213a8ae11244a58cfe95b56d5b7 Mon Sep 17 00:00:00 2001 From: Ankan Date: Thu, 21 Sep 2023 20:05:04 +0200 Subject: [PATCH 100/103] fmt --- substrate/frame/nomination-pools/src/lib.rs | 40 +++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 27e7255a690e..c2781bfab1ef 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -352,14 +352,20 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Codec; -use frame_support::{defensive, ensure, pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ - fungible::{ - Inspect as FunInspect, InspectFreeze, Mutate as FunMutate, - MutateFreeze as FunMutateFreeze, +use frame_support::{ + defensive, defensive_assert, ensure, + pallet_prelude::{MaxEncodedLen, *}, + storage::bounded_btree_map::BoundedBTreeMap, + traits::{ + fungible::{ + Inspect as FunInspect, InspectFreeze, Mutate as FunMutate, + MutateFreeze as FunMutateFreeze, + }, + tokens::{Fortitude, Preservation}, + Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, }, - tokens::{Fortitude, Preservation}, - Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, -}, DefaultNoBound, PalletError, defensive_assert}; + DefaultNoBound, PalletError, +}; use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; use sp_core::U256; @@ -2743,8 +2749,14 @@ impl Pallet { // consumers anyway. // 2. the bonded account should become a 'killed stash' in the staking system, and all of // its consumers removed. - defensive_assert!(frame_system::Pallet::::consumers(&reward_account) == 0, "reward account of dissolving pool should have no consumers"); - defensive_assert!(frame_system::Pallet::::consumers(&bonded_account) == 0, "bonded account of dissolving pool should have no consumers"); + defensive_assert!( + frame_system::Pallet::::consumers(&reward_account) == 0, + "reward account of dissolving pool should have no consumers" + ); + defensive_assert!( + frame_system::Pallet::::consumers(&bonded_account) == 0, + "bonded account of dissolving pool should have no consumers" + ); defensive_assert!( T::Staking::total_stake(&bonded_account).unwrap_or_default() == Zero::zero(), "dissolving pool should not have any stake in the staking pallet" @@ -2764,8 +2776,14 @@ impl Pallet { Preservation::Expendable, ); - defensive_assert!(T::Currency::total_balance(&reward_account) == Zero::zero(), "could not transfer all amount to depositor while dissolving pool"); - defensive_assert!(T::Currency::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), "dissolving pool should not have any balance"); + defensive_assert!( + T::Currency::total_balance(&reward_account) == Zero::zero(), + "could not transfer all amount to depositor while dissolving pool" + ); + defensive_assert!( + T::Currency::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), + "dissolving pool should not have any balance" + ); // NOTE: Defensively force set balance to zero. T::Currency::set_balance(&reward_account, Zero::zero()); T::Currency::set_balance(&bonded_pool.bonded_account(), Zero::zero()); From 0395a4c8c486d4bac332285ffcea0d6e53b003c2 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Fri, 22 Sep 2023 11:33:41 +0000 Subject: [PATCH 101/103] ".git/.scripts/commands/bench/bench.sh" --subcommand=runtime --runtime=westend --target_dir=polkadot --pallet=pallet_nomination_pools --- .../src/weights/pallet_nomination_pools.rs | 842 +++++++++--------- 1 file changed, 429 insertions(+), 413 deletions(-) diff --git a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs index 961e019ada38..49bc687a3e4f 100644 --- a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs @@ -17,27 +17,25 @@ //! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-09-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner--ss9ysm1-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-nbnwcyh-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=westend-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_nomination_pools // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/westend/src/weights/ +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_nomination_pools +// --chain=westend-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,556 +48,574 @@ use core::marker::PhantomData; /// Weight functions for `pallet_nomination_pools`. pub struct WeightInfo(PhantomData); impl pallet_nomination_pools::WeightInfo for WeightInfo { - /// Storage: NominationPools MinJoinBond (r:1 w:0) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:1 w:0) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn join() -> Weight { // Proof Size summary in bytes: - // Measured: `3281` + // Measured: `3318` // Estimated: `8877` - // Minimum execution time: 196_298_000 picoseconds. - Weight::from_parts(202_857_000, 0) + // Minimum execution time: 187_795_000 picoseconds. + Weight::from_parts(193_857_000, 0) .saturating_add(Weight::from_parts(0, 8877)) .saturating_add(T::DbWeight::get().reads(19)) .saturating_add(T::DbWeight::get().writes(12)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3291` + // Measured: `3328` // Estimated: `8877` - // Minimum execution time: 191_639_000 picoseconds. - Weight::from_parts(197_000_000, 0) + // Minimum execution time: 186_245_000 picoseconds. + Weight::from_parts(190_916_000, 0) .saturating_add(Weight::from_parts(0, 8877)) .saturating_add(T::DbWeight::get().reads(16)) .saturating_add(T::DbWeight::get().writes(12)) } - /// Storage: NominationPools ClaimPermissions (r:1 w:0) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:2 w:2) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:2 w:2) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra_other() -> Weight { // Proof Size summary in bytes: - // Measured: `3186` + // Measured: `3274` // Estimated: `8799` - // Minimum execution time: 224_836_000 picoseconds. - Weight::from_parts(230_990_000, 0) + // Minimum execution time: 217_918_000 picoseconds. + Weight::from_parts(224_772_000, 0) .saturating_add(Weight::from_parts(0, 8799)) .saturating_add(T::DbWeight::get().reads(16)) .saturating_add(T::DbWeight::get().writes(12)) } - /// Storage: NominationPools ClaimPermissions (r:1 w:0) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn claim_payout() -> Weight { // Proof Size summary in bytes: // Measured: `1137` // Estimated: `4182` - // Minimum execution time: 79_609_000 picoseconds. - Weight::from_parts(81_434_000, 0) + // Minimum execution time: 76_958_000 picoseconds. + Weight::from_parts(78_278_000, 0) .saturating_add(Weight::from_parts(0, 4182)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(261), added: 2736, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) - /// Proof: NominationPools CounterForSubPoolsStorage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `3560` + // Measured: `3597` // Estimated: `8877` - // Minimum execution time: 175_473_000 picoseconds. - Weight::from_parts(179_976_000, 0) + // Minimum execution time: 170_992_000 picoseconds. + Weight::from_parts(179_987_000, 0) .saturating_add(Weight::from_parts(0, 8877)) .saturating_add(T::DbWeight::get().reads(20)) .saturating_add(T::DbWeight::get().writes(13)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1614` + // Measured: `1670` // Estimated: `4764` - // Minimum execution time: 63_011_000 picoseconds. - Weight::from_parts(65_966_680, 0) + // Minimum execution time: 60_740_000 picoseconds. + Weight::from_parts(64_502_831, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 2_422 - .saturating_add(Weight::from_parts(58_078, 0).saturating_mul(s.into())) + // Standard Error: 2_724 + .saturating_add(Weight::from_parts(37_725, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(261), added: 2736, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:0 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2042` + // Measured: `2098` // Estimated: `4764` - // Minimum execution time: 134_765_000 picoseconds. - Weight::from_parts(140_539_571, 0) + // Minimum execution time: 127_322_000 picoseconds. + Weight::from_parts(132_064_603, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 4_169 - .saturating_add(Weight::from_parts(61_448, 0).saturating_mul(s.into())) + // Standard Error: 3_424 + .saturating_add(Weight::from_parts(64_590, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools SubPoolsStorage (r:1 w:1) - /// Proof: NominationPools SubPoolsStorage (max_values: None, max_size: Some(261), added: 2736, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:1 w:0) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools ReversePoolIdLookup (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools CounterForReversePoolIdLookup (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForRewardPools (r:1 w:1) - /// Proof: NominationPools CounterForRewardPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) - /// Proof: NominationPools CounterForSubPoolsStorage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools Metadata (r:1 w:1) - /// Proof: NominationPools Metadata (max_values: None, max_size: Some(270), added: 2745, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForBondedPools (r:1 w:1) - /// Proof: NominationPools CounterForBondedPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:0 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::SlashingSpans` (r:1 w:0) + /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:2 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:2 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) + /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::Metadata` (r:1 w:1) + /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForBondedPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { + fn withdraw_unbonded_kill(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2398` - // Estimated: `6196` - // Minimum execution time: 226_632_000 picoseconds. - Weight::from_parts(234_263_474, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(21)) - .saturating_add(T::DbWeight::get().writes(18)) + // Measured: `2454` + // Estimated: `8538` + // Minimum execution time: 236_510_000 picoseconds. + Weight::from_parts(243_943_334, 0) + .saturating_add(Weight::from_parts(0, 8538)) + // Standard Error: 4_864 + .saturating_add(Weight::from_parts(14_974, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(23)) + .saturating_add(T::DbWeight::get().writes(19)) } - /// Storage: NominationPools LastPoolId (r:1 w:1) - /// Proof: NominationPools LastPoolId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MinCreateBond (r:1 w:0) - /// Proof: NominationPools MinCreateBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MinJoinBond (r:1 w:0) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPools (r:1 w:0) - /// Proof: NominationPools MaxPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForBondedPools (r:1 w:1) - /// Proof: NominationPools CounterForBondedPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools PoolMembers (r:1 w:1) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:1 w:0) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForPoolMembers (r:1 w:1) - /// Proof: NominationPools CounterForPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:1) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForRewardPools (r:1 w:1) - /// Proof: NominationPools CounterForRewardPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools ReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools ReversePoolIdLookup (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForReversePoolIdLookup (r:1 w:1) - /// Proof: NominationPools CounterForReversePoolIdLookup (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:1) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `NominationPools::LastPoolId` (r:1 w:1) + /// Proof: `NominationPools::LastPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:1 w:0) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPools` (r:1 w:0) + /// Proof: `NominationPools::MaxPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForBondedPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:1) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:1 w:0) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) + /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:2 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:2 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) + /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `1222` - // Estimated: `6196` - // Minimum execution time: 197_132_000 picoseconds. - Weight::from_parts(202_099_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(22)) - .saturating_add(T::DbWeight::get().writes(15)) + // Estimated: `8538` + // Minimum execution time: 197_883_000 picoseconds. + Weight::from_parts(201_750_000, 0) + .saturating_add(Weight::from_parts(0, 8538)) + .saturating_add(T::DbWeight::get().reads(24)) + .saturating_add(T::DbWeight::get().writes(16)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking MinNominatorBond (r:1 w:0) - /// Proof: Staking MinNominatorBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking MaxNominatorsCount (r:1 w:0) - /// Proof: Staking MaxNominatorsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:17 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxNominatorsCount` (r:1 w:0) + /// Proof: `Staking::MaxNominatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:17 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1779` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 68_142_000 picoseconds. - Weight::from_parts(68_977_842, 0) + // Minimum execution time: 65_505_000 picoseconds. + Weight::from_parts(67_148_657, 0) .saturating_add(Weight::from_parts(0, 4556)) - // Standard Error: 10_560 - .saturating_add(Weight::from_parts(1_606_142, 0).saturating_mul(n.into())) + // Standard Error: 9_115 + .saturating_add(Weight::from_parts(1_421_198, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(5)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(n.into())) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_state() -> Weight { // Proof Size summary in bytes: // Measured: `1367` // Estimated: `4556` - // Minimum execution time: 36_343_000 picoseconds. - Weight::from_parts(37_669_000, 0) + // Minimum execution time: 34_157_000 picoseconds. + Weight::from_parts(35_557_000, 0) .saturating_add(Weight::from_parts(0, 4556)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools Metadata (r:1 w:1) - /// Proof: NominationPools Metadata (max_values: None, max_size: Some(270), added: 2745, mode: MaxEncodedLen) - /// Storage: NominationPools CounterForMetadata (r:1 w:1) - /// Proof: NominationPools CounterForMetadata (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::Metadata` (r:1 w:1) + /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::CounterForMetadata` (r:1 w:1) + /// Proof: `NominationPools::CounterForMetadata` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 256]`. fn set_metadata(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `497` // Estimated: `3735` - // Minimum execution time: 14_157_000 picoseconds. - Weight::from_parts(15_201_514, 0) + // Minimum execution time: 13_806_000 picoseconds. + Weight::from_parts(14_540_018, 0) .saturating_add(Weight::from_parts(0, 3735)) - // Standard Error: 194 - .saturating_add(Weight::from_parts(718, 0).saturating_mul(n.into())) + // Standard Error: 123 + .saturating_add(Weight::from_parts(644, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: NominationPools MinJoinBond (r:0 w:1) - /// Proof: NominationPools MinJoinBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembers (r:0 w:1) - /// Proof: NominationPools MaxPoolMembers (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPoolMembersPerPool (r:0 w:1) - /// Proof: NominationPools MaxPoolMembersPerPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MinCreateBond (r:0 w:1) - /// Proof: NominationPools MinCreateBond (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:0 w:1) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: NominationPools MaxPools (r:0 w:1) - /// Proof: NominationPools MaxPools (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::MinJoinBond` (r:0 w:1) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembers` (r:0 w:1) + /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:0 w:1) + /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:0 w:1) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:0 w:1) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MaxPools` (r:0 w:1) + /// Proof: `NominationPools::MaxPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_configs() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_082_000 picoseconds. - Weight::from_parts(6_275_000, 0) + // Minimum execution time: 5_870_000 picoseconds. + Weight::from_parts(6_253_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) fn update_roles() -> Weight { // Proof Size summary in bytes: // Measured: `497` // Estimated: `3685` - // Minimum execution time: 19_952_000 picoseconds. - Weight::from_parts(20_880_000, 0) + // Minimum execution time: 18_290_000 picoseconds. + Weight::from_parts(18_961_000, 0) .saturating_add(Weight::from_parts(0, 3685)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: // Measured: `1942` // Estimated: `4556` - // Minimum execution time: 66_233_000 picoseconds. - Weight::from_parts(68_181_000, 0) + // Minimum execution time: 63_708_000 picoseconds. + Weight::from_parts(65_570_000, 0) .saturating_add(Weight::from_parts(0, 4556)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn set_commission() -> Weight { // Proof Size summary in bytes: // Measured: `736` // Estimated: `3685` - // Minimum execution time: 33_533_000 picoseconds. - Weight::from_parts(34_915_000, 0) + // Minimum execution time: 34_291_000 picoseconds. + Weight::from_parts(34_767_000, 0) .saturating_add(Weight::from_parts(0, 3685)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_commission_max() -> Weight { // Proof Size summary in bytes: // Measured: `537` // Estimated: `3685` - // Minimum execution time: 18_920_000 picoseconds. - Weight::from_parts(19_410_000, 0) + // Minimum execution time: 18_406_000 picoseconds. + Weight::from_parts(18_999_000, 0) .saturating_add(Weight::from_parts(0, 3685)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: NominationPools BondedPools (r:1 w:1) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:1) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) fn set_commission_change_rate() -> Weight { // Proof Size summary in bytes: // Measured: `497` // Estimated: `3685` - // Minimum execution time: 19_388_000 picoseconds. - Weight::from_parts(20_346_000, 0) + // Minimum execution time: 18_440_000 picoseconds. + Weight::from_parts(19_230_000, 0) .saturating_add(Weight::from_parts(0, 3685)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: NominationPools PoolMembers (r:1 w:0) - /// Proof: NominationPools PoolMembers (max_values: None, max_size: Some(717), added: 3192, mode: MaxEncodedLen) - /// Storage: NominationPools ClaimPermissions (r:1 w:1) - /// Proof: NominationPools ClaimPermissions (max_values: None, max_size: Some(41), added: 2516, mode: MaxEncodedLen) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ClaimPermissions` (r:1 w:1) + /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) fn set_claim_permission() -> Weight { // Proof Size summary in bytes: // Measured: `508` // Estimated: `4182` - // Minimum execution time: 14_137_000 picoseconds. - Weight::from_parts(14_846_000, 0) + // Minimum execution time: 14_310_000 picoseconds. + Weight::from_parts(14_681_000, 0) .saturating_add(Weight::from_parts(0, 4182)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: NominationPools BondedPools (r:1 w:0) - /// Proof: NominationPools BondedPools (max_values: None, max_size: Some(220), added: 2695, mode: MaxEncodedLen) - /// Storage: NominationPools RewardPools (r:1 w:1) - /// Proof: NominationPools RewardPools (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) - /// Storage: NominationPools GlobalMaxCommission (r:1 w:0) - /// Proof: NominationPools GlobalMaxCommission (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::RewardPools` (r:1 w:1) + /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) + /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn claim_commission() -> Weight { // Proof Size summary in bytes: // Measured: `934` // Estimated: `3685` - // Minimum execution time: 66_667_000 picoseconds. - Weight::from_parts(68_573_000, 0) + // Minimum execution time: 64_526_000 picoseconds. + Weight::from_parts(66_800_000, 0) .saturating_add(Weight::from_parts(0, 3685)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } - + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(220), added: 2695, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn adjust_pool_deposit() -> Weight { - Weight::default() + // Proof Size summary in bytes: + // Measured: `866` + // Estimated: `4764` + // Minimum execution time: 73_472_000 picoseconds. + Weight::from_parts(74_698_000, 0) + .saturating_add(Weight::from_parts(0, 4764)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) } } From 9eee4f6bc041d9b4a1cbcb1b31e0c3dc78364e8a Mon Sep 17 00:00:00 2001 From: Ankan Date: Fri, 22 Sep 2023 13:39:54 +0200 Subject: [PATCH 102/103] add pr doc --- prdoc/pr_1255.prdoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 prdoc/pr_1255.prdoc diff --git a/prdoc/pr_1255.prdoc b/prdoc/pr_1255.prdoc new file mode 100644 index 000000000000..793b5c3c8597 --- /dev/null +++ b/prdoc/pr_1255.prdoc @@ -0,0 +1,22 @@ +# Schema: Parity PR Documentation Schema (prdoc) +# See doc at https://github.com/paritytech/prdoc + +title: Fix for Reward Deficit in the pool + +doc: + - audience: Core Dev + description: Instead of fragile calculation of current balance by looking at free balance - ED, Nomination Pool now freezes ED in the pool reward account to restrict an account from going below minimum balance. This also has a nice side effect that if ED changes, we know how much is the imbalance in ED frozen in the pool and the current required ED. A pool operator can diligently top up the pool with the deficit in ED or vice versa, withdraw the excess they transferred to the pool. + notes: + - Introduces new call `adjust_pool_deposit` that allows to top up the deficit or withdraw the excess deposit for the pool. + - Switch to using Fungible trait from Currency trait. + +migrations: + db: [] + + runtime: + - { pallet: "pallet-nomination-pools", description: "One time migration of freezing ED from each of the existing pools."} + +crates: + - name: pallet-nomination-pools + +host_functions: [] \ No newline at end of file From 7ea6b34ea47a7a1e651ec9f97b854fd1932d30bc Mon Sep 17 00:00:00 2001 From: Ankan Date: Tue, 26 Sep 2023 21:50:26 +0200 Subject: [PATCH 103/103] make adjust ed permissionless --- substrate/frame/nomination-pools/src/lib.rs | 11 ++------ substrate/frame/nomination-pools/src/tests.rs | 25 ++++++++----------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index c2781bfab1ef..2ec9b537d320 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1053,10 +1053,6 @@ impl BondedPool { self.is_root(who) } - fn is_depositor(&self, who: &T::AccountId) -> bool { - &self.roles.depositor == who - } - fn is_destroying(&self) -> bool { matches!(self.state, PoolState::Destroying) } @@ -2681,8 +2677,8 @@ pub mod pallet { /// When a pool is created, the pool depositor transfers ED to the reward account of the /// pool. ED is subject to change and over time, the deposit in the reward account may be /// insufficient to cover the ED deficit of the pool or vice-versa where there is excess - /// deposit to the pool. This call allows the pool operator to adjust the ED deposit of the - /// pool. + /// deposit to the pool. This call allows anyone to adjust the ED deposit of the + /// pool by either topping up the deficit or claiming the excess. #[pallet::call_index(21)] #[pallet::weight(T::WeightInfo::adjust_pool_deposit())] pub fn adjust_pool_deposit(origin: OriginFor, pool_id: PoolId) -> DispatchResult { @@ -3112,9 +3108,6 @@ impl Pallet { fn do_adjust_pool_deposit(who: T::AccountId, pool: PoolId) -> DispatchResult { let bonded_pool = BondedPool::::get(pool).ok_or(Error::::PoolNotFound)?; - // only depositor can adjust ED deposit. - ensure!(bonded_pool.is_depositor(&who), Error::::DoesNotHavePermission); - let reward_acc = &bonded_pool.reward_account(); let pre_frozen_balance = T::Currency::balance_frozen(&FreezeReason::PoolMinBalance.into(), reward_acc); diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 346c135b29f8..67183e25689e 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -405,21 +405,15 @@ mod reward_pool { // clear events pool_events_since_last_call(); - // Then: - // Only depositor (10) can adjust ED deposit. Others do not have permission. - assert_ok!(Currency::mint_into(&99, 100)); - assert_err!( - Pools::adjust_pool_deposit(RuntimeOrigin::signed(99), 1), - Error::::DoesNotHavePermission - ); + // Then: Anyone can permissionlessly can adjust ED deposit. - // make sure depositor has enough funds.. - assert_ok!(Currency::mint_into(&10, 100)); - let pre_dep_balance = Currency::free_balance(&10); + // make sure caller has enough funds.. + assert_ok!(Currency::mint_into(&99, 100)); + let pre_balance = Currency::free_balance(&99); // adjust ED - assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1)); + assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(99), 1)); // depositor's balance should decrease by 45 - assert_eq!(Currency::free_balance(&10), pre_dep_balance - 45); + assert_eq!(Currency::free_balance(&99), pre_balance - 45); assert_eq!(reward_imbalance(1), Surplus(0)); assert_eq!( @@ -437,10 +431,11 @@ mod reward_pool { ExistentialDeposit::set(5); // And:: adjust ED deposit is called - assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(10), 1)); + let pre_balance = Currency::free_balance(&100); + assert_ok!(Pools::adjust_pool_deposit(RuntimeOrigin::signed(100), 1)); - // Then: excess ED is transferred back to depositor - assert_eq!(Currency::free_balance(&10), pre_dep_balance); + // Then: excess ED is claimed by the caller + assert_eq!(Currency::free_balance(&100), pre_balance + 45); assert_eq!( pool_events_since_last_call(),