Refactoring Checkpoint: (WIP)
This commit is contained in:
@@ -0,0 +1,464 @@
|
||||
// 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.
|
||||
|
||||
//! Benchmarking setup for pezpallet-collator-selection
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use super::*;
|
||||
|
||||
#[allow(unused)]
|
||||
use crate::Pallet as CollatorSelection;
|
||||
use alloc::vec::Vec;
|
||||
use codec::Decode;
|
||||
use core::cmp;
|
||||
use pezframe_benchmarking::{account, v2::*, whitelisted_caller, BenchmarkError};
|
||||
use pezframe_support::traits::{Currency, EnsureOrigin, Get, ReservableCurrency};
|
||||
use pezframe_system::{pezpallet_prelude::BlockNumberFor, EventRecord, RawOrigin};
|
||||
use pezpallet_authorship::EventHandler;
|
||||
use pezpallet_session::{self as session, SessionManager};
|
||||
|
||||
pub type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Currency<<T as pezframe_system::Config>::AccountId>>::Balance;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
||||
let events = pezframe_system::Pallet::<T>::events();
|
||||
let system_event: <T as pezframe_system::Config>::RuntimeEvent = generic_event.into();
|
||||
// compare to the last event record
|
||||
let EventRecord { event, .. } = &events[events.len() - 1];
|
||||
assert_eq!(event, &system_event);
|
||||
}
|
||||
|
||||
fn create_funded_user<T: Config>(
|
||||
string: &'static str,
|
||||
n: u32,
|
||||
balance_factor: u32,
|
||||
) -> T::AccountId {
|
||||
let user = account(string, n, SEED);
|
||||
let balance = <T as pallet::Config>::Currency::minimum_balance() * balance_factor.into();
|
||||
let _ = <T as pallet::Config>::Currency::make_free_balance_be(&user, balance);
|
||||
user
|
||||
}
|
||||
|
||||
fn keys<T: Config + session::Config>(c: u32) -> <T as session::Config>::Keys {
|
||||
use rand::{RngCore, SeedableRng};
|
||||
|
||||
let keys = {
|
||||
let mut keys = [0u8; 128];
|
||||
|
||||
if c > 0 {
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(c as u64);
|
||||
rng.fill_bytes(&mut keys);
|
||||
}
|
||||
|
||||
keys
|
||||
};
|
||||
|
||||
Decode::decode(&mut &keys[..]).unwrap()
|
||||
}
|
||||
|
||||
fn validator<T: Config + session::Config>(c: u32) -> (T::AccountId, <T as session::Config>::Keys) {
|
||||
(create_funded_user::<T>("candidate", c, 1000), keys::<T>(c))
|
||||
}
|
||||
|
||||
fn register_validators<T: Config + session::Config>(count: u32) -> Vec<T::AccountId> {
|
||||
let validators = (0..count).map(|c| validator::<T>(c)).collect::<Vec<_>>();
|
||||
|
||||
for (who, keys) in validators.clone() {
|
||||
<session::Pallet<T>>::ensure_can_pay_key_deposit(&who).unwrap();
|
||||
<session::Pallet<T>>::set_keys(RawOrigin::Signed(who).into(), keys, Vec::new()).unwrap();
|
||||
}
|
||||
|
||||
validators.into_iter().map(|(who, _)| who).collect()
|
||||
}
|
||||
|
||||
fn register_candidates<T: Config>(count: u32) {
|
||||
let candidates = (0..count).map(|c| account("candidate", c, SEED)).collect::<Vec<_>>();
|
||||
assert!(CandidacyBond::<T>::get() > 0u32.into(), "Bond cannot be zero!");
|
||||
|
||||
for who in candidates {
|
||||
<T as pallet::Config>::Currency::make_free_balance_be(
|
||||
&who,
|
||||
CandidacyBond::<T>::get() * 3u32.into(),
|
||||
);
|
||||
<CollatorSelection<T>>::register_as_candidate(RawOrigin::Signed(who).into()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn min_candidates<T: Config>() -> u32 {
|
||||
let min_collators = T::MinEligibleCollators::get();
|
||||
let invulnerable_length = Invulnerables::<T>::get().len();
|
||||
min_collators.saturating_sub(invulnerable_length.try_into().unwrap())
|
||||
}
|
||||
|
||||
fn min_invulnerables<T: Config>() -> u32 {
|
||||
let min_collators = T::MinEligibleCollators::get();
|
||||
let candidates_length = CandidateList::<T>::decode_len()
|
||||
.unwrap_or_default()
|
||||
.try_into()
|
||||
.unwrap_or_default();
|
||||
min_collators.saturating_sub(candidates_length)
|
||||
}
|
||||
|
||||
#[benchmarks(where T: pezpallet_authorship::Config + session::Config)]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
#[benchmark]
|
||||
fn set_invulnerables(
|
||||
b: Linear<1, { T::MaxInvulnerables::get() }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
let new_invulnerables = register_validators::<T>(b);
|
||||
let mut sorted_new_invulnerables = new_invulnerables.clone();
|
||||
sorted_new_invulnerables.sort();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin as T::RuntimeOrigin, new_invulnerables.clone());
|
||||
|
||||
// assert that it comes out sorted
|
||||
assert_last_event::<T>(
|
||||
Event::NewInvulnerables { invulnerables: sorted_new_invulnerables }.into(),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn add_invulnerable(
|
||||
b: Linear<1, { T::MaxInvulnerables::get() - 1 }>,
|
||||
c: Linear<1, { T::MaxCandidates::get() - 1 }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
// need to fill up candidates
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
DesiredCandidates::<T>::put(c);
|
||||
// get accounts and keys for the `c` candidates
|
||||
let mut candidates = (0..c).map(|cc| validator::<T>(cc)).collect::<Vec<_>>();
|
||||
// add one more to the list. should not be in `b` (invulnerables) because it's the account
|
||||
// we will _add_ to invulnerables. we want it to be in `candidates` because we need the
|
||||
// weight associated with removing it.
|
||||
let (new_invulnerable, new_invulnerable_keys) = validator::<T>(b.max(c) + 1);
|
||||
candidates.push((new_invulnerable.clone(), new_invulnerable_keys));
|
||||
// set their keys ...
|
||||
for (who, keys) in candidates.clone() {
|
||||
<session::Pallet<T>>::ensure_can_pay_key_deposit(&who).unwrap();
|
||||
<session::Pallet<T>>::set_keys(RawOrigin::Signed(who).into(), keys, Vec::new())
|
||||
.unwrap();
|
||||
}
|
||||
// ... and register them.
|
||||
for (who, _) in candidates.iter() {
|
||||
let deposit = CandidacyBond::<T>::get();
|
||||
<T as pallet::Config>::Currency::make_free_balance_be(who, deposit * 1000_u32.into());
|
||||
CandidateList::<T>::try_mutate(|list| {
|
||||
list.try_push(CandidateInfo { who: who.clone(), deposit }).unwrap();
|
||||
Ok::<(), BenchmarkError>(())
|
||||
})
|
||||
.unwrap();
|
||||
<T as pallet::Config>::Currency::reserve(who, deposit)?;
|
||||
LastAuthoredBlock::<T>::insert(
|
||||
who.clone(),
|
||||
pezframe_system::Pallet::<T>::block_number() + T::KickThreshold::get(),
|
||||
);
|
||||
}
|
||||
|
||||
// now we need to fill up invulnerables
|
||||
let mut invulnerables = register_validators::<T>(b);
|
||||
invulnerables.sort();
|
||||
let invulnerables: pezframe_support::BoundedVec<_, T::MaxInvulnerables> =
|
||||
pezframe_support::BoundedVec::try_from(invulnerables).unwrap();
|
||||
Invulnerables::<T>::put(invulnerables);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin as T::RuntimeOrigin, new_invulnerable.clone());
|
||||
|
||||
assert_last_event::<T>(Event::InvulnerableAdded { account_id: new_invulnerable }.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn remove_invulnerable(
|
||||
b: Linear<{ min_invulnerables::<T>() + 1 }, { T::MaxInvulnerables::get() }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
let mut invulnerables = register_validators::<T>(b);
|
||||
invulnerables.sort();
|
||||
let invulnerables: pezframe_support::BoundedVec<_, T::MaxInvulnerables> =
|
||||
pezframe_support::BoundedVec::try_from(invulnerables).unwrap();
|
||||
Invulnerables::<T>::put(invulnerables);
|
||||
let to_remove = Invulnerables::<T>::get().first().unwrap().clone();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin as T::RuntimeOrigin, to_remove.clone());
|
||||
|
||||
assert_last_event::<T>(Event::InvulnerableRemoved { account_id: to_remove }.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn set_desired_candidates() -> Result<(), BenchmarkError> {
|
||||
let max: u32 = T::MaxCandidates::get();
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin as T::RuntimeOrigin, max);
|
||||
|
||||
assert_last_event::<T>(Event::NewDesiredCandidates { desired_candidates: max }.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn set_candidacy_bond(
|
||||
c: Linear<0, { T::MaxCandidates::get() }>,
|
||||
k: Linear<0, { T::MaxCandidates::get() }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
let initial_bond_amount: BalanceOf<T> =
|
||||
<T as pallet::Config>::Currency::minimum_balance() * 2u32.into();
|
||||
CandidacyBond::<T>::put(initial_bond_amount);
|
||||
register_validators::<T>(c);
|
||||
register_candidates::<T>(c);
|
||||
let kicked = cmp::min(k, c);
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
let bond_amount = if k > 0 {
|
||||
CandidateList::<T>::mutate(|candidates| {
|
||||
for info in candidates.iter_mut().skip(kicked as usize) {
|
||||
info.deposit = <T as pallet::Config>::Currency::minimum_balance() * 3u32.into();
|
||||
}
|
||||
});
|
||||
<T as pallet::Config>::Currency::minimum_balance() * 3u32.into()
|
||||
} else {
|
||||
<T as pallet::Config>::Currency::minimum_balance()
|
||||
};
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin as T::RuntimeOrigin, bond_amount);
|
||||
|
||||
assert_last_event::<T>(Event::NewCandidacyBond { bond_amount }.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn update_bond(
|
||||
c: Linear<{ min_candidates::<T>() + 1 }, { T::MaxCandidates::get() }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
DesiredCandidates::<T>::put(c);
|
||||
|
||||
register_validators::<T>(c);
|
||||
register_candidates::<T>(c);
|
||||
|
||||
let caller = CandidateList::<T>::get()[0].who.clone();
|
||||
v2::whitelist!(caller);
|
||||
|
||||
let bond_amount: BalanceOf<T> = <T as pallet::Config>::Currency::minimum_balance() +
|
||||
<T as pallet::Config>::Currency::minimum_balance();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()), bond_amount);
|
||||
|
||||
assert_last_event::<T>(
|
||||
Event::CandidateBondUpdated { account_id: caller, deposit: bond_amount }.into(),
|
||||
);
|
||||
assert!(
|
||||
CandidateList::<T>::get().iter().last().unwrap().deposit ==
|
||||
<T as pallet::Config>::Currency::minimum_balance() * 2u32.into()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// worse case is when we have all the max-candidate slots filled except one, and we fill that
|
||||
// one.
|
||||
#[benchmark]
|
||||
fn register_as_candidate(c: Linear<1, { T::MaxCandidates::get() - 1 }>) {
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
DesiredCandidates::<T>::put(c + 1);
|
||||
|
||||
register_validators::<T>(c);
|
||||
register_candidates::<T>(c);
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let bond: BalanceOf<T> = <T as pallet::Config>::Currency::minimum_balance() * 2u32.into();
|
||||
<T as pallet::Config>::Currency::make_free_balance_be(&caller, bond);
|
||||
|
||||
<session::Pallet<T>>::ensure_can_pay_key_deposit(&caller).unwrap();
|
||||
<session::Pallet<T>>::set_keys(
|
||||
RawOrigin::Signed(caller.clone()).into(),
|
||||
keys::<T>(c + 1),
|
||||
Vec::new(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()));
|
||||
|
||||
assert_last_event::<T>(
|
||||
Event::CandidateAdded { account_id: caller, deposit: bond / 2u32.into() }.into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn take_candidate_slot(c: Linear<{ min_candidates::<T>() + 1 }, { T::MaxCandidates::get() }>) {
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
DesiredCandidates::<T>::put(1);
|
||||
|
||||
register_validators::<T>(c);
|
||||
register_candidates::<T>(c);
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let bond: BalanceOf<T> = <T as pallet::Config>::Currency::minimum_balance() * 10u32.into();
|
||||
<T as pallet::Config>::Currency::make_free_balance_be(&caller, bond);
|
||||
|
||||
<session::Pallet<T>>::ensure_can_pay_key_deposit(&caller).unwrap();
|
||||
<session::Pallet<T>>::set_keys(
|
||||
RawOrigin::Signed(caller.clone()).into(),
|
||||
keys::<T>(c + 1),
|
||||
Vec::new(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let target = CandidateList::<T>::get().iter().last().unwrap().who.clone();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()), bond / 2u32.into(), target.clone());
|
||||
|
||||
assert_last_event::<T>(
|
||||
Event::CandidateReplaced { old: target, new: caller, deposit: bond / 2u32.into() }
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
// worse case is the last candidate leaving.
|
||||
#[benchmark]
|
||||
fn leave_intent(c: Linear<{ min_candidates::<T>() + 1 }, { T::MaxCandidates::get() }>) {
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
DesiredCandidates::<T>::put(c);
|
||||
|
||||
register_validators::<T>(c);
|
||||
register_candidates::<T>(c);
|
||||
|
||||
let leaving = CandidateList::<T>::get().iter().last().unwrap().who.clone();
|
||||
v2::whitelist!(leaving);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(leaving.clone()));
|
||||
|
||||
assert_last_event::<T>(Event::CandidateRemoved { account_id: leaving }.into());
|
||||
}
|
||||
|
||||
// worse case is paying a non-existing candidate account.
|
||||
#[benchmark]
|
||||
fn note_author() {
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
<T as pallet::Config>::Currency::make_free_balance_be(
|
||||
&<CollatorSelection<T>>::account_id(),
|
||||
<T as pallet::Config>::Currency::minimum_balance() * 4u32.into(),
|
||||
);
|
||||
let author = account("author", 0, SEED);
|
||||
let new_block: BlockNumberFor<T> = 10u32.into();
|
||||
|
||||
pezframe_system::Pallet::<T>::set_block_number(new_block);
|
||||
assert!(<T as pallet::Config>::Currency::free_balance(&author) == 0u32.into());
|
||||
|
||||
#[block]
|
||||
{
|
||||
<CollatorSelection<T> as EventHandler<_, _>>::note_author(author.clone())
|
||||
}
|
||||
|
||||
assert!(<T as pallet::Config>::Currency::free_balance(&author) > 0u32.into());
|
||||
assert_eq!(pezframe_system::Pallet::<T>::block_number(), new_block);
|
||||
}
|
||||
|
||||
// worst case for new session.
|
||||
#[benchmark]
|
||||
fn new_session(
|
||||
r: Linear<1, { T::MaxCandidates::get() }>,
|
||||
c: Linear<1, { T::MaxCandidates::get() }>,
|
||||
) {
|
||||
CandidacyBond::<T>::put(<T as pallet::Config>::Currency::minimum_balance());
|
||||
DesiredCandidates::<T>::put(c);
|
||||
pezframe_system::Pallet::<T>::set_block_number(0u32.into());
|
||||
|
||||
register_validators::<T>(c);
|
||||
register_candidates::<T>(c);
|
||||
|
||||
let new_block: BlockNumberFor<T> = T::KickThreshold::get();
|
||||
let zero_block: BlockNumberFor<T> = 0u32.into();
|
||||
let candidates: Vec<T::AccountId> = CandidateList::<T>::get()
|
||||
.iter()
|
||||
.map(|candidate_info| candidate_info.who.clone())
|
||||
.collect();
|
||||
|
||||
let non_removals = c.saturating_sub(r);
|
||||
|
||||
for i in 0..c {
|
||||
LastAuthoredBlock::<T>::insert(candidates[i as usize].clone(), zero_block);
|
||||
}
|
||||
|
||||
if non_removals > 0 {
|
||||
for i in 0..non_removals {
|
||||
LastAuthoredBlock::<T>::insert(candidates[i as usize].clone(), new_block);
|
||||
}
|
||||
} else {
|
||||
for i in 0..c {
|
||||
LastAuthoredBlock::<T>::insert(candidates[i as usize].clone(), new_block);
|
||||
}
|
||||
}
|
||||
|
||||
let min_candidates = min_candidates::<T>();
|
||||
let pre_length = CandidateList::<T>::decode_len().unwrap_or_default();
|
||||
|
||||
pezframe_system::Pallet::<T>::set_block_number(new_block);
|
||||
|
||||
let current_length: u32 = CandidateList::<T>::decode_len()
|
||||
.unwrap_or_default()
|
||||
.try_into()
|
||||
.unwrap_or_default();
|
||||
assert!(c == current_length);
|
||||
#[block]
|
||||
{
|
||||
<CollatorSelection<T> as SessionManager<_>>::new_session(0);
|
||||
}
|
||||
|
||||
if c > r && non_removals >= min_candidates {
|
||||
// candidates > removals and remaining candidates > min candidates
|
||||
// => remaining candidates should be shorter than before removal, i.e. some were
|
||||
// actually removed.
|
||||
assert!(CandidateList::<T>::decode_len().unwrap_or_default() < pre_length);
|
||||
} else if c > r && non_removals < min_candidates {
|
||||
// candidates > removals and remaining candidates would be less than min candidates
|
||||
// => remaining candidates should equal min candidates, i.e. some were removed up to
|
||||
// the minimum, but then any more were "forced" to stay in candidates.
|
||||
let current_length: u32 = CandidateList::<T>::decode_len()
|
||||
.unwrap_or_default()
|
||||
.try_into()
|
||||
.unwrap_or_default();
|
||||
assert!(min_candidates == current_length);
|
||||
} else {
|
||||
// removals >= candidates, non removals must == 0
|
||||
// can't remove more than exist
|
||||
assert!(CandidateList::<T>::decode_len().unwrap_or_default() == pre_length);
|
||||
}
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(CollatorSelection, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,321 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// 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 module that is responsible for migration of storage for Collator Selection.
|
||||
|
||||
use super::*;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use alloc::vec::Vec;
|
||||
use pezframe_support::traits::{OnRuntimeUpgrade, UncheckedOnRuntimeUpgrade};
|
||||
use log;
|
||||
|
||||
/// Migrate to v2. Should have been part of <https://github.com/pezkuwichain/kurdistan-sdk/issues/104>.
|
||||
pub mod v2 {
|
||||
use super::*;
|
||||
use pezframe_support::{
|
||||
pezpallet_prelude::*,
|
||||
storage_alias,
|
||||
traits::{Currency, ReservableCurrency},
|
||||
};
|
||||
use pezsp_runtime::traits::{Saturating, Zero};
|
||||
|
||||
/// [`UncheckedMigrationToV2`] wrapped in a
|
||||
/// [`VersionedMigration`](pezframe_support::migrations::VersionedMigration), ensuring the
|
||||
/// migration is only performed when on-chain version is 1.
|
||||
pub type MigrationToV2<T> = pezframe_support::migrations::VersionedMigration<
|
||||
1,
|
||||
2,
|
||||
UncheckedMigrationToV2<T>,
|
||||
Pallet<T>,
|
||||
<T as pezframe_system::Config>::DbWeight,
|
||||
>;
|
||||
|
||||
#[storage_alias]
|
||||
pub type Candidates<T: Config> = StorageValue<
|
||||
Pallet<T>,
|
||||
BoundedVec<CandidateInfo<<T as pezframe_system::Config>::AccountId, <<T as Config>::Currency as Currency<<T as pezframe_system::Config>::AccountId>>::Balance>, <T as Config>::MaxCandidates>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
/// Migrate to V2.
|
||||
pub struct UncheckedMigrationToV2<T>(PhantomData<T>);
|
||||
impl<T: Config + pezpallet_balances::Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV2<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight = Weight::zero();
|
||||
let mut count: u64 = 0;
|
||||
// candidates who exist under the old `Candidates` key
|
||||
let candidates = Candidates::<T>::take();
|
||||
|
||||
// New candidates who have registered since the upgrade. Under normal circumstances,
|
||||
// this should not exist because the migration should be applied when the upgrade
|
||||
// happens. But in Pezkuwi/Kusama we messed this up, and people registered under
|
||||
// `CandidateList` while their funds were locked in `Candidates`.
|
||||
let new_candidate_list = CandidateList::<T>::get();
|
||||
if new_candidate_list.len().is_zero() {
|
||||
// The new list is empty, so this is essentially being applied correctly. We just
|
||||
// put the candidates into the new storage item.
|
||||
CandidateList::<T>::put(&candidates);
|
||||
// 1 write for the new list
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1));
|
||||
} else {
|
||||
// Oops, the runtime upgraded without the migration. There are new candidates in
|
||||
// `CandidateList`. So, let's just refund the old ones and assume they have already
|
||||
// started participating in the new system.
|
||||
for candidate in candidates {
|
||||
let err = T::Currency::unreserve(&candidate.who, candidate.deposit);
|
||||
if err > Zero::zero() {
|
||||
log::error!(
|
||||
target: LOG_TARGET,
|
||||
"{:?} balance was unable to be unreserved from {:?}",
|
||||
err, &candidate.who,
|
||||
);
|
||||
}
|
||||
count.saturating_inc();
|
||||
}
|
||||
weight.saturating_accrue(
|
||||
<<T as pezpallet_balances::Config>::WeightInfo as pezpallet_balances::WeightInfo>::force_unreserve().saturating_mul(count.into()),
|
||||
);
|
||||
}
|
||||
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Unreserved locked bond of {} candidates, upgraded storage to version 2",
|
||||
count,
|
||||
);
|
||||
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(3, 2));
|
||||
weight
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, pezsp_runtime::DispatchError> {
|
||||
let number_of_candidates = Candidates::<T>::get().to_vec().len();
|
||||
Ok((number_of_candidates as u32).encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_number_of_candidates: Vec<u8>) -> Result<(), pezsp_runtime::DispatchError> {
|
||||
let new_number_of_candidates = Candidates::<T>::get().to_vec().len();
|
||||
assert_eq!(
|
||||
new_number_of_candidates, 0 as usize,
|
||||
"after migration, the candidates map should be empty"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Version 1 Migration
|
||||
/// This migration ensures that any existing `Invulnerables` storage lists are sorted.
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
use pezframe_support::pezpallet_prelude::*;
|
||||
|
||||
pub struct MigrateToV1<T>(PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let on_chain_version = Pallet::<T>::on_chain_storage_version();
|
||||
if on_chain_version == 0 {
|
||||
let invulnerables_len = Invulnerables::<T>::get().to_vec().len();
|
||||
Invulnerables::<T>::mutate(|invulnerables| {
|
||||
invulnerables.sort();
|
||||
});
|
||||
|
||||
StorageVersion::new(1).put::<Pallet<T>>();
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Sorted {} Invulnerables, upgraded storage to version 1",
|
||||
invulnerables_len,
|
||||
);
|
||||
// Similar complexity to `set_invulnerables` (put storage value)
|
||||
// Plus 1 read for length, 1 read for `on_chain_version`, 1 write to put version
|
||||
T::WeightInfo::set_invulnerables(invulnerables_len as u32)
|
||||
.saturating_add(T::DbWeight::get().reads_writes(2, 1))
|
||||
} else {
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Migration did not execute. This probably should be removed"
|
||||
);
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, pezsp_runtime::DispatchError> {
|
||||
let number_of_invulnerables = Invulnerables::<T>::get().to_vec().len();
|
||||
Ok((number_of_invulnerables as u32).encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(number_of_invulnerables: Vec<u8>) -> Result<(), pezsp_runtime::DispatchError> {
|
||||
let stored_invulnerables = Invulnerables::<T>::get().to_vec();
|
||||
let mut sorted_invulnerables = stored_invulnerables.clone();
|
||||
sorted_invulnerables.sort();
|
||||
assert_eq!(
|
||||
stored_invulnerables, sorted_invulnerables,
|
||||
"after migration, the stored invulnerables should be sorted"
|
||||
);
|
||||
|
||||
let number_of_invulnerables: u32 = Decode::decode(
|
||||
&mut number_of_invulnerables.as_slice(),
|
||||
)
|
||||
.expect("the state parameter should be something that was generated by pre_upgrade");
|
||||
let stored_invulnerables_len = stored_invulnerables.len() as u32;
|
||||
assert_eq!(
|
||||
number_of_invulnerables, stored_invulnerables_len,
|
||||
"after migration, there should be the same number of invulnerables"
|
||||
);
|
||||
|
||||
let on_chain_version = Pallet::<T>::on_chain_storage_version();
|
||||
pezframe_support::ensure!(on_chain_version >= 1, "must_upgrade");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "try-runtime", test))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
migration::v2::Candidates,
|
||||
mock::{new_test_ext, Balances, Test},
|
||||
};
|
||||
use pezframe_support::{
|
||||
traits::{Currency, ReservableCurrency, StorageVersion},
|
||||
BoundedVec,
|
||||
};
|
||||
use pezsp_runtime::traits::ConstU32;
|
||||
|
||||
#[test]
|
||||
fn migrate_to_v2_with_new_candidates() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let storage_version = StorageVersion::new(1);
|
||||
storage_version.put::<Pallet<Test>>();
|
||||
|
||||
let one = 1u64;
|
||||
let two = 2u64;
|
||||
let three = 3u64;
|
||||
let deposit = 10u64;
|
||||
|
||||
// Set balance to 100
|
||||
Balances::make_free_balance_be(&one, 100u64);
|
||||
Balances::make_free_balance_be(&two, 100u64);
|
||||
Balances::make_free_balance_be(&three, 100u64);
|
||||
|
||||
// Reservations: 10 for the "old" candidacy and 10 for the "new"
|
||||
Balances::reserve(&one, 10u64).unwrap(); // old
|
||||
Balances::reserve(&two, 20u64).unwrap(); // old + new
|
||||
Balances::reserve(&three, 10u64).unwrap(); // new
|
||||
|
||||
// Candidate info
|
||||
let candidate_one = CandidateInfo { who: one, deposit };
|
||||
let candidate_two = CandidateInfo { who: two, deposit };
|
||||
let candidate_three = CandidateInfo { who: three, deposit };
|
||||
|
||||
// Storage lists
|
||||
let bounded_candidates =
|
||||
BoundedVec::<CandidateInfo<u64, u64>, ConstU32<20>>::try_from(vec![
|
||||
candidate_one.clone(),
|
||||
candidate_two.clone(),
|
||||
])
|
||||
.expect("it works");
|
||||
let bounded_candidate_list =
|
||||
BoundedVec::<CandidateInfo<u64, u64>, ConstU32<20>>::try_from(vec![
|
||||
candidate_two.clone(),
|
||||
candidate_three.clone(),
|
||||
])
|
||||
.expect("it works");
|
||||
|
||||
// Set storage
|
||||
Candidates::<Test>::put(bounded_candidates);
|
||||
CandidateList::<Test>::put(bounded_candidate_list.clone());
|
||||
|
||||
// Sanity check
|
||||
assert_eq!(Balances::free_balance(one), 90);
|
||||
assert_eq!(Balances::free_balance(two), 80);
|
||||
assert_eq!(Balances::free_balance(three), 90);
|
||||
|
||||
// Run migration
|
||||
v2::MigrationToV2::<Test>::on_runtime_upgrade();
|
||||
|
||||
let new_storage_version = StorageVersion::get::<Pallet<Test>>();
|
||||
assert_eq!(new_storage_version, 2);
|
||||
|
||||
// 10 should have been unreserved from the old candidacy
|
||||
assert_eq!(Balances::free_balance(one), 100);
|
||||
assert_eq!(Balances::free_balance(two), 90);
|
||||
assert_eq!(Balances::free_balance(three), 90);
|
||||
// The storage item should be gone
|
||||
assert!(Candidates::<Test>::get().is_empty());
|
||||
// The new storage item should be preserved
|
||||
assert_eq!(CandidateList::<Test>::get(), bounded_candidate_list);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn migrate_to_v2_without_new_candidates() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let storage_version = StorageVersion::new(1);
|
||||
storage_version.put::<Pallet<Test>>();
|
||||
|
||||
let one = 1u64;
|
||||
let two = 2u64;
|
||||
let deposit = 10u64;
|
||||
|
||||
// Set balance to 100
|
||||
Balances::make_free_balance_be(&one, 100u64);
|
||||
Balances::make_free_balance_be(&two, 100u64);
|
||||
|
||||
// Reservations
|
||||
Balances::reserve(&one, 10u64).unwrap(); // old
|
||||
Balances::reserve(&two, 10u64).unwrap(); // old
|
||||
|
||||
// Candidate info
|
||||
let candidate_one = CandidateInfo { who: one, deposit };
|
||||
let candidate_two = CandidateInfo { who: two, deposit };
|
||||
|
||||
// Storage lists
|
||||
let bounded_candidates =
|
||||
BoundedVec::<CandidateInfo<u64, u64>, ConstU32<20>>::try_from(vec![
|
||||
candidate_one.clone(),
|
||||
candidate_two.clone(),
|
||||
])
|
||||
.expect("it works");
|
||||
|
||||
// Set storage
|
||||
Candidates::<Test>::put(bounded_candidates.clone());
|
||||
|
||||
// Sanity check
|
||||
assert_eq!(Balances::free_balance(one), 90);
|
||||
assert_eq!(Balances::free_balance(two), 90);
|
||||
|
||||
// Run migration
|
||||
v2::MigrationToV2::<Test>::on_runtime_upgrade();
|
||||
|
||||
let new_storage_version = StorageVersion::get::<Pallet<Test>>();
|
||||
assert_eq!(new_storage_version, 2);
|
||||
|
||||
// Nothing changes deposit-wise
|
||||
assert_eq!(Balances::free_balance(one), 90);
|
||||
assert_eq!(Balances::free_balance(two), 90);
|
||||
// The storage item should be gone
|
||||
assert!(Candidates::<Test>::get().is_empty());
|
||||
// The new storage item should have the info now
|
||||
assert_eq!(CandidateList::<Test>::get(), bounded_candidates);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
// 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::*;
|
||||
use crate as collator_selection;
|
||||
use pezframe_support::{
|
||||
derive_impl, ord_parameter_types, parameter_types,
|
||||
traits::{ConstBool, ConstU32, ConstU64, FindAuthor, ValidatorRegistration},
|
||||
PalletId,
|
||||
};
|
||||
use pezframe_system as system;
|
||||
use pezframe_system::EnsureSignedBy;
|
||||
use pezsp_runtime::{testing::UintAuthorityId, traits::OpaqueKeys, BuildStorage, RuntimeAppPublic};
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
// Configure a mock runtime to test the pallet.
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system,
|
||||
Timestamp: pezpallet_timestamp,
|
||||
Session: pezpallet_session,
|
||||
Aura: pezpallet_aura,
|
||||
Balances: pezpallet_balances,
|
||||
CollatorSelection: collator_selection,
|
||||
Authorship: pezpallet_authorship,
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const SS58Prefix: u8 = 42;
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl system::Config for Test {
|
||||
type Block = Block;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
type SS58Prefix = SS58Prefix;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 5;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
pub struct Author4;
|
||||
impl FindAuthor<u64> for Author4 {
|
||||
fn find_author<'a, I>(_digests: I) -> Option<u64>
|
||||
where
|
||||
I: 'a + IntoIterator<Item = (pezframe_support::ConsensusEngineId, &'a [u8])>,
|
||||
{
|
||||
Some(4)
|
||||
}
|
||||
}
|
||||
|
||||
impl pezpallet_authorship::Config for Test {
|
||||
type FindAuthor = Author4;
|
||||
type EventHandler = CollatorSelection;
|
||||
}
|
||||
|
||||
impl pezpallet_timestamp::Config for Test {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = Aura;
|
||||
type MinimumPeriod = ConstU64<1>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl pezpallet_aura::Config for Test {
|
||||
type AuthorityId = pezsp_consensus_aura::sr25519::AuthorityId;
|
||||
type MaxAuthorities = ConstU32<100_000>;
|
||||
type DisabledValidators = ();
|
||||
type AllowMultipleBlocksPerSlot = ConstBool<false>;
|
||||
type SlotDuration = pezpallet_aura::MinimumPeriodTimesTwo<Self>;
|
||||
}
|
||||
|
||||
pezsp_runtime::impl_opaque_keys! {
|
||||
pub struct MockSessionKeys {
|
||||
// a key for aura authoring
|
||||
pub aura: UintAuthorityId,
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UintAuthorityId> for MockSessionKeys {
|
||||
fn from(aura: pezsp_runtime::testing::UintAuthorityId) -> Self {
|
||||
Self { aura }
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static SessionHandlerCollators: Vec<u64> = Vec::new();
|
||||
pub static SessionChangeBlock: u64 = 0;
|
||||
}
|
||||
|
||||
pub struct TestSessionHandler;
|
||||
impl pezpallet_session::SessionHandler<u64> for TestSessionHandler {
|
||||
const KEY_TYPE_IDS: &'static [pezsp_runtime::KeyTypeId] = &[UintAuthorityId::ID];
|
||||
fn on_genesis_session<Ks: OpaqueKeys>(keys: &[(u64, Ks)]) {
|
||||
SessionHandlerCollators::set(keys.iter().map(|(a, _)| *a).collect::<Vec<_>>())
|
||||
}
|
||||
fn on_new_session<Ks: OpaqueKeys>(_: bool, keys: &[(u64, Ks)], _: &[(u64, Ks)]) {
|
||||
SessionChangeBlock::set(System::block_number());
|
||||
SessionHandlerCollators::set(keys.iter().map(|(a, _)| *a).collect::<Vec<_>>())
|
||||
}
|
||||
fn on_before_session_ending() {}
|
||||
fn on_disabled(_: u32) {}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const Offset: u64 = 0;
|
||||
pub const Period: u64 = 10;
|
||||
}
|
||||
|
||||
impl pezpallet_session::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type ValidatorId = <Self as pezframe_system::Config>::AccountId;
|
||||
// we don't have stash and controller, thus we don't need the convert as well.
|
||||
type ValidatorIdOf = IdentityCollator;
|
||||
type ShouldEndSession = pezpallet_session::PeriodicSessions<Period, Offset>;
|
||||
type NextSessionRotation = pezpallet_session::PeriodicSessions<Period, Offset>;
|
||||
type SessionManager = CollatorSelection;
|
||||
type SessionHandler = TestSessionHandler;
|
||||
type Keys = MockSessionKeys;
|
||||
type DisablingStrategy = ();
|
||||
type WeightInfo = ();
|
||||
type Currency = Balances;
|
||||
type KeyDeposit = ();
|
||||
}
|
||||
|
||||
ord_parameter_types! {
|
||||
pub const RootAccount: u64 = 777;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
}
|
||||
|
||||
pub struct IsRegistered;
|
||||
impl ValidatorRegistration<u64> for IsRegistered {
|
||||
fn is_registered(id: &u64) -> bool {
|
||||
*id != 42u64
|
||||
}
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = EnsureSignedBy<RootAccount, u64>;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<20>;
|
||||
type MinEligibleCollators = ConstU32<1>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as pezframe_system::Config>::AccountId;
|
||||
type ValidatorIdOf = IdentityCollator;
|
||||
type ValidatorRegistration = IsRegistered;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
pezsp_tracing::try_init_simple();
|
||||
let mut t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
let invulnerables = vec![2, 1]; // unsorted
|
||||
|
||||
let balances = vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)];
|
||||
let keys = balances
|
||||
.iter()
|
||||
.map(|&(i, _)| (i, i, MockSessionKeys { aura: UintAuthorityId(i) }))
|
||||
.collect::<Vec<_>>();
|
||||
let collator_selection = collator_selection::GenesisConfig::<Test> {
|
||||
desired_candidates: 2,
|
||||
candidacy_bond: 10,
|
||||
invulnerables,
|
||||
};
|
||||
let session = pezpallet_session::GenesisConfig::<Test> { keys, ..Default::default() };
|
||||
pezpallet_balances::GenesisConfig::<Test> { balances, ..Default::default() }
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
// collator selection must be initialized before session.
|
||||
collator_selection.assimilate_storage(&mut t).unwrap();
|
||||
session.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
t.into()
|
||||
}
|
||||
|
||||
pub fn initialize_to_block(n: u64) {
|
||||
for i in System::block_number() + 1..=n {
|
||||
System::set_block_number(i);
|
||||
<AllPalletsWithSystem as pezframe_support::traits::OnInitialize<u64>>::on_initialize(i);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,243 @@
|
||||
// This file is part of Pezcumulus.
|
||||
|
||||
// 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.
|
||||
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use pezframe_support::{
|
||||
traits::Get,
|
||||
weights::{constants::RocksDbWeight, Weight},
|
||||
};
|
||||
|
||||
// The weight info trait for `pezpallet_collator_selection`.
|
||||
pub trait WeightInfo {
|
||||
fn set_invulnerables(_b: u32) -> Weight;
|
||||
fn add_invulnerable(_b: u32, _c: u32) -> Weight;
|
||||
fn remove_invulnerable(_b: u32) -> Weight;
|
||||
fn set_desired_candidates() -> Weight;
|
||||
fn set_candidacy_bond(_c: u32, _k: u32) -> Weight;
|
||||
fn register_as_candidate(_c: u32) -> Weight;
|
||||
fn leave_intent(_c: u32) -> Weight;
|
||||
fn update_bond(_c: u32) -> Weight;
|
||||
fn take_candidate_slot(_c: u32) -> Weight;
|
||||
fn note_author() -> Weight;
|
||||
fn new_session(_c: u32, _r: u32) -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for pezpallet_collator_selection using the Bizinikiwi node and recommended hardware.
|
||||
pub struct BizinikiwiWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
|
||||
fn set_invulnerables(b: u32) -> Weight {
|
||||
Weight::from_parts(18_563_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(68_000_u64, 0).saturating_mul(b as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
fn set_desired_candidates() -> Weight {
|
||||
Weight::from_parts(16_363_000_u64, 0).saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
fn set_candidacy_bond(_c: u32, _k: u32) -> Weight {
|
||||
Weight::from_parts(16_840_000_u64, 0).saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
fn register_as_candidate(c: u32) -> Weight {
|
||||
Weight::from_parts(71_196_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(198_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
fn leave_intent(c: u32) -> Weight {
|
||||
Weight::from_parts(55_336_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(151_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
fn update_bond(c: u32) -> Weight {
|
||||
Weight::from_parts(55_336_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(151_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
fn take_candidate_slot(c: u32) -> Weight {
|
||||
Weight::from_parts(71_196_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(198_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
fn note_author() -> Weight {
|
||||
Weight::from_parts(71_461_000_u64, 0)
|
||||
.saturating_add(T::DbWeight::get().reads(3_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(4_u64))
|
||||
}
|
||||
fn new_session(r: u32, c: u32) -> Weight {
|
||||
Weight::from_parts(0_u64, 0)
|
||||
// Standard Error: 1_010_000
|
||||
.saturating_add(Weight::from_parts(109_961_000_u64, 0).saturating_mul(r as u64))
|
||||
// Standard Error: 1_010_000
|
||||
.saturating_add(Weight::from_parts(151_952_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64.saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64.saturating_mul(c as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64.saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64.saturating_mul(c as u64)))
|
||||
}
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added:
|
||||
/// 1136, mode: MaxEncodedLen) Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297,
|
||||
/// mode: MaxEncodedLen) Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode:
|
||||
/// MaxEncodedLen) The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added:
|
||||
/// 3697, mode: MaxEncodedLen) The range of component `b` is `[1, 100]`.
|
||||
fn remove_invulnerable(b: u32) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `119 + b * (32 ±0)`
|
||||
// Estimated: `4687`
|
||||
// Minimum execution time: 183_054_000 picoseconds.
|
||||
Weight::from_parts(197_205_427, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 13_533
|
||||
.saturating_add(Weight::from_parts(376_231, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn set_invulnerables(b: u32) -> Weight {
|
||||
Weight::from_parts(18_563_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(68_000_u64, 0).saturating_mul(b as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
fn set_desired_candidates() -> Weight {
|
||||
Weight::from_parts(16_363_000_u64, 0).saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
fn set_candidacy_bond(_c: u32, _k: u32) -> Weight {
|
||||
Weight::from_parts(16_840_000_u64, 0).saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
fn register_as_candidate(c: u32) -> Weight {
|
||||
Weight::from_parts(71_196_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(198_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
fn leave_intent(c: u32) -> Weight {
|
||||
Weight::from_parts(55_336_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(151_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
fn note_author() -> Weight {
|
||||
Weight::from_parts(71_461_000_u64, 0)
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(4_u64))
|
||||
}
|
||||
fn update_bond(c: u32) -> Weight {
|
||||
Weight::from_parts(55_336_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(151_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(4_u64))
|
||||
}
|
||||
fn take_candidate_slot(c: u32) -> Weight {
|
||||
Weight::from_parts(71_196_000_u64, 0)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(198_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(4_u64))
|
||||
}
|
||||
fn new_session(r: u32, c: u32) -> Weight {
|
||||
Weight::from_parts(0_u64, 0)
|
||||
// Standard Error: 1_010_000
|
||||
.saturating_add(Weight::from_parts(109_961_000_u64, 0).saturating_mul(r as u64))
|
||||
// Standard Error: 1_010_000
|
||||
.saturating_add(Weight::from_parts(151_952_000_u64, 0).saturating_mul(c as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64.saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64.saturating_mul(c as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64.saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64.saturating_mul(c as u64)))
|
||||
}
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added:
|
||||
/// 1136, mode: MaxEncodedLen) Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297,
|
||||
/// mode: MaxEncodedLen) Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode:
|
||||
/// MaxEncodedLen) The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4))
|
||||
.saturating_add(RocksDbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added:
|
||||
/// 3697, mode: MaxEncodedLen) The range of component `b` is `[1, 100]`.
|
||||
fn remove_invulnerable(b: u32) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `119 + b * (32 ±0)`
|
||||
// Estimated: `4687`
|
||||
// Minimum execution time: 183_054_000 picoseconds.
|
||||
Weight::from_parts(197_205_427, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 13_533
|
||||
.saturating_add(Weight::from_parts(376_231, 0).saturating_mul(b.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user