difftreelog
refactor! decouple pallet-collator-selection from pallet-configuration (#962)
in: master
* feat!: decoupling configuration&collators pallets BREAKING CHANGE: pallet `collator-selection` no longer has a tight coupling with the `configuration` pallet * refactor(collator-selection): type bounds, tests * refactor(collator-selection): tests * add ci step for banchmark tests * add opsFee tests ---------
15 files changed
.github/workflows/yarn-dev.ymldiffbeforeafterboth--- a/.github/workflows/yarn-dev.yml
+++ b/.github/workflows/yarn-dev.yml
@@ -87,6 +87,18 @@
run: |
echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"
+ - name: Run benchmark mintFee tests
+ working-directory: tests
+ run: |
+ yarn install
+ npx ts-node --esm ./src/benchmarks/mintFee/index.ts
+
+ - name: Run benchmark opsFee tests
+ working-directory: tests
+ run: |
+ yarn install
+ npx ts-node --esm ./src/benchmarks/opsFee/index.ts
+
- name: Stop running containers
if: always() # run this step always
run: docker-compose -f ".docker/docker-compose.${{ matrix.network }}.yml" down
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6371,7 +6371,7 @@
[[package]]
name = "pallet-collator-selection"
-version = "4.0.0"
+version = "5.0.0"
dependencies = [
"frame-benchmarking",
"frame-support",
@@ -6380,7 +6380,6 @@
"pallet-aura",
"pallet-authorship",
"pallet-balances",
- "pallet-configuration",
"pallet-session",
"pallet-timestamp",
"parity-scale-codec",
@@ -6435,7 +6434,7 @@
[[package]]
name = "pallet-configuration"
-version = "0.1.3"
+version = "0.2.0"
dependencies = [
"fp-evm",
"frame-benchmarking",
pallets/collator-selection/CHANGELOG.mddiffbeforeafterboth--- a/pallets/collator-selection/CHANGELOG.md
+++ b/pallets/collator-selection/CHANGELOG.md
@@ -4,22 +4,28 @@
<!-- bureaucracy goes here -->
+## [5.0.0] - 2023-06-27
+
+### Major change
+
+- The dependency (tight coupling) this pallet on the configuration pallet has been removed.
+
## [4.0.0] - 2022-12-29
### Added
- Entire functionality moved over from cumulus/pallet-collator-selection (v3.0.0). Refactored business logic:
- - Added an extra step for candidacy, `get_license`, at which payment happens. The number of license holders is unlimited.
- - Only licensed accounts can apply for candidacy with `onboard`. No extra deposits are made.
- - Active candidates may `offboard`, but they will retain their license.
- - Deposit is returned, and candidacy possibly removed with `release_license`.
- - License can be forcibly forfeited and candidacy removed with `force_release_license`.
- - Failing collators' deposits will now be fully slashed, and funds will be redirected to Treasury.
- - Unify `MaxInvulnerables` and `MaxCandidates` into `MaxCollators`.
- - Remove `MinCandidates`.
- - Minimal amount of invulnerables is now 1.
- - Both invulnerables and candidates count against the limits together, however invulnerables ignore `DesiredCollators`.
- - `KickThreshold` is made configurable.
- - `DesiredCollators`, `LicenseBond`, and `KickThreshold` are moved to and referenced from `pallet-configuration`.
- - Naming changes to better reflect the new functionality.
- - More minor changes, tests, benchmarks, etc.
\ No newline at end of file
+ - Added an extra step for candidacy, `get_license`, at which payment happens. The number of license holders is unlimited.
+ - Only licensed accounts can apply for candidacy with `onboard`. No extra deposits are made.
+ - Active candidates may `offboard`, but they will retain their license.
+ - Deposit is returned, and candidacy possibly removed with `release_license`.
+ - License can be forcibly forfeited and candidacy removed with `force_release_license`.
+ - Failing collators' deposits will now be fully slashed, and funds will be redirected to Treasury.
+ - Unify `MaxInvulnerables` and `MaxCandidates` into `MaxCollators`.
+ - Remove `MinCandidates`.
+ - Minimal amount of invulnerables is now 1.
+ - Both invulnerables and candidates count against the limits together, however invulnerables ignore `DesiredCollators`.
+ - `KickThreshold` is made configurable.
+ - `DesiredCollators`, `LicenseBond`, and `KickThreshold` are moved to and referenced from `pallet-configuration`.
+ - Naming changes to better reflect the new functionality.
+ - More minor changes, tests, benchmarks, etc.
pallets/collator-selection/Cargo.tomldiffbeforeafterboth--- a/pallets/collator-selection/Cargo.toml
+++ b/pallets/collator-selection/Cargo.toml
@@ -6,7 +6,7 @@
license = "GPLv3"
name = "pallet-collator-selection"
repository = "https://github.com/UniqueNetwork/unique-chain"
-version = "4.0.0"
+version = "5.0.0"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
@@ -23,7 +23,6 @@
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-authorship = { workspace = true }
-pallet-configuration = { workspace = true }
pallet-session = { workspace = true }
sp-runtime = { workspace = true }
sp-staking = { workspace = true }
@@ -55,8 +54,6 @@
"frame-system/std",
"log/std",
"pallet-authorship/std",
- 'pallet-aura/std',
- 'pallet-balances/std',
"pallet-session/std",
"rand/std",
"scale-info/std",
@@ -64,6 +61,8 @@
"sp-runtime/std",
"sp-staking/std",
"sp-std/std",
+ 'pallet-aura/std',
+ 'pallet-balances/std',
]
try-runtime = ["frame-support/try-runtime"]
pallets/collator-selection/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/collator-selection/src/benchmarking.rs
+++ b/pallets/collator-selection/src/benchmarking.rs
@@ -35,7 +35,7 @@
use super::*;
#[allow(unused)]
-use crate::Pallet as CollatorSelection;
+use crate::{Pallet as CollatorSelection, BalanceOf};
use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller};
use frame_support::{
assert_ok,
@@ -49,11 +49,6 @@
use frame_system::{EventRecord, RawOrigin};
use pallet_authorship::EventHandler;
use pallet_session::{self as session, SessionManager};
-use pallet_configuration::{
- self as configuration, BalanceOf,
- CollatorSelectionDesiredCollatorsOverride as DesiredCollators,
- CollatorSelectionLicenseBondOverride as LicenseBond,
-};
use sp_std::prelude::*;
const SEED: u32 = 0;
@@ -117,7 +112,7 @@
validators.into_iter().map(|(who, _)| who).collect()
}
-fn register_invulnerables<T: Config + configuration::Config>(count: u32) {
+fn register_invulnerables<T: Config>(count: u32) {
let candidates = (0..count)
.map(|c| account("candidate", c, SEED))
.collect::<Vec<_>>();
@@ -131,33 +126,27 @@
}
}
-fn register_candidates<T: Config + configuration::Config>(count: u32) {
+fn register_candidates<T: Config>(count: u32) {
let candidates = (0..count)
.map(|c| account("candidate", c, SEED))
.collect::<Vec<_>>();
- assert!(
- <LicenseBond<T>>::get() > 0u32.into(),
- "Bond cannot be zero!"
- );
+ assert!(T::LicenseBond::get() > 0u32.into(), "Bond cannot be zero!");
for who in candidates {
- T::Currency::set_balance(&who, <LicenseBond<T>>::get() * 2u32.into());
+ T::Currency::set_balance(&who, T::LicenseBond::get() * 2u32.into());
<CollatorSelection<T>>::get_license(RawOrigin::Signed(who.clone()).into()).unwrap();
<CollatorSelection<T>>::onboard(RawOrigin::Signed(who).into()).unwrap();
}
}
-fn get_licenses<T: Config + configuration::Config>(count: u32) {
+fn get_licenses<T: Config>(count: u32) {
let candidates = (0..count)
.map(|c| account("candidate", c, SEED))
.collect::<Vec<_>>();
- assert!(
- <LicenseBond<T>>::get() > 0u32.into(),
- "Bond cannot be zero!"
- );
+ assert!(T::LicenseBond::get() > 0u32.into(), "Bond cannot be zero!");
for who in candidates {
- T::Currency::set_balance(&who, <LicenseBond<T>>::get() * 2u32.into());
+ T::Currency::set_balance(&who, T::LicenseBond::get() * 2u32.into());
<CollatorSelection<T>>::get_license(RawOrigin::Signed(who.clone()).into()).unwrap();
}
}
@@ -165,7 +154,7 @@
/// `Currency::minimum_balance` was used originally, but in unique-chain, we have
/// zero existential deposit, thus triggering zero bond assertion.
fn balance_unit<T: Config>() -> BalanceOf<T> {
- 200u32.into()
+ T::LicenseBond::get()
}
/// Our benchmarking environment already has invulnerables registered.
@@ -173,7 +162,7 @@
benchmarks! {
where_clause { where
- T: pallet_authorship::Config + session::Config + configuration::Config
+ T: Config + pallet_authorship::Config + session::Config
}
// todo:collator this and all the following do not work for some reason, going all the way up to 10 in length
@@ -188,7 +177,7 @@
let new_invulnerable: T::AccountId = whitelisted_caller();
let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();
- T::Currency::set_balance(&new_invulnerable, bond.clone());
+ <T as Config>::Currency::set_balance(&new_invulnerable, bond);
<session::Pallet<T>>::set_keys(
RawOrigin::Signed(new_invulnerable.clone()).into(),
@@ -225,15 +214,13 @@
get_license {
let c in 1 .. T::MaxCollators::get() - 1;
-
- <LicenseBond<T>>::put(balance_unit::<T>());
register_validators::<T>(c);
get_licenses::<T>(c);
let caller: T::AccountId = whitelisted_caller();
let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();
- T::Currency::set_balance(&caller, bond.clone());
+ T::Currency::set_balance(&caller, bond);
<session::Pallet<T>>::set_keys(
RawOrigin::Signed(caller.clone()).into(),
@@ -251,15 +238,12 @@
onboard {
let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES - 1;
- <LicenseBond<T>>::put(balance_unit::<T>());
- <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES + 1);
-
register_validators::<T>(c);
register_candidates::<T>(c);
let caller: T::AccountId = whitelisted_caller();
let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();
- T::Currency::set_balance(&caller, bond.clone());
+ T::Currency::set_balance(&caller, bond);
let origin = RawOrigin::Signed(caller.clone());
@@ -279,9 +263,7 @@
// worst case is the last candidate leaving.
offboard {
- let c in 1 .. T::MaxCollators::get();
- <LicenseBond<T>>::put(balance_unit::<T>());
- <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);
+ let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;
register_validators::<T>(c);
register_candidates::<T>(c);
@@ -295,10 +277,8 @@
// worst case is the last candidate leaving.
release_license {
- let c in 1 .. T::MaxCollators::get();
+ let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;
let bond = balance_unit::<T>();
- <LicenseBond<T>>::put(bond);
- <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);
register_validators::<T>(c);
register_candidates::<T>(c);
@@ -312,10 +292,8 @@
// worst case is the last candidate leaving.
force_release_license {
- let c in 1 .. T::MaxCollators::get();
+ let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;
let bond = balance_unit::<T>();
- <LicenseBond<T>>::put(bond);
- <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);
register_validators::<T>(c);
register_candidates::<T>(c);
@@ -334,7 +312,6 @@
// worst case is paying a non-existing candidate account.
note_author {
- <LicenseBond<T>>::put(balance_unit::<T>());
T::Currency::set_balance(
&<CollatorSelection<T>>::account_id(),
balance_unit::<T>() * 4u32.into(),
@@ -353,11 +330,9 @@
// worst case for new session.
new_session {
- let r in 1 .. T::MaxCollators::get();
- let c in 1 .. T::MaxCollators::get();
+ let r in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;
+ let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;
- <LicenseBond<T>>::put(balance_unit::<T>());
- <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);
frame_system::Pallet::<T>::set_block_number(0u32.into());
register_validators::<T>(c);
pallets/collator-selection/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license:18// Copyright (C) 2021 Parity Technologies (UK) Ltd.19// SPDX-License-Identifier: Apache-2.02021// Licensed under the Apache License, Version 2.0 (the "License");22// you may not use this file except in compliance with the License.23// You may obtain a copy of the License at24//25// http://www.apache.org/licenses/LICENSE-2.026//27// Unless required by applicable law or agreed to in writing, software28// distributed under the License is distributed on an "AS IS" BASIS,29// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.30// See the License for the specific language governing permissions and31// limitations under the License.3233// todo:collator documentation34//! Collator Selection pallet.35//!36//! A pallet to manage collators in a parachain.37//!38//! ## Overview39//!40//! The Collator Selection pallet manages the collators of a parachain. **Collation is _not_ a41//! secure activity** and this pallet does not implement any game-theoretic mechanisms to meet BFT42//! safety assumptions of the chosen set.43//!44//! ## Terminology45//!46//! - Collator: A parachain block producer.47//! - Bond: An amount of `Balance` _reserved_ for candidate registration.48//! - Invulnerable: An account guaranteed to be in the collator set.49//!50//! ## Implementation51//!52//! The final `Collators` are aggregated from two individual lists:53//!54//! 1. [`Invulnerables`]: a set of collators appointed by governance. These accounts will always be55//! collators.56//! 2. [`Candidates`]: these are *candidates to the collation task* and may or may not be elected as57//! a final collator.58//!59//! The current implementation resolves congestion of [`Candidates`] in a first-come-first-serve60//! manner.61//!62//! Candidates will not be allowed to get kicked or leave_intent if the total number of candidates63//! fall below MinCandidates. This is for potential disaster recovery scenarios.64//!65//! ### Rewards66//!67//! The Collator Selection pallet maintains an on-chain account (the "Pot"). In each block, the68//! collator who authored it receives:69//!70//! - Half the value of the Pot.71//! - Half the value of the transaction fees within the block. The other half of the transaction72//! fees are deposited into the Pot.73//!74//! To initiate rewards an ED needs to be transferred to the pot address.75//!76//! Note: Eventually the Pot distribution may be modified as discussed in77//! [this issue](https://github.com/paritytech/statemint/issues/21#issuecomment-810481073).7879#![cfg_attr(not(feature = "std"), no_std)]8081pub use pallet::*;8283#[cfg(test)]84mod mock;8586#[cfg(test)]87mod tests;8889#[cfg(feature = "runtime-benchmarks")]90mod benchmarking;91pub mod weights;9293use frame_support::traits::fungible::Inspect;9495type BalanceOf<T> =96 <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;97#[frame_support::pallet]98pub mod pallet {99 use super::*;100 pub use crate::weights::WeightInfo;101 use core::ops::Div;102 use frame_support::{103 dispatch::{DispatchClass, DispatchResultWithPostInfo},104 inherent::Vec,105 pallet_prelude::*,106 sp_runtime::traits::{AccountIdConversion, CheckedSub, Saturating, Zero},107 traits::{108 EnsureOrigin,109 fungible::{Balanced, BalancedHold, Inspect, InspectHold, Mutate, MutateHold},110 ValidatorRegistration,111 tokens::{Precision, Preservation},112 },113 BoundedVec, PalletId,114 };115 use frame_system::pallet_prelude::*;116 use pallet_session::SessionManager;117 use sp_runtime::{Perbill, traits::Convert};118 use sp_staking::SessionIndex;119120 /// A convertor from collators id. Since this pallet does not have stash/controller, this is121 /// just identity.122 pub struct IdentityCollator;123 impl<T> sp_runtime::traits::Convert<T, Option<T>> for IdentityCollator {124 fn convert(t: T) -> Option<T> {125 Some(t)126 }127 }128129 /// Configure the pallet by specifying the parameters and types on which it depends.130 #[pallet::config]131 pub trait Config: frame_system::Config {132 /// Overarching event type.133 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;134 type Currency: Mutate<Self::AccountId>135 + MutateHold<Self::AccountId>136 + BalancedHold<Self::AccountId>;137138 /// Origin that can dictate updating parameters of this pallet.139 type UpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;140141 /// Account Identifier that holds the chain's treasury.142 type TreasuryAccountId: Get<Self::AccountId>;143144 /// Account Identifier from which the internal Pot is generated.145 type PotId: Get<PalletId>;146147 /// Maximum number of candidates and invulnerables that we should have. This is enforced in code.148 type MaxCollators: Get<u32>;149150 /// If kicked, how much of the collator's deposit will be slashed and sent to the slash destination.151 type SlashRatio: Get<Perbill>;152153 /// A stable ID for a validator.154 type ValidatorId: Member + Parameter;155156 /// A conversion from account ID to validator ID.157 ///158 /// Its cost must be at most one storage read.159 type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;160161 /// Validate a user is registered162 type ValidatorRegistration: ValidatorRegistration<Self::ValidatorId>;163164 /// The weight information of this pallet.165 type WeightInfo: WeightInfo;166167 #[pallet::constant]168 type LicenceBondIdentifier: Get<<Self::Currency as InspectHold<Self::AccountId>>::Reason>;169170 type DesiredCollators: Get<u32>;171172 type LicenseBond: Get<BalanceOf<Self>>;173174 type KickThreshold: Get<Self::BlockNumber>;175 }176177 #[pallet::pallet]178 pub struct Pallet<T>(_);179180 /// The invulnerable, fixed collators.181 #[pallet::storage]182 #[pallet::getter(fn invulnerables)]183 pub type Invulnerables<T: Config> =184 StorageValue<_, BoundedVec<T::AccountId, T::MaxCollators>, ValueQuery>;185186 /// The (community) collation license holders.187 #[pallet::storage]188 #[pallet::getter(fn license_deposit_of)]189 pub type LicenseDepositOf<T: Config> =190 StorageMap<_, Blake2_128Concat, T::AccountId, BalanceOf<T>, ValueQuery>;191192 /// The (community, limited) collation candidates.193 #[pallet::storage]194 #[pallet::getter(fn candidates)]195 pub type Candidates<T: Config> =196 StorageValue<_, BoundedVec<T::AccountId, T::MaxCollators>, ValueQuery>;197198 /// Last block authored by collator.199 #[pallet::storage]200 #[pallet::getter(fn last_authored_block)]201 pub type LastAuthoredBlock<T: Config> =202 StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>;203204 #[pallet::genesis_config]205 pub struct GenesisConfig<T: Config> {206 pub invulnerables: Vec<T::AccountId>,207 }208209 #[cfg(feature = "std")]210 impl<T: Config> Default for GenesisConfig<T> {211 fn default() -> Self {212 Self {213 invulnerables: Default::default(),214 }215 }216 }217218 #[pallet::genesis_build]219 impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {220 fn build(&self) {221 let duplicate_invulnerables = self222 .invulnerables223 .iter()224 .collect::<std::collections::BTreeSet<_>>();225 assert!(226 duplicate_invulnerables.len() == self.invulnerables.len(),227 "duplicate invulnerables in genesis."228 );229230 let bounded_invulnerables =231 BoundedVec::<_, T::MaxCollators>::try_from(self.invulnerables.clone())232 .expect("genesis invulnerables are more than T::MaxCollators");233234 <Invulnerables<T>>::put(bounded_invulnerables);235 }236 }237238 #[pallet::event]239 #[pallet::generate_deposit(pub(super) fn deposit_event)]240 pub enum Event<T: Config> {241 InvulnerableAdded {242 invulnerable: T::AccountId,243 },244 InvulnerableRemoved {245 invulnerable: T::AccountId,246 },247 LicenseObtained {248 account_id: T::AccountId,249 deposit: BalanceOf<T>,250 },251 LicenseReleased {252 account_id: T::AccountId,253 deposit_returned: BalanceOf<T>,254 },255 CandidateAdded {256 account_id: T::AccountId,257 },258 CandidateRemoved {259 account_id: T::AccountId,260 },261 }262263 // Errors inform users that something went wrong.264 #[pallet::error]265 pub enum Error<T> {266 /// Too many candidates267 TooManyCandidates,268 /// Unknown error269 Unknown,270 /// Permission issue271 Permission,272 /// User already holds license to collate273 AlreadyHoldingLicense,274 /// User does not hold a license to collate275 NoLicense,276 /// User is already a candidate277 AlreadyCandidate,278 /// User is not a candidate279 NotCandidate,280 /// Too many invulnerables281 TooManyInvulnerables,282 /// Too few invulnerables283 TooFewInvulnerables,284 /// User is already an Invulnerable285 AlreadyInvulnerable,286 /// User is not an Invulnerable287 NotInvulnerable,288 /// Account has no associated validator ID289 NoAssociatedValidatorId,290 /// Validator ID is not yet registered291 ValidatorNotRegistered,292 }293294 #[pallet::hooks]295 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}296297 #[pallet::call]298 impl<T: Config> Pallet<T> {299 /// Add a collator to the list of invulnerable (fixed) collators.300 #[pallet::call_index(0)]301 #[pallet::weight(<T as Config>::WeightInfo::add_invulnerable(T::MaxCollators::get()))]302 pub fn add_invulnerable(303 origin: OriginFor<T>,304 new: T::AccountId,305 ) -> DispatchResultWithPostInfo {306 T::UpdateOrigin::ensure_origin(origin)?;307308 // check if the new invulnerable has associated validator keys before it is added309 let validator_key = T::ValidatorIdOf::convert(new.clone())310 .ok_or(Error::<T>::NoAssociatedValidatorId)?;311 ensure!(312 T::ValidatorRegistration::is_registered(&validator_key),313 Error::<T>::ValidatorNotRegistered314 );315 if Self::invulnerables().contains(&new) {316 return Ok(().into());317 }318319 <Invulnerables<T>>::try_append(new.clone())320 .map_err(|_| Error::<T>::TooManyInvulnerables)?;321322 // try to offboard the new invulnerable if it was a collator candidate before323 let _ = Self::try_remove_candidate(&new);324325 Self::deposit_event(Event::InvulnerableAdded { invulnerable: new });326 Ok(().into())327 }328329 /// Remove a collator from the list of invulnerable (fixed) collators.330 #[pallet::call_index(1)]331 #[pallet::weight(<T as Config>::WeightInfo::remove_invulnerable(T::MaxCollators::get()))]332 pub fn remove_invulnerable(333 origin: OriginFor<T>,334 who: T::AccountId,335 ) -> DispatchResultWithPostInfo {336 T::UpdateOrigin::ensure_origin(origin)?;337338 <Invulnerables<T>>::try_mutate(|invulnerables| -> DispatchResult {339 if invulnerables.len() <= 1 {340 return Err(Error::<T>::TooFewInvulnerables.into());341 }342343 let index = invulnerables344 .into_iter()345 .position(|r| *r == who)346 .ok_or(Error::<T>::NotInvulnerable)?;347 invulnerables.remove(index);348 Ok(())349 })?;350 Self::deposit_event(Event::InvulnerableRemoved { invulnerable: who });351 Ok(().into())352 }353354 /// Purchase a license on block collation for this account.355 /// It does not make it a collator candidate, use `onboard` afterward. The account must356 /// (a) already have registered session keys and (b) be able to reserve the `LicenseBond`.357 ///358 /// This call is not available to `Invulnerable` collators.359 #[pallet::call_index(2)]360 #[pallet::weight(<T as Config>::WeightInfo::get_license(T::MaxCollators::get()))]361 pub fn get_license(origin: OriginFor<T>) -> DispatchResultWithPostInfo {362 // register_as_candidate363 let who = ensure_signed(origin)?;364365 if LicenseDepositOf::<T>::contains_key(&who) {366 return Err(Error::<T>::AlreadyHoldingLicense.into());367 }368369 let validator_key = T::ValidatorIdOf::convert(who.clone())370 .ok_or(Error::<T>::NoAssociatedValidatorId)?;371 ensure!(372 T::ValidatorRegistration::is_registered(&validator_key),373 Error::<T>::ValidatorNotRegistered374 );375376 let deposit = T::LicenseBond::get();377378 T::Currency::hold(&T::LicenceBondIdentifier::get(), &who, deposit)?;379 LicenseDepositOf::<T>::insert(who.clone(), deposit);380381 Self::deposit_event(Event::LicenseObtained {382 account_id: who,383 deposit,384 });385 Ok(().into()) // Some(T::WeightInfo::register_as_candidate(current_count as u32)).into())386 }387388 /// Register this account as a candidate for collators for next sessions.389 /// The account must already hold a license, and cannot offboard immediately during a session.390 ///391 /// This call is not available to `Invulnerable` collators.392 #[pallet::call_index(3)]393 #[pallet::weight(<T as Config>::WeightInfo::onboard(T::MaxCollators::get()))]394 pub fn onboard(origin: OriginFor<T>) -> DispatchResultWithPostInfo {395 // register_as_candidate396 let who = ensure_signed(origin)?;397398 // ensure the user obtained the license.399 ensure!(400 LicenseDepositOf::<T>::contains_key(&who),401 Error::<T>::NoLicense402 );403 // ensure we are below limit.404 let length = <Candidates<T>>::decode_len().unwrap_or_default()405 + <Invulnerables<T>>::decode_len().unwrap_or_default();406 ensure!(407 (length as u32) < T::DesiredCollators::get(),408 Error::<T>::TooManyCandidates409 );410 ensure!(411 !Self::invulnerables().contains(&who),412 Error::<T>::AlreadyInvulnerable413 );414415 let current_count =416 <Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {417 if candidates.iter().any(|candidate| *candidate == who) {418 Err(Error::<T>::AlreadyCandidate)?419 } else {420 candidates421 .try_push(who.clone())422 .map_err(|_| Error::<T>::TooManyCandidates)?;423 // First authored block is current block plus kick threshold to handle session delay424 <LastAuthoredBlock<T>>::insert(425 who.clone(),426 frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),427 );428 Ok(candidates.len())429 }430 })?;431432 Self::deposit_event(Event::CandidateAdded { account_id: who });433 Ok(Some(<T as Config>::WeightInfo::onboard(current_count as u32)).into())434 }435436 /// Deregister `origin` as a collator candidate. Note that the collator can only leave on437 /// session change. The license to `onboard` later at any other time will remain.438 #[pallet::call_index(4)]439 #[pallet::weight(<T as Config>::WeightInfo::offboard(T::MaxCollators::get()))]440 pub fn offboard(origin: OriginFor<T>) -> DispatchResultWithPostInfo {441 // leave_intent442 let who = ensure_signed(origin)?;443 let current_count = Self::try_remove_candidate(&who)?;444445 Ok(Some(<T as Config>::WeightInfo::offboard(current_count as u32)).into())446 }447448 /// Forfeit `origin`'s own license. The `LicenseBond` will be unreserved immediately.449 ///450 /// This call is not available to `Invulnerable` collators.451 #[pallet::call_index(5)]452 #[pallet::weight(<T as Config>::WeightInfo::release_license(T::MaxCollators::get()))]453 pub fn release_license(origin: OriginFor<T>) -> DispatchResultWithPostInfo {454 // leave_intent455 let who = ensure_signed(origin)?;456457 let current_count = Self::try_remove_candidate_and_release_license(&who, false, true)?;458459 Ok(Some(<T as Config>::WeightInfo::release_license(460 current_count as u32,461 ))462 .into())463 }464465 /// Force deregister `origin` as a collator candidate as a governing authority, and revoke its license.466 /// Note that the collator can only leave on session change.467 /// The `LicenseBond` will be unreserved and returned immediately.468 ///469 /// This call is, of course, not applicable to `Invulnerable` collators.470 #[pallet::call_index(6)]471 #[pallet::weight(<T as Config>::WeightInfo::force_release_license(T::MaxCollators::get()))]472 pub fn force_release_license(473 origin: OriginFor<T>,474 who: T::AccountId,475 ) -> DispatchResultWithPostInfo {476 // leave_intent477 T::UpdateOrigin::ensure_origin(origin)?;478479 let current_count = Self::try_remove_candidate_and_release_license(&who, false, true)?;480481 Ok(Some(<T as Config>::WeightInfo::force_release_license(482 current_count as u32,483 ))484 .into())485 }486 }487488 impl<T: Config> Pallet<T> {489 /// Get a unique, inaccessible account id from the `PotId`.490 pub fn account_id() -> T::AccountId {491 T::PotId::get().into_account_truncating()492 }493494 /// Removes a candidate and their license, optionally slashed and optionally ignoring,495 /// whether or not they actually are a candidate.496 fn try_remove_candidate_and_release_license(497 who: &T::AccountId,498 should_slash: bool,499 ignore_if_not_candidate: bool,500 ) -> Result<usize, DispatchError> {501 let current_count = Self::try_remove_candidate(who);502 let current_count = if ignore_if_not_candidate503 && current_count == Err(Error::<T>::NotCandidate.into())504 {505 <Candidates<T>>::decode_len().unwrap_or_default()506 } else {507 current_count?508 };509 Self::try_release_license(who, should_slash)?;510 Ok(current_count)511 }512513 /// Removes a candidate from the collator pool for the next session if they exist.514 fn try_remove_candidate(who: &T::AccountId) -> Result<usize, DispatchError> {515 let current_count =516 <Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {517 let index = candidates518 .iter()519 .position(|candidate| *candidate == *who)520 .ok_or(Error::<T>::NotCandidate)?;521 candidates.remove(index);522 <LastAuthoredBlock<T>>::remove(who.clone());523 Ok(candidates.len())524 })?;525 Self::deposit_event(Event::CandidateRemoved {526 account_id: who.clone(),527 });528 Ok(current_count)529 }530531 /// Removes a candidate if they exist and sends them back their deposit, optionally slashed.532 fn try_release_license(who: &T::AccountId, should_slash: bool) -> DispatchResult {533 let mut deposit_returned = BalanceOf::<T>::default();534 LicenseDepositOf::<T>::try_mutate_exists(who, |deposit| -> DispatchResult {535 if let Some(deposit) = deposit.take() {536 if should_slash {537 let slashed = T::SlashRatio::get() * deposit;538 let remaining = deposit - slashed;539540 let (imbalance, _) =541 T::Currency::slash(&T::LicenceBondIdentifier::get(), who, slashed);542 deposit_returned = remaining;543544 T::Currency::resolve(&T::TreasuryAccountId::get(), imbalance)545 .map_err(|_| DispatchError::Other("Failed to deposit imbalance"))?;546 } else {547 deposit_returned = deposit;548 }549550 T::Currency::release(551 &T::LicenceBondIdentifier::get(),552 who,553 deposit_returned,554 Precision::Exact,555 )?;556 Ok(())557 } else {558 Err(Error::<T>::NoLicense.into())559 }560 })?;561 Self::deposit_event(Event::LicenseReleased {562 account_id: who.clone(),563 deposit_returned,564 });565 Ok(())566 }567568 /// Assemble the current set of candidates and invulnerables into the next collator set.569 ///570 /// This is done on the fly, as frequent as we are told to do so, as the session manager.571 pub fn assemble_collators(572 candidates: BoundedVec<T::AccountId, T::MaxCollators>,573 ) -> Vec<T::AccountId> {574 let mut collators = Self::invulnerables().to_vec();575 collators.extend(candidates);576 collators577 }578579 /// Kicks out candidates that did not produce a block in the kick threshold580 /// and **confiscates** their deposits to the treasury.581 pub fn kick_stale_candidates(582 candidates: BoundedVec<T::AccountId, T::MaxCollators>,583 ) -> BoundedVec<T::AccountId, T::MaxCollators> {584 let now = frame_system::Pallet::<T>::block_number();585 let kick_threshold = T::KickThreshold::get();586 candidates587 .into_iter()588 .filter_map(|c| {589 let last_block = <LastAuthoredBlock<T>>::get(c.clone());590 let since_last = now.saturating_sub(last_block);591 if since_last < kick_threshold {592 Some(c)593 } else {594 let outcome = Self::try_remove_candidate_and_release_license(&c, true, false);595 if let Err(why) = outcome {596 log::warn!("Failed to kick collator and release license {:?}", why);597 debug_assert!(false, "failed to kick collator and release license {why:?}");598 }599 None600 }601 })602 .collect::<Vec<_>>()603 .try_into()604 .expect("filter_map operation can't result in a bounded vec larger than its original; qed")605 }606 }607608 /// Keep track of number of authored blocks per authority, uncles are counted as well since609 /// they're a valid proof of being online.610 impl<T: Config + pallet_authorship::Config>611 pallet_authorship::EventHandler<T::AccountId, T::BlockNumber> for Pallet<T>612 {613 fn note_author(author: T::AccountId) {614 let pot = Self::account_id();615 // assumes an ED will be sent to pot.616 let reward = T::Currency::balance(&pot)617 .checked_sub(&T::Currency::minimum_balance())618 .unwrap_or_else(Zero::zero)619 .div(2u32.into());620621 if !reward.is_zero() {622 // `reward` is half of pot account minus ED, this should never fail.623 let _success = T::Currency::transfer(&pot, &author, reward, Preservation::Preserve);624 debug_assert!(_success.is_ok());625 }626 <LastAuthoredBlock<T>>::insert(author, frame_system::Pallet::<T>::block_number());627628 frame_system::Pallet::<T>::register_extra_weight_unchecked(629 <T as Config>::WeightInfo::note_author(),630 DispatchClass::Mandatory,631 );632 }633 }634635 /// Play the role of the session manager.636 impl<T: Config> SessionManager<T::AccountId> for Pallet<T> {637 fn new_session(index: SessionIndex) -> Option<Vec<T::AccountId>> {638 log::info!(639 "assembling new collators for new session {} at #{:?}",640 index,641 <frame_system::Pallet<T>>::block_number(),642 );643644 let candidates = Self::candidates();645 let candidates_len_before = candidates.len();646 let active_candidates = Self::kick_stale_candidates(candidates);647 let removed = candidates_len_before - active_candidates.len();648 let result = Self::assemble_collators(active_candidates);649650 frame_system::Pallet::<T>::register_extra_weight_unchecked(651 <T as Config>::WeightInfo::new_session(652 candidates_len_before as u32,653 removed as u32,654 ),655 DispatchClass::Mandatory,656 );657 Some(result)658 }659 fn start_session(_: SessionIndex) {660 // we don't care.661 }662 fn end_session(_: SessionIndex) {663 // we don't care.664 }665 }666}pallets/collator-selection/src/mock.rsdiffbeforeafterboth--- a/pallets/collator-selection/src/mock.rs
+++ b/pallets/collator-selection/src/mock.rs
@@ -63,7 +63,6 @@
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
CollatorSelection: collator_selection::{Pallet, Call, Storage, Event<T>},
Authorship: pallet_authorship::{Pallet, Storage},
- Configuration: pallet_configuration::{Pallet, Call, Storage, Event<T>},
}
);
@@ -216,21 +215,6 @@
pub AppPromotionDailyRate: Perbill = Perbill::from_rational(5u32, 10_000);
pub const DayRelayBlocks: u32 = 1;
pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";
-}
-
-impl pallet_configuration::Config for Test {
- type RuntimeEvent = RuntimeEvent;
- type Currency = Balances;
- type DefaultCollatorSelectionMaxCollators = MaxCollators;
- type DefaultCollatorSelectionKickThreshold = KickThreshold;
- type DefaultCollatorSelectionLicenseBond = LicenseBond;
- // the following constants we don't care about
- type DefaultWeightToFeeCoefficient = DefaultWeightToFeeCoefficient;
- type DefaultMinGasPrice = DefaultMinGasPrice;
- type MaxXcmAllowedLocations = MaxXcmAllowedLocations;
- type AppPromotionDailyRate = AppPromotionDailyRate;
- type DayRelayBlocks = DayRelayBlocks;
- type WeightInfo = pallet_configuration::weights::SubstrateWeight<Self>;
}
ord_parameter_types! {
@@ -246,11 +230,7 @@
pub struct IsRegistered;
impl ValidatorRegistration<u64> for IsRegistered {
fn is_registered(id: &u64) -> bool {
- if *id == 7u64 {
- false
- } else {
- true
- }
+ *id != 7u64
}
}
@@ -265,6 +245,10 @@
type ValidatorIdOf = IdentityCollator;
type ValidatorRegistration = IsRegistered;
type LicenceBondIdentifier = LicenceBondIdentifier;
+ type Currency = Balances;
+ type DesiredCollators = MaxCollators;
+ type LicenseBond = LicenseBond;
+ type KickThreshold = KickThreshold;
type WeightInfo = ();
}
@@ -277,7 +261,11 @@
let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();
- let balances = vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (33, ed)];
+ let balances: Vec<(u64, u64)> = (1..=<Test as Config>::DesiredCollators::get() as u64 + 1)
+ .map(|i| (i, 100))
+ .chain(core::iter::once((33, ed)))
+ .collect();
+
let keys = balances
.iter()
.map(|&(i, _)| {
pallets/collator-selection/src/tests.rsdiffbeforeafterboth--- a/pallets/collator-selection/src/tests.rs
+++ b/pallets/collator-selection/src/tests.rs
@@ -30,19 +30,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate as collator_selection;
+use crate::{self as collator_selection, Config};
use crate::{mock::*, Error};
use frame_support::{
assert_noop, assert_ok,
traits::{fungible, GenesisBuild, OnInitialize},
};
-use frame_system::RawOrigin;
use sp_runtime::{traits::BadOrigin, TokenError};
-use pallet_configuration::{
- CollatorSelectionDesiredCollatorsOverride as DesiredCollators,
- CollatorSelectionKickThresholdOverride as KickThreshold,
- CollatorSelectionLicenseBondOverride as LicenseBond,
-};
use scale_info::prelude::*;
fn get_license_and_onboard(account_id: <Test as frame_system::Config>::AccountId) {
@@ -57,9 +51,6 @@
#[test]
fn basic_setup_works() {
new_test_ext().execute_with(|| {
- assert_eq!(<DesiredCollators<Test>>::get(), 5);
- assert_eq!(<LicenseBond<Test>>::get(), 10);
-
assert!(CollatorSelection::candidates().is_empty());
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
});
@@ -120,51 +111,6 @@
assert_noop!(
CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 1),
Error::<Test>::TooFewInvulnerables
- );
- });
-}
-
-#[test]
-fn set_desired_collators_works() {
- new_test_ext().execute_with(|| {
- // given
- assert_eq!(<DesiredCollators<Test>>::get(), 5);
-
- // can set
- assert_ok!(Configuration::set_collator_selection_desired_collators(
- RawOrigin::Root.into(),
- Some(7)
- ));
- assert_eq!(<DesiredCollators<Test>>::get(), 7);
-
- // rejects bad origin
- assert_noop!(
- Configuration::set_collator_selection_desired_collators(
- RuntimeOrigin::signed(1),
- Some(8)
- ),
- BadOrigin
- );
- });
-}
-
-#[test]
-fn set_license_bond() {
- new_test_ext().execute_with(|| {
- // given
- assert_eq!(<LicenseBond<Test>>::get(), 10);
-
- // can set
- assert_ok!(Configuration::set_collator_selection_license_bond(
- RawOrigin::Root.into(),
- Some(7)
- ));
- assert_eq!(<LicenseBond<Test>>::get(), 7);
-
- // rejects bad origin.
- assert_noop!(
- Configuration::set_collator_selection_license_bond(RuntimeOrigin::signed(1), Some(8)),
- BadOrigin
);
});
}
@@ -187,26 +133,19 @@
#[test]
fn cannot_onboard_candidate_if_too_many() {
new_test_ext().execute_with(|| {
- // reset desired candidates
- <pallet_configuration::CollatorSelectionDesiredCollatorsOverride<Test>>::put(0);
-
- // can still get a license.
- assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));
-
- // can't accept anyone anymore.
- assert_noop!(
- CollatorSelection::onboard(RuntimeOrigin::signed(4)),
- Error::<Test>::TooManyCandidates,
- );
-
- // reset desired candidates to invulnerables + 1
- <pallet_configuration::CollatorSelectionDesiredCollatorsOverride<Test>>::put(3);
- assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(4)));
+ // can accept desired value of collators.
+ for c in 3u64..=(<Test as Config>::DesiredCollators::get()).into() {
+ assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(c)));
+ assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(c)));
+ }
// but no more.
- assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(5)));
+ let undesired_collator = (<Test as Config>::DesiredCollators::get() + 1) as u64;
+ assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(
+ undesired_collator
+ )));
assert_noop!(
- CollatorSelection::onboard(RuntimeOrigin::signed(5)),
+ CollatorSelection::onboard(RuntimeOrigin::signed(undesired_collator)),
Error::<Test>::TooManyCandidates,
);
})
@@ -227,8 +166,8 @@
fn cannot_obtain_license_if_poor() {
new_test_ext().execute_with(|| {
let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();
- assert_eq!(Balances::free_balance(&3), 100);
- assert_eq!(Balances::free_balance(&33), ed);
+ assert_eq!(Balances::free_balance(3), 100);
+ assert_eq!(Balances::free_balance(33), ed);
// works
assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));
@@ -266,21 +205,18 @@
#[test]
fn becoming_candidate_works() {
new_test_ext().execute_with(|| {
- // given
- assert_eq!(<DesiredCollators<Test>>::get(), 5);
- assert_eq!(<LicenseBond<Test>>::get(), 10);
assert_eq!(CollatorSelection::candidates(), Vec::new());
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
// take two endowed, non-invulnerables accounts.
- assert_eq!(Balances::free_balance(&3), 100);
- assert_eq!(Balances::free_balance(&4), 100);
+ assert_eq!(Balances::free_balance(3), 100);
+ assert_eq!(Balances::free_balance(4), 100);
get_license_and_onboard(3);
get_license_and_onboard(4);
- assert_eq!(Balances::free_balance(&3), 90);
- assert_eq!(Balances::free_balance(&4), 90);
+ assert_eq!(Balances::free_balance(3), 90);
+ assert_eq!(Balances::free_balance(4), 90);
assert_eq!(CollatorSelection::candidates().len(), 2);
});
@@ -513,7 +449,7 @@
assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);
assert_eq!(CollatorSelection::candidates(), vec![4]);
- assert_eq!(<KickThreshold<Test>>::get(), 10);
+ // assert_eq!(<KickThreshold<Test>>::get(), 10);
assert_eq!(CollatorSelection::last_authored_block(4), 20);
initialize_to_block(30);
pallets/configuration/CHANGELOG.mddiffbeforeafterboth--- a/pallets/configuration/CHANGELOG.md
+++ b/pallets/configuration/CHANGELOG.md
@@ -3,7 +3,12 @@
All notable changes to this project will be documented in this file.
<!-- bureaucrate goes here -->
+## [0.2.0] - 2023-06-27
+
+### Major change
+- Architecture fixed: in the configuration of this pallet, bounds on the associated type were determined not by the functional requirements for this pallet itself, but by the pallet that had tight coupling with it.
+
## [0.1.3] - 2022-12-29
### Added
@@ -20,4 +25,4 @@
### Other changes
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
\ No newline at end of file
+- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
pallets/configuration/Cargo.tomldiffbeforeafterboth--- a/pallets/configuration/Cargo.toml
+++ b/pallets/configuration/Cargo.toml
@@ -1,7 +1,7 @@
[package]
edition = "2021"
name = "pallet-configuration"
-version = "0.1.3"
+version = "0.2.0"
[dependencies]
# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.
@@ -22,11 +22,11 @@
default = ["std"]
runtime-benchmarks = ["frame-benchmarking"]
std = [
+ "codec/std",
"fp-evm/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
- "codec/std",
"sp-arithmetic/std",
"sp-core/std",
"sp-std/std",
pallets/configuration/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/configuration/src/benchmarking.rs
+++ b/pallets/configuration/src/benchmarking.rs
@@ -19,7 +19,7 @@
use super::*;
use frame_benchmarking::benchmarks;
use frame_system::{EventRecord, RawOrigin};
-use frame_support::{assert_ok, traits::fungible::Inspect};
+use frame_support::assert_ok;
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
let events = frame_system::Pallet::<T>::events();
@@ -30,7 +30,10 @@
}
benchmarks! {
- where_clause { where T: Config }
+ where_clause { where
+ T: Config,
+ T::Balance: From<u32>
+ }
set_weight_to_fee_coefficient_override {
let coeff: u64 = 999;
@@ -60,7 +63,7 @@
let max: u32 = 999;
}: {
assert_ok!(
- <Pallet<T>>::set_collator_selection_desired_collators(RawOrigin::Root.into(), Some(max.clone()))
+ <Pallet<T>>::set_collator_selection_desired_collators(RawOrigin::Root.into(), Some(max))
);
}
verify {
@@ -68,10 +71,10 @@
}
set_collator_selection_license_bond {
- let bond_cost: Option<BalanceOf<T>> = Some(T::Currency::minimum_balance() * 10u32.into());
+ let bond_cost: Option<T::Balance> = Some(1000u32.into());
}: {
assert_ok!(
- <Pallet<T>>::set_collator_selection_license_bond(RawOrigin::Root.into(), bond_cost.clone())
+ <Pallet<T>>::set_collator_selection_license_bond(RawOrigin::Root.into(), bond_cost)
);
}
verify {
@@ -82,7 +85,7 @@
let threshold: Option<T::BlockNumber> = Some(900u32.into());
}: {
assert_ok!(
- <Pallet<T>>::set_collator_selection_kick_threshold(RawOrigin::Root.into(), threshold.clone())
+ <Pallet<T>>::set_collator_selection_kick_threshold(RawOrigin::Root.into(), threshold)
);
}
verify {
pallets/configuration/src/lib.rsdiffbeforeafterboth--- a/pallets/configuration/src/lib.rs
+++ b/pallets/configuration/src/lib.rs
@@ -22,6 +22,7 @@
pallet,
weights::{WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient, Weight},
traits::Get,
+ Parameter,
};
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
@@ -42,27 +43,33 @@
mod pallet {
use super::*;
use frame_support::{
- traits::{fungible, Get},
- pallet_prelude::{StorageValue, ValueQuery, DispatchResult, IsType},
+ traits::{Get},
+ pallet_prelude::{
+ StorageValue, ValueQuery, DispatchResult, IsType, Member, MaybeSerializeDeserialize,
+ },
log,
+ dispatch::{Codec, fmt::Debug},
};
- use frame_system::{pallet_prelude::OriginFor, ensure_root, Config as SystemConfig};
-
+ use frame_system::{pallet_prelude::OriginFor, ensure_root};
+ use sp_arithmetic::{FixedPointOperand, traits::AtLeast32BitUnsigned};
pub use crate::weights::WeightInfo;
- pub type BalanceOf<T> =
- <<T as Config>::Currency as fungible::Inspect<<T as SystemConfig>::AccountId>>::Balance;
#[pallet::config]
pub trait Config: frame_system::Config {
/// Overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
- type Currency: fungible::Inspect<Self::AccountId>
- + fungible::Mutate<Self::AccountId>
- + fungible::MutateFreeze<Self::AccountId>
- + fungible::InspectHold<Self::AccountId>
- + fungible::MutateHold<Self::AccountId>
- + fungible::BalancedHold<Self::AccountId>;
+ type Balance: Parameter
+ + Member
+ + AtLeast32BitUnsigned
+ + Codec
+ + Default
+ + Copy
+ + MaybeSerializeDeserialize
+ + Debug
+ + MaxEncodedLen
+ + TypeInfo
+ + FixedPointOperand;
#[pallet::constant]
type DefaultWeightToFeeCoefficient: Get<u64>;
@@ -79,7 +86,7 @@
#[pallet::constant]
type DefaultCollatorSelectionMaxCollators: Get<u32>;
#[pallet::constant]
- type DefaultCollatorSelectionLicenseBond: Get<BalanceOf<Self>>;
+ type DefaultCollatorSelectionLicenseBond: Get<Self::Balance>;
#[pallet::constant]
type DefaultCollatorSelectionKickThreshold: Get<Self::BlockNumber>;
@@ -94,7 +101,7 @@
desired_collators: Option<u32>,
},
NewCollatorLicenseBond {
- bond_cost: Option<BalanceOf<T>>,
+ bond_cost: Option<T::Balance>,
},
NewCollatorKickThreshold {
length_in_blocks: Option<T::BlockNumber>,
@@ -130,7 +137,7 @@
#[pallet::storage]
pub type CollatorSelectionLicenseBondOverride<T: Config> = StorageValue<
- Value = BalanceOf<T>,
+ Value = T::Balance,
QueryKind = ValueQuery,
OnEmpty = T::DefaultCollatorSelectionLicenseBond,
>;
@@ -221,7 +228,7 @@
#[pallet::weight(T::WeightInfo::set_collator_selection_license_bond())]
pub fn set_collator_selection_license_bond(
origin: OriginFor<T>,
- amount: Option<BalanceOf<T>>,
+ amount: Option<<T as Config>::Balance>,
) -> DispatchResult {
ensure_root(origin)?;
if let Some(amount) = amount {
runtime/common/config/pallets/collator_selection.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/collator_selection.rs
+++ b/runtime/common/config/pallets/collator_selection.rs
@@ -23,7 +23,10 @@
};
use sp_runtime::Perbill;
use up_common::constants::{UNIQUE, MILLIUNIQUE};
-
+use pallet_configuration::{
+ CollatorSelectionKickThresholdOverride, CollatorSelectionLicenseBondOverride,
+ CollatorSelectionDesiredCollatorsOverride,
+};
parameter_types! {
pub const SessionOffset: BlockNumber = 0;
}
@@ -60,6 +63,9 @@
pub const MaxAdditionalFields: u32 = 100;
pub const MaxRegistrars: u32 = 20;
pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";
+ pub LicenseBond: Balance = CollatorSelectionLicenseBondOverride::<Runtime>::get();
+ pub DesiredCollators: u32 = CollatorSelectionDesiredCollatorsOverride::<Runtime>::get();
+ pub KickThreshold: BlockNumber = CollatorSelectionKickThresholdOverride::<Runtime>::get();
}
impl pallet_identity::Config for Runtime {
@@ -84,6 +90,7 @@
impl pallet_collator_selection::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
// We allow root only to execute privileged collator selection operations.
type UpdateOrigin = EnsureRoot<AccountId>;
type TreasuryAccountId = TreasuryAccountId;
@@ -95,4 +102,7 @@
type ValidatorRegistration = Session;
type WeightInfo = pallet_collator_selection::weights::SubstrateWeight<Runtime>;
type LicenceBondIdentifier = LicenceBondIdentifier;
+ type DesiredCollators = DesiredCollators;
+ type LicenseBond = LicenseBond;
+ type KickThreshold = KickThreshold;
}
runtime/common/config/pallets/mod.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -129,7 +129,7 @@
impl pallet_configuration::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
- type Currency = Balances;
+ type Balance = Balance;
type DefaultWeightToFeeCoefficient = ConstU64<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;
type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;
type DefaultCollatorSelectionMaxCollators = MaxCollators;
tests/src/benchmarks/mintFee/index.tsdiffbeforeafterboth--- a/tests/src/benchmarks/mintFee/index.ts
+++ b/tests/src/benchmarks/mintFee/index.ts
@@ -360,7 +360,7 @@
susbstrateReceiver.addressRaw,
PROPERTIES.slice(0, setup.propertiesNumber),
)
- .send({from: ethSigner, gas: 25_000_000});
+ .send({from: ethSigner});
},
);