mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 16:51:03 +00:00
Audit fixes for election/staking decoupling part 2 (#8167)
* 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 * Audit fixes for election-provider: part 2 signed phase. * Fix weight * Some grumbles. * Try and weigh to get_npos_voters * Fix build * Fix line width * 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 tests. * Fix build * Reorg some stuff * More reorg. * Reorg done. * Fix build * Another rename * Fix build * Update frame/election-provider-multi-phase/src/mock.rs Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com> * nit * better doc * Line width * Fix build * Self-review * Self-review * Fix wan * 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_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * fix build and review comments. * Update frame/election-provider-multi-phase/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * add comment 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> Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>
This commit is contained in:
Generated
+357
-353
File diff suppressed because it is too large
Load Diff
@@ -76,6 +76,7 @@ members = [
|
||||
"frame/try-runtime",
|
||||
"frame/elections",
|
||||
"frame/election-provider-multi-phase",
|
||||
"frame/election-provider-support",
|
||||
"frame/example",
|
||||
"frame/example-offchain-worker",
|
||||
"frame/example-parallel",
|
||||
@@ -145,7 +146,6 @@ members = [
|
||||
"primitives/database",
|
||||
"primitives/debug-derive",
|
||||
"primitives/externalities",
|
||||
"primitives/election-providers",
|
||||
"primitives/finality-grandpa",
|
||||
"primitives/inherents",
|
||||
"primitives/io",
|
||||
|
||||
@@ -37,7 +37,7 @@ pallet-offences = { version = "3.0.0", path = "../offences" }
|
||||
pallet-staking = { version = "3.0.0", path = "../staking" }
|
||||
pallet-staking-reward-curve = { version = "3.0.0", path = "../staking/reward-curve" }
|
||||
sp-core = { version = "3.0.0", path = "../../primitives/core" }
|
||||
sp-election-providers = { version = "3.0.0", path = "../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", path = "../election-provider-support" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -37,7 +37,7 @@ use sp_consensus_babe::{AuthorityId, AuthorityPair, Slot};
|
||||
use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof};
|
||||
use sp_staking::SessionIndex;
|
||||
use pallet_staking::EraIndex;
|
||||
use sp_election_providers::onchain;
|
||||
use frame_election_provider_support::onchain;
|
||||
use pallet_session::historical as pallet_session_historical;
|
||||
|
||||
type DummyValidatorId = u64;
|
||||
@@ -187,6 +187,7 @@ parameter_types! {
|
||||
impl onchain::Config for Test {
|
||||
type AccountId = <Self as frame_system::Config>::AccountId;
|
||||
type BlockNumber = <Self as frame_system::Config>::BlockNumber;
|
||||
type BlockWeights = ();
|
||||
type Accuracy = Perbill;
|
||||
type DataProvider = Staking;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ sp-std = { version = "3.0.0", default-features = false, path = "../../primitives
|
||||
sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" }
|
||||
sp-npos-elections = { version = "3.0.0", default-features = false, path = "../../primitives/npos-elections" }
|
||||
sp-arithmetic = { version = "3.0.0", default-features = false, path = "../../primitives/arithmetic" }
|
||||
sp-election-providers = { version = "3.0.0", default-features = false, path = "../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", default-features = false, path = "../election-provider-support" }
|
||||
|
||||
# Optional imports for benchmarking
|
||||
frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true }
|
||||
@@ -41,9 +41,9 @@ substrate-test-utils = { version = "3.0.0", path = "../../test-utils" }
|
||||
sp-io = { version = "3.0.0", path = "../../primitives/io" }
|
||||
sp-core = { version = "3.0.0", path = "../../primitives/core" }
|
||||
sp-tracing = { version = "3.0.0", path = "../../primitives/tracing" }
|
||||
sp-election-providers = { version = "3.0.0", features = ["runtime-benchmarks"], path = "../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", features = ["runtime-benchmarks"], path = "../election-provider-support" }
|
||||
pallet-balances = { version = "3.0.0", path = "../balances" }
|
||||
frame-benchmarking = { path = "../benchmarking" , version = "3.1.0"}
|
||||
frame-benchmarking = { version = "3.1.0", path = "../benchmarking" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -60,7 +60,7 @@ std = [
|
||||
"sp-runtime/std",
|
||||
"sp-npos-elections/std",
|
||||
"sp-arithmetic/std",
|
||||
"sp-election-providers/std",
|
||||
"frame-election-provider-support/std",
|
||||
"log/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2020 Parity Technologies (UK) Ltd.
|
||||
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -19,17 +19,16 @@
|
||||
|
||||
use super::*;
|
||||
use crate::Module as MultiPhase;
|
||||
|
||||
pub use frame_benchmarking::{account, benchmarks, whitelist_account, whitelisted_caller};
|
||||
use frame_benchmarking::impl_benchmark_test_suite;
|
||||
use frame_support::{assert_ok, traits::OnInitialize};
|
||||
use frame_system::RawOrigin;
|
||||
use rand::{prelude::SliceRandom, rngs::SmallRng, SeedableRng};
|
||||
use sp_election_providers::Assignment;
|
||||
use frame_election_provider_support::Assignment;
|
||||
use sp_arithmetic::traits::One;
|
||||
use sp_runtime::InnerOf;
|
||||
use sp_std::convert::TryInto;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
const SEED: u32 = 999;
|
||||
|
||||
/// Creates a **valid** solution with exactly the given size.
|
||||
///
|
||||
@@ -55,9 +54,9 @@ fn solution_with_size<T: Config>(
|
||||
|
||||
// first generates random targets.
|
||||
let targets: Vec<T::AccountId> =
|
||||
(0..size.targets).map(|i| account("Targets", i, SEED)).collect();
|
||||
(0..size.targets).map(|i| frame_benchmarking::account("Targets", i, SEED)).collect();
|
||||
|
||||
let mut rng = SmallRng::seed_from_u64(999u64);
|
||||
let mut rng = SmallRng::seed_from_u64(SEED as u64);
|
||||
|
||||
// decide who are the winners.
|
||||
let winners = targets
|
||||
@@ -75,7 +74,7 @@ fn solution_with_size<T: Config>(
|
||||
.choose_multiple(&mut rng, <CompactOf<T>>::LIMIT)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
let voter = account::<T::AccountId>("Voter", i, SEED);
|
||||
let voter = frame_benchmarking::account::<T::AccountId>("Voter", i, SEED);
|
||||
(voter, stake, winner_votes)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -89,7 +88,7 @@ fn solution_with_size<T: Config>(
|
||||
.choose_multiple(&mut rng, <CompactOf<T>>::LIMIT)
|
||||
.cloned()
|
||||
.collect::<Vec<T::AccountId>>();
|
||||
let voter = account::<T::AccountId>("Voter", i, SEED);
|
||||
let voter = frame_benchmarking::account::<T::AccountId>("Voter", i, SEED);
|
||||
(voter, stake, votes)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -109,8 +108,9 @@ fn solution_with_size<T: Config>(
|
||||
<DesiredTargets<T>>::put(desired_targets);
|
||||
<Snapshot<T>>::put(RoundSnapshot { voters: all_voters.clone(), targets: targets.clone() });
|
||||
|
||||
// write the snapshot to staking or whoever is the data provider.
|
||||
T::DataProvider::put_snapshot(all_voters.clone(), targets.clone());
|
||||
// write the snapshot to staking or whoever is the data provider, in case it is needed further
|
||||
// down the road.
|
||||
T::DataProvider::put_snapshot(all_voters.clone(), targets.clone(), Some(stake));
|
||||
|
||||
let cache = helpers::generate_voter_cache::<T>(&all_voters);
|
||||
let stake_of = helpers::stake_of_fn::<T>(&all_voters, &cache);
|
||||
@@ -138,10 +138,12 @@ fn solution_with_size<T: Config>(
|
||||
<CompactOf<T>>::from_assignment(assignments, &voter_index, &target_index).unwrap();
|
||||
let score = compact.clone().score(&winners, stake_of, voter_at, target_at).unwrap();
|
||||
let round = <MultiPhase<T>>::round();
|
||||
|
||||
assert!(score[0] > 0, "score is zero, this probably means that the stakes are not set.");
|
||||
RawSolution { compact, score, round }
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
frame_benchmarking::benchmarks! {
|
||||
on_initialize_nothing {
|
||||
assert!(<MultiPhase<T>>::current_phase().is_off());
|
||||
}: {
|
||||
@@ -157,7 +159,7 @@ benchmarks! {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_none());
|
||||
assert!(<MultiPhase<T>>::current_phase().is_off());
|
||||
}: {
|
||||
<MultiPhase<T>>::on_initialize_open_signed();
|
||||
<MultiPhase<T>>::on_initialize_open_signed().unwrap();
|
||||
} verify {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||
assert!(<MultiPhase<T>>::current_phase().is_signed());
|
||||
@@ -167,7 +169,7 @@ benchmarks! {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_none());
|
||||
assert!(<MultiPhase<T>>::current_phase().is_off());
|
||||
}: {
|
||||
<MultiPhase<T>>::on_initialize_open_unsigned(true, true, 1u32.into());
|
||||
<MultiPhase<T>>::on_initialize_open_unsigned(true, true, 1u32.into()).unwrap();
|
||||
} verify {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||
assert!(<MultiPhase<T>>::current_phase().is_unsigned());
|
||||
@@ -175,21 +177,51 @@ benchmarks! {
|
||||
|
||||
on_initialize_open_unsigned_without_snapshot {
|
||||
// need to assume signed phase was open before
|
||||
<MultiPhase<T>>::on_initialize_open_signed();
|
||||
<MultiPhase<T>>::on_initialize_open_signed().unwrap();
|
||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||
assert!(<MultiPhase<T>>::current_phase().is_signed());
|
||||
}: {
|
||||
<MultiPhase<T>>::on_initialize_open_unsigned(false, true, 1u32.into());
|
||||
<MultiPhase<T>>::on_initialize_open_unsigned(false, true, 1u32.into()).unwrap();
|
||||
} verify {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||
assert!(<MultiPhase<T>>::current_phase().is_unsigned());
|
||||
}
|
||||
|
||||
// a call to `<Pallet as ElectionProvider>::elect` where we only return the queued solution.
|
||||
elect_queued {
|
||||
// assume largest values for the election status. These will merely affect the decoding.
|
||||
let v = T::BenchmarkingConfig::VOTERS[1];
|
||||
let t = T::BenchmarkingConfig::TARGETS[1];
|
||||
let a = T::BenchmarkingConfig::ACTIVE_VOTERS[1];
|
||||
let d = T::BenchmarkingConfig::DESIRED_TARGETS[1];
|
||||
|
||||
let witness = SolutionOrSnapshotSize { voters: v, targets: t };
|
||||
let raw_solution = solution_with_size::<T>(witness, a, d);
|
||||
let ready_solution =
|
||||
<MultiPhase<T>>::feasibility_check(raw_solution, ElectionCompute::Signed).unwrap();
|
||||
|
||||
// these are set by the `solution_with_size` function.
|
||||
assert!(<DesiredTargets<T>>::get().is_some());
|
||||
assert!(<Snapshot<T>>::get().is_some());
|
||||
assert!(<SnapshotMetadata<T>>::get().is_some());
|
||||
<CurrentPhase<T>>::put(Phase::Signed);
|
||||
// assume a queued solution is stored, regardless of where it comes from.
|
||||
<QueuedSolution<T>>::put(ready_solution);
|
||||
}: {
|
||||
let _ = <MultiPhase<T> as ElectionProvider<T::AccountId, T::BlockNumber>>::elect();
|
||||
} verify {
|
||||
assert!(<MultiPhase<T>>::queued_solution().is_none());
|
||||
assert!(<DesiredTargets<T>>::get().is_none());
|
||||
assert!(<Snapshot<T>>::get().is_none());
|
||||
assert!(<SnapshotMetadata<T>>::get().is_none());
|
||||
assert_eq!(<CurrentPhase<T>>::get(), <Phase<T::BlockNumber>>::Off);
|
||||
}
|
||||
|
||||
#[extra]
|
||||
create_snapshot {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_none());
|
||||
}: {
|
||||
<MultiPhase::<T>>::create_snapshot()
|
||||
<MultiPhase::<T>>::create_snapshot().unwrap()
|
||||
} verify {
|
||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||
}
|
||||
@@ -248,35 +280,8 @@ benchmarks! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::mock::*;
|
||||
|
||||
#[test]
|
||||
fn test_benchmarks() {
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
assert_ok!(test_benchmark_feasibility_check::<Runtime>());
|
||||
});
|
||||
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
assert_ok!(test_benchmark_submit_unsigned::<Runtime>());
|
||||
});
|
||||
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
assert_ok!(test_benchmark_on_initialize_open_unsigned_with_snapshot::<Runtime>());
|
||||
});
|
||||
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
assert_ok!(test_benchmark_on_initialize_open_unsigned_without_snapshot::<Runtime>());
|
||||
});
|
||||
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
assert_ok!(test_benchmark_on_initialize_nothing::<Runtime>());
|
||||
});
|
||||
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
assert_ok!(test_benchmark_create_snapshot::<Runtime>());
|
||||
});
|
||||
}
|
||||
}
|
||||
impl_benchmark_test_suite!(
|
||||
MultiPhase,
|
||||
crate::mock::ExtBuilder::default().build(),
|
||||
crate::mock::Runtime,
|
||||
);
|
||||
|
||||
@@ -25,7 +25,7 @@ macro_rules! log {
|
||||
($level:tt, $pattern:expr $(, $values:expr)* $(,)?) => {
|
||||
log::$level!(
|
||||
target: $crate::LOG_TARGET,
|
||||
concat!("🗳 ", $pattern) $(, $values)*
|
||||
concat!("[#{:?}] 🗳 ", $pattern), <frame_system::Module<T>>::block_number() $(, $values)*
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
//! ## Phases
|
||||
//!
|
||||
//! The timeline of pallet is as follows. At each block,
|
||||
//! [`sp_election_providers::ElectionDataProvider::next_election_prediction`] is used to estimate
|
||||
//! the time remaining to the next call to [`sp_election_providers::ElectionProvider::elect`]. Based
|
||||
//! on this, a phase is chosen. The timeline is as follows.
|
||||
//! [`frame_election_provider_support::ElectionDataProvider::next_election_prediction`] is used to
|
||||
//! estimate the time remaining to the next call to
|
||||
//! [`frame_election_provider_support::ElectionProvider::elect`]. Based on this, a phase is chosen.
|
||||
//! The timeline is as follows.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! elect()
|
||||
@@ -149,7 +150,8 @@
|
||||
//! are helpful for logging and are thus nested as:
|
||||
//! - [`ElectionError::Miner`]: wraps a [`unsigned::MinerError`].
|
||||
//! - [`ElectionError::Feasibility`]: wraps a [`FeasibilityError`].
|
||||
//! - [`ElectionError::OnChainFallback`]: wraps a [`sp_election_providers::onchain::Error`].
|
||||
//! - [`ElectionError::OnChainFallback`]: wraps a
|
||||
//! [`frame_election_provider_support::onchain::Error`].
|
||||
//!
|
||||
//! Note that there could be an overlap between these sub-errors. For example, A
|
||||
//! `SnapshotUnavailable` can happen in both miner and feasibility check phase.
|
||||
@@ -184,10 +186,10 @@
|
||||
//!
|
||||
//! **Recursive Fallback**: Currently, the fallback is a separate enum. A different and fancier way
|
||||
//! of doing this would be to have the fallback be another
|
||||
//! [`sp_election_providers::ElectionProvider`]. In this case, this pallet can even have the
|
||||
//! on-chain election provider as fallback, or special _noop_ fallback that simply returns an error,
|
||||
//! thus replicating [`FallbackStrategy::Nothing`]. In this case, we won't need the additional
|
||||
//! config OnChainAccuracy either.
|
||||
//! [`frame_election_provider_support::ElectionProvider`]. In this case, this pallet can even have
|
||||
//! the on-chain election provider as fallback, or special _noop_ fallback that simply returns an
|
||||
//! error, thus replicating [`FallbackStrategy::Nothing`]. In this case, we won't need the
|
||||
//! additional config OnChainAccuracy either.
|
||||
//!
|
||||
//! **Score based on (byte) size**: We should always prioritize small solutions over bigger ones, if
|
||||
//! there is a tie. Even more harsh should be to enforce the bound of the `reduce` algorithm.
|
||||
@@ -200,6 +202,15 @@
|
||||
//! dependency from staking and the compact solution type. It should be generated at runtime, there
|
||||
//! it should be encoded how many votes each nominators have. Essentially translate
|
||||
//! <https://github.com/paritytech/substrate/pull/7929> to this pallet.
|
||||
//!
|
||||
//! **More accurate weight for error cases**: Both `ElectionDataProvider` and `ElectionProvider`
|
||||
//! assume no weight is consumed in their functions, when operations fail with `Err`. This can
|
||||
//! clearly be improved, but not a priority as we generally expect snapshot creation to fail only
|
||||
//! due to extreme circumstances.
|
||||
//!
|
||||
//! **Take into account the encode/decode weight in benchmarks.** Currently, we only take into
|
||||
//! account the weight of encode/decode in the `submit_unsigned` given its priority. Nonetheless,
|
||||
//! all operations on the solution and the snapshot are worthy of taking this into account.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
@@ -211,7 +222,7 @@ use frame_support::{
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::{ensure_none, offchain::SendTransactionTypes};
|
||||
use sp_election_providers::{ElectionDataProvider, ElectionProvider, onchain};
|
||||
use frame_election_provider_support::{ElectionDataProvider, ElectionProvider, onchain};
|
||||
use sp_npos_elections::{
|
||||
assignment_ratio_to_staked_normalized, is_score_better, CompactSolution, ElectionScore,
|
||||
EvaluateSupport, PerThing128, Supports, VoteWeight,
|
||||
@@ -222,6 +233,7 @@ use sp_runtime::{
|
||||
TransactionValidityError, ValidTransaction,
|
||||
},
|
||||
DispatchError, PerThing, Perbill, RuntimeDebug, SaturatedConversion,
|
||||
traits::Bounded,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
use sp_arithmetic::{
|
||||
@@ -261,6 +273,7 @@ struct OnChainConfig<T: Config>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> onchain::Config for OnChainConfig<T> {
|
||||
type AccountId = T::AccountId;
|
||||
type BlockNumber = T::BlockNumber;
|
||||
type BlockWeights = T::BlockWeights;
|
||||
type Accuracy = T::OnChainAccuracy;
|
||||
type DataProvider = T::DataProvider;
|
||||
}
|
||||
@@ -436,6 +449,8 @@ pub enum ElectionError {
|
||||
Miner(unsigned::MinerError),
|
||||
/// An error in the on-chain fallback.
|
||||
OnChainFallback(onchain::Error),
|
||||
/// An error happened in the data provider.
|
||||
DataProvider(&'static str),
|
||||
/// No fallback is configured. This is a special case.
|
||||
NoFallbackConfigured,
|
||||
}
|
||||
@@ -563,17 +578,28 @@ pub mod pallet {
|
||||
|
||||
match current_phase {
|
||||
Phase::Off if remaining <= signed_deadline && remaining > unsigned_deadline => {
|
||||
Self::on_initialize_open_signed();
|
||||
log!(info, "Starting signed phase at #{:?} , round {}.", now, Self::round());
|
||||
T::WeightInfo::on_initialize_open_signed()
|
||||
// NOTE: if signed-phase length is zero, second part of the if-condition fails.
|
||||
match Self::on_initialize_open_signed() {
|
||||
Ok(snap_weight) => {
|
||||
log!(info, "Starting signed phase round {}.", Self::round());
|
||||
T::WeightInfo::on_initialize_open_signed().saturating_add(snap_weight)
|
||||
}
|
||||
Err(why) => {
|
||||
// not much we can do about this at this point.
|
||||
log!(warn, "failed to open signed phase due to {:?}", why);
|
||||
T::WeightInfo::on_initialize_nothing()
|
||||
// NOTE: ^^ The trait specifies that this is a noop in terms of weight
|
||||
// in case of error.
|
||||
}
|
||||
}
|
||||
}
|
||||
Phase::Signed | Phase::Off
|
||||
if remaining <= unsigned_deadline && remaining > 0u32.into() =>
|
||||
if remaining <= unsigned_deadline && remaining > Zero::zero() =>
|
||||
{
|
||||
let (need_snapshot, enabled, additional) = if current_phase == Phase::Signed {
|
||||
// determine if followed by signed or not.
|
||||
let (need_snapshot, enabled, signed_weight) = if current_phase == Phase::Signed {
|
||||
// followed by a signed phase: close the signed phase, no need for snapshot.
|
||||
// TWO_PHASE_NOTE: later on once we have signed phase, this should return
|
||||
// something else.
|
||||
// TODO: proper weight https://github.com/paritytech/substrate/pull/7910.
|
||||
(false, true, Weight::zero())
|
||||
} else {
|
||||
// no signed phase: create a new snapshot, definitely `enable` the unsigned
|
||||
@@ -581,15 +607,25 @@ pub mod pallet {
|
||||
(true, true, Weight::zero())
|
||||
};
|
||||
|
||||
Self::on_initialize_open_unsigned(need_snapshot, enabled, now);
|
||||
log!(info, "Starting unsigned phase({}) at #{:?}.", enabled, now);
|
||||
match Self::on_initialize_open_unsigned(need_snapshot, enabled, now) {
|
||||
Ok(snap_weight) => {
|
||||
log!(info, "Starting unsigned phase({}).", enabled);
|
||||
let base_weight = if need_snapshot {
|
||||
T::WeightInfo::on_initialize_open_unsigned_with_snapshot()
|
||||
} else {
|
||||
T::WeightInfo::on_initialize_open_unsigned_without_snapshot()
|
||||
};
|
||||
|
||||
let base_weight = if need_snapshot {
|
||||
T::WeightInfo::on_initialize_open_unsigned_with_snapshot()
|
||||
} else {
|
||||
T::WeightInfo::on_initialize_open_unsigned_without_snapshot()
|
||||
};
|
||||
base_weight.saturating_add(additional)
|
||||
base_weight.saturating_add(snap_weight).saturating_add(signed_weight)
|
||||
}
|
||||
Err(why) => {
|
||||
// not much we can do about this at this point.
|
||||
log!(warn, "failed to open unsigned phase due to {:?}", why);
|
||||
T::WeightInfo::on_initialize_nothing()
|
||||
// NOTE: ^^ The trait specifies that this is a noop in terms of weight
|
||||
// in case of error.
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => T::WeightInfo::on_initialize_nothing(),
|
||||
}
|
||||
@@ -601,7 +637,7 @@ pub mod pallet {
|
||||
match Self::try_acquire_offchain_lock(n) {
|
||||
Ok(_) => {
|
||||
let outcome = Self::mine_check_and_submit().map_err(ElectionError::from);
|
||||
log!(info, "miner exeuction done: {:?}", outcome);
|
||||
log!(info, "mine_check_and_submit execution done: {:?}", outcome);
|
||||
}
|
||||
Err(why) => log!(warn, "denied offchain worker: {:?}", why),
|
||||
}
|
||||
@@ -838,32 +874,41 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Logic for `<Pallet as Hooks>::on_initialize` when signed phase is being opened.
|
||||
/// Logic for [`<Pallet as Hooks>::on_initialize`] when signed phase is being opened.
|
||||
///
|
||||
/// This is decoupled for easy weight calculation.
|
||||
pub(crate) fn on_initialize_open_signed() {
|
||||
///
|
||||
/// Returns `Ok(snapshot_weight)` if success, where `snapshot_weight` is the weight that
|
||||
/// needs to recorded for the creation of snapshot.
|
||||
pub(crate) fn on_initialize_open_signed() -> Result<Weight, ElectionError> {
|
||||
let weight = Self::create_snapshot()?;
|
||||
<CurrentPhase<T>>::put(Phase::Signed);
|
||||
Self::create_snapshot();
|
||||
Self::deposit_event(Event::SignedPhaseStarted(Self::round()));
|
||||
Ok(weight.saturating_add(T::DbWeight::get().writes(1)))
|
||||
}
|
||||
|
||||
/// Logic for `<Pallet as Hooks<T>>::on_initialize` when unsigned phase is being opened.
|
||||
/// Logic for [`<Pallet as Hooks<T>>::on_initialize`] when unsigned phase is being opened.
|
||||
///
|
||||
/// This is decoupled for easy weight calculation. Note that the default weight benchmark of
|
||||
/// this function will assume an empty signed queue for `finalize_signed_phase`.
|
||||
/// This is decoupled for easy weight calculation.
|
||||
///
|
||||
/// Returns `Ok(snapshot_weight)` if success, where `snapshot_weight` is the weight that
|
||||
/// needs to recorded for the creation of snapshot.
|
||||
pub(crate) fn on_initialize_open_unsigned(
|
||||
need_snapshot: bool,
|
||||
enabled: bool,
|
||||
now: T::BlockNumber,
|
||||
) {
|
||||
if need_snapshot {
|
||||
) -> Result<Weight, ElectionError> {
|
||||
let weight = if need_snapshot {
|
||||
// if not being followed by a signed phase, then create the snapshots.
|
||||
debug_assert!(Self::snapshot().is_none());
|
||||
Self::create_snapshot();
|
||||
}
|
||||
Self::create_snapshot()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
<CurrentPhase<T>>::put(Phase::Unsigned((enabled, now)));
|
||||
Self::deposit_event(Event::UnsignedPhaseStarted(Self::round()));
|
||||
Ok(weight.saturating_add(T::DbWeight::get().writes(1)))
|
||||
}
|
||||
|
||||
/// Creates the snapshot. Writes new data to:
|
||||
@@ -871,18 +916,33 @@ impl<T: Config> Pallet<T> {
|
||||
/// 1. [`SnapshotMetadata`]
|
||||
/// 2. [`RoundSnapshot`]
|
||||
/// 3. [`DesiredTargets`]
|
||||
pub(crate) fn create_snapshot() {
|
||||
// if any of them don't exist, create all of them. This is a bit conservative.
|
||||
let targets = T::DataProvider::targets();
|
||||
let voters = T::DataProvider::voters();
|
||||
let desired_targets = T::DataProvider::desired_targets();
|
||||
///
|
||||
/// Returns `Ok(consumed_weight)` if operation is okay.
|
||||
pub(crate) fn create_snapshot() -> Result<Weight, ElectionError> {
|
||||
let target_limit = <CompactTargetIndexOf<T>>::max_value().saturated_into::<usize>();
|
||||
let voter_limit = <CompactVoterIndexOf<T>>::max_value().saturated_into::<usize>();
|
||||
|
||||
let (targets, w1) =
|
||||
T::DataProvider::targets(Some(target_limit)).map_err(ElectionError::DataProvider)?;
|
||||
let (voters, w2) =
|
||||
T::DataProvider::voters(Some(voter_limit)).map_err(ElectionError::DataProvider)?;
|
||||
let (desired_targets, w3) =
|
||||
T::DataProvider::desired_targets().map_err(ElectionError::DataProvider)?;
|
||||
|
||||
// defensive-only
|
||||
if targets.len() > target_limit || voters.len() > voter_limit {
|
||||
debug_assert!(false, "Snapshot limit has not been respected.");
|
||||
return Err(ElectionError::DataProvider("Snapshot too big for submission."));
|
||||
}
|
||||
|
||||
// only write snapshot if all existed.
|
||||
<SnapshotMetadata<T>>::put(SolutionOrSnapshotSize {
|
||||
voters: voters.len() as u32,
|
||||
targets: targets.len() as u32,
|
||||
});
|
||||
<DesiredTargets<T>>::put(desired_targets);
|
||||
<Snapshot<T>>::put(RoundSnapshot { voters, targets });
|
||||
Ok(w1.saturating_add(w2).saturating_add(w3).saturating_add(T::DbWeight::get().writes(3)))
|
||||
}
|
||||
|
||||
/// Kill everything created by [`Pallet::create_snapshot`].
|
||||
@@ -998,7 +1058,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// On-chain fallback of election.
|
||||
fn onchain_fallback() -> Result<Supports<T::AccountId>, ElectionError> {
|
||||
fn onchain_fallback() -> Result<(Supports<T::AccountId>, Weight), ElectionError> {
|
||||
<onchain::OnChainSequentialPhragmen<OnChainConfig<T>> as ElectionProvider<
|
||||
T::AccountId,
|
||||
T::BlockNumber,
|
||||
@@ -1006,23 +1066,27 @@ impl<T: Config> Pallet<T> {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn do_elect() -> Result<Supports<T::AccountId>, ElectionError> {
|
||||
fn do_elect() -> Result<(Supports<T::AccountId>, Weight), ElectionError> {
|
||||
<QueuedSolution<T>>::take()
|
||||
.map_or_else(
|
||||
|| match T::Fallback::get() {
|
||||
FallbackStrategy::OnChain => Self::onchain_fallback()
|
||||
.map(|r| (r, ElectionCompute::OnChain))
|
||||
.map(|(s, w)| (s, w, ElectionCompute::OnChain))
|
||||
.map_err(Into::into),
|
||||
FallbackStrategy::Nothing => Err(ElectionError::NoFallbackConfigured),
|
||||
},
|
||||
|ReadySolution { supports, compute, .. }| Ok((supports, compute)),
|
||||
|ReadySolution { supports, compute, .. }| Ok((
|
||||
supports,
|
||||
T::WeightInfo::elect_queued(),
|
||||
compute
|
||||
)),
|
||||
)
|
||||
.map(|(supports, compute)| {
|
||||
.map(|(supports, weight, compute)| {
|
||||
Self::deposit_event(Event::ElectionFinalized(Some(compute)));
|
||||
if Self::round() != 1 {
|
||||
log!(info, "Finalized election round with compute {:?}.", compute);
|
||||
}
|
||||
supports
|
||||
(supports, weight)
|
||||
})
|
||||
.map_err(|err| {
|
||||
Self::deposit_event(Event::ElectionFinalized(None));
|
||||
@@ -1038,10 +1102,11 @@ impl<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for Pallet<T> {
|
||||
type Error = ElectionError;
|
||||
type DataProvider = T::DataProvider;
|
||||
|
||||
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
|
||||
let outcome = Self::do_elect();
|
||||
fn elect() -> Result<(Supports<T::AccountId>, Weight), Self::Error> {
|
||||
let outcome_and_weight = Self::do_elect();
|
||||
// IMPORTANT: regardless of if election was `Ok` or `Err`, we shall do some cleanup.
|
||||
Self::post_elect();
|
||||
outcome
|
||||
outcome_and_weight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1132,13 +1197,13 @@ mod feasibility_check {
|
||||
.compact
|
||||
.votes1
|
||||
.iter_mut()
|
||||
.filter(|(_, t)| *t == 3u16)
|
||||
.filter(|(_, t)| *t == TargetIndex::from(3u16))
|
||||
.for_each(|(_, t)| *t += 1);
|
||||
solution.compact.votes2.iter_mut().for_each(|(_, (t0, _), t1)| {
|
||||
if *t0 == 3u16 {
|
||||
if *t0 == TargetIndex::from(3u16) {
|
||||
*t0 += 1
|
||||
};
|
||||
if *t1 == 3u16 {
|
||||
if *t1 == TargetIndex::from(3u16) {
|
||||
*t1 += 1
|
||||
};
|
||||
});
|
||||
@@ -1166,7 +1231,7 @@ mod feasibility_check {
|
||||
.compact
|
||||
.votes1
|
||||
.iter_mut()
|
||||
.filter(|(v, _)| *v == 7u32)
|
||||
.filter(|(v, _)| *v == VoterIndex::from(7u32))
|
||||
.map(|(v, _)| *v = 8)
|
||||
.count() > 0
|
||||
);
|
||||
@@ -1229,7 +1294,7 @@ mod feasibility_check {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{mock::*, Event, *};
|
||||
use sp_election_providers::ElectionProvider;
|
||||
use frame_election_provider_support::ElectionProvider;
|
||||
use sp_npos_elections::Support;
|
||||
|
||||
#[test]
|
||||
@@ -1401,7 +1466,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn fallback_strategy_works() {
|
||||
ExtBuilder::default().fallabck(FallbackStrategy::OnChain).build_and_execute(|| {
|
||||
ExtBuilder::default().fallback(FallbackStrategy::OnChain).build_and_execute(|| {
|
||||
roll_to(15);
|
||||
assert_eq!(MultiPhase::current_phase(), Phase::Signed);
|
||||
|
||||
@@ -1409,7 +1474,7 @@ mod tests {
|
||||
assert_eq!(MultiPhase::current_phase(), Phase::Unsigned((true, 25)));
|
||||
|
||||
// zilch solutions thus far.
|
||||
let supports = MultiPhase::elect().unwrap();
|
||||
let (supports, _) = MultiPhase::elect().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
supports,
|
||||
@@ -1420,7 +1485,7 @@ mod tests {
|
||||
)
|
||||
});
|
||||
|
||||
ExtBuilder::default().fallabck(FallbackStrategy::Nothing).build_and_execute(|| {
|
||||
ExtBuilder::default().fallback(FallbackStrategy::Nothing).build_and_execute(|| {
|
||||
roll_to(15);
|
||||
assert_eq!(MultiPhase::current_phase(), Phase::Signed);
|
||||
|
||||
@@ -1432,6 +1497,26 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_creation_fails_if_too_big() {
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
Targets::set((0..(TargetIndex::max_value() as AccountId) + 1).collect::<Vec<_>>());
|
||||
|
||||
// signed phase failed to open.
|
||||
roll_to(15);
|
||||
assert_eq!(MultiPhase::current_phase(), Phase::Off);
|
||||
|
||||
// unsigned phase failed to open.
|
||||
roll_to(25);
|
||||
assert_eq!(MultiPhase::current_phase(), Phase::Off);
|
||||
|
||||
// on-chain backup works though.
|
||||
roll_to(29);
|
||||
let (supports, _) = MultiPhase::elect().unwrap();
|
||||
assert!(supports.len() > 0);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_of_voters_allowed_2sec_block() {
|
||||
// Just a rough estimate with the substrate weights.
|
||||
|
||||
@@ -31,7 +31,7 @@ use sp_core::{
|
||||
},
|
||||
H256,
|
||||
};
|
||||
use sp_election_providers::ElectionDataProvider;
|
||||
use frame_election_provider_support::{ElectionDataProvider, data_provider};
|
||||
use sp_npos_elections::{
|
||||
assignment_ratio_to_staked_normalized, seq_phragmen, to_supports, to_without_backing,
|
||||
CompactSolution, ElectionResult, EvaluateSupport,
|
||||
@@ -60,10 +60,12 @@ frame_support::construct_runtime!(
|
||||
|
||||
pub(crate) type Balance = u64;
|
||||
pub(crate) type AccountId = u64;
|
||||
pub(crate) type VoterIndex = u32;
|
||||
pub(crate) type TargetIndex = u16;
|
||||
|
||||
sp_npos_elections::generate_solution_type!(
|
||||
#[compact]
|
||||
pub struct TestCompact::<u32, u16, PerU16>(16)
|
||||
pub struct TestCompact::<VoterIndex, TargetIndex, PerU16>(16)
|
||||
);
|
||||
|
||||
/// All events of this pallet.
|
||||
@@ -239,6 +241,13 @@ impl multi_phase::weights::WeightInfo for DualMockWeightInfo {
|
||||
<() as multi_phase::weights::WeightInfo>::on_initialize_open_unsigned_without_snapshot()
|
||||
}
|
||||
}
|
||||
fn elect_queued() -> Weight {
|
||||
if MockWeightInfo::get() {
|
||||
Zero::zero()
|
||||
} else {
|
||||
<() as multi_phase::weights::WeightInfo>::elect_queued()
|
||||
}
|
||||
}
|
||||
fn submit_unsigned(v: u32, t: u32, a: u32, d: u32) -> Weight {
|
||||
if MockWeightInfo::get() {
|
||||
// 10 base
|
||||
@@ -291,18 +300,43 @@ pub struct ExtBuilder {}
|
||||
|
||||
pub struct StakingMock;
|
||||
impl ElectionDataProvider<AccountId, u64> for StakingMock {
|
||||
fn targets() -> Vec<AccountId> {
|
||||
Targets::get()
|
||||
fn targets(maybe_max_len: Option<usize>) -> data_provider::Result<(Vec<AccountId>, Weight)> {
|
||||
let targets = Targets::get();
|
||||
|
||||
if maybe_max_len.map_or(false, |max_len| targets.len() > max_len) {
|
||||
return Err("Targets too big");
|
||||
}
|
||||
|
||||
Ok((targets, 0))
|
||||
}
|
||||
fn voters() -> Vec<(AccountId, VoteWeight, Vec<AccountId>)> {
|
||||
Voters::get()
|
||||
|
||||
fn voters(
|
||||
maybe_max_len: Option<usize>,
|
||||
) -> data_provider::Result<(Vec<(AccountId, VoteWeight, Vec<AccountId>)>, Weight)> {
|
||||
let voters = Voters::get();
|
||||
if maybe_max_len.map_or(false, |max_len| voters.len() > max_len) {
|
||||
return Err("Voters too big");
|
||||
}
|
||||
|
||||
Ok((voters, 0))
|
||||
}
|
||||
fn desired_targets() -> u32 {
|
||||
DesiredTargets::get()
|
||||
fn desired_targets() -> data_provider::Result<(u32, Weight)> {
|
||||
Ok((DesiredTargets::get(), 0))
|
||||
}
|
||||
|
||||
fn next_election_prediction(now: u64) -> u64 {
|
||||
now + EpochLength::get() - now % EpochLength::get()
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "runtime-benchmarks", test))]
|
||||
fn put_snapshot(
|
||||
voters: Vec<(AccountId, VoteWeight, Vec<AccountId>)>,
|
||||
targets: Vec<AccountId>,
|
||||
_target_stake: Option<VoteWeight>,
|
||||
) {
|
||||
Targets::set(targets);
|
||||
Voters::set(voters);
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtBuilder {
|
||||
@@ -319,7 +353,7 @@ impl ExtBuilder {
|
||||
<UnsignedPhase>::set(unsigned);
|
||||
self
|
||||
}
|
||||
pub fn fallabck(self, fallback: FallbackStrategy) -> Self {
|
||||
pub fn fallback(self, fallback: FallbackStrategy) -> Self {
|
||||
<Fallback>::set(fallback);
|
||||
self
|
||||
}
|
||||
|
||||
@@ -66,8 +66,17 @@ impl<T: Config> Pallet<T> {
|
||||
let iters = Self::get_balancing_iters();
|
||||
// get the solution, with a load of checks to ensure if submitted, IT IS ABSOLUTELY VALID.
|
||||
let (raw_solution, witness) = Self::mine_and_check(iters)?;
|
||||
let score = raw_solution.score.clone();
|
||||
|
||||
let call: <T as frame_system::offchain::SendTransactionTypes<Call<T>>>::OverarchingCall =
|
||||
Call::submit_unsigned(raw_solution, witness).into();
|
||||
log!(
|
||||
info,
|
||||
"mined a solution with score {:?} and size {}",
|
||||
score,
|
||||
call.using_encoded(|b| b.len())
|
||||
);
|
||||
|
||||
let call = Call::submit_unsigned(raw_solution, witness).into();
|
||||
SubmitTransaction::<T, Call<T>>::submit_unsigned_transaction(call)
|
||||
.map_err(|_| MinerError::PoolSubmissionFailed)
|
||||
}
|
||||
@@ -413,6 +422,9 @@ mod max_weight {
|
||||
fn on_initialize_open_unsigned_with_snapshot() -> Weight {
|
||||
unreachable!()
|
||||
}
|
||||
fn elect_queued() -> Weight {
|
||||
0
|
||||
}
|
||||
fn on_initialize_open_unsigned_without_snapshot() -> Weight {
|
||||
unreachable!()
|
||||
}
|
||||
@@ -487,7 +499,7 @@ mod tests {
|
||||
};
|
||||
use frame_support::{dispatch::Dispatchable, traits::OffchainWorker};
|
||||
use mock::Call as OuterCall;
|
||||
use sp_election_providers::Assignment;
|
||||
use frame_election_provider_support::Assignment;
|
||||
use sp_runtime::{traits::ValidateUnsigned, PerU16};
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! Autogenerated weights for pallet_election_provider_multi_phase
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
|
||||
//! DATE: 2021-02-12, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
|
||||
//! DATE: 2021-03-14, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
|
||||
|
||||
// Executed Command:
|
||||
@@ -48,6 +48,7 @@ pub trait WeightInfo {
|
||||
fn on_initialize_open_signed() -> Weight;
|
||||
fn on_initialize_open_unsigned_with_snapshot() -> Weight;
|
||||
fn on_initialize_open_unsigned_without_snapshot() -> Weight;
|
||||
fn elect_queued() -> Weight;
|
||||
fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight;
|
||||
fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight;
|
||||
}
|
||||
@@ -56,47 +57,52 @@ pub trait WeightInfo {
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
fn on_initialize_nothing() -> Weight {
|
||||
(23_401_000 as Weight)
|
||||
(22_833_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(7 as Weight))
|
||||
}
|
||||
fn on_initialize_open_signed() -> Weight {
|
||||
(79_260_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(7 as Weight))
|
||||
(106_993_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(8 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
fn on_initialize_open_unsigned_with_snapshot() -> Weight {
|
||||
(77_745_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(7 as Weight))
|
||||
(106_490_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(8 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
fn on_initialize_open_unsigned_without_snapshot() -> Weight {
|
||||
(21_764_000 as Weight)
|
||||
(21_275_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn elect_queued() -> Weight {
|
||||
(7_274_346_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(6 as Weight))
|
||||
}
|
||||
fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 23_000
|
||||
.saturating_add((4_171_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 78_000
|
||||
.saturating_add((229_000 as Weight).saturating_mul(t as Weight))
|
||||
// Standard Error: 23_000
|
||||
.saturating_add((13_661_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 117_000
|
||||
.saturating_add((4_499_000 as Weight).saturating_mul(d as Weight))
|
||||
// Standard Error: 19_000
|
||||
.saturating_add((4_017_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 66_000
|
||||
.saturating_add((130_000 as Weight).saturating_mul(t as Weight))
|
||||
// Standard Error: 19_000
|
||||
.saturating_add((13_057_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 99_000
|
||||
.saturating_add((4_558_000 as Weight).saturating_mul(d as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(6 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 12_000
|
||||
.saturating_add((4_232_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 42_000
|
||||
.saturating_add((636_000 as Weight).saturating_mul(t as Weight))
|
||||
.saturating_add((4_186_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 40_000
|
||||
.saturating_add((803_000 as Weight).saturating_mul(t as Weight))
|
||||
// Standard Error: 12_000
|
||||
.saturating_add((10_294_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 64_000
|
||||
.saturating_add((4_428_000 as Weight).saturating_mul(d as Weight))
|
||||
.saturating_add((9_806_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 61_000
|
||||
.saturating_add((4_156_000 as Weight).saturating_mul(d as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
}
|
||||
}
|
||||
@@ -104,47 +110,52 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn on_initialize_nothing() -> Weight {
|
||||
(23_401_000 as Weight)
|
||||
(22_833_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
|
||||
}
|
||||
fn on_initialize_open_signed() -> Weight {
|
||||
(79_260_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
|
||||
(106_993_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(8 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
fn on_initialize_open_unsigned_with_snapshot() -> Weight {
|
||||
(77_745_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
|
||||
(106_490_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(8 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
fn on_initialize_open_unsigned_without_snapshot() -> Weight {
|
||||
(21_764_000 as Weight)
|
||||
(21_275_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn elect_queued() -> Weight {
|
||||
(7_274_346_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
|
||||
}
|
||||
fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 23_000
|
||||
.saturating_add((4_171_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 78_000
|
||||
.saturating_add((229_000 as Weight).saturating_mul(t as Weight))
|
||||
// Standard Error: 23_000
|
||||
.saturating_add((13_661_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 117_000
|
||||
.saturating_add((4_499_000 as Weight).saturating_mul(d as Weight))
|
||||
// Standard Error: 19_000
|
||||
.saturating_add((4_017_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 66_000
|
||||
.saturating_add((130_000 as Weight).saturating_mul(t as Weight))
|
||||
// Standard Error: 19_000
|
||||
.saturating_add((13_057_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 99_000
|
||||
.saturating_add((4_558_000 as Weight).saturating_mul(d as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 12_000
|
||||
.saturating_add((4_232_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 42_000
|
||||
.saturating_add((636_000 as Weight).saturating_mul(t as Weight))
|
||||
.saturating_add((4_186_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 40_000
|
||||
.saturating_add((803_000 as Weight).saturating_mul(t as Weight))
|
||||
// Standard Error: 12_000
|
||||
.saturating_add((10_294_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 64_000
|
||||
.saturating_add((4_428_000 as Weight).saturating_mul(d as Weight))
|
||||
.saturating_add((9_806_000 as Weight).saturating_mul(a as Weight))
|
||||
// Standard Error: 61_000
|
||||
.saturating_add((4_156_000 as Weight).saturating_mul(d as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -1,12 +1,12 @@
|
||||
[package]
|
||||
name = "sp-election-providers"
|
||||
name = "frame-election-provider-support"
|
||||
version = "3.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://substrate.dev"
|
||||
repository = "https://github.com/paritytech/substrate/"
|
||||
description = "Primitive election providers"
|
||||
description = "election provider supporting traits"
|
||||
readme = "README.md"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
@@ -14,20 +14,24 @@ targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
|
||||
sp-std = { version = "3.0.0", default-features = false, path = "../std" }
|
||||
sp-arithmetic = { version = "3.0.0", default-features = false, path = "../arithmetic" }
|
||||
sp-npos-elections = { version = "3.0.0", default-features = false, path = "../npos-elections" }
|
||||
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
|
||||
sp-arithmetic = { version = "3.0.0", default-features = false, path = "../../primitives/arithmetic" }
|
||||
sp-npos-elections = { version = "3.0.0", default-features = false, path = "../../primitives/npos-elections" }
|
||||
frame-support = { version = "3.0.0", default-features = false, path = "../support" }
|
||||
frame-system = { version = "3.0.0", default-features = false, path = "../system" }
|
||||
|
||||
[dev-dependencies]
|
||||
sp-npos-elections = { version = "3.0.0", path = "../npos-elections" }
|
||||
sp-runtime = { version = "3.0.0", path = "../runtime" }
|
||||
sp-npos-elections = { version = "3.0.0", path = "../../primitives/npos-elections" }
|
||||
sp-runtime = { version = "3.0.0", path = "../../primitives/runtime" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
runtime-benchmarks = []
|
||||
std = [
|
||||
"codec/std",
|
||||
"sp-std/std",
|
||||
"sp-npos-elections/std",
|
||||
"sp-arithmetic/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
]
|
||||
runtime-benchmarks = []
|
||||
+57
-29
@@ -78,14 +78,15 @@
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use sp_election_providers::*;
|
||||
//! # use frame_election_provider_support::{*, data_provider};
|
||||
//! # use sp_npos_elections::{Support, Assignment};
|
||||
//! # use frame_support::weights::Weight;
|
||||
//!
|
||||
//! type AccountId = u64;
|
||||
//! type Balance = u64;
|
||||
//! type BlockNumber = u32;
|
||||
//!
|
||||
//! mod data_provider {
|
||||
//! mod data_provider_mod {
|
||||
//! use super::*;
|
||||
//!
|
||||
//! pub trait Config: Sized {
|
||||
@@ -99,14 +100,16 @@
|
||||
//! pub struct Module<T: Config>(std::marker::PhantomData<T>);
|
||||
//!
|
||||
//! impl<T: Config> ElectionDataProvider<AccountId, BlockNumber> for Module<T> {
|
||||
//! fn desired_targets() -> u32 {
|
||||
//! 1
|
||||
//! fn desired_targets() -> data_provider::Result<(u32, Weight)> {
|
||||
//! Ok((1, 0))
|
||||
//! }
|
||||
//! fn voters() -> Vec<(AccountId, VoteWeight, Vec<AccountId>)> {
|
||||
//! Default::default()
|
||||
//! fn voters(maybe_max_len: Option<usize>)
|
||||
//! -> data_provider::Result<(Vec<(AccountId, VoteWeight, Vec<AccountId>)>, Weight)>
|
||||
//! {
|
||||
//! Ok((Default::default(), 0))
|
||||
//! }
|
||||
//! fn targets() -> Vec<AccountId> {
|
||||
//! vec![10, 20, 30]
|
||||
//! fn targets(maybe_max_len: Option<usize>) -> data_provider::Result<(Vec<AccountId>, Weight)> {
|
||||
//! Ok((vec![10, 20, 30], 0))
|
||||
//! }
|
||||
//! fn next_election_prediction(now: BlockNumber) -> BlockNumber {
|
||||
//! 0
|
||||
@@ -125,29 +128,30 @@
|
||||
//! }
|
||||
//!
|
||||
//! impl<T: Config> ElectionProvider<AccountId, BlockNumber> for GenericElectionProvider<T> {
|
||||
//! type Error = ();
|
||||
//! type Error = &'static str;
|
||||
//! type DataProvider = T::DataProvider;
|
||||
//!
|
||||
//! fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
||||
//! Self::DataProvider::targets()
|
||||
//! .first()
|
||||
//! .map(|winner| vec![(*winner, Support::default())])
|
||||
//! .ok_or(())
|
||||
//! fn elect() -> Result<(Supports<AccountId>, Weight), Self::Error> {
|
||||
//! Self::DataProvider::targets(None)
|
||||
//! .map_err(|_| "failed to elect")
|
||||
//! .map(|(t, weight)| {
|
||||
//! (vec![(t[0], Support::default())], weight)
|
||||
//! })
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! mod runtime {
|
||||
//! use super::generic_election_provider;
|
||||
//! use super::data_provider;
|
||||
//! use super::data_provider_mod;
|
||||
//! use super::AccountId;
|
||||
//!
|
||||
//! struct Runtime;
|
||||
//! impl generic_election_provider::Config for Runtime {
|
||||
//! type DataProvider = data_provider::Module<Runtime>;
|
||||
//! type DataProvider = data_provider_mod::Module<Runtime>;
|
||||
//! }
|
||||
//!
|
||||
//! impl data_provider::Config for Runtime {
|
||||
//! impl data_provider_mod::Config for Runtime {
|
||||
//! type ElectionProvider = generic_election_provider::GenericElectionProvider<Runtime>;
|
||||
//! }
|
||||
//!
|
||||
@@ -160,23 +164,44 @@
|
||||
|
||||
pub mod onchain;
|
||||
use sp_std::{prelude::*, fmt::Debug};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Re-export some type as they are used in the interface.
|
||||
pub use sp_arithmetic::PerThing;
|
||||
pub use sp_npos_elections::{Assignment, ExtendedBalance, PerThing128, Supports, VoteWeight};
|
||||
|
||||
/// Types that are used by the data provider trait.
|
||||
pub mod data_provider {
|
||||
/// Alias for the result type of the election data provider.
|
||||
pub type Result<T> = sp_std::result::Result<T, &'static str>;
|
||||
}
|
||||
|
||||
/// Something that can provide the data to an [`ElectionProvider`].
|
||||
pub trait ElectionDataProvider<AccountId, BlockNumber> {
|
||||
/// All possible targets for the election, i.e. the candidates.
|
||||
fn targets() -> Vec<AccountId>;
|
||||
///
|
||||
/// If `maybe_max_len` is `Some(v)` then the resulting vector MUST NOT be longer than `v` items
|
||||
/// long.
|
||||
///
|
||||
/// It is assumed that this function will only consume a notable amount of weight, when it
|
||||
/// returns `Ok(_)`.
|
||||
fn targets(maybe_max_len: Option<usize>) -> data_provider::Result<(Vec<AccountId>, Weight)>;
|
||||
|
||||
/// All possible voters for the election.
|
||||
///
|
||||
/// Note that if a notion of self-vote exists, it should be represented here.
|
||||
fn voters() -> Vec<(AccountId, VoteWeight, Vec<AccountId>)>;
|
||||
///
|
||||
/// If `maybe_max_len` is `Some(v)` then the resulting vector MUST NOT be longer than `v` items
|
||||
/// long.
|
||||
///
|
||||
/// It is assumed that this function will only consume a notable amount of weight, when it
|
||||
/// returns `Ok(_)`.
|
||||
fn voters(
|
||||
maybe_max_len: Option<usize>,
|
||||
) -> data_provider::Result<(Vec<(AccountId, VoteWeight, Vec<AccountId>)>, Weight)>;
|
||||
|
||||
/// The number of targets to elect.
|
||||
fn desired_targets() -> u32;
|
||||
fn desired_targets() -> data_provider::Result<(u32, Weight)>;
|
||||
|
||||
/// Provide a best effort prediction about when the next election is about to happen.
|
||||
///
|
||||
@@ -192,20 +217,23 @@ pub trait ElectionDataProvider<AccountId, BlockNumber> {
|
||||
fn put_snapshot(
|
||||
_voters: Vec<(AccountId, VoteWeight, Vec<AccountId>)>,
|
||||
_targets: Vec<AccountId>,
|
||||
_target_stake: Option<VoteWeight>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<AccountId, BlockNumber> ElectionDataProvider<AccountId, BlockNumber> for () {
|
||||
fn targets() -> Vec<AccountId> {
|
||||
Default::default()
|
||||
fn targets(_maybe_max_len: Option<usize>) -> data_provider::Result<(Vec<AccountId>, Weight)> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
fn voters() -> Vec<(AccountId, VoteWeight, Vec<AccountId>)> {
|
||||
Default::default()
|
||||
fn voters(
|
||||
_maybe_max_len: Option<usize>,
|
||||
) -> data_provider::Result<(Vec<(AccountId, VoteWeight, Vec<AccountId>)>, Weight)> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
fn desired_targets() -> u32 {
|
||||
Default::default()
|
||||
fn desired_targets() -> data_provider::Result<(u32, Weight)> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
fn next_election_prediction(now: BlockNumber) -> BlockNumber {
|
||||
now
|
||||
@@ -226,8 +254,8 @@ pub trait ElectionProvider<AccountId, BlockNumber> {
|
||||
|
||||
/// Elect a new set of winners.
|
||||
///
|
||||
/// The result is returned in a target major format, namely as vector of supports.
|
||||
fn elect() -> Result<Supports<AccountId>, Self::Error>;
|
||||
/// The result is returned in a target major format, namely as vector of supports.
|
||||
fn elect() -> Result<(Supports<AccountId>, Weight), Self::Error>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@@ -235,7 +263,7 @@ impl<AccountId, BlockNumber> ElectionProvider<AccountId, BlockNumber> for () {
|
||||
type Error = &'static str;
|
||||
type DataProvider = ();
|
||||
|
||||
fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
||||
fn elect() -> Result<(Supports<AccountId>, Weight), Self::Error> {
|
||||
Err("<() as ElectionProvider> cannot do anything.")
|
||||
}
|
||||
}
|
||||
+30
-19
@@ -20,12 +20,15 @@
|
||||
use crate::{ElectionDataProvider, ElectionProvider};
|
||||
use sp_npos_elections::*;
|
||||
use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*};
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
|
||||
/// Errors of the on-chain election.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum Error {
|
||||
/// An internal error in the NPoS elections crate.
|
||||
NposElections(sp_npos_elections::Error),
|
||||
/// Errors from the data provider.
|
||||
DataProvider(&'static str),
|
||||
}
|
||||
|
||||
impl From<sp_npos_elections::Error> for Error {
|
||||
@@ -40,13 +43,20 @@ impl From<sp_npos_elections::Error> for Error {
|
||||
///
|
||||
/// ### Warning
|
||||
///
|
||||
/// This can be very expensive to run frequently on-chain. Use with care.
|
||||
/// This can be very expensive to run frequently on-chain. Use with care. Moreover, this
|
||||
/// implementation ignores the additional data of the election data provider and gives no insight on
|
||||
/// how much weight was consumed.
|
||||
///
|
||||
/// Finally, this implementation does not impose any limits on the number of voters and targets that
|
||||
/// are provided.
|
||||
pub struct OnChainSequentialPhragmen<T: Config>(PhantomData<T>);
|
||||
|
||||
/// Configuration trait of [`OnChainSequentialPhragmen`].
|
||||
///
|
||||
/// Note that this is similar to a pallet traits, but [`OnChainSequentialPhragmen`] is not a pallet.
|
||||
pub trait Config {
|
||||
/// The block limits.
|
||||
type BlockWeights: Get<frame_system::limits::BlockWeights>;
|
||||
/// The account identifier type.
|
||||
type AccountId: IdentifierT;
|
||||
/// The block number type.
|
||||
@@ -61,10 +71,11 @@ impl<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for OnChainSequen
|
||||
type Error = Error;
|
||||
type DataProvider = T::DataProvider;
|
||||
|
||||
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
|
||||
let voters = Self::DataProvider::voters();
|
||||
let targets = Self::DataProvider::targets();
|
||||
let desired_targets = Self::DataProvider::desired_targets() as usize;
|
||||
fn elect() -> Result<(Supports<T::AccountId>, Weight), Self::Error> {
|
||||
let (voters, _) = Self::DataProvider::voters(None).map_err(Error::DataProvider)?;
|
||||
let (targets, _) = Self::DataProvider::targets(None).map_err(Error::DataProvider)?;
|
||||
let (desired_targets, _) =
|
||||
Self::DataProvider::desired_targets().map_err(Error::DataProvider)?;
|
||||
|
||||
let mut stake_map: BTreeMap<T::AccountId, VoteWeight> = BTreeMap::new();
|
||||
|
||||
@@ -77,13 +88,13 @@ impl<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for OnChainSequen
|
||||
};
|
||||
|
||||
let ElectionResult { winners, assignments } =
|
||||
seq_phragmen::<_, T::Accuracy>(desired_targets, targets, voters, None)
|
||||
seq_phragmen::<_, T::Accuracy>(desired_targets as usize, targets, voters, None)
|
||||
.map_err(Error::from)?;
|
||||
|
||||
let staked = assignment_ratio_to_staked_normalized(assignments, &stake_of)?;
|
||||
let winners = to_without_backing(winners);
|
||||
|
||||
to_supports(&winners, &staked).map_err(Error::from)
|
||||
to_supports(&winners, &staked).map_err(Error::from).map(|s| (s, T::BlockWeights::get().max_block))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +103,13 @@ mod tests {
|
||||
use super::*;
|
||||
use sp_npos_elections::Support;
|
||||
use sp_runtime::Perbill;
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
type AccountId = u64;
|
||||
type BlockNumber = u32;
|
||||
|
||||
struct Runtime;
|
||||
impl Config for Runtime {
|
||||
type BlockWeights = ();
|
||||
type AccountId = AccountId;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Accuracy = Perbill;
|
||||
@@ -108,24 +120,23 @@ mod tests {
|
||||
|
||||
mod mock_data_provider {
|
||||
use super::*;
|
||||
use crate::data_provider;
|
||||
|
||||
pub struct DataProvider;
|
||||
|
||||
impl ElectionDataProvider<AccountId, BlockNumber> for DataProvider {
|
||||
fn voters() -> Vec<(AccountId, VoteWeight, Vec<AccountId>)> {
|
||||
vec![
|
||||
(1, 10, vec![10, 20]),
|
||||
(2, 20, vec![30, 20]),
|
||||
(3, 30, vec![10, 30]),
|
||||
]
|
||||
fn voters(
|
||||
_: Option<usize>,
|
||||
) -> data_provider::Result<(Vec<(AccountId, VoteWeight, Vec<AccountId>)>, Weight)> {
|
||||
Ok((vec![(1, 10, vec![10, 20]), (2, 20, vec![30, 20]), (3, 30, vec![10, 30])], 0))
|
||||
}
|
||||
|
||||
fn targets() -> Vec<AccountId> {
|
||||
vec![10, 20, 30]
|
||||
fn targets(_: Option<usize>) -> data_provider::Result<(Vec<AccountId>, Weight)> {
|
||||
Ok((vec![10, 20, 30], 0))
|
||||
}
|
||||
|
||||
fn desired_targets() -> u32 {
|
||||
2
|
||||
fn desired_targets() -> data_provider::Result<(u32, Weight)> {
|
||||
Ok((2, 0))
|
||||
}
|
||||
|
||||
fn next_election_prediction(_: BlockNumber) -> BlockNumber {
|
||||
@@ -137,7 +148,7 @@ mod tests {
|
||||
#[test]
|
||||
fn onchain_seq_phragmen_works() {
|
||||
assert_eq!(
|
||||
OnChainPhragmen::elect().unwrap(),
|
||||
OnChainPhragmen::elect().unwrap().0,
|
||||
vec![
|
||||
(
|
||||
10,
|
||||
@@ -39,7 +39,7 @@ pallet-offences = { version = "3.0.0", path = "../offences" }
|
||||
pallet-staking = { version = "3.0.0", path = "../staking" }
|
||||
pallet-staking-reward-curve = { version = "3.0.0", path = "../staking/reward-curve" }
|
||||
pallet-timestamp = { version = "3.0.0", path = "../timestamp" }
|
||||
sp-election-providers = { version = "3.0.0", path = "../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", path = "../election-provider-support" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -40,7 +40,7 @@ use sp_runtime::{
|
||||
};
|
||||
use sp_staking::SessionIndex;
|
||||
use pallet_session::historical as pallet_session_historical;
|
||||
use sp_election_providers::onchain;
|
||||
use frame_election_provider_support::onchain;
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
@@ -193,6 +193,7 @@ parameter_types! {
|
||||
impl onchain::Config for Test {
|
||||
type AccountId = <Self as frame_system::Config>::AccountId;
|
||||
type BlockNumber = <Self as frame_system::Config>::BlockNumber;
|
||||
type BlockWeights = ();
|
||||
type Accuracy = Perbill;
|
||||
type DataProvider = Staking;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ pallet-staking = { version = "3.0.0", default-features = false, features = ["run
|
||||
sp-runtime = { version = "3.0.0", default-features = false, path = "../../../primitives/runtime" }
|
||||
sp-staking = { version = "3.0.0", default-features = false, path = "../../../primitives/staking" }
|
||||
sp-std = { version = "3.0.0", default-features = false, path = "../../../primitives/std" }
|
||||
sp-election-providers = { version = "3.0.0", default-features = false, path = "../../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", default-features = false, path = "../../election-provider-support" }
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-staking-reward-curve = { version = "3.0.0", path = "../../staking/reward-curve" }
|
||||
@@ -51,7 +51,7 @@ std = [
|
||||
"pallet-staking/std",
|
||||
"sp-runtime/std",
|
||||
"sp-staking/std",
|
||||
"sp-election-providers/std",
|
||||
"frame-election-provider-support/std",
|
||||
"sp-std/std",
|
||||
"codec/std",
|
||||
]
|
||||
|
||||
@@ -29,7 +29,7 @@ use sp_runtime::{
|
||||
traits::IdentityLookup,
|
||||
testing::{Header, UintAuthorityId},
|
||||
};
|
||||
use sp_election_providers::onchain;
|
||||
use frame_election_provider_support::onchain;
|
||||
use pallet_session::historical as pallet_session_historical;
|
||||
|
||||
type AccountId = u64;
|
||||
@@ -152,6 +152,7 @@ pub type Extrinsic = sp_runtime::testing::TestXt<Call, ()>;
|
||||
impl onchain::Config for Test {
|
||||
type AccountId = AccountId;
|
||||
type BlockNumber = BlockNumber;
|
||||
type BlockWeights = ();
|
||||
type Accuracy = Perbill;
|
||||
type DataProvider = Staking;
|
||||
}
|
||||
|
||||
@@ -31,14 +31,14 @@ pallet-staking-reward-curve = { version = "3.0.0", path = "../../staking/reward-
|
||||
sp-io ={ version = "3.0.0", path = "../../../primitives/io" }
|
||||
pallet-timestamp = { version = "3.0.0", path = "../../timestamp" }
|
||||
pallet-balances = { version = "3.0.0", path = "../../balances" }
|
||||
sp-election-providers = { version = "3.0.0", path = "../../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", path = "../../election-provider-support" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"sp-std/std",
|
||||
"sp-session/std",
|
||||
"sp-election-providers/std",
|
||||
"frame-election-provider-support/std",
|
||||
"sp-runtime/std",
|
||||
"frame-system/std",
|
||||
"frame-benchmarking/std",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use sp_runtime::traits::IdentityLookup;
|
||||
use sp_election_providers::onchain;
|
||||
use frame_election_provider_support::onchain;
|
||||
use frame_support::parameter_types;
|
||||
|
||||
type AccountId = u64;
|
||||
@@ -157,6 +157,7 @@ where
|
||||
impl onchain::Config for Test {
|
||||
type AccountId = AccountId;
|
||||
type BlockNumber = BlockNumber;
|
||||
type BlockWeights = ();
|
||||
type Accuracy = sp_runtime::Perbill;
|
||||
type DataProvider = Staking;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ pallet-session = { version = "3.0.0", default-features = false, features = ["his
|
||||
pallet-authorship = { version = "3.0.0", default-features = false, path = "../authorship" }
|
||||
sp-application-crypto = { version = "3.0.0", default-features = false, path = "../../primitives/application-crypto" }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
sp-election-providers = { version = "3.0.0", default-features = false, path = "../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", default-features = false, path = "../election-provider-support" }
|
||||
|
||||
# Optional imports for benchmarking
|
||||
frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true }
|
||||
@@ -43,7 +43,7 @@ pallet-timestamp = { version = "3.0.0", path = "../timestamp" }
|
||||
pallet-staking-reward-curve = { version = "3.0.0", path = "../staking/reward-curve" }
|
||||
substrate-test-utils = { version = "3.0.0", path = "../../test-utils" }
|
||||
frame-benchmarking = { version = "3.1.0", path = "../benchmarking" }
|
||||
sp-election-providers = { version = "3.0.0", features = ["runtime-benchmarks"], path = "../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", features = ["runtime-benchmarks"], path = "../election-provider-support" }
|
||||
rand_chacha = { version = "0.2" }
|
||||
parking_lot = "0.11.1"
|
||||
hex = "0.4"
|
||||
@@ -64,11 +64,11 @@ std = [
|
||||
"pallet-authorship/std",
|
||||
"sp-application-crypto/std",
|
||||
"log/std",
|
||||
"sp-election-providers/std",
|
||||
"frame-election-provider-support/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking",
|
||||
"sp-election-providers/runtime-benchmarks",
|
||||
"frame-election-provider-support/runtime-benchmarks",
|
||||
"rand_chacha",
|
||||
]
|
||||
try-runtime = ["frame-support/try-runtime"]
|
||||
|
||||
@@ -28,7 +28,7 @@ sp-io ={ version = "3.0.0", path = "../../../primitives/io" }
|
||||
sp-core = { version = "3.0.0", path = "../../../primitives/core" }
|
||||
sp-npos-elections = { version = "3.0.0", path = "../../../primitives/npos-elections" }
|
||||
sp-runtime = { version = "3.0.0", path = "../../../primitives/runtime" }
|
||||
sp-election-providers = { version = "3.0.0", path = "../../../primitives/election-providers" }
|
||||
frame-election-provider-support = { version = "3.0.0", path = "../../election-provider-support" }
|
||||
serde = "1.0.101"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -158,11 +158,16 @@ where
|
||||
}
|
||||
|
||||
pub struct MockElectionProvider;
|
||||
impl sp_election_providers::ElectionProvider<AccountId, BlockNumber> for MockElectionProvider {
|
||||
impl frame_election_provider_support::ElectionProvider<AccountId, BlockNumber>
|
||||
for MockElectionProvider
|
||||
{
|
||||
type Error = ();
|
||||
type DataProvider = pallet_staking::Module<Test>;
|
||||
|
||||
fn elect() -> Result<sp_npos_elections::Supports<AccountId>, Self::Error> {
|
||||
fn elect() -> Result<
|
||||
(sp_npos_elections::Supports<AccountId>, frame_support::weights::Weight),
|
||||
Self::Error
|
||||
> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,9 @@ use sp_npos_elections::CompactSolution;
|
||||
use sp_runtime::traits::One;
|
||||
use frame_system::RawOrigin;
|
||||
pub use frame_benchmarking::{
|
||||
benchmarks,
|
||||
account,
|
||||
whitelisted_caller,
|
||||
whitelist_account,
|
||||
impl_benchmark_test_suite,
|
||||
benchmarks, account, whitelisted_caller, whitelist_account, impl_benchmark_test_suite,
|
||||
};
|
||||
|
||||
const SEED: u32 = 0;
|
||||
const MAX_SPANS: u32 = 100;
|
||||
const MAX_VALIDATORS: u32 = 1000;
|
||||
@@ -768,6 +765,39 @@ benchmarks! {
|
||||
).is_err()
|
||||
);
|
||||
}
|
||||
|
||||
get_npos_voters {
|
||||
// number of validator intention.
|
||||
let v in 200 .. 400;
|
||||
// number of nominator intention.
|
||||
let n in 200 .. 400;
|
||||
// total number of slashing spans. Assigned to validators randomly.
|
||||
let s in 1 .. 20;
|
||||
|
||||
let validators = create_validators_with_nominators_for_era::<T>(v, n, MAX_NOMINATIONS, false, None)?
|
||||
.into_iter()
|
||||
.map(|v| T::Lookup::lookup(v).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(0..s).for_each(|index| {
|
||||
add_slashing_spans::<T>(&validators[index as usize], 10);
|
||||
});
|
||||
}: {
|
||||
let voters = <Staking<T>>::get_npos_voters();
|
||||
assert_eq!(voters.len() as u32, v + n);
|
||||
}
|
||||
|
||||
get_npos_targets {
|
||||
// number of validator intention.
|
||||
let v in 200 .. 400;
|
||||
// number of nominator intention.
|
||||
let n = 500;
|
||||
|
||||
let _ = create_validators_with_nominators_for_era::<T>(v, n, MAX_NOMINATIONS, false, None)?;
|
||||
}: {
|
||||
let targets = <Staking<T>>::get_npos_targets();
|
||||
assert_eq!(targets.len() as u32, v);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -875,7 +905,6 @@ mod tests {
|
||||
assert_ok!(test_benchmark_submit_solution_weaker::<Test>());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
|
||||
@@ -331,7 +331,7 @@ use sp_npos_elections::{
|
||||
to_supports, EvaluateSupport, seq_phragmen, generate_solution_type, is_score_better, Supports,
|
||||
VoteWeight, CompactSolution, PerThing128,
|
||||
};
|
||||
use sp_election_providers::ElectionProvider;
|
||||
use frame_election_provider_support::{ElectionProvider, data_provider};
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
const STAKING_ID: LockIdentifier = *b"staking ";
|
||||
@@ -800,7 +800,7 @@ pub trait Config: frame_system::Config + SendTransactionTypes<Call<Self>> {
|
||||
type CurrencyToVote: CurrencyToVote<BalanceOf<Self>>;
|
||||
|
||||
/// Something that provides the election functionality.
|
||||
type ElectionProvider: sp_election_providers::ElectionProvider<
|
||||
type ElectionProvider: frame_election_provider_support::ElectionProvider<
|
||||
Self::AccountId,
|
||||
Self::BlockNumber,
|
||||
// we only accept an election provider that has staking as data provider.
|
||||
@@ -3345,19 +3345,45 @@ impl<T: Config> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> sp_election_providers::ElectionDataProvider<T::AccountId, T::BlockNumber>
|
||||
impl<T: Config> frame_election_provider_support::ElectionDataProvider<T::AccountId, T::BlockNumber>
|
||||
for Module<T>
|
||||
{
|
||||
fn desired_targets() -> u32 {
|
||||
Self::validator_count()
|
||||
fn desired_targets() -> data_provider::Result<(u32, Weight)> {
|
||||
Ok((Self::validator_count(), <T as frame_system::Config>::DbWeight::get().reads(1)))
|
||||
}
|
||||
|
||||
fn voters() -> Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> {
|
||||
Self::get_npos_voters()
|
||||
fn voters(
|
||||
maybe_max_len: Option<usize>,
|
||||
) -> data_provider::Result<(Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>, Weight)> {
|
||||
// NOTE: reading these counts already needs to iterate a lot of storage keys, but they get
|
||||
// cached. This is okay for the case of `Ok(_)`, but bad for `Err(_)`, as the trait does not
|
||||
// report weight in failures.
|
||||
let nominator_count = <Nominators<T>>::iter().count();
|
||||
let validator_count = <Validators<T>>::iter().count();
|
||||
let voter_count = nominator_count.saturating_add(validator_count);
|
||||
|
||||
if maybe_max_len.map_or(false, |max_len| voter_count > max_len) {
|
||||
return Err("Voter snapshot too big");
|
||||
}
|
||||
|
||||
let slashing_span_count = <SlashingSpans<T>>::iter().count();
|
||||
let weight = T::WeightInfo::get_npos_voters(
|
||||
nominator_count as u32,
|
||||
validator_count as u32,
|
||||
slashing_span_count as u32,
|
||||
);
|
||||
Ok((Self::get_npos_voters(), weight))
|
||||
}
|
||||
|
||||
fn targets() -> Vec<T::AccountId> {
|
||||
Self::get_npos_targets()
|
||||
fn targets(maybe_max_len: Option<usize>) -> data_provider::Result<(Vec<T::AccountId>, Weight)> {
|
||||
let target_count = <Validators<T>>::iter().count();
|
||||
|
||||
if maybe_max_len.map_or(false, |max_len| target_count > max_len) {
|
||||
return Err("Target snapshot too big");
|
||||
}
|
||||
|
||||
let weight = <T as frame_system::Config>::DbWeight::get().reads(target_count as u64);
|
||||
Ok((Self::get_npos_targets(), weight))
|
||||
}
|
||||
|
||||
fn next_election_prediction(now: T::BlockNumber) -> T::BlockNumber {
|
||||
@@ -3391,15 +3417,45 @@ impl<T: Config> sp_election_providers::ElectionDataProvider<T::AccountId, T::Blo
|
||||
fn put_snapshot(
|
||||
voters: Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
|
||||
targets: Vec<T::AccountId>,
|
||||
target_stake: Option<VoteWeight>,
|
||||
) {
|
||||
use sp_std::convert::TryFrom;
|
||||
targets.into_iter().for_each(|v| {
|
||||
let stake: BalanceOf<T> = target_stake
|
||||
.and_then(|w| <BalanceOf<T>>::try_from(w).ok())
|
||||
.unwrap_or(T::Currency::minimum_balance() * 100u32.into());
|
||||
<Bonded<T>>::insert(v.clone(), v.clone());
|
||||
<Ledger<T>>::insert(
|
||||
v.clone(),
|
||||
StakingLedger {
|
||||
stash: v.clone(),
|
||||
active: stake,
|
||||
total: stake,
|
||||
unlocking: vec![],
|
||||
claimed_rewards: vec![],
|
||||
},
|
||||
);
|
||||
<Validators<T>>::insert(
|
||||
v,
|
||||
ValidatorPrefs { commission: Perbill::zero(), blocked: false },
|
||||
);
|
||||
});
|
||||
|
||||
voters.into_iter().for_each(|(v, _s, t)| {
|
||||
voters.into_iter().for_each(|(v, s, t)| {
|
||||
let stake = <BalanceOf<T>>::try_from(s).unwrap_or_else(|_| {
|
||||
panic!("cannot convert a VoteWeight into BalanceOf, benchmark needs reconfiguring.")
|
||||
});
|
||||
<Bonded<T>>::insert(v.clone(), v.clone());
|
||||
<Ledger<T>>::insert(
|
||||
v.clone(),
|
||||
StakingLedger {
|
||||
stash: v.clone(),
|
||||
active: stake,
|
||||
total: stake,
|
||||
unlocking: vec![],
|
||||
claimed_rewards: vec![],
|
||||
},
|
||||
);
|
||||
<Nominators<T>>::insert(
|
||||
v,
|
||||
Nominations { targets: t, submitted_in: 0, suppressed: false },
|
||||
|
||||
@@ -37,7 +37,7 @@ use sp_runtime::{
|
||||
};
|
||||
use sp_staking::offence::{OffenceDetails, OnOffenceHandler};
|
||||
use std::{cell::RefCell, collections::HashSet};
|
||||
use sp_election_providers::onchain;
|
||||
use frame_election_provider_support::onchain;
|
||||
|
||||
pub const INIT_TIMESTAMP: u64 = 30_000;
|
||||
pub const BLOCK_TIME: u64 = 1000;
|
||||
@@ -243,6 +243,7 @@ impl OnUnbalanced<NegativeImbalanceOf<Test>> for RewardRemainderMock {
|
||||
impl onchain::Config for Test {
|
||||
type AccountId = AccountId;
|
||||
type BlockNumber = BlockNumber;
|
||||
type BlockWeights = BlockWeights;
|
||||
type Accuracy = Perbill;
|
||||
type DataProvider = Staking;
|
||||
}
|
||||
|
||||
@@ -521,6 +521,12 @@ mod test {
|
||||
fn kick(w: u32) -> Weight {
|
||||
unimplemented!()
|
||||
}
|
||||
fn get_npos_voters(v: u32, n: u32, s: u32) -> Weight {
|
||||
unimplemented!()
|
||||
}
|
||||
fn get_npos_targets(v: u32) -> Weight {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -112,10 +112,10 @@ pub fn create_validators<T: Config>(
|
||||
/// - `nominators`: number of bonded nominators.
|
||||
/// - `edge_per_nominator`: number of edge (vote) per nominator.
|
||||
/// - `randomize_stake`: whether to randomize the stakes.
|
||||
/// - `to_nominate`: if `Some(n)`, only the first `n` bonded validator are voted upon.
|
||||
/// Else, all of them are considered and `edge_per_nominator` random validators are voted for.
|
||||
/// - `to_nominate`: if `Some(n)`, only the first `n` bonded validator are voted upon. Else, all of
|
||||
/// them are considered and `edge_per_nominator` random validators are voted for.
|
||||
///
|
||||
/// Return the validators choosen to be nominated.
|
||||
/// Return the validators chosen to be nominated.
|
||||
pub fn create_validators_with_nominators_for_era<T: Config>(
|
||||
validators: u32,
|
||||
nominators: u32,
|
||||
|
||||
@@ -5019,12 +5019,14 @@ fn do_not_die_when_active_is_ed() {
|
||||
|
||||
mod election_data_provider {
|
||||
use super::*;
|
||||
use sp_election_providers::ElectionDataProvider;
|
||||
use frame_election_provider_support::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()
|
||||
assert!(<Validators<Test>>::iter().map(|(x, _)| x).all(|v| Staking::voters(None)
|
||||
.unwrap()
|
||||
.0
|
||||
.into_iter()
|
||||
.find(|(w, _, t)| { v == *w && t[0] == *w })
|
||||
.is_some()))
|
||||
@@ -5036,7 +5038,9 @@ mod election_data_provider {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]);
|
||||
assert_eq!(
|
||||
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters()
|
||||
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters(None)
|
||||
.unwrap()
|
||||
.0
|
||||
.iter()
|
||||
.find(|x| x.0 == 101)
|
||||
.unwrap()
|
||||
@@ -5050,7 +5054,9 @@ mod election_data_provider {
|
||||
// 11 is gone.
|
||||
start_active_era(2);
|
||||
assert_eq!(
|
||||
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters()
|
||||
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters(None)
|
||||
.unwrap()
|
||||
.0
|
||||
.iter()
|
||||
.find(|x| x.0 == 101)
|
||||
.unwrap()
|
||||
@@ -5061,7 +5067,9 @@ mod election_data_provider {
|
||||
// resubmit and it is back
|
||||
assert_ok!(Staking::nominate(Origin::signed(100), vec![11, 21]));
|
||||
assert_eq!(
|
||||
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters()
|
||||
<Staking as ElectionDataProvider<AccountId, BlockNumber>>::voters(None)
|
||||
.unwrap()
|
||||
.0
|
||||
.iter()
|
||||
.find(|x| x.0 == 101)
|
||||
.unwrap()
|
||||
@@ -5071,6 +5079,14 @@ mod election_data_provider {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn respects_len_limits() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
assert_eq!(Staking::voters(Some(1)).unwrap_err(), "Voter snapshot too big");
|
||||
assert_eq!(Staking::targets(Some(1)).unwrap_err(), "Target snapshot too big");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn estimate_next_election_works() {
|
||||
ExtBuilder::default().session_per_era(5).period(5).build().execute_with(|| {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! Autogenerated weights for pallet_staking
|
||||
//!
|
||||
//! 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: []
|
||||
//! DATE: 2021-03-14, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
|
||||
|
||||
// Executed Command:
|
||||
@@ -69,161 +69,163 @@ pub trait WeightInfo {
|
||||
fn reap_stash(s: u32, ) -> Weight;
|
||||
fn new_era(v: u32, n: u32, ) -> Weight;
|
||||
fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight;
|
||||
fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight;
|
||||
fn get_npos_targets(v: u32, ) -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for pallet_staking using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
fn bond() -> Weight {
|
||||
(81_642_000 as Weight)
|
||||
(80_317_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 {
|
||||
(66_025_000 as Weight)
|
||||
(64_495_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn unbond() -> Weight {
|
||||
(60_810_000 as Weight)
|
||||
(59_679_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 {
|
||||
(61_537_000 as Weight)
|
||||
(61_078_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((60_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add((40_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 {
|
||||
(95_741_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((2_754_000 as Weight).saturating_mul(s as Weight))
|
||||
(95_129_000 as Weight)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((2_755_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 {
|
||||
(21_009_000 as Weight)
|
||||
(20_608_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_832_000 as Weight)
|
||||
// Standard Error: 15_000
|
||||
.saturating_add((19_418_000 as Weight).saturating_mul(k as Weight))
|
||||
(33_365_000 as Weight)
|
||||
// Standard Error: 11_000
|
||||
.saturating_add((18_830_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 {
|
||||
(34_304_000 as Weight)
|
||||
// Standard Error: 20_000
|
||||
.saturating_add((5_643_000 as Weight).saturating_mul(n as Weight))
|
||||
(33_885_000 as Weight)
|
||||
// Standard Error: 22_000
|
||||
.saturating_add((5_562_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 {
|
||||
(20_103_000 as Weight)
|
||||
(19_741_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_858_000 as Weight)
|
||||
(13_674_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 {
|
||||
(30_269_000 as Weight)
|
||||
(29_691_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_444_000 as Weight)
|
||||
(2_375_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_no_eras() -> Weight {
|
||||
(2_766_000 as Weight)
|
||||
(2_601_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_new_era() -> Weight {
|
||||
(2_724_000 as Weight)
|
||||
(2_605_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_new_era_always() -> Weight {
|
||||
(2_702_000 as Weight)
|
||||
(2_584_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_invulnerables(v: u32, ) -> Weight {
|
||||
(2_914_000 as Weight)
|
||||
(2_725_000 as Weight)
|
||||
// Standard Error: 0
|
||||
.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 {
|
||||
(64_032_000 as Weight)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((2_787_000 as Weight).saturating_mul(s as Weight))
|
||||
(63_551_000 as Weight)
|
||||
// Standard Error: 7_000
|
||||
.saturating_add((2_844_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_903_394_000 as Weight)
|
||||
(5_905_400_000 as Weight)
|
||||
// Standard Error: 391_000
|
||||
.saturating_add((34_834_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add((34_785_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 {
|
||||
(141_724_000 as Weight)
|
||||
// Standard Error: 24_000
|
||||
.saturating_add((53_018_000 as Weight).saturating_mul(n as Weight))
|
||||
(142_264_000 as Weight)
|
||||
// Standard Error: 22_000
|
||||
.saturating_add((52_542_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 {
|
||||
(159_994_000 as Weight)
|
||||
// Standard Error: 28_000
|
||||
.saturating_add((67_746_000 as Weight).saturating_mul(n as Weight))
|
||||
(180_166_000 as Weight)
|
||||
// Standard Error: 23_000
|
||||
.saturating_add((66_767_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 {
|
||||
(42_177_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((82_000 as Weight).saturating_mul(l as Weight))
|
||||
(42_577_000 as Weight)
|
||||
// Standard Error: 12_000
|
||||
.saturating_add((60_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: 65_000
|
||||
.saturating_add((34_151_000 as Weight).saturating_mul(e as Weight))
|
||||
// Standard Error: 68_000
|
||||
.saturating_add((33_362_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 {
|
||||
(68_377_000 as Weight)
|
||||
// Standard Error: 0
|
||||
.saturating_add((2_757_000 as Weight).saturating_mul(s as Weight))
|
||||
(68_474_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((2_770_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: 908_000
|
||||
.saturating_add((588_562_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 903_000
|
||||
.saturating_add((594_145_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((83_373_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)))
|
||||
@@ -233,172 +235,191 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 52_000
|
||||
.saturating_add((750_000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add((1_460_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 20_000
|
||||
.saturating_add((556_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add((754_000 as Weight).saturating_mul(n as Weight))
|
||||
// Standard Error: 52_000
|
||||
.saturating_add((76_201_000 as Weight).saturating_mul(a as Weight))
|
||||
.saturating_add((74_798_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((8_108_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)))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 94_000
|
||||
.saturating_add((29_321_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 94_000
|
||||
.saturating_add((66_885_000 as Weight).saturating_mul(n as Weight))
|
||||
// Standard Error: 1_283_000
|
||||
.saturating_add((22_991_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 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)))
|
||||
}
|
||||
fn get_npos_targets(v: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 26_000
|
||||
.saturating_add((10_972_000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight)))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn bond() -> Weight {
|
||||
(81_642_000 as Weight)
|
||||
(80_317_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
fn bond_extra() -> Weight {
|
||||
(66_025_000 as Weight)
|
||||
(64_495_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn unbond() -> Weight {
|
||||
(60_810_000 as Weight)
|
||||
(59_679_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 {
|
||||
(61_537_000 as Weight)
|
||||
(61_078_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((60_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add((40_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 {
|
||||
(95_741_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((2_754_000 as Weight).saturating_mul(s as Weight))
|
||||
(95_129_000 as Weight)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((2_755_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 {
|
||||
(21_009_000 as Weight)
|
||||
(20_608_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_832_000 as Weight)
|
||||
// Standard Error: 15_000
|
||||
.saturating_add((19_418_000 as Weight).saturating_mul(k as Weight))
|
||||
(33_365_000 as Weight)
|
||||
// Standard Error: 11_000
|
||||
.saturating_add((18_830_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 {
|
||||
(34_304_000 as Weight)
|
||||
// Standard Error: 20_000
|
||||
.saturating_add((5_643_000 as Weight).saturating_mul(n as Weight))
|
||||
(33_885_000 as Weight)
|
||||
// Standard Error: 22_000
|
||||
.saturating_add((5_562_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 {
|
||||
(20_103_000 as Weight)
|
||||
(19_741_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn set_payee() -> Weight {
|
||||
(13_858_000 as Weight)
|
||||
(13_674_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_controller() -> Weight {
|
||||
(30_269_000 as Weight)
|
||||
(29_691_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_444_000 as Weight)
|
||||
(2_375_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_no_eras() -> Weight {
|
||||
(2_766_000 as Weight)
|
||||
(2_601_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_new_era() -> Weight {
|
||||
(2_724_000 as Weight)
|
||||
(2_605_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_new_era_always() -> Weight {
|
||||
(2_702_000 as Weight)
|
||||
(2_584_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_invulnerables(v: u32, ) -> Weight {
|
||||
(2_914_000 as Weight)
|
||||
(2_725_000 as Weight)
|
||||
// Standard Error: 0
|
||||
.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 {
|
||||
(64_032_000 as Weight)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((2_787_000 as Weight).saturating_mul(s as Weight))
|
||||
(63_551_000 as Weight)
|
||||
// Standard Error: 7_000
|
||||
.saturating_add((2_844_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_903_394_000 as Weight)
|
||||
(5_905_400_000 as Weight)
|
||||
// Standard Error: 391_000
|
||||
.saturating_add((34_834_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add((34_785_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 {
|
||||
(141_724_000 as Weight)
|
||||
// Standard Error: 24_000
|
||||
.saturating_add((53_018_000 as Weight).saturating_mul(n as Weight))
|
||||
(142_264_000 as Weight)
|
||||
// Standard Error: 22_000
|
||||
.saturating_add((52_542_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 {
|
||||
(159_994_000 as Weight)
|
||||
// Standard Error: 28_000
|
||||
.saturating_add((67_746_000 as Weight).saturating_mul(n as Weight))
|
||||
(180_166_000 as Weight)
|
||||
// Standard Error: 23_000
|
||||
.saturating_add((66_767_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 {
|
||||
(42_177_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((82_000 as Weight).saturating_mul(l as Weight))
|
||||
(42_577_000 as Weight)
|
||||
// Standard Error: 12_000
|
||||
.saturating_add((60_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: 65_000
|
||||
.saturating_add((34_151_000 as Weight).saturating_mul(e as Weight))
|
||||
// Standard Error: 68_000
|
||||
.saturating_add((33_362_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 {
|
||||
(68_377_000 as Weight)
|
||||
// Standard Error: 0
|
||||
.saturating_add((2_757_000 as Weight).saturating_mul(s as Weight))
|
||||
(68_474_000 as Weight)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add((2_770_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: 908_000
|
||||
.saturating_add((588_562_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 903_000
|
||||
.saturating_add((594_145_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((83_373_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)))
|
||||
@@ -408,16 +429,35 @@ impl WeightInfo for () {
|
||||
fn submit_solution_better(v: u32, n: u32, a: u32, w: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 52_000
|
||||
.saturating_add((750_000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add((1_460_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 20_000
|
||||
.saturating_add((556_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add((754_000 as Weight).saturating_mul(n as Weight))
|
||||
// Standard Error: 52_000
|
||||
.saturating_add((76_201_000 as Weight).saturating_mul(a as Weight))
|
||||
.saturating_add((74_798_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((8_108_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)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 94_000
|
||||
.saturating_add((29_321_000 as Weight).saturating_mul(v as Weight))
|
||||
// Standard Error: 94_000
|
||||
.saturating_add((66_885_000 as Weight).saturating_mul(n as Weight))
|
||||
// Standard Error: 1_283_000
|
||||
.saturating_add((22_991_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 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)))
|
||||
}
|
||||
fn get_npos_targets(v: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
// Standard Error: 26_000
|
||||
.saturating_add((10_972_000 as Weight).saturating_mul(v as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
//!
|
||||
//! To be able to use signing, the following trait should be implemented:
|
||||
//!
|
||||
//! - [`AppCrypto`](./trait.AppCrypto.html): where an application-specific key
|
||||
//! is defined and can be used by this module's helpers for signing.
|
||||
//! - [`CreateSignedTransaction`](./trait.CreateSignedTransaction.html): where
|
||||
//! the manner in which the transaction is constructed is defined.
|
||||
//! - [`AppCrypto`](./trait.AppCrypto.html): where an application-specific key is defined and can be
|
||||
//! used by this module's helpers for signing.
|
||||
//! - [`CreateSignedTransaction`](./trait.CreateSignedTransaction.html): where the manner in which
|
||||
//! the transaction is constructed is defined.
|
||||
//!
|
||||
//! #### Submit an unsigned transaction with a signed payload
|
||||
//!
|
||||
@@ -53,7 +53,6 @@
|
||||
//! #### Submit a signed transaction
|
||||
//!
|
||||
//! [`Signer`](./struct.Signer.html) can be used to sign/verify payloads
|
||||
//!
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
@@ -473,7 +472,7 @@ pub trait SendTransactionTypes<LocalCall> {
|
||||
/// The runtime's call type.
|
||||
///
|
||||
/// This has additional bound to be able to be created from pallet-local `Call` types.
|
||||
type OverarchingCall: From<LocalCall>;
|
||||
type OverarchingCall: From<LocalCall> + codec::Encode;
|
||||
}
|
||||
|
||||
/// Create signed transaction.
|
||||
|
||||
@@ -142,10 +142,22 @@ pub trait CompactSolution: Sized {
|
||||
const LIMIT: usize;
|
||||
|
||||
/// The voter type. Needs to be an index (convert to usize).
|
||||
type Voter: UniqueSaturatedInto<usize> + TryInto<usize> + TryFrom<usize> + Debug + Copy + Clone;
|
||||
type Voter: UniqueSaturatedInto<usize>
|
||||
+ TryInto<usize>
|
||||
+ TryFrom<usize>
|
||||
+ Debug
|
||||
+ Copy
|
||||
+ Clone
|
||||
+ Bounded;
|
||||
|
||||
/// The target type. Needs to be an index (convert to usize).
|
||||
type Target: UniqueSaturatedInto<usize> + TryInto<usize> + TryFrom<usize> + Debug + Copy + Clone;
|
||||
type Target: UniqueSaturatedInto<usize>
|
||||
+ TryInto<usize>
|
||||
+ TryFrom<usize>
|
||||
+ Debug
|
||||
+ Copy
|
||||
+ Clone
|
||||
+ Bounded;
|
||||
|
||||
/// The weight/accuracy type of each vote.
|
||||
type Accuracy: PerThing128;
|
||||
|
||||
Reference in New Issue
Block a user