PhragMMS election. (#6685)

* Revamp npos-elections and implement phragmms

* Update primitives/npos-elections/src/phragmms.rs

* Fix build

* Some review grumbles

* Add some stuff for remote testing

* fix some of the grumbles.

* Add remote testing stuff.

* Cleanup

* fix docs

* Update primitives/arithmetic/src/rational.rs

Co-authored-by: Dan Forbes <dan@danforbes.dev>

* Small config change

* Better handling of approval_stake == 0

* Final touhces.

* Clean fuzzer a bit

* Clean fuzzer a bit

* Update primitives/npos-elections/src/balancing.rs

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* Fix fuzzer.

* Better api for normalize

* Add noramlize_up

* A large number of small fixes.

* make it merge ready

* Fix warns

* bump

* Fix fuzzers a bit.

* Fix warns as well.

* Fix more tests.

Co-authored-by: Dan Forbes <dan@danforbes.dev>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Kian Paimani
2020-09-23 10:16:10 +02:00
committed by GitHub
parent ecdc94420e
commit 313f86ec23
32 changed files with 2074 additions and 914 deletions
+20 -27
View File
@@ -33,7 +33,6 @@ use frame_support::{
use sp_io;
use sp_npos_elections::{
build_support_map, evaluate_support, reduce, ExtendedBalance, StakedAssignment, ElectionScore,
VoteWeight,
};
use crate::*;
@@ -198,6 +197,7 @@ parameter_types! {
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
pub const MaxLocks: u32 = 1024;
}
impl frame_system::Trait for Test {
type BaseCallFilter = ();
@@ -227,7 +227,7 @@ impl frame_system::Trait for Test {
type SystemWeightInfo = ();
}
impl pallet_balances::Trait for Test {
type MaxLocks = ();
type MaxLocks = MaxLocks;
type Balance = Balance;
type Event = MetaEvent;
type DustRemoval = ();
@@ -857,9 +857,9 @@ pub(crate) fn horrible_npos_solution(
// Ensure that this result is worse than seq-phragmen. Otherwise, it should not have been used
// for testing.
let score = {
let (_, _, better_score) = prepare_submission_with(true, 0, |_| {});
let (_, _, better_score) = prepare_submission_with(true, true, 0, |_| {});
let support = build_support_map::<AccountId>(&winners, &staked_assignment).0;
let support = build_support_map::<AccountId>(&winners, &staked_assignment).unwrap();
let score = evaluate_support(&support);
assert!(sp_npos_elections::is_score_better::<Perbill>(
@@ -898,9 +898,13 @@ pub(crate) fn horrible_npos_solution(
(compact, winners, score)
}
// Note: this should always logically reproduce [`offchain_election::prepare_submission`], yet we
// cannot do it since we want to have `tweak` injected into the process.
/// Note: this should always logically reproduce [`offchain_election::prepare_submission`], yet we
/// cannot do it since we want to have `tweak` injected into the process.
///
/// If the input is being tweaked in a way that the score cannot be compute accurately,
/// `compute_real_score` can be set to true. In this case a `Default` score is returned.
pub(crate) fn prepare_submission_with(
compute_real_score: bool,
do_reduce: bool,
iterations: usize,
tweak: impl FnOnce(&mut Vec<StakedAssignment<AccountId>>),
@@ -909,26 +913,13 @@ pub(crate) fn prepare_submission_with(
let sp_npos_elections::ElectionResult {
winners,
assignments,
} = Staking::do_phragmen::<OffchainAccuracy>().unwrap();
} = Staking::do_phragmen::<OffchainAccuracy>(iterations).unwrap();
let winners = sp_npos_elections::to_without_backing(winners);
let stake_of = |who: &AccountId| -> VoteWeight {
<CurrencyToVoteHandler as Convert<Balance, VoteWeight>>::convert(
Staking::slashable_balance_of(&who)
)
};
let mut staked = sp_npos_elections::assignment_ratio_to_staked(assignments, stake_of);
let (mut support_map, _) = build_support_map::<AccountId>(&winners, &staked);
if iterations > 0 {
sp_npos_elections::balance_solution(
&mut staked,
&mut support_map,
Zero::zero(),
iterations,
);
}
let mut staked = sp_npos_elections::assignment_ratio_to_staked(
assignments,
Staking::slashable_balance_of_vote_weight,
);
// apply custom tweaks. awesome for testing.
tweak(&mut staked);
@@ -962,17 +953,19 @@ pub(crate) fn prepare_submission_with(
let assignments_reduced = sp_npos_elections::assignment_staked_to_ratio(staked);
// re-compute score by converting, yet again, into staked type
let score = {
let score = if compute_real_score {
let staked = sp_npos_elections::assignment_ratio_to_staked(
assignments_reduced.clone(),
Staking::slashable_balance_of_vote_weight,
);
let (support_map, _) = build_support_map::<AccountId>(
let support_map = build_support_map::<AccountId>(
winners.as_slice(),
staked.as_slice(),
);
).unwrap();
evaluate_support::<AccountId>(&support_map)
} else {
Default::default()
};
let compact =