From 710e4c16796c226e08b751d08c6609c9ff4e7be9 Mon Sep 17 00:00:00 2001
From: Gav Wood <gavin@parity.io>
Date: Tue, 19 Jan 2021 08:08:48 +0100
Subject: [PATCH 1/7] Allow validators to block and kick their nominator set.

---
 frame/staking/src/benchmarking.rs      | 57 ++++++++++++++++++++++++++
 frame/staking/src/lib.rs               | 51 +++++++++++++++++++++++
 frame/staking/src/offchain_election.rs |  3 ++
 frame/staking/src/testing_utils.rs     |  2 +
 frame/staking/src/tests.rs             |  3 +-
 frame/staking/src/weights.rs           | 25 ++++-------
 6 files changed, 122 insertions(+), 19 deletions(-)

diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs
index 6009761f365da..beddc326b5109 100644
--- a/frame/staking/src/benchmarking.rs
+++ b/frame/staking/src/benchmarking.rs
@@ -63,6 +63,7 @@ pub fn create_validator_with_nominators<T: Config>(
 	let (v_stash, v_controller) = create_stash_controller::<T>(0, 100, destination.clone())?;
 	let validator_prefs = ValidatorPrefs {
 		commission: Perbill::from_percent(50),
+		.. Default::default()
 	};
 	Staking::<T>::validate(RawOrigin::Signed(v_controller).into(), validator_prefs)?;
 	let stash_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(v_stash.clone());
@@ -198,6 +199,61 @@ benchmarks! {
 		assert!(Validators::<T>::contains_key(stash));
 	}
 
+	kick {
+		// scenario: we want to kick `k` nominators from nominating us (we are a validator).
+		// we'll assume that `k` is under 128 for the purposes of determining the slope.
+		// each nominator should have `MAX_NOMINATIONS` validators nominated, and our validator
+		// should be somewhere in there.
+		let k in 1 .. 128;
+
+		// these are the other validators; there are `MAX_NOMINATIONS - 1` of them, so there are a
+		// total of `MAX_NOMINATIONS` validators in the system.
+		let rest_of_validators = create_validators::<T>(MAX_NOMINATIONS as u32 - 1, 100)?;
+
+		// this is the validator that will be kicking.
+		let (stash, controller) = create_stash_controller::<T>(MAX_NOMINATIONS as u32 - 1, 100, Default::default())?;
+		let stash_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(stash.clone());
+
+		// they start validating.
+		Staking::<T>::validate(RawOrigin::Signed(controller.clone()).into(), Default::default())?;
+
+		// we now create the nominators. there will be `k` of them; each will nominate all
+		// validators. we will then kick each of the `k` nominators from the main validator.
+		let mut nominator_stashes = Vec::with_capacity(k as usize);
+		for i in 0 .. k {
+			// create a nominator stash.
+			let (n_stash, n_controller) = create_stash_controller::<T>(MAX_NOMINATIONS as u32 + i, 100, Default::default())?;
+
+			// bake the nominations; we first clone them from the rest of the validators.
+			let mut nominations = rest_of_validators.clone();
+			// then insert "our" validator somewhere in there (we vary it) to avoid accidental
+			// optimisations/pessimisations.
+			nominations.insert(i as usize % (nominations.len() + 1), stash_lookup.clone());
+			// then we nominate.
+			Staking::<T>::nominate(RawOrigin::Signed(n_controller.clone()).into(), nominations)?;
+
+			nominator_stashes.push(n_stash);
+		}
+
+		// all nominators now should be nominating our validator...
+		for n in nominator_stashes.iter() {
+			assert!(Nominators::<T>::get(n).unwrap().targets.contains(&stash));
+		}
+
+		// we need the unlookuped version of the nominator stash for the kick.
+		let kicks = nominator_stashes.iter()
+			.map(|n| T::Lookup::unlookup(n.clone()))
+			.collect::<Vec<_>>();
+
+		whitelist_account!(controller);
+	}: _(RawOrigin::Signed(controller), kicks)
+	verify {
+		// all nominators now should *not* be nominating our validator...
+		for n in nominator_stashes.iter() {
+			assert!(!Nominators::<T>::get(n).unwrap().targets.contains(&stash));
+		}
+	}
+
 	// Worst case scenario, MAX_NOMINATIONS
 	nominate {
 		let n in 1 .. MAX_NOMINATIONS as u32;
@@ -814,6 +870,7 @@ mod tests {
 			assert_ok!(test_benchmark_withdraw_unbonded_update::<Test>());
 			assert_ok!(test_benchmark_withdraw_unbonded_kill::<Test>());
 			assert_ok!(test_benchmark_validate::<Test>());
+			assert_ok!(test_benchmark_kick::<Test>());
 			assert_ok!(test_benchmark_nominate::<Test>());
 			assert_ok!(test_benchmark_chill::<Test>());
 			assert_ok!(test_benchmark_set_payee::<Test>());
diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs
index c3aeaada421b9..240ed652f07d5 100644
--- a/frame/staking/src/lib.rs
+++ b/frame/staking/src/lib.rs
@@ -454,12 +454,17 @@ pub struct ValidatorPrefs {
 	/// nominators.
 	#[codec(compact)]
 	pub commission: Perbill,
+	/// Whether or not this validator is accepting more nominations. If `true`, then no nominator
+	/// who is not already nominating this validator may nominate them. By default, validators
+	/// are accepting nominations.
+	pub closed: bool,
 }
 
 impl Default for ValidatorPrefs {
 	fn default() -> Self {
 		ValidatorPrefs {
 			commission: Default::default(),
+			closed: false,
 		}
 	}
 }
@@ -1152,6 +1157,8 @@ decl_event!(
 		/// An account has called `withdraw_unbonded` and removed unbonding chunks worth `Balance`
 		/// from the unlocking queue. \[stash, amount\]
 		Withdrawn(AccountId, Balance),
+		/// A nominator has been kicked from a validator. \[nominator, stash\]
+		Kicked(AccountId, AccountId),
 	}
 );
 
@@ -1675,9 +1682,17 @@ decl_module! {
 			let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
 			let stash = &ledger.stash;
 			ensure!(!targets.is_empty(), Error::<T>::EmptyTargets);
+
+			let old = Nominators::<T>::get(stash).map_or_else(Vec::new, |x| x.targets);
+
 			let targets = targets.into_iter()
 				.take(MAX_NOMINATIONS)
 				.map(|t| T::Lookup::lookup(t))
+				.filter(|n| if let Ok(ref n) = n {
+					old.contains(n) || !Validators::<T>::get(n).closed
+				} else {
+					true
+				})
 				.collect::<result::Result<Vec<T::AccountId>, _>>()?;
 
 			let nominations = Nominations {
@@ -2168,6 +2183,42 @@ decl_module! {
 
 			Ok(adjustments)
 		}
+
+		/// Remove the given nominations from the calling validator.
+		///
+		/// Effects will be felt at the beginning of the next era.
+		///
+		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
+		/// And, it can be only called when [`EraElectionStatus`] is `Closed`. The controller
+		/// account should represent a validator.
+		///
+		/// - `who`: A list of nominator stash accounts who are nominating this validator which
+		///   should no longer be nominating this validator.
+		///
+		/// Note: Making this call only makes sense if you first set the validator preferences to
+		/// block any further nominations.
+		#[weight = T::WeightInfo::kick(who.len() as u32)]
+		pub fn kick(origin, who: Vec<<T::Lookup as StaticLookup>::Source>) -> DispatchResult {
+			ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
+			let controller = ensure_signed(origin)?;
+			let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
+			let stash = &ledger.stash;
+
+			for nom_stash in who.into_iter()
+				.map(T::Lookup::lookup)
+				.collect::<Result<Vec<T::AccountId>, _>>()?
+				.into_iter()
+			{
+				Nominators::<T>::mutate(&nom_stash, |maybe_nom| if let Some(ref mut nom) = maybe_nom {
+					if let Some(pos) = nom.targets.iter().position(|v| v == stash) {
+						nom.targets.swap_remove(pos);
+						Self::deposit_event(RawEvent::Kicked(nom_stash.clone(), stash.clone()));
+					}
+				});
+			}
+
+			Ok(())
+		}
 	}
 }
 
diff --git a/frame/staking/src/offchain_election.rs b/frame/staking/src/offchain_election.rs
index 5b1fe44d7e2ce..2ab29b7105d9c 100644
--- a/frame/staking/src/offchain_election.rs
+++ b/frame/staking/src/offchain_election.rs
@@ -520,6 +520,9 @@ mod test {
 		fn submit_solution_better(v: u32, n: u32, a: u32, w: u32) -> Weight {
 			(0 * v + 0 * n + 1000 * a + 0 * w) as Weight
 		}
+		fn kick(w: u32) -> Weight {
+			unimplemented!()
+		}
 	}
 
 	#[test]
diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs
index c8d8cb28e2b22..5ec43b43efa9c 100644
--- a/frame/staking/src/testing_utils.rs
+++ b/frame/staking/src/testing_utils.rs
@@ -92,6 +92,7 @@ pub fn create_validators<T: Config>(
 		let (stash, controller) = create_stash_controller::<T>(i, balance_factor, RewardDestination::Staked)?;
 		let validator_prefs = ValidatorPrefs {
 			commission: Perbill::from_percent(50),
+			closed: false,
 		};
 		Staking::<T>::validate(RawOrigin::Signed(controller).into(), validator_prefs)?;
 		let stash_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(stash);
@@ -134,6 +135,7 @@ pub fn create_validators_with_nominators_for_era<T: Config>(
 		let (v_stash, v_controller) = create_stash_controller::<T>(i, balance_factor, RewardDestination::Staked)?;
 		let validator_prefs = ValidatorPrefs {
 			commission: Perbill::from_percent(50),
+			.. Default::default()
 		};
 		Staking::<T>::validate(RawOrigin::Signed(v_controller.clone()).into(), validator_prefs)?;
 		let stash_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(v_stash.clone());
diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs
index 914aff9c45242..b1aad9e337cd4 100644
--- a/frame/staking/src/tests.rs
+++ b/frame/staking/src/tests.rs
@@ -403,7 +403,7 @@ fn no_candidate_emergency_condition() {
 		.execute_with(|| {
 			// initial validators
 			assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]);
-			let prefs = ValidatorPrefs { commission: Perbill::one() };
+			let prefs = ValidatorPrefs { commission: Perbill::one(), closed: false };
 			<Staking as crate::Store>::Validators::insert(11, prefs.clone());
 
 			// set the minimum validator count.
@@ -971,6 +971,7 @@ fn validator_payment_prefs_work() {
 		let commission = Perbill::from_percent(40);
 		<Validators<Test>>::insert(&11, ValidatorPrefs {
 			commission: commission.clone(),
+			closed: false,
 		});
 
 		// Reward controller so staked ratio doesn't change.
diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs
index c0099f637850d..79b1ea21b8d75 100644
--- a/frame/staking/src/weights.rs
+++ b/frame/staking/src/weights.rs
@@ -67,6 +67,7 @@ pub trait WeightInfo {
 	fn reap_stash(_s: u32, ) -> Weight;
 	fn new_era(_v: u32, _n: u32, ) -> Weight;
 	fn submit_solution_better(_v: u32, _n: u32, _a: u32, _w: u32, ) -> Weight;
+	fn kick(_w: u32, ) -> Weight;
 
 }
 
@@ -77,26 +78,22 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		(99_659_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(4 as Weight))
-
 	}
 	fn bond_extra() -> Weight {
 		(79_045_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
-
 	}
 	fn unbond() -> Weight {
 		(71_716_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
-
 	}
 	fn withdraw_unbonded_update(s: u32, ) -> Weight {
 		(72_835_000 as Weight)
 			.saturating_add((63_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
-
 	}
 	fn withdraw_unbonded_kill(s: u32, ) -> Weight {
 		(118_239_000 as Weight)
@@ -109,58 +106,48 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		(25_691_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
-
 	}
 	fn nominate(n: u32, ) -> Weight {
 		(35_374_000 as Weight)
 			.saturating_add((203_000 as Weight).saturating_mul(n as Weight))
 			.saturating_add(T::DbWeight::get().reads(3 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
-
 	}
 	fn chill() -> Weight {
 		(25_227_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
-
 	}
 	fn set_payee() -> Weight {
 		(17_601_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn set_controller() -> Weight {
 		(37_514_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(3 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
-
 	}
 	fn set_validator_count() -> Weight {
 		(3_338_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_no_eras() -> Weight {
 		(3_869_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_new_era() -> Weight {
 		(3_795_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_new_era_always() -> Weight {
 		(3_829_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn set_invulnerables(v: u32, ) -> Weight {
 		(4_087_000 as Weight)
 			.saturating_add((9_000 as Weight).saturating_mul(v as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_unstake(s: u32, ) -> Weight {
 		(81_063_000 as Weight)
@@ -174,7 +161,6 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 			.saturating_add((34_806_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-
 	}
 	fn payout_stakers_dead_controller(n: u32, ) -> Weight {
 		(153_024_000 as Weight)
@@ -197,7 +183,6 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 			.saturating_add((92_000 as Weight).saturating_mul(l as Weight))
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
-
 	}
 	fn set_history_depth(e: u32, ) -> Weight {
 		(0 as Weight)
@@ -233,9 +218,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 			.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(a as Weight)))
 			.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(w as Weight)))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
-
 	}
-
+	fn kick(w: u32, ) -> Weight {
+		(w as Weight)
+	}
 }
 
 // For backwards compatibility and tests
@@ -402,5 +388,8 @@ impl WeightInfo for () {
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
 
 	}
+	fn kick(w: u32, ) -> Weight {
+		(w as Weight)
+	}
 
 }

From 8ddf6c836d4c1a30b48e878dff6bce46c6e28915 Mon Sep 17 00:00:00 2001
From: Gav Wood <gavin@parity.io>
Date: Tue, 19 Jan 2021 08:32:03 +0100
Subject: [PATCH 2/7] migration

---
 frame/staking/src/lib.rs           | 44 ++++++++++++++++++++++++++----
 frame/staking/src/testing_utils.rs |  2 +-
 frame/staking/src/tests.rs         |  7 +++--
 3 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs
index 240ed652f07d5..598f5d5aed555 100644
--- a/frame/staking/src/lib.rs
+++ b/frame/staking/src/lib.rs
@@ -457,14 +457,14 @@ pub struct ValidatorPrefs {
 	/// Whether or not this validator is accepting more nominations. If `true`, then no nominator
 	/// who is not already nominating this validator may nominate them. By default, validators
 	/// are accepting nominations.
-	pub closed: bool,
+	pub blocked: bool,
 }
 
 impl Default for ValidatorPrefs {
 	fn default() -> Self {
 		ValidatorPrefs {
 			commission: Default::default(),
-			closed: false,
+			blocked: false,
 		}
 	}
 }
@@ -901,11 +901,12 @@ enum Releases {
 	V2_0_0,
 	V3_0_0,
 	V4_0_0,
+	V5_0_0,
 }
 
 impl Default for Releases {
 	fn default() -> Self {
-		Releases::V4_0_0
+		Releases::V5_0_0
 	}
 }
 
@@ -1092,8 +1093,8 @@ decl_storage! {
 		/// True if network has been upgraded to this version.
 		/// Storage version of the pallet.
 		///
-		/// This is set to v3.0.0 for new networks.
-		StorageVersion build(|_: &GenesisConfig<T>| Releases::V4_0_0): Releases;
+		/// This is set to v5.0.0 for new networks.
+		StorageVersion build(|_: &GenesisConfig<T>| Releases::V5_0_0): Releases;
 	}
 	add_extra_genesis {
 		config(stakers):
@@ -1129,6 +1130,37 @@ decl_storage! {
 	}
 }
 
+mod migrations {
+	use super::*;
+
+	#[derive(Decode)]
+	struct OldValidatorPrefs {
+		#[codec(compact)]
+		pub commission: Perbill
+	}
+	impl OldValidatorPrefs {
+		fn upgraded(self) -> ValidatorPrefs {
+			ValidatorPrefs {
+				commission: self.commission,
+				.. Default::default()
+			}
+		}
+	}
+	fn migrate_to_blockable<T: Config>() {
+		Validators::<T>::translate::<OldValidatorPrefs, _>(|_, p| Some(p.upgraded()));
+		ErasValidatorPrefs::<T>::translate::<OldValidatorPrefs, _>(|_, _, p| Some(p.upgraded()));
+	}
+
+	pub fn migrate<T: Config>() {
+		if StorageVersion::get() == Releases::V4_0_0 {
+			StorageVersion::put(Releases::V5_0_0);
+			migrate_to_blockable::<T>();
+		}
+	}
+}
+
+pub use migrations::migrate;
+
 decl_event!(
 	pub enum Event<T> where Balance = BalanceOf<T>, <T as frame_system::Config>::AccountId {
 		/// The era payout has been set; the first balance is the validator-payout; the second is
@@ -1689,7 +1721,7 @@ decl_module! {
 				.take(MAX_NOMINATIONS)
 				.map(|t| T::Lookup::lookup(t))
 				.filter(|n| if let Ok(ref n) = n {
-					old.contains(n) || !Validators::<T>::get(n).closed
+					old.contains(n) || !Validators::<T>::get(n).blocked
 				} else {
 					true
 				})
diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs
index 5ec43b43efa9c..a30c0136550b4 100644
--- a/frame/staking/src/testing_utils.rs
+++ b/frame/staking/src/testing_utils.rs
@@ -92,7 +92,7 @@ pub fn create_validators<T: Config>(
 		let (stash, controller) = create_stash_controller::<T>(i, balance_factor, RewardDestination::Staked)?;
 		let validator_prefs = ValidatorPrefs {
 			commission: Perbill::from_percent(50),
-			closed: false,
+			.. Default::default()
 		};
 		Staking::<T>::validate(RawOrigin::Signed(controller).into(), validator_prefs)?;
 		let stash_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(stash);
diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs
index b1aad9e337cd4..7e1e1f62077f0 100644
--- a/frame/staking/src/tests.rs
+++ b/frame/staking/src/tests.rs
@@ -364,6 +364,9 @@ fn staking_should_work() {
 		});
 }
 
+#[test]
+fn 
+
 #[test]
 fn less_than_needed_candidates_works() {
 	ExtBuilder::default()
@@ -403,7 +406,7 @@ fn no_candidate_emergency_condition() {
 		.execute_with(|| {
 			// initial validators
 			assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]);
-			let prefs = ValidatorPrefs { commission: Perbill::one(), closed: false };
+			let prefs = ValidatorPrefs { commission: Perbill::one(), .. Default::default() };
 			<Staking as crate::Store>::Validators::insert(11, prefs.clone());
 
 			// set the minimum validator count.
@@ -971,7 +974,7 @@ fn validator_payment_prefs_work() {
 		let commission = Perbill::from_percent(40);
 		<Validators<Test>>::insert(&11, ValidatorPrefs {
 			commission: commission.clone(),
-			closed: false,
+			.. Default::default()
 		});
 
 		// Reward controller so staked ratio doesn't change.

From 6cfe82f0d3cdd6a0d0b2bde4b5f2f0f0811da114 Mon Sep 17 00:00:00 2001
From: Gav Wood <gavin@parity.io>
Date: Tue, 19 Jan 2021 08:57:58 +0100
Subject: [PATCH 3/7] Test

---
 frame/staking/src/lib.rs   | 16 ++++++++++------
 frame/staking/src/tests.rs | 23 ++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs
index 598f5d5aed555..dd35e7a29f154 100644
--- a/frame/staking/src/lib.rs
+++ b/frame/staking/src/lib.rs
@@ -1264,6 +1264,10 @@ decl_error! {
 		IncorrectSlashingSpans,
 		/// Internal state has become somehow corrupted and the operation cannot continue.
 		BadState,
+		/// Too many nomination targets supplied.
+		TooManyTargets,
+		/// A nomination target was supplied that was blocked or otherwise not a validator.
+		BadTarget,
 	}
 }
 
@@ -1714,17 +1718,17 @@ decl_module! {
 			let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
 			let stash = &ledger.stash;
 			ensure!(!targets.is_empty(), Error::<T>::EmptyTargets);
+			ensure!(targets.len() <= MAX_NOMINATIONS, Error::<T>::TooManyTargets);
 
 			let old = Nominators::<T>::get(stash).map_or_else(Vec::new, |x| x.targets);
 
 			let targets = targets.into_iter()
-				.take(MAX_NOMINATIONS)
-				.map(|t| T::Lookup::lookup(t))
-				.filter(|n| if let Ok(ref n) = n {
-					old.contains(n) || !Validators::<T>::get(n).blocked
+				.map(|t| T::Lookup::lookup(t).map_err(DispatchError::from))
+				.map(|n| n.and_then(|n| if old.contains(&n) || !Validators::<T>::get(&n).blocked {
+					Ok(n)
 				} else {
-					true
-				})
+					Err(Error::<T>::BadTarget.into())
+				}))
 				.collect::<result::Result<Vec<T::AccountId>, _>>()?;
 
 			let nominations = Nominations {
diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs
index 7e1e1f62077f0..a10c95d0f24d2 100644
--- a/frame/staking/src/tests.rs
+++ b/frame/staking/src/tests.rs
@@ -365,7 +365,28 @@ fn staking_should_work() {
 }
 
 #[test]
-fn 
+fn blocking_and_kicking_works() {
+	ExtBuilder::default()
+		.minimum_validator_count(1)
+		.validator_count(4)
+		.nominate(true)
+		.num_validators(3)
+		.build()
+		.execute_with(|| {
+			// block validator 10/11
+			assert_ok!(Staking::validate(Origin::signed(10), ValidatorPrefs { blocked: true, .. Default::default() }));
+			// attempt to nominate from 100/101...
+			assert_ok!(Staking::nominate(Origin::signed(100), vec![11]));
+			// should have worked since we're already nominated them
+			assert_eq!(Nominators::<Test>::get(&101).unwrap().targets, vec![11]);
+			// kick the nominator
+			assert_ok!(Staking::kick(Origin::signed(10), vec![101]));
+			// should have been kicked now
+			assert!(Nominators::<Test>::get(&101).unwrap().targets.is_empty());
+			// attempt to nominate from 100/101...
+			assert_noop!(Staking::nominate(Origin::signed(100), vec![11]), Error::<Test>::BadTarget);
+		});
+}
 
 #[test]
 fn less_than_needed_candidates_works() {

From 72799252607d117d9d6440eedb10ee09dc701aa5 Mon Sep 17 00:00:00 2001
From: Gav Wood <gavin@parity.io>
Date: Tue, 19 Jan 2021 09:05:55 +0100
Subject: [PATCH 4/7] Better migration

---
 frame/staking/src/lib.rs | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs
index dd35e7a29f154..92fdce0c46ac4 100644
--- a/frame/staking/src/lib.rs
+++ b/frame/staking/src/lib.rs
@@ -1130,7 +1130,7 @@ decl_storage! {
 	}
 }
 
-mod migrations {
+pub mod migrations {
 	use super::*;
 
 	#[derive(Decode)]
@@ -1146,21 +1146,13 @@ mod migrations {
 			}
 		}
 	}
-	fn migrate_to_blockable<T: Config>() {
+	pub fn migrate_to_blockable<T: Config>() -> frame_support::weights::Weight {
 		Validators::<T>::translate::<OldValidatorPrefs, _>(|_, p| Some(p.upgraded()));
 		ErasValidatorPrefs::<T>::translate::<OldValidatorPrefs, _>(|_, _, p| Some(p.upgraded()));
-	}
-
-	pub fn migrate<T: Config>() {
-		if StorageVersion::get() == Releases::V4_0_0 {
-			StorageVersion::put(Releases::V5_0_0);
-			migrate_to_blockable::<T>();
-		}
+		T::BlockWeights::get().max_block
 	}
 }
 
-pub use migrations::migrate;
-
 decl_event!(
 	pub enum Event<T> where Balance = BalanceOf<T>, <T as frame_system::Config>::AccountId {
 		/// The era payout has been set; the first balance is the validator-payout; the second is
@@ -1313,6 +1305,15 @@ decl_module! {
 
 		fn deposit_event() = default;
 
+		fn on_runtime_upgrade() -> frame_support::weights::Weight {
+			if StorageVersion::get() == Releases::V4_0_0 {
+				StorageVersion::put(Releases::V5_0_0);
+				migrations::migrate_to_blockable::<T>()
+			} else {
+				0
+			}
+		}
+
 		/// sets `ElectionStatus` to `Open(now)` where `now` is the block number at which the
 		/// election window has opened, if we are at the last session and less blocks than
 		/// `T::ElectionLookahead` is remaining until the next new session schedule. The offchain

From a51c210df6404011277a1a2cb0032c035fa28d41 Mon Sep 17 00:00:00 2001
From: Gav Wood <gavin@parity.io>
Date: Tue, 19 Jan 2021 10:28:02 +0100
Subject: [PATCH 5/7] Fixes

---
 frame/offences/benchmarking/src/lib.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs
index f2807ba6c7a88..1151bfea4807b 100644
--- a/frame/offences/benchmarking/src/lib.rs
+++ b/frame/offences/benchmarking/src/lib.rs
@@ -109,6 +109,7 @@ fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'
 
 	let validator_prefs = ValidatorPrefs {
 		commission: Perbill::from_percent(50),
+		.. Default::default()
 	};
 	Staking::<T>::validate(RawOrigin::Signed(controller.clone()).into(), validator_prefs)?;
 

From 60ce6f61e38bf3f75d921cb8ecae81f65a67f468 Mon Sep 17 00:00:00 2001
From: Parity Benchmarking Bot <admin@parity.io>
Date: Tue, 19 Jan 2021 10:52:54 +0000
Subject: [PATCH 6/7] cargo run --release --features=runtime-benchmarks
 --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50
 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm
 --wasm-execution=compiled --heap-pages=4096
 --output=./frame/staking/src/weights.rs
 --template=./.maintain/frame-weight-template.hbs

---
 frame/staking/src/weights.rs | 270 +++++++++++++++++++----------------
 1 file changed, 149 insertions(+), 121 deletions(-)

diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs
index 79b1ea21b8d75..b70563ccf41b3 100644
--- a/frame/staking/src/weights.rs
+++ b/frame/staking/src/weights.rs
@@ -1,6 +1,6 @@
 // This file is part of Substrate.
 
-// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// Copyright (C) 2021 Parity Technologies (UK) Ltd.
 // SPDX-License-Identifier: Apache-2.0
 
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Weights for pallet_staking
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0
-//! DATE: 2020-10-27, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
+//! Autogenerated weights for pallet_staking
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1
+//! DATE: 2021-01-19, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
 //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
 
 // Executed Command:
@@ -46,10 +47,11 @@ pub trait WeightInfo {
 	fn bond() -> Weight;
 	fn bond_extra() -> Weight;
 	fn unbond() -> Weight;
-	fn withdraw_unbonded_update(_s: u32, ) -> Weight;
-	fn withdraw_unbonded_kill(_s: u32, ) -> Weight;
+	fn withdraw_unbonded_update(s: u32, ) -> Weight;
+	fn withdraw_unbonded_kill(s: u32, ) -> Weight;
 	fn validate() -> Weight;
-	fn nominate(_n: u32, ) -> Weight;
+	fn kick(k: u32, ) -> Weight;
+	fn nominate(n: u32, ) -> Weight;
 	fn chill() -> Weight;
 	fn set_payee() -> Weight;
 	fn set_controller() -> Weight;
@@ -57,152 +59,172 @@ pub trait WeightInfo {
 	fn force_no_eras() -> Weight;
 	fn force_new_era() -> Weight;
 	fn force_new_era_always() -> Weight;
-	fn set_invulnerables(_v: u32, ) -> Weight;
-	fn force_unstake(_s: u32, ) -> Weight;
-	fn cancel_deferred_slash(_s: u32, ) -> Weight;
-	fn payout_stakers_dead_controller(_n: u32, ) -> Weight;
-	fn payout_stakers_alive_staked(_n: u32, ) -> Weight;
-	fn rebond(_l: u32, ) -> Weight;
-	fn set_history_depth(_e: u32, ) -> Weight;
-	fn reap_stash(_s: u32, ) -> Weight;
-	fn new_era(_v: u32, _n: u32, ) -> Weight;
-	fn submit_solution_better(_v: u32, _n: u32, _a: u32, _w: u32, ) -> Weight;
-	fn kick(_w: u32, ) -> Weight;
-
+	fn set_invulnerables(v: u32, ) -> Weight;
+	fn force_unstake(s: u32, ) -> Weight;
+	fn cancel_deferred_slash(s: u32, ) -> Weight;
+	fn payout_stakers_dead_controller(n: u32, ) -> Weight;
+	fn payout_stakers_alive_staked(n: u32, ) -> Weight;
+	fn rebond(l: u32, ) -> Weight;
+	fn set_history_depth(e: u32, ) -> Weight;
+	fn reap_stash(s: u32, ) -> Weight;
+	fn new_era(v: u32, n: u32, ) -> Weight;
+	fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight;
 }
 
 /// Weights for pallet_staking using the Substrate node and recommended hardware.
 pub struct SubstrateWeight<T>(PhantomData<T>);
 impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	fn bond() -> Weight {
-		(99_659_000 as Weight)
+		(76_281_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(4 as Weight))
 	}
 	fn bond_extra() -> Weight {
-		(79_045_000 as Weight)
+		(62_062_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
 	}
 	fn unbond() -> Weight {
-		(71_716_000 as Weight)
+		(57_195_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
 	}
 	fn withdraw_unbonded_update(s: u32, ) -> Weight {
-		(72_835_000 as Weight)
-			.saturating_add((63_000 as Weight).saturating_mul(s as Weight))
+		(58_043_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((52_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
 	}
 	fn withdraw_unbonded_kill(s: u32, ) -> Weight {
-		(118_239_000 as Weight)
-			.saturating_add((3_910_000 as Weight).saturating_mul(s as Weight))
+		(89_920_000 as Weight)
+			// Standard Error: 3_000
+			.saturating_add((2_526_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(7 as Weight))
 			.saturating_add(T::DbWeight::get().writes(8 as Weight))
 			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
 	}
 	fn validate() -> Weight {
-		(25_691_000 as Weight)
+		(20_228_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
 	}
+	fn kick(k: u32, ) -> Weight {
+		(31_066_000 as Weight)
+			// Standard Error: 11_000
+			.saturating_add((17_754_000 as Weight).saturating_mul(k as Weight))
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight)))
+			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight)))
+	}
 	fn nominate(n: u32, ) -> Weight {
-		(35_374_000 as Weight)
-			.saturating_add((203_000 as Weight).saturating_mul(n as Weight))
-			.saturating_add(T::DbWeight::get().reads(3 as Weight))
+		(33_494_000 as Weight)
+			// Standard Error: 23_000
+			.saturating_add((5_253_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(4 as Weight))
+			.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
 	}
 	fn chill() -> Weight {
-		(25_227_000 as Weight)
+		(19_396_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
 	}
 	fn set_payee() -> Weight {
-		(17_601_000 as Weight)
+		(13_449_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn set_controller() -> Weight {
-		(37_514_000 as Weight)
+		(29_184_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(3 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
 	}
 	fn set_validator_count() -> Weight {
-		(3_338_000 as Weight)
+		(2_266_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn force_no_eras() -> Weight {
-		(3_869_000 as Weight)
+		(2_462_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn force_new_era() -> Weight {
-		(3_795_000 as Weight)
+		(2_483_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn force_new_era_always() -> Weight {
-		(3_829_000 as Weight)
+		(2_495_000 as Weight)
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn set_invulnerables(v: u32, ) -> Weight {
-		(4_087_000 as Weight)
+		(2_712_000 as Weight)
+			// Standard Error: 0
 			.saturating_add((9_000 as Weight).saturating_mul(v as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn force_unstake(s: u32, ) -> Weight {
-		(81_063_000 as Weight)
-			.saturating_add((3_872_000 as Weight).saturating_mul(s as Weight))
+		(60_508_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((2_525_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(8 as Weight))
 			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
 	}
 	fn cancel_deferred_slash(s: u32, ) -> Weight {
-		(5_840_640_000 as Weight)
-			.saturating_add((34_806_000 as Weight).saturating_mul(s as Weight))
+		(5_886_772_000 as Weight)
+			// Standard Error: 393_000
+			.saturating_add((34_849_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 	fn payout_stakers_dead_controller(n: u32, ) -> Weight {
-		(153_024_000 as Weight)
-			.saturating_add((59_909_000 as Weight).saturating_mul(n as Weight))
+		(127_627_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((49_354_000 as Weight).saturating_mul(n as Weight))
 			.saturating_add(T::DbWeight::get().reads(11 as Weight))
 			.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(n as Weight)))
 	}
 	fn payout_stakers_alive_staked(n: u32, ) -> Weight {
-		(196_058_000 as Weight)
-			.saturating_add((78_955_000 as Weight).saturating_mul(n as Weight))
+		(156_838_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((62_653_000 as Weight).saturating_mul(n as Weight))
 			.saturating_add(T::DbWeight::get().reads(12 as Weight))
 			.saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
 			.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(n as Weight)))
 	}
 	fn rebond(l: u32, ) -> Weight {
-		(49_966_000 as Weight)
-			.saturating_add((92_000 as Weight).saturating_mul(l as Weight))
+		(40_110_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((78_000 as Weight).saturating_mul(l as Weight))
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(3 as Weight))
 	}
 	fn set_history_depth(e: u32, ) -> Weight {
 		(0 as Weight)
-			.saturating_add((38_529_000 as Weight).saturating_mul(e as Weight))
+			// Standard Error: 70_000
+			.saturating_add((32_883_000 as Weight).saturating_mul(e as Weight))
 			.saturating_add(T::DbWeight::get().reads(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight)))
 	}
 	fn reap_stash(s: u32, ) -> Weight {
-		(101_457_000 as Weight)
-			.saturating_add((3_914_000 as Weight).saturating_mul(s as Weight))
+		(64_605_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((2_506_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(8 as Weight))
 			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
 	}
 	fn new_era(v: u32, n: u32, ) -> Weight {
 		(0 as Weight)
-			.saturating_add((948_467_000 as Weight).saturating_mul(v as Weight))
-			.saturating_add((117_579_000 as Weight).saturating_mul(n as Weight))
-			.saturating_add(T::DbWeight::get().reads(10 as Weight))
+			// Standard Error: 926_000
+			.saturating_add((548_212_000 as Weight).saturating_mul(v as Weight))
+			// Standard Error: 46_000
+			.saturating_add((78_343_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(7 as Weight))
 			.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(v as Weight)))
 			.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(T::DbWeight::get().writes(8 as Weight))
@@ -210,167 +232,174 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	}
 	fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight {
 		(0 as Weight)
-			.saturating_add((1_728_000 as Weight).saturating_mul(v as Weight))
-			.saturating_add((907_000 as Weight).saturating_mul(n as Weight))
-			.saturating_add((99_762_000 as Weight).saturating_mul(a as Weight))
-			.saturating_add((9_017_000 as Weight).saturating_mul(w as Weight))
+			// Standard Error: 48_000
+			.saturating_add((937_000 as Weight).saturating_mul(v as Weight))
+			// Standard Error: 19_000
+			.saturating_add((657_000 as Weight).saturating_mul(n as Weight))
+			// Standard Error: 48_000
+			.saturating_add((70_669_000 as Weight).saturating_mul(a as Weight))
+			// Standard Error: 101_000
+			.saturating_add((7_658_000 as Weight).saturating_mul(w as Weight))
 			.saturating_add(T::DbWeight::get().reads(6 as Weight))
 			.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(a as Weight)))
 			.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(w as Weight)))
 			.saturating_add(T::DbWeight::get().writes(2 as Weight))
 	}
-	fn kick(w: u32, ) -> Weight {
-		(w as Weight)
-	}
 }
 
 // For backwards compatibility and tests
 impl WeightInfo for () {
 	fn bond() -> Weight {
-		(99_659_000 as Weight)
+		(76_281_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
-
 	}
 	fn bond_extra() -> Weight {
-		(79_045_000 as Weight)
+		(62_062_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
-
 	}
 	fn unbond() -> Weight {
-		(71_716_000 as Weight)
+		(57_195_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(3 as Weight))
-
 	}
 	fn withdraw_unbonded_update(s: u32, ) -> Weight {
-		(72_835_000 as Weight)
-			.saturating_add((63_000 as Weight).saturating_mul(s as Weight))
+		(58_043_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((52_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(3 as Weight))
-
 	}
 	fn withdraw_unbonded_kill(s: u32, ) -> Weight {
-		(118_239_000 as Weight)
-			.saturating_add((3_910_000 as Weight).saturating_mul(s as Weight))
+		(89_920_000 as Weight)
+			// Standard Error: 3_000
+			.saturating_add((2_526_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(RocksDbWeight::get().reads(7 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
 			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
 	}
 	fn validate() -> Weight {
-		(25_691_000 as Weight)
+		(20_228_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
-
+	}
+	fn kick(k: u32, ) -> Weight {
+		(31_066_000 as Weight)
+			// Standard Error: 11_000
+			.saturating_add((17_754_000 as Weight).saturating_mul(k as Weight))
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight)))
+			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight)))
 	}
 	fn nominate(n: u32, ) -> Weight {
-		(35_374_000 as Weight)
-			.saturating_add((203_000 as Weight).saturating_mul(n as Weight))
-			.saturating_add(RocksDbWeight::get().reads(3 as Weight))
+		(33_494_000 as Weight)
+			// Standard Error: 23_000
+			.saturating_add((5_253_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
-
 	}
 	fn chill() -> Weight {
-		(25_227_000 as Weight)
+		(19_396_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
-
 	}
 	fn set_payee() -> Weight {
-		(17_601_000 as Weight)
+		(13_449_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn set_controller() -> Weight {
-		(37_514_000 as Weight)
+		(29_184_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(3 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(3 as Weight))
-
 	}
 	fn set_validator_count() -> Weight {
-		(3_338_000 as Weight)
+		(2_266_000 as Weight)
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_no_eras() -> Weight {
-		(3_869_000 as Weight)
+		(2_462_000 as Weight)
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_new_era() -> Weight {
-		(3_795_000 as Weight)
+		(2_483_000 as Weight)
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_new_era_always() -> Weight {
-		(3_829_000 as Weight)
+		(2_495_000 as Weight)
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn set_invulnerables(v: u32, ) -> Weight {
-		(4_087_000 as Weight)
+		(2_712_000 as Weight)
+			// Standard Error: 0
 			.saturating_add((9_000 as Weight).saturating_mul(v as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn force_unstake(s: u32, ) -> Weight {
-		(81_063_000 as Weight)
-			.saturating_add((3_872_000 as Weight).saturating_mul(s as Weight))
+		(60_508_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((2_525_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
 			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
 	}
 	fn cancel_deferred_slash(s: u32, ) -> Weight {
-		(5_840_640_000 as Weight)
-			.saturating_add((34_806_000 as Weight).saturating_mul(s as Weight))
+		(5_886_772_000 as Weight)
+			// Standard Error: 393_000
+			.saturating_add((34_849_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-
 	}
 	fn payout_stakers_dead_controller(n: u32, ) -> Weight {
-		(153_024_000 as Weight)
-			.saturating_add((59_909_000 as Weight).saturating_mul(n as Weight))
+		(127_627_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((49_354_000 as Weight).saturating_mul(n as Weight))
 			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
 			.saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
 			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(n as Weight)))
 	}
 	fn payout_stakers_alive_staked(n: u32, ) -> Weight {
-		(196_058_000 as Weight)
-			.saturating_add((78_955_000 as Weight).saturating_mul(n as Weight))
+		(156_838_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((62_653_000 as Weight).saturating_mul(n as Weight))
 			.saturating_add(RocksDbWeight::get().reads(12 as Weight))
 			.saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(RocksDbWeight::get().writes(3 as Weight))
 			.saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(n as Weight)))
 	}
 	fn rebond(l: u32, ) -> Weight {
-		(49_966_000 as Weight)
-			.saturating_add((92_000 as Weight).saturating_mul(l as Weight))
+		(40_110_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((78_000 as Weight).saturating_mul(l as Weight))
 			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(3 as Weight))
-
 	}
 	fn set_history_depth(e: u32, ) -> Weight {
 		(0 as Weight)
-			.saturating_add((38_529_000 as Weight).saturating_mul(e as Weight))
+			// Standard Error: 70_000
+			.saturating_add((32_883_000 as Weight).saturating_mul(e as Weight))
 			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
 			.saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight)))
 	}
 	fn reap_stash(s: u32, ) -> Weight {
-		(101_457_000 as Weight)
-			.saturating_add((3_914_000 as Weight).saturating_mul(s as Weight))
+		(64_605_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((2_506_000 as Weight).saturating_mul(s as Weight))
 			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
 			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
 	}
 	fn new_era(v: u32, n: u32, ) -> Weight {
 		(0 as Weight)
-			.saturating_add((948_467_000 as Weight).saturating_mul(v as Weight))
-			.saturating_add((117_579_000 as Weight).saturating_mul(n as Weight))
-			.saturating_add(RocksDbWeight::get().reads(10 as Weight))
+			// Standard Error: 926_000
+			.saturating_add((548_212_000 as Weight).saturating_mul(v as Weight))
+			// Standard Error: 46_000
+			.saturating_add((78_343_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(7 as Weight))
 			.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(v as Weight)))
 			.saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
 			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
@@ -378,18 +407,17 @@ impl WeightInfo for () {
 	}
 	fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight {
 		(0 as Weight)
-			.saturating_add((1_728_000 as Weight).saturating_mul(v as Weight))
-			.saturating_add((907_000 as Weight).saturating_mul(n as Weight))
-			.saturating_add((99_762_000 as Weight).saturating_mul(a as Weight))
-			.saturating_add((9_017_000 as Weight).saturating_mul(w as Weight))
+			// Standard Error: 48_000
+			.saturating_add((937_000 as Weight).saturating_mul(v as Weight))
+			// Standard Error: 19_000
+			.saturating_add((657_000 as Weight).saturating_mul(n as Weight))
+			// Standard Error: 48_000
+			.saturating_add((70_669_000 as Weight).saturating_mul(a as Weight))
+			// Standard Error: 101_000
+			.saturating_add((7_658_000 as Weight).saturating_mul(w as Weight))
 			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
 			.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(a as Weight)))
 			.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(w as Weight)))
 			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
-
-	}
-	fn kick(w: u32, ) -> Weight {
-		(w as Weight)
 	}
-
 }

From 3c5abf38cb7e2fcb09845deba45bfbe74928f9eb Mon Sep 17 00:00:00 2001
From: Gavin Wood <gavin@parity.io>
Date: Tue, 19 Jan 2021 17:04:42 +0100
Subject: [PATCH 7/7] Update frame/staking/src/lib.rs

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
---
 frame/staking/src/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs
index 92fdce0c46ac4..6c0bbc33a4e3d 100644
--- a/frame/staking/src/lib.rs
+++ b/frame/staking/src/lib.rs
@@ -2236,8 +2236,8 @@ decl_module! {
 		/// block any further nominations.
 		#[weight = T::WeightInfo::kick(who.len() as u32)]
 		pub fn kick(origin, who: Vec<<T::Lookup as StaticLookup>::Source>) -> DispatchResult {
-			ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
 			let controller = ensure_signed(origin)?;
+			ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
 			let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
 			let stash = &ledger.stash;