Skip to content
Prev Previous commit
Next Next commit
add max winners bound to elections
  • Loading branch information
maciejnems committed Feb 13, 2023
commit 5b787e7f4aebd36bdeb2ea2314f3a351208305be
4 changes: 3 additions & 1 deletion bin/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use primitives::{
staking::MAX_NOMINATORS_REWARDED_PER_VALIDATOR, wrap_methods, ApiError as AlephApiError,
AuthorityId as AlephId, SessionAuthorityData, Version as FinalityVersion, ADDRESSES_ENCODING,
DEFAULT_BAN_REASON_LENGTH, DEFAULT_SESSIONS_PER_ERA, DEFAULT_SESSION_PERIOD, MAX_BLOCK_SIZE,
MILLISECS_PER_BLOCK, TOKEN,
MILLISECS_PER_BLOCK, TOKEN, DEFAULT_MAX_WINNERS,
};
use sp_api::impl_runtime_apis;
use sp_consensus_aura::{sr25519::AuthorityId as AuraId, SlotDuration};
Expand Down Expand Up @@ -327,6 +327,7 @@ impl_opaque_keys! {
parameter_types! {
pub const SessionPeriod: u32 = DEFAULT_SESSION_PERIOD;
pub const MaximumBanReasonLength: u32 = DEFAULT_BAN_REASON_LENGTH;
pub const MaxWinners: u32 = DEFAULT_MAX_WINNERS;
}

impl pallet_elections::Config for Runtime {
Expand All @@ -339,6 +340,7 @@ impl pallet_elections::Config for Runtime {
type ValidatorRewardsHandler = Staking;
type ValidatorExtractor = Staking;
type MaximumBanReasonLength = MaximumBanReasonLength;
type MaxWinners = MaxWinners;
}

impl pallet_randomness_collective_flip::Config for Runtime {}
Expand Down
27 changes: 22 additions & 5 deletions pallets/elections/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ pub struct ValidatorTotalRewards<T>(pub BTreeMap<T, TotalReward>);
#[frame_support::pallet]
pub mod pallet {
use frame_election_provider_support::{
ElectionDataProvider, ElectionProvider, ElectionProviderBase, Support, Supports,
BoundedSupportsOf, ElectionDataProvider, ElectionProvider, ElectionProviderBase, Support,
Supports,
};
use frame_support::{log, pallet_prelude::*, traits::Get};
use frame_system::{
Expand Down Expand Up @@ -108,6 +109,13 @@ pub mod pallet {
/// Maximum acceptable ban reason length.
#[pallet::constant]
type MaximumBanReasonLength: Get<u32>;

/// The maximum number of winners that can be elected by this `ElectionProvider`
/// implementation.
///
/// Note: This must always be greater or equal to `T::DataProvider::desired_targets()`.
#[pallet::constant]
type MaxWinners: Get<u32>;
}

#[pallet::event]
Expand Down Expand Up @@ -451,6 +459,10 @@ pub mod pallet {
#[derive(Debug)]
pub enum ElectionError {
DataProvider(&'static str),

/// Winner number is greater than
/// [`Config::MaxWinners`]
TooManyWinners,
}

#[pallet::error]
Expand All @@ -476,17 +488,18 @@ pub mod pallet {
type BlockNumber = T::BlockNumber;
type Error = ElectionError;
type DataProvider = T::DataProvider;
type MaxWinners = T::MaxWinners;
}

impl<T: Config> ElectionProvider for Pallet<T> {
fn ongoing() -> bool {
false
}
}

impl<T: Config> ElectionProvider for Pallet<T> {
/// We calculate the supports for each validator. The external validators are chosen as:
/// 1) "`NextEraNonReservedValidators` that are staking and are not banned" in case of Permissioned ElectionOpenness
/// 2) "All staking and not banned validators" in case of Permissionless ElectionOpenness
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
fn elect() -> Result<BoundedSupportsOf<Self>, Self::Error> {
Self::emit_fresh_bans_event();
let active_era = <T as Config>::EraInfoProvider::active_era().unwrap_or(0);
let ban_period = BanConfig::<T>::get().ban_period;
Expand Down Expand Up @@ -554,7 +567,11 @@ pub mod pallet {
}
}

Ok(supports.into_iter().collect())
supports
.into_iter()
.collect::<Supports<_>>()
.try_into()
.map_err(|_| Self::Error::TooManyWinners)
}
}
}
3 changes: 2 additions & 1 deletion pallets/elections/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use frame_support::{
weights::{RuntimeDbWeight, Weight},
BasicExternalities, BoundedVec,
};
use primitives::{BanConfig, CommitteeSeats};
use primitives::{BanConfig, CommitteeSeats, DEFAULT_MAX_WINNERS};
use sp_core::H256;
use sp_runtime::{
testing::{Header, TestXt},
Expand Down Expand Up @@ -186,6 +186,7 @@ impl Config for Test {
type ValidatorRewardsHandler = MockProvider;
type ValidatorExtractor = MockProvider;
type MaximumBanReasonLength = ConstU32<300>;
type MaxWinners = ConstU32<DEFAULT_MAX_WINNERS>;
}

type MaxVotesPerVoter = ConstU32<1>;
Expand Down
2 changes: 1 addition & 1 deletion pallets/elections/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn validators_are_elected_only_when_staking() {
<Elections as ElectionProvider>::elect().expect("`elect()` should succeed");

assert_eq!(
elected,
elected.into_inner(),
&[
(1, support(10, vec![(1, 10)])),
(2, no_support()),
Expand Down
1 change: 1 addition & 0 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub const DEFAULT_COMMITTEE_SIZE: u32 = 4;
pub const DEFAULT_BAN_MINIMAL_EXPECTED_PERFORMANCE: Perbill = Perbill::from_percent(0);
pub const DEFAULT_BAN_SESSION_COUNT_THRESHOLD: SessionCount = 3;
pub const DEFAULT_BAN_REASON_LENGTH: u32 = 300;
pub const DEFAULT_MAX_WINNERS: u32 = u32::MAX;

pub const DEFAULT_CLEAN_SESSION_COUNTER_DELAY: SessionCount = 960;
pub const DEFAULT_BAN_PERIOD: EraIndex = 10;
Expand Down