make MAX_VOTERS and MAX_CANDIDATES in elections-phragmen configurable. Fix: #11092 (#11908)

* make MAX_VOTERS and MAX_CANDIDATES in elections-phragmen configurable

* Configure election-phragmen in node bin configuring max candidates & voters

* Add document comment for added Config parameter

* Incorporate suggestion

* fix benchmarks

* Update frame/elections-phragmen/src/lib.rs

* Update frame/elections-phragmen/src/lib.rs

* fix wrong values

* fix typo

* docs

* more detailed docs

* fmt

* ".git/.scripts/bench-bot.sh" pallet dev pallet_elections_phragmen

Co-authored-by: Szegoo <sakacszergej@gmail.com>
Co-authored-by: Sergej Sakac <73715684+Szegoo@users.noreply.github.com>
Co-authored-by: command-bot <>
This commit is contained in:
Sudip Ghimire
2022-08-14 23:50:06 +05:45
committed by GitHub
parent e5ed764d39
commit bc6f7bdda9
4 changed files with 94 additions and 78 deletions
+4
View File
@@ -966,6 +966,8 @@ parameter_types! {
pub const TermDuration: BlockNumber = 7 * DAYS;
pub const DesiredMembers: u32 = 13;
pub const DesiredRunnersUp: u32 = 7;
pub const MaxVoters: u32 = 10 * 1000;
pub const MaxCandidates: u32 = 1000;
pub const ElectionsPhragmenPalletId: LockIdentifier = *b"phrelect";
}
@@ -989,6 +991,8 @@ impl pallet_elections_phragmen::Config for Runtime {
type DesiredMembers = DesiredMembers;
type DesiredRunnersUp = DesiredRunnersUp;
type TermDuration = TermDuration;
type MaxVoters = MaxVoters;
type MaxCandidates = MaxCandidates;
type WeightInfo = pallet_elections_phragmen::weights::SubstrateWeight<Runtime>;
}
@@ -36,7 +36,7 @@ fn endowed_account<T: Config>(name: &'static str, index: u32) -> T::AccountId {
let account: T::AccountId = account(name, index, 0);
// Fund each account with at-least his stake but still a sane amount as to not mess up
// the vote calculation.
let amount = default_stake::<T>(MAX_VOTERS) * BalanceOf::<T>::from(BALANCE_FACTOR);
let amount = default_stake::<T>(T::MaxVoters::get()) * BalanceOf::<T>::from(BALANCE_FACTOR);
let _ = T::Currency::make_free_balance_be(&account, amount);
// important to increase the total issuance since T::CurrencyToVote will need it to be sane for
// phragmen to work.
@@ -230,7 +230,7 @@ benchmarks! {
submit_candidacy {
// number of already existing candidates.
let c in 1 .. MAX_CANDIDATES;
let c in 1 .. T::MaxCandidates::get();
// we fix the number of members to the number of desired members and runners-up. We'll be in
// this state almost always.
let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get();
@@ -261,7 +261,7 @@ benchmarks! {
// this will check members, runners-up and candidate for removal. Members and runners-up are
// limited by the runtime bound, nonetheless we fill them by `m`.
// number of already existing candidates.
let c in 1 .. MAX_CANDIDATES;
let c in 1 .. T::MaxCandidates::get();
// we fix the number of members to the number of desired members and runners-up. We'll be in
// this state almost always.
let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get();
@@ -362,14 +362,14 @@ benchmarks! {
clean_defunct_voters {
// total number of voters.
let v in (MAX_VOTERS / 2) .. MAX_VOTERS;
let v in (T::MaxVoters::get() / 2) .. T::MaxVoters::get();
// those that are defunct and need removal.
let d in 1 .. (MAX_VOTERS / 2);
let d in 1 .. (T::MaxVoters::get() / 2);
// remove any previous stuff.
clean::<T>();
let all_candidates = submit_candidates::<T>(MAX_CANDIDATES, "candidates")?;
let all_candidates = submit_candidates::<T>(T::MaxCandidates::get(), "candidates")?;
distribute_voters::<T>(all_candidates, v, MAXIMUM_VOTE)?;
// all candidates leave.
@@ -389,9 +389,9 @@ benchmarks! {
// members, this is hard-coded in the runtime and cannot be trivially changed at this stage.
// Yet, change the number of voters, candidates and edge per voter to see the impact. Note
// that we give all candidates a self vote to make sure they are all considered.
let c in 1 .. MAX_CANDIDATES;
let v in 1 .. MAX_VOTERS;
let e in MAX_VOTERS .. MAX_VOTERS * MAXIMUM_VOTE as u32;
let c in 1 .. T::MaxCandidates::get();
let v in 1 .. T::MaxVoters::get();
let e in (T::MaxVoters::get()) .. T::MaxVoters::get() as u32 * MAXIMUM_VOTE as u32;
clean::<T>();
// so we have a situation with v and e. we want e to basically always be in the range of `e
@@ -425,9 +425,9 @@ benchmarks! {
#[extra]
election_phragmen_c_e {
let c in 1 .. MAX_CANDIDATES;
let e in MAX_VOTERS .. MAX_VOTERS * MAXIMUM_VOTE as u32;
let fixed_v = MAX_VOTERS;
let c in 1 .. T::MaxCandidates::get();
let e in (T::MaxVoters::get()) .. T::MaxVoters::get() * MAXIMUM_VOTE as u32;
let fixed_v = T::MaxVoters::get();
clean::<T>();
let votes_per_voter = e / fixed_v;
@@ -459,7 +459,7 @@ benchmarks! {
#[extra]
election_phragmen_v {
let v in 4 .. 16;
let fixed_c = MAX_CANDIDATES / 10;
let fixed_c = T::MaxCandidates::get() / 10;
let fixed_e = 64;
clean::<T>();
+26 -14
View File
@@ -125,17 +125,6 @@ pub mod migrations;
/// The maximum votes allowed per voter.
pub const MAXIMUM_VOTE: usize = 16;
// Some safe temp values to make the wasm execution sane while we still use this pallet.
#[cfg(test)]
pub(crate) const MAX_CANDIDATES: u32 = 100;
#[cfg(not(test))]
pub(crate) const MAX_CANDIDATES: u32 = 1000;
#[cfg(test)]
pub(crate) const MAX_VOTERS: u32 = 1000;
#[cfg(not(test))]
pub(crate) const MAX_VOTERS: u32 = 10 * 1000;
type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
@@ -259,6 +248,21 @@ pub mod pallet {
#[pallet::constant]
type TermDuration: Get<Self::BlockNumber>;
/// The maximum number of candidates in a phragmen election.
///
/// Warning: The election happens onchain, and this value will determine
/// the size of the election. When this limit is reached no more
/// candidates are accepted in the election.
#[pallet::constant]
type MaxCandidates: Get<u32>;
/// The maximum number of voters to allow in a phragmen election.
///
/// Warning: This impacts the size of the election which is run onchain.
/// When the limit is reached the new voters are ignored.
#[pallet::constant]
type MaxVoters: Get<u32>;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
@@ -397,7 +401,10 @@ pub mod pallet {
let actual_count = <Candidates<T>>::decode_len().unwrap_or(0) as u32;
ensure!(actual_count <= candidate_count, Error::<T>::InvalidWitnessData);
ensure!(actual_count <= MAX_CANDIDATES, Error::<T>::TooManyCandidates);
ensure!(
actual_count <= <T as Config>::MaxCandidates::get(),
Error::<T>::TooManyCandidates
);
let index = Self::is_candidate(&who).err().ok_or(Error::<T>::DuplicatedCandidate)?;
@@ -913,10 +920,11 @@ impl<T: Config> Pallet<T> {
let mut num_edges: u32 = 0;
let max_voters = <T as Config>::MaxVoters::get() as usize;
// used for prime election.
let mut voters_and_stakes = Vec::new();
match Voting::<T>::iter().try_for_each(|(voter, Voter { stake, votes, .. })| {
if voters_and_stakes.len() < MAX_VOTERS as usize {
if voters_and_stakes.len() < max_voters {
voters_and_stakes.push((voter, stake, votes));
Ok(())
} else {
@@ -930,7 +938,7 @@ impl<T: Config> Pallet<T> {
"Failed to run election. Number of voters exceeded",
);
Self::deposit_event(Event::ElectionError);
return T::DbWeight::get().reads(3 + MAX_VOTERS as u64)
return T::DbWeight::get().reads(3 + max_voters as u64)
},
}
@@ -1266,6 +1274,8 @@ mod tests {
parameter_types! {
pub const ElectionsPhragmenPalletId: LockIdentifier = *b"phrelect";
pub const PhragmenMaxVoters: u32 = 1000;
pub const PhragmenMaxCandidates: u32 = 100;
}
impl Config for Test {
@@ -1284,6 +1294,8 @@ mod tests {
type LoserCandidate = ();
type KickedMember = ();
type WeightInfo = ();
type MaxVoters = PhragmenMaxVoters;
type MaxCandidates = PhragmenMaxCandidates;
}
pub type Block = sp_runtime::generic::Block<Header, UncheckedExtrinsic>;
@@ -18,7 +18,7 @@
//! Autogenerated weights for pallet_elections_phragmen
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2022-08-01, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! DATE: 2022-08-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
@@ -70,9 +70,9 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Balances Locks (r:1 w:1)
/// The range of component `v` is `[1, 16]`.
fn vote_equal(v: u32, ) -> Weight {
(26_143_000 as Weight)
// Standard Error: 23_000
.saturating_add((297_000 as Weight).saturating_mul(v as Weight))
(27_011_000 as Weight)
// Standard Error: 3_000
.saturating_add((214_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -83,9 +83,9 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Balances Locks (r:1 w:1)
/// The range of component `v` is `[2, 16]`.
fn vote_more(v: u32, ) -> Weight {
(40_431_000 as Weight)
// Standard Error: 6_000
.saturating_add((205_000 as Weight).saturating_mul(v as Weight))
(40_240_000 as Weight)
// Standard Error: 5_000
.saturating_add((244_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -96,16 +96,16 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Balances Locks (r:1 w:1)
/// The range of component `v` is `[2, 16]`.
fn vote_less(v: u32, ) -> Weight {
(40_188_000 as Weight)
// Standard Error: 6_000
.saturating_add((225_000 as Weight).saturating_mul(v as Weight))
(40_394_000 as Weight)
// Standard Error: 5_000
.saturating_add((217_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
// Storage: Elections Voting (r:1 w:1)
// Storage: Balances Locks (r:1 w:1)
fn remove_voter() -> Weight {
(38_031_000 as Weight)
(37_651_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -114,18 +114,18 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Elections RunnersUp (r:1 w:0)
/// The range of component `c` is `[1, 1000]`.
fn submit_candidacy(c: u32, ) -> Weight {
(43_715_000 as Weight)
(42_217_000 as Weight)
// Standard Error: 0
.saturating_add((49_000 as Weight).saturating_mul(c as Weight))
.saturating_add((50_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Elections Candidates (r:1 w:1)
/// The range of component `c` is `[1, 1000]`.
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
(47_882_000 as Weight)
// Standard Error: 1_000
.saturating_add((25_000 as Weight).saturating_mul(c as Weight))
(46_459_000 as Weight)
// Standard Error: 0
.saturating_add((26_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -135,13 +135,13 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Council Proposals (r:1 w:0)
// Storage: Council Members (r:0 w:1)
fn renounce_candidacy_members() -> Weight {
(45_600_000 as Weight)
(45_189_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Elections RunnersUp (r:1 w:1)
fn renounce_candidacy_runners_up() -> Weight {
(34_959_000 as Weight)
(34_516_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -156,7 +156,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Council Proposals (r:1 w:0)
// Storage: Council Members (r:0 w:1)
fn remove_member_with_replacement() -> Weight {
(52_684_000 as Weight)
(51_838_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -170,8 +170,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// The range of component `d` is `[1, 5000]`.
fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 65_000
.saturating_add((64_009_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 76_000
.saturating_add((63_721_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight)))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(v as Weight)))
@@ -184,17 +184,17 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: Elections ElectionRounds (r:1 w:1)
// Storage: Council Members (r:0 w:1)
// Storage: Council Prime (r:0 w:1)
// Storage: System Account (r:19 w:19)
// Storage: System Account (r:1 w:1)
/// The range of component `c` is `[1, 1000]`.
/// The range of component `v` is `[1, 10000]`.
/// The range of component `e` is `[10000, 160000]`.
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 778_000
.saturating_add((81_049_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 773_000
.saturating_add((81_534_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 51_000
.saturating_add((4_420_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(279 as Weight))
.saturating_add((4_453_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(280 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight)))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight)))
@@ -210,9 +210,9 @@ impl WeightInfo for () {
// Storage: Balances Locks (r:1 w:1)
/// The range of component `v` is `[1, 16]`.
fn vote_equal(v: u32, ) -> Weight {
(26_143_000 as Weight)
// Standard Error: 23_000
.saturating_add((297_000 as Weight).saturating_mul(v as Weight))
(27_011_000 as Weight)
// Standard Error: 3_000
.saturating_add((214_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -223,9 +223,9 @@ impl WeightInfo for () {
// Storage: Balances Locks (r:1 w:1)
/// The range of component `v` is `[2, 16]`.
fn vote_more(v: u32, ) -> Weight {
(40_431_000 as Weight)
// Standard Error: 6_000
.saturating_add((205_000 as Weight).saturating_mul(v as Weight))
(40_240_000 as Weight)
// Standard Error: 5_000
.saturating_add((244_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -236,16 +236,16 @@ impl WeightInfo for () {
// Storage: Balances Locks (r:1 w:1)
/// The range of component `v` is `[2, 16]`.
fn vote_less(v: u32, ) -> Weight {
(40_188_000 as Weight)
// Standard Error: 6_000
.saturating_add((225_000 as Weight).saturating_mul(v as Weight))
(40_394_000 as Weight)
// Standard Error: 5_000
.saturating_add((217_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
// Storage: Elections Voting (r:1 w:1)
// Storage: Balances Locks (r:1 w:1)
fn remove_voter() -> Weight {
(38_031_000 as Weight)
(37_651_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -254,18 +254,18 @@ impl WeightInfo for () {
// Storage: Elections RunnersUp (r:1 w:0)
/// The range of component `c` is `[1, 1000]`.
fn submit_candidacy(c: u32, ) -> Weight {
(43_715_000 as Weight)
(42_217_000 as Weight)
// Standard Error: 0
.saturating_add((49_000 as Weight).saturating_mul(c as Weight))
.saturating_add((50_000 as Weight).saturating_mul(c as Weight))
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Elections Candidates (r:1 w:1)
/// The range of component `c` is `[1, 1000]`.
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
(47_882_000 as Weight)
// Standard Error: 1_000
.saturating_add((25_000 as Weight).saturating_mul(c as Weight))
(46_459_000 as Weight)
// Standard Error: 0
.saturating_add((26_000 as Weight).saturating_mul(c as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -275,13 +275,13 @@ impl WeightInfo for () {
// Storage: Council Proposals (r:1 w:0)
// Storage: Council Members (r:0 w:1)
fn renounce_candidacy_members() -> Weight {
(45_600_000 as Weight)
(45_189_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
// Storage: Elections RunnersUp (r:1 w:1)
fn renounce_candidacy_runners_up() -> Weight {
(34_959_000 as Weight)
(34_516_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -296,7 +296,7 @@ impl WeightInfo for () {
// Storage: Council Proposals (r:1 w:0)
// Storage: Council Members (r:0 w:1)
fn remove_member_with_replacement() -> Weight {
(52_684_000 as Weight)
(51_838_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -310,8 +310,8 @@ impl WeightInfo for () {
/// The range of component `d` is `[1, 5000]`.
fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 65_000
.saturating_add((64_009_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 76_000
.saturating_add((63_721_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight)))
.saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(v as Weight)))
@@ -324,17 +324,17 @@ impl WeightInfo for () {
// Storage: Elections ElectionRounds (r:1 w:1)
// Storage: Council Members (r:0 w:1)
// Storage: Council Prime (r:0 w:1)
// Storage: System Account (r:19 w:19)
// Storage: System Account (r:1 w:1)
/// The range of component `c` is `[1, 1000]`.
/// The range of component `v` is `[1, 10000]`.
/// The range of component `e` is `[10000, 160000]`.
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 778_000
.saturating_add((81_049_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 773_000
.saturating_add((81_534_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 51_000
.saturating_add((4_420_000 as Weight).saturating_mul(e as Weight))
.saturating_add(RocksDbWeight::get().reads(279 as Weight))
.saturating_add((4_453_000 as Weight).saturating_mul(e as Weight))
.saturating_add(RocksDbWeight::get().reads(280 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(c as Weight)))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight)))
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(c as Weight)))