Abstracts elections-phragmen pallet to use NposSolver (#12588)

* Abstracts elections-phragmen pallet to use NposSolver

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

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

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

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* changes the name of the pallet; adds changelog

* update changelog

* Adds weight testing

* Adds log macro_rules

* renames elections-phragment dir to elections

* weights rename

* fixes typo in cargo toml

* pre/post solve weight scafolding

* refactor do_post_election

* refactors into pre and post election solve for independent benchmarking

* deconstructs PreElectionResults struct

* updates benchmarking pre and post election solve; mock weights

* Update frame/elections/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update frame/elections/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* addresses PR comments

* adds pre_solve and post_sove weights

* Adds comments on election pallet id param name change

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

* Finishes pre-post solve weights

* Update frame/elections/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update frame/elections/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Addresses PR comments: no panic in on_init path; nits

* Fixes node build

* Implements approval voting to use as a `NposSolver` (#13367)

* Implements the approval voting methods in sp_npos_elections

* fmt

* remove unecessary file

* comment clarification

* re-run weights

* fix typo

* updates MaxVoters in tests for integrity_tests to pass

* Refactors election provider support benchmarks outside its own crate (#13431)

* Refactors election provider support benchmarks outside its own crate
---------

Co-authored-by: command-bot <>

---------

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: parity-processbot <>
Co-authored-by: Ross Bulat <ross@parity.io>
This commit is contained in:
Gonçalo Pestana
2023-02-23 11:21:00 +00:00
committed by GitHub
parent 17e055e594
commit b793666ca5
28 changed files with 1197 additions and 1018 deletions
@@ -1,35 +0,0 @@
# Changelog
All notable changes to this crate will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this crate adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.0.0] - UNRELEASED
### Added
### Changed
\[**Needs Migration**\] [migrate pallet-elections-phragmen to attribute macros](https://github.com/paritytech/substrate/pull/8044)
### Fixed
### Security
## [3.0.0]
### Added
[Add slashing events to elections-phragmen](https://github.com/paritytech/substrate/pull/7543)
### Changed
### Fixed
[Don't slash all outgoing members](https://github.com/paritytech/substrate/pull/7394)
[Fix wrong outgoing calculation in election](https://github.com/paritytech/substrate/pull/7384)
### Security
\[**Needs Migration**\] [Fix elections-phragmen and proxy issue + Record deposits on-chain](https://github.com/paritytech/substrate/pull/7040)
## [2.0.0] - 2020-09-2020
Initial version from which version tracking has begun.
@@ -1,56 +0,0 @@
[package]
name = "pallet-elections-phragmen"
version = "5.0.0-dev"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://substrate.io"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME pallet based on seq-Phragmén election method."
readme = "README.md"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = [
"derive",
] }
log = { version = "0.4.14", default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
sp-core = { version = "7.0.0", default-features = false, path = "../../primitives/core" }
sp-io = { version = "7.0.0", default-features = false, path = "../../primitives/io" }
sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" }
sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "5.0.0", default-features = false, path = "../../primitives/std" }
[dev-dependencies]
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
sp-core = { version = "7.0.0", path = "../../primitives/core" }
sp-tracing = { path = "../../primitives/tracing" }
substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" }
[features]
default = ["std"]
std = [
"frame-benchmarking?/std",
"codec/std",
"frame-support/std",
"frame-system/std",
"log/std",
"scale-info/std",
"sp-core/std",
"sp-io/std",
"sp-npos-elections/std",
"sp-runtime/std",
"sp-std/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
@@ -1,67 +0,0 @@
# Phragmén Election Module.
An election module based on sequential phragmen.
### Term and Round
The election happens in _rounds_: every `N` blocks, all previous members are retired and a new
set is elected (which may or may not have an intersection with the previous set). Each round
lasts for some number of blocks defined by `TermDuration` storage item. The words _term_ and
_round_ can be used interchangeably in this context.
`TermDuration` might change during a round. This can shorten or extend the length of the round.
The next election round's block number is never stored but rather always checked on the fly.
Based on the current block number and `TermDuration`, the condition `BlockNumber % TermDuration
== 0` being satisfied will always trigger a new election round.
### Voting
Voters can vote for any set of the candidates by providing a list of account ids. Invalid votes
(voting for non-candidates) are ignored during election. Yet, a voter _might_ vote for a future
candidate. Voters reserve a bond as they vote. Each vote defines a `value`. This amount is
locked from the account of the voter and indicates the weight of the vote. Voters can update
their votes at any time by calling `vote()` again. This keeps the bond untouched but can
optionally change the locked `value`. After a round, votes are kept and might still be valid for
further rounds. A voter is responsible for calling `remove_voter` once they are done to have
their bond back and remove the lock.
Voters also report other voters as being defunct to earn their bond. A voter is defunct once all
of the candidates that they have voted for are neither a valid candidate anymore nor a member.
Upon reporting, if the target voter is actually defunct, the reporter will be rewarded by the
voting bond of the target. The target will lose their bond and get removed. If the target is not
defunct, the reporter is slashed and removed. To prevent being reported, voters should manually
submit a `remove_voter()` as soon as they are in the defunct state.
### Candidacy and Members
Candidates also reserve a bond as they submit candidacy. A candidate cannot take their candidacy
back. A candidate can end up in one of the below situations:
- **Winner**: A winner is kept as a _member_. They must still have a bond in reserve and they
are automatically counted as a candidate for the next election.
- **Runner-up**: Runners-up are the best candidates immediately after the winners. The number
of runners_up to keep is configurable. Runners-up are used, in order that they are elected,
as replacements when a candidate is kicked by `[remove_member]`, or when an active member
renounces their candidacy. Runners are automatically counted as a candidate for the next
election.
- **Loser**: Any of the candidate who are not a winner are left as losers. A loser might be an
_outgoing member or runner_, meaning that they are an active member who failed to keep their
spot. An outgoing will always lose their bond.
##### Renouncing candidacy.
All candidates, elected or not, can renounce their candidacy. A call to [`Module::renounce_candidacy`]
will always cause the candidacy bond to be refunded.
Note that with the members being the default candidates for the next round and votes persisting
in storage, the election system is entirely stable given no further input. This means that if
the system has a particular set of candidates `C` and voters `V` that lead to a set of members
`M` being elected, as long as `V` and `C` don't remove their candidacy and votes, `M` will keep
being re-elected at the end of each round.
### Module Information
- [`election_sp_phragmen::Config`](https://docs.rs/pallet-elections-phragmen/latest/pallet_elections_phragmen/trait.Config.html)
- [`Call`](https://docs.rs/pallet-elections-phragmen/latest/pallet_elections_phragmen/enum.Call.html)
- [`Module`](https://docs.rs/pallet-elections-phragmen/latest/pallet_elections_phragmen/struct.Module.html)
License: Apache-2.0
@@ -1,430 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Elections-Phragmen pallet benchmarking.
#![cfg(feature = "runtime-benchmarks")]
use super::*;
use frame_benchmarking::v1::{account, benchmarks, whitelist, BenchmarkError, BenchmarkResult};
use frame_support::{dispatch::DispatchResultWithPostInfo, traits::OnInitialize};
use frame_system::RawOrigin;
use crate::Pallet as Elections;
const BALANCE_FACTOR: u32 = 250;
/// grab new account with infinite balance.
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 their stake but still a sane amount as to not mess up
// the vote calculation.
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.
T::Currency::issue(amount);
account
}
/// Account to lookup type of system trait.
fn as_lookup<T: Config>(account: T::AccountId) -> AccountIdLookupOf<T> {
T::Lookup::unlookup(account)
}
/// Get a reasonable amount of stake based on the execution trait's configuration
fn default_stake<T: Config>(num_votes: u32) -> BalanceOf<T> {
let min = T::Currency::minimum_balance();
Elections::<T>::deposit_of(num_votes as usize).max(min)
}
/// Get the current number of candidates.
fn candidate_count<T: Config>() -> u32 {
<Candidates<T>>::decode_len().unwrap_or(0usize) as u32
}
/// Add `c` new candidates.
fn submit_candidates<T: Config>(
c: u32,
prefix: &'static str,
) -> Result<Vec<T::AccountId>, &'static str> {
(0..c)
.map(|i| {
let account = endowed_account::<T>(prefix, i);
<Elections<T>>::submit_candidacy(
RawOrigin::Signed(account.clone()).into(),
candidate_count::<T>(),
)
.map_err(|_| "failed to submit candidacy")?;
Ok(account)
})
.collect::<Result<_, _>>()
}
/// Add `c` new candidates with self vote.
fn submit_candidates_with_self_vote<T: Config>(
c: u32,
prefix: &'static str,
) -> Result<Vec<T::AccountId>, &'static str> {
let candidates = submit_candidates::<T>(c, prefix)?;
let stake = default_stake::<T>(c);
let _ = candidates
.iter()
.try_for_each(|c| submit_voter::<T>(c.clone(), vec![c.clone()], stake).map(|_| ()))?;
Ok(candidates)
}
/// Submit one voter.
fn submit_voter<T: Config>(
caller: T::AccountId,
votes: Vec<T::AccountId>,
stake: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
<Elections<T>>::vote(RawOrigin::Signed(caller).into(), votes, stake)
}
/// create `num_voter` voters who randomly vote for at most `votes` of `all_candidates` if
/// available.
fn distribute_voters<T: Config>(
mut all_candidates: Vec<T::AccountId>,
num_voters: u32,
votes: usize,
) -> Result<(), &'static str> {
let stake = default_stake::<T>(num_voters);
for i in 0..num_voters {
// to ensure that votes are different
all_candidates.rotate_left(1);
let votes = all_candidates.iter().cloned().take(votes).collect::<Vec<_>>();
let voter = endowed_account::<T>("voter", i);
submit_voter::<T>(voter, votes, stake)?;
}
Ok(())
}
/// Fill the seats of members and runners-up up until `m`. Note that this might include either only
/// members, or members and runners-up.
fn fill_seats_up_to<T: Config>(m: u32) -> Result<Vec<T::AccountId>, &'static str> {
let _ = submit_candidates_with_self_vote::<T>(m, "fill_seats_up_to")?;
assert_eq!(<Elections<T>>::candidates().len() as u32, m, "wrong number of candidates.");
<Elections<T>>::do_phragmen();
assert_eq!(<Elections<T>>::candidates().len(), 0, "some candidates remaining.");
assert_eq!(
<Elections<T>>::members().len() + <Elections<T>>::runners_up().len(),
m as usize,
"wrong number of members and runners-up",
);
Ok(<Elections<T>>::members()
.into_iter()
.map(|m| m.who)
.chain(<Elections<T>>::runners_up().into_iter().map(|r| r.who))
.collect())
}
/// removes all the storage items to reverse any genesis state.
fn clean<T: Config>() {
<Members<T>>::kill();
<Candidates<T>>::kill();
<RunnersUp<T>>::kill();
#[allow(deprecated)]
<Voting<T>>::remove_all(None);
}
benchmarks! {
// -- Signed ones
vote_equal {
let v in 1 .. T::MaxVotesPerVoter::get();
clean::<T>();
// create a bunch of candidates.
let all_candidates = submit_candidates::<T>(v, "candidates")?;
let caller = endowed_account::<T>("caller", 0);
let stake = default_stake::<T>(v);
// original votes.
let mut votes = all_candidates;
submit_voter::<T>(caller.clone(), votes.clone(), stake)?;
// new votes.
votes.rotate_left(1);
whitelist!(caller);
}: vote(RawOrigin::Signed(caller), votes, stake)
vote_more {
let v in 2 .. T::MaxVotesPerVoter::get();
clean::<T>();
// create a bunch of candidates.
let all_candidates = submit_candidates::<T>(v, "candidates")?;
let caller = endowed_account::<T>("caller", 0);
// Multiply the stake with 10 since we want to be able to divide it by 10 again.
let stake = default_stake::<T>(v) * BalanceOf::<T>::from(10u32);
// original votes.
let mut votes = all_candidates.iter().skip(1).cloned().collect::<Vec<_>>();
submit_voter::<T>(caller.clone(), votes.clone(), stake / <BalanceOf<T>>::from(10u32))?;
// new votes.
votes = all_candidates;
assert!(votes.len() > <Voting<T>>::get(caller.clone()).votes.len());
whitelist!(caller);
}: vote(RawOrigin::Signed(caller), votes, stake / <BalanceOf<T>>::from(10u32))
vote_less {
let v in 2 .. T::MaxVotesPerVoter::get();
clean::<T>();
// create a bunch of candidates.
let all_candidates = submit_candidates::<T>(v, "candidates")?;
let caller = endowed_account::<T>("caller", 0);
let stake = default_stake::<T>(v);
// original votes.
let mut votes = all_candidates;
submit_voter::<T>(caller.clone(), votes.clone(), stake)?;
// new votes.
votes = votes.into_iter().skip(1).collect::<Vec<_>>();
assert!(votes.len() < <Voting<T>>::get(caller.clone()).votes.len());
whitelist!(caller);
}: vote(RawOrigin::Signed(caller), votes, stake)
remove_voter {
// we fix the number of voted candidates to max
let v = T::MaxVotesPerVoter::get();
clean::<T>();
// create a bunch of candidates.
let all_candidates = submit_candidates::<T>(v, "candidates")?;
let caller = endowed_account::<T>("caller", 0);
let stake = default_stake::<T>(v);
submit_voter::<T>(caller.clone(), all_candidates, stake)?;
whitelist!(caller);
}: _(RawOrigin::Signed(caller))
submit_candidacy {
// number of already existing 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();
clean::<T>();
let stake = default_stake::<T>(c);
// create m members and runners combined.
let _ = fill_seats_up_to::<T>(m)?;
// create previous candidates;
let _ = submit_candidates::<T>(c, "candidates")?;
// we assume worse case that: extrinsic is successful and candidate is not duplicate.
let candidate_account = endowed_account::<T>("caller", 0);
whitelist!(candidate_account);
}: _(RawOrigin::Signed(candidate_account.clone()), candidate_count::<T>())
verify {
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
renounce_candidacy_candidate {
// 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 .. 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();
clean::<T>();
// create m members and runners combined.
let _ = fill_seats_up_to::<T>(m)?;
let all_candidates = submit_candidates::<T>(c, "caller")?;
let bailing = all_candidates[0].clone(); // Should be ("caller", 0)
let count = candidate_count::<T>();
whitelist!(bailing);
}: renounce_candidacy(RawOrigin::Signed(bailing), Renouncing::Candidate(count))
verify {
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
renounce_candidacy_members {
// removing members and runners will be cheaper than a candidate.
// we fix the number of members to when members and runners-up to the desired. We'll be in
// this state almost always.
let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get();
clean::<T>();
// create m members and runners combined.
let members_and_runners_up = fill_seats_up_to::<T>(m)?;
let bailing = members_and_runners_up[0].clone();
assert!(<Elections<T>>::is_member(&bailing));
whitelist!(bailing);
}: renounce_candidacy(RawOrigin::Signed(bailing.clone()), Renouncing::Member)
verify {
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
renounce_candidacy_runners_up {
// removing members and runners will be cheaper than a candidate.
// we fix the number of members to when members and runners-up to the desired. We'll be in
// this state almost always.
let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get();
clean::<T>();
// create m members and runners combined.
let members_and_runners_up = fill_seats_up_to::<T>(m)?;
let bailing = members_and_runners_up[T::DesiredMembers::get() as usize + 1].clone();
assert!(<Elections<T>>::is_runner_up(&bailing));
whitelist!(bailing);
}: renounce_candidacy(RawOrigin::Signed(bailing.clone()), Renouncing::RunnerUp)
verify {
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
// We use the max block weight for this extrinsic for now. See below.
remove_member_without_replacement {}: {
Err(BenchmarkError::Override(
BenchmarkResult::from_weight(T::BlockWeights::get().max_block)
))?;
}
remove_member_with_replacement {
// easy case. We have a runner up. Nothing will have that much of an impact. m will be
// number of members and runners. There is always at least one runner.
let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get();
clean::<T>();
let _ = fill_seats_up_to::<T>(m)?;
let removing = as_lookup::<T>(<Elections<T>>::members_ids()[0].clone());
}: remove_member(RawOrigin::Root, removing, true, false)
verify {
// must still have enough members.
assert_eq!(<Elections<T>>::members().len() as u32, T::DesiredMembers::get());
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
clean_defunct_voters {
// total number of voters.
let v in (T::MaxVoters::get() / 2) .. T::MaxVoters::get();
// those that are defunct and need removal.
let d in 0 .. (T::MaxVoters::get() / 2);
// remove any previous stuff.
clean::<T>();
let all_candidates = submit_candidates::<T>(T::MaxCandidates::get(), "candidates")?;
distribute_voters::<T>(all_candidates, v, T::MaxVotesPerVoter::get() as usize)?;
// all candidates leave.
<Candidates<T>>::kill();
// now everyone is defunct
assert!(<Voting<T>>::iter().all(|(_, v)| <Elections<T>>::is_defunct_voter(&v.votes)));
assert_eq!(<Voting<T>>::iter().count() as u32, v);
let root = RawOrigin::Root;
}: _(root, v, d)
verify {
assert_eq!(<Voting<T>>::iter().count() as u32, 0);
}
election_phragmen {
// This is just to focus on phragmen in the context of this module. We always select 20
// 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 .. T::MaxCandidates::get();
let v in 1 .. T::MaxVoters::get();
let e in (T::MaxVoters::get()) .. T::MaxVoters::get() * T::MaxVotesPerVoter::get();
clean::<T>();
// so we have a situation with v and e. we want e to basically always be in the range of `e
// -> e * T::MaxVotesPerVoter::get()`, but we cannot express that now with the benchmarks.
// So what we do is: when c is being iterated, v, and e are max and fine. when v is being
// iterated, e is being set to max and this is a problem. In these cases, we cap e to a
// lower value, namely v * T::MaxVotesPerVoter::get(). when e is being iterated, v is at
// max, and again fine. all in all, votes_per_voter can never be more than
// T::MaxVotesPerVoter::get(). Note that this might cause `v` to be an overestimate.
let votes_per_voter = (e / v).min(T::MaxVotesPerVoter::get());
let all_candidates = submit_candidates_with_self_vote::<T>(c, "candidates")?;
let _ = distribute_voters::<T>(all_candidates, v.saturating_sub(c), votes_per_voter as usize)?;
}: {
<Elections<T>>::on_initialize(T::TermDuration::get());
}
verify {
assert_eq!(<Elections<T>>::members().len() as u32, T::DesiredMembers::get().min(c));
assert_eq!(
<Elections<T>>::runners_up().len() as u32,
T::DesiredRunnersUp::get().min(c.saturating_sub(T::DesiredMembers::get())),
);
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
impl_benchmark_test_suite!(
Elections,
crate::tests::ExtBuilder::default().desired_members(13).desired_runners_up(7),
crate::tests::Test,
exec_name = build_and_execute,
);
}
File diff suppressed because it is too large Load Diff
@@ -1,25 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! All migrations of this pallet.
/// Version 3.
pub mod v3;
/// Version 4.
pub mod v4;
/// Version 5.
pub mod v5;
@@ -1,165 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Migrations to version [`3.0.0`], as denoted by the changelog.
use super::super::LOG_TARGET;
use crate::{Config, Pallet};
use codec::{Decode, Encode, FullCodec};
use frame_support::{
pallet_prelude::ValueQuery, traits::StorageVersion, weights::Weight, RuntimeDebug, Twox64Concat,
};
use sp_std::prelude::*;
#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq)]
struct SeatHolder<AccountId, Balance> {
who: AccountId,
stake: Balance,
deposit: Balance,
}
#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq)]
struct Voter<AccountId, Balance> {
votes: Vec<AccountId>,
stake: Balance,
deposit: Balance,
}
/// Trait to implement to give information about types used for migration
pub trait V2ToV3 {
/// System config account id
type AccountId: 'static + FullCodec;
/// Elections-phragmen currency balance.
type Balance: 'static + FullCodec + Copy;
}
#[frame_support::storage_alias]
type Candidates<V, T: Config> =
StorageValue<Pallet<T>, Vec<(<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance)>, ValueQuery>;
#[frame_support::storage_alias]
type Members<V, T: Config> = StorageValue<
Pallet<T>,
Vec<SeatHolder<<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance>>,
ValueQuery,
>;
#[frame_support::storage_alias]
type RunnersUp<V, T: Config> = StorageValue<
Pallet<T>,
Vec<SeatHolder<<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance>>,
ValueQuery,
>;
#[frame_support::storage_alias]
type Voting<V, T: Config> = StorageMap<
Pallet<T>,
Twox64Concat,
<V as V2ToV3>::AccountId,
Voter<<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance>,
>;
/// Apply all of the migrations from 2 to 3.
///
/// ### Warning
///
/// This code will **ONLY** check that the storage version is less than or equal to 2_0_0.
/// Further check might be needed at the user runtime.
///
/// Be aware that this migration is intended to be used only for the mentioned versions. Use
/// with care and run at your own risk.
pub fn apply<V: V2ToV3, T: Config>(
old_voter_bond: V::Balance,
old_candidacy_bond: V::Balance,
) -> Weight {
let storage_version = StorageVersion::get::<Pallet<T>>();
log::info!(
target: LOG_TARGET,
"Running migration for elections-phragmen with storage version {:?}",
storage_version,
);
if storage_version <= 2 {
migrate_voters_to_recorded_deposit::<V, T>(old_voter_bond);
migrate_candidates_to_recorded_deposit::<V, T>(old_candidacy_bond);
migrate_runners_up_to_recorded_deposit::<V, T>(old_candidacy_bond);
migrate_members_to_recorded_deposit::<V, T>(old_candidacy_bond);
StorageVersion::new(3).put::<Pallet<T>>();
Weight::MAX
} else {
log::warn!(
target: LOG_TARGET,
"Attempted to apply migration to V3 but failed because storage version is {:?}",
storage_version,
);
Weight::zero()
}
}
/// Migrate from the old legacy voting bond (fixed) to the new one (per-vote dynamic).
pub fn migrate_voters_to_recorded_deposit<V: V2ToV3, T: Config>(old_deposit: V::Balance) {
<Voting<V, T>>::translate::<(V::Balance, Vec<V::AccountId>), _>(|_who, (stake, votes)| {
Some(Voter { votes, stake, deposit: old_deposit })
});
log::info!(target: LOG_TARGET, "migrated {} voter accounts.", <Voting<V, T>>::iter().count());
}
/// Migrate all candidates to recorded deposit.
pub fn migrate_candidates_to_recorded_deposit<V: V2ToV3, T: Config>(old_deposit: V::Balance) {
let _ = <Candidates<V, T>>::translate::<Vec<V::AccountId>, _>(|maybe_old_candidates| {
maybe_old_candidates.map(|old_candidates| {
log::info!(target: LOG_TARGET, "migrated {} candidate accounts.", old_candidates.len());
old_candidates.into_iter().map(|c| (c, old_deposit)).collect::<Vec<_>>()
})
});
}
/// Migrate all members to recorded deposit.
pub fn migrate_members_to_recorded_deposit<V: V2ToV3, T: Config>(old_deposit: V::Balance) {
let _ = <Members<V, T>>::translate::<Vec<(V::AccountId, V::Balance)>, _>(|maybe_old_members| {
maybe_old_members.map(|old_members| {
log::info!(target: LOG_TARGET, "migrated {} member accounts.", old_members.len());
old_members
.into_iter()
.map(|(who, stake)| SeatHolder { who, stake, deposit: old_deposit })
.collect::<Vec<_>>()
})
});
}
/// Migrate all runners-up to recorded deposit.
pub fn migrate_runners_up_to_recorded_deposit<V: V2ToV3, T: Config>(old_deposit: V::Balance) {
let _ = <RunnersUp<V, T>>::translate::<Vec<(V::AccountId, V::Balance)>, _>(
|maybe_old_runners_up| {
maybe_old_runners_up.map(|old_runners_up| {
log::info!(
target: LOG_TARGET,
"migrated {} runner-up accounts.",
old_runners_up.len(),
);
old_runners_up
.into_iter()
.map(|(who, stake)| SeatHolder { who, stake, deposit: old_deposit })
.collect::<Vec<_>>()
})
},
);
}
@@ -1,107 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Migrations to version [`4.0.0`], as denoted by the changelog.
use super::super::LOG_TARGET;
use frame_support::{
traits::{Get, StorageVersion},
weights::Weight,
};
/// The old prefix.
pub const OLD_PREFIX: &[u8] = b"PhragmenElection";
/// Migrate the entire storage of this pallet to a new prefix.
///
/// This new prefix must be the same as the one set in construct_runtime. For safety, use
/// `PalletInfo` to get it, as:
/// `<Runtime as frame_system::Config>::PalletInfo::name::<ElectionsPhragmenPallet>`.
///
/// The old storage prefix, `PhragmenElection` is hardcoded in the migration code.
pub fn migrate<T: crate::Config, N: AsRef<str>>(new_pallet_name: N) -> Weight {
if new_pallet_name.as_ref().as_bytes() == OLD_PREFIX {
log::info!(
target: LOG_TARGET,
"New pallet name is equal to the old prefix. No migration needs to be done.",
);
return Weight::zero()
}
let storage_version = StorageVersion::get::<crate::Pallet<T>>();
log::info!(
target: LOG_TARGET,
"Running migration to v4 for elections-phragmen with storage version {:?}",
storage_version,
);
if storage_version <= 3 {
log::info!("new prefix: {}", new_pallet_name.as_ref());
frame_support::storage::migration::move_pallet(
OLD_PREFIX,
new_pallet_name.as_ref().as_bytes(),
);
StorageVersion::new(4).put::<crate::Pallet<T>>();
<T as frame_system::Config>::BlockWeights::get().max_block
} else {
log::warn!(
target: LOG_TARGET,
"Attempted to apply migration to v4 but failed because storage version is {:?}",
storage_version,
);
Weight::zero()
}
}
/// Some checks prior to migration. This can be linked to
/// [`frame_support::traits::OnRuntimeUpgrade::pre_upgrade`] for further testing.
///
/// Panics if anything goes wrong.
pub fn pre_migration<T: crate::Config, N: AsRef<str>>(new: N) {
let new = new.as_ref();
log::info!("pre-migration elections-phragmen test with new = {}", new);
// the next key must exist, and start with the hash of `OLD_PREFIX`.
let next_key = sp_io::storage::next_key(OLD_PREFIX).unwrap();
assert!(next_key.starts_with(&sp_io::hashing::twox_128(OLD_PREFIX)));
// ensure nothing is stored in the new prefix.
assert!(
sp_io::storage::next_key(new.as_bytes()).map_or(
// either nothing is there
true,
// or we ensure that it has no common prefix with twox_128(new).
|next_key| !next_key.starts_with(&sp_io::hashing::twox_128(new.as_bytes()))
),
"unexpected next_key({}) = {:?}",
new,
sp_core::hexdisplay::HexDisplay::from(&sp_io::storage::next_key(new.as_bytes()).unwrap())
);
// ensure storage version is 3.
assert_eq!(StorageVersion::get::<crate::Pallet<T>>(), 3);
}
/// Some checks for after migration. This can be linked to
/// [`frame_support::traits::OnRuntimeUpgrade::post_upgrade`] for further testing.
///
/// Panics if anything goes wrong.
pub fn post_migration<T: crate::Config>() {
log::info!("post-migration elections-phragmen");
// ensure we've been updated to v4 by the automatic write of crate version -> storage version.
assert_eq!(StorageVersion::get::<crate::Pallet<T>>(), 4);
}
@@ -1,70 +0,0 @@
use super::super::*;
/// Migrate the locks and vote stake on accounts (as specified with param `to_migrate`) that have
/// more than their free balance locked.
///
/// This migration addresses a bug were a voter could lock up to their reserved balance + free
/// balance. Since locks are only designed to operate on free balance, this put those affected in a
/// situation where they could increase their free balance but still not be able to use their funds
/// because they were less than the lock.
pub fn migrate<T: Config>(to_migrate: Vec<T::AccountId>) -> Weight {
let mut weight = Weight::zero();
for who in to_migrate.iter() {
if let Ok(mut voter) = Voting::<T>::try_get(who) {
let free_balance = T::Currency::free_balance(who);
weight = weight.saturating_add(T::DbWeight::get().reads(2));
if voter.stake > free_balance {
voter.stake = free_balance;
Voting::<T>::insert(&who, voter);
let pallet_id = T::PalletId::get();
T::Currency::set_lock(pallet_id, who, free_balance, WithdrawReasons::all());
weight = weight.saturating_add(T::DbWeight::get().writes(2));
}
}
}
weight
}
/// Given the list of voters to migrate return a function that does some checks and information
/// prior to migration. This can be linked to [`frame_support::traits::OnRuntimeUpgrade::
/// pre_upgrade`] for further testing.
pub fn pre_migrate_fn<T: Config>(to_migrate: Vec<T::AccountId>) -> Box<dyn Fn() -> ()> {
Box::new(move || {
for who in to_migrate.iter() {
if let Ok(voter) = Voting::<T>::try_get(who) {
let free_balance = T::Currency::free_balance(who);
if voter.stake > free_balance {
// all good
} else {
log::warn!("pre-migrate elections-phragmen: voter={:?} has less stake then free balance", who);
}
} else {
log::warn!("pre-migrate elections-phragmen: cannot find voter={:?}", who);
}
}
log::info!("pre-migrate elections-phragmen complete");
})
}
/// Some checks for after migration. This can be linked to
/// [`frame_support::traits::OnRuntimeUpgrade::post_upgrade`] for further testing.
///
/// Panics if anything goes wrong.
pub fn post_migrate<T: crate::Config>() {
for (who, voter) in Voting::<T>::iter() {
let free_balance = T::Currency::free_balance(&who);
assert!(voter.stake <= free_balance, "migration should have made locked <= free_balance");
// Ideally we would also check that the locks and AccountData.misc_frozen where correctly
// updated, but since both of those are generic we can't do that without further bounding T.
}
log::info!("post-migrate elections-phragmen complete");
}
@@ -1,559 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Autogenerated weights for pallet_elections_phragmen
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-02-03, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `runner-b3zmxxc-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
// Executed Command:
// target/production/substrate
// benchmark
// pallet
// --steps=50
// --repeat=20
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json
// --pallet=pallet_elections_phragmen
// --chain=dev
// --header=./HEADER-APACHE2
// --output=./frame/elections-phragmen/src/weights.rs
// --template=./.maintain/frame-weight-template.hbs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData;
/// Weight functions needed for pallet_elections_phragmen.
pub trait WeightInfo {
fn vote_equal(v: u32, ) -> Weight;
fn vote_more(v: u32, ) -> Weight;
fn vote_less(v: u32, ) -> Weight;
fn remove_voter() -> Weight;
fn submit_candidacy(c: u32, ) -> Weight;
fn renounce_candidacy_candidate(c: u32, ) -> Weight;
fn renounce_candidacy_members() -> Weight;
fn renounce_candidacy_runners_up() -> Weight;
fn remove_member_without_replacement() -> Weight;
fn remove_member_with_replacement() -> Weight;
fn clean_defunct_voters(v: u32, d: u32, ) -> Weight;
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight;
}
/// Weights for pallet_elections_phragmen using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// The range of component `v` is `[1, 16]`.
fn vote_equal(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `499 + v * (80 ±0)`
// Estimated: `9726 + v * (320 ±0)`
// Minimum execution time: 27_362 nanoseconds.
Weight::from_parts(28_497_963, 9726)
// Standard Error: 3_968
.saturating_add(Weight::from_ref_time(176_840).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(5_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(Weight::from_proof_size(320).saturating_mul(v.into()))
}
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// The range of component `v` is `[2, 16]`.
fn vote_more(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `467 + v * (80 ±0)`
// Estimated: `9598 + v * (320 ±0)`
// Minimum execution time: 37_120 nanoseconds.
Weight::from_parts(38_455_302, 9598)
// Standard Error: 5_478
.saturating_add(Weight::from_ref_time(219_678).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(5_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(Weight::from_proof_size(320).saturating_mul(v.into()))
}
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// The range of component `v` is `[2, 16]`.
fn vote_less(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `499 + v * (80 ±0)`
// Estimated: `9726 + v * (320 ±0)`
// Minimum execution time: 36_928 nanoseconds.
Weight::from_parts(38_334_669, 9726)
// Standard Error: 5_271
.saturating_add(Weight::from_ref_time(232_355).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(5_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(Weight::from_proof_size(320).saturating_mul(v.into()))
}
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
fn remove_voter() -> Weight {
// Proof Size summary in bytes:
// Measured: `989`
// Estimated: `7238`
// Minimum execution time: 34_338 nanoseconds.
Weight::from_parts(35_672_000, 7238)
.saturating_add(T::DbWeight::get().reads(2_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
}
/// Storage: Elections Candidates (r:1 w:1)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// The range of component `c` is `[1, 64]`.
fn submit_candidacy(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `1697 + c * (48 ±0)`
// Estimated: `6576 + c * (144 ±0)`
// Minimum execution time: 31_864 nanoseconds.
Weight::from_parts(33_490_161, 6576)
// Standard Error: 2_643
.saturating_add(Weight::from_ref_time(158_386).saturating_mul(c.into()))
.saturating_add(T::DbWeight::get().reads(3_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
.saturating_add(Weight::from_proof_size(144).saturating_mul(c.into()))
}
/// Storage: Elections Candidates (r:1 w:1)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// The range of component `c` is `[1, 64]`.
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `349 + c * (48 ±0)`
// Estimated: `844 + c * (48 ±0)`
// Minimum execution time: 27_292 nanoseconds.
Weight::from_parts(28_364_955, 844)
// Standard Error: 1_335
.saturating_add(Weight::from_ref_time(78_086).saturating_mul(c.into()))
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
.saturating_add(Weight::from_proof_size(48).saturating_mul(c.into()))
}
/// Storage: Elections Members (r:1 w:1)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Prime (r:1 w:1)
/// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Proposals (r:1 w:0)
/// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Members (r:0 w:1)
/// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured)
fn renounce_candidacy_members() -> Weight {
// Proof Size summary in bytes:
// Measured: `2027`
// Estimated: `12115`
// Minimum execution time: 45_975 nanoseconds.
Weight::from_parts(47_103_000, 12115)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(4_u64))
}
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
fn renounce_candidacy_runners_up() -> Weight {
// Proof Size summary in bytes:
// Measured: `975`
// Estimated: `1470`
// Minimum execution time: 29_243 nanoseconds.
Weight::from_parts(30_582_000, 1470)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: Benchmark Override (r:0 w:0)
/// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured)
fn remove_member_without_replacement() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 2_000_000_000 nanoseconds.
Weight::from_ref_time(2_000_000_000_000)
}
/// Storage: Elections Members (r:1 w:1)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Prime (r:1 w:1)
/// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Proposals (r:1 w:0)
/// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Members (r:0 w:1)
/// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured)
fn remove_member_with_replacement() -> Weight {
// Proof Size summary in bytes:
// Measured: `2027`
// Estimated: `14718`
// Minimum execution time: 52_527 nanoseconds.
Weight::from_parts(53_538_000, 14718)
.saturating_add(T::DbWeight::get().reads(5_u64))
.saturating_add(T::DbWeight::get().writes(5_u64))
}
/// Storage: Elections Voting (r:513 w:512)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Balances Locks (r:512 w:512)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// Storage: System Account (r:512 w:512)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// The range of component `v` is `[256, 512]`.
/// The range of component `d` is `[0, 256]`.
fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `1115 + v * (875 ±0)`
// Estimated: `8448 + v * (12352 ±0)`
// Minimum execution time: 14_934_185 nanoseconds.
Weight::from_parts(15_014_057_000, 8448)
// Standard Error: 245_588
.saturating_add(Weight::from_ref_time(35_586_946).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(v.into())))
.saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into())))
.saturating_add(Weight::from_proof_size(12352).saturating_mul(v.into()))
}
/// Storage: Elections Candidates (r:1 w:1)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:1)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:513 w:0)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Council Proposals (r:1 w:0)
/// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: System Account (r:44 w:44)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// Storage: Elections ElectionRounds (r:1 w:1)
/// Proof Skipped: Elections ElectionRounds (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Members (r:0 w:1)
/// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Prime (r:0 w:1)
/// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured)
/// The range of component `c` is `[1, 64]`.
/// The range of component `v` is `[1, 512]`.
/// The range of component `e` is `[512, 8192]`.
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + v * (638 ±0) + e * (28 ±0)`
// Estimated: `330033 + v * (5229 ±6) + e * (89 ±0) + c * (2135 ±7)`
// Minimum execution time: 1_273_671 nanoseconds.
Weight::from_parts(1_279_716_000, 330033)
// Standard Error: 543_277
.saturating_add(Weight::from_ref_time(20_613_753).saturating_mul(v.into()))
// Standard Error: 34_857
.saturating_add(Weight::from_ref_time(688_354).saturating_mul(e.into()))
.saturating_add(T::DbWeight::get().reads(21_u64))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into())))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into())))
.saturating_add(T::DbWeight::get().writes(6_u64))
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into())))
.saturating_add(Weight::from_proof_size(5229).saturating_mul(v.into()))
.saturating_add(Weight::from_proof_size(89).saturating_mul(e.into()))
.saturating_add(Weight::from_proof_size(2135).saturating_mul(c.into()))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// The range of component `v` is `[1, 16]`.
fn vote_equal(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `499 + v * (80 ±0)`
// Estimated: `9726 + v * (320 ±0)`
// Minimum execution time: 27_362 nanoseconds.
Weight::from_parts(28_497_963, 9726)
// Standard Error: 3_968
.saturating_add(Weight::from_ref_time(176_840).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(Weight::from_proof_size(320).saturating_mul(v.into()))
}
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// The range of component `v` is `[2, 16]`.
fn vote_more(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `467 + v * (80 ±0)`
// Estimated: `9598 + v * (320 ±0)`
// Minimum execution time: 37_120 nanoseconds.
Weight::from_parts(38_455_302, 9598)
// Standard Error: 5_478
.saturating_add(Weight::from_ref_time(219_678).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(Weight::from_proof_size(320).saturating_mul(v.into()))
}
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// The range of component `v` is `[2, 16]`.
fn vote_less(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `499 + v * (80 ±0)`
// Estimated: `9726 + v * (320 ±0)`
// Minimum execution time: 36_928 nanoseconds.
Weight::from_parts(38_334_669, 9726)
// Standard Error: 5_271
.saturating_add(Weight::from_ref_time(232_355).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(Weight::from_proof_size(320).saturating_mul(v.into()))
}
/// Storage: Elections Voting (r:1 w:1)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:1 w:1)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
fn remove_voter() -> Weight {
// Proof Size summary in bytes:
// Measured: `989`
// Estimated: `7238`
// Minimum execution time: 34_338 nanoseconds.
Weight::from_parts(35_672_000, 7238)
.saturating_add(RocksDbWeight::get().reads(2_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
}
/// Storage: Elections Candidates (r:1 w:1)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// The range of component `c` is `[1, 64]`.
fn submit_candidacy(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `1697 + c * (48 ±0)`
// Estimated: `6576 + c * (144 ±0)`
// Minimum execution time: 31_864 nanoseconds.
Weight::from_parts(33_490_161, 6576)
// Standard Error: 2_643
.saturating_add(Weight::from_ref_time(158_386).saturating_mul(c.into()))
.saturating_add(RocksDbWeight::get().reads(3_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
.saturating_add(Weight::from_proof_size(144).saturating_mul(c.into()))
}
/// Storage: Elections Candidates (r:1 w:1)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// The range of component `c` is `[1, 64]`.
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `349 + c * (48 ±0)`
// Estimated: `844 + c * (48 ±0)`
// Minimum execution time: 27_292 nanoseconds.
Weight::from_parts(28_364_955, 844)
// Standard Error: 1_335
.saturating_add(Weight::from_ref_time(78_086).saturating_mul(c.into()))
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
.saturating_add(Weight::from_proof_size(48).saturating_mul(c.into()))
}
/// Storage: Elections Members (r:1 w:1)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Prime (r:1 w:1)
/// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Proposals (r:1 w:0)
/// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Members (r:0 w:1)
/// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured)
fn renounce_candidacy_members() -> Weight {
// Proof Size summary in bytes:
// Measured: `2027`
// Estimated: `12115`
// Minimum execution time: 45_975 nanoseconds.
Weight::from_parts(47_103_000, 12115)
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().writes(4_u64))
}
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
fn renounce_candidacy_runners_up() -> Weight {
// Proof Size summary in bytes:
// Measured: `975`
// Estimated: `1470`
// Minimum execution time: 29_243 nanoseconds.
Weight::from_parts(30_582_000, 1470)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: Benchmark Override (r:0 w:0)
/// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured)
fn remove_member_without_replacement() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 2_000_000_000 nanoseconds.
Weight::from_ref_time(2_000_000_000_000)
}
/// Storage: Elections Members (r:1 w:1)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Prime (r:1 w:1)
/// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Proposals (r:1 w:0)
/// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Members (r:0 w:1)
/// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured)
fn remove_member_with_replacement() -> Weight {
// Proof Size summary in bytes:
// Measured: `2027`
// Estimated: `14718`
// Minimum execution time: 52_527 nanoseconds.
Weight::from_parts(53_538_000, 14718)
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(5_u64))
}
/// Storage: Elections Voting (r:513 w:512)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:0)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:0)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Candidates (r:1 w:0)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Balances Locks (r:512 w:512)
/// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen)
/// Storage: System Account (r:512 w:512)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// The range of component `v` is `[256, 512]`.
/// The range of component `d` is `[0, 256]`.
fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `1115 + v * (875 ±0)`
// Estimated: `8448 + v * (12352 ±0)`
// Minimum execution time: 14_934_185 nanoseconds.
Weight::from_parts(15_014_057_000, 8448)
// Standard Error: 245_588
.saturating_add(Weight::from_ref_time(35_586_946).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(v.into())))
.saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(v.into())))
.saturating_add(Weight::from_proof_size(12352).saturating_mul(v.into()))
}
/// Storage: Elections Candidates (r:1 w:1)
/// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Members (r:1 w:1)
/// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections RunnersUp (r:1 w:1)
/// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Elections Voting (r:513 w:0)
/// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured)
/// Storage: Council Proposals (r:1 w:0)
/// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: System Account (r:44 w:44)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// Storage: Elections ElectionRounds (r:1 w:1)
/// Proof Skipped: Elections ElectionRounds (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Members (r:0 w:1)
/// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: Council Prime (r:0 w:1)
/// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured)
/// The range of component `c` is `[1, 64]`.
/// The range of component `v` is `[1, 512]`.
/// The range of component `e` is `[512, 8192]`.
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + v * (638 ±0) + e * (28 ±0)`
// Estimated: `330033 + v * (5229 ±6) + e * (89 ±0) + c * (2135 ±7)`
// Minimum execution time: 1_273_671 nanoseconds.
Weight::from_parts(1_279_716_000, 330033)
// Standard Error: 543_277
.saturating_add(Weight::from_ref_time(20_613_753).saturating_mul(v.into()))
// Standard Error: 34_857
.saturating_add(Weight::from_ref_time(688_354).saturating_mul(e.into()))
.saturating_add(RocksDbWeight::get().reads(21_u64))
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(c.into())))
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into())))
.saturating_add(RocksDbWeight::get().writes(6_u64))
.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(c.into())))
.saturating_add(Weight::from_proof_size(5229).saturating_mul(v.into()))
.saturating_add(Weight::from_proof_size(89).saturating_mul(e.into()))
.saturating_add(Weight::from_proof_size(2135).saturating_mul(c.into()))
}
}