Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 4ac74e9

Browse files
authored
Decouple Stkaing and Election - Part1: Support traits (#7908)
* Base features and traits. * Fix the build * Remove unused boxing * Self review cleanup * Fix build
1 parent d42240b commit 4ac74e9

File tree

23 files changed

+921
-337
lines changed

23 files changed

+921
-337
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ members = [
139139
"primitives/database",
140140
"primitives/debug-derive",
141141
"primitives/externalities",
142+
"primitives/election-providers",
142143
"primitives/finality-grandpa",
143144
"primitives/inherents",
144145
"primitives/io",

frame/staking/src/benchmarking.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use super::*;
2121
use crate::Module as Staking;
2222
use testing_utils::*;
2323

24+
use sp_npos_elections::CompactSolution;
2425
use sp_runtime::traits::One;
2526
use frame_system::RawOrigin;
2627
pub use frame_benchmarking::{benchmarks, account, whitelisted_caller, whitelist_account};

frame/staking/src/lib.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,11 @@
232232
//!
233233
//! The controller account can free a portion (or all) of the funds using the
234234
//! [`unbond`](enum.Call.html#variant.unbond) call. Note that the funds are not immediately
235-
//! accessible. Instead, a duration denoted by [`BondingDuration`](./trait.Config.html#associatedtype.BondingDuration)
236-
//! (in number of eras) must pass until the funds can actually be removed. Once the
237-
//! `BondingDuration` is over, the [`withdraw_unbonded`](./enum.Call.html#variant.withdraw_unbonded)
238-
//! call can be used to actually withdraw the funds.
235+
//! accessible. Instead, a duration denoted by
236+
//! [`BondingDuration`](./trait.Config.html#associatedtype.BondingDuration) (in number of eras) must
237+
//! pass until the funds can actually be removed. Once the `BondingDuration` is over, the
238+
//! [`withdraw_unbonded`](./enum.Call.html#variant.withdraw_unbonded) call can be used to actually
239+
//! withdraw the funds.
239240
//!
240241
//! Note that there is a limitation to the number of fund-chunks that can be scheduled to be
241242
//! unlocked in the future via [`unbond`](enum.Call.html#variant.unbond). In case this maximum
@@ -304,7 +305,7 @@ use frame_support::{
304305
};
305306
use pallet_session::historical;
306307
use sp_runtime::{
307-
Percent, Perbill, PerU16, PerThing, InnerOf, RuntimeDebug, DispatchError,
308+
Percent, Perbill, PerU16, InnerOf, RuntimeDebug, DispatchError,
308309
curve::PiecewiseLinear,
309310
traits::{
310311
Convert, Zero, StaticLookup, CheckedSub, Saturating, SaturatedConversion,
@@ -327,14 +328,14 @@ use frame_system::{
327328
};
328329
use sp_npos_elections::{
329330
ExtendedBalance, Assignment, ElectionScore, ElectionResult as PrimitiveElectionResult,
330-
build_support_map, evaluate_support, seq_phragmen, generate_solution_type,
331-
is_score_better, VotingLimit, SupportMap, VoteWeight,
331+
to_support_map, EvaluateSupport, seq_phragmen, generate_solution_type, is_score_better,
332+
SupportMap, VoteWeight, CompactSolution, PerThing128,
332333
};
333334
pub use weights::WeightInfo;
334335

335336
const STAKING_ID: LockIdentifier = *b"staking ";
336337
pub const MAX_UNLOCKING_CHUNKS: usize = 32;
337-
pub const MAX_NOMINATIONS: usize = <CompactAssignments as VotingLimit>::LIMIT;
338+
pub const MAX_NOMINATIONS: usize = <CompactAssignments as CompactSolution>::LIMIT;
338339

339340
pub(crate) const LOG_TARGET: &'static str = "staking";
340341

@@ -2105,7 +2106,7 @@ decl_module! {
21052106
#[weight = T::WeightInfo::submit_solution_better(
21062107
size.validators.into(),
21072108
size.nominators.into(),
2108-
compact.len() as u32,
2109+
compact.voter_count() as u32,
21092110
winners.len() as u32,
21102111
)]
21112112
pub fn submit_election_solution(
@@ -2139,7 +2140,7 @@ decl_module! {
21392140
#[weight = T::WeightInfo::submit_solution_better(
21402141
size.validators.into(),
21412142
size.nominators.into(),
2142-
compact.len() as u32,
2143+
compact.voter_count() as u32,
21432144
winners.len() as u32,
21442145
)]
21452146
pub fn submit_election_solution_unsigned(
@@ -2601,13 +2602,11 @@ impl<T: Config> Module<T> {
26012602
);
26022603

26032604
// build the support map thereof in order to evaluate.
2604-
let supports = build_support_map::<T::AccountId>(
2605-
&winners,
2606-
&staked_assignments,
2607-
).map_err(|_| Error::<T>::OffchainElectionBogusEdge)?;
2605+
let supports = to_support_map::<T::AccountId>(&winners, &staked_assignments)
2606+
.map_err(|_| Error::<T>::OffchainElectionBogusEdge)?;
26082607

26092608
// Check if the score is the same as the claimed one.
2610-
let submitted_score = evaluate_support(&supports);
2609+
let submitted_score = (&supports).evaluate();
26112610
ensure!(submitted_score == claimed_score, Error::<T>::OffchainElectionBogusScore);
26122611

26132612
// At last, alles Ok. Exposures and store the result.
@@ -2863,7 +2862,7 @@ impl<T: Config> Module<T> {
28632862
Self::slashable_balance_of_fn(),
28642863
);
28652864

2866-
let supports = build_support_map::<T::AccountId>(
2865+
let supports = to_support_map::<T::AccountId>(
28672866
&elected_stashes,
28682867
&staked_assignments,
28692868
)
@@ -2902,7 +2901,7 @@ impl<T: Config> Module<T> {
29022901
/// Self votes are added and nominations before the most recent slashing span are ignored.
29032902
///
29042903
/// No storage item is updated.
2905-
pub fn do_phragmen<Accuracy: PerThing>(
2904+
pub fn do_phragmen<Accuracy: PerThing128>(
29062905
iterations: usize,
29072906
) -> Option<PrimitiveElectionResult<T::AccountId, Accuracy>>
29082907
where
@@ -2952,7 +2951,7 @@ impl<T: Config> Module<T> {
29522951
all_nominators,
29532952
Some((iterations, 0)), // exactly run `iterations` rounds.
29542953
)
2955-
.map_err(|err| log!(error, "Call to seq-phragmen failed due to {}", err))
2954+
.map_err(|err| log!(error, "Call to seq-phragmen failed due to {:?}", err))
29562955
.ok()
29572956
}
29582957
}

frame/staking/src/mock.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use frame_support::{
2727
use sp_core::H256;
2828
use sp_io;
2929
use sp_npos_elections::{
30-
build_support_map, evaluate_support, reduce, ExtendedBalance, StakedAssignment, ElectionScore,
30+
to_support_map, EvaluateSupport, reduce, ExtendedBalance, StakedAssignment, ElectionScore,
3131
};
3232
use sp_runtime::{
3333
curve::PiecewiseLinear,
@@ -860,8 +860,8 @@ pub(crate) fn horrible_npos_solution(
860860
let score = {
861861
let (_, _, better_score) = prepare_submission_with(true, true, 0, |_| {});
862862

863-
let support = build_support_map::<AccountId>(&winners, &staked_assignment).unwrap();
864-
let score = evaluate_support(&support);
863+
let support = to_support_map::<AccountId>(&winners, &staked_assignment).unwrap();
864+
let score = support.evaluate();
865865

866866
assert!(sp_npos_elections::is_score_better::<Perbill>(
867867
better_score,
@@ -960,11 +960,11 @@ pub(crate) fn prepare_submission_with(
960960
Staking::slashable_balance_of_fn(),
961961
);
962962

963-
let support_map = build_support_map::<AccountId>(
963+
let support_map = to_support_map::<AccountId>(
964964
winners.as_slice(),
965965
staked.as_slice(),
966966
).unwrap();
967-
evaluate_support::<AccountId>(&support_map)
967+
support_map.evaluate()
968968
} else {
969969
Default::default()
970970
};

frame/staking/src/offchain_election.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use codec::Decode;
2525
use frame_support::{traits::Get, weights::Weight, IterableStorageMap};
2626
use frame_system::offchain::SubmitTransaction;
2727
use sp_npos_elections::{
28-
build_support_map, evaluate_support, reduce, Assignment, ElectionResult, ElectionScore,
29-
ExtendedBalance,
28+
to_support_map, EvaluateSupport, reduce, Assignment, ElectionResult, ElectionScore,
29+
ExtendedBalance, CompactSolution,
3030
};
3131
use sp_runtime::{
3232
offchain::storage::StorageValueRef, traits::TrailingZeroInput, PerThing, RuntimeDebug,
@@ -265,7 +265,7 @@ pub fn trim_to_weight<T: Config, FN>(
265265
where
266266
for<'r> FN: Fn(&'r T::AccountId) -> Option<NominatorIndex>,
267267
{
268-
match compact.len().checked_sub(maximum_allowed_voters as usize) {
268+
match compact.voter_count().checked_sub(maximum_allowed_voters as usize) {
269269
Some(to_remove) if to_remove > 0 => {
270270
// grab all voters and sort them by least stake.
271271
let balance_of = <Module<T>>::slashable_balance_of_fn();
@@ -300,7 +300,7 @@ where
300300
warn,
301301
"💸 {} nominators out of {} had to be removed from compact solution due to size limits.",
302302
removed,
303-
compact.len() + removed,
303+
compact.voter_count() + removed,
304304
);
305305
Ok(compact)
306306
}
@@ -324,12 +324,7 @@ pub fn prepare_submission<T: Config>(
324324
do_reduce: bool,
325325
maximum_weight: Weight,
326326
) -> Result<
327-
(
328-
Vec<ValidatorIndex>,
329-
CompactAssignments,
330-
ElectionScore,
331-
ElectionSize,
332-
),
327+
(Vec<ValidatorIndex>, CompactAssignments, ElectionScore, ElectionSize),
333328
OffchainElectionError,
334329
>
335330
where
@@ -403,11 +398,11 @@ where
403398
T::WeightInfo::submit_solution_better(
404399
size.validators.into(),
405400
size.nominators.into(),
406-
compact.len() as u32,
401+
compact.voter_count() as u32,
407402
winners.len() as u32,
408403
),
409404
maximum_allowed_voters,
410-
compact.len(),
405+
compact.voter_count(),
411406
);
412407

413408
let compact = trim_to_weight::<T, _>(maximum_allowed_voters, compact, &nominator_index)?;
@@ -423,9 +418,9 @@ where
423418
<Module<T>>::slashable_balance_of_fn(),
424419
);
425420

426-
let support_map = build_support_map::<T::AccountId>(&winners, &staked)
421+
let support_map = to_support_map::<T::AccountId>(&winners, &staked)
427422
.map_err(|_| OffchainElectionError::ElectionFailed)?;
428-
evaluate_support::<T::AccountId>(&support_map)
423+
support_map.evaluate()
429424
};
430425

431426
// winners to index. Use a simple for loop for a more expressive early exit in case of error.

frame/staking/src/testing_utils.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,9 @@ pub fn get_weak_solution<T: Config>(
244244
<Module<T>>::slashable_balance_of_fn(),
245245
);
246246

247-
let support_map = build_support_map::<T::AccountId>(
248-
winners.as_slice(),
249-
staked.as_slice(),
250-
).unwrap();
251-
evaluate_support::<T::AccountId>(&support_map)
247+
let support_map =
248+
to_support_map::<T::AccountId>(winners.as_slice(), staked.as_slice()).unwrap();
249+
support_map.evaluate()
252250
};
253251

254252
// compact encode the assignment.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[package]
2+
name = "sp-election-providers"
3+
version = "2.0.0"
4+
authors = ["Parity Technologies <[email protected]>"]
5+
edition = "2018"
6+
license = "Apache-2.0"
7+
homepage = "https://substrate.dev"
8+
repository = "https://github.com/paritytech/substrate/"
9+
description = "Primitive election providers"
10+
readme = "README.md"
11+
12+
[package.metadata.docs.rs]
13+
targets = ["x86_64-unknown-linux-gnu"]
14+
15+
[dependencies]
16+
codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
17+
sp-std = { version = "2.0.1", default-features = false, path = "../std" }
18+
sp-arithmetic = { version = "2.0.1", default-features = false, path = "../arithmetic" }
19+
sp-npos-elections = { version = "2.0.1", default-features = false, path = "../npos-elections" }
20+
21+
[dev-dependencies]
22+
sp-npos-elections = { version = "2.0.1", path = "../npos-elections" }
23+
sp-runtime = { version = "2.0.1", path = "../runtime" }
24+
25+
[features]
26+
default = ["std"]
27+
runtime-benchmarks = []
28+
std = [
29+
"codec/std",
30+
"sp-std/std",
31+
"sp-npos-elections/std",
32+
"sp-arithmetic/std",
33+
]

0 commit comments

Comments
 (0)