mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 18:41:05 +00:00
Benchmark Offences Pallet (#5411)
* Add initial report_ofence bench. * Remove unused imports * Style nit * Add nominators * Remove logs. * Nits. * Add nominators param. * Reorg, comment. * Remove whitespaces. * Apply review suggestion: move benchmark to own crate. * Remove import. * Remove line. * Add feature flag. * Pass can_report. * Cleaning up. * More cleaning
This commit is contained in:
Generated
+210
-194
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,7 @@ pallet-indices = { version = "2.0.0-alpha.5", default-features = false, path = "
|
|||||||
pallet-identity = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/identity" }
|
pallet-identity = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/identity" }
|
||||||
pallet-membership = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/membership" }
|
pallet-membership = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/membership" }
|
||||||
pallet-offences = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/offences" }
|
pallet-offences = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/offences" }
|
||||||
|
pallet-offences-benchmarking = { version = "2.0.0-alpha.5", path = "../../../frame/offences/benchmarking", default-features = false, optional = true }
|
||||||
pallet-randomness-collective-flip = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/randomness-collective-flip" }
|
pallet-randomness-collective-flip = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/randomness-collective-flip" }
|
||||||
pallet-recovery = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/recovery" }
|
pallet-recovery = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/recovery" }
|
||||||
pallet-session = { version = "2.0.0-alpha.5", features = ["historical"], path = "../../../frame/session", default-features = false }
|
pallet-session = { version = "2.0.0-alpha.5", features = ["historical"], path = "../../../frame/session", default-features = false }
|
||||||
@@ -150,6 +151,7 @@ runtime-benchmarks = [
|
|||||||
"pallet-utility/runtime-benchmarks",
|
"pallet-utility/runtime-benchmarks",
|
||||||
"pallet-vesting/runtime-benchmarks",
|
"pallet-vesting/runtime-benchmarks",
|
||||||
"pallet-collective/runtime-benchmarks",
|
"pallet-collective/runtime-benchmarks",
|
||||||
|
"pallet-offences-benchmarking",
|
||||||
"pallet-session-benchmarking",
|
"pallet-session-benchmarking",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -887,10 +887,14 @@ impl_runtime_apis! {
|
|||||||
// To get around that, we separated the Session benchmarks into its own crate, which is why
|
// To get around that, we separated the Session benchmarks into its own crate, which is why
|
||||||
// we need these two lines below.
|
// we need these two lines below.
|
||||||
use pallet_session_benchmarking::Module as SessionBench;
|
use pallet_session_benchmarking::Module as SessionBench;
|
||||||
|
use pallet_offences_benchmarking::Module as OffencesBench;
|
||||||
|
|
||||||
impl pallet_session_benchmarking::Trait for Runtime {}
|
impl pallet_session_benchmarking::Trait for Runtime {}
|
||||||
|
impl pallet_offences_benchmarking::Trait for Runtime {}
|
||||||
|
|
||||||
let mut batches = Vec::<BenchmarkBatch>::new();
|
let mut batches = Vec::<BenchmarkBatch>::new();
|
||||||
let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat);
|
let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat);
|
||||||
|
|
||||||
add_benchmark!(params, batches, b"balances", Balances);
|
add_benchmark!(params, batches, b"balances", Balances);
|
||||||
add_benchmark!(params, batches, b"collective", Council);
|
add_benchmark!(params, batches, b"collective", Council);
|
||||||
add_benchmark!(params, batches, b"democracy", Democracy);
|
add_benchmark!(params, batches, b"democracy", Democracy);
|
||||||
@@ -902,6 +906,8 @@ impl_runtime_apis! {
|
|||||||
add_benchmark!(params, batches, b"treasury", Treasury);
|
add_benchmark!(params, batches, b"treasury", Treasury);
|
||||||
add_benchmark!(params, batches, b"utility", Utility);
|
add_benchmark!(params, batches, b"utility", Utility);
|
||||||
add_benchmark!(params, batches, b"vesting", Vesting);
|
add_benchmark!(params, batches, b"vesting", Vesting);
|
||||||
|
add_benchmark!(params, batches, b"offences", OffencesBench::<Runtime>);
|
||||||
|
|
||||||
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
|
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
|
||||||
Ok(batches)
|
Ok(batches)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -679,11 +679,11 @@ pub struct UnresponsivenessOffence<Offender> {
|
|||||||
///
|
///
|
||||||
/// It acts as a time measure for unresponsiveness reports and effectively will always point
|
/// It acts as a time measure for unresponsiveness reports and effectively will always point
|
||||||
/// at the end of the session.
|
/// at the end of the session.
|
||||||
session_index: SessionIndex,
|
pub session_index: SessionIndex,
|
||||||
/// The size of the validator set in current session/era.
|
/// The size of the validator set in current session/era.
|
||||||
validator_set_count: u32,
|
pub validator_set_count: u32,
|
||||||
/// Authorities that were unresponsive during the current era.
|
/// Authorities that were unresponsive during the current era.
|
||||||
offenders: Vec<Offender>,
|
pub offenders: Vec<Offender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Offender: Clone> Offence<Offender> for UnresponsivenessOffence<Offender> {
|
impl<Offender: Clone> Offence<Offender> for UnresponsivenessOffence<Offender> {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ std = [
|
|||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"frame-system/std",
|
"frame-system/std",
|
||||||
]
|
]
|
||||||
|
runtime-benchmarks = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
[package]
|
||||||
|
name = "pallet-offences-benchmarking"
|
||||||
|
version = "2.0.0-alpha.5"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
homepage = "https://substrate.dev"
|
||||||
|
repository = "https://github.com/paritytech/substrate/"
|
||||||
|
description = "FRAME offences pallet benchmarking"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false }
|
||||||
|
|
||||||
|
sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" }
|
||||||
|
sp-staking = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/staking" }
|
||||||
|
sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" }
|
||||||
|
frame-benchmarking = { version = "2.0.0-alpha.5", default-features = false, path = "../../benchmarking" }
|
||||||
|
frame-system = { version = "2.0.0-alpha.5", default-features = false, path = "../../system" }
|
||||||
|
frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../support" }
|
||||||
|
pallet-im-online = { version = "2.0.0-alpha.5", default-features = false, path = "../../im-online" }
|
||||||
|
pallet-offences = { version = "2.0.0-alpha.5", default-features = false, features = ["runtime-benchmarks"], path = "../../offences" }
|
||||||
|
pallet-staking = { version = "2.0.0-alpha.5", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" }
|
||||||
|
pallet-session = { version = "2.0.0-alpha.5", default-features = false, path = "../../session" }
|
||||||
|
sp-io = { path = "../../../primitives/io", default-features = false, version = "2.0.0-alpha.5"}
|
||||||
|
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = [
|
||||||
|
"sp-runtime/std",
|
||||||
|
"sp-std/std",
|
||||||
|
"sp-staking/std",
|
||||||
|
"frame-benchmarking/std",
|
||||||
|
"frame-support/std",
|
||||||
|
"frame-system/std",
|
||||||
|
"pallet-offences/std",
|
||||||
|
"pallet-im-online/std",
|
||||||
|
"pallet-staking/std",
|
||||||
|
"pallet-session/std",
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Substrate.
|
||||||
|
|
||||||
|
// Substrate is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Substrate is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Offences pallet benchmarking.
|
||||||
|
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
use sp_std::prelude::*;
|
||||||
|
use sp_std::vec;
|
||||||
|
|
||||||
|
use frame_system::RawOrigin;
|
||||||
|
use frame_benchmarking::{benchmarks, account};
|
||||||
|
use frame_support::traits::{Currency, OnInitialize};
|
||||||
|
|
||||||
|
use sp_runtime::{Perbill, traits::{Convert, StaticLookup}};
|
||||||
|
use sp_staking::offence::ReportOffence;
|
||||||
|
|
||||||
|
use pallet_im_online::{Trait as ImOnlineTrait, Module as ImOnline, UnresponsivenessOffence};
|
||||||
|
use pallet_offences::{Trait as OffencesTrait, Module as Offences};
|
||||||
|
use pallet_staking::{
|
||||||
|
Module as Staking, Trait as StakingTrait, RewardDestination, ValidatorPrefs,
|
||||||
|
Exposure, IndividualExposure, ElectionStatus
|
||||||
|
};
|
||||||
|
use pallet_session::Trait as SessionTrait;
|
||||||
|
use pallet_session::historical::{Trait as HistoricalTrait, IdentificationTuple};
|
||||||
|
|
||||||
|
const SEED: u32 = 0;
|
||||||
|
|
||||||
|
const MAX_USERS: u32 = 1000;
|
||||||
|
const MAX_REPORTERS: u32 = 100;
|
||||||
|
const MAX_OFFENDERS: u32 = 100;
|
||||||
|
const MAX_NOMINATORS: u32 = 100;
|
||||||
|
const MAX_DEFERRED_OFFENCES: u32 = 100;
|
||||||
|
|
||||||
|
pub struct Module<T: Trait>(Offences<T>);
|
||||||
|
|
||||||
|
pub trait Trait: SessionTrait + StakingTrait + OffencesTrait + ImOnlineTrait + HistoricalTrait {}
|
||||||
|
|
||||||
|
fn create_offender<T: Trait>(n: u32, nominators: u32) -> Result<T::AccountId, &'static str> {
|
||||||
|
let stash: T::AccountId = account("stash", n, SEED);
|
||||||
|
let controller: T::AccountId = account("controller", n, SEED);
|
||||||
|
let controller_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(controller.clone());
|
||||||
|
let reward_destination = RewardDestination::Staked;
|
||||||
|
let amount = T::Currency::minimum_balance();
|
||||||
|
|
||||||
|
Staking::<T>::bond(
|
||||||
|
RawOrigin::Signed(stash.clone()).into(),
|
||||||
|
controller_lookup.clone(),
|
||||||
|
amount.clone(),
|
||||||
|
reward_destination.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let validator_prefs = ValidatorPrefs {
|
||||||
|
commission: Perbill::from_percent(50),
|
||||||
|
};
|
||||||
|
Staking::<T>::validate(RawOrigin::Signed(controller.clone()).into(), validator_prefs)?;
|
||||||
|
|
||||||
|
let mut individual_exposures = vec![];
|
||||||
|
|
||||||
|
// Create n nominators
|
||||||
|
for i in 0 .. nominators {
|
||||||
|
let nominator_stash: T::AccountId = account("nominator stash", n * MAX_NOMINATORS + i, SEED);
|
||||||
|
let nominator_controller: T::AccountId = account("nominator controller", n * MAX_NOMINATORS + i, SEED);
|
||||||
|
let nominator_controller_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(nominator_controller.clone());
|
||||||
|
|
||||||
|
Staking::<T>::bond(
|
||||||
|
RawOrigin::Signed(nominator_stash.clone()).into(),
|
||||||
|
nominator_controller_lookup.clone(),
|
||||||
|
amount,
|
||||||
|
reward_destination,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let selected_validators: Vec<<T::Lookup as StaticLookup>::Source> = vec![controller_lookup.clone()];
|
||||||
|
Staking::<T>::nominate(RawOrigin::Signed(nominator_controller.clone()).into(), selected_validators)?;
|
||||||
|
|
||||||
|
individual_exposures.push(IndividualExposure {
|
||||||
|
who: nominator_controller.clone(),
|
||||||
|
value: amount.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let exposure = Exposure {
|
||||||
|
total: amount.clone() * n.into(),
|
||||||
|
own: amount,
|
||||||
|
others: individual_exposures,
|
||||||
|
};
|
||||||
|
let current_era = 0u32;
|
||||||
|
Staking::<T>::add_era_stakers(current_era.into(), stash.clone().into(), exposure);
|
||||||
|
|
||||||
|
Ok(controller)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_offenders<T: Trait>(num_offenders: u32, num_nominators: u32) -> Result<Vec<IdentificationTuple<T>>, &'static str> {
|
||||||
|
let mut offenders: Vec<T::AccountId> = vec![];
|
||||||
|
|
||||||
|
for i in 0 .. num_offenders {
|
||||||
|
let offender = create_offender::<T>(i, num_nominators)?;
|
||||||
|
offenders.push(offender);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(offenders.iter()
|
||||||
|
.map(|id|
|
||||||
|
<T as SessionTrait>::ValidatorIdOf::convert(id.clone())
|
||||||
|
.expect("failed to get validator id from account id"))
|
||||||
|
.map(|validator_id|
|
||||||
|
<T as HistoricalTrait>::FullIdentificationOf::convert(validator_id.clone())
|
||||||
|
.map(|full_id| (validator_id, full_id))
|
||||||
|
.expect("failed to convert validator id to full identification"))
|
||||||
|
.collect::<Vec<IdentificationTuple<T>>>())
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmarks! {
|
||||||
|
_ {
|
||||||
|
let u in 1 .. MAX_USERS => ();
|
||||||
|
let r in 1 .. MAX_REPORTERS => ();
|
||||||
|
let o in 1 .. MAX_OFFENDERS => ();
|
||||||
|
let n in 1 .. MAX_NOMINATORS => ();
|
||||||
|
let d in 1 .. MAX_DEFERRED_OFFENCES => ();
|
||||||
|
}
|
||||||
|
|
||||||
|
report_offence {
|
||||||
|
let r in ...;
|
||||||
|
let o in ...;
|
||||||
|
let n in ...;
|
||||||
|
|
||||||
|
let mut reporters = vec![];
|
||||||
|
|
||||||
|
for i in 0 .. r {
|
||||||
|
let reporter = account("reporter", i, SEED);
|
||||||
|
reporters.push(reporter);
|
||||||
|
}
|
||||||
|
|
||||||
|
let offenders = make_offenders::<T>(o, n).expect("failed to create offenders");
|
||||||
|
let keys = ImOnline::<T>::keys();
|
||||||
|
|
||||||
|
let offence = UnresponsivenessOffence {
|
||||||
|
session_index: 0,
|
||||||
|
validator_set_count: keys.len() as u32,
|
||||||
|
offenders,
|
||||||
|
};
|
||||||
|
|
||||||
|
}: {
|
||||||
|
let _ = <T as ImOnlineTrait>::ReportUnresponsiveness::report_offence(reporters, offence);
|
||||||
|
}
|
||||||
|
|
||||||
|
on_initialize {
|
||||||
|
let d in ...;
|
||||||
|
|
||||||
|
Staking::<T>::put_election_status(ElectionStatus::Closed);
|
||||||
|
|
||||||
|
let mut deferred_offences = vec![];
|
||||||
|
|
||||||
|
for i in 0 .. d {
|
||||||
|
deferred_offences.push((vec![], vec![], 0u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
Offences::<T>::set_deferred_offences(deferred_offences);
|
||||||
|
|
||||||
|
}: {
|
||||||
|
Offences::<T>::on_initialize(u.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ type OpaqueTimeSlot = Vec<u8>;
|
|||||||
type ReportIdOf<T> = <T as frame_system::Trait>::Hash;
|
type ReportIdOf<T> = <T as frame_system::Trait>::Hash;
|
||||||
|
|
||||||
/// Type of data stored as a deferred offence
|
/// Type of data stored as a deferred offence
|
||||||
type DeferredOffenceOf<T> = (
|
pub type DeferredOffenceOf<T> = (
|
||||||
Vec<OffenceDetails<<T as frame_system::Trait>::AccountId, <T as Trait>::IdentificationTuple>>,
|
Vec<OffenceDetails<<T as frame_system::Trait>::AccountId, <T as Trait>::IdentificationTuple>>,
|
||||||
Vec<Perbill>,
|
Vec<Perbill>,
|
||||||
SessionIndex,
|
SessionIndex,
|
||||||
@@ -249,6 +249,11 @@ impl<T: Trait> Module<T> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
|
pub fn set_deferred_offences(offences: Vec<DeferredOffenceOf<T>>) {
|
||||||
|
<DeferredOffences<T>>::put(offences);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TriageOutcome<T: Trait> {
|
struct TriageOutcome<T: Trait> {
|
||||||
|
|||||||
@@ -191,8 +191,8 @@ decl_storage! {
|
|||||||
<CandidateExists<T, I>>::insert(who, true);
|
<CandidateExists<T, I>>::insert(who, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Sorts the `Pool` by score in a descending order. Entities which
|
// Sorts the `Pool` by score in a descending order. Entities which
|
||||||
/// have a score of `None` are sorted to the beginning of the vec.
|
// have a score of `None` are sorted to the beginning of the vec.
|
||||||
pool.sort_by_key(|(_, maybe_score)|
|
pool.sort_by_key(|(_, maybe_score)|
|
||||||
Reverse(maybe_score.unwrap_or_default())
|
Reverse(maybe_score.unwrap_or_default())
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -583,10 +583,10 @@ pub struct Nominations<AccountId> {
|
|||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug)]
|
||||||
pub struct IndividualExposure<AccountId, Balance: HasCompact> {
|
pub struct IndividualExposure<AccountId, Balance: HasCompact> {
|
||||||
/// The stash account of the nominator in question.
|
/// The stash account of the nominator in question.
|
||||||
who: AccountId,
|
pub who: AccountId,
|
||||||
/// Amount of funds exposed.
|
/// Amount of funds exposed.
|
||||||
#[codec(compact)]
|
#[codec(compact)]
|
||||||
value: Balance,
|
pub value: Balance,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A snapshot of the stake backing a single validator in the system.
|
/// A snapshot of the stake backing a single validator in the system.
|
||||||
@@ -1252,7 +1252,7 @@ decl_module! {
|
|||||||
/// unless the `origin` falls below _existential deposit_ and gets removed as dust.
|
/// unless the `origin` falls below _existential deposit_ and gets removed as dust.
|
||||||
/// # </weight>
|
/// # </weight>
|
||||||
#[weight = SimpleDispatchInfo::FixedNormal(500_000)]
|
#[weight = SimpleDispatchInfo::FixedNormal(500_000)]
|
||||||
fn bond(origin,
|
pub fn bond(origin,
|
||||||
controller: <T::Lookup as StaticLookup>::Source,
|
controller: <T::Lookup as StaticLookup>::Source,
|
||||||
#[compact] value: BalanceOf<T>,
|
#[compact] value: BalanceOf<T>,
|
||||||
payee: RewardDestination,
|
payee: RewardDestination,
|
||||||
@@ -1446,7 +1446,7 @@ decl_module! {
|
|||||||
/// - Writes are limited to the `origin` account key.
|
/// - Writes are limited to the `origin` account key.
|
||||||
/// # </weight>
|
/// # </weight>
|
||||||
#[weight = SimpleDispatchInfo::FixedNormal(750_000)]
|
#[weight = SimpleDispatchInfo::FixedNormal(750_000)]
|
||||||
fn validate(origin, prefs: ValidatorPrefs) {
|
pub fn validate(origin, prefs: ValidatorPrefs) {
|
||||||
let controller = ensure_signed(origin)?;
|
let controller = ensure_signed(origin)?;
|
||||||
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
|
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
|
||||||
let stash = &ledger.stash;
|
let stash = &ledger.stash;
|
||||||
@@ -1466,7 +1466,7 @@ decl_module! {
|
|||||||
/// - Both the reads and writes follow a similar pattern.
|
/// - Both the reads and writes follow a similar pattern.
|
||||||
/// # </weight>
|
/// # </weight>
|
||||||
#[weight = SimpleDispatchInfo::FixedNormal(750_000)]
|
#[weight = SimpleDispatchInfo::FixedNormal(750_000)]
|
||||||
fn nominate(origin, targets: Vec<<T::Lookup as StaticLookup>::Source>) {
|
pub fn nominate(origin, targets: Vec<<T::Lookup as StaticLookup>::Source>) {
|
||||||
let controller = ensure_signed(origin)?;
|
let controller = ensure_signed(origin)?;
|
||||||
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
|
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
|
||||||
let stash = &ledger.stash;
|
let stash = &ledger.stash;
|
||||||
@@ -2878,6 +2878,16 @@ impl<T: Trait> Module<T> {
|
|||||||
_ => ForceEra::put(Forcing::ForceNew),
|
_ => ForceEra::put(Forcing::ForceNew),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
|
pub fn add_era_stakers(current_era: EraIndex, controller: T::AccountId, exposure: Exposure<T::AccountId, BalanceOf<T>>) {
|
||||||
|
<ErasStakers<T>>::insert(¤t_era, &controller, &exposure);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
|
pub fn put_election_status(status: ElectionStatus::<T::BlockNumber>) {
|
||||||
|
<EraElectionStatus<T>>::put(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In this implementation `new_session(session)` must be called before `end_session(session-1)`
|
/// In this implementation `new_session(session)` must be called before `end_session(session-1)`
|
||||||
|
|||||||
Reference in New Issue
Block a user