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.ymldiffbeforeafterboth87 run: |87 run: |88 echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"88 echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"8990 - name: Run benchmark mintFee tests91 working-directory: tests92 run: |93 yarn install94 npx ts-node --esm ./src/benchmarks/mintFee/index.ts9596 - name: Run benchmark opsFee tests97 working-directory: tests98 run: |99 yarn install100 npx ts-node --esm ./src/benchmarks/opsFee/index.ts8910190 - name: Stop running containers102 - name: Stop running containers91 if: always() # run this step always103 if: always() # run this step alwaysCargo.lockdiffbeforeafterboth637163716372[[package]]6372[[package]]6373name = "pallet-collator-selection"6373name = "pallet-collator-selection"6374version = "4.0.0"6374version = "5.0.0"6375dependencies = [6375dependencies = [6376 "frame-benchmarking",6376 "frame-benchmarking",6377 "frame-support",6377 "frame-support",6380 "pallet-aura",6380 "pallet-aura",6381 "pallet-authorship",6381 "pallet-authorship",6382 "pallet-balances",6382 "pallet-balances",6383 "pallet-configuration",6384 "pallet-session",6383 "pallet-session",6385 "pallet-timestamp",6384 "pallet-timestamp",6386 "parity-scale-codec",6385 "parity-scale-codec",643564346436[[package]]6435[[package]]6437name = "pallet-configuration"6436name = "pallet-configuration"6438version = "0.1.3"6437version = "0.2.0"6439dependencies = [6438dependencies = [6440 "fp-evm",6439 "fp-evm",6441 "frame-benchmarking",6440 "frame-benchmarking",pallets/collator-selection/CHANGELOG.mddiffbeforeafterboth445<!-- bureaucracy goes here -->5<!-- bureaucracy goes here -->667## [5.0.0] - 2023-06-2789### Major change1011- The dependency (tight coupling) this pallet on the configuration pallet has been removed.127## [4.0.0] - 2022-12-2913## [4.0.0] - 2022-12-298149### Added15### Added101611- Entire functionality moved over from cumulus/pallet-collator-selection (v3.0.0). Refactored business logic:17- Entire functionality moved over from cumulus/pallet-collator-selection (v3.0.0). Refactored business logic:12 - Added an extra step for candidacy, `get_license`, at which payment happens. The number of license holders is unlimited. 18 - Added an extra step for candidacy, `get_license`, at which payment happens. The number of license holders is unlimited.13 - Only licensed accounts can apply for candidacy with `onboard`. No extra deposits are made.19 - Only licensed accounts can apply for candidacy with `onboard`. No extra deposits are made.14 - Active candidates may `offboard`, but they will retain their license.20 - Active candidates may `offboard`, but they will retain their license.15 - Deposit is returned, and candidacy possibly removed with `release_license`.21 - Deposit is returned, and candidacy possibly removed with `release_license`.16 - License can be forcibly forfeited and candidacy removed with `force_release_license`.22 - License can be forcibly forfeited and candidacy removed with `force_release_license`.17 - Failing collators' deposits will now be fully slashed, and funds will be redirected to Treasury.23 - Failing collators' deposits will now be fully slashed, and funds will be redirected to Treasury.18 - Unify `MaxInvulnerables` and `MaxCandidates` into `MaxCollators`.24 - Unify `MaxInvulnerables` and `MaxCandidates` into `MaxCollators`.19 - Remove `MinCandidates`.25 - Remove `MinCandidates`.20 - Minimal amount of invulnerables is now 1.26 - Minimal amount of invulnerables is now 1.21 - Both invulnerables and candidates count against the limits together, however invulnerables ignore `DesiredCollators`.27 - Both invulnerables and candidates count against the limits together, however invulnerables ignore `DesiredCollators`.22 - `KickThreshold` is made configurable.28 - `KickThreshold` is made configurable.23 - `DesiredCollators`, `LicenseBond`, and `KickThreshold` are moved to and referenced from `pallet-configuration`.29 - `DesiredCollators`, `LicenseBond`, and `KickThreshold` are moved to and referenced from `pallet-configuration`.24 - Naming changes to better reflect the new functionality.30 - Naming changes to better reflect the new functionality.25 - More minor changes, tests, benchmarks, etc.31 - More minor changes, tests, benchmarks, etc.32pallets/collator-selection/Cargo.tomldiffbeforeafterboth6license = "GPLv3"6license = "GPLv3"7name = "pallet-collator-selection"7name = "pallet-collator-selection"8repository = "https://github.com/UniqueNetwork/unique-chain"8repository = "https://github.com/UniqueNetwork/unique-chain"9version = "4.0.0"9version = "5.0.0"101011[package.metadata.docs.rs]11[package.metadata.docs.rs]12targets = ["x86_64-unknown-linux-gnu"]12targets = ["x86_64-unknown-linux-gnu"]23frame-support = { workspace = true }23frame-support = { workspace = true }24frame-system = { workspace = true }24frame-system = { workspace = true }25pallet-authorship = { workspace = true }25pallet-authorship = { workspace = true }26pallet-configuration = { workspace = true }27pallet-session = { workspace = true }26pallet-session = { workspace = true }28sp-runtime = { workspace = true }27sp-runtime = { workspace = true }29sp-staking = { workspace = true }28sp-staking = { workspace = true }55 "frame-system/std",54 "frame-system/std",56 "log/std",55 "log/std",57 "pallet-authorship/std",56 "pallet-authorship/std",58 'pallet-aura/std',59 'pallet-balances/std',60 "pallet-session/std",57 "pallet-session/std",61 "rand/std",58 "rand/std",62 "scale-info/std",59 "scale-info/std",63 "sp-consensus-aura/std",60 "sp-consensus-aura/std",64 "sp-runtime/std",61 "sp-runtime/std",65 "sp-staking/std",62 "sp-staking/std",66 "sp-std/std",63 "sp-std/std",64 'pallet-aura/std',65 'pallet-balances/std',67]66]686769try-runtime = ["frame-support/try-runtime"]68try-runtime = ["frame-support/try-runtime"]pallets/collator-selection/src/benchmarking.rsdiffbeforeafterboth35use super::*;35use super::*;363637#[allow(unused)]37#[allow(unused)]38use crate::Pallet as CollatorSelection;38use crate::{Pallet as CollatorSelection, BalanceOf};39use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller};39use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller};40use frame_support::{40use frame_support::{41 assert_ok,41 assert_ok,49use frame_system::{EventRecord, RawOrigin};49use frame_system::{EventRecord, RawOrigin};50use pallet_authorship::EventHandler;50use pallet_authorship::EventHandler;51use pallet_session::{self as session, SessionManager};51use pallet_session::{self as session, SessionManager};52use pallet_configuration::{53 self as configuration, BalanceOf,54 CollatorSelectionDesiredCollatorsOverride as DesiredCollators,55 CollatorSelectionLicenseBondOverride as LicenseBond,56};57use sp_std::prelude::*;52use sp_std::prelude::*;585359const SEED: u32 = 0;54const SEED: u32 = 0;117 validators.into_iter().map(|(who, _)| who).collect()112 validators.into_iter().map(|(who, _)| who).collect()118}113}119114120fn register_invulnerables<T: Config + configuration::Config>(count: u32) {115fn register_invulnerables<T: Config>(count: u32) {121 let candidates = (0..count)116 let candidates = (0..count)122 .map(|c| account("candidate", c, SEED))117 .map(|c| account("candidate", c, SEED))123 .collect::<Vec<_>>();118 .collect::<Vec<_>>();131 }126 }132}127}133128134fn register_candidates<T: Config + configuration::Config>(count: u32) {129fn register_candidates<T: Config>(count: u32) {135 let candidates = (0..count)130 let candidates = (0..count)136 .map(|c| account("candidate", c, SEED))131 .map(|c| account("candidate", c, SEED))137 .collect::<Vec<_>>();132 .collect::<Vec<_>>();138 assert!(133 assert!(T::LicenseBond::get() > 0u32.into(), "Bond cannot be zero!");139 <LicenseBond<T>>::get() > 0u32.into(),140 "Bond cannot be zero!"141 );142134143 for who in candidates {135 for who in candidates {144 T::Currency::set_balance(&who, <LicenseBond<T>>::get() * 2u32.into());136 T::Currency::set_balance(&who, T::LicenseBond::get() * 2u32.into());145 <CollatorSelection<T>>::get_license(RawOrigin::Signed(who.clone()).into()).unwrap();137 <CollatorSelection<T>>::get_license(RawOrigin::Signed(who.clone()).into()).unwrap();146 <CollatorSelection<T>>::onboard(RawOrigin::Signed(who).into()).unwrap();138 <CollatorSelection<T>>::onboard(RawOrigin::Signed(who).into()).unwrap();147 }139 }148}140}149141150fn get_licenses<T: Config + configuration::Config>(count: u32) {142fn get_licenses<T: Config>(count: u32) {151 let candidates = (0..count)143 let candidates = (0..count)152 .map(|c| account("candidate", c, SEED))144 .map(|c| account("candidate", c, SEED))153 .collect::<Vec<_>>();145 .collect::<Vec<_>>();154 assert!(146 assert!(T::LicenseBond::get() > 0u32.into(), "Bond cannot be zero!");155 <LicenseBond<T>>::get() > 0u32.into(),156 "Bond cannot be zero!"157 );158147159 for who in candidates {148 for who in candidates {160 T::Currency::set_balance(&who, <LicenseBond<T>>::get() * 2u32.into());149 T::Currency::set_balance(&who, T::LicenseBond::get() * 2u32.into());161 <CollatorSelection<T>>::get_license(RawOrigin::Signed(who.clone()).into()).unwrap();150 <CollatorSelection<T>>::get_license(RawOrigin::Signed(who.clone()).into()).unwrap();162 }151 }163}152}164153165/// `Currency::minimum_balance` was used originally, but in unique-chain, we have154/// `Currency::minimum_balance` was used originally, but in unique-chain, we have166/// zero existential deposit, thus triggering zero bond assertion.155/// zero existential deposit, thus triggering zero bond assertion.167fn balance_unit<T: Config>() -> BalanceOf<T> {156fn balance_unit<T: Config>() -> BalanceOf<T> {168 200u32.into()157 T::LicenseBond::get()169}158}170159171/// Our benchmarking environment already has invulnerables registered.160/// Our benchmarking environment already has invulnerables registered.172const INITIAL_INVULNERABLES: u32 = 2;161const INITIAL_INVULNERABLES: u32 = 2;173162174benchmarks! {163benchmarks! {175 where_clause { where164 where_clause { where176 T: pallet_authorship::Config + session::Config + configuration::Config165 T: Config + pallet_authorship::Config + session::Config177 }166 }178167179 // todo:collator this and all the following do not work for some reason, going all the way up to 10 in length168 // todo:collator this and all the following do not work for some reason, going all the way up to 10 in length188177189 let new_invulnerable: T::AccountId = whitelisted_caller();178 let new_invulnerable: T::AccountId = whitelisted_caller();190 let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();179 let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();191 T::Currency::set_balance(&new_invulnerable, bond.clone());180 <T as Config>::Currency::set_balance(&new_invulnerable, bond);192181193 <session::Pallet<T>>::set_keys(182 <session::Pallet<T>>::set_keys(194 RawOrigin::Signed(new_invulnerable.clone()).into(),183 RawOrigin::Signed(new_invulnerable.clone()).into(),226 get_license {215 get_license {227 let c in 1 .. T::MaxCollators::get() - 1;216 let c in 1 .. T::MaxCollators::get() - 1;228229 <LicenseBond<T>>::put(balance_unit::<T>());230217231 register_validators::<T>(c);218 register_validators::<T>(c);232 get_licenses::<T>(c);219 get_licenses::<T>(c);233220234 let caller: T::AccountId = whitelisted_caller();221 let caller: T::AccountId = whitelisted_caller();235 let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();222 let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();236 T::Currency::set_balance(&caller, bond.clone());223 T::Currency::set_balance(&caller, bond);237224238 <session::Pallet<T>>::set_keys(225 <session::Pallet<T>>::set_keys(239 RawOrigin::Signed(caller.clone()).into(),226 RawOrigin::Signed(caller.clone()).into(),251 onboard {238 onboard {252 let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES - 1;239 let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES - 1;253254 <LicenseBond<T>>::put(balance_unit::<T>());255 <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES + 1);256240257 register_validators::<T>(c);241 register_validators::<T>(c);258 register_candidates::<T>(c);242 register_candidates::<T>(c);259243260 let caller: T::AccountId = whitelisted_caller();244 let caller: T::AccountId = whitelisted_caller();261 let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();245 let bond: BalanceOf<T> = balance_unit::<T>() * 2u32.into();262 T::Currency::set_balance(&caller, bond.clone());246 T::Currency::set_balance(&caller, bond);263247264 let origin = RawOrigin::Signed(caller.clone());248 let origin = RawOrigin::Signed(caller.clone());265249279263280 // worst case is the last candidate leaving.264 // worst case is the last candidate leaving.281 offboard {265 offboard {282 let c in 1 .. T::MaxCollators::get();266 let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;283 <LicenseBond<T>>::put(balance_unit::<T>());284 <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);285267286 register_validators::<T>(c);268 register_validators::<T>(c);287 register_candidates::<T>(c);269 register_candidates::<T>(c);295277296 // worst case is the last candidate leaving.278 // worst case is the last candidate leaving.297 release_license {279 release_license {298 let c in 1 .. T::MaxCollators::get();280 let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;299 let bond = balance_unit::<T>();281 let bond = balance_unit::<T>();300 <LicenseBond<T>>::put(bond);301 <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);302282303 register_validators::<T>(c);283 register_validators::<T>(c);304 register_candidates::<T>(c);284 register_candidates::<T>(c);312292313 // worst case is the last candidate leaving.293 // worst case is the last candidate leaving.314 force_release_license {294 force_release_license {315 let c in 1 .. T::MaxCollators::get();295 let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;316 let bond = balance_unit::<T>();296 let bond = balance_unit::<T>();317 <LicenseBond<T>>::put(bond);318 <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);319297320 register_validators::<T>(c);298 register_validators::<T>(c);321 register_candidates::<T>(c);299 register_candidates::<T>(c);334312335 // worst case is paying a non-existing candidate account.313 // worst case is paying a non-existing candidate account.336 note_author {314 note_author {337 <LicenseBond<T>>::put(balance_unit::<T>());338 T::Currency::set_balance(315 T::Currency::set_balance(339 &<CollatorSelection<T>>::account_id(),316 &<CollatorSelection<T>>::account_id(),340 balance_unit::<T>() * 4u32.into(),317 balance_unit::<T>() * 4u32.into(),353330354 // worst case for new session.331 // worst case for new session.355 new_session {332 new_session {356 let r in 1 .. T::MaxCollators::get();333 let r in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;357 let c in 1 .. T::MaxCollators::get();334 let c in 1 .. T::MaxCollators::get() - INITIAL_INVULNERABLES;358335359 <LicenseBond<T>>::put(balance_unit::<T>());360 <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES);361 frame_system::Pallet::<T>::set_block_number(0u32.into());336 frame_system::Pallet::<T>::set_block_number(0u32.into());362337363 register_validators::<T>(c);338 register_validators::<T>(c);pallets/collator-selection/src/lib.rsdiffbeforeafterboth90mod benchmarking;90mod benchmarking;91pub mod weights;91pub mod weights;929293use frame_support::traits::fungible::Inspect;9495type BalanceOf<T> =96 <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;93#[frame_support::pallet]97#[frame_support::pallet]94pub mod pallet {98pub mod pallet {95 use super::*;99 use super::*;111 use frame_system::pallet_prelude::*;115 use frame_system::pallet_prelude::*;112 use pallet_session::SessionManager;116 use pallet_session::SessionManager;113 use sp_runtime::{Perbill, traits::Convert};117 use sp_runtime::{Perbill, traits::Convert};114 use pallet_configuration::{115 CollatorSelectionDesiredCollatorsOverride as DesiredCollators,116 CollatorSelectionLicenseBondOverride as LicenseBond,117 CollatorSelectionKickThresholdOverride as KickThreshold, BalanceOf,118 };119 use sp_staking::SessionIndex;118 use sp_staking::SessionIndex;120119121 /// A convertor from collators id. Since this pallet does not have stash/controller, this is120 /// A convertor from collators id. Since this pallet does not have stash/controller, this is129128130 /// Configure the pallet by specifying the parameters and types on which it depends.129 /// Configure the pallet by specifying the parameters and types on which it depends.131 #[pallet::config]130 #[pallet::config]132 pub trait Config: frame_system::Config + pallet_configuration::Config {131 pub trait Config: frame_system::Config {133 /// Overarching event type.132 /// Overarching event type.134 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;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>;135137136 /// Origin that can dictate updating parameters of this pallet.138 /// Origin that can dictate updating parameters of this pallet.137 type UpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;139 type UpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;163 type WeightInfo: WeightInfo;165 type WeightInfo: WeightInfo;164166165 #[pallet::constant]167 #[pallet::constant]166 type LicenceBondIdentifier: Get<<<Self as pallet_configuration::Config>::Currency as InspectHold<Self::AccountId>>::Reason>;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>;167 }175 }168176169 #[pallet::pallet]177 #[pallet::pallet]365 Error::<T>::ValidatorNotRegistered373 Error::<T>::ValidatorNotRegistered366 );374 );367375368 let deposit = <LicenseBond<T>>::get();376 let deposit = T::LicenseBond::get();369377370 T::Currency::hold(&T::LicenceBondIdentifier::get(), &who, deposit)?;378 T::Currency::hold(&T::LicenceBondIdentifier::get(), &who, deposit)?;371 LicenseDepositOf::<T>::insert(who.clone(), deposit);379 LicenseDepositOf::<T>::insert(who.clone(), deposit);396 let length = <Candidates<T>>::decode_len().unwrap_or_default()404 let length = <Candidates<T>>::decode_len().unwrap_or_default()397 + <Invulnerables<T>>::decode_len().unwrap_or_default();405 + <Invulnerables<T>>::decode_len().unwrap_or_default();398 ensure!(406 ensure!(399 (length as u32) < <DesiredCollators<T>>::get(),407 (length as u32) < T::DesiredCollators::get(),400 Error::<T>::TooManyCandidates408 Error::<T>::TooManyCandidates401 );409 );402 ensure!(410 ensure!(415 // First authored block is current block plus kick threshold to handle session delay423 // First authored block is current block plus kick threshold to handle session delay416 <LastAuthoredBlock<T>>::insert(424 <LastAuthoredBlock<T>>::insert(417 who.clone(),425 who.clone(),418 frame_system::Pallet::<T>::block_number() + <KickThreshold<T>>::get(),426 frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),419 );427 );420 Ok(candidates.len())428 Ok(candidates.len())421 }429 }574 candidates: BoundedVec<T::AccountId, T::MaxCollators>,582 candidates: BoundedVec<T::AccountId, T::MaxCollators>,575 ) -> BoundedVec<T::AccountId, T::MaxCollators> {583 ) -> BoundedVec<T::AccountId, T::MaxCollators> {576 let now = frame_system::Pallet::<T>::block_number();584 let now = frame_system::Pallet::<T>::block_number();577 let kick_threshold = <KickThreshold<T>>::get();585 let kick_threshold = T::KickThreshold::get();578 candidates586 candidates579 .into_iter()587 .into_iter()580 .filter_map(|c| {588 .filter_map(|c| {pallets/collator-selection/src/mock.rsdiffbeforeafterboth63 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},63 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},64 CollatorSelection: collator_selection::{Pallet, Call, Storage, Event<T>},64 CollatorSelection: collator_selection::{Pallet, Call, Storage, Event<T>},65 Authorship: pallet_authorship::{Pallet, Storage},65 Authorship: pallet_authorship::{Pallet, Storage},66 Configuration: pallet_configuration::{Pallet, Call, Storage, Event<T>},67 }66 }68);67);6968218 pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";217 pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";219}218}220221impl pallet_configuration::Config for Test {222 type RuntimeEvent = RuntimeEvent;223 type Currency = Balances;224 type DefaultCollatorSelectionMaxCollators = MaxCollators;225 type DefaultCollatorSelectionKickThreshold = KickThreshold;226 type DefaultCollatorSelectionLicenseBond = LicenseBond;227 // the following constants we don't care about228 type DefaultWeightToFeeCoefficient = DefaultWeightToFeeCoefficient;229 type DefaultMinGasPrice = DefaultMinGasPrice;230 type MaxXcmAllowedLocations = MaxXcmAllowedLocations;231 type AppPromotionDailyRate = AppPromotionDailyRate;232 type DayRelayBlocks = DayRelayBlocks;233 type WeightInfo = pallet_configuration::weights::SubstrateWeight<Self>;234}235219236ord_parameter_types! {220ord_parameter_types! {237 pub const RootAccount: u64 = 777;221 pub const RootAccount: u64 = 777;246pub struct IsRegistered;230pub struct IsRegistered;247impl ValidatorRegistration<u64> for IsRegistered {231impl ValidatorRegistration<u64> for IsRegistered {248 fn is_registered(id: &u64) -> bool {232 fn is_registered(id: &u64) -> bool {249 if *id == 7u64 {233 *id != 7u64250 false251 } else {252 true253 }254 }234 }255}235}256236265 type ValidatorIdOf = IdentityCollator;245 type ValidatorIdOf = IdentityCollator;266 type ValidatorRegistration = IsRegistered;246 type ValidatorRegistration = IsRegistered;267 type LicenceBondIdentifier = LicenceBondIdentifier;247 type LicenceBondIdentifier = LicenceBondIdentifier;248 type Currency = Balances;249 type DesiredCollators = MaxCollators;250 type LicenseBond = LicenseBond;251 type KickThreshold = KickThreshold;268 type WeightInfo = ();252 type WeightInfo = ();269}253}270254277261278 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();262 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();279263280 let balances = vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (33, ed)];264 let balances: Vec<(u64, u64)> = (1..=<Test as Config>::DesiredCollators::get() as u64 + 1)265 .map(|i| (i, 100))266 .chain(core::iter::once((33, ed)))267 .collect();268281 let keys = balances269 let keys = balances282 .iter()270 .iter()pallets/collator-selection/src/tests.rsdiffbeforeafterboth30// See the License for the specific language governing permissions and30// See the License for the specific language governing permissions and31// limitations under the License.31// limitations under the License.323233use crate as collator_selection;33use crate::{self as collator_selection, Config};34use crate::{mock::*, Error};34use crate::{mock::*, Error};35use frame_support::{35use frame_support::{36 assert_noop, assert_ok,36 assert_noop, assert_ok,37 traits::{fungible, GenesisBuild, OnInitialize},37 traits::{fungible, GenesisBuild, OnInitialize},38};38};39use frame_system::RawOrigin;40use sp_runtime::{traits::BadOrigin, TokenError};39use sp_runtime::{traits::BadOrigin, TokenError};41use pallet_configuration::{42 CollatorSelectionDesiredCollatorsOverride as DesiredCollators,43 CollatorSelectionKickThresholdOverride as KickThreshold,44 CollatorSelectionLicenseBondOverride as LicenseBond,45};46use scale_info::prelude::*;40use scale_info::prelude::*;474148fn get_license_and_onboard(account_id: <Test as frame_system::Config>::AccountId) {42fn get_license_and_onboard(account_id: <Test as frame_system::Config>::AccountId) {57#[test]51#[test]58fn basic_setup_works() {52fn basic_setup_works() {59 new_test_ext().execute_with(|| {53 new_test_ext().execute_with(|| {60 assert_eq!(<DesiredCollators<Test>>::get(), 5);61 assert_eq!(<LicenseBond<Test>>::get(), 10);6263 assert!(CollatorSelection::candidates().is_empty());54 assert!(CollatorSelection::candidates().is_empty());64 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);55 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);124 });115 });125}116}126127#[test]128fn set_desired_collators_works() {129 new_test_ext().execute_with(|| {130 // given131 assert_eq!(<DesiredCollators<Test>>::get(), 5);132133 // can set134 assert_ok!(Configuration::set_collator_selection_desired_collators(135 RawOrigin::Root.into(),136 Some(7)137 ));138 assert_eq!(<DesiredCollators<Test>>::get(), 7);139140 // rejects bad origin141 assert_noop!(142 Configuration::set_collator_selection_desired_collators(143 RuntimeOrigin::signed(1),144 Some(8)145 ),146 BadOrigin147 );148 });149}150151#[test]152fn set_license_bond() {153 new_test_ext().execute_with(|| {154 // given155 assert_eq!(<LicenseBond<Test>>::get(), 10);156157 // can set158 assert_ok!(Configuration::set_collator_selection_license_bond(159 RawOrigin::Root.into(),160 Some(7)161 ));162 assert_eq!(<LicenseBond<Test>>::get(), 7);163164 // rejects bad origin.165 assert_noop!(166 Configuration::set_collator_selection_license_bond(RuntimeOrigin::signed(1), Some(8)),167 BadOrigin168 );169 });170}171117172#[test]118#[test]173fn cannot_onboard_candidate_with_no_license() {119fn cannot_onboard_candidate_with_no_license() {187#[test]133#[test]188fn cannot_onboard_candidate_if_too_many() {134fn cannot_onboard_candidate_if_too_many() {189 new_test_ext().execute_with(|| {135 new_test_ext().execute_with(|| {190 // reset desired candidates136 // can accept desired value of collators.191 <pallet_configuration::CollatorSelectionDesiredCollatorsOverride<Test>>::put(0);137 for c in 3u64..=(<Test as Config>::DesiredCollators::get()).into() {192193 // can still get a license.194 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));138 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(c)));195196 // can't accept anyone anymore.197 assert_noop!(139 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(c)));198 CollatorSelection::onboard(RuntimeOrigin::signed(4)),140 }199 Error::<Test>::TooManyCandidates,141200 );142 // but no more.201202 // reset desired candidates to invulnerables + 1203 <pallet_configuration::CollatorSelectionDesiredCollatorsOverride<Test>>::put(3);204 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(4)));143 let undesired_collator = (<Test as Config>::DesiredCollators::get() + 1) as u64;205206 // but no more.207 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(5)));144 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(145 undesired_collator146 )));208 assert_noop!(147 assert_noop!(209 CollatorSelection::onboard(RuntimeOrigin::signed(5)),148 CollatorSelection::onboard(RuntimeOrigin::signed(undesired_collator)),210 Error::<Test>::TooManyCandidates,149 Error::<Test>::TooManyCandidates,211 );150 );212 })151 })227fn cannot_obtain_license_if_poor() {166fn cannot_obtain_license_if_poor() {228 new_test_ext().execute_with(|| {167 new_test_ext().execute_with(|| {229 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();168 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();230 assert_eq!(Balances::free_balance(&3), 100);169 assert_eq!(Balances::free_balance(3), 100);231 assert_eq!(Balances::free_balance(&33), ed);170 assert_eq!(Balances::free_balance(33), ed);232171233 // works172 // works234 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));173 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));266#[test]205#[test]267fn becoming_candidate_works() {206fn becoming_candidate_works() {268 new_test_ext().execute_with(|| {207 new_test_ext().execute_with(|| {269 // given270 assert_eq!(<DesiredCollators<Test>>::get(), 5);271 assert_eq!(<LicenseBond<Test>>::get(), 10);272 assert_eq!(CollatorSelection::candidates(), Vec::new());208 assert_eq!(CollatorSelection::candidates(), Vec::new());273 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);209 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);274210275 // take two endowed, non-invulnerables accounts.211 // take two endowed, non-invulnerables accounts.276 assert_eq!(Balances::free_balance(&3), 100);212 assert_eq!(Balances::free_balance(3), 100);277 assert_eq!(Balances::free_balance(&4), 100);213 assert_eq!(Balances::free_balance(4), 100);278214279 get_license_and_onboard(3);215 get_license_and_onboard(3);280 get_license_and_onboard(4);216 get_license_and_onboard(4);281217282 assert_eq!(Balances::free_balance(&3), 90);218 assert_eq!(Balances::free_balance(3), 90);283 assert_eq!(Balances::free_balance(&4), 90);219 assert_eq!(Balances::free_balance(4), 90);284220285 assert_eq!(CollatorSelection::candidates().len(), 2);221 assert_eq!(CollatorSelection::candidates().len(), 2);286 });222 });513 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);449 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);514450515 assert_eq!(CollatorSelection::candidates(), vec![4]);451 assert_eq!(CollatorSelection::candidates(), vec![4]);516 assert_eq!(<KickThreshold<Test>>::get(), 10);452 // assert_eq!(<KickThreshold<Test>>::get(), 10);517 assert_eq!(CollatorSelection::last_authored_block(4), 20);453 assert_eq!(CollatorSelection::last_authored_block(4), 20);518454519 initialize_to_block(30);455 initialize_to_block(30);pallets/configuration/CHANGELOG.mddiffbeforeafterboth3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->6## [0.2.0] - 2023-06-27678### Major change910- 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.117## [0.1.3] - 2022-12-2912## [0.1.3] - 2022-12-298139### Added14### Added202521### Other changes26### Other changes222723- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a28- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a29pallets/configuration/Cargo.tomldiffbeforeafterboth1[package]1[package]2edition = "2021"2edition = "2021"3name = "pallet-configuration"3name = "pallet-configuration"4version = "0.1.3"4version = "0.2.0"556[dependencies]6[dependencies]7# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.7# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.22default = ["std"]22default = ["std"]23runtime-benchmarks = ["frame-benchmarking"]23runtime-benchmarks = ["frame-benchmarking"]24std = [24std = [25 "codec/std",25 "fp-evm/std",26 "fp-evm/std",26 "frame-benchmarking/std",27 "frame-benchmarking/std",27 "frame-support/std",28 "frame-support/std",28 "frame-system/std",29 "frame-system/std",29 "codec/std",30 "sp-arithmetic/std",30 "sp-arithmetic/std",31 "sp-core/std",31 "sp-core/std",32 "sp-std/std",32 "sp-std/std",pallets/configuration/src/benchmarking.rsdiffbeforeafterboth19use super::*;19use super::*;20use frame_benchmarking::benchmarks;20use frame_benchmarking::benchmarks;21use frame_system::{EventRecord, RawOrigin};21use frame_system::{EventRecord, RawOrigin};22use frame_support::{assert_ok, traits::fungible::Inspect};22use frame_support::assert_ok;232324fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {24fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {25 let events = frame_system::Pallet::<T>::events();25 let events = frame_system::Pallet::<T>::events();313132benchmarks! {32benchmarks! {33 where_clause { where T: Config }33 where_clause { where34 T: Config,35 T::Balance: From<u32>36 }343735 set_weight_to_fee_coefficient_override {38 set_weight_to_fee_coefficient_override {60 let max: u32 = 999;63 let max: u32 = 999;61 }: {64 }: {62 assert_ok!(65 assert_ok!(63 <Pallet<T>>::set_collator_selection_desired_collators(RawOrigin::Root.into(), Some(max.clone()))66 <Pallet<T>>::set_collator_selection_desired_collators(RawOrigin::Root.into(), Some(max))64 );67 );65 }68 }66 verify {69 verify {67 assert_last_event::<T>(Event::NewDesiredCollators{desired_collators: Some(max)}.into());70 assert_last_event::<T>(Event::NewDesiredCollators{desired_collators: Some(max)}.into());68 }71 }697270 set_collator_selection_license_bond {73 set_collator_selection_license_bond {71 let bond_cost: Option<BalanceOf<T>> = Some(T::Currency::minimum_balance() * 10u32.into());74 let bond_cost: Option<T::Balance> = Some(1000u32.into());72 }: {75 }: {73 assert_ok!(76 assert_ok!(74 <Pallet<T>>::set_collator_selection_license_bond(RawOrigin::Root.into(), bond_cost.clone())77 <Pallet<T>>::set_collator_selection_license_bond(RawOrigin::Root.into(), bond_cost)75 );78 );76 }79 }77 verify {80 verify {82 let threshold: Option<T::BlockNumber> = Some(900u32.into());85 let threshold: Option<T::BlockNumber> = Some(900u32.into());83 }: {86 }: {84 assert_ok!(87 assert_ok!(85 <Pallet<T>>::set_collator_selection_kick_threshold(RawOrigin::Root.into(), threshold.clone())88 <Pallet<T>>::set_collator_selection_kick_threshold(RawOrigin::Root.into(), threshold)86 );89 );87 }90 }88 verify {91 verify {pallets/configuration/src/lib.rsdiffbeforeafterboth22 pallet,22 pallet,23 weights::{WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient, Weight},23 weights::{WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient, Weight},24 traits::Get,24 traits::Get,25 Parameter,25};26};26use codec::{Decode, Encode, MaxEncodedLen};27use codec::{Decode, Encode, MaxEncodedLen};27use scale_info::TypeInfo;28use scale_info::TypeInfo;42mod pallet {43mod pallet {43 use super::*;44 use super::*;44 use frame_support::{45 use frame_support::{45 traits::{fungible, Get},46 traits::{Get},46 pallet_prelude::{StorageValue, ValueQuery, DispatchResult, IsType},47 pallet_prelude::{48 StorageValue, ValueQuery, DispatchResult, IsType, Member, MaybeSerializeDeserialize,49 },47 log,50 log,51 dispatch::{Codec, fmt::Debug},48 };52 };49 use frame_system::{pallet_prelude::OriginFor, ensure_root, Config as SystemConfig};53 use frame_system::{pallet_prelude::OriginFor, ensure_root};5054 use sp_arithmetic::{FixedPointOperand, traits::AtLeast32BitUnsigned};51 pub use crate::weights::WeightInfo;55 pub use crate::weights::WeightInfo;52 pub type BalanceOf<T> =53 <<T as Config>::Currency as fungible::Inspect<<T as SystemConfig>::AccountId>>::Balance;545655 #[pallet::config]57 #[pallet::config]56 pub trait Config: frame_system::Config {58 pub trait Config: frame_system::Config {57 /// Overarching event type.59 /// Overarching event type.58 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;60 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;596160 type Currency: fungible::Inspect<Self::AccountId>62 type Balance: Parameter61 + fungible::Mutate<Self::AccountId>63 + Member62 + fungible::MutateFreeze<Self::AccountId>64 + AtLeast32BitUnsigned63 + fungible::InspectHold<Self::AccountId>65 + Codec64 + fungible::MutateHold<Self::AccountId>66 + Default65 + fungible::BalancedHold<Self::AccountId>;67 + Copy68 + MaybeSerializeDeserialize69 + Debug70 + MaxEncodedLen71 + TypeInfo72 + FixedPointOperand;667367 #[pallet::constant]74 #[pallet::constant]68 type DefaultWeightToFeeCoefficient: Get<u64>;75 type DefaultWeightToFeeCoefficient: Get<u64>;79 #[pallet::constant]86 #[pallet::constant]80 type DefaultCollatorSelectionMaxCollators: Get<u32>;87 type DefaultCollatorSelectionMaxCollators: Get<u32>;81 #[pallet::constant]88 #[pallet::constant]82 type DefaultCollatorSelectionLicenseBond: Get<BalanceOf<Self>>;89 type DefaultCollatorSelectionLicenseBond: Get<Self::Balance>;83 #[pallet::constant]90 #[pallet::constant]84 type DefaultCollatorSelectionKickThreshold: Get<Self::BlockNumber>;91 type DefaultCollatorSelectionKickThreshold: Get<Self::BlockNumber>;859294 desired_collators: Option<u32>,101 desired_collators: Option<u32>,95 },102 },96 NewCollatorLicenseBond {103 NewCollatorLicenseBond {97 bond_cost: Option<BalanceOf<T>>,104 bond_cost: Option<T::Balance>,98 },105 },99 NewCollatorKickThreshold {106 NewCollatorKickThreshold {100 length_in_blocks: Option<T::BlockNumber>,107 length_in_blocks: Option<T::BlockNumber>,130137131 #[pallet::storage]138 #[pallet::storage]132 pub type CollatorSelectionLicenseBondOverride<T: Config> = StorageValue<139 pub type CollatorSelectionLicenseBondOverride<T: Config> = StorageValue<133 Value = BalanceOf<T>,140 Value = T::Balance,134 QueryKind = ValueQuery,141 QueryKind = ValueQuery,135 OnEmpty = T::DefaultCollatorSelectionLicenseBond,142 OnEmpty = T::DefaultCollatorSelectionLicenseBond,136 >;143 >;221 #[pallet::weight(T::WeightInfo::set_collator_selection_license_bond())]228 #[pallet::weight(T::WeightInfo::set_collator_selection_license_bond())]222 pub fn set_collator_selection_license_bond(229 pub fn set_collator_selection_license_bond(223 origin: OriginFor<T>,230 origin: OriginFor<T>,224 amount: Option<BalanceOf<T>>,231 amount: Option<<T as Config>::Balance>,225 ) -> DispatchResult {232 ) -> DispatchResult {226 ensure_root(origin)?;233 ensure_root(origin)?;227 if let Some(amount) = amount {234 if let Some(amount) = amount {runtime/common/config/pallets/collator_selection.rsdiffbeforeafterboth23};23};24use sp_runtime::Perbill;24use sp_runtime::Perbill;25use up_common::constants::{UNIQUE, MILLIUNIQUE};25use up_common::constants::{UNIQUE, MILLIUNIQUE};2626use pallet_configuration::{27 CollatorSelectionKickThresholdOverride, CollatorSelectionLicenseBondOverride,28 CollatorSelectionDesiredCollatorsOverride,29};27parameter_types! {30parameter_types! {28 pub const SessionOffset: BlockNumber = 0;31 pub const SessionOffset: BlockNumber = 0;29}32}60 pub const MaxAdditionalFields: u32 = 100;63 pub const MaxAdditionalFields: u32 = 100;61 pub const MaxRegistrars: u32 = 20;64 pub const MaxRegistrars: u32 = 20;62 pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";65 pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";66 pub LicenseBond: Balance = CollatorSelectionLicenseBondOverride::<Runtime>::get();67 pub DesiredCollators: u32 = CollatorSelectionDesiredCollatorsOverride::<Runtime>::get();68 pub KickThreshold: BlockNumber = CollatorSelectionKickThresholdOverride::<Runtime>::get();63}69}647065impl pallet_identity::Config for Runtime {71impl pallet_identity::Config for Runtime {849085impl pallet_collator_selection::Config for Runtime {91impl pallet_collator_selection::Config for Runtime {86 type RuntimeEvent = RuntimeEvent;92 type RuntimeEvent = RuntimeEvent;93 type Currency = Balances;87 // We allow root only to execute privileged collator selection operations.94 // We allow root only to execute privileged collator selection operations.88 type UpdateOrigin = EnsureRoot<AccountId>;95 type UpdateOrigin = EnsureRoot<AccountId>;89 type TreasuryAccountId = TreasuryAccountId;96 type TreasuryAccountId = TreasuryAccountId;95 type ValidatorRegistration = Session;102 type ValidatorRegistration = Session;96 type WeightInfo = pallet_collator_selection::weights::SubstrateWeight<Runtime>;103 type WeightInfo = pallet_collator_selection::weights::SubstrateWeight<Runtime>;97 type LicenceBondIdentifier = LicenceBondIdentifier;104 type LicenceBondIdentifier = LicenceBondIdentifier;105 type DesiredCollators = DesiredCollators;106 type LicenseBond = LicenseBond;107 type KickThreshold = KickThreshold;98}108}99109runtime/common/config/pallets/mod.rsdiffbeforeafterboth129129130impl pallet_configuration::Config for Runtime {130impl pallet_configuration::Config for Runtime {131 type RuntimeEvent = RuntimeEvent;131 type RuntimeEvent = RuntimeEvent;132 type Currency = Balances;132 type Balance = Balance;133 type DefaultWeightToFeeCoefficient = ConstU64<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;133 type DefaultWeightToFeeCoefficient = ConstU64<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;134 type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;134 type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;135 type DefaultCollatorSelectionMaxCollators = MaxCollators;135 type DefaultCollatorSelectionMaxCollators = MaxCollators;tests/src/benchmarks/mintFee/index.tsdiffbeforeafterboth360 susbstrateReceiver.addressRaw,360 susbstrateReceiver.addressRaw,361 PROPERTIES.slice(0, setup.propertiesNumber),361 PROPERTIES.slice(0, setup.propertiesNumber),362 )362 )363 .send({from: ethSigner, gas: 25_000_000});363 .send({from: ethSigner});364 },364 },365 );365 );366366