mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 06:48:01 +00:00
Move Staking Weights to T::WeightInfo (#7007)
* Fix the benchmarks * Migrate staking to weightInfo * Fix global benchmarks * re-calculate the submit solution weight. * Fix some refund. * Get rid of all the extra parameters. * Fix staking tests. * new values from the bench machine. * Fix some grumbles * better macro * Some better doc * Move to interpreted wasm * Make it work temporarily * Final fix of default ones. * Fix payout benchmarks * Fix payout stuff * One last fix * use benchmarking machine for numbers * update weight docs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -29,6 +29,14 @@ const MAX_SPANS: u32 = 100;
|
||||
const MAX_VALIDATORS: u32 = 1000;
|
||||
const MAX_SLASHES: u32 = 1000;
|
||||
|
||||
macro_rules! do_whitelist {
|
||||
($acc:ident) => {
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(
|
||||
frame_system::Account::<T>::hashed_key_for(&$acc).into()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add slashing spans to a user account. Not relevant for actual use, only to benchmark
|
||||
// read and write operations.
|
||||
fn add_slashing_spans<T: Trait>(who: &T::AccountId, spans: u32) {
|
||||
@@ -51,11 +59,12 @@ pub fn create_validator_with_nominators<T: Trait>(
|
||||
n: u32,
|
||||
upper_bound: u32,
|
||||
dead: bool,
|
||||
destination: RewardDestination<T::AccountId>
|
||||
) -> Result<T::AccountId, &'static str> {
|
||||
let mut points_total = 0;
|
||||
let mut points_individual = Vec::new();
|
||||
|
||||
let (v_stash, v_controller) = create_stash_controller::<T>(0, 100)?;
|
||||
let (v_stash, v_controller) = create_stash_controller::<T>(0, 100, destination.clone())?;
|
||||
let validator_prefs = ValidatorPrefs {
|
||||
commission: Perbill::from_percent(50),
|
||||
};
|
||||
@@ -68,9 +77,9 @@ pub fn create_validator_with_nominators<T: Trait>(
|
||||
// Give the validator n nominators, but keep total users in the system the same.
|
||||
for i in 0 .. upper_bound {
|
||||
let (_n_stash, n_controller) = if !dead {
|
||||
create_stash_controller::<T>(u32::max_value() - i, 100)?
|
||||
create_stash_controller::<T>(u32::max_value() - i, 100, destination.clone())?
|
||||
} else {
|
||||
create_stash_and_dead_controller::<T>(u32::max_value() - i, 100)?
|
||||
create_stash_and_dead_controller::<T>(u32::max_value() - i, 100, destination.clone())?
|
||||
};
|
||||
if i < n {
|
||||
Staking::<T>::nominate(RawOrigin::Signed(n_controller.clone()).into(), vec![stash_lookup.clone()])?;
|
||||
@@ -100,19 +109,18 @@ pub fn create_validator_with_nominators<T: Trait>(
|
||||
Ok(v_stash)
|
||||
}
|
||||
|
||||
const USER_SEED: u32 = 999666;
|
||||
|
||||
benchmarks! {
|
||||
_{
|
||||
// User account seed
|
||||
let u in 0 .. 1000 => ();
|
||||
}
|
||||
_{}
|
||||
|
||||
bond {
|
||||
let u in ...;
|
||||
let stash = create_funded_user::<T>("stash", u, 100);
|
||||
let controller = create_funded_user::<T>("controller", u, 100);
|
||||
let stash = create_funded_user::<T>("stash", USER_SEED, 100);
|
||||
let controller = create_funded_user::<T>("controller", USER_SEED, 100);
|
||||
let controller_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(controller.clone());
|
||||
let reward_destination = RewardDestination::Staked;
|
||||
let amount = T::Currency::minimum_balance() * 10.into();
|
||||
do_whitelist!(stash);
|
||||
}: _(RawOrigin::Signed(stash.clone()), controller_lookup, amount, reward_destination)
|
||||
verify {
|
||||
assert!(Bonded::<T>::contains_key(stash));
|
||||
@@ -120,11 +128,11 @@ benchmarks! {
|
||||
}
|
||||
|
||||
bond_extra {
|
||||
let u in ...;
|
||||
let (stash, controller) = create_stash_controller::<T>(u, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
let max_additional = T::Currency::minimum_balance() * 10.into();
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created before")?;
|
||||
let original_bonded: BalanceOf<T> = ledger.active;
|
||||
do_whitelist!(stash);
|
||||
}: _(RawOrigin::Signed(stash), max_additional)
|
||||
verify {
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created after")?;
|
||||
@@ -133,11 +141,11 @@ benchmarks! {
|
||||
}
|
||||
|
||||
unbond {
|
||||
let u in ...;
|
||||
let (_, controller) = create_stash_controller::<T>(u, 100)?;
|
||||
let (_, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
let amount = T::Currency::minimum_balance() * 10.into();
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created before")?;
|
||||
let original_bonded: BalanceOf<T> = ledger.active;
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller.clone()), amount)
|
||||
verify {
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created after")?;
|
||||
@@ -149,13 +157,14 @@ benchmarks! {
|
||||
withdraw_unbonded_update {
|
||||
// Slashing Spans
|
||||
let s in 0 .. MAX_SPANS;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100, Default::default())?;
|
||||
add_slashing_spans::<T>(&stash, s);
|
||||
let amount = T::Currency::minimum_balance() * 5.into(); // Half of total
|
||||
Staking::<T>::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?;
|
||||
CurrentEra::put(EraIndex::max_value());
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created before")?;
|
||||
let original_total: BalanceOf<T> = ledger.total;
|
||||
do_whitelist!(controller);
|
||||
}: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s)
|
||||
verify {
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created after")?;
|
||||
@@ -167,22 +176,23 @@ benchmarks! {
|
||||
withdraw_unbonded_kill {
|
||||
// Slashing Spans
|
||||
let s in 0 .. MAX_SPANS;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100, Default::default())?;
|
||||
add_slashing_spans::<T>(&stash, s);
|
||||
let amount = T::Currency::minimum_balance() * 10.into();
|
||||
Staking::<T>::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?;
|
||||
CurrentEra::put(EraIndex::max_value());
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created before")?;
|
||||
let original_total: BalanceOf<T> = ledger.total;
|
||||
do_whitelist!(controller);
|
||||
}: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s)
|
||||
verify {
|
||||
assert!(!Ledger::<T>::contains_key(controller));
|
||||
}
|
||||
|
||||
validate {
|
||||
let u in ...;
|
||||
let (stash, controller) = create_stash_controller::<T>(u, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
let prefs = ValidatorPrefs::default();
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller), prefs)
|
||||
verify {
|
||||
assert!(Validators::<T>::contains_key(stash));
|
||||
@@ -191,51 +201,52 @@ benchmarks! {
|
||||
// Worst case scenario, MAX_NOMINATIONS
|
||||
nominate {
|
||||
let n in 1 .. MAX_NOMINATIONS as u32;
|
||||
let (stash, controller) = create_stash_controller::<T>(n + 1, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(n + 1, 100, Default::default())?;
|
||||
let validators = create_validators::<T>(n, 100)?;
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller), validators)
|
||||
verify {
|
||||
assert!(Nominators::<T>::contains_key(stash));
|
||||
}
|
||||
|
||||
chill {
|
||||
let u in ...;
|
||||
let (_, controller) = create_stash_controller::<T>(u, 100)?;
|
||||
let (_, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller))
|
||||
|
||||
set_payee {
|
||||
let u in ...;
|
||||
let (stash, controller) = create_stash_controller::<T>(u, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
assert_eq!(Payee::<T>::get(&stash), RewardDestination::Staked);
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller), RewardDestination::Controller)
|
||||
verify {
|
||||
assert_eq!(Payee::<T>::get(&stash), RewardDestination::Controller);
|
||||
}
|
||||
|
||||
set_controller {
|
||||
let u in ...;
|
||||
let (stash, _) = create_stash_controller::<T>(u, 100)?;
|
||||
let new_controller = create_funded_user::<T>("new_controller", u, 100);
|
||||
let (stash, _) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
let new_controller = create_funded_user::<T>("new_controller", USER_SEED, 100);
|
||||
let new_controller_lookup = T::Lookup::unlookup(new_controller.clone());
|
||||
do_whitelist!(stash);
|
||||
}: _(RawOrigin::Signed(stash), new_controller_lookup)
|
||||
verify {
|
||||
assert!(Ledger::<T>::contains_key(&new_controller));
|
||||
}
|
||||
|
||||
set_validator_count {
|
||||
let c in 0 .. MAX_VALIDATORS;
|
||||
}: _(RawOrigin::Root, c)
|
||||
let validator_count = MAX_VALIDATORS;
|
||||
}: _(RawOrigin::Root, validator_count)
|
||||
verify {
|
||||
assert_eq!(ValidatorCount::get(), c);
|
||||
assert_eq!(ValidatorCount::get(), validator_count);
|
||||
}
|
||||
|
||||
force_no_eras { let i in 0 .. 1; }: _(RawOrigin::Root)
|
||||
force_no_eras {}: _(RawOrigin::Root)
|
||||
verify { assert_eq!(ForceEra::get(), Forcing::ForceNone); }
|
||||
|
||||
force_new_era {let i in 0 .. 1; }: _(RawOrigin::Root)
|
||||
force_new_era {}: _(RawOrigin::Root)
|
||||
verify { assert_eq!(ForceEra::get(), Forcing::ForceNew); }
|
||||
|
||||
force_new_era_always { let i in 0 .. 1; }: _(RawOrigin::Root)
|
||||
force_new_era_always {}: _(RawOrigin::Root)
|
||||
verify { assert_eq!(ForceEra::get(), Forcing::ForceAlways); }
|
||||
|
||||
// Worst case scenario, the list of invulnerables is very long.
|
||||
@@ -253,7 +264,7 @@ benchmarks! {
|
||||
force_unstake {
|
||||
// Slashing Spans
|
||||
let s in 0 .. MAX_SPANS;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100, Default::default())?;
|
||||
add_slashing_spans::<T>(&stash, s);
|
||||
}: _(RawOrigin::Root, stash, s)
|
||||
verify {
|
||||
@@ -275,37 +286,60 @@ benchmarks! {
|
||||
assert_eq!(UnappliedSlashes::<T>::get(&era).len(), (MAX_SLASHES - s) as usize);
|
||||
}
|
||||
|
||||
payout_stakers {
|
||||
payout_stakers_dead_controller {
|
||||
let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32;
|
||||
let validator = create_validator_with_nominators::<T>(n, T::MaxNominatorRewardedPerValidator::get() as u32, true)?;
|
||||
let validator = create_validator_with_nominators::<T>(
|
||||
n,
|
||||
T::MaxNominatorRewardedPerValidator::get() as u32,
|
||||
true,
|
||||
RewardDestination::Controller,
|
||||
)?;
|
||||
|
||||
let current_era = CurrentEra::get().unwrap();
|
||||
// set the commission for this particular era as well.
|
||||
<ErasValidatorPrefs<T>>::insert(current_era, validator.clone(), <Staking<T>>::validators(&validator));
|
||||
|
||||
let caller = whitelisted_caller();
|
||||
let balance_before = T::Currency::free_balance(&validator);
|
||||
}: _(RawOrigin::Signed(caller), validator.clone(), current_era)
|
||||
let validator_controller = <Bonded<T>>::get(&validator).unwrap();
|
||||
let balance_before = T::Currency::free_balance(&validator_controller);
|
||||
}: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era)
|
||||
verify {
|
||||
// Validator has been paid!
|
||||
let balance_after = T::Currency::free_balance(&validator);
|
||||
assert!(balance_before < balance_after);
|
||||
let balance_after = T::Currency::free_balance(&validator_controller);
|
||||
assert!(
|
||||
balance_before < balance_after,
|
||||
"Balance of controller {:?} should have increased after payout.",
|
||||
validator,
|
||||
);
|
||||
}
|
||||
|
||||
payout_stakers_alive_controller {
|
||||
payout_stakers_alive_staked {
|
||||
let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32;
|
||||
let validator = create_validator_with_nominators::<T>(n, T::MaxNominatorRewardedPerValidator::get() as u32, false)?;
|
||||
let validator = create_validator_with_nominators::<T>(
|
||||
n,
|
||||
T::MaxNominatorRewardedPerValidator::get() as u32,
|
||||
false,
|
||||
RewardDestination::Staked,
|
||||
)?;
|
||||
|
||||
let current_era = CurrentEra::get().unwrap();
|
||||
// set the commission for this particular era as well.
|
||||
<ErasValidatorPrefs<T>>::insert(current_era, validator.clone(), <Staking<T>>::validators(&validator));
|
||||
|
||||
let caller = whitelisted_caller();
|
||||
let balance_before = T::Currency::free_balance(&validator);
|
||||
}: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era)
|
||||
verify {
|
||||
// Validator has been paid!
|
||||
let balance_after = T::Currency::free_balance(&validator);
|
||||
assert!(balance_before < balance_after);
|
||||
assert!(
|
||||
balance_before < balance_after,
|
||||
"Balance of stash {:?} should have increased after payout.",
|
||||
validator,
|
||||
);
|
||||
}
|
||||
|
||||
rebond {
|
||||
let l in 1 .. MAX_UNLOCKING_CHUNKS as u32;
|
||||
let (_, controller) = create_stash_controller::<T>(u, 100)?;
|
||||
let (_, controller) = create_stash_controller::<T>(USER_SEED, 100, Default::default())?;
|
||||
let mut staking_ledger = Ledger::<T>::get(controller.clone()).unwrap();
|
||||
let unlock_chunk = UnlockChunk::<BalanceOf<T>> {
|
||||
value: 1.into(),
|
||||
@@ -316,6 +350,7 @@ benchmarks! {
|
||||
}
|
||||
Ledger::<T>::insert(controller.clone(), staking_ledger.clone());
|
||||
let original_bonded: BalanceOf<T> = staking_ledger.active;
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller.clone()), (l + 100).into())
|
||||
verify {
|
||||
let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created after")?;
|
||||
@@ -343,9 +378,10 @@ benchmarks! {
|
||||
|
||||
reap_stash {
|
||||
let s in 1 .. MAX_SPANS;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100, Default::default())?;
|
||||
add_slashing_spans::<T>(&stash, s);
|
||||
T::Currency::make_free_balance_be(&stash, 0.into());
|
||||
do_whitelist!(controller);
|
||||
}: _(RawOrigin::Signed(controller), stash.clone(), s)
|
||||
verify {
|
||||
assert!(!Bonded::<T>::contains_key(&stash));
|
||||
@@ -362,32 +398,7 @@ benchmarks! {
|
||||
assert!(validators.len() == v as usize);
|
||||
}
|
||||
|
||||
do_slash {
|
||||
let l in 1 .. MAX_UNLOCKING_CHUNKS as u32;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100)?;
|
||||
let mut staking_ledger = Ledger::<T>::get(controller.clone()).unwrap();
|
||||
let unlock_chunk = UnlockChunk::<BalanceOf<T>> {
|
||||
value: 1.into(),
|
||||
era: EraIndex::zero(),
|
||||
};
|
||||
for _ in 0 .. l {
|
||||
staking_ledger.unlocking.push(unlock_chunk.clone())
|
||||
}
|
||||
Ledger::<T>::insert(controller, staking_ledger);
|
||||
let slash_amount = T::Currency::minimum_balance() * 10.into();
|
||||
let balance_before = T::Currency::free_balance(&stash);
|
||||
}: {
|
||||
crate::slashing::do_slash::<T>(
|
||||
&stash,
|
||||
slash_amount,
|
||||
&mut BalanceOf::<T>::zero(),
|
||||
&mut NegativeImbalanceOf::<T>::zero()
|
||||
);
|
||||
} verify {
|
||||
let balance_after = T::Currency::free_balance(&stash);
|
||||
assert!(balance_before > balance_after);
|
||||
}
|
||||
|
||||
#[extra]
|
||||
payout_all {
|
||||
let v in 1 .. 10;
|
||||
let n in 1 .. 100;
|
||||
@@ -426,18 +437,45 @@ benchmarks! {
|
||||
}
|
||||
}
|
||||
|
||||
// This benchmark create `v` validators intent, `n` nominators intent, each nominator nominate
|
||||
// MAX_NOMINATIONS in the set of the first `w` validators.
|
||||
// It builds a solution with `w` winners composed of nominated validators randomly nominated,
|
||||
// `a` assignment with MAX_NOMINATIONS.
|
||||
#[extra]
|
||||
do_slash {
|
||||
let l in 1 .. MAX_UNLOCKING_CHUNKS as u32;
|
||||
let (stash, controller) = create_stash_controller::<T>(0, 100, Default::default())?;
|
||||
let mut staking_ledger = Ledger::<T>::get(controller.clone()).unwrap();
|
||||
let unlock_chunk = UnlockChunk::<BalanceOf<T>> {
|
||||
value: 1.into(),
|
||||
era: EraIndex::zero(),
|
||||
};
|
||||
for _ in 0 .. l {
|
||||
staking_ledger.unlocking.push(unlock_chunk.clone())
|
||||
}
|
||||
Ledger::<T>::insert(controller, staking_ledger);
|
||||
let slash_amount = T::Currency::minimum_balance() * 10.into();
|
||||
let balance_before = T::Currency::free_balance(&stash);
|
||||
}: {
|
||||
crate::slashing::do_slash::<T>(
|
||||
&stash,
|
||||
slash_amount,
|
||||
&mut BalanceOf::<T>::zero(),
|
||||
&mut NegativeImbalanceOf::<T>::zero()
|
||||
);
|
||||
} verify {
|
||||
let balance_after = T::Currency::free_balance(&stash);
|
||||
assert!(balance_before > balance_after);
|
||||
}
|
||||
|
||||
// This benchmark create `v` validators intent, `n` nominators intent, in total creating `e`
|
||||
// edges.
|
||||
#[extra]
|
||||
submit_solution_initial {
|
||||
// number of validator intent
|
||||
let v in 1000 .. 2000;
|
||||
// number of nominator intent
|
||||
let n in 1000 .. 2000;
|
||||
// number of assignments. Basically, number of active nominators.
|
||||
let a in 200 .. 500;
|
||||
// number of winners, also ValidatorCount
|
||||
// number of validator intention. This will be equal to `ElectionSize::validators`.
|
||||
let v in 200 .. 400;
|
||||
// number of nominator intention. This will be equal to `ElectionSize::nominators`.
|
||||
let n in 500 .. 1000;
|
||||
// number of assignments. Basically, number of active nominators. This will be equal to
|
||||
// `compact.len()`.
|
||||
let a in 200 .. 400;
|
||||
// number of winners, also ValidatorCount. This will be equal to `winner.len()`.
|
||||
let w in 16 .. 100;
|
||||
|
||||
ensure!(w as usize >= MAX_NOMINATIONS, "doesn't support lower value");
|
||||
@@ -466,15 +504,19 @@ benchmarks! {
|
||||
size
|
||||
) = offchain_election::prepare_submission::<T>(assignments, winners, false).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
winners.len(), compact.unique_targets().len(),
|
||||
"unique targets ({}) and winners ({}) count not same. This solution is not valid.",
|
||||
compact.unique_targets().len(),
|
||||
winners.len(),
|
||||
);
|
||||
|
||||
// needed for the solution to be accepted
|
||||
<EraElectionStatus<T>>::put(ElectionStatus::Open(T::BlockNumber::from(1u32)));
|
||||
|
||||
let era = <Staking<T>>::current_era().unwrap_or(0);
|
||||
let caller: T::AccountId = account("caller", n, SEED);
|
||||
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
do_whitelist!(caller);
|
||||
}: {
|
||||
let result = <Staking<T>>::submit_election_solution(
|
||||
RawOrigin::Signed(caller.clone()).into(),
|
||||
@@ -493,13 +535,13 @@ benchmarks! {
|
||||
|
||||
// same as submit_solution_initial but we place a very weak solution on chian first.
|
||||
submit_solution_better {
|
||||
// number of validator intent
|
||||
let v in 1000 .. 2000;
|
||||
// number of nominator intent
|
||||
let n in 1000 .. 2000;
|
||||
// number of validator intention.
|
||||
let v in 200 .. 400;
|
||||
// number of nominator intention.
|
||||
let n in 500 .. 1000;
|
||||
// number of assignments. Basically, number of active nominators.
|
||||
let a in 200 .. 500;
|
||||
// number of winners, also ValidatorCount
|
||||
let a in 200 .. 400;
|
||||
// number of winners, also ValidatorCount.
|
||||
let w in 16 .. 100;
|
||||
|
||||
ensure!(w as usize >= MAX_NOMINATIONS, "doesn't support lower value");
|
||||
@@ -530,15 +572,19 @@ benchmarks! {
|
||||
size
|
||||
) = offchain_election::prepare_submission::<T>(assignments, winners, false).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
winners.len(), compact.unique_targets().len(),
|
||||
"unique targets ({}) and winners ({}) count not same. This solution is not valid.",
|
||||
compact.unique_targets().len(),
|
||||
winners.len(),
|
||||
);
|
||||
|
||||
// needed for the solution to be accepted
|
||||
<EraElectionStatus<T>>::put(ElectionStatus::Open(T::BlockNumber::from(1u32)));
|
||||
|
||||
let era = <Staking<T>>::current_era().unwrap_or(0);
|
||||
let caller: T::AccountId = account("caller", n, SEED);
|
||||
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
do_whitelist!(caller);
|
||||
|
||||
// submit a very bad solution on-chain
|
||||
{
|
||||
@@ -576,11 +622,12 @@ benchmarks! {
|
||||
}
|
||||
|
||||
// This will be early rejected based on the score.
|
||||
#[extra]
|
||||
submit_solution_weaker {
|
||||
// number of validator intent
|
||||
let v in 1000 .. 2000;
|
||||
// number of nominator intent
|
||||
let n in 1000 .. 2000;
|
||||
// number of validator intention.
|
||||
let v in 200 .. 400;
|
||||
// number of nominator intention.
|
||||
let n in 500 .. 1000;
|
||||
|
||||
create_validators_with_nominators_for_era::<T>(v, n, MAX_NOMINATIONS, false, None)?;
|
||||
|
||||
@@ -589,16 +636,19 @@ benchmarks! {
|
||||
|
||||
// needed for the solution to be accepted
|
||||
<EraElectionStatus<T>>::put(ElectionStatus::Open(T::BlockNumber::from(1u32)));
|
||||
let caller: T::AccountId = account("caller", n, SEED);
|
||||
let era = <Staking<T>>::current_era().unwrap_or(0);
|
||||
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
let caller: T::AccountId = account("caller", n, SEED);
|
||||
do_whitelist!(caller);
|
||||
|
||||
// submit a seq-phragmen with all the good stuff on chain.
|
||||
{
|
||||
let (winners, compact, score, size) = get_seq_phragmen_solution::<T>(true);
|
||||
assert_eq!(
|
||||
winners.len(), compact.unique_targets().len(),
|
||||
"unique targets ({}) and winners ({}) count not same. This solution is not valid.",
|
||||
compact.unique_targets().len(),
|
||||
winners.len(),
|
||||
);
|
||||
assert!(
|
||||
<Staking<T>>::submit_election_solution(
|
||||
RawOrigin::Signed(caller.clone()).into(),
|
||||
@@ -662,6 +712,7 @@ mod tests {
|
||||
n,
|
||||
<Test as Trait>::MaxNominatorRewardedPerValidator::get() as u32,
|
||||
false,
|
||||
RewardDestination::Staked,
|
||||
).unwrap();
|
||||
|
||||
let current_era = CurrentEra::get().unwrap();
|
||||
@@ -683,6 +734,7 @@ mod tests {
|
||||
n,
|
||||
<Test as Trait>::MaxNominatorRewardedPerValidator::get() as u32,
|
||||
false,
|
||||
RewardDestination::Staked,
|
||||
).unwrap();
|
||||
|
||||
// Add 20 slashing spans
|
||||
@@ -743,8 +795,8 @@ mod tests {
|
||||
assert_ok!(test_benchmark_set_invulnerables::<Test>());
|
||||
assert_ok!(test_benchmark_force_unstake::<Test>());
|
||||
assert_ok!(test_benchmark_cancel_deferred_slash::<Test>());
|
||||
assert_ok!(test_benchmark_payout_stakers::<Test>());
|
||||
assert_ok!(test_benchmark_payout_stakers_alive_controller::<Test>());
|
||||
assert_ok!(test_benchmark_payout_stakers_dead_controller::<Test>());
|
||||
assert_ok!(test_benchmark_payout_stakers_alive_staked::<Test>());
|
||||
assert_ok!(test_benchmark_rebond::<Test>());
|
||||
assert_ok!(test_benchmark_set_history_depth::<Test>());
|
||||
assert_ok!(test_benchmark_reap_stash::<Test>());
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Default weights of pallet-staking.
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0-rc6
|
||||
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};
|
||||
|
||||
impl crate::WeightInfo for () {
|
||||
fn bond() -> Weight {
|
||||
(144278000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
fn bond_extra() -> Weight {
|
||||
(110715000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn unbond() -> Weight {
|
||||
(99840000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn withdraw_unbonded_update(s: u32, ) -> Weight {
|
||||
(100728000 as Weight)
|
||||
.saturating_add((63000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn withdraw_unbonded_kill(s: u32, ) -> Weight {
|
||||
(168879000 as Weight)
|
||||
.saturating_add((6666000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(DbWeight::get().reads(7 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(8 as Weight))
|
||||
.saturating_add(DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
|
||||
}
|
||||
fn validate() -> Weight {
|
||||
(35539000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn nominate(n: u32, ) -> Weight {
|
||||
(48596000 as Weight)
|
||||
.saturating_add((308000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn chill() -> Weight {
|
||||
(35144000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn set_payee() -> Weight {
|
||||
(24255000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_controller() -> Weight {
|
||||
(52294000 as Weight)
|
||||
.saturating_add(DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn set_validator_count() -> Weight {
|
||||
(5185000 as Weight)
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_no_eras() -> Weight {
|
||||
(5907000 as Weight)
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_new_era() -> Weight {
|
||||
(5917000 as Weight)
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_new_era_always() -> Weight {
|
||||
(5952000 as Weight)
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_invulnerables(v: u32, ) -> Weight {
|
||||
(6324000 as Weight)
|
||||
.saturating_add((9000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_unstake(s: u32, ) -> Weight {
|
||||
(119691000 as Weight)
|
||||
.saturating_add((6681000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(8 as Weight))
|
||||
.saturating_add(DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
|
||||
}
|
||||
fn cancel_deferred_slash(s: u32, ) -> Weight {
|
||||
(5820201000 as Weight)
|
||||
.saturating_add((34672000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn payout_stakers_dead_controller(n: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((92486000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
|
||||
.saturating_add(DbWeight::get().writes((1 as Weight).saturating_mul(n as Weight)))
|
||||
}
|
||||
fn payout_stakers_alive_staked(n: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((117324000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight)))
|
||||
.saturating_add(DbWeight::get().writes((3 as Weight).saturating_mul(n as Weight)))
|
||||
}
|
||||
fn rebond(l: u32, ) -> Weight {
|
||||
(71316000 as Weight)
|
||||
.saturating_add((142000 as Weight).saturating_mul(l as Weight))
|
||||
.saturating_add(DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn set_history_depth(e: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((51901000 as Weight).saturating_mul(e as Weight))
|
||||
.saturating_add(DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(4 as Weight))
|
||||
.saturating_add(DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight)))
|
||||
}
|
||||
fn reap_stash(s: u32, ) -> Weight {
|
||||
(147166000 as Weight)
|
||||
.saturating_add((6661000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(DbWeight::get().writes(8 as Weight))
|
||||
.saturating_add(DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight)))
|
||||
}
|
||||
fn new_era(v: u32, n: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((1440459000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add((182580000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(DbWeight::get().reads(10 as Weight))
|
||||
.saturating_add(DbWeight::get().reads((4 as Weight).saturating_mul(v as Weight)))
|
||||
.saturating_add(DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight)))
|
||||
.saturating_add(DbWeight::get().writes(8 as Weight))
|
||||
.saturating_add(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)
|
||||
.saturating_add((964000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add((432000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add((204294000 as Weight).saturating_mul(a as Weight))
|
||||
.saturating_add((9546000 as Weight).saturating_mul(w as Weight))
|
||||
.saturating_add(DbWeight::get().reads(6 as Weight))
|
||||
.saturating_add(DbWeight::get().reads((4 as Weight).saturating_mul(a as Weight)))
|
||||
.saturating_add(DbWeight::get().reads((1 as Weight).saturating_mul(w as Weight)))
|
||||
.saturating_add(DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
}
|
||||
@@ -279,6 +279,7 @@ pub mod benchmarking;
|
||||
pub mod slashing;
|
||||
pub mod offchain_election;
|
||||
pub mod inflation;
|
||||
pub mod default_weights;
|
||||
|
||||
use sp_std::{
|
||||
result,
|
||||
@@ -356,6 +357,8 @@ pub type ValidatorIndex = u16;
|
||||
// Ensure the size of both ValidatorIndex and NominatorIndex. They both need to be well below usize.
|
||||
static_assertions::const_assert!(size_of::<ValidatorIndex>() <= size_of::<usize>());
|
||||
static_assertions::const_assert!(size_of::<NominatorIndex>() <= size_of::<usize>());
|
||||
static_assertions::const_assert!(size_of::<ValidatorIndex>() <= size_of::<u32>());
|
||||
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;
|
||||
@@ -766,132 +769,31 @@ impl<T: Trait> SessionInterface<<T as frame_system::Trait>::AccountId> for T whe
|
||||
}
|
||||
}
|
||||
|
||||
pub mod weight {
|
||||
use super::*;
|
||||
|
||||
/// All weight notes are pertaining to the case of a better solution, in which we execute
|
||||
/// the longest code path.
|
||||
/// Weight: 0 + (0.63 μs * v) + (0.36 μs * n) + (96.53 μs * a ) + (8 μs * w ) with:
|
||||
/// * v validators in snapshot validators,
|
||||
/// * n nominators in snapshot nominators,
|
||||
/// * a assignment in the submitted solution
|
||||
/// * w winners in the submitted solution
|
||||
///
|
||||
/// State reads:
|
||||
/// - Initial checks:
|
||||
/// - ElectionState, CurrentEra, QueuedScore
|
||||
/// - SnapshotValidators.len() + SnapShotNominators.len()
|
||||
/// - ValidatorCount
|
||||
/// - SnapshotValidators
|
||||
/// - SnapshotNominators
|
||||
/// - Iterate over nominators:
|
||||
/// - compact.len() * Nominators(who)
|
||||
/// - (non_self_vote_edges) * SlashingSpans
|
||||
/// - For `assignment_ratio_to_staked`: Basically read the staked value of each stash.
|
||||
/// - (winners.len() + compact.len()) * (Ledger + Bonded)
|
||||
/// - TotalIssuance (read a gzillion times potentially, but well it is cached.)
|
||||
/// - State writes:
|
||||
/// - QueuedElected, QueuedScore
|
||||
pub fn weight_for_submit_solution<T: Trait>(
|
||||
winners: &Vec<ValidatorIndex>,
|
||||
compact: &CompactAssignments,
|
||||
size: &ElectionSize,
|
||||
) -> Weight {
|
||||
(630 * WEIGHT_PER_NANOS).saturating_mul(size.validators as Weight)
|
||||
.saturating_add((360 * WEIGHT_PER_NANOS).saturating_mul(size.nominators as Weight))
|
||||
.saturating_add((96 * WEIGHT_PER_MICROS).saturating_mul(compact.len() as Weight))
|
||||
.saturating_add((8 * WEIGHT_PER_MICROS).saturating_mul(winners.len() as Weight))
|
||||
// Initial checks
|
||||
.saturating_add(T::DbWeight::get().reads(8))
|
||||
// Nominators
|
||||
.saturating_add(T::DbWeight::get().reads(compact.len() as Weight))
|
||||
// SlashingSpans (upper bound for invalid solution)
|
||||
.saturating_add(T::DbWeight::get().reads(compact.edge_count() as Weight))
|
||||
// `assignment_ratio_to_staked`
|
||||
.saturating_add(T::DbWeight::get().reads(2 * ((winners.len() + compact.len()) as Weight)))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
// write queued score and elected
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
|
||||
/// Weight of `submit_solution` in case of a correct submission.
|
||||
///
|
||||
/// refund: we charged compact.len() * read(1) for SlashingSpans. A valid solution only reads
|
||||
/// winners.len().
|
||||
pub fn weight_for_correct_submit_solution<T: Trait>(
|
||||
winners: &Vec<ValidatorIndex>,
|
||||
compact: &CompactAssignments,
|
||||
size: &ElectionSize,
|
||||
) -> Weight {
|
||||
// NOTE: for consistency, we re-compute the original weight to maintain their relation and
|
||||
// prevent any foot-guns.
|
||||
let original_weight = weight_for_submit_solution::<T>(winners, compact, size);
|
||||
original_weight
|
||||
.saturating_sub(T::DbWeight::get().reads(compact.edge_count() as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(winners.len() as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WeightInfo {
|
||||
fn bond(u: u32, ) -> Weight;
|
||||
fn bond_extra(u: u32, ) -> Weight;
|
||||
fn unbond(u: u32, ) -> Weight;
|
||||
fn bond() -> Weight;
|
||||
fn bond_extra() -> Weight;
|
||||
fn unbond() -> Weight;
|
||||
fn withdraw_unbonded_update(s: u32, ) -> Weight;
|
||||
fn withdraw_unbonded_kill(s: u32, ) -> Weight;
|
||||
fn validate(u: u32, ) -> Weight;
|
||||
fn validate() -> Weight;
|
||||
fn nominate(n: u32, ) -> Weight;
|
||||
fn chill(u: u32, ) -> Weight;
|
||||
fn set_payee(u: u32, ) -> Weight;
|
||||
fn set_controller(u: u32, ) -> Weight;
|
||||
fn set_validator_count(c: u32, ) -> Weight;
|
||||
fn force_no_eras(i: u32, ) -> Weight;
|
||||
fn force_new_era(i: u32, ) -> Weight;
|
||||
fn force_new_era_always(i: u32, ) -> Weight;
|
||||
fn chill() -> Weight;
|
||||
fn set_payee() -> Weight;
|
||||
fn set_controller() -> Weight;
|
||||
fn set_validator_count() -> Weight;
|
||||
fn force_no_eras() -> Weight;
|
||||
fn force_new_era() -> Weight;
|
||||
fn force_new_era_always() -> Weight;
|
||||
fn set_invulnerables(v: u32, ) -> Weight;
|
||||
fn force_unstake(s: u32, ) -> Weight;
|
||||
fn cancel_deferred_slash(s: u32, ) -> Weight;
|
||||
fn payout_stakers(n: u32, ) -> Weight;
|
||||
fn payout_stakers_alive_controller(n: u32, ) -> Weight;
|
||||
fn payout_stakers_alive_staked(n: u32, ) -> Weight;
|
||||
fn payout_stakers_dead_controller(n: u32, ) -> Weight;
|
||||
fn rebond(l: u32, ) -> Weight;
|
||||
fn set_history_depth(e: u32, ) -> Weight;
|
||||
fn reap_stash(s: u32, ) -> Weight;
|
||||
fn new_era(v: u32, n: u32, ) -> Weight;
|
||||
fn do_slash(l: u32, ) -> Weight;
|
||||
fn payout_all(v: u32, n: u32, ) -> Weight;
|
||||
fn submit_solution_initial(v: u32, n: u32, a: u32, w: u32, ) -> Weight;
|
||||
fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight;
|
||||
fn submit_solution_weaker(v: u32, n: u32, ) -> Weight;
|
||||
}
|
||||
|
||||
impl WeightInfo for () {
|
||||
fn bond(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn bond_extra(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn unbond(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn withdraw_unbonded_update(_s: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn withdraw_unbonded_kill(_s: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn validate(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn nominate(_n: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn chill(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn set_payee(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn set_controller(_u: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn set_validator_count(_c: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn force_no_eras(_i: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn force_new_era(_i: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn force_new_era_always(_i: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn set_invulnerables(_v: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn force_unstake(_s: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn cancel_deferred_slash(_s: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn payout_stakers(_n: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn payout_stakers_alive_controller(_n: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn rebond(_l: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn set_history_depth(_e: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn reap_stash(_s: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn new_era(_v: u32, _n: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn do_slash(_l: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn payout_all(_v: u32, _n: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn submit_solution_initial(_v: u32, _n: u32, _a: u32, _w: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn submit_solution_better(_v: u32, _n: u32, _a: u32, _w: u32, ) -> Weight { 1_000_000_000 }
|
||||
fn submit_solution_weaker(_v: u32, _n: u32, ) -> Weight { 1_000_000_000 }
|
||||
}
|
||||
|
||||
pub trait Trait: frame_system::Trait + SendTransactionTypes<Call<Self>> {
|
||||
@@ -1489,12 +1391,12 @@ decl_module! {
|
||||
/// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned
|
||||
/// unless the `origin` falls below _existential deposit_ and gets removed as dust.
|
||||
/// ------------------
|
||||
/// Base Weight: 67.87 µs
|
||||
/// Weight: O(1)
|
||||
/// DB Weight:
|
||||
/// - Read: Bonded, Ledger, [Origin Account], Current Era, History Depth, Locks
|
||||
/// - Write: Bonded, Payee, [Origin Account], Locks, Ledger
|
||||
/// # </weight>
|
||||
#[weight = 67 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(5, 4)]
|
||||
#[weight = T::WeightInfo::bond()]
|
||||
pub fn bond(origin,
|
||||
controller: <T::Lookup as StaticLookup>::Source,
|
||||
#[compact] value: BalanceOf<T>,
|
||||
@@ -1558,12 +1460,11 @@ decl_module! {
|
||||
/// - O(1).
|
||||
/// - One DB entry.
|
||||
/// ------------
|
||||
/// Base Weight: 54.88 µs
|
||||
/// DB Weight:
|
||||
/// - Read: Era Election Status, Bonded, Ledger, [Origin Account], Locks
|
||||
/// - Write: [Origin Account], Locks, Ledger
|
||||
/// # </weight>
|
||||
#[weight = 55 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)]
|
||||
#[weight = T::WeightInfo::bond_extra()]
|
||||
fn bond_extra(origin, #[compact] max_additional: BalanceOf<T>) {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let stash = ensure_signed(origin)?;
|
||||
@@ -1609,12 +1510,12 @@ decl_module! {
|
||||
/// `withdraw_unbonded`.
|
||||
/// - One DB entry.
|
||||
/// ----------
|
||||
/// Base Weight: 50.34 µs
|
||||
/// Weight: O(1)
|
||||
/// DB Weight:
|
||||
/// - Read: Era Election Status, Ledger, Current Era, Locks, [Origin Account]
|
||||
/// - Write: [Origin Account], Locks, Ledger
|
||||
/// - Read: EraElectionStatus, Ledger, CurrentEra, Locks, BalanceOf Stash,
|
||||
/// - Write: Locks, Ledger, BalanceOf Stash,
|
||||
/// </weight>
|
||||
#[weight = 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)]
|
||||
#[weight = T::WeightInfo::unbond()]
|
||||
fn unbond(origin, #[compact] value: BalanceOf<T>) {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let controller = ensure_signed(origin)?;
|
||||
@@ -1663,25 +1564,18 @@ decl_module! {
|
||||
/// - Writes are limited to the `origin` account key.
|
||||
/// ---------------
|
||||
/// Complexity O(S) where S is the number of slashing spans to remove
|
||||
/// Base Weight:
|
||||
/// Update: 50.52 + .028 * S µs
|
||||
/// Update:
|
||||
/// - Reads: EraElectionStatus, Ledger, Current Era, Locks, [Origin Account]
|
||||
/// - Writes: [Origin Account], Locks, Ledger
|
||||
/// Kill: 79.41 + 2.366 * S µs
|
||||
/// - Reads: EraElectionStatus, Ledger, Current Era, Bonded, Slashing Spans, [Origin Account], Locks
|
||||
/// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, [Origin Account], Locks
|
||||
/// Kill:
|
||||
/// - Reads: EraElectionStatus, Ledger, Current Era, Bonded, Slashing Spans, [Origin
|
||||
/// Account], Locks, BalanceOf stash
|
||||
/// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators,
|
||||
/// [Origin Account], Locks, BalanceOf stash.
|
||||
/// - Writes Each: SpanSlash * S
|
||||
/// NOTE: Weight annotation is the kill scenario, we refund otherwise.
|
||||
/// # </weight>
|
||||
#[weight = T::DbWeight::get().reads_writes(6, 6)
|
||||
.saturating_add(80 * WEIGHT_PER_MICROS)
|
||||
.saturating_add(
|
||||
(2 * WEIGHT_PER_MICROS).saturating_mul(Weight::from(*num_slashing_spans))
|
||||
)
|
||||
.saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans)))
|
||||
// if slashing spans is non-zero, add 1 more write
|
||||
.saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans).min(1)))
|
||||
]
|
||||
#[weight = T::WeightInfo::withdraw_unbonded_kill(*num_slashing_spans)]
|
||||
fn withdraw_unbonded(origin, num_slashing_spans: u32) -> DispatchResultWithPostInfo {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let controller = ensure_signed(origin)?;
|
||||
@@ -1703,8 +1597,9 @@ decl_module! {
|
||||
} else {
|
||||
// This was the consequence of a partial unbond. just update the ledger and move on.
|
||||
Self::update_ledger(&controller, &ledger);
|
||||
// This is only an update, so we use less overall weight
|
||||
Some(50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2))
|
||||
|
||||
// This is only an update, so we use less overall weight.
|
||||
Some(T::WeightInfo::withdraw_unbonded_update(num_slashing_spans))
|
||||
};
|
||||
|
||||
// `old_total` should never be less than the new total because
|
||||
@@ -1730,12 +1625,12 @@ decl_module! {
|
||||
/// - Contains a limited number of reads.
|
||||
/// - Writes are limited to the `origin` account key.
|
||||
/// -----------
|
||||
/// Base Weight: 17.13 µs
|
||||
/// Weight: O(1)
|
||||
/// DB Weight:
|
||||
/// - Read: Era Election Status, Ledger
|
||||
/// - Write: Nominators, Validators
|
||||
/// # </weight>
|
||||
#[weight = 17 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(2, 2)]
|
||||
#[weight = T::WeightInfo::validate()]
|
||||
pub fn validate(origin, prefs: ValidatorPrefs) {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let controller = ensure_signed(origin)?;
|
||||
@@ -1758,16 +1653,13 @@ decl_module! {
|
||||
/// which is capped at CompactAssignments::LIMIT (MAX_NOMINATIONS).
|
||||
/// - Both the reads and writes follow a similar pattern.
|
||||
/// ---------
|
||||
/// Base Weight: 22.34 + .36 * N µs
|
||||
/// Weight: O(N)
|
||||
/// where N is the number of targets
|
||||
/// DB Weight:
|
||||
/// - Reads: Era Election Status, Ledger, Current Era
|
||||
/// - Writes: Validators, Nominators
|
||||
/// # </weight>
|
||||
#[weight = T::DbWeight::get().reads_writes(3, 2)
|
||||
.saturating_add(22 * WEIGHT_PER_MICROS)
|
||||
.saturating_add((360 * WEIGHT_PER_NANOS).saturating_mul(targets.len() as Weight))
|
||||
]
|
||||
#[weight = T::WeightInfo::nominate(targets.len() as u32)]
|
||||
pub fn nominate(origin, targets: Vec<<T::Lookup as StaticLookup>::Source>) {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let controller = ensure_signed(origin)?;
|
||||
@@ -1802,12 +1694,12 @@ decl_module! {
|
||||
/// - Contains one read.
|
||||
/// - Writes are limited to the `origin` account key.
|
||||
/// --------
|
||||
/// Base Weight: 16.53 µs
|
||||
/// Weight: O(1)
|
||||
/// DB Weight:
|
||||
/// - Read: EraElectionStatus, Ledger
|
||||
/// - Write: Validators, Nominators
|
||||
/// # </weight>
|
||||
#[weight = 16 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(2, 2)]
|
||||
#[weight = T::WeightInfo::chill()]
|
||||
fn chill(origin) {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let controller = ensure_signed(origin)?;
|
||||
@@ -1826,12 +1718,12 @@ decl_module! {
|
||||
/// - Contains a limited number of reads.
|
||||
/// - Writes are limited to the `origin` account key.
|
||||
/// ---------
|
||||
/// - Base Weight: 11.33 µs
|
||||
/// - Weight: O(1)
|
||||
/// - DB Weight:
|
||||
/// - Read: Ledger
|
||||
/// - Write: Payee
|
||||
/// # </weight>
|
||||
#[weight = 11 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)]
|
||||
#[weight = T::WeightInfo::set_payee()]
|
||||
fn set_payee(origin, payee: RewardDestination<T::AccountId>) {
|
||||
let controller = ensure_signed(origin)?;
|
||||
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
|
||||
@@ -1850,12 +1742,12 @@ decl_module! {
|
||||
/// - Contains a limited number of reads.
|
||||
/// - Writes are limited to the `origin` account key.
|
||||
/// ----------
|
||||
/// Base Weight: 25.22 µs
|
||||
/// Weight: O(1)
|
||||
/// DB Weight:
|
||||
/// - Read: Bonded, Ledger New Controller, Ledger Old Controller
|
||||
/// - Write: Bonded, Ledger New Controller, Ledger Old Controller
|
||||
/// # </weight>
|
||||
#[weight = 25 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(3, 3)]
|
||||
#[weight = T::WeightInfo::set_controller()]
|
||||
fn set_controller(origin, controller: <T::Lookup as StaticLookup>::Source) {
|
||||
let stash = ensure_signed(origin)?;
|
||||
let old_controller = Self::bonded(&stash).ok_or(Error::<T>::NotStash)?;
|
||||
@@ -1876,10 +1768,10 @@ decl_module! {
|
||||
/// The dispatch origin must be Root.
|
||||
///
|
||||
/// # <weight>
|
||||
/// Base Weight: 1.717 µs
|
||||
/// Weight: O(1)
|
||||
/// Write: Validator Count
|
||||
/// # </weight>
|
||||
#[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)]
|
||||
#[weight = T::WeightInfo::set_validator_count()]
|
||||
fn set_validator_count(origin, #[compact] new: u32) {
|
||||
ensure_root(origin)?;
|
||||
ValidatorCount::put(new);
|
||||
@@ -1890,10 +1782,9 @@ decl_module! {
|
||||
/// The dispatch origin must be Root.
|
||||
///
|
||||
/// # <weight>
|
||||
/// Base Weight: 1.717 µs
|
||||
/// Read/Write: Validator Count
|
||||
/// Same as [`set_validator_count`].
|
||||
/// # </weight>
|
||||
#[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)]
|
||||
#[weight = T::WeightInfo::set_validator_count()]
|
||||
fn increase_validator_count(origin, #[compact] additional: u32) {
|
||||
ensure_root(origin)?;
|
||||
ValidatorCount::mutate(|n| *n += additional);
|
||||
@@ -1904,10 +1795,9 @@ decl_module! {
|
||||
/// The dispatch origin must be Root.
|
||||
///
|
||||
/// # <weight>
|
||||
/// Base Weight: 1.717 µs
|
||||
/// Read/Write: Validator Count
|
||||
/// Same as [`set_validator_count`].
|
||||
/// # </weight>
|
||||
#[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)]
|
||||
#[weight = T::WeightInfo::set_validator_count()]
|
||||
fn scale_validator_count(origin, factor: Percent) {
|
||||
ensure_root(origin)?;
|
||||
ValidatorCount::mutate(|n| *n += factor * *n);
|
||||
@@ -1919,10 +1809,10 @@ decl_module! {
|
||||
///
|
||||
/// # <weight>
|
||||
/// - No arguments.
|
||||
/// - Base Weight: 1.857 µs
|
||||
/// - Weight: O(1)
|
||||
/// - Write: ForceEra
|
||||
/// # </weight>
|
||||
#[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)]
|
||||
#[weight = T::WeightInfo::force_no_eras()]
|
||||
fn force_no_eras(origin) {
|
||||
ensure_root(origin)?;
|
||||
ForceEra::put(Forcing::ForceNone);
|
||||
@@ -1935,10 +1825,10 @@ decl_module! {
|
||||
///
|
||||
/// # <weight>
|
||||
/// - No arguments.
|
||||
/// - Base Weight: 1.959 µs
|
||||
/// - Weight: O(1)
|
||||
/// - Write ForceEra
|
||||
/// # </weight>
|
||||
#[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)]
|
||||
#[weight = T::WeightInfo::force_new_era()]
|
||||
fn force_new_era(origin) {
|
||||
ensure_root(origin)?;
|
||||
ForceEra::put(Forcing::ForceNew);
|
||||
@@ -1950,16 +1840,12 @@ decl_module! {
|
||||
///
|
||||
/// # <weight>
|
||||
/// - O(V)
|
||||
/// - Base Weight: 2.208 + .006 * V µs
|
||||
/// - Write: Invulnerables
|
||||
/// # </weight>
|
||||
#[weight = T::DbWeight::get().writes(1)
|
||||
.saturating_add(2 * WEIGHT_PER_MICROS)
|
||||
.saturating_add((6 * WEIGHT_PER_NANOS).saturating_mul(validators.len() as Weight))
|
||||
]
|
||||
fn set_invulnerables(origin, validators: Vec<T::AccountId>) {
|
||||
#[weight = T::WeightInfo::set_invulnerables(invulnerables.len() as u32)]
|
||||
fn set_invulnerables(origin, invulnerables: Vec<T::AccountId>) {
|
||||
ensure_root(origin)?;
|
||||
<Invulnerables<T>>::put(validators);
|
||||
<Invulnerables<T>>::put(invulnerables);
|
||||
}
|
||||
|
||||
/// Force a current staker to become completely unstaked, immediately.
|
||||
@@ -1968,20 +1854,11 @@ decl_module! {
|
||||
///
|
||||
/// # <weight>
|
||||
/// O(S) where S is the number of slashing spans to be removed
|
||||
/// Base Weight: 53.07 + 2.365 * S µs
|
||||
/// Reads: Bonded, Slashing Spans, Account, Locks
|
||||
/// Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, Account, Locks
|
||||
/// Writes Each: SpanSlash * S
|
||||
/// # </weight>
|
||||
#[weight = T::DbWeight::get().reads_writes(4, 7)
|
||||
.saturating_add(53 * WEIGHT_PER_MICROS)
|
||||
.saturating_add(
|
||||
WEIGHT_PER_MICROS.saturating_mul(2).saturating_mul(Weight::from(*num_slashing_spans))
|
||||
)
|
||||
.saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans)))
|
||||
// if slashing spans is non-zero, add 1 more write
|
||||
.saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans > 0)))
|
||||
]
|
||||
#[weight = T::WeightInfo::force_unstake(*num_slashing_spans)]
|
||||
fn force_unstake(origin, stash: T::AccountId, num_slashing_spans: u32) {
|
||||
ensure_root(origin)?;
|
||||
|
||||
@@ -1997,10 +1874,10 @@ decl_module! {
|
||||
/// The dispatch origin must be Root.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Base Weight: 2.05 µs
|
||||
/// - Weight: O(1)
|
||||
/// - Write: ForceEra
|
||||
/// # </weight>
|
||||
#[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)]
|
||||
#[weight = T::WeightInfo::force_new_era_always()]
|
||||
fn force_new_era_always(origin) {
|
||||
ensure_root(origin)?;
|
||||
ForceEra::put(Forcing::ForceAlways);
|
||||
@@ -2016,14 +1893,10 @@ decl_module! {
|
||||
/// Complexity: O(U + S)
|
||||
/// with U unapplied slashes weighted with U=1000
|
||||
/// and S is the number of slash indices to be canceled.
|
||||
/// - Base: 5870 + 34.61 * S µs
|
||||
/// - Read: Unapplied Slashes
|
||||
/// - Write: Unapplied Slashes
|
||||
/// # </weight>
|
||||
#[weight = T::DbWeight::get().reads_writes(1, 1)
|
||||
.saturating_add(5_870 * WEIGHT_PER_MICROS)
|
||||
.saturating_add((35 * WEIGHT_PER_MICROS).saturating_mul(slash_indices.len() as Weight))
|
||||
]
|
||||
#[weight = T::WeightInfo::cancel_deferred_slash(slash_indices.len() as u32)]
|
||||
fn cancel_deferred_slash(origin, era: EraIndex, slash_indices: Vec<u32>) {
|
||||
T::SlashCancelOrigin::ensure_origin(origin)?;
|
||||
|
||||
@@ -2058,22 +1931,19 @@ decl_module! {
|
||||
/// - Contains a limited number of reads and writes.
|
||||
/// -----------
|
||||
/// N is the Number of payouts for the validator (including the validator)
|
||||
/// Base Weight:
|
||||
/// - Reward Destination Staked: 110 + 54.2 * N µs (Median Slopes)
|
||||
/// - Reward Destination Controller (Creating): 120 + 41.95 * N µs (Median Slopes)
|
||||
/// Weight:
|
||||
/// - Reward Destination Staked: O(N)
|
||||
/// - Reward Destination Controller (Creating): O(N)
|
||||
/// DB Weight:
|
||||
/// - Read: EraElectionStatus, CurrentEra, HistoryDepth, ErasValidatorReward,
|
||||
/// ErasStakersClipped, ErasRewardPoints, ErasValidatorPrefs (8 items)
|
||||
/// - Read Each: Bonded, Ledger, Payee, Locks, System Account (5 items)
|
||||
/// - Write Each: System Account, Locks, Ledger (3 items)
|
||||
///
|
||||
/// NOTE: weights are assuming that payouts are made to alive stash account (Staked).
|
||||
/// Paying even a dead controller is cheaper weight-wise. We don't do any refunds here.
|
||||
/// # </weight>
|
||||
#[weight =
|
||||
120 * WEIGHT_PER_MICROS
|
||||
+ 54 * WEIGHT_PER_MICROS * Weight::from(T::MaxNominatorRewardedPerValidator::get())
|
||||
+ T::DbWeight::get().reads(7)
|
||||
+ T::DbWeight::get().reads(5) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1)
|
||||
+ T::DbWeight::get().writes(3) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1)
|
||||
]
|
||||
#[weight = T::WeightInfo::payout_stakers_alive_staked(T::MaxNominatorRewardedPerValidator::get())]
|
||||
fn payout_stakers(origin, validator_stash: T::AccountId, era: EraIndex) -> DispatchResult {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
ensure_signed(origin)?;
|
||||
@@ -2090,16 +1960,11 @@ decl_module! {
|
||||
/// - Bounded by `MAX_UNLOCKING_CHUNKS`.
|
||||
/// - Storage changes: Can't increase storage, only decrease it.
|
||||
/// ---------------
|
||||
/// - Base Weight: 34.51 µs * .048 L µs
|
||||
/// - DB Weight:
|
||||
/// - Reads: EraElectionStatus, Ledger, Locks, [Origin Account]
|
||||
/// - Writes: [Origin Account], Locks, Ledger
|
||||
/// # </weight>
|
||||
#[weight =
|
||||
35 * WEIGHT_PER_MICROS
|
||||
+ 50 * WEIGHT_PER_NANOS * (MAX_UNLOCKING_CHUNKS as Weight)
|
||||
+ T::DbWeight::get().reads_writes(3, 2)
|
||||
]
|
||||
#[weight = T::WeightInfo::rebond(MAX_UNLOCKING_CHUNKS as u32)]
|
||||
fn rebond(origin, #[compact] value: BalanceOf<T>) -> DispatchResultWithPostInfo {
|
||||
ensure!(Self::era_election_status().is_closed(), Error::<T>::CallNotAllowed);
|
||||
let controller = ensure_signed(origin)?;
|
||||
@@ -2129,19 +1994,14 @@ decl_module! {
|
||||
///
|
||||
/// # <weight>
|
||||
/// - E: Number of history depths removed, i.e. 10 -> 7 = 3
|
||||
/// - Base Weight: 29.13 * E µs
|
||||
/// - Weight: O(E)
|
||||
/// - DB Weight:
|
||||
/// - Reads: Current Era, History Depth
|
||||
/// - Writes: History Depth
|
||||
/// - Clear Prefix Each: Era Stakers, EraStakersClipped, ErasValidatorPrefs
|
||||
/// - Writes Each: ErasValidatorReward, ErasRewardPoints, ErasTotalStake, ErasStartSessionIndex
|
||||
/// # </weight>
|
||||
#[weight = {
|
||||
let items = Weight::from(*_era_items_deleted);
|
||||
T::DbWeight::get().reads_writes(2, 1)
|
||||
.saturating_add(T::DbWeight::get().reads_writes(items, items))
|
||||
|
||||
}]
|
||||
#[weight = T::WeightInfo::set_history_depth(*_era_items_deleted)]
|
||||
fn set_history_depth(origin,
|
||||
#[compact] new_history_depth: EraIndex,
|
||||
#[compact] _era_items_deleted: u32,
|
||||
@@ -2169,21 +2029,12 @@ decl_module! {
|
||||
///
|
||||
/// # <weight>
|
||||
/// Complexity: O(S) where S is the number of slashing spans on the account.
|
||||
/// Base Weight: 75.94 + 2.396 * S µs
|
||||
/// DB Weight:
|
||||
/// - Reads: Stash Account, Bonded, Slashing Spans, Locks
|
||||
/// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, Stash Account, Locks
|
||||
/// - Writes Each: SpanSlash * S
|
||||
/// # </weight>
|
||||
#[weight = T::DbWeight::get().reads_writes(4, 7)
|
||||
.saturating_add(76 * WEIGHT_PER_MICROS)
|
||||
.saturating_add(
|
||||
WEIGHT_PER_MICROS.saturating_mul(2).saturating_mul(Weight::from(*num_slashing_spans))
|
||||
)
|
||||
.saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans)))
|
||||
// if slashing spans is non-zero, add 1 more write
|
||||
.saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans).min(1)))
|
||||
]
|
||||
#[weight = T::WeightInfo::reap_stash(*num_slashing_spans)]
|
||||
fn reap_stash(_origin, stash: T::AccountId, num_slashing_spans: u32) {
|
||||
ensure!(T::Currency::total_balance(&stash).is_zero(), Error::<T>::FundedTarget);
|
||||
Self::kill_stash(&stash, num_slashing_spans)?;
|
||||
@@ -2235,9 +2086,16 @@ decl_module! {
|
||||
/// minimized (to ensure less variance)
|
||||
///
|
||||
/// # <weight>
|
||||
/// See `crate::weight` module.
|
||||
/// The transaction is assumed to be the longest path, a better solution.
|
||||
/// - Initial solution is almost the same.
|
||||
/// - Worse solution is retraced in pre-dispatch-checks which sets its own weight.
|
||||
/// # </weight>
|
||||
#[weight = weight::weight_for_submit_solution::<T>(winners, compact, size)]
|
||||
#[weight = T::WeightInfo::submit_solution_better(
|
||||
size.validators.into(),
|
||||
size.nominators.into(),
|
||||
compact.len() as u32,
|
||||
winners.len() as u32,
|
||||
)]
|
||||
pub fn submit_election_solution(
|
||||
origin,
|
||||
winners: Vec<ValidatorIndex>,
|
||||
@@ -2266,7 +2124,12 @@ decl_module! {
|
||||
/// # <weight>
|
||||
/// See `crate::weight` module.
|
||||
/// # </weight>
|
||||
#[weight = weight::weight_for_submit_solution::<T>(winners, compact, size)]
|
||||
#[weight = T::WeightInfo::submit_solution_better(
|
||||
size.validators.into(),
|
||||
size.nominators.into(),
|
||||
compact.len() as u32,
|
||||
winners.len() as u32,
|
||||
)]
|
||||
pub fn submit_election_solution_unsigned(
|
||||
origin,
|
||||
winners: Vec<ValidatorIndex>,
|
||||
@@ -2580,13 +2443,16 @@ impl<T: Trait> Module<T> {
|
||||
election_size: ElectionSize,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
// Do the basic checks. era, claimed score and window open.
|
||||
Self::pre_dispatch_checks(claimed_score, era)?;
|
||||
// the weight that we will refund in case of a correct submission. We compute this now
|
||||
// because the data needed for it will be consumed further down.
|
||||
let adjusted_weight = weight::weight_for_correct_submit_solution::<T>(
|
||||
&winners,
|
||||
&compact_assignments,
|
||||
&election_size,
|
||||
let _ = Self::pre_dispatch_checks(claimed_score, era)?;
|
||||
|
||||
// before we read any further state, we check that the unique targets in compact is same as
|
||||
// compact. is a all in-memory check and easy to do. Moreover, it ensures that the solution
|
||||
// is not full of bogus edges that can cause lots of reads to SlashingSpans. Thus, we can
|
||||
// assume that the storage access of this function is always O(|winners|), not
|
||||
// O(|compact.edge_count()|).
|
||||
ensure!(
|
||||
compact_assignments.unique_targets().len() == winners.len(),
|
||||
Error::<T>::OffchainElectionBogusWinnerCount,
|
||||
);
|
||||
|
||||
// Check that the number of presented winners is sane. Most often we have more candidates
|
||||
@@ -2744,7 +2610,7 @@ impl<T: Trait> Module<T> {
|
||||
// emit event.
|
||||
Self::deposit_event(RawEvent::SolutionStored(compute));
|
||||
|
||||
Ok(Some(adjusted_weight).into())
|
||||
Ok(None.into())
|
||||
}
|
||||
|
||||
/// Start a session potentially starting an era.
|
||||
@@ -2862,7 +2728,6 @@ impl<T: Trait> Module<T> {
|
||||
maybe_new_validators
|
||||
}
|
||||
|
||||
|
||||
/// Remove all the storage items associated with the election.
|
||||
fn close_election_window() {
|
||||
// Close window.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
use crate::*;
|
||||
use crate::Module as Staking;
|
||||
use frame_benchmarking::{account};
|
||||
use frame_benchmarking::account;
|
||||
use frame_system::RawOrigin;
|
||||
use sp_io::hashing::blake2_256;
|
||||
use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng};
|
||||
@@ -29,7 +29,11 @@ use sp_npos_elections::*;
|
||||
const SEED: u32 = 0;
|
||||
|
||||
/// Grab a funded user.
|
||||
pub fn create_funded_user<T: Trait>(string: &'static str, n: u32, balance_factor: u32) -> T::AccountId {
|
||||
pub fn create_funded_user<T: Trait>(
|
||||
string: &'static str,
|
||||
n: u32,
|
||||
balance_factor: u32,
|
||||
) -> T::AccountId {
|
||||
let user = account(string, n, SEED);
|
||||
let balance = T::Currency::minimum_balance() * balance_factor.into();
|
||||
T::Currency::make_free_balance_be(&user, balance);
|
||||
@@ -39,30 +43,36 @@ pub fn create_funded_user<T: Trait>(string: &'static str, n: u32, balance_factor
|
||||
}
|
||||
|
||||
/// Create a stash and controller pair.
|
||||
pub fn create_stash_controller<T: Trait>(n: u32, balance_factor: u32)
|
||||
pub fn create_stash_controller<T: Trait>(
|
||||
n: u32,
|
||||
balance_factor: u32,
|
||||
destination: RewardDestination<T::AccountId>,
|
||||
)
|
||||
-> Result<(T::AccountId, T::AccountId), &'static str>
|
||||
{
|
||||
let stash = create_funded_user::<T>("stash", n, balance_factor);
|
||||
let controller = create_funded_user::<T>("controller", n, balance_factor);
|
||||
let controller_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(controller.clone());
|
||||
let reward_destination = RewardDestination::Staked;
|
||||
let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into();
|
||||
Staking::<T>::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?;
|
||||
Staking::<T>::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, destination)?;
|
||||
return Ok((stash, controller))
|
||||
}
|
||||
|
||||
/// Create a stash and controller pair, where the controller is dead, and payouts go to controller.
|
||||
/// This is used to test worst case payout scenarios.
|
||||
pub fn create_stash_and_dead_controller<T: Trait>(n: u32, balance_factor: u32)
|
||||
pub fn create_stash_and_dead_controller<T: Trait>(
|
||||
n: u32,
|
||||
balance_factor: u32,
|
||||
destination: RewardDestination<T::AccountId>,
|
||||
)
|
||||
-> Result<(T::AccountId, T::AccountId), &'static str>
|
||||
{
|
||||
let stash = create_funded_user::<T>("stash", n, balance_factor);
|
||||
// controller has no funds
|
||||
let controller = create_funded_user::<T>("controller", n, 0);
|
||||
let controller_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(controller.clone());
|
||||
let reward_destination = RewardDestination::Controller;
|
||||
let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into();
|
||||
Staking::<T>::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?;
|
||||
Staking::<T>::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, destination)?;
|
||||
return Ok((stash, controller))
|
||||
}
|
||||
|
||||
@@ -73,7 +83,7 @@ pub fn create_validators<T: Trait>(
|
||||
) -> Result<Vec<<T::Lookup as StaticLookup>::Source>, &'static str> {
|
||||
let mut validators: Vec<<T::Lookup as StaticLookup>::Source> = Vec::with_capacity(max as usize);
|
||||
for i in 0 .. max {
|
||||
let (stash, controller) = create_stash_controller::<T>(i, balance_factor)?;
|
||||
let (stash, controller) = create_stash_controller::<T>(i, balance_factor, RewardDestination::Staked)?;
|
||||
let validator_prefs = ValidatorPrefs {
|
||||
commission: Perbill::from_percent(50),
|
||||
};
|
||||
@@ -110,7 +120,7 @@ pub fn create_validators_with_nominators_for_era<T: Trait>(
|
||||
// Create validators
|
||||
for i in 0 .. validators {
|
||||
let balance_factor = if randomize_stake { rng.next_u32() % 255 + 10 } else { 100u32 };
|
||||
let (v_stash, v_controller) = create_stash_controller::<T>(i, balance_factor)?;
|
||||
let (v_stash, v_controller) = create_stash_controller::<T>(i, balance_factor, RewardDestination::Staked)?;
|
||||
let validator_prefs = ValidatorPrefs {
|
||||
commission: Perbill::from_percent(50),
|
||||
};
|
||||
@@ -128,6 +138,7 @@ pub fn create_validators_with_nominators_for_era<T: Trait>(
|
||||
let (_n_stash, n_controller) = create_stash_controller::<T>(
|
||||
u32::max_value() - j,
|
||||
balance_factor,
|
||||
RewardDestination::Staked,
|
||||
)?;
|
||||
|
||||
// Have them randomly validate
|
||||
|
||||
@@ -3615,7 +3615,7 @@ mod offchain_election {
|
||||
// A validator index which is out of bound
|
||||
ExtBuilder::default()
|
||||
.offchain_election_ext()
|
||||
.validator_count(4)
|
||||
.validator_count(2)
|
||||
.has_stakers(false)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
@@ -3627,7 +3627,7 @@ mod offchain_election {
|
||||
let (mut compact, winners, score) = prepare_submission_with(true, 2, |_| {});
|
||||
|
||||
// index 4 doesn't exist.
|
||||
compact.votes1.push((3, 4));
|
||||
compact.votes1.iter_mut().for_each(|(_, vidx)| if *vidx == 1 { *vidx = 4 });
|
||||
|
||||
// The error type sadly cannot be more specific now.
|
||||
assert_noop!(
|
||||
@@ -3689,11 +3689,17 @@ mod offchain_election {
|
||||
assert_eq!(Staking::snapshot_nominators().unwrap().len(), 5 + 4);
|
||||
assert_eq!(Staking::snapshot_validators().unwrap().len(), 4);
|
||||
let (compact, winners, score) = prepare_submission_with(true, 2, |a| {
|
||||
a.iter_mut()
|
||||
.find(|x| x.who == 5)
|
||||
// all 3 cannot be among the winners. Although, all of them are validator
|
||||
// candidates.
|
||||
.map(|x| x.distribution = vec![(21, 50), (41, 30), (31, 20)]);
|
||||
// swap all 11 and 41s in the distribution with non-winners. Note that it is
|
||||
// important that the count of winners and the count of unique targets remain
|
||||
// valid.
|
||||
a.iter_mut().for_each(| StakedAssignment { who, distribution } |
|
||||
distribution.iter_mut().for_each(|(t, _)| {
|
||||
if *t == 41 { *t = 31 } else { *t = 21 }
|
||||
// if it is self vote, correct that.
|
||||
if *who == 41 { *who = 31 }
|
||||
if *who == 11 { *who = 21 }
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
assert_noop!(
|
||||
@@ -3703,7 +3709,46 @@ mod offchain_election {
|
||||
compact,
|
||||
score,
|
||||
),
|
||||
Error::<Test>::OffchainElectionBogusEdge,
|
||||
Error::<Test>::OffchainElectionBogusNomination,
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offchain_election_unique_target_count_is_checked() {
|
||||
// Number of unique targets and and winners.len must match.
|
||||
ExtBuilder::default()
|
||||
.offchain_election_ext()
|
||||
.validator_count(2) // we select only 2.
|
||||
.has_stakers(false)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
build_offchain_election_test_ext();
|
||||
run_to_block(12);
|
||||
|
||||
assert_eq!(Staking::snapshot_nominators().unwrap().len(), 5 + 4);
|
||||
assert_eq!(Staking::snapshot_validators().unwrap().len(), 4);
|
||||
|
||||
let (compact, winners, score) = prepare_submission_with(true, 2, |a| {
|
||||
a.iter_mut()
|
||||
.find(|x| x.who == 5)
|
||||
// just add any new target.
|
||||
.map(|x| {
|
||||
// old value.
|
||||
assert_eq!(x.distribution, vec![(41, 100)]);
|
||||
// new value.
|
||||
x.distribution = vec![(21, 50), (41, 50)]
|
||||
});
|
||||
});
|
||||
|
||||
assert_noop!(
|
||||
submit_solution(
|
||||
Origin::signed(10),
|
||||
winners,
|
||||
compact,
|
||||
score,
|
||||
),
|
||||
Error::<Test>::OffchainElectionBogusWinnerCount,
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user