Skip to content

Commit e7d6b25

Browse files
committed
Candidate whitelist
1 parent 5735cdc commit e7d6b25

File tree

7 files changed

+64
-2
lines changed

7 files changed

+64
-2
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

substrate/frame/staking/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pallet-staking"
3-
version = "4.0.0-dev"
3+
version = "4.1.0-dev"
44
authors = ["Dock.io", "Parity Technologies <admin@parity.io>"]
55
edition = "2021"
66
license = "Apache-2.0"
@@ -39,6 +39,7 @@ rand_chacha = { version = "0.2", default-features = false, optional = true }
3939
[dev-dependencies]
4040
sp-tracing = { version = "5.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
4141
sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
42+
sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
4243
sp-npos-elections = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
4344
pallet-balances = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
4445
pallet-timestamp = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }

substrate/frame/staking/src/mock.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ impl ExtBuilder {
422422
.build_storage::<Test>()
423423
.unwrap();
424424

425+
sp_state_machine::BasicExternalities::execute_with_storage(&mut storage, || {
426+
Staking::set_whitelist(Origin::root(), (0..100).collect()).unwrap();
427+
});
428+
425429
let _ = pallet_balances::GenesisConfig::<Test> {
426430
balances: vec![
427431
(1, 10 * self.balance_factor),

substrate/frame/staking/src/pallet/impls.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,14 @@ impl<T: Config> Pallet<T> {
442442
Self::clear_era_information(old_era);
443443
}
444444

445+
let whitelist = Self::candidate_whitelist();
446+
let to_remove: Vec<_> = Validators::<T>::iter_keys()
447+
.filter(|validator| !whitelist.contains(&validator))
448+
.collect();
449+
for validator in to_remove {
450+
Self::do_remove_validator(&validator);
451+
}
452+
445453
// Set staking information for the new era.
446454
Self::store_stakers_info(exposures, new_planned_era)
447455
}

substrate/frame/staking/src/pallet/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ const STAKING_ID: LockIdentifier = *b"staking ";
5050

5151
#[frame_support::pallet]
5252
pub mod pallet {
53+
use std::collections::BTreeSet;
54+
5355
use frame_election_provider_support::ElectionDataProvider;
5456

5557
use crate::BenchmarkingConfig;
@@ -516,6 +518,10 @@ pub mod pallet {
516518
#[pallet::storage]
517519
pub(crate) type ChillThreshold<T: Config> = StorageValue<_, Percent, OptionQuery>;
518520

521+
#[pallet::storage]
522+
#[pallet::getter(fn candidate_whitelist)]
523+
pub type CandidateWhitelist<T: Config> = StorageValue<_, BTreeSet<T::AccountId>, ValueQuery>;
524+
519525
#[pallet::genesis_config]
520526
pub struct GenesisConfig<T: Config> {
521527
pub history_depth: u32,
@@ -716,6 +722,8 @@ pub mod pallet {
716722
CommissionTooLow,
717723
/// Can't kill the stash while it has some unclaimed era rewards. It will be possible after claiming.
718724
CantKillStashWithUnclaimedRewards,
725+
/// Can only submit as candidates accounts that were whitelisted.
726+
NotInAWhitelist,
719727
}
720728

721729
#[pallet::hooks]
@@ -1048,6 +1056,11 @@ pub mod pallet {
10481056
Error::<T>::CommissionTooLow
10491057
);
10501058

1059+
ensure!(
1060+
Self::candidate_whitelist().contains(&stash),
1061+
Error::<T>::NotInAWhitelist
1062+
);
1063+
10511064
// Only check limits if they are not already a validator.
10521065
if !Validators::<T>::contains_key(stash) {
10531066
// If this error is reached, we need to adjust the `MinValidatorBond` and start
@@ -1753,6 +1766,18 @@ pub mod pallet {
17531766
})?;
17541767
Ok(())
17551768
}
1769+
1770+
#[pallet::weight(T::DbWeight::get().writes(1))]
1771+
pub fn set_whitelist(
1772+
origin: OriginFor<T>,
1773+
whitelist: BTreeSet<T::AccountId>,
1774+
) -> DispatchResult {
1775+
ensure_root(origin)?;
1776+
1777+
CandidateWhitelist::<T>::put(whitelist);
1778+
1779+
Ok(())
1780+
}
17561781
}
17571782
}
17581783

substrate/frame/staking/src/testing_utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ pub fn create_stash_controller<T: Config>(
8888
amount,
8989
destination,
9090
)?;
91+
let mut whitelist = Staking::<T>::candidate_whitelist();
92+
whitelist.insert(stash.clone());
93+
Staking::<T>::set_whitelist(RawOrigin::Root.into(), whitelist).unwrap();
94+
9195
Ok((stash, controller))
9296
}
9397

substrate/frame/staking/src/tests.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
//! Tests for the module.
1919
20+
use core::iter::empty;
21+
2022
use super::{ConfigOp, Event, MaxUnlockingChunks, *};
2123
use frame_election_provider_support::{ElectionProvider, SortedListProvider, Support};
2224
use frame_support::{
@@ -424,6 +426,23 @@ fn change_controller_works() {
424426
})
425427
}
426428

429+
#[test]
430+
fn whitelist_works() {
431+
ExtBuilder::default().build_and_execute(|| {
432+
super::Pallet::<Test>::set_whitelist(Origin::root(), empty().collect()).unwrap();
433+
// 10 and 11 are bonded as stash controller.
434+
assert_eq!(Staking::bonded(&11), Some(10));
435+
436+
// 10 can control 11 who is initially a validator.
437+
assert_ok!(Staking::chill(Origin::signed(10)));
438+
439+
assert_noop!(
440+
Staking::validate(Origin::signed(10), ValidatorPrefs::default()),
441+
Error::<Test>::NotInAWhitelist
442+
);
443+
})
444+
}
445+
427446
#[test]
428447
fn rewards_should_work() {
429448
ExtBuilder::default()

0 commit comments

Comments
 (0)