Decouple Staking and Election - Part 2 Unsigned Phase (#7909)

* Base features and traits.

* pallet and unsigned phase

* Undo bad formattings.

* some formatting cleanup.

* Small self-cleanup.

* Make it all build

* self-review

* Some doc tests.

* Some changes from other PR

* Fix session test

* Update Cargo.lock

* Update frame/election-provider-multi-phase/src/lib.rs

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

* Some review comments

* Rename + make encode/decode

* Do an assert as well, just in case.

* Fix build

* Update frame/election-provider-multi-phase/src/unsigned.rs

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

* Las comment

* fix staking fuzzer.

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

* Add one last layer of feasibility check as well.

* Last fixes to benchmarks

* Some more docs.

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

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

* Some nits

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

* Fix doc

* Mkae ci green

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Co-authored-by: Parity Benchmarking Bot <admin@parity.io>
This commit is contained in:
Kian Paimani
2021-02-23 14:46:17 +00:00
committed by GitHub
parent ba659f9440
commit 7205eea40d
34 changed files with 4092 additions and 231 deletions
+275 -51
View File
@@ -328,15 +328,13 @@ use frame_system::{
};
use sp_npos_elections::{
ExtendedBalance, Assignment, ElectionScore, ElectionResult as PrimitiveElectionResult,
to_support_map, EvaluateSupport, seq_phragmen, generate_solution_type, is_score_better,
SupportMap, VoteWeight, CompactSolution, PerThing128,
to_supports, EvaluateSupport, seq_phragmen, generate_solution_type, is_score_better, Supports,
VoteWeight, CompactSolution, PerThing128,
};
use sp_election_providers::ElectionProvider;
pub use weights::WeightInfo;
const STAKING_ID: LockIdentifier = *b"staking ";
pub const MAX_UNLOCKING_CHUNKS: usize = 32;
pub const MAX_NOMINATIONS: usize = <CompactAssignments as CompactSolution>::LIMIT;
pub(crate) const LOG_TARGET: &'static str = "staking";
// syntactic sugar for logging.
@@ -345,7 +343,7 @@ macro_rules! log {
($level:tt, $patter:expr $(, $values:expr)* $(,)?) => {
frame_support::debug::$level!(
target: crate::LOG_TARGET,
$patter $(, $values)*
concat!("💸 ", $patter) $(, $values)*
)
};
}
@@ -365,6 +363,10 @@ static_assertions::const_assert!(size_of::<NominatorIndex>() <= size_of::<u32>()
/// Maximum number of stakers that can be stored in a snapshot.
pub(crate) const MAX_VALIDATORS: usize = ValidatorIndex::max_value() as usize;
pub(crate) const MAX_NOMINATORS: usize = NominatorIndex::max_value() as usize;
pub const MAX_NOMINATIONS: usize =
<CompactAssignments as sp_npos_elections::CompactSolution>::LIMIT;
pub const MAX_UNLOCKING_CHUNKS: usize = 32;
/// Counter for the number of eras that have passed.
pub type EraIndex = u32;
@@ -388,10 +390,12 @@ pub type OffchainAccuracy = PerU16;
pub type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
type PositiveImbalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::PositiveImbalance;
type NegativeImbalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
type PositiveImbalanceOf<T> = <<T as Config>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::PositiveImbalance;
type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::NegativeImbalance;
/// Information regarding the active era (era in used in session).
#[derive(Encode, Decode, RuntimeDebug)]
@@ -778,7 +782,7 @@ impl<T: Config> SessionInterface<<T as frame_system::Config>::AccountId> for T w
pub trait Config: frame_system::Config + SendTransactionTypes<Call<Self>> {
/// The staking balance.
type Currency: LockableCurrency<Self::AccountId, Moment=Self::BlockNumber>;
type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>;
/// Time used for computing era duration.
///
@@ -793,6 +797,14 @@ pub trait Config: frame_system::Config + SendTransactionTypes<Call<Self>> {
/// [`BalanceOf`].
type CurrencyToVote: CurrencyToVote<BalanceOf<Self>>;
/// Something that provides the election functionality.
type ElectionProvider: sp_election_providers::ElectionProvider<
Self::AccountId,
Self::BlockNumber,
// we only accept an election provider that has staking as data provider.
DataProvider = Module<Self>,
>;
/// Tokens have been minted and are unused for validator-reward.
/// See [Era payout](./index.html#era-payout).
type RewardRemainder: OnUnbalanced<NegativeImbalanceOf<Self>>;
@@ -889,7 +901,9 @@ pub enum Forcing {
}
impl Default for Forcing {
fn default() -> Self { Forcing::NotForcing }
fn default() -> Self {
Forcing::NotForcing
}
}
// A value placed in storage that represents the current version of the Staking storage. This value
@@ -1066,28 +1080,45 @@ decl_storage! {
/// The earliest era for which we have a pending, unapplied slash.
EarliestUnappliedSlash: Option<EraIndex>;
/// The last planned session scheduled by the session pallet.
///
/// This is basically in sync with the call to [`SessionManager::new_session`].
pub CurrentPlannedSession get(fn current_planned_session): SessionIndex;
/// Snapshot of validators at the beginning of the current election window. This should only
/// have a value when [`EraElectionStatus`] == `ElectionStatus::Open(_)`.
///
/// TWO_PHASE_NOTE: should be removed once we switch to multi-phase.
pub SnapshotValidators get(fn snapshot_validators): Option<Vec<T::AccountId>>;
/// Snapshot of nominators at the beginning of the current election window. This should only
/// have a value when [`EraElectionStatus`] == `ElectionStatus::Open(_)`.
///
/// TWO_PHASE_NOTE: should be removed once we switch to multi-phase.
pub SnapshotNominators get(fn snapshot_nominators): Option<Vec<T::AccountId>>;
/// The next validator set. At the end of an era, if this is available (potentially from the
/// result of an offchain worker), it is immediately used. Otherwise, the on-chain election
/// is executed.
///
/// TWO_PHASE_NOTE: should be removed once we switch to multi-phase.
pub QueuedElected get(fn queued_elected): Option<ElectionResult<T::AccountId, BalanceOf<T>>>;
/// The score of the current [`QueuedElected`].
///
/// TWO_PHASE_NOTE: should be removed once we switch to multi-phase.
pub QueuedScore get(fn queued_score): Option<ElectionScore>;
/// Flag to control the execution of the offchain election. When `Open(_)`, we accept
/// solutions to be submitted.
///
/// TWO_PHASE_NOTE: should be removed once we switch to multi-phase.
pub EraElectionStatus get(fn era_election_status): ElectionStatus<T::BlockNumber>;
/// True if the current **planned** session is final. Note that this does not take era
/// forcing into account.
///
/// TWO_PHASE_NOTE: should be removed once we switch to multi-phase.
pub IsCurrentSessionFinal get(fn is_current_session_final): bool = false;
/// True if network has been upgraded to this version.
@@ -1345,14 +1376,14 @@ decl_module! {
ElectionStatus::<T::BlockNumber>::Open(now)
);
add_weight(0, 1, 0);
log!(info, "💸 Election window is Open({:?}). Snapshot created", now);
log!(info, "Election window is Open({:?}). Snapshot created", now);
} else {
log!(warn, "💸 Failed to create snapshot at {:?}.", now);
log!(warn, "Failed to create snapshot at {:?}.", now);
}
}
}
} else {
log!(warn, "💸 Estimating next session change failed.");
log!(warn, "Estimating next session change failed.");
}
add_weight(0, 0, T::NextNewSession::weight(now))
}
@@ -1367,16 +1398,15 @@ decl_module! {
/// to open. If so, it runs the offchain worker code.
fn offchain_worker(now: T::BlockNumber) {
use offchain_election::{set_check_offchain_execution_status, compute_offchain_election};
if Self::era_election_status().is_open_at(now) {
let offchain_status = set_check_offchain_execution_status::<T>(now);
if let Err(why) = offchain_status {
log!(warn, "💸 skipping offchain worker in open election window due to [{}]", why);
log!(warn, "skipping offchain worker in open election window due to [{}]", why);
} else {
if let Err(e) = compute_offchain_election::<T>() {
log!(error, "💸 Error in election offchain worker: {:?}", e);
log!(error, "Error in election offchain worker: {:?}", e);
} else {
log!(debug, "💸 Executed offchain worker thread without errors.");
log!(debug, "Executed offchain worker thread without errors.");
}
}
}
@@ -2267,7 +2297,10 @@ impl<T: Config> Module<T> {
}
/// Internal impl of [`Self::slashable_balance_of`] that returns [`VoteWeight`].
pub fn slashable_balance_of_vote_weight(stash: &T::AccountId, issuance: BalanceOf<T>) -> VoteWeight {
pub fn slashable_balance_of_vote_weight(
stash: &T::AccountId,
issuance: BalanceOf<T>,
) -> VoteWeight {
T::CurrencyToVote::to_vote(Self::slashable_balance_of(stash), issuance)
}
@@ -2306,7 +2339,7 @@ impl<T: Config> Module<T> {
{
log!(
warn,
"💸 Snapshot size too big [{} <> {}][{} <> {}].",
"Snapshot size too big [{} <> {}][{} <> {}].",
num_validators,
MAX_VALIDATORS,
num_nominators,
@@ -2330,10 +2363,7 @@ impl<T: Config> Module<T> {
<SnapshotNominators<T>>::kill();
}
fn do_payout_stakers(
validator_stash: T::AccountId,
era: EraIndex,
) -> DispatchResult {
fn do_payout_stakers(validator_stash: T::AccountId, era: EraIndex) -> DispatchResult {
// Validate input data
let current_era = CurrentEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
ensure!(era <= current_era, Error::<T>::InvalidEraToReward);
@@ -2626,7 +2656,7 @@ impl<T: Config> Module<T> {
validator_at,
).map_err(|e| {
// log the error since it is not propagated into the runtime error.
log!(warn, "💸 un-compacting solution failed due to {:?}", e);
log!(warn, "un-compacting solution failed due to {:?}", e);
Error::<T>::OffchainElectionBogusCompact
})?;
@@ -2641,7 +2671,7 @@ impl<T: Config> Module<T> {
// all of the indices must map to either a validator or a nominator. If this is ever
// not the case, then the locking system of staking is most likely faulty, or we
// have bigger problems.
log!(error, "💸 detected an error in the staking locking and snapshot.");
log!(error, "detected an error in the staking locking and snapshot.");
// abort.
return Err(Error::<T>::OffchainElectionBogusNominator.into());
}
@@ -2690,7 +2720,7 @@ impl<T: Config> Module<T> {
);
// build the support map thereof in order to evaluate.
let supports = to_support_map::<T::AccountId>(&winners, &staked_assignments)
let supports = to_supports(&winners, &staked_assignments)
.map_err(|_| Error::<T>::OffchainElectionBogusEdge)?;
// Check if the score is the same as the claimed one.
@@ -2698,10 +2728,11 @@ impl<T: Config> Module<T> {
ensure!(submitted_score == claimed_score, Error::<T>::OffchainElectionBogusScore);
// At last, alles Ok. Exposures and store the result.
let exposures = Self::collect_exposure(supports);
let exposures = Self::collect_exposures(supports);
log!(
info,
"💸 A better solution (with compute {:?} and score {:?}) has been validated and stored on chain.",
"A better solution (with compute {:?} and score {:?}) has been validated and stored \
on chain.",
compute,
submitted_score,
);
@@ -2834,6 +2865,8 @@ impl<T: Config> Module<T> {
// Set staking information for new era.
let maybe_new_validators = Self::select_and_update_validators(current_era);
// TWO_PHASE_NOTE: use this later on.
let _unused_new_validators = Self::enact_election(current_era);
maybe_new_validators
}
@@ -2901,7 +2934,7 @@ impl<T: Config> Module<T> {
log!(
info,
"💸 new validator set of size {:?} has been elected via {:?} for era {:?}",
"new validator set of size {:?} has been elected via {:?} for staring era {:?}",
elected_stashes.len(),
compute,
current_era,
@@ -2950,20 +2983,20 @@ impl<T: Config> Module<T> {
Self::slashable_balance_of_fn(),
);
let supports = to_support_map::<T::AccountId>(
let supports = to_supports(
&elected_stashes,
&staked_assignments,
)
.map_err(|_|
log!(
error,
"💸 on-chain phragmen is failing due to a problem in the result. This must be a bug."
"on-chain phragmen is failing due to a problem in the result. This must be a bug."
)
)
.ok()?;
// collect exposures
let exposures = Self::collect_exposure(supports);
let exposures = Self::collect_exposures(supports);
// In order to keep the property required by `on_session_ending` that we must return the
// new validator set even if it's the same as the old, as long as any underlying
@@ -3025,7 +3058,7 @@ impl<T: Config> Module<T> {
// If we don't have enough candidates, nothing to do.
log!(
warn,
"💸 Chain does not have enough staking candidates to operate. Era {:?}.",
"chain does not have enough staking candidates to operate. Era {:?}.",
Self::current_era()
);
None
@@ -3041,9 +3074,10 @@ impl<T: Config> Module<T> {
}
}
/// Consume a set of [`Supports`] from [`sp_npos_elections`] and collect them into a [`Exposure`]
fn collect_exposure(
supports: SupportMap<T::AccountId>,
/// Consume a set of [`Supports`] from [`sp_npos_elections`] and collect them into a
/// [`Exposure`].
fn collect_exposures(
supports: Supports<T::AccountId>,
) -> Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)> {
let total_issuance = T::Currency::total_issuance();
let to_currency = |e: ExtendedBalance| T::CurrencyToVote::to_currency(e, total_issuance);
@@ -3075,6 +3109,80 @@ impl<T: Config> Module<T> {
}).collect::<Vec<(T::AccountId, Exposure<_, _>)>>()
}
/// Process the output of the election.
///
/// This ensures enough validators have been elected, converts all supports to exposures and
/// writes them to the associated storage.
///
/// Returns `Err(())` if less than [`MinimumValidatorCount`] validators have been elected, `Ok`
/// otherwise.
// TWO_PHASE_NOTE: remove the dead code.
#[allow(dead_code)]
pub fn process_election(
flat_supports: sp_npos_elections::Supports<T::AccountId>,
current_era: EraIndex,
) -> Result<Vec<T::AccountId>, ()> {
let exposures = Self::collect_exposures(flat_supports);
let elected_stashes = exposures.iter().cloned().map(|(x, _)| x).collect::<Vec<_>>();
if (elected_stashes.len() as u32) <= Self::minimum_validator_count() {
log!(
warn,
"chain does not have enough staking candidates to operate for era {:?}",
current_era,
);
return Err(());
}
// Populate Stakers and write slot stake.
let mut total_stake: BalanceOf<T> = Zero::zero();
exposures.into_iter().for_each(|(stash, exposure)| {
total_stake = total_stake.saturating_add(exposure.total);
<ErasStakers<T>>::insert(current_era, &stash, &exposure);
let mut exposure_clipped = exposure;
let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize;
if exposure_clipped.others.len() > clipped_max_len {
exposure_clipped.others.sort_by(|a, b| a.value.cmp(&b.value).reverse());
exposure_clipped.others.truncate(clipped_max_len);
}
<ErasStakersClipped<T>>::insert(&current_era, &stash, exposure_clipped);
});
// Insert current era staking information
<ErasTotalStake<T>>::insert(&current_era, total_stake);
// collect the pref of all winners
for stash in &elected_stashes {
let pref = Self::validators(stash);
<ErasValidatorPrefs<T>>::insert(&current_era, stash, pref);
}
// emit event
// TWO_PHASE_NOTE: remove the inner value.
Self::deposit_event(RawEvent::StakingElection(ElectionCompute::Signed));
log!(
info,
"new validator set of size {:?} has been processed for era {:?}",
elected_stashes.len(),
current_era,
);
Ok(elected_stashes)
}
/// Enact and process the election using the `ElectionProvider` type.
///
/// This will also process the election, as noted in [`process_election`].
fn enact_election(_current_era: EraIndex) -> Option<Vec<T::AccountId>> {
let _outcome = T::ElectionProvider::elect().map(|_| ());
log!(debug, "Experimental election provider outputted {:?}", _outcome);
// TWO_PHASE_NOTE: This code path shall not return anything for now. Later on, redirect the
// results to `process_election`.
None
}
/// Remove all associated data of a stash account from the staking system.
///
/// Assumes storage is upgraded before calling.
@@ -3167,7 +3275,11 @@ impl<T: Config> Module<T> {
}
#[cfg(feature = "runtime-benchmarks")]
pub fn add_era_stakers(current_era: EraIndex, controller: T::AccountId, exposure: Exposure<T::AccountId, BalanceOf<T>>) {
pub fn add_era_stakers(
current_era: EraIndex,
controller: T::AccountId,
exposure: Exposure<T::AccountId, BalanceOf<T>>,
) {
<ErasStakers<T>>::insert(&current_era, &controller, &exposure);
}
@@ -3180,6 +3292,109 @@ impl<T: Config> Module<T> {
pub fn set_slash_reward_fraction(fraction: Perbill) {
SlashRewardFraction::put(fraction);
}
/// Get all of the voters that are eligible for the npos election.
///
/// This will use all on-chain nominators, and all the validators will inject a self vote.
///
/// ### Slashing
///
/// All nominations that have been submitted before the last non-zero slash of the validator are
/// auto-chilled.
///
/// Note that this is VERY expensive. Use with care.
pub fn get_npos_voters() -> Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> {
let weight_of = Self::slashable_balance_of_fn();
let mut all_voters = Vec::new();
for (validator, _) in <Validators<T>>::iter() {
// append self vote
let self_vote = (validator.clone(), weight_of(&validator), vec![validator.clone()]);
all_voters.push(self_vote);
}
for (nominator, nominations) in <Nominators<T>>::iter() {
let Nominations { submitted_in, mut targets, suppressed: _ } = nominations;
// Filter out nomination targets which were nominated before the most recent
// slashing span.
targets.retain(|stash| {
Self::slashing_spans(&stash)
.map_or(true, |spans| submitted_in >= spans.last_nonzero_slash())
});
let vote_weight = weight_of(&nominator);
all_voters.push((nominator, vote_weight, targets))
}
all_voters
}
pub fn get_npos_targets() -> Vec<T::AccountId> {
<Validators<T>>::iter().map(|(v, _)| v).collect::<Vec<_>>()
}
}
impl<T: Config> sp_election_providers::ElectionDataProvider<T::AccountId, T::BlockNumber>
for Module<T>
{
fn desired_targets() -> u32 {
Self::validator_count()
}
fn voters() -> Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> {
Self::get_npos_voters()
}
fn targets() -> Vec<T::AccountId> {
Self::get_npos_targets()
}
fn next_election_prediction(now: T::BlockNumber) -> T::BlockNumber {
let current_era = Self::current_era().unwrap_or(0);
let current_session = Self::current_planned_session();
let current_era_start_session_index =
Self::eras_start_session_index(current_era).unwrap_or(0);
let era_length = current_session
.saturating_sub(current_era_start_session_index)
.min(T::SessionsPerEra::get());
let session_length = T::NextNewSession::average_session_length();
let until_this_session_end = T::NextNewSession::estimate_next_new_session(now)
.unwrap_or_default()
.saturating_sub(now);
let sessions_left: T::BlockNumber = T::SessionsPerEra::get()
.saturating_sub(era_length)
// one session is computed in this_session_end.
.saturating_sub(1)
.into();
now.saturating_add(
until_this_session_end.saturating_add(sessions_left.saturating_mul(session_length)),
)
}
#[cfg(any(feature = "runtime-benchmarks", test))]
fn put_snapshot(
voters: Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
targets: Vec<T::AccountId>,
) {
targets.into_iter().for_each(|v| {
<Validators<T>>::insert(
v,
ValidatorPrefs { commission: Perbill::zero(), blocked: false },
);
});
voters.into_iter().for_each(|(v, _s, t)| {
<Nominators<T>>::insert(
v,
Nominations { targets: t, submitted_in: 0, suppressed: false },
);
});
}
}
/// In this implementation `new_session(session)` must be called before `end_session(session-1)`
@@ -3195,6 +3410,7 @@ impl<T: Config> pallet_session::SessionManager<T::AccountId> for Module<T> {
<frame_system::Module<T>>::block_number(),
new_index
);
CurrentPlannedSession::put(new_index);
Self::new_session(new_index)
}
fn start_session(start_index: SessionIndex) {
@@ -3217,10 +3433,12 @@ impl<T: Config> pallet_session::SessionManager<T::AccountId> for Module<T> {
}
}
impl<T: Config> historical::SessionManager<T::AccountId, Exposure<T::AccountId, BalanceOf<T>>> for Module<T> {
fn new_session(new_index: SessionIndex)
-> Option<Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)>>
{
impl<T: Config> historical::SessionManager<T::AccountId, Exposure<T::AccountId, BalanceOf<T>>>
for Module<T>
{
fn new_session(
new_index: SessionIndex,
) -> Option<Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)>> {
<Self as pallet_session::SessionManager<_>>::new_session(new_index).map(|validators| {
let current_era = Self::current_era()
// Must be some as a new era has been created.
@@ -3245,8 +3463,8 @@ impl<T: Config> historical::SessionManager<T::AccountId, Exposure<T::AccountId,
/// * 2 points to the block producer for each reference to a previously unreferenced uncle, and
/// * 1 point to the producer of each referenced uncle block.
impl<T> pallet_authorship::EventHandler<T::AccountId, T::BlockNumber> for Module<T>
where
T: Config + pallet_authorship::Config + pallet_session::Config
where
T: Config + pallet_authorship::Config + pallet_session::Config,
{
fn note_author(author: T::AccountId) {
Self::reward_by_ids(vec![(author, 20)])
@@ -3289,9 +3507,10 @@ impl<T: Config> Convert<T::AccountId, Option<Exposure<T::AccountId, BalanceOf<T>
}
/// This is intended to be used with `FilterHistoricalOffences`.
impl <T: Config>
impl<T: Config>
OnOffenceHandler<T::AccountId, pallet_session::historical::IdentificationTuple<T>, Weight>
for Module<T> where
for Module<T>
where
T: pallet_session::Config<ValidatorId = <T as frame_system::Config>::AccountId>,
T: pallet_session::historical::Config<
FullIdentification = Exposure<<T as frame_system::Config>::AccountId, BalanceOf<T>>,
@@ -3305,12 +3524,15 @@ for Module<T> where
>,
{
fn on_offence(
offenders: &[OffenceDetails<T::AccountId, pallet_session::historical::IdentificationTuple<T>>],
offenders: &[OffenceDetails<
T::AccountId,
pallet_session::historical::IdentificationTuple<T>,
>],
slash_fraction: &[Perbill],
slash_session: SessionIndex,
) -> Result<Weight, ()> {
if !Self::can_report() {
return Err(())
return Err(());
}
let reward_proportion = SlashRewardFraction::get();
@@ -3421,6 +3643,7 @@ for Module<T> where
}
fn can_report() -> bool {
// TWO_PHASE_NOTE: we can get rid of this API
Self::era_election_status().is_closed()
}
}
@@ -3431,7 +3654,8 @@ pub struct FilterHistoricalOffences<T, R> {
}
impl<T, Reporter, Offender, R, O> ReportOffence<Reporter, Offender, O>
for FilterHistoricalOffences<Module<T>, R> where
for FilterHistoricalOffences<Module<T>, R>
where
T: Config,
R: ReportOffence<Reporter, Offender, O>,
O: Offence<Offender>,
@@ -3488,7 +3712,7 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
return invalid.into();
}
log!(debug, "💸 validateUnsigned succeeded for a solution at era {}.", era);
log!(debug, "validateUnsigned succeeded for a solution at era {}.", era);
ValidTransaction::with_tag_prefix("StakingOffchain")
// The higher the score[0], the better a solution is.
+17 -10
View File
@@ -28,7 +28,7 @@ use frame_support::{
use sp_core::H256;
use sp_io;
use sp_npos_elections::{
to_support_map, EvaluateSupport, reduce, ExtendedBalance, StakedAssignment, ElectionScore,
to_supports, reduce, ExtendedBalance, StakedAssignment, ElectionScore, EvaluateSupport,
};
use sp_runtime::{
curve::PiecewiseLinear,
@@ -37,6 +37,7 @@ use sp_runtime::{
};
use sp_staking::offence::{OffenceDetails, OnOffenceHandler};
use std::{cell::RefCell, collections::HashSet};
use sp_election_providers::onchain;
pub const INIT_TIMESTAMP: u64 = 30_000;
pub const BLOCK_TIME: u64 = 1000;
@@ -239,6 +240,12 @@ impl OnUnbalanced<NegativeImbalanceOf<Test>> for RewardRemainderMock {
}
}
impl onchain::Config for Test {
type AccountId = AccountId;
type BlockNumber = BlockNumber;
type Accuracy = Perbill;
type DataProvider = Staking;
}
impl Config for Test {
type Currency = Balances;
type UnixTime = Timestamp;
@@ -261,6 +268,7 @@ impl Config for Test {
type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
type UnsignedPriority = UnsignedPriority;
type OffchainSolutionWeightLimit = OffchainSolutionWeightLimit;
type ElectionProvider = onchain::OnChainSequentialPhragmen<Self>;
type WeightInfo = ();
}
@@ -760,7 +768,7 @@ pub(crate) fn add_slash(who: &AccountId) {
on_offence_now(
&[
OffenceDetails {
offender: (who.clone(), Staking::eras_stakers(Staking::active_era().unwrap().index, who.clone())),
offender: (who.clone(), Staking::eras_stakers(active_era(), who.clone())),
reporters: vec![],
},
],
@@ -841,7 +849,7 @@ pub(crate) fn horrible_npos_solution(
let score = {
let (_, _, better_score) = prepare_submission_with(true, true, 0, |_| {});
let support = to_support_map::<AccountId>(&winners, &staked_assignment).unwrap();
let support = to_supports::<AccountId>(&winners, &staked_assignment).unwrap();
let score = support.evaluate();
assert!(sp_npos_elections::is_score_better::<Perbill>(
@@ -941,7 +949,7 @@ pub(crate) fn prepare_submission_with(
Staking::slashable_balance_of_fn(),
);
let support_map = to_support_map::<AccountId>(
let support_map = to_supports(
winners.as_slice(),
staked.as_slice(),
).unwrap();
@@ -962,9 +970,8 @@ pub(crate) fn prepare_submission_with(
/// Make all validator and nominator request their payment
pub(crate) fn make_all_reward_payment(era: EraIndex) {
let validators_with_reward = ErasRewardPoints::<Test>::get(era).individual.keys()
.cloned()
.collect::<Vec<_>>();
let validators_with_reward =
ErasRewardPoints::<Test>::get(era).individual.keys().cloned().collect::<Vec<_>>();
// reward validators
for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) {
@@ -988,10 +995,10 @@ macro_rules! assert_session_era {
$session,
);
assert_eq!(
Staking::active_era().unwrap().index,
Staking::current_era().unwrap(),
$era,
"wrong active era {} != {}",
Staking::active_era().unwrap().index,
"wrong current era {} != {}",
Staking::current_era().unwrap(),
$era,
);
};
@@ -25,7 +25,7 @@ use codec::Decode;
use frame_support::{traits::Get, weights::Weight, IterableStorageMap};
use frame_system::offchain::SubmitTransaction;
use sp_npos_elections::{
to_support_map, EvaluateSupport, reduce, Assignment, ElectionResult, ElectionScore,
to_supports, EvaluateSupport, reduce, Assignment, ElectionResult, ElectionScore,
ExtendedBalance, CompactSolution,
};
use sp_runtime::{
@@ -127,7 +127,7 @@ pub(crate) fn compute_offchain_election<T: Config>() -> Result<(), OffchainElect
crate::log!(
info,
"💸 prepared a seq-phragmen solution with {} balancing iterations and score {:?}",
"prepared a seq-phragmen solution with {} balancing iterations and score {:?}",
iters,
score,
);
@@ -284,7 +284,7 @@ where
if compact.remove_voter(index) {
crate::log!(
trace,
"💸 removed a voter at index {} with stake {:?} from compact to reduce the size",
"removed a voter at index {} with stake {:?} from compact to reduce the size",
index,
_stake,
);
@@ -297,19 +297,17 @@ where
}
crate::log!(
warn,
"💸 {} nominators out of {} had to be removed from compact solution due to size limits.",
removed,
compact.voter_count() + removed,
);
warn,
"{} nominators out of {} had to be removed from compact solution due to size \
limits.",
removed,
compact.voter_count() + removed,
);
Ok(compact)
}
_ => {
// nada, return as-is
crate::log!(
info,
"💸 Compact solution did not get trimmed due to block weight limits.",
);
crate::log!(info, "Compact solution did not get trimmed due to block weight limits.",);
Ok(compact)
}
}
@@ -390,13 +388,16 @@ pub fn prepare_submission<T: Config>(
let maximum_allowed_voters =
maximum_compact_len::<T::WeightInfo>(winners.len() as u32, size, maximum_weight);
crate::log!(debug, "💸 Maximum weight = {:?} // current weight = {:?} // maximum voters = {:?} // current votes = {:?}",
crate::log!(
debug,
"Maximum weight = {:?} // current weight = {:?} // maximum voters = {:?} // current votes \
= {:?}",
maximum_weight,
T::WeightInfo::submit_solution_better(
size.validators.into(),
size.nominators.into(),
compact.voter_count() as u32,
winners.len() as u32,
size.validators.into(),
size.nominators.into(),
compact.voter_count() as u32,
winners.len() as u32,
),
maximum_allowed_voters,
compact.voter_count(),
@@ -415,7 +416,7 @@ pub fn prepare_submission<T: Config>(
<Module<T>>::slashable_balance_of_fn(),
);
let support_map = to_support_map::<T::AccountId>(&winners, &staked)
let support_map = to_supports::<T::AccountId>(&winners, &staked)
.map_err(|_| OffchainElectionError::ElectionFailed)?;
support_map.evaluate()
};
+1 -1
View File
@@ -247,7 +247,7 @@ pub fn get_weak_solution<T: Config>(
);
let support_map =
to_support_map::<T::AccountId>(winners.as_slice(), staked.as_slice()).unwrap();
to_supports::<T::AccountId>(winners.as_slice(), staked.as_slice()).unwrap();
support_map.evaluate()
};
+93 -4
View File
@@ -1833,6 +1833,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_npos_election() {
}
assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller));
// 11 should not be elected. All of these count as ONE vote.
assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 11, 11, 21, 31,]));
assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller));
@@ -1886,7 +1887,6 @@ fn bond_with_duplicate_vote_should_be_ignored_by_npos_election_elected() {
assert_ok!(Staking::nominate(Origin::signed(4), vec![21, 31]));
// winners should be 21 and 31. Otherwise this election is taking duplicates into account.
let sp_npos_elections::ElectionResult {
winners,
assignments,
@@ -2029,7 +2029,7 @@ fn reward_from_authorship_event_handler_works() {
fn add_reward_points_fns_works() {
ExtBuilder::default().build_and_execute(|| {
// Not mandatory but must be coherent with rewards
assert_eq!(Session::validators(), vec![21, 11]);
assert_eq_uvec!(Session::validators(), vec![21, 11]);
<Module<Test>>::reward_by_ids(vec![
(21, 1),
@@ -3048,7 +3048,7 @@ mod offchain_election {
assert_eq!(Staking::era_election_status(), ElectionStatus::Open(37));
run_to_block(40);
assert_session_era!(4, 0);
assert_session_era!(4, 1);
assert_eq!(Staking::era_election_status(), ElectionStatus::Closed);
assert!(Staking::snapshot_nominators().is_none());
assert!(Staking::snapshot_validators().is_none());
@@ -3066,7 +3066,7 @@ mod offchain_election {
assert!(Staking::snapshot_validators().is_some());
run_to_block(90);
assert_session_era!(9, 1);
assert_session_era!(9, 2);
assert_eq!(Staking::era_election_status(), ElectionStatus::Closed);
assert!(Staking::snapshot_nominators().is_none());
assert!(Staking::snapshot_validators().is_none());
@@ -5015,3 +5015,92 @@ fn do_not_die_when_active_is_ed() {
);
})
}
mod election_data_provider {
use super::*;
use sp_election_providers::ElectionDataProvider;
#[test]
fn voters_include_self_vote() {
ExtBuilder::default().nominate(false).build().execute_with(|| {
assert!(<Validators<Test>>::iter().map(|(x, _)| x).all(|v| Staking::voters()
.into_iter()
.find(|(w, _, t)| { v == *w && t[0] == *w })
.is_some()))
})
}
#[test]
fn voters_exclude_slashed() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]);
assert_eq!(
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters()
.iter()
.find(|x| x.0 == 101)
.unwrap()
.2,
vec![11, 21]
);
start_active_era(1);
add_slash(&11);
// 11 is gone.
start_active_era(2);
assert_eq!(
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters()
.iter()
.find(|x| x.0 == 101)
.unwrap()
.2,
vec![21]
);
// resubmit and it is back
assert_ok!(Staking::nominate(Origin::signed(100), vec![11, 21]));
assert_eq!(
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters()
.iter()
.find(|x| x.0 == 101)
.unwrap()
.2,
vec![11, 21]
);
})
}
#[test]
fn estimate_next_election_works() {
ExtBuilder::default().session_per_era(5).period(5).build().execute_with(|| {
// first session is always length 0.
for b in 1..20 {
run_to_block(b);
assert_eq!(Staking::next_election_prediction(System::block_number()), 20);
}
// election
run_to_block(20);
assert_eq!(Staking::next_election_prediction(System::block_number()), 45);
assert_eq!(staking_events().len(), 1);
assert_eq!(
*staking_events().last().unwrap(),
RawEvent::StakingElection(ElectionCompute::OnChain)
);
for b in 21..45 {
run_to_block(b);
assert_eq!(Staking::next_election_prediction(System::block_number()), 45);
}
// election
run_to_block(45);
assert_eq!(Staking::next_election_prediction(System::block_number()), 70);
assert_eq!(staking_events().len(), 3);
assert_eq!(
*staking_events().last().unwrap(),
RawEvent::StakingElection(ElectionCompute::OnChain)
);
})
}
}
+116 -116
View File
@@ -17,8 +17,8 @@
//! Autogenerated weights for pallet_staking
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1
//! DATE: 2021-01-19, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
//! DATE: 2021-02-13, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
// Executed Command:
@@ -75,171 +75,171 @@ pub trait WeightInfo {
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
fn bond() -> Weight {
(76_281_000 as Weight)
(81_642_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
fn bond_extra() -> Weight {
(62_062_000 as Weight)
(66_025_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn unbond() -> Weight {
(57_195_000 as Weight)
(60_810_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn withdraw_unbonded_update(s: u32, ) -> Weight {
(58_043_000 as Weight)
(61_537_000 as Weight)
// Standard Error: 1_000
.saturating_add((52_000 as Weight).saturating_mul(s as Weight))
.saturating_add((60_000 as Weight).saturating_mul(s as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn withdraw_unbonded_kill(s: u32, ) -> Weight {
(89_920_000 as Weight)
// Standard Error: 3_000
.saturating_add((2_526_000 as Weight).saturating_mul(s as Weight))
(95_741_000 as Weight)
// Standard Error: 1_000
.saturating_add((2_754_000 as Weight).saturating_mul(s as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(8 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
}
fn validate() -> Weight {
(20_228_000 as Weight)
(21_009_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn kick(k: u32, ) -> Weight {
(31_066_000 as Weight)
// Standard Error: 11_000
.saturating_add((17_754_000 as Weight).saturating_mul(k as Weight))
(31_832_000 as Weight)
// Standard Error: 15_000
.saturating_add((19_418_000 as Weight).saturating_mul(k as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight)))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight)))
}
fn nominate(n: u32, ) -> Weight {
(33_494_000 as Weight)
// Standard Error: 23_000
.saturating_add((5_253_000 as Weight).saturating_mul(n as Weight))
(34_304_000 as Weight)
// Standard Error: 20_000
.saturating_add((5_643_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight)))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn chill() -> Weight {
(19_396_000 as Weight)
(20_103_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn set_payee() -> Weight {
(13_449_000 as Weight)
(13_858_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn set_controller() -> Weight {
(29_184_000 as Weight)
(30_269_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn set_validator_count() -> Weight {
(2_266_000 as Weight)
(2_444_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn force_no_eras() -> Weight {
(2_462_000 as Weight)
(2_766_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn force_new_era() -> Weight {
(2_483_000 as Weight)
(2_724_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn force_new_era_always() -> Weight {
(2_495_000 as Weight)
(2_702_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn set_invulnerables(v: u32, ) -> Weight {
(2_712_000 as Weight)
(2_914_000 as Weight)
// Standard Error: 0
.saturating_add((9_000 as Weight).saturating_mul(v as Weight))
.saturating_add((35_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn force_unstake(s: u32, ) -> Weight {
(60_508_000 as Weight)
// Standard Error: 1_000
.saturating_add((2_525_000 as Weight).saturating_mul(s as Weight))
(64_032_000 as Weight)
// Standard Error: 2_000
.saturating_add((2_787_000 as Weight).saturating_mul(s as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(8 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
}
fn cancel_deferred_slash(s: u32, ) -> Weight {
(5_886_772_000 as Weight)
// Standard Error: 393_000
.saturating_add((34_849_000 as Weight).saturating_mul(s as Weight))
(5_903_394_000 as Weight)
// Standard Error: 391_000
.saturating_add((34_834_000 as Weight).saturating_mul(s as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn payout_stakers_dead_controller(n: u32, ) -> Weight {
(127_627_000 as Weight)
// Standard Error: 27_000
.saturating_add((49_354_000 as Weight).saturating_mul(n as Weight))
(141_724_000 as Weight)
// Standard Error: 24_000
.saturating_add((53_018_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(11 as Weight))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(n as Weight)))
}
fn payout_stakers_alive_staked(n: u32, ) -> Weight {
(156_838_000 as Weight)
// Standard Error: 24_000
.saturating_add((62_653_000 as Weight).saturating_mul(n as Weight))
(159_994_000 as Weight)
// Standard Error: 28_000
.saturating_add((67_746_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(12 as Weight))
.saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight)))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(n as Weight)))
}
fn rebond(l: u32, ) -> Weight {
(40_110_000 as Weight)
(42_177_000 as Weight)
// Standard Error: 1_000
.saturating_add((78_000 as Weight).saturating_mul(l as Weight))
.saturating_add((82_000 as Weight).saturating_mul(l as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn set_history_depth(e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 70_000
.saturating_add((32_883_000 as Weight).saturating_mul(e as Weight))
// Standard Error: 65_000
.saturating_add((34_151_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
.saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight)))
}
fn reap_stash(s: u32, ) -> Weight {
(64_605_000 as Weight)
// Standard Error: 1_000
.saturating_add((2_506_000 as Weight).saturating_mul(s as Weight))
(68_377_000 as Weight)
// Standard Error: 0
.saturating_add((2_757_000 as Weight).saturating_mul(s as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(8 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
}
fn new_era(v: u32, n: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 926_000
.saturating_add((548_212_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 46_000
.saturating_add((78_343_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
// Standard Error: 908_000
.saturating_add((588_562_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 45_000
.saturating_add((83_485_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(9 as Weight))
.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(v as Weight)))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
.saturating_add(T::DbWeight::get().writes(8 as Weight))
.saturating_add(T::DbWeight::get().writes(13 as Weight))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(v as Weight)))
}
fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 48_000
.saturating_add((937_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 19_000
.saturating_add((657_000 as Weight).saturating_mul(n as Weight))
// Standard Error: 48_000
.saturating_add((70_669_000 as Weight).saturating_mul(a as Weight))
// Standard Error: 101_000
.saturating_add((7_658_000 as Weight).saturating_mul(w as Weight))
// Standard Error: 52_000
.saturating_add((750_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 20_000
.saturating_add((556_000 as Weight).saturating_mul(n as Weight))
// Standard Error: 52_000
.saturating_add((76_201_000 as Weight).saturating_mul(a as Weight))
// Standard Error: 108_000
.saturating_add((7_271_000 as Weight).saturating_mul(w as Weight))
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(a as Weight)))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(w as Weight)))
@@ -250,171 +250,171 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// For backwards compatibility and tests
impl WeightInfo for () {
fn bond() -> Weight {
(76_281_000 as Weight)
(81_642_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
fn bond_extra() -> Weight {
(62_062_000 as Weight)
(66_025_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn unbond() -> Weight {
(57_195_000 as Weight)
(60_810_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn withdraw_unbonded_update(s: u32, ) -> Weight {
(58_043_000 as Weight)
(61_537_000 as Weight)
// Standard Error: 1_000
.saturating_add((52_000 as Weight).saturating_mul(s as Weight))
.saturating_add((60_000 as Weight).saturating_mul(s as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn withdraw_unbonded_kill(s: u32, ) -> Weight {
(89_920_000 as Weight)
// Standard Error: 3_000
.saturating_add((2_526_000 as Weight).saturating_mul(s as Weight))
(95_741_000 as Weight)
// Standard Error: 1_000
.saturating_add((2_754_000 as Weight).saturating_mul(s as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().writes(8 as Weight))
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
}
fn validate() -> Weight {
(20_228_000 as Weight)
(21_009_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn kick(k: u32, ) -> Weight {
(31_066_000 as Weight)
// Standard Error: 11_000
.saturating_add((17_754_000 as Weight).saturating_mul(k as Weight))
(31_832_000 as Weight)
// Standard Error: 15_000
.saturating_add((19_418_000 as Weight).saturating_mul(k as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight)))
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight)))
}
fn nominate(n: u32, ) -> Weight {
(33_494_000 as Weight)
// Standard Error: 23_000
.saturating_add((5_253_000 as Weight).saturating_mul(n as Weight))
(34_304_000 as Weight)
// Standard Error: 20_000
.saturating_add((5_643_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight)))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn chill() -> Weight {
(19_396_000 as Weight)
(20_103_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn set_payee() -> Weight {
(13_449_000 as Weight)
(13_858_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn set_controller() -> Weight {
(29_184_000 as Weight)
(30_269_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn set_validator_count() -> Weight {
(2_266_000 as Weight)
(2_444_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn force_no_eras() -> Weight {
(2_462_000 as Weight)
(2_766_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn force_new_era() -> Weight {
(2_483_000 as Weight)
(2_724_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn force_new_era_always() -> Weight {
(2_495_000 as Weight)
(2_702_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn set_invulnerables(v: u32, ) -> Weight {
(2_712_000 as Weight)
(2_914_000 as Weight)
// Standard Error: 0
.saturating_add((9_000 as Weight).saturating_mul(v as Weight))
.saturating_add((35_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn force_unstake(s: u32, ) -> Weight {
(60_508_000 as Weight)
// Standard Error: 1_000
.saturating_add((2_525_000 as Weight).saturating_mul(s as Weight))
(64_032_000 as Weight)
// Standard Error: 2_000
.saturating_add((2_787_000 as Weight).saturating_mul(s as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(8 as Weight))
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
}
fn cancel_deferred_slash(s: u32, ) -> Weight {
(5_886_772_000 as Weight)
// Standard Error: 393_000
.saturating_add((34_849_000 as Weight).saturating_mul(s as Weight))
(5_903_394_000 as Weight)
// Standard Error: 391_000
.saturating_add((34_834_000 as Weight).saturating_mul(s as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn payout_stakers_dead_controller(n: u32, ) -> Weight {
(127_627_000 as Weight)
// Standard Error: 27_000
.saturating_add((49_354_000 as Weight).saturating_mul(n as Weight))
(141_724_000 as Weight)
// Standard Error: 24_000
.saturating_add((53_018_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(11 as Weight))
.saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(n as Weight)))
}
fn payout_stakers_alive_staked(n: u32, ) -> Weight {
(156_838_000 as Weight)
// Standard Error: 24_000
.saturating_add((62_653_000 as Weight).saturating_mul(n as Weight))
(159_994_000 as Weight)
// Standard Error: 28_000
.saturating_add((67_746_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(12 as Weight))
.saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight)))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
.saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(n as Weight)))
}
fn rebond(l: u32, ) -> Weight {
(40_110_000 as Weight)
(42_177_000 as Weight)
// Standard Error: 1_000
.saturating_add((78_000 as Weight).saturating_mul(l as Weight))
.saturating_add((82_000 as Weight).saturating_mul(l as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn set_history_depth(e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 70_000
.saturating_add((32_883_000 as Weight).saturating_mul(e as Weight))
// Standard Error: 65_000
.saturating_add((34_151_000 as Weight).saturating_mul(e as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
.saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight)))
}
fn reap_stash(s: u32, ) -> Weight {
(64_605_000 as Weight)
// Standard Error: 1_000
.saturating_add((2_506_000 as Weight).saturating_mul(s as Weight))
(68_377_000 as Weight)
// Standard Error: 0
.saturating_add((2_757_000 as Weight).saturating_mul(s as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(8 as Weight))
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
}
fn new_era(v: u32, n: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 926_000
.saturating_add((548_212_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 46_000
.saturating_add((78_343_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
// Standard Error: 908_000
.saturating_add((588_562_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 45_000
.saturating_add((83_485_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(9 as Weight))
.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(v as Weight)))
.saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
.saturating_add(RocksDbWeight::get().writes(8 as Weight))
.saturating_add(RocksDbWeight::get().writes(13 as Weight))
.saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(v as Weight)))
}
fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 48_000
.saturating_add((937_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 19_000
.saturating_add((657_000 as Weight).saturating_mul(n as Weight))
// Standard Error: 48_000
.saturating_add((70_669_000 as Weight).saturating_mul(a as Weight))
// Standard Error: 101_000
.saturating_add((7_658_000 as Weight).saturating_mul(w as Weight))
// Standard Error: 52_000
.saturating_add((750_000 as Weight).saturating_mul(v as Weight))
// Standard Error: 20_000
.saturating_add((556_000 as Weight).saturating_mul(n as Weight))
// Standard Error: 52_000
.saturating_add((76_201_000 as Weight).saturating_mul(a as Weight))
// Standard Error: 108_000
.saturating_add((7_271_000 as Weight).saturating_mul(w as Weight))
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(a as Weight)))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(w as Weight)))