Make the number of nominations configurable (#8368)

* 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

* It all works

* Some self cleanup

* Update frame/staking/src/lib.rs

Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>

* remove most todos.

* Round of self-review.

* Fix migration

* clean macro

* Revert wrong merge

* Make the number of nominations configurable

* Self reivew

* renmae.

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:
Kian Paimani
2021-03-25 10:15:28 +01:00
committed by GitHub
parent 1063fc7e35
commit f571023df3
17 changed files with 98 additions and 68 deletions
+39 -14
View File
@@ -204,16 +204,20 @@ benchmarks! {
kick {
// scenario: we want to kick `k` nominators from nominating us (we are a validator).
// we'll assume that `k` is under 128 for the purposes of determining the slope.
// each nominator should have `MAX_NOMINATIONS` validators nominated, and our validator
// each nominator should have `T::MAX_NOMINATIONS` validators nominated, and our validator
// should be somewhere in there.
let k in 1 .. 128;
// these are the other validators; there are `MAX_NOMINATIONS - 1` of them, so there are a
// total of `MAX_NOMINATIONS` validators in the system.
let rest_of_validators = create_validators::<T>(MAX_NOMINATIONS as u32 - 1, 100)?;
// these are the other validators; there are `T::MAX_NOMINATIONS - 1` of them, so
// there are a total of `T::MAX_NOMINATIONS` validators in the system.
let rest_of_validators = create_validators::<T>(T::MAX_NOMINATIONS - 1, 100)?;
// this is the validator that will be kicking.
let (stash, controller) = create_stash_controller::<T>(MAX_NOMINATIONS as u32 - 1, 100, Default::default())?;
let (stash, controller) = create_stash_controller::<T>(
T::MAX_NOMINATIONS - 1,
100,
Default::default(),
)?;
let stash_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(stash.clone());
// they start validating.
@@ -224,7 +228,11 @@ benchmarks! {
let mut nominator_stashes = Vec::with_capacity(k as usize);
for i in 0 .. k {
// create a nominator stash.
let (n_stash, n_controller) = create_stash_controller::<T>(MAX_NOMINATIONS as u32 + i, 100, Default::default())?;
let (n_stash, n_controller) = create_stash_controller::<T>(
T::MAX_NOMINATIONS + i,
100,
Default::default(),
)?;
// bake the nominations; we first clone them from the rest of the validators.
let mut nominations = rest_of_validators.clone();
@@ -256,9 +264,9 @@ benchmarks! {
}
}
// Worst case scenario, MAX_NOMINATIONS
// Worst case scenario, T::MAX_NOMINATIONS
nominate {
let n in 1 .. MAX_NOMINATIONS as u32;
let n in 1 .. T::MAX_NOMINATIONS;
let (stash, controller) = create_stash_controller::<T>(n + 1, 100, Default::default())?;
let validators = create_validators::<T>(n, 100)?;
whitelist_account!(controller);
@@ -467,7 +475,13 @@ benchmarks! {
let v in 1 .. 10;
let n in 1 .. 100;
create_validators_with_nominators_for_era::<T>(v, n, MAX_NOMINATIONS, false, None)?;
create_validators_with_nominators_for_era::<T>(
v,
n,
<T as Config>::MAX_NOMINATIONS as usize,
false,
None,
)?;
let session_index = SessionIndex::one();
}: {
let validators = Staking::<T>::new_era(session_index).ok_or("`new_era` failed")?;
@@ -478,7 +492,13 @@ benchmarks! {
payout_all {
let v in 1 .. 10;
let n in 1 .. 100;
create_validators_with_nominators_for_era::<T>(v, n, MAX_NOMINATIONS, false, None)?;
create_validators_with_nominators_for_era::<T>(
v,
n,
<T as Config>::MAX_NOMINATIONS as usize,
false,
None,
)?;
// Start a new Era
let new_validators = Staking::<T>::new_era(SessionIndex::one()).unwrap();
assert!(new_validators.len() == v as usize);
@@ -548,7 +568,7 @@ benchmarks! {
// 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)?
let validators = create_validators_with_nominators_for_era::<T>(v, n, T::MAX_NOMINATIONS as usize, false, None)?
.into_iter()
.map(|v| T::Lookup::lookup(v).unwrap())
.collect::<Vec<_>>();
@@ -567,7 +587,7 @@ benchmarks! {
// number of nominator intention.
let n = 500;
let _ = create_validators_with_nominators_for_era::<T>(v, n, MAX_NOMINATIONS, false, None)?;
let _ = create_validators_with_nominators_for_era::<T>(v, n, T::MAX_NOMINATIONS as usize, false, None)?;
}: {
let targets = <Staking<T>>::get_npos_targets();
assert_eq!(targets.len() as u32, v);
@@ -586,8 +606,13 @@ mod tests {
let v = 10;
let n = 100;
create_validators_with_nominators_for_era::<Test>(v, n, MAX_NOMINATIONS, false, None)
.unwrap();
create_validators_with_nominators_for_era::<Test>(
v,
n,
<Test as Config>::MAX_NOMINATIONS as usize,
false,
None,
).unwrap();
let count_validators = Validators::<Test>::iter().count();
let count_nominators = Nominators::<Test>::iter().count();
+11 -39
View File
@@ -284,8 +284,7 @@ use sp_std::{
result,
prelude::*,
collections::btree_map::BTreeMap,
convert::{TryInto, From},
mem::size_of,
convert::From,
};
use codec::{HasCompact, Encode, Decode};
use frame_support::{
@@ -303,7 +302,7 @@ use frame_support::{
};
use pallet_session::historical;
use sp_runtime::{
Percent, Perbill, PerU16, RuntimeDebug, DispatchError,
Percent, Perbill, RuntimeDebug, DispatchError,
curve::PiecewiseLinear,
traits::{
Convert, Zero, StaticLookup, CheckedSub, Saturating, SaturatedConversion,
@@ -337,22 +336,6 @@ macro_rules! log {
};
}
/// Data type used to index nominators in the compact type
pub type NominatorIndex = u32;
/// Data type used to index validators in the compact type.
pub type ValidatorIndex = u16;
// Ensure the size of both ValidatorIndex and NominatorIndex. They both need to be well below usize.
static_assertions::const_assert!(size_of::<ValidatorIndex>() <= size_of::<usize>());
static_assertions::const_assert!(size_of::<NominatorIndex>() <= size_of::<usize>());
static_assertions::const_assert!(size_of::<ValidatorIndex>() <= size_of::<u32>());
static_assertions::const_assert!(size_of::<NominatorIndex>() <= size_of::<u32>());
/// Maximum number of stakers that can be stored in a snapshot.
pub const MAX_NOMINATIONS: usize =
<CompactAssignments as sp_npos_elections::CompactSolution>::LIMIT;
pub const MAX_UNLOCKING_CHUNKS: usize = 32;
/// Counter for the number of eras that have passed.
@@ -361,15 +344,6 @@ pub type EraIndex = u32;
/// Counter for the number of "reward" points earned by a given validator.
pub type RewardPoint = u32;
// Note: Maximum nomination limit is set here -- 16.
sp_npos_elections::generate_solution_type!(
#[compact]
pub struct CompactAssignments::<NominatorIndex, ValidatorIndex, OffchainAccuracy>(16)
);
/// Accuracy used for off-chain election. This better be small.
pub type OffchainAccuracy = PerU16;
/// The balance type of this module.
pub type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
@@ -766,6 +740,9 @@ pub trait Config: frame_system::Config + SendTransactionTypes<Call<Self>> {
DataProvider = Module<Self>,
>;
/// Maximum number of nominations per nominator.
const MAX_NOMINATIONS: u32;
/// Tokens have been minted and are unused for validator-reward.
/// See [Era payout](./index.html#era-payout).
type RewardRemainder: OnUnbalanced<NegativeImbalanceOf<Self>>;
@@ -1213,6 +1190,9 @@ decl_module! {
/// their reward. This used to limit the i/o cost for the nominator payout.
const MaxNominatorRewardedPerValidator: u32 = T::MaxNominatorRewardedPerValidator::get();
/// Maximum number of nominations per nominator.
const MaxNominations: u32 = T::MAX_NOMINATIONS;
type Error = Error<T>;
fn deposit_event() = default;
@@ -1247,15 +1227,6 @@ decl_module! {
T::BondingDuration::get(),
)
);
use sp_runtime::UpperOf;
// 1. Maximum sum of Vec<OffchainAccuracy> must fit into `UpperOf<OffchainAccuracy>`.
assert!(
<usize as TryInto<UpperOf<OffchainAccuracy>>>::try_into(MAX_NOMINATIONS)
.unwrap()
.checked_mul(<OffchainAccuracy>::one().deconstruct().try_into().unwrap())
.is_some()
);
}
/// Take the origin account as a stash and lock up `value` of its balance. `controller` will
@@ -1547,7 +1518,7 @@ decl_module! {
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
let stash = &ledger.stash;
ensure!(!targets.is_empty(), Error::<T>::EmptyTargets);
ensure!(targets.len() <= MAX_NOMINATIONS, Error::<T>::TooManyTargets);
ensure!(targets.len() <= T::MAX_NOMINATIONS as usize, Error::<T>::TooManyTargets);
let old = Nominators::<T>::get(stash).map_or_else(Vec::new, |x| x.targets);
@@ -2313,7 +2284,7 @@ impl<T: Config> Module<T> {
/// Returns `Err(())` if less than [`MinimumValidatorCount`] validators have been elected, `Ok`
/// otherwise.
pub fn process_election(
flat_supports: sp_npos_elections::Supports<T::AccountId>,
flat_supports: frame_election_provider_support::Supports<T::AccountId>,
current_era: EraIndex,
) -> Result<Vec<T::AccountId>, ()> {
let exposures = Self::collect_exposures(flat_supports);
@@ -2554,6 +2525,7 @@ impl<T: Config> Module<T> {
impl<T: Config> frame_election_provider_support::ElectionDataProvider<T::AccountId, T::BlockNumber>
for Module<T>
{
const MAXIMUM_VOTES_PER_VOTER: u32 = T::MAX_NOMINATIONS;
fn desired_targets() -> data_provider::Result<(u32, Weight)> {
Ok((Self::validator_count(), <T as frame_system::Config>::DbWeight::get().reads(1)))
}
+1
View File
@@ -240,6 +240,7 @@ impl onchain::Config for Test {
type DataProvider = Staking;
}
impl Config for Test {
const MAX_NOMINATIONS: u32 = 16;
type Currency = Balances;
type UnixTime = Timestamp;
type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote;