feat: Rebrand Polkadot/Substrate references to PezkuwiChain

This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
@@ -0,0 +1,35 @@
# 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 pezpallet-elections-phragmen to attribute macros](https://github.com/pezkuwichain/kurdistan-sdk/issues/75)
### Fixed
### Security
## [3.0.0]
### Added
[Add slashing events to elections-phragmen](https://github.com/pezkuwichain/kurdistan-sdk/issues/70)
### Changed
### Fixed
[Don't slash all outgoing members](https://github.com/pezkuwichain/kurdistan-sdk/issues/68)
[Fix wrong outgoing calculation in election](https://github.com/pezkuwichain/kurdistan-sdk/issues/67)
### Security
\[**Needs Migration**\] [Fix elections-phragmen and proxy issue + Record deposits on-chain](https://github.com/pezkuwichain/kurdistan-sdk/issues/59)
## [2.0.0] - 2020-09-2020
Initial version from which version tracking has begun.
@@ -0,0 +1,69 @@
[package]
name = "pezpallet-elections-phragmen"
version = "29.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "FRAME pallet based on seq-Phragmén election method."
readme = "README.md"
[lints]
workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { features = ["derive"], workspace = true }
pezframe-benchmarking = { optional = true, workspace = true }
pezframe-support = { workspace = true }
pezframe-system = { workspace = true }
log = { workspace = true }
scale-info = { features = ["derive"], workspace = true }
pezsp-core = { workspace = true }
pezsp-io = { workspace = true }
pezsp-npos-elections = { workspace = true }
pezsp-runtime = { workspace = true }
pezsp-staking = { workspace = true }
[dev-dependencies]
pezpallet-balances = { workspace = true, default-features = true }
pezsp-core = { workspace = true, default-features = true }
pezsp-tracing = { workspace = true, default-features = true }
bizinikiwi-test-utils = { workspace = true }
[features]
default = ["std"]
std = [
"codec/std",
"pezframe-benchmarking?/std",
"pezframe-support/std",
"pezframe-system/std",
"log/std",
"pezpallet-balances/std",
"scale-info/std",
"pezsp-core/std",
"pezsp-io/std",
"pezsp-npos-elections/std",
"pezsp-runtime/std",
"pezsp-staking/std",
"pezsp-tracing/std",
]
runtime-benchmarks = [
"pezframe-benchmarking/runtime-benchmarks",
"pezframe-support/runtime-benchmarks",
"pezframe-system/runtime-benchmarks",
"pezpallet-balances/runtime-benchmarks",
"pezsp-io/runtime-benchmarks",
"pezsp-npos-elections/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
"pezsp-staking/runtime-benchmarks",
]
try-runtime = [
"pezframe-support/try-runtime",
"pezframe-system/try-runtime",
"pezpallet-balances/try-runtime",
"pezsp-runtime/try-runtime",
]
@@ -0,0 +1,61 @@
# 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/pezpallet-elections-phragmen/latest/pallet_elections_phragmen/trait.Config.html)
- [`Call`](https://docs.rs/pezpallet-elections-phragmen/latest/pallet_elections_phragmen/enum.Call.html)
- [`Module`](https://docs.rs/pezpallet-elections-phragmen/latest/pallet_elections_phragmen/struct.Module.html)
License: Apache-2.0
@@ -0,0 +1,486 @@
// This file is part of Bizinikiwi.
// 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 pezframe_benchmarking::v2::*;
use pezframe_support::{dispatch::DispatchResultWithPostInfo, traits::OnInitialize};
use pezframe_system::RawOrigin;
#[cfg(test)]
use crate::tests::MEMBERS;
use crate::*;
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.
let _ = 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();
Pallet::<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);
Pallet::<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);
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 {
Pallet::<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> {
submit_candidates_with_self_vote::<T>(m, "fill_seats_up_to")?;
assert_eq!(Candidates::<T>::get().len() as u32, m, "wrong number of candidates.");
Pallet::<T>::do_phragmen();
assert_eq!(Candidates::<T>::get().len(), 0, "some candidates remaining.");
assert_eq!(
Members::<T>::get().len() + RunnersUp::<T>::get().len(),
m as usize,
"wrong number of members and runners-up",
);
Ok(Members::<T>::get()
.into_iter()
.map(|m| m.who)
.chain(RunnersUp::<T>::get().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]
mod benchmarks {
use super::*;
// -- Signed ones
#[benchmark]
fn vote_equal(v: Linear<1, { T::MaxVotesPerVoter::get() }>) -> Result<(), BenchmarkError> {
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);
#[extrinsic_call]
vote(RawOrigin::Signed(caller), votes, stake);
Ok(())
}
#[benchmark]
fn vote_more(v: Linear<2, { T::MaxVotesPerVoter::get() }>) -> Result<(), BenchmarkError> {
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(10_u32);
// Original votes.
let mut votes = all_candidates.iter().skip(1).cloned().collect::<Vec<_>>();
submit_voter::<T>(caller.clone(), votes.clone(), stake / BalanceOf::<T>::from(10_u32))?;
// New votes.
votes = all_candidates;
assert!(votes.len() > Voting::<T>::get(caller.clone()).votes.len());
whitelist!(caller);
#[extrinsic_call]
vote(RawOrigin::Signed(caller), votes, stake / BalanceOf::<T>::from(10_u32));
Ok(())
}
#[benchmark]
fn vote_less(v: Linear<2, { T::MaxVotesPerVoter::get() }>) -> Result<(), BenchmarkError> {
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);
#[extrinsic_call]
vote(RawOrigin::Signed(caller), votes, stake);
Ok(())
}
#[benchmark]
fn remove_voter() -> Result<(), BenchmarkError> {
// 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);
#[extrinsic_call]
_(RawOrigin::Signed(caller));
Ok(())
}
#[benchmark]
fn submit_candidacy(
// Number of already existing candidates.
c: Linear<1, { T::MaxCandidates::get() }>,
) -> Result<(), BenchmarkError> {
// 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.
fill_seats_up_to::<T>(m)?;
// Create previous candidates.
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);
#[extrinsic_call]
_(RawOrigin::Signed(candidate_account), candidate_count::<T>());
// Reset members in between benchmark tests.
#[cfg(test)]
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
Ok(())
}
#[benchmark]
fn 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.
c: Linear<1, { T::MaxCandidates::get() }>,
) -> Result<(), BenchmarkError> {
// 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.
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);
#[extrinsic_call]
renounce_candidacy(RawOrigin::Signed(bailing), Renouncing::Candidate(count));
// Reset members in between benchmark tests.
#[cfg(test)]
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
Ok(())
}
#[benchmark]
fn renounce_candidacy_members() -> Result<(), BenchmarkError> {
// 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!(Pallet::<T>::is_member(&bailing));
whitelist!(bailing);
#[extrinsic_call]
renounce_candidacy(RawOrigin::Signed(bailing.clone()), Renouncing::Member);
// Reset members in between benchmark tests.
#[cfg(test)]
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
Ok(())
}
#[benchmark]
fn renounce_candidacy_runners_up() -> Result<(), BenchmarkError> {
// 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!(Pallet::<T>::is_runner_up(&bailing));
whitelist!(bailing);
#[extrinsic_call]
renounce_candidacy(RawOrigin::Signed(bailing.clone()), Renouncing::RunnerUp);
// Reset members in between benchmark tests.
#[cfg(test)]
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
Ok(())
}
// We use the max block weight for this extrinsic for now. See below.
#[benchmark]
fn remove_member_without_replacement() -> Result<(), BenchmarkError> {
#[block]
{
Err(BenchmarkError::Override(BenchmarkResult::from_weight(
T::BlockWeights::get().max_block,
)))?;
}
Ok(())
}
#[benchmark]
fn remove_member_with_replacement() -> Result<(), BenchmarkError> {
// 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>();
fill_seats_up_to::<T>(m)?;
let removing = as_lookup::<T>(Pallet::<T>::members_ids()[0].clone());
#[extrinsic_call]
remove_member(RawOrigin::Root, removing, true, false);
// Must still have enough members.
assert_eq!(Members::<T>::get().len() as u32, T::DesiredMembers::get());
// Reset members in between benchmark tests.
#[cfg(test)]
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
Ok(())
}
#[benchmark]
fn clean_defunct_voters(
// Total number of voters.
v: Linear<{ T::MaxVoters::get() / 2 }, { T::MaxVoters::get() }>,
// Those that are defunct and need removal.
d: Linear<0, { T::MaxVoters::get() / 2 }>,
) -> Result<(), BenchmarkError> {
// 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)| Pallet::<T>::is_defunct_voter(&v.votes)));
assert_eq!(Voting::<T>::iter().count() as u32, v);
#[extrinsic_call]
_(RawOrigin::Root, v, d);
assert_eq!(Voting::<T>::iter().count() as u32, v - d);
Ok(())
}
#[benchmark]
fn 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.
c: Linear<1, { T::MaxCandidates::get() }>,
v: Linear<1, { T::MaxVoters::get() }>,
e: Linear<{ T::MaxVoters::get() }, { T::MaxVoters::get() * T::MaxVotesPerVoter::get() }>,
) -> Result<(), BenchmarkError> {
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")?;
distribute_voters::<T>(all_candidates, v.saturating_sub(c), votes_per_voter as usize)?;
#[block]
{
Pallet::<T>::on_initialize(T::TermDuration::get());
}
assert_eq!(Members::<T>::get().len() as u32, T::DesiredMembers::get().min(c));
assert_eq!(
RunnersUp::<T>::get().len() as u32,
T::DesiredRunnersUp::get().min(c.saturating_sub(T::DesiredMembers::get())),
);
// reset members in between benchmark tests.
#[cfg(test)]
MEMBERS.with(|m| *m.borrow_mut() = vec![]);
Ok(())
}
impl_benchmark_test_suite! {
Pallet,
tests::ExtBuilder::default().desired_members(13).desired_runners_up(7),
tests::Test,
exec_name = build_and_execute,
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,27 @@
// This file is part of Bizinikiwi.
// 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.
/// Migration to unreserve all pallet funds.
pub mod unlock_and_unreserve_all_funds;
/// Version 3.
pub mod v3;
/// Version 4.
pub mod v4;
/// Version 5.
pub mod v5;
@@ -0,0 +1,513 @@
// This file is part of Bizinikiwi.
// 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.
//! A migration that unreserves all deposit and unlocks all stake held in the context of this
//! pallet.
use alloc::{collections::btree_map::BTreeMap, vec::Vec};
use core::iter::Sum;
use pezframe_support::{
pezpallet_prelude::ValueQuery,
storage_alias,
traits::{Currency, LockIdentifier, LockableCurrency, OnRuntimeUpgrade, ReservableCurrency},
weights::RuntimeDbWeight,
Parameter, Twox64Concat,
};
use pezsp_core::Get;
use pezsp_runtime::traits::Zero;
const LOG_TARGET: &str = "elections_phragmen::migrations::unlock_and_unreserve_all_funds";
type BalanceOf<T> =
<<T as UnlockConfig>::Currency as Currency<<T as UnlockConfig>::AccountId>>::Balance;
/// The configuration for [`UnlockAndUnreserveAllFunds`].
pub trait UnlockConfig: 'static {
/// The account ID used in the runtime.
type AccountId: Parameter + Ord;
/// The currency type used in the runtime.
///
/// Should match the currency type previously used for the pallet, if applicable.
type Currency: LockableCurrency<Self::AccountId> + ReservableCurrency<Self::AccountId>;
/// The name of the pallet as previously configured in
/// [`construct_runtime!`](pezframe_support::construct_runtime).
type PalletName: Get<&'static str>;
/// The maximum number of votes per voter as configured previously in the previous runtime.
type MaxVotesPerVoter: Get<u32>;
/// Identifier for the elections-phragmen pallet's lock, as previously configured in the
/// runtime.
type PalletId: Get<LockIdentifier>;
/// The DB weight as configured in the runtime to calculate the correct weight.
type DbWeight: Get<RuntimeDbWeight>;
}
#[storage_alias(dynamic)]
type Members<T: UnlockConfig> = StorageValue<
<T as UnlockConfig>::PalletName,
Vec<crate::SeatHolder<<T as UnlockConfig>::AccountId, BalanceOf<T>>>,
ValueQuery,
>;
#[storage_alias(dynamic)]
type RunnersUp<T: UnlockConfig> = StorageValue<
<T as UnlockConfig>::PalletName,
Vec<crate::SeatHolder<<T as UnlockConfig>::AccountId, BalanceOf<T>>>,
ValueQuery,
>;
#[storage_alias(dynamic)]
type Candidates<T: UnlockConfig> = StorageValue<
<T as UnlockConfig>::PalletName,
Vec<(<T as UnlockConfig>::AccountId, BalanceOf<T>)>,
ValueQuery,
>;
#[storage_alias(dynamic)]
type Voting<T: UnlockConfig> = StorageMap<
<T as UnlockConfig>::PalletName,
Twox64Concat,
<T as UnlockConfig>::AccountId,
crate::Voter<<T as UnlockConfig>::AccountId, BalanceOf<T>>,
ValueQuery,
>;
/// A migration that unreserves all deposit and unlocks all stake held in the context of this
/// pallet.
///
/// Useful to prevent funds from being locked up when the pallet is being deprecated.
///
/// The pallet should be made inoperable before this migration is run.
///
/// (See also [`RemovePallet`][pezframe_support::migrations::RemovePallet])
pub struct UnlockAndUnreserveAllFunds<T: UnlockConfig>(core::marker::PhantomData<T>);
impl<T: UnlockConfig> UnlockAndUnreserveAllFunds<T> {
/// Calculates and returns the total amounts deposited and staked by each account in the context
/// of this pallet.
///
/// The deposited and staked amounts are returned in two separate `BTreeMap` collections.
///
/// The first `BTreeMap`, `account_deposited_sums`, contains each account's total amount
/// deposited. This includes deposits made by Members, RunnerUps, Candidates, and Voters.
///
/// The second `BTreeMap`, `account_staked_sums`, contains each account's total amount staked.
/// This includes stakes made by Voters.
///
/// # Returns
///
/// This function returns a tuple of two `BTreeMap` collections and the weight of the reads:
///
/// * `BTreeMap<T::AccountId, BalanceOf<T>>`: Map of account IDs to their respective total
/// deposit sums.
/// * `BTreeMap<T::AccountId, BalanceOf<T>>`: Map of account IDs to their respective total
/// staked sums.
/// * `pezframe_support::weights::Weight`: The weight of reading the storage.
fn get_account_deposited_and_staked_sums() -> (
BTreeMap<T::AccountId, BalanceOf<T>>,
BTreeMap<T::AccountId, BalanceOf<T>>,
pezframe_support::weights::Weight,
) {
use pezsp_runtime::Saturating;
let members = Members::<T>::get();
let runner_ups = RunnersUp::<T>::get();
let candidates = Candidates::<T>::get();
// Get the total amount deposited (Members, RunnerUps, Candidates and Voters all can have
// deposits).
let account_deposited_sums: BTreeMap<T::AccountId, BalanceOf<T>> = members
// Massage all data structures into (account_id, deposit) tuples.
.iter()
.chain(runner_ups.iter())
.map(|member| (member.who.clone(), member.deposit))
.chain(candidates.iter().map(|(candidate, amount)| (candidate.clone(), *amount)))
.chain(
Voting::<T>::iter().map(|(account_id, voter)| (account_id.clone(), voter.deposit)),
)
// Finally, aggregate the tuples into a Map.
.fold(BTreeMap::new(), |mut acc, (id, deposit)| {
acc.entry(id.clone()).or_insert(Zero::zero()).saturating_accrue(deposit);
acc
});
// Get the total amount staked (only Voters stake) and count the number of voters.
let mut voters_len = 0;
let account_staked_sums: BTreeMap<T::AccountId, BalanceOf<T>> = Voting::<T>::iter()
.map(|(account_id, voter)| (account_id.clone(), voter.stake))
.fold(BTreeMap::new(), |mut acc, (id, stake)| {
voters_len.saturating_accrue(1);
acc.entry(id.clone()).or_insert(Zero::zero()).saturating_accrue(stake);
acc
});
(
account_deposited_sums,
account_staked_sums,
T::DbWeight::get().reads(
members
.len()
.saturating_add(runner_ups.len())
.saturating_add(candidates.len())
.saturating_add(voters_len.saturating_mul(T::MaxVotesPerVoter::get() as usize))
as u64,
),
)
}
}
impl<T: UnlockConfig> OnRuntimeUpgrade for UnlockAndUnreserveAllFunds<T>
where
BalanceOf<T>: Sum,
{
/// Collects pre-migration data useful for validating the migration was successful, and also
/// checks the integrity of deposited and reserved balances.
///
/// Steps:
/// 1. Gets the deposited and staked balances for each account stored in this pallet.
/// 2. Collects actual pre-migration locked and reserved balances for each account.
/// 3. Checks the integrity of the deposited and reserved balances.
/// 4. Prints summary statistics about the state to be migrated.
/// 5. Encodes and returns pre-migration data to be used in post_upgrade.
///
/// Fails with a `TryRuntimeError` if there's a discrepancy between the amount
/// reported as staked by the pallet and the amount actually locked in `Balances`.
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, pezsp_runtime::TryRuntimeError> {
use alloc::collections::btree_set::BTreeSet;
use codec::Encode;
// Get staked and deposited balances as reported by this pallet.
let (account_deposited_sums, account_staked_sums, _) =
Self::get_account_deposited_and_staked_sums();
let all_accounts: BTreeSet<T::AccountId> = account_staked_sums
.keys()
.chain(account_deposited_sums.keys())
.cloned()
.collect();
let account_reserved_before: BTreeMap<T::AccountId, BalanceOf<T>> = all_accounts
.iter()
.map(|account| (account.clone(), T::Currency::reserved_balance(&account)))
.collect();
// Total deposited for each account *should* be less than or equal to the total reserved,
// however this does not hold for all cases due to bugs in the reserve logic of this pallet.
let bugged_deposits = all_accounts
.iter()
.filter(|account| {
account_deposited_sums.get(&account).unwrap_or(&Zero::zero()) >
account_reserved_before.get(&account).unwrap_or(&Zero::zero())
})
.count();
// Print some summary stats.
let total_stake_to_unlock = account_staked_sums.clone().into_values().sum::<BalanceOf<T>>();
let total_deposits_to_unreserve =
account_deposited_sums.clone().into_values().sum::<BalanceOf<T>>();
log::info!(target: LOG_TARGET, "Total accounts: {:?}", all_accounts.len());
log::info!(target: LOG_TARGET, "Total stake to unlock: {:?}", total_stake_to_unlock);
log::info!(
target: LOG_TARGET,
"Total deposit to unreserve: {:?}",
total_deposits_to_unreserve
);
if bugged_deposits > 0 {
log::warn!(
target: LOG_TARGET,
"Bugged deposits: {}/{}",
bugged_deposits,
all_accounts.len()
);
}
Ok(account_reserved_before.encode())
}
/// Executes the migration.
///
/// Steps:
/// 1. Retrieves the deposit and stake amounts from the pallet.
/// 2. Unreserves the deposited funds for each account.
/// 3. Unlocks the staked funds for each account.
fn on_runtime_upgrade() -> pezframe_support::weights::Weight {
// Get staked and deposited balances as reported by this pallet.
let (account_deposited_sums, account_staked_sums, initial_reads) =
Self::get_account_deposited_and_staked_sums();
// Deposited funds need to be unreserved.
for (account, unreserve_amount) in account_deposited_sums.iter() {
if unreserve_amount.is_zero() {
log::warn!(target: LOG_TARGET, "Unexpected zero amount to unreserve");
continue;
}
T::Currency::unreserve(&account, *unreserve_amount);
}
// Staked funds need to be unlocked.
for (account, amount) in account_staked_sums.iter() {
if amount.is_zero() {
log::warn!(target: LOG_TARGET, "Unexpected zero amount to unlock");
continue;
}
T::Currency::remove_lock(T::PalletId::get(), account);
}
T::DbWeight::get()
.reads_writes(
(account_deposited_sums.len().saturating_add(account_staked_sums.len())) as u64,
(account_deposited_sums.len().saturating_add(account_staked_sums.len())) as u64,
)
.saturating_add(initial_reads)
}
/// Performs post-upgrade sanity checks:
///
/// 1. All expected locks were removed after the migration.
/// 2. The reserved balance for each account has been reduced by the expected amount.
#[cfg(feature = "try-runtime")]
fn post_upgrade(
account_reserved_before_bytes: Vec<u8>,
) -> Result<(), pezsp_runtime::TryRuntimeError> {
use codec::Decode;
use pezsp_runtime::Saturating;
let account_reserved_before =
BTreeMap::<T::AccountId, BalanceOf<T>>::decode(&mut &account_reserved_before_bytes[..])
.map_err(|_| "Failed to decode account_reserved_before_bytes")?;
// Get deposited balances as reported by this pallet.
let (account_deposited_sums, _, _) = Self::get_account_deposited_and_staked_sums();
// Check that the reserved balance is reduced by the expected deposited amount.
for (account, actual_reserved_before) in account_reserved_before {
let actual_reserved_after = T::Currency::reserved_balance(&account);
let expected_amount_deducted = *account_deposited_sums
.get(&account)
.unwrap_or(&Zero::zero())
// .min here to handle bugged deposits where actual_reserved_before is less than the
// amount the pallet reports is reserved
.min(&actual_reserved_before);
let expected_reserved_after =
actual_reserved_before.saturating_sub(expected_amount_deducted);
assert!(
actual_reserved_after == expected_reserved_after,
"Reserved balance for {:?} is incorrect. actual before: {:?}, actual after, {:?}, expected deducted: {:?}",
account,
actual_reserved_before,
actual_reserved_after,
expected_amount_deducted,
);
}
Ok(())
}
}
#[cfg(all(feature = "try-runtime", test))]
mod test {
use super::*;
use crate::{
tests::{Balances, ElectionsPhragmenPalletId, ExtBuilder, PhragmenMaxVoters, Test},
Candidates, Members, RunnersUp, SeatHolder, Voter, Voting,
};
use pezframe_support::{
assert_ok, parameter_types,
traits::{Currency, OnRuntimeUpgrade, ReservableCurrency, WithdrawReasons},
};
parameter_types! {
const PalletName: &'static str = "Elections";
}
struct UnlockConfigImpl;
impl super::UnlockConfig for UnlockConfigImpl {
type Currency = Balances;
type AccountId = u64;
type DbWeight = ();
type PalletName = PalletName;
type MaxVotesPerVoter = PhragmenMaxVoters;
type PalletId = ElectionsPhragmenPalletId;
}
#[test]
fn unreserve_works_for_candidate() {
let candidate = 10;
let deposit = 100;
let initial_reserved = 15;
let initial_balance = 100_000;
ExtBuilder::default().build_and_execute(|| {
// Set up initial state.
<Test as crate::Config>::Currency::make_free_balance_be(&candidate, initial_balance);
assert_ok!(<Test as crate::Config>::Currency::reserve(&candidate, initial_reserved));
Candidates::<Test>::set(vec![(candidate, deposit)]);
assert_ok!(<Test as crate::Config>::Currency::reserve(&candidate, deposit));
// Sanity check: ensure initial Balance state was set up correctly.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&candidate),
deposit + initial_reserved
);
// Run the migration.
let bytes = UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::pre_upgrade()
.unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e));
UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::on_runtime_upgrade();
assert_ok!(UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::post_upgrade(bytes));
// Assert the candidate reserved balance was reduced by the expected amount.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&candidate),
initial_reserved
);
});
}
#[test]
fn unreserve_works_for_runner_up() {
let runner_up = 10;
let deposit = 100;
let initial_reserved = 15;
let initial_balance = 100_000;
ExtBuilder::default().build_and_execute(|| {
// Set up initial state.
<Test as crate::Config>::Currency::make_free_balance_be(&runner_up, initial_balance);
assert_ok!(<Test as crate::Config>::Currency::reserve(&runner_up, initial_reserved));
RunnersUp::<Test>::set(vec![SeatHolder { who: runner_up, deposit, stake: 10 }]);
assert_ok!(<Test as crate::Config>::Currency::reserve(&runner_up, deposit));
// Sanity check: ensure initial Balance state was set up correctly.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&runner_up),
deposit + initial_reserved
);
// Run the migration.
let bytes = UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::pre_upgrade()
.unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e));
UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::on_runtime_upgrade();
assert_ok!(UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::post_upgrade(bytes));
// Assert the reserved balance was reduced by the expected amount.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&runner_up),
initial_reserved
);
});
}
#[test]
fn unreserve_works_for_member() {
let member = 10;
let deposit = 100;
let initial_reserved = 15;
let initial_balance = 100_000;
ExtBuilder::default().build_and_execute(|| {
// Set up initial state.
<Test as crate::Config>::Currency::make_free_balance_be(&member, initial_balance);
assert_ok!(<Test as crate::Config>::Currency::reserve(&member, initial_reserved));
Members::<Test>::set(vec![SeatHolder { who: member, deposit, stake: 10 }]);
assert_ok!(<Test as crate::Config>::Currency::reserve(&member, deposit));
// Sanity check: ensure initial Balance state was set up correctly.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&member),
deposit + initial_reserved
);
// Run the migration.
let bytes = UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::pre_upgrade()
.unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e));
UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::on_runtime_upgrade();
assert_ok!(UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::post_upgrade(bytes));
// Assert the reserved balance was reduced by the expected amount.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&member),
initial_reserved
);
});
}
#[test]
fn unlock_and_unreserve_works_for_voter() {
let voter = 10;
let deposit = 100;
let initial_reserved = 15;
let initial_locks = vec![(b"somethin", 10)];
let stake = 25;
let initial_balance = 100_000;
ExtBuilder::default().build_and_execute(|| {
let pezpallet_id = <Test as crate::Config>::PalletId::get();
// Set up initial state.
<Test as crate::Config>::Currency::make_free_balance_be(&voter, initial_balance);
assert_ok!(<Test as crate::Config>::Currency::reserve(&voter, initial_reserved));
for lock in initial_locks.clone() {
<Test as crate::Config>::Currency::set_lock(
*lock.0,
&voter,
lock.1,
WithdrawReasons::all(),
);
}
Voting::<Test>::insert(voter, Voter { votes: vec![], deposit, stake });
assert_ok!(<Test as crate::Config>::Currency::reserve(&voter, deposit));
<Test as crate::Config>::Currency::set_lock(
<Test as crate::Config>::PalletId::get(),
&voter,
stake,
WithdrawReasons::all(),
);
// Sanity check: ensure initial Balance state was set up correctly.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&voter),
deposit + initial_reserved
);
let mut voter_all_locks = initial_locks.clone();
voter_all_locks.push((&pezpallet_id, stake));
assert_eq!(
<Test as crate::Config>::Currency::locks(&voter)
.iter()
.map(|lock| (&lock.id, lock.amount))
.collect::<Vec<_>>(),
voter_all_locks
);
// Run the migration.
let bytes = UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::pre_upgrade()
.unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e));
UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::on_runtime_upgrade();
assert_ok!(UnlockAndUnreserveAllFunds::<UnlockConfigImpl>::post_upgrade(bytes));
// Assert the voter lock was removed and the reserved balance was reduced by the
// expected amount.
assert_eq!(
<Test as crate::Config>::Currency::reserved_balance(&voter),
initial_reserved
);
assert_eq!(
<Test as crate::Config>::Currency::locks(&voter)
.iter()
.map(|lock| (&lock.id, lock.amount))
.collect::<Vec<_>>(),
initial_locks
);
});
}
}
@@ -0,0 +1,166 @@
// This file is part of Bizinikiwi.
// 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 alloc::vec::Vec;
use codec::{Decode, Encode, FullCodec};
use pezframe_support::{
pezpallet_prelude::ValueQuery, traits::StorageVersion, weights::Weight, Twox64Concat,
};
use pezsp_runtime::RuntimeDebug;
#[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;
}
#[pezframe_support::storage_alias]
type Candidates<V, T: Config> =
StorageValue<Pallet<T>, Vec<(<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance)>, ValueQuery>;
#[pezframe_support::storage_alias]
type Members<V, T: Config> = StorageValue<
Pallet<T>,
Vec<SeatHolder<<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance>>,
ValueQuery,
>;
#[pezframe_support::storage_alias]
type RunnersUp<V, T: Config> = StorageValue<
Pallet<T>,
Vec<SeatHolder<<V as V2ToV3>::AccountId, <V as V2ToV3>::Balance>>,
ValueQuery,
>;
#[pezframe_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<_>>()
})
},
);
}
@@ -0,0 +1,107 @@
// This file is part of Bizinikiwi.
// 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 pezframe_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 pezframe_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());
pezframe_support::storage::migration::move_pallet(
OLD_PREFIX,
new_pallet_name.as_ref().as_bytes(),
);
StorageVersion::new(4).put::<crate::Pallet<T>>();
<T as pezframe_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
/// `pezframe_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 = pezsp_io::storage::next_key(OLD_PREFIX).unwrap();
assert!(next_key.starts_with(&pezsp_io::hashing::twox_128(OLD_PREFIX)));
// ensure nothing is stored in the new prefix.
assert!(
pezsp_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(&pezsp_io::hashing::twox_128(new.as_bytes()))
),
"unexpected next_key({}) = {:?}",
new,
pezsp_core::hexdisplay::HexDisplay::from(&pezsp_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
/// `pezframe_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);
}
@@ -0,0 +1,88 @@
// This file is part of Bizinikiwi.
// 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.
use super::super::*;
use alloc::{boxed::Box, vec::Vec};
/// 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 pezpallet_id = T::PalletId::get();
T::Currency::set_lock(pezpallet_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 [`pezframe_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
/// `pezframe_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");
}
@@ -0,0 +1,608 @@
// This file is part of Bizinikiwi.
// 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.
// This file is part of Bizinikiwi.
// 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 `pezpallet_elections_phragmen`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-02-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `4563561839a5`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
// Executed Command:
// frame-omni-bencher
// v1
// benchmark
// pallet
// --extrinsic=*
// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm
// --pallet=pezpallet_elections_phragmen
// --header=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/HEADER-APACHE2
// --output=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/pezframe/elections-phragmen/src/weights.rs
// --wasm-execution=compiled
// --steps=50
// --repeat=20
// --heap-pages=4096
// --template=bizinikiwi/.maintain/frame-weight-template.hbs
// --no-storage-info
// --no-min-squares
// --no-median-slopes
// --genesis-builder-policy=none
// --exclude-pallets=pezpallet_xcm,pezpallet_xcm_benchmarks::fungible,pezpallet_xcm_benchmarks::generic,pezpallet_nomination_pools,pezpallet_remark,pezpallet_transaction_storage,pezpallet_election_provider_multi_block,pezpallet_election_provider_multi_block::signed,pezpallet_election_provider_multi_block::unsigned,pezpallet_election_provider_multi_block::verifier
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
#![allow(dead_code)]
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use core::marker::PhantomData;
/// Weight functions needed for `pezpallet_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 `pezpallet_elections_phragmen` using the Bizinikiwi node and recommended hardware.
pub struct BizinikiwiWeight<T>(PhantomData<T>);
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// The range of component `v` is `[1, 16]`.
fn vote_equal(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `273 + v * (80 ±0)`
// Estimated: `4764 + v * (83 ±0)`
// Minimum execution time: 30_859_000 picoseconds.
Weight::from_parts(31_688_053, 4764)
// Standard Error: 4_354
.saturating_add(Weight::from_parts(239_976, 0).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(6_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(Weight::from_parts(0, 83).saturating_mul(v.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// The range of component `v` is `[2, 16]`.
fn vote_more(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `241 + v * (80 ±0)`
// Estimated: `4764 + v * (83 ±0)`
// Minimum execution time: 42_425_000 picoseconds.
Weight::from_parts(43_125_592, 4764)
// Standard Error: 4_549
.saturating_add(Weight::from_parts(244_542, 0).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(6_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(Weight::from_parts(0, 83).saturating_mul(v.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// The range of component `v` is `[2, 16]`.
fn vote_less(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `273 + v * (80 ±0)`
// Estimated: `4764 + v * (83 ±0)`
// Minimum execution time: 42_205_000 picoseconds.
Weight::from_parts(43_351_255, 4764)
// Standard Error: 4_319
.saturating_add(Weight::from_parts(242_837, 0).saturating_mul(v.into()))
.saturating_add(T::DbWeight::get().reads(6_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
.saturating_add(Weight::from_parts(0, 83).saturating_mul(v.into()))
}
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
fn remove_voter() -> Weight {
// Proof Size summary in bytes:
// Measured: `794`
// Estimated: `4764`
// Minimum execution time: 42_574_000 picoseconds.
Weight::from_parts(43_828_000, 4764)
.saturating_add(T::DbWeight::get().reads(3_u64))
.saturating_add(T::DbWeight::get().writes(2_u64))
}
/// Storage: `Elections::Candidates` (r:1 w:1)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `c` is `[1, 128]`.
fn submit_candidacy(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `1473 + c * (48 ±0)`
// Estimated: `2959 + c * (48 ±0)`
// Minimum execution time: 35_171_000 picoseconds.
Weight::from_parts(36_158_550, 2959)
// Standard Error: 1_017
.saturating_add(Weight::from_parts(80_161, 0).saturating_mul(c.into()))
.saturating_add(T::DbWeight::get().reads(3_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
.saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:1)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `c` is `[1, 128]`.
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `214 + c * (48 ±0)`
// Estimated: `1750 + c * (48 ±0)`
// Minimum execution time: 27_427_000 picoseconds.
Weight::from_parts(28_254_151, 1750)
// Standard Error: 658
.saturating_add(Weight::from_parts(68_988, 0).saturating_mul(c.into()))
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
.saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into()))
}
/// Storage: `Elections::Members` (r:1 w:1)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:1)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Prime` (r:1 w:1)
/// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Proposals` (r:1 w:0)
/// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Members` (r:0 w:1)
/// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn renounce_candidacy_members() -> Weight {
// Proof Size summary in bytes:
// Measured: `1575`
// Estimated: `3060`
// Minimum execution time: 40_828_000 picoseconds.
Weight::from_parts(42_179_000, 3060)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(4_u64))
}
/// Storage: `Elections::RunnersUp` (r:1 w:1)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn renounce_candidacy_runners_up() -> Weight {
// Proof Size summary in bytes:
// Measured: `751`
// Estimated: `2236`
// Minimum execution time: 29_536_000 picoseconds.
Weight::from_parts(30_472_000, 2236)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Benchmark::Override` (r:0 w:0)
/// Proof: `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_000 picoseconds.
Weight::from_parts(2_000_000_000_000, 0)
}
/// Storage: `Elections::Members` (r:1 w:1)
/// Proof: `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: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Prime` (r:1 w:1)
/// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Proposals` (r:1 w:0)
/// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Members` (r:0 w:1)
/// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn remove_member_with_replacement() -> Weight {
// Proof Size summary in bytes:
// Measured: `1575`
// Estimated: `3593`
// Minimum execution time: 45_629_000 picoseconds.
Weight::from_parts(47_206_000, 3593)
.saturating_add(T::DbWeight::get().reads(5_u64))
.saturating_add(T::DbWeight::get().writes(5_u64))
}
/// Storage: `Elections::Voting` (r:129 w:128)
/// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Balances::Locks` (r:128 w:128)
/// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`)
/// Storage: `Balances::Freezes` (r:128 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:128 w:128)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// The range of component `v` is `[128, 256]`.
/// The range of component `d` is `[0, 128]`.
fn clean_defunct_voters(v: u32, d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + d * (810 ±0) + v * (56 ±0)`
// Estimated: `12490 + d * (3774 ±0) + v * (28 ±0)`
// Minimum execution time: 5_075_000 picoseconds.
Weight::from_parts(5_442_000, 12490)
// Standard Error: 10_524
.saturating_add(Weight::from_parts(356_284, 0).saturating_mul(v.into()))
// Standard Error: 22_925
.saturating_add(Weight::from_parts(59_936_319, 0).saturating_mul(d.into()))
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(d.into())))
.saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(d.into())))
.saturating_add(Weight::from_parts(0, 3774).saturating_mul(d.into()))
.saturating_add(Weight::from_parts(0, 28).saturating_mul(v.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:1)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:1)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:1)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:257 w:0)
/// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Council::Proposals` (r:1 w:0)
/// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `System::Account` (r:108 w:108)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Elections::ElectionRounds` (r:1 w:1)
/// Proof: `Elections::ElectionRounds` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Members` (r:0 w:1)
/// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Prime` (r:0 w:1)
/// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `c` is `[1, 128]`.
/// The range of component `v` is `[1, 256]`.
/// The range of component `e` is `[256, 4096]`.
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + e * (16 ±0) + v * (331 ±0)`
// Estimated: `253201 + c * (2409 ±3) + e * (9 ±0) + v * (1952 ±4)`
// Minimum execution time: 1_442_707_000 picoseconds.
Weight::from_parts(1_453_511_000, 253201)
// Standard Error: 339_169
.saturating_add(Weight::from_parts(17_830_182, 0).saturating_mul(v.into()))
// Standard Error: 21_751
.saturating_add(Weight::from_parts(521_821, 0).saturating_mul(e.into()))
.saturating_add(T::DbWeight::get().reads(112_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_parts(0, 2409).saturating_mul(c.into()))
.saturating_add(Weight::from_parts(0, 9).saturating_mul(e.into()))
.saturating_add(Weight::from_parts(0, 1952).saturating_mul(v.into()))
}
}
// For backwards compatibility and tests.
impl WeightInfo for () {
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// The range of component `v` is `[1, 16]`.
fn vote_equal(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `273 + v * (80 ±0)`
// Estimated: `4764 + v * (83 ±0)`
// Minimum execution time: 30_859_000 picoseconds.
Weight::from_parts(31_688_053, 4764)
// Standard Error: 4_354
.saturating_add(Weight::from_parts(239_976, 0).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(6_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(Weight::from_parts(0, 83).saturating_mul(v.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// The range of component `v` is `[2, 16]`.
fn vote_more(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `241 + v * (80 ±0)`
// Estimated: `4764 + v * (83 ±0)`
// Minimum execution time: 42_425_000 picoseconds.
Weight::from_parts(43_125_592, 4764)
// Standard Error: 4_549
.saturating_add(Weight::from_parts(244_542, 0).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(6_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(Weight::from_parts(0, 83).saturating_mul(v.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// The range of component `v` is `[2, 16]`.
fn vote_less(v: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `273 + v * (80 ±0)`
// Estimated: `4764 + v * (83 ±0)`
// Minimum execution time: 42_205_000 picoseconds.
Weight::from_parts(43_351_255, 4764)
// Standard Error: 4_319
.saturating_add(Weight::from_parts(242_837, 0).saturating_mul(v.into()))
.saturating_add(RocksDbWeight::get().reads(6_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
.saturating_add(Weight::from_parts(0, 83).saturating_mul(v.into()))
}
/// Storage: `Elections::Voting` (r:1 w:1)
/// Proof: `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`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
fn remove_voter() -> Weight {
// Proof Size summary in bytes:
// Measured: `794`
// Estimated: `4764`
// Minimum execution time: 42_574_000 picoseconds.
Weight::from_parts(43_828_000, 4764)
.saturating_add(RocksDbWeight::get().reads(3_u64))
.saturating_add(RocksDbWeight::get().writes(2_u64))
}
/// Storage: `Elections::Candidates` (r:1 w:1)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `c` is `[1, 128]`.
fn submit_candidacy(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `1473 + c * (48 ±0)`
// Estimated: `2959 + c * (48 ±0)`
// Minimum execution time: 35_171_000 picoseconds.
Weight::from_parts(36_158_550, 2959)
// Standard Error: 1_017
.saturating_add(Weight::from_parts(80_161, 0).saturating_mul(c.into()))
.saturating_add(RocksDbWeight::get().reads(3_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
.saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:1)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `c` is `[1, 128]`.
fn renounce_candidacy_candidate(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `214 + c * (48 ±0)`
// Estimated: `1750 + c * (48 ±0)`
// Minimum execution time: 27_427_000 picoseconds.
Weight::from_parts(28_254_151, 1750)
// Standard Error: 658
.saturating_add(Weight::from_parts(68_988, 0).saturating_mul(c.into()))
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
.saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into()))
}
/// Storage: `Elections::Members` (r:1 w:1)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:1)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Prime` (r:1 w:1)
/// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Proposals` (r:1 w:0)
/// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Members` (r:0 w:1)
/// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn renounce_candidacy_members() -> Weight {
// Proof Size summary in bytes:
// Measured: `1575`
// Estimated: `3060`
// Minimum execution time: 40_828_000 picoseconds.
Weight::from_parts(42_179_000, 3060)
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().writes(4_u64))
}
/// Storage: `Elections::RunnersUp` (r:1 w:1)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn renounce_candidacy_runners_up() -> Weight {
// Proof Size summary in bytes:
// Measured: `751`
// Estimated: `2236`
// Minimum execution time: 29_536_000 picoseconds.
Weight::from_parts(30_472_000, 2236)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Benchmark::Override` (r:0 w:0)
/// Proof: `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_000 picoseconds.
Weight::from_parts(2_000_000_000_000, 0)
}
/// Storage: `Elections::Members` (r:1 w:1)
/// Proof: `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: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Prime` (r:1 w:1)
/// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Proposals` (r:1 w:0)
/// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Members` (r:0 w:1)
/// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn remove_member_with_replacement() -> Weight {
// Proof Size summary in bytes:
// Measured: `1575`
// Estimated: `3593`
// Minimum execution time: 45_629_000 picoseconds.
Weight::from_parts(47_206_000, 3593)
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(5_u64))
}
/// Storage: `Elections::Voting` (r:129 w:128)
/// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:0)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:0)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Candidates` (r:1 w:0)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Balances::Locks` (r:128 w:128)
/// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`)
/// Storage: `Balances::Freezes` (r:128 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:128 w:128)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// The range of component `v` is `[128, 256]`.
/// The range of component `d` is `[0, 128]`.
fn clean_defunct_voters(v: u32, d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + d * (810 ±0) + v * (56 ±0)`
// Estimated: `12490 + d * (3774 ±0) + v * (28 ±0)`
// Minimum execution time: 5_075_000 picoseconds.
Weight::from_parts(5_442_000, 12490)
// Standard Error: 10_524
.saturating_add(Weight::from_parts(356_284, 0).saturating_mul(v.into()))
// Standard Error: 22_925
.saturating_add(Weight::from_parts(59_936_319, 0).saturating_mul(d.into()))
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(d.into())))
.saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(d.into())))
.saturating_add(Weight::from_parts(0, 3774).saturating_mul(d.into()))
.saturating_add(Weight::from_parts(0, 28).saturating_mul(v.into()))
}
/// Storage: `Elections::Candidates` (r:1 w:1)
/// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Members` (r:1 w:1)
/// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::RunnersUp` (r:1 w:1)
/// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Elections::Voting` (r:257 w:0)
/// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Council::Proposals` (r:1 w:0)
/// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `System::Account` (r:108 w:108)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Elections::ElectionRounds` (r:1 w:1)
/// Proof: `Elections::ElectionRounds` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Members` (r:0 w:1)
/// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `Council::Prime` (r:0 w:1)
/// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `c` is `[1, 128]`.
/// The range of component `v` is `[1, 256]`.
/// The range of component `e` is `[256, 4096]`.
fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + e * (16 ±0) + v * (331 ±0)`
// Estimated: `253201 + c * (2409 ±3) + e * (9 ±0) + v * (1952 ±4)`
// Minimum execution time: 1_442_707_000 picoseconds.
Weight::from_parts(1_453_511_000, 253201)
// Standard Error: 339_169
.saturating_add(Weight::from_parts(17_830_182, 0).saturating_mul(v.into()))
// Standard Error: 21_751
.saturating_add(Weight::from_parts(521_821, 0).saturating_mul(e.into()))
.saturating_add(RocksDbWeight::get().reads(112_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_parts(0, 2409).saturating_mul(c.into()))
.saturating_add(Weight::from_parts(0, 9).saturating_mul(e.into()))
.saturating_add(Weight::from_parts(0, 1952).saturating_mul(v.into()))
}
}