Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

session, staking: introduce static limit on the number of validators #11967

Closed
wants to merge 17 commits into from
Closed
7 changes: 6 additions & 1 deletion bin/node/cli/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,12 @@ pub fn testnet_genesis(
staking: StakingConfig {
validator_count: initial_authorities.len() as u32,
minimum_validator_count: initial_authorities.len() as u32,
invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
invulnerables: initial_authorities
.iter()
.map(|x| x.0.clone())
.collect::<Vec<_>>()
.try_into()
.unwrap(),
slash_reward_fraction: Perbill::from_percent(10),
stakers,
..Default::default()
Expand Down
6 changes: 6 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@ impl_opaque_keys! {
}
}

parameter_types! {
pub const MaxValidators: u32 = 3072;
}

impl pallet_session::Config for Runtime {
type Event = Event;
type ValidatorId = <Self as frame_system::Config>::AccountId;
Expand All @@ -505,6 +509,7 @@ impl pallet_session::Config for Runtime {
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
type MaxValidators = MaxValidators;
}

impl pallet_session::historical::Config for Runtime {
Expand Down Expand Up @@ -569,6 +574,7 @@ impl pallet_staking::Config for Runtime {
type OnStakerSlash = NominationPools;
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
type BenchmarkingConfig = StakingBenchmarkingConfig;
type MaxValidators = MaxValidators;
}

parameter_types! {
Expand Down
2 changes: 1 addition & 1 deletion bin/node/testing/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub fn config_endowed(code: Option<&[u8]>, extra_endowed: Vec<AccountId>) -> Gen
validator_count: 3,
minimum_validator_count: 0,
slash_reward_fraction: Perbill::from_percent(10),
invulnerables: vec![alice(), bob(), charlie()],
invulnerables: vec![alice(), bob(), charlie()].try_into().unwrap(),
..Default::default()
},
babe: BabeConfig { authorities: vec![], epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG) },
Expand Down
1 change: 1 addition & 0 deletions frame/authority-discovery/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ mod tests {
type ValidatorIdOf = ConvertInto;
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

impl pallet_session::historical::Config for Test {
Expand Down
8 changes: 7 additions & 1 deletion frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ impl_opaque_keys! {
}
}

parameter_types! {
pub const MaxValidators: u32 = 3072;
}

impl pallet_session::Config for Test {
type Event = Event;
type ValidatorId = <Self as frame_system::Config>::AccountId;
Expand All @@ -120,6 +124,7 @@ impl pallet_session::Config for Test {
type SessionHandler = <MockSessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = MockSessionKeys;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

impl pallet_session::historical::Config for Test {
Expand Down Expand Up @@ -206,6 +211,7 @@ impl pallet_staking::Config for Test {
type OnStakerSlash = ();
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

impl pallet_offences::Config for Test {
Expand Down Expand Up @@ -403,7 +409,7 @@ pub fn new_test_ext_raw_authorities(authorities: Vec<AuthorityId>) -> sp_io::Tes
validator_count: 8,
force_era: pallet_staking::Forcing::ForceNew,
minimum_validator_count: 0,
invulnerables: vec![],
invulnerables: vec![].try_into().unwrap(),
..Default::default()
};

Expand Down
1 change: 1 addition & 0 deletions frame/beefy-mmr/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl pallet_session::Config for Test {
type SessionHandler = <MockSessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = MockSessionKeys;
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

pub type MmrLeaf = beefy_primitives::mmr::MmrLeaf<
Expand Down
1 change: 1 addition & 0 deletions frame/beefy/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ impl pallet_session::Config for Test {
type SessionHandler = <MockSessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = MockSessionKeys;
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

pub struct MockSessionManager;
Expand Down
5 changes: 4 additions & 1 deletion frame/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ where
parameter_types! {
pub const Period: u64 = 1;
pub const Offset: u64 = 0;
pub const MaxValidators: u32 = 3072;
}

/// Custom `SessionHandler` since we use `TestSessionKeys` as `Keys`.
Expand All @@ -125,6 +126,7 @@ impl pallet_session::Config for Test {
type SessionHandler = <TestSessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = TestSessionKeys;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

impl pallet_session::historical::Config for Test {
Expand Down Expand Up @@ -210,6 +212,7 @@ impl pallet_staking::Config for Test {
type OnStakerSlash = ();
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

impl pallet_offences::Config for Test {
Expand Down Expand Up @@ -304,7 +307,7 @@ pub fn new_test_ext_raw_authorities(authorities: AuthorityList) -> sp_io::TestEx
validator_count: 8,
force_era: pallet_staking::Forcing::ForceNew,
minimum_validator_count: 0,
invulnerables: vec![],
invulnerables: vec![].try_into().unwrap(),
..Default::default()
};

Expand Down
1 change: 1 addition & 0 deletions frame/im-online/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ impl pallet_session::Config for Runtime {
type Event = Event;
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

impl pallet_session::historical::Config for Runtime {
Expand Down
13 changes: 7 additions & 6 deletions frame/im-online/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ fn should_report_offline_validators() {

// should not report when heartbeat is sent
for (idx, v) in validators.into_iter().take(4).enumerate() {
let _ = heartbeat(block, 3, idx as u32, v.into(), Session::validators()).unwrap();
let _ = heartbeat(block, 3, idx as u32, v.into(), Session::validators().into_inner())
.unwrap();
}
advance_session();

Expand Down Expand Up @@ -162,15 +163,15 @@ fn should_mark_online_validator_when_heartbeat_is_received() {
assert!(!ImOnline::is_online(2));

// when
let _ = heartbeat(1, 2, 0, 1.into(), Session::validators()).unwrap();
let _ = heartbeat(1, 2, 0, 1.into(), Session::validators().into_inner()).unwrap();

// then
assert!(ImOnline::is_online(0));
assert!(!ImOnline::is_online(1));
assert!(!ImOnline::is_online(2));

// and when
let _ = heartbeat(1, 2, 2, 3.into(), Session::validators()).unwrap();
let _ = heartbeat(1, 2, 2, 3.into(), Session::validators().into_inner()).unwrap();

// then
assert!(ImOnline::is_online(0));
Expand All @@ -194,11 +195,11 @@ fn late_heartbeat_and_invalid_keys_len_should_fail() {

// when
assert_noop!(
heartbeat(1, 3, 0, 1.into(), Session::validators()),
heartbeat(1, 3, 0, 1.into(), Session::validators().into_inner()),
"Transaction is outdated"
);
assert_noop!(
heartbeat(1, 1, 0, 1.into(), Session::validators()),
heartbeat(1, 1, 0, 1.into(), Session::validators().into_inner()),
"Transaction is outdated"
);

Expand Down Expand Up @@ -272,7 +273,7 @@ fn should_cleanup_received_heartbeats_on_session_end() {
assert_eq!(Session::validators(), vec![1, 2, 3]);

// send an heartbeat from authority id 0 at session 2
let _ = heartbeat(1, 2, 0, 1.into(), Session::validators()).unwrap();
let _ = heartbeat(1, 2, 0, 1.into(), Session::validators().into_inner()).unwrap();

// the heartbeat is stored
assert!(!ImOnline::received_heartbeats(&2, &0).is_none());
Expand Down
1 change: 1 addition & 0 deletions frame/nomination-pools/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ impl pallet_staking::Config for Runtime {
type OnStakerSlash = Pools;
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

parameter_types! {
Expand Down
1 change: 1 addition & 0 deletions frame/nomination-pools/test-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ impl pallet_staking::Config for Runtime {
type OnStakerSlash = Pools;
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

parameter_types! {
Expand Down
3 changes: 3 additions & 0 deletions frame/offences/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl pallet_session::SessionHandler<AccountId> for TestSessionHandler {
parameter_types! {
pub const Period: u64 = 1;
pub const Offset: u64 = 0;
pub const MaxValidators: u32 = 3072;
}

impl pallet_session::Config for Test {
Expand All @@ -130,6 +131,7 @@ impl pallet_session::Config for Test {
type ValidatorId = AccountId;
type ValidatorIdOf = pallet_staking::StashOf<Test>;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

pallet_staking_reward_curve::build! {
Expand Down Expand Up @@ -182,6 +184,7 @@ impl pallet_staking::Config for Test {
type OnStakerSlash = ();
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

impl pallet_im_online::Config for Test {
Expand Down
6 changes: 6 additions & 0 deletions frame/session/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ impl pallet_session::SessionHandler<AccountId> for TestSessionHandler {
fn on_disabled(_: u32) {}
}

parameter_types! {
pub const MaxValidators: u32 = 3072;
}

impl pallet_session::Config for Test {
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Test, Staking>;
type Keys = SessionKeys;
Expand All @@ -129,6 +133,7 @@ impl pallet_session::Config for Test {
type ValidatorId = AccountId;
type ValidatorIdOf = pallet_staking::StashOf<Test>;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}
pallet_staking_reward_curve::build! {
const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!(
Expand Down Expand Up @@ -178,6 +183,7 @@ impl pallet_staking::Config for Test {
type OnStakerSlash = ();
type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig;
type WeightInfo = ();
type MaxValidators = MaxValidators;
}

impl crate::Config for Test {}
Expand Down
2 changes: 1 addition & 1 deletion frame/session/src/historical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
}

fn validators() -> Vec<Self::ValidatorId> {
super::Pallet::<T>::validators()
super::Pallet::<T>::validators().into_inner()
}
}

Expand Down
29 changes: 20 additions & 9 deletions frame/session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
//! use pallet_session as session;
//!
//! fn validators<T: pallet_session::Config>() -> Vec<<T as pallet_session::Config>::ValidatorId> {
//! <pallet_session::Pallet<T>>::validators()
//! <pallet_session::Pallet<T>>::validators().into_inner()
//! }
//! # fn main(){}
//! ```
Expand Down Expand Up @@ -124,7 +124,7 @@ use frame_support::{
ValidatorRegistration, ValidatorSet,
},
weights::Weight,
Parameter,
Parameter, WeakBoundedVec,
};
use sp_runtime::{
traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero},
Expand Down Expand Up @@ -412,6 +412,10 @@ pub mod pallet {

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;

// Maximum number of validators.
#[pallet::constant]
type MaxValidators: Get<u32>;
}

#[pallet::genesis_config]
Expand Down Expand Up @@ -466,6 +470,8 @@ pub mod pallet {
);
self.keys.iter().map(|x| x.1.clone()).collect()
});
let initial_validators: WeakBoundedVec<T::ValidatorId, T::MaxValidators> =
initial_validators_0.clone().try_into().expect("Too many initial validators");
assert!(
!initial_validators_0.is_empty(),
"Empty validator set for session 0 in genesis block!"
Expand All @@ -492,7 +498,7 @@ pub mod pallet {
// Tell everyone about the genesis session keys
T::SessionHandler::on_genesis_session::<T::Keys>(&queued_keys);

Validators::<T>::put(initial_validators_0);
Validators::<T>::put(initial_validators);
<QueuedKeys<T>>::put(queued_keys);

T::SessionManager::start_session(0);
Expand All @@ -502,7 +508,8 @@ pub mod pallet {
/// The current set of validators.
#[pallet::storage]
#[pallet::getter(fn validators)]
pub type Validators<T: Config> = StorageValue<_, Vec<T::ValidatorId>, ValueQuery>;
pub type Validators<T: Config> =
StorageValue<_, WeakBoundedVec<T::ValidatorId, T::MaxValidators>, ValueQuery>;

/// Current index of the session.
#[pallet::storage]
Expand All @@ -527,7 +534,8 @@ pub mod pallet {
/// a new set of identities.
#[pallet::storage]
#[pallet::getter(fn disabled_validators)]
pub type DisabledValidators<T> = StorageValue<_, Vec<u32>, ValueQuery>;
pub type DisabledValidators<T: Config> =
StorageValue<_, BoundedVec<u32, T::MaxValidators>, ValueQuery>;

/// The next session keys for a validator.
#[pallet::storage]
Expand Down Expand Up @@ -647,7 +655,10 @@ impl<T: Config> Pallet<T> {
let session_keys = <QueuedKeys<T>>::get();
let validators =
session_keys.iter().map(|(validator, _)| validator.clone()).collect::<Vec<_>>();
Validators::<T>::put(&validators);

let bounded_validator_set: WeakBoundedVec<T::ValidatorId, T::MaxValidators> =
validators.clone().try_into().expect("Max validators reached");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this panic is still not valid.

Validators::<T>::put(bounded_validator_set);

if changed {
// reset disabled validators
Expand All @@ -669,7 +680,7 @@ impl<T: Config> Pallet<T> {
// same as before, as underlying economic conditions may have changed.
(validators, true)
} else {
(Validators::<T>::get(), false)
(Validators::<T>::get().into_inner(), false)
};

// Queue next session keys.
Expand Down Expand Up @@ -722,7 +733,7 @@ impl<T: Config> Pallet<T> {

<DisabledValidators<T>>::mutate(|disabled| {
if let Err(index) = disabled.binary_search(&i) {
disabled.insert(index, i);
disabled.try_insert(index, i).expect("Limit reached");
T::SessionHandler::on_disabled(i);
return true
}
Expand Down Expand Up @@ -911,7 +922,7 @@ impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
}

fn validators() -> Vec<Self::ValidatorId> {
Pallet::<T>::validators()
Pallet::<T>::validators().into_inner()
}
}

Expand Down
1 change: 1 addition & 0 deletions frame/session/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ impl Config for Test {
type Event = Event;
type NextSessionRotation = ();
type WeightInfo = ();
type MaxValidators = ConstU32<3072>;
}

#[cfg(feature = "historical")]
Expand Down
Loading