Fix elections-phragmen and proxy issue (#7040)

* Fix elections-phragmen and proxy issue

* remove TODO

* Update bond to be per-vote

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

* Fix benchmakrs

* Fix weight as well.

* Add license

* Make weight interpreted wasm! 🤦🏻‍♂️

* Remove a bunch of TODOs

* Add migration

* Better storage version.

* Functionify.

* Fix deposit scheme.

* remove legacy bond.

* Master.into()

* better logging.

* Fix benchmarking test

* Fix confused deposit collection.

* Add fine

* Better name for storage item

* Fix name again.

* remove unused

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

Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>

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

Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>

* cargo run --release --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml -- benchmark --chain dev --steps 50 --repeat 20 --extrinsic * --execution=wasm --wasm-execution=compiled --output ./bin/node/runtime/src/weights --header ./HEADER --pallet pallet_elections_phragmen

* new weight fns

* Fix build

* Fix line width

* fix benchmakrs

* fix warning

* cargo run --release --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml -- benchmark --chain dev --steps 50 --repeat 20 --extrinsic * --execution=wasm --wasm-execution=compiled --output ./bin/node/runtime/src/weights --header ./HEADER --pallet pallet_elections_phragmen

* Tune the stake again

* cargo run --release --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml -- benchmark --chain dev --steps 50 --repeat 20 --extrinsic * --execution=wasm --wasm-execution=compiled --output ./bin/node/runtime/src/weights --header ./HEADER --pallet pallet_elections_phragmen

* All tests work again.

* A large number of fixes.

* more fixes.

* Fix node build

* Some fixes to benchmarks

* Fix some warnings.

* cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_elections_phragmen --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/elections-phragmen/src/weights.rs --template=./.maintain/frame-weight-template.hbs

* cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_elections_phragmen --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/elections-phragmen/src/weights.rs --template=./.maintain/frame-weight-template.hbs

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

Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>

* a batch of review comments.

* Fix a test.

* Fix some more tests.

* do migration with pallet version???

* Final touches.

* Remove unused storage.

* another rounds of changes and fixes.

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

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

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

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* Review grumbles.

* Fix a bit more.

* Fix build

* Experimental: independent migration.

* WIP: isolated migration logics

* clean up.

* make migration struct private and move migration to own file

* add doc

* fix StorageInstance new syntax

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

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* another round of self-review.

* bit better formatting

* cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_elections_phragmen --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/elections-phragmen/src/weights.rs --template=./.maintain/frame-weight-template.hbs

* Fix tests.

* Round of self-review

* Clean migrations

* cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_elections_phragmen --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/elections-phragmen/src/weights.rs --template=./.maintain/frame-weight-template.hbs

* Revert unwanted change to construct-runtime

Co-authored-by: Gavin Wood <gavin@parity.io>
Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Parity Benchmarking Bot <admin@parity.io>
This commit is contained in:
Kian Paimani
2021-01-20 14:19:49 +00:00
committed by GitHub
parent fb5f945a01
commit e8307b7b57
11 changed files with 1678 additions and 1303 deletions
@@ -0,0 +1,24 @@
# 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).
## [3.0.0] - UNRELEASED
### 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,6 +1,6 @@
[package]
name = "pallet-elections-phragmen"
version = "2.0.1"
version = "3.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "Apache-2.0"
@@ -69,20 +69,6 @@ fn candidate_count<T: Config>() -> u32 {
<Candidates<T>>::decode_len().unwrap_or(0usize) as u32
}
/// Get the number of votes of a voter.
fn vote_count_of<T: Config>(who: &T::AccountId) -> u32 {
<Voting<T>>::get(who).1.len() as u32
}
/// A `DefunctVoter` struct with correct value
fn defunct_for<T: Config>(who: T::AccountId) -> DefunctVoter<Lookup<T>> {
DefunctVoter {
who: as_lookup::<T>(who.clone()),
candidate_count: candidate_count::<T>(),
vote_count: vote_count_of::<T>(&who),
}
}
/// Add `c` new candidates.
fn submit_candidates<T: Config>(c: u32, prefix: &'static str)
-> Result<Vec<T::AccountId>, &'static str>
@@ -104,7 +90,7 @@ fn submit_candidates_with_self_vote<T: Config>(c: u32, prefix: &'static str)
let candidates = submit_candidates::<T>(c, prefix)?;
let stake = default_stake::<T>(BALANCE_FACTOR);
let _ = candidates.iter().map(|c|
submit_voter::<T>(c.clone(), vec![c.clone()], stake)
submit_voter::<T>(c.clone(), vec![c.clone()], stake).map(|_| ())
).collect::<Result<_, _>>()?;
Ok(candidates)
}
@@ -112,7 +98,7 @@ fn submit_candidates_with_self_vote<T: Config>(c: u32, prefix: &'static str)
/// Submit one voter.
fn submit_voter<T: Config>(caller: T::AccountId, votes: Vec<T::AccountId>, stake: BalanceOf<T>)
-> Result<(), sp_runtime::DispatchError>
-> frame_support::dispatch::DispatchResult
{
<Elections<T>>::vote(RawOrigin::Signed(caller).into(), votes, stake)
}
@@ -152,8 +138,8 @@ fn fill_seats_up_to<T: Config>(m: u32) -> Result<Vec<T::AccountId>, &'static str
Ok(
<Elections<T>>::members()
.into_iter()
.map(|(x, _)| x)
.chain(<Elections<T>>::runners_up().into_iter().map(|(x, _)| x))
.map(|m| m.who)
.chain(<Elections<T>>::runners_up().into_iter().map(|r| r.who))
.collect()
)
}
@@ -163,28 +149,12 @@ fn clean<T: Config>() {
<Members<T>>::kill();
<Candidates<T>>::kill();
<RunnersUp<T>>::kill();
let _ = <Voting<T>>::drain();
<Voting<T>>::remove_all();
}
benchmarks! {
// -- Signed ones
vote {
let v in 1 .. (MAXIMUM_VOTE as u32);
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>(BALANCE_FACTOR);
// vote for all of them.
let votes = all_candidates;
whitelist!(caller);
}: _(RawOrigin::Signed(caller), votes, stake)
vote_update {
vote_equal {
let v in 1 .. (MAXIMUM_VOTE as u32);
clean::<T>();
@@ -204,6 +174,48 @@ benchmarks! {
whitelist!(caller);
}: vote(RawOrigin::Signed(caller), votes, stake)
vote_more {
let v in 2 .. (MAXIMUM_VOTE as u32);
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>(BALANCE_FACTOR);
// 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 .. (MAXIMUM_VOTE as u32);
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>(BALANCE_FACTOR);
// 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 = MAXIMUM_VOTE as u32;
@@ -220,123 +232,6 @@ benchmarks! {
whitelist!(caller);
}: _(RawOrigin::Signed(caller))
report_defunct_voter_correct {
// number of already existing candidates that may or may not be voted by the reported
// account.
let c in 1 .. MAX_CANDIDATES;
// number of candidates that the reported voter voted for. The worse case of search here is
// basically `c * v`.
let v in 1 .. (MAXIMUM_VOTE as u32);
// 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>(BALANCE_FACTOR);
// create m members and runners combined.
let _ = fill_seats_up_to::<T>(m)?;
// create a bunch of candidates as well.
let bailing_candidates = submit_candidates::<T>(v, "bailing_candidates")?;
let all_candidates = submit_candidates::<T>(c, "all_candidates")?;
// account 1 is the reporter and must be whitelisted, and a voter.
let account_1 = endowed_account::<T>("caller", 0);
submit_voter::<T>(
account_1.clone(),
all_candidates.iter().take(1).cloned().collect(),
stake,
)?;
// account 2 votes for all of the mentioned candidates.
let account_2 = endowed_account::<T>("caller_2", 1);
submit_voter::<T>(
account_2.clone(),
bailing_candidates.clone(),
stake,
)?;
// all the bailers go away. NOTE: we can simplify this. There's no need to create all these
// candidates and remove them. The defunct voter can just vote for random accounts as long
// as there are enough members (potential candidates).
bailing_candidates.into_iter().for_each(|b| {
let count = candidate_count::<T>();
assert!(<Elections<T>>::renounce_candidacy(
RawOrigin::Signed(b).into(),
Renouncing::Candidate(count),
).is_ok());
});
let defunct_info = defunct_for::<T>(account_2.clone());
whitelist!(account_1);
assert!(<Elections<T>>::is_voter(&account_2));
}: report_defunct_voter(RawOrigin::Signed(account_1.clone()), defunct_info)
verify {
assert!(!<Elections<T>>::is_voter(&account_2));
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
report_defunct_voter_incorrect {
// number of already existing candidates that may or may not be voted by the reported
// account.
let c in 1 .. MAX_CANDIDATES;
// number of candidates that the reported voter voted for. The worse case of search here is
// basically `c * v`.
let v in 1 .. (MAXIMUM_VOTE as u32);
// 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>(BALANCE_FACTOR);
// create m members and runners combined.
let _ = fill_seats_up_to::<T>(m)?;
// create a bunch of candidates as well.
let all_candidates = submit_candidates::<T>(c, "candidates")?;
// account 1 is the reporter and need to be whitelisted, and a voter.
let account_1 = endowed_account::<T>("caller", 0);
submit_voter::<T>(
account_1.clone(),
all_candidates.iter().take(1).cloned().collect(),
stake,
)?;
// account 2 votes for a bunch of crap, and finally a correct candidate.
let account_2 = endowed_account::<T>("caller_2", 1);
let mut invalid: Vec<T::AccountId> = (0..(v-1))
.map(|seed| account::<T::AccountId>("invalid", 0, seed).clone())
.collect();
invalid.push(all_candidates.last().unwrap().clone());
submit_voter::<T>(
account_2.clone(),
invalid,
stake,
)?;
let defunct_info = defunct_for::<T>(account_2.clone());
whitelist!(account_1);
}: report_defunct_voter(RawOrigin::Signed(account_1.clone()), defunct_info)
verify {
// account 2 is still a voter.
assert!(<Elections<T>>::is_voter(&account_2));
#[cfg(test)]
{
// reset members in between benchmark tests.
use crate::tests::MEMBERS;
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
submit_candidacy {
// number of already existing candidates.
let c in 1 .. MAX_CANDIDATES;
@@ -519,20 +414,52 @@ benchmarks! {
}
}
#[extra]
on_initialize {
// if n % TermDuration is zero, then we run phragmen. The weight function must and should
// check this as it is cheap to do so. TermDuration is not a storage item, it is a constant
// encoded in the runtime.
let c in 1 .. MAX_CANDIDATES;
clean_defunct_voters {
// total number of voters.
let v in (MAX_VOTERS / 2) .. MAX_VOTERS;
// those that are defunct and need removal.
let d in 1 .. (MAX_VOTERS / 2);
// remove any previous stuff.
clean::<T>();
// create c candidates.
let all_candidates = submit_candidates::<T>(v, "candidates")?;
distribute_voters::<T>(all_candidates, v, MAXIMUM_VOTE)?;
// 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 .. MAX_CANDIDATES;
let v in 1 .. MAX_VOTERS;
let e in MAX_VOTERS .. MAX_VOTERS * 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
// -> e * MAXIMUM_VOTE`, 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 * MAXIMUM_VOTE. when e is being iterated, v is at max, and again fine. all in all,
// votes_per_voter can never be more than MAXIMUM_VOTE. Note that this might cause `v` to be
// an overestimate.
let votes_per_voter = (e / v).min(MAXIMUM_VOTE as u32);
let all_candidates = submit_candidates_with_self_vote::<T>(c, "candidates")?;
// create 500 voters, each voting the maximum 16
distribute_voters::<T>(all_candidates, MAX_VOTERS, MAXIMUM_VOTE)?;
let _ = distribute_voters::<T>(all_candidates, v, votes_per_voter as usize)?;
}: {
// elect
<Elections<T>>::on_initialize(T::TermDuration::get());
}
verify {
@@ -551,18 +478,16 @@ benchmarks! {
}
#[extra]
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.
election_phragmen_c_e {
let c in 1 .. MAX_CANDIDATES;
let v in 1 .. MAX_VOTERS;
let e in 1 .. (MAXIMUM_VOTE as u32);
let e in MAX_VOTERS .. MAX_VOTERS * MAXIMUM_VOTE as u32;
let fixed_v = MAX_VOTERS;
clean::<T>();
let votes_per_voter = e / fixed_v;
let all_candidates = submit_candidates_with_self_vote::<T>(c, "candidates")?;
let _ = distribute_voters::<T>(all_candidates, v, e as usize)?;
let _ = distribute_voters::<T>(all_candidates, fixed_v, votes_per_voter as usize)?;
}: {
<Elections<T>>::on_initialize(T::TermDuration::get());
}
@@ -580,6 +505,35 @@ benchmarks! {
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
}
}
#[extra]
election_phragmen_v {
let v in 4 .. 16;
let fixed_c = MAX_CANDIDATES;
let fixed_e = 64;
clean::<T>();
let votes_per_voter = fixed_e / v;
let all_candidates = submit_candidates_with_self_vote::<T>(fixed_c, "candidates")?;
let _ = distribute_voters::<T>(all_candidates, v, 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(fixed_c));
assert_eq!(
<Elections<T>>::runners_up().len() as u32,
T::DesiredRunnersUp::get().min(fixed_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![]);
}
}
}
#[cfg(test)]
@@ -590,21 +544,33 @@ mod tests {
#[test]
fn test_benchmarks_elections_phragmen() {
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_vote::<Test>());
});
ExtBuilder::default()
.desired_members(13)
.desired_runners_up(7)
.build_and_execute(|| {
assert_ok!(test_benchmark_vote_equal::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_remove_voter::<Test>());
});
ExtBuilder::default()
.desired_members(13)
.desired_runners_up(7)
.build_and_execute(|| {
assert_ok!(test_benchmark_vote_more::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_report_defunct_voter_correct::<Test>());
});
ExtBuilder::default()
.desired_members(13)
.desired_runners_up(7)
.build_and_execute(|| {
assert_ok!(test_benchmark_vote_less::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_report_defunct_voter_incorrect::<Test>());
});
ExtBuilder::default()
.desired_members(13)
.desired_runners_up(7)
.build_and_execute(|| {
assert_ok!(test_benchmark_remove_voter::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_submit_candidacy::<Test>());
@@ -631,11 +597,23 @@ mod tests {
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_on_initialize::<Test>());
assert_ok!(test_benchmark_clean_defunct_voters::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_phragmen::<Test>());
assert_ok!(test_benchmark_election_phragmen::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_election_phragmen::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_election_phragmen_c_e::<Test>());
});
ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| {
assert_ok!(test_benchmark_election_phragmen_v::<Test>());
});
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,195 @@
// This file is part of Substrate.
// Copyright (C) 2019-2020 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 codec::{Encode, Decode, FullCodec};
use sp_std::prelude::*;
use frame_support::{
RuntimeDebug, weights::Weight, Twox64Concat,
storage::types::{StorageMap, StorageValue},
traits::{GetPalletVersion, PalletVersion},
};
#[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 {
/// elections-phragmen module, used to check storage version.
type Module: GetPalletVersion;
/// System config account id
type AccountId: 'static + FullCodec;
/// Elections-phragmen currency balance.
type Balance: 'static + FullCodec + Copy;
}
struct __Candidates;
impl frame_support::traits::StorageInstance for __Candidates {
fn pallet_prefix() -> &'static str { "PhragmenElection" }
const STORAGE_PREFIX: &'static str = "Candidates";
}
#[allow(type_alias_bounds)]
type Candidates<T: V2ToV3> = StorageValue<__Candidates, Vec<(T::AccountId, T::Balance)>>;
struct __Members;
impl frame_support::traits::StorageInstance for __Members {
fn pallet_prefix() -> &'static str { "PhragmenElection" }
const STORAGE_PREFIX: &'static str = "Members";
}
#[allow(type_alias_bounds)]
type Members<T: V2ToV3> = StorageValue<__Members, Vec<SeatHolder<T::AccountId, T::Balance>>>;
struct __RunnersUp;
impl frame_support::traits::StorageInstance for __RunnersUp {
fn pallet_prefix() -> &'static str { "PhragmenElection" }
const STORAGE_PREFIX: &'static str = "RunnersUp";
}
#[allow(type_alias_bounds)]
type RunnersUp<T: V2ToV3> = StorageValue<__RunnersUp, Vec<SeatHolder<T::AccountId, T::Balance>>>;
struct __Voting;
impl frame_support::traits::StorageInstance for __Voting {
fn pallet_prefix() -> &'static str { "PhragmenElection" }
const STORAGE_PREFIX: &'static str = "Voting";
}
#[allow(type_alias_bounds)]
type Voting<T: V2ToV3> = StorageMap<__Voting, Twox64Concat, T::AccountId, Voter<T::AccountId, T::Balance>>;
/// Apply all of the migrations from 2_0_0 to 3_0_0.
///
/// ### 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<T: V2ToV3>(old_voter_bond: T::Balance, old_candidacy_bond: T::Balance) -> Weight {
let maybe_storage_version = <T::Module as GetPalletVersion>::storage_version();
frame_support::debug::info!(
"Running migration for elections-phragmen with storage version {:?}",
maybe_storage_version
);
match maybe_storage_version {
Some(storage_version) if storage_version <= PalletVersion::new(2, 0, 0) => {
migrate_voters_to_recorded_deposit::<T>(old_voter_bond);
migrate_candidates_to_recorded_deposit::<T>(old_candidacy_bond);
migrate_runners_up_to_recorded_deposit::<T>(old_candidacy_bond);
migrate_members_to_recorded_deposit::<T>(old_candidacy_bond);
Weight::max_value()
}
_ => {
frame_support::debug::warn!(
"Attempted to apply migration to V3 but failed because storage version is {:?}",
maybe_storage_version
);
0
},
}
}
/// Migrate from the old legacy voting bond (fixed) to the new one (per-vote dynamic).
pub fn migrate_voters_to_recorded_deposit<T: V2ToV3>(old_deposit: T::Balance) {
<Voting<T>>::translate::<(T::Balance, Vec<T::AccountId>), _>(
|_who, (stake, votes)| {
Some(Voter {
votes,
stake,
deposit: old_deposit,
})
},
);
frame_support::debug::info!(
"migrated {} voter accounts.",
<Voting<T>>::iter().count(),
);
}
/// Migrate all candidates to recorded deposit.
pub fn migrate_candidates_to_recorded_deposit<T: V2ToV3>(old_deposit: T::Balance) {
let _ = <Candidates<T>>::translate::<Vec<T::AccountId>, _>(
|maybe_old_candidates| {
maybe_old_candidates.map(|old_candidates| {
frame_support::debug::info!(
"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<T: V2ToV3>(old_deposit: T::Balance) {
let _ = <Members<T>>::translate::<Vec<(T::AccountId, T::Balance)>, _>(
|maybe_old_members| {
maybe_old_members.map(|old_members| {
frame_support::debug::info!("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<T: V2ToV3>(old_deposit: T::Balance) {
let _ = <RunnersUp<T>>::translate::<Vec<(T::AccountId, T::Balance)>, _>(
|maybe_old_runners_up| {
maybe_old_runners_up.map(|old_runners_up| {
frame_support::debug::info!(
"migrated {} runner-up accounts.",
old_runners_up.len()
);
old_runners_up
.into_iter()
.map(|(who, stake)| SeatHolder {
who,
stake,
deposit: old_deposit,
})
.collect::<Vec<_>>()
})
},
);
}
+112 -97
View File
@@ -1,6 +1,6 @@
// This file is part of Substrate.
// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Weights for pallet_elections_phragmen
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0
//! DATE: 2020-10-27, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
//! Autogenerated weights for pallet_elections_phragmen
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1
//! DATE: 2021-01-20, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
// Executed Command:
@@ -43,173 +44,187 @@ use sp_std::marker::PhantomData;
/// Weight functions needed for pallet_elections_phragmen.
pub trait WeightInfo {
fn vote(_v: u32, ) -> Weight;
fn vote_update(_v: u32, ) -> Weight;
fn vote_equal(v: u32, ) -> Weight;
fn vote_more(v: u32, ) -> Weight;
fn vote_less(v: u32, ) -> Weight;
fn remove_voter() -> Weight;
fn report_defunct_voter_correct(_c: u32, _v: u32, ) -> Weight;
fn report_defunct_voter_incorrect(_c: u32, _v: u32, ) -> Weight;
fn submit_candidacy(_c: u32, ) -> Weight;
fn renounce_candidacy_candidate(_c: u32, ) -> 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_with_replacement() -> Weight;
fn remove_member_wrong_refund() -> 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> {
fn vote(v: u32, ) -> Weight {
(89_627_000 as Weight)
.saturating_add((197_000 as Weight).saturating_mul(v as Weight))
fn vote_equal(v: u32, ) -> Weight {
(45_157_000 as Weight)
// Standard Error: 6_000
.saturating_add((399_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))
}
fn vote_update(v: u32, ) -> Weight {
(54_724_000 as Weight)
.saturating_add((213_000 as Weight).saturating_mul(v as Weight))
fn vote_more(v: u32, ) -> Weight {
(69_738_000 as Weight)
// Standard Error: 14_000
.saturating_add((450_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))
}
fn vote_less(v: u32, ) -> Weight {
(73_955_000 as Weight)
// Standard Error: 38_000
.saturating_add((227_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))
}
fn remove_voter() -> Weight {
(73_774_000 as Weight)
(68_398_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn report_defunct_voter_correct(c: u32, v: u32, ) -> Weight {
(0 as Weight)
.saturating_add((1_746_000 as Weight).saturating_mul(c as Weight))
.saturating_add((31_383_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn report_defunct_voter_incorrect(c: u32, v: u32, ) -> Weight {
(0 as Weight)
.saturating_add((1_725_000 as Weight).saturating_mul(c as Weight))
.saturating_add((31_293_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn submit_candidacy(c: u32, ) -> Weight {
(73_403_000 as Weight)
.saturating_add((314_000 as Weight).saturating_mul(c as Weight))
(59_291_000 as Weight)
// Standard Error: 2_000
.saturating_add((412_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))
}
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
(48_834_000 as Weight)
.saturating_add((187_000 as Weight).saturating_mul(c as Weight))
(55_026_000 as Weight)
// Standard Error: 2_000
.saturating_add((207_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))
}
fn renounce_candidacy_members() -> Weight {
(78_402_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
(77_840_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
fn renounce_candidacy_runners_up() -> Weight {
(49_054_000 as Weight)
(54_559_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn remove_member_with_replacement() -> Weight {
(75_421_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
(84_311_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
fn remove_member_wrong_refund() -> Weight {
(8_489_000 as Weight)
(7_677_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
}
fn clean_defunct_voters(v: u32, d: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 55_000
.saturating_add((114_815_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 53_000
.saturating_add((49_000 as Weight).saturating_mul(d 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)))
}
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 1_940_000
.saturating_add((43_557_000 as Weight).saturating_mul(c as Weight))
// Standard Error: 807_000
.saturating_add((65_849_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 55_000
.saturating_add((4_206_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads((2 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)))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
fn vote(v: u32, ) -> Weight {
(89_627_000 as Weight)
.saturating_add((197_000 as Weight).saturating_mul(v as Weight))
fn vote_equal(v: u32, ) -> Weight {
(45_157_000 as Weight)
// Standard Error: 6_000
.saturating_add((399_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn vote_update(v: u32, ) -> Weight {
(54_724_000 as Weight)
.saturating_add((213_000 as Weight).saturating_mul(v as Weight))
fn vote_more(v: u32, ) -> Weight {
(69_738_000 as Weight)
// Standard Error: 14_000
.saturating_add((450_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn vote_less(v: u32, ) -> Weight {
(73_955_000 as Weight)
// Standard Error: 38_000
.saturating_add((227_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn remove_voter() -> Weight {
(73_774_000 as Weight)
(68_398_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn report_defunct_voter_correct(c: u32, v: u32, ) -> Weight {
(0 as Weight)
.saturating_add((1_746_000 as Weight).saturating_mul(c as Weight))
.saturating_add((31_383_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn report_defunct_voter_incorrect(c: u32, v: u32, ) -> Weight {
(0 as Weight)
.saturating_add((1_725_000 as Weight).saturating_mul(c as Weight))
.saturating_add((31_293_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn submit_candidacy(c: u32, ) -> Weight {
(73_403_000 as Weight)
.saturating_add((314_000 as Weight).saturating_mul(c as Weight))
(59_291_000 as Weight)
// Standard Error: 2_000
.saturating_add((412_000 as Weight).saturating_mul(c as Weight))
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
(48_834_000 as Weight)
.saturating_add((187_000 as Weight).saturating_mul(c as Weight))
(55_026_000 as Weight)
// Standard Error: 2_000
.saturating_add((207_000 as Weight).saturating_mul(c as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn renounce_candidacy_members() -> Weight {
(78_402_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
(77_840_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
fn renounce_candidacy_runners_up() -> Weight {
(49_054_000 as Weight)
(54_559_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn remove_member_with_replacement() -> Weight {
(75_421_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
(84_311_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
fn remove_member_wrong_refund() -> Weight {
(8_489_000 as Weight)
(7_677_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
}
fn clean_defunct_voters(v: u32, d: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 55_000
.saturating_add((114_815_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 53_000
.saturating_add((49_000 as Weight).saturating_mul(d 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)))
}
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 1_940_000
.saturating_add((43_557_000 as Weight).saturating_mul(c as Weight))
// Standard Error: 807_000
.saturating_add((65_849_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 55_000
.saturating_add((4_206_000 as Weight).saturating_mul(e as Weight))
.saturating_add(RocksDbWeight::get().reads((2 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)))
}
}