git.delta.rocks / unique-network / refs/commits / d8a735e3ebdb

difftreelog

refactor! decouple pallet-collator-selection from pallet-configuration (#962)

Pavel Orlov2023-06-30parent: #1ecd8fc.patch.diff
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

modified.github/workflows/yarn-dev.ymldiffbeforeafterboth
87 run: |87 run: |
88 echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"88 echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"
89
90 - name: Run benchmark mintFee tests
91 working-directory: tests
92 run: |
93 yarn install
94 npx ts-node --esm ./src/benchmarks/mintFee/index.ts
95
96 - name: Run benchmark opsFee tests
97 working-directory: tests
98 run: |
99 yarn install
100 npx ts-node --esm ./src/benchmarks/opsFee/index.ts
89101
90 - name: Stop running containers102 - name: Stop running containers
91 if: always() # run this step always103 if: always() # run this step always
modifiedCargo.lockdiffbeforeafterboth
63716371
6372[[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",
64356434
6436[[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",
modifiedpallets/collator-selection/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucracy goes here -->5<!-- bureaucracy goes here -->
66
7## [5.0.0] - 2023-06-27
8
9### Major change
10
11- The dependency (tight coupling) this pallet on the configuration pallet has been removed.
12
7## [4.0.0] - 2022-12-2913## [4.0.0] - 2022-12-29
814
9### Added15### Added
1016
11- 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.
32
modifiedpallets/collator-selection/Cargo.tomldiffbeforeafterboth
6license = "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"
1010
11[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]
6867
69try-runtime = ["frame-support/try-runtime"]68try-runtime = ["frame-support/try-runtime"]
modifiedpallets/collator-selection/src/benchmarking.rsdiffbeforeafterboth
35use super::*;35use super::*;
3636
37#[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::*;
5853
59const 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}
119114
120fn 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}
133128
134fn 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 );
142134
143 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}
149141
150fn 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 );
158147
159 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}
164153
165/// `Currency::minimum_balance` was used originally, but in unique-chain, we have154/// `Currency::minimum_balance` was used originally, but in unique-chain, we have
166/// 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}
170159
171/// 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;
173162
174benchmarks! {163benchmarks! {
175 where_clause { where164 where_clause { where
176 T: pallet_authorship::Config + session::Config + configuration::Config165 T: Config + pallet_authorship::Config + session::Config
177 }166 }
178167
179 // 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 length
188177
189 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);
192181
193 <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;
228
229 <LicenseBond<T>>::put(balance_unit::<T>());
230217
231 register_validators::<T>(c);218 register_validators::<T>(c);
232 get_licenses::<T>(c);219 get_licenses::<T>(c);
233220
234 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);
237224
238 <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;
253
254 <LicenseBond<T>>::put(balance_unit::<T>());
255 <DesiredCollators<T>>::put(c + INITIAL_INVULNERABLES + 1);
256240
257 register_validators::<T>(c);241 register_validators::<T>(c);
258 register_candidates::<T>(c);242 register_candidates::<T>(c);
259243
260 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);
263247
264 let origin = RawOrigin::Signed(caller.clone());248 let origin = RawOrigin::Signed(caller.clone());
265249
279263
280 // 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);
285267
286 register_validators::<T>(c);268 register_validators::<T>(c);
287 register_candidates::<T>(c);269 register_candidates::<T>(c);
295277
296 // 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);
302282
303 register_validators::<T>(c);283 register_validators::<T>(c);
304 register_candidates::<T>(c);284 register_candidates::<T>(c);
312292
313 // 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);
319297
320 register_validators::<T>(c);298 register_validators::<T>(c);
321 register_candidates::<T>(c);299 register_candidates::<T>(c);
334312
335 // 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(),
353330
354 // 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;
358335
359 <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());
362337
363 register_validators::<T>(c);338 register_validators::<T>(c);
modifiedpallets/collator-selection/src/lib.rsdiffbeforeafterboth
90mod benchmarking;90mod benchmarking;
91pub mod weights;91pub mod weights;
9292
93use frame_support::traits::fungible::Inspect;
94
95type 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;
120119
121 /// 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 is
129128
130 /// 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>;
135137
136 /// 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;
164166
165 #[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>;
169
170 type DesiredCollators: Get<u32>;
171
172 type LicenseBond: Get<BalanceOf<Self>>;
173
174 type KickThreshold: Get<Self::BlockNumber>;
167 }175 }
168176
169 #[pallet::pallet]177 #[pallet::pallet]
365 Error::<T>::ValidatorNotRegistered373 Error::<T>::ValidatorNotRegistered
366 );374 );
367375
368 let deposit = <LicenseBond<T>>::get();376 let deposit = T::LicenseBond::get();
369377
370 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>::TooManyCandidates
401 );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 delay
416 <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 candidates
579 .into_iter()587 .into_iter()
580 .filter_map(|c| {588 .filter_map(|c| {
modifiedpallets/collator-selection/src/mock.rsdiffbeforeafterboth
63 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);
6968
218 pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";217 pub const LicenceBondIdentifier: [u8; 16] = *b"licenceidentifie";
219}218}
220
221impl 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 about
228 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}
235219
236ord_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 != 7u64
250 false
251 } else {
252 true
253 }
254 }234 }
255}235}
256236
265 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}
270254
277261
278 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();262 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();
279263
280 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();
268
281 let keys = balances269 let keys = balances
282 .iter()270 .iter()
modifiedpallets/collator-selection/src/tests.rsdiffbeforeafterboth
30// See the License for the specific language governing permissions and30// See the License for the specific language governing permissions and
31// limitations under the License.31// limitations under the License.
3232
33use 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::*;
4741
48fn 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);
62
63 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}
126
127#[test]
128fn set_desired_collators_works() {
129 new_test_ext().execute_with(|| {
130 // given
131 assert_eq!(<DesiredCollators<Test>>::get(), 5);
132
133 // can set
134 assert_ok!(Configuration::set_collator_selection_desired_collators(
135 RawOrigin::Root.into(),
136 Some(7)
137 ));
138 assert_eq!(<DesiredCollators<Test>>::get(), 7);
139
140 // rejects bad origin
141 assert_noop!(
142 Configuration::set_collator_selection_desired_collators(
143 RuntimeOrigin::signed(1),
144 Some(8)
145 ),
146 BadOrigin
147 );
148 });
149}
150
151#[test]
152fn set_license_bond() {
153 new_test_ext().execute_with(|| {
154 // given
155 assert_eq!(<LicenseBond<Test>>::get(), 10);
156
157 // can set
158 assert_ok!(Configuration::set_collator_selection_license_bond(
159 RawOrigin::Root.into(),
160 Some(7)
161 ));
162 assert_eq!(<LicenseBond<Test>>::get(), 7);
163
164 // rejects bad origin.
165 assert_noop!(
166 Configuration::set_collator_selection_license_bond(RuntimeOrigin::signed(1), Some(8)),
167 BadOrigin
168 );
169 });
170}
171117
172#[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() {
192
193 // can still get a license.
194 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));138 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(c)));
195
196 // 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,141
200 );142 // but no more.
201
202 // reset desired candidates to invulnerables + 1
203 <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;
205
206 // but no more.
207 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(5)));144 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(
145 undesired_collator
146 )));
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);
232171
233 // works172 // works
234 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 // given
270 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]);
274210
275 // 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);
278214
279 get_license_and_onboard(3);215 get_license_and_onboard(3);
280 get_license_and_onboard(4);216 get_license_and_onboard(4);
281217
282 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);
284220
285 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]);
514450
515 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);
518454
519 initialize_to_block(30);455 initialize_to_block(30);
modifiedpallets/configuration/CHANGELOG.mddiffbeforeafterboth
3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
6## [0.2.0] - 2023-06-27
67
8### Major change
9
10- 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.
11
7## [0.1.3] - 2022-12-2912## [0.1.3] - 2022-12-29
813
9### Added14### Added
2025
21### Other changes26### Other changes
2227
23- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a28- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
29
modifiedpallets/configuration/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2edition = "2021"2edition = "2021"
3name = "pallet-configuration"3name = "pallet-configuration"
4version = "0.1.3"4version = "0.2.0"
55
6[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",
modifiedpallets/configuration/src/benchmarking.rsdiffbeforeafterboth
19use 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;
2323
24fn 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();
3131
32benchmarks! {32benchmarks! {
33 where_clause { where T: Config }33 where_clause { where
34 T: Config,
35 T::Balance: From<u32>
36 }
3437
35 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 }
6972
70 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 {
modifiedpallets/configuration/src/lib.rsdiffbeforeafterboth
22 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;
5456
55 #[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>;
5961
60 type Currency: fungible::Inspect<Self::AccountId>62 type Balance: Parameter
61 + fungible::Mutate<Self::AccountId>63 + Member
62 + fungible::MutateFreeze<Self::AccountId>64 + AtLeast32BitUnsigned
63 + fungible::InspectHold<Self::AccountId>65 + Codec
64 + fungible::MutateHold<Self::AccountId>66 + Default
65 + fungible::BalancedHold<Self::AccountId>;67 + Copy
68 + MaybeSerializeDeserialize
69 + Debug
70 + MaxEncodedLen
71 + TypeInfo
72 + FixedPointOperand;
6673
67 #[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>;
8592
94 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>,
130137
131 #[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 {
modifiedruntime/common/config/pallets/collator_selection.rsdiffbeforeafterboth
23};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}
6470
65impl pallet_identity::Config for Runtime {71impl pallet_identity::Config for Runtime {
8490
85impl 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}
99109
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
129129
130impl 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;
modifiedtests/src/benchmarks/mintFee/index.tsdiffbeforeafterboth
360 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