mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 15:41:02 +00:00
Clean Phragmén Equlise API (#5452)
* Clean phragmen API and equalise() * Stabilize new api * Fix phragmen fuzzers * More fixes * Make fuzzers reproducible * improvements * Make equalize update assignments as well. * total function for staked_assignment. * Fix fuzzer build * remvoe TODO * Fix a bunch more. * clean stray debug stuff * Update primitives/phragmen/src/lib.rs Co-Authored-By: thiolliere <gui.thiolliere@gmail.com> * fix range function * fix number generator Co-authored-by: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
@@ -94,7 +94,7 @@ use frame_support::{
|
||||
ChangeMembers, OnUnbalanced, WithdrawReason, Contains, BalanceStatus, InitializeMembers,
|
||||
}
|
||||
};
|
||||
use sp_phragmen::{build_support_map, ExtendedBalance};
|
||||
use sp_phragmen::{build_support_map, ExtendedBalance, VoteWeight, PhragmenResult};
|
||||
use frame_system::{self as system, ensure_signed, ensure_root};
|
||||
|
||||
const MODULE_ID: LockIdentifier = *b"phrelect";
|
||||
@@ -123,7 +123,7 @@ pub trait Trait: frame_system::Trait {
|
||||
|
||||
/// Convert a balance into a number used for election calculation.
|
||||
/// This must fit into a `u64` but is allowed to be sensibly lossy.
|
||||
type CurrencyToVote: Convert<BalanceOf<Self>, u64> + Convert<u128, BalanceOf<Self>>;
|
||||
type CurrencyToVote: Convert<BalanceOf<Self>, VoteWeight> + Convert<ExtendedBalance, BalanceOf<Self>>;
|
||||
|
||||
/// How much should be locked up in order to submit one's candidacy.
|
||||
type CandidacyBond: Get<BalanceOf<Self>>;
|
||||
@@ -703,17 +703,28 @@ impl<T: Trait> Module<T> {
|
||||
// previous runners_up are also always candidates for the next round.
|
||||
candidates.append(&mut Self::runners_up_ids());
|
||||
|
||||
// helper closures to deal with balance/stake.
|
||||
let to_votes = |b: BalanceOf<T>| -> VoteWeight {
|
||||
<T::CurrencyToVote as Convert<BalanceOf<T>, VoteWeight>>::convert(b)
|
||||
};
|
||||
let to_balance = |e: ExtendedBalance| -> BalanceOf<T> {
|
||||
<T::CurrencyToVote as Convert<ExtendedBalance, BalanceOf<T>>>::convert(e)
|
||||
};
|
||||
let stake_of = |who: &T::AccountId| -> VoteWeight {
|
||||
to_votes(Self::locked_stake_of(who))
|
||||
};
|
||||
|
||||
let voters_and_votes = Voting::<T>::iter()
|
||||
.map(|(voter, (stake, targets))| { (voter, stake, targets) })
|
||||
.map(|(voter, (stake, targets))| { (voter, to_votes(stake), targets) })
|
||||
.collect::<Vec<_>>();
|
||||
let maybe_phragmen_result = sp_phragmen::elect::<_, _, T::CurrencyToVote, Perbill>(
|
||||
let maybe_phragmen_result = sp_phragmen::elect::<T::AccountId, Perbill>(
|
||||
num_to_elect,
|
||||
0,
|
||||
candidates,
|
||||
voters_and_votes.clone(),
|
||||
);
|
||||
|
||||
if let Some(phragmen_result) = maybe_phragmen_result {
|
||||
if let Some(PhragmenResult { winners, assignments }) = maybe_phragmen_result {
|
||||
let old_members_ids = <Members<T>>::take().into_iter()
|
||||
.map(|(m, _)| m)
|
||||
.collect::<Vec<T::AccountId>>();
|
||||
@@ -726,26 +737,19 @@ impl<T: Trait> Module<T> {
|
||||
// vote are still considered by phragmen and when good candidates are scarce, then these
|
||||
// cheap ones might get elected. We might actually want to remove the filter and allow
|
||||
// zero-voted candidates to also make it to the membership set.
|
||||
let new_set_with_approval = phragmen_result.winners;
|
||||
let new_set_with_approval = winners;
|
||||
let new_set = new_set_with_approval
|
||||
.into_iter()
|
||||
.filter_map(|(m, a)| if a.is_zero() { None } else { Some(m) } )
|
||||
.collect::<Vec<T::AccountId>>();
|
||||
|
||||
let stake_of = |who: &T::AccountId| -> ExtendedBalance {
|
||||
<T::CurrencyToVote as Convert<BalanceOf<T>, u64>>::convert(
|
||||
Self::locked_stake_of(who)
|
||||
) as ExtendedBalance
|
||||
};
|
||||
let staked_assignments = sp_phragmen::assignment_ratio_to_staked(
|
||||
phragmen_result.assignments,
|
||||
assignments,
|
||||
stake_of,
|
||||
);
|
||||
|
||||
let (support_map, _) = build_support_map::<T::AccountId>(&new_set, &staked_assignments);
|
||||
|
||||
let to_balance = |e: ExtendedBalance|
|
||||
<T::CurrencyToVote as Convert<ExtendedBalance, BalanceOf<T>>>::convert(e);
|
||||
let new_set_with_stake = new_set
|
||||
.into_iter()
|
||||
.map(|ref m| {
|
||||
@@ -766,14 +770,14 @@ impl<T: Trait> Module<T> {
|
||||
// save the members, sorted based on account id.
|
||||
new_members.sort_by(|i, j| i.0.cmp(&j.0));
|
||||
|
||||
let mut prime_votes: Vec<_> = new_members.iter().map(|c| (&c.0, BalanceOf::<T>::zero())).collect();
|
||||
let mut prime_votes: Vec<_> = new_members.iter().map(|c| (&c.0, VoteWeight::zero())).collect();
|
||||
for (_, stake, targets) in voters_and_votes.into_iter() {
|
||||
for (votes, who) in targets.iter()
|
||||
.enumerate()
|
||||
.map(|(votes, who)| ((MAXIMUM_VOTE - votes) as u32, who))
|
||||
{
|
||||
if let Ok(i) = prime_votes.binary_search_by_key(&who, |k| k.0) {
|
||||
prime_votes[i].1 += stake * votes.into();
|
||||
prime_votes[i].1 += stake * votes as VoteWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ use frame_system::{
|
||||
};
|
||||
use sp_phragmen::{
|
||||
ExtendedBalance, Assignment, PhragmenScore, PhragmenResult, build_support_map, evaluate_support,
|
||||
elect, generate_compact_solution_type, is_score_better, VotingLimit, SupportMap,
|
||||
elect, generate_compact_solution_type, is_score_better, VotingLimit, SupportMap, VoteWeight,
|
||||
};
|
||||
|
||||
const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4;
|
||||
@@ -737,12 +737,11 @@ pub trait Trait: frame_system::Trait {
|
||||
/// is not used.
|
||||
type UnixTime: UnixTime;
|
||||
|
||||
/// Convert a balance into a number used for election calculation.
|
||||
/// This must fit into a `u64` but is allowed to be sensibly lossy.
|
||||
/// TODO: #1377
|
||||
/// The backward convert should be removed as the new Phragmen API returns ratio.
|
||||
/// The post-processing needs it but will be moved to off-chain. TODO: #2908
|
||||
type CurrencyToVote: Convert<BalanceOf<Self>, u64> + Convert<u128, BalanceOf<Self>>;
|
||||
/// Convert a balance into a number used for election calculation. This must fit into a `u64`
|
||||
/// but is allowed to be sensibly lossy. The `u64` is used to communicate with the
|
||||
/// [`sp_phragmen`] crate which accepts u64 numbers and does operations in 128. Consequently,
|
||||
/// the backward convert is used convert the u128s from phragmen back to a [`BalanceOf`].
|
||||
type CurrencyToVote: Convert<BalanceOf<Self>, VoteWeight> + Convert<u128, BalanceOf<Self>>;
|
||||
|
||||
/// Tokens have been minted and are unused for validator-reward.
|
||||
type RewardRemainder: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
@@ -1853,7 +1852,7 @@ decl_module! {
|
||||
/// - Memory: O(n + m) reads to map index to `AccountId` for un-compact.
|
||||
///
|
||||
/// - Storage: O(e) accountid reads from `Nomination` to read correct nominations.
|
||||
/// - Storage: O(e) calls into `slashable_balance_of_extended` to convert ratio to staked.
|
||||
/// - Storage: O(e) calls into `slashable_balance_of_vote_weight` to convert ratio to staked.
|
||||
///
|
||||
/// - Memory: build_support_map. O(e).
|
||||
/// - Memory: evaluate_support: O(E).
|
||||
@@ -1953,11 +1952,11 @@ impl<T: Trait> Module<T> {
|
||||
Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// internal impl of [`slashable_balance_of`] that returns [`ExtendedBalance`].
|
||||
fn slashable_balance_of_extended(stash: &T::AccountId) -> ExtendedBalance {
|
||||
<T::CurrencyToVote as Convert<BalanceOf<T>, u64>>::convert(
|
||||
/// internal impl of [`slashable_balance_of`] that returns [`VoteWeight`].
|
||||
fn slashable_balance_of_vote_weight(stash: &T::AccountId) -> VoteWeight {
|
||||
<T::CurrencyToVote as Convert<BalanceOf<T>, VoteWeight>>::convert(
|
||||
Self::slashable_balance_of(stash)
|
||||
) as ExtendedBalance
|
||||
)
|
||||
}
|
||||
|
||||
/// Dump the list of validators and nominators into vectors and keep them on-chain.
|
||||
@@ -2456,7 +2455,7 @@ impl<T: Trait> Module<T> {
|
||||
// convert into staked assignments.
|
||||
let staked_assignments = sp_phragmen::assignment_ratio_to_staked(
|
||||
assignments,
|
||||
Self::slashable_balance_of_extended,
|
||||
Self::slashable_balance_of_vote_weight,
|
||||
);
|
||||
|
||||
// build the support map thereof in order to evaluate.
|
||||
@@ -2711,7 +2710,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
let staked_assignments = sp_phragmen::assignment_ratio_to_staked(
|
||||
assignments,
|
||||
Self::slashable_balance_of_extended,
|
||||
Self::slashable_balance_of_vote_weight,
|
||||
);
|
||||
|
||||
let (supports, _) = build_support_map::<T::AccountId>(
|
||||
@@ -2747,11 +2746,11 @@ impl<T: Trait> Module<T> {
|
||||
///
|
||||
/// No storage item is updated.
|
||||
fn do_phragmen<Accuracy: PerThing>() -> Option<PhragmenResult<T::AccountId, Accuracy>> {
|
||||
let mut all_nominators: Vec<(T::AccountId, BalanceOf<T>, Vec<T::AccountId>)> = Vec::new();
|
||||
let mut all_nominators: Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> = Vec::new();
|
||||
let mut all_validators = Vec::new();
|
||||
for (validator, _) in <Validators<T>>::iter() {
|
||||
// append self vote
|
||||
let self_vote = (validator.clone(), Self::slashable_balance_of(&validator), vec![validator.clone()]);
|
||||
let self_vote = (validator.clone(), Self::slashable_balance_of_vote_weight(&validator), vec![validator.clone()]);
|
||||
all_nominators.push(self_vote);
|
||||
all_validators.push(validator);
|
||||
}
|
||||
@@ -2771,11 +2770,11 @@ impl<T: Trait> Module<T> {
|
||||
(nominator, targets)
|
||||
});
|
||||
all_nominators.extend(nominator_votes.map(|(n, ns)| {
|
||||
let s = Self::slashable_balance_of(&n);
|
||||
let s = Self::slashable_balance_of_vote_weight(&n);
|
||||
(n, s, ns)
|
||||
}));
|
||||
|
||||
elect::<_, _, T::CurrencyToVote, Accuracy>(
|
||||
elect::<_, Accuracy>(
|
||||
Self::validator_count() as usize,
|
||||
Self::minimum_validator_count().max(1) as usize,
|
||||
all_validators,
|
||||
|
||||
@@ -33,6 +33,7 @@ use frame_system::offchain::TransactionSubmitter;
|
||||
use sp_io;
|
||||
use sp_phragmen::{
|
||||
build_support_map, evaluate_support, reduce, ExtendedBalance, StakedAssignment, PhragmenScore,
|
||||
VoteWeight,
|
||||
};
|
||||
use crate::*;
|
||||
|
||||
@@ -846,10 +847,10 @@ pub(crate) fn prepare_submission_with(
|
||||
} = Staking::do_phragmen::<OffchainAccuracy>().unwrap();
|
||||
let winners = winners.into_iter().map(|(w, _)| w).collect::<Vec<AccountId>>();
|
||||
|
||||
let stake_of = |who: &AccountId| -> ExtendedBalance {
|
||||
<CurrencyToVoteHandler as Convert<Balance, u64>>::convert(
|
||||
let stake_of = |who: &AccountId| -> VoteWeight {
|
||||
<CurrencyToVoteHandler as Convert<Balance, VoteWeight>>::convert(
|
||||
Staking::slashable_balance_of(&who)
|
||||
) as ExtendedBalance
|
||||
)
|
||||
};
|
||||
let mut staked = sp_phragmen::assignment_ratio_to_staked(assignments, stake_of);
|
||||
|
||||
@@ -888,7 +889,7 @@ pub(crate) fn prepare_submission_with(
|
||||
let score = {
|
||||
let staked = sp_phragmen::assignment_ratio_to_staked(
|
||||
assignments_reduced.clone(),
|
||||
Staking::slashable_balance_of_extended,
|
||||
Staking::slashable_balance_of_vote_weight,
|
||||
);
|
||||
|
||||
let (support_map, _) = build_support_map::<AccountId>(
|
||||
|
||||
@@ -167,7 +167,7 @@ pub fn prepare_submission<T: Trait>(
|
||||
// convert into absolute value and to obtain the reduced version.
|
||||
let mut staked = sp_phragmen::assignment_ratio_to_staked(
|
||||
assignments,
|
||||
<Module<T>>::slashable_balance_of_extended,
|
||||
<Module<T>>::slashable_balance_of_vote_weight,
|
||||
);
|
||||
|
||||
if do_reduce {
|
||||
@@ -188,7 +188,7 @@ pub fn prepare_submission<T: Trait>(
|
||||
let score = {
|
||||
let staked = sp_phragmen::assignment_ratio_to_staked(
|
||||
low_accuracy_assignment.clone(),
|
||||
<Module<T>>::slashable_balance_of_extended,
|
||||
<Module<T>>::slashable_balance_of_vote_weight,
|
||||
);
|
||||
|
||||
let (support_map, _) = build_support_map::<T::AccountId>(&winners, &staked);
|
||||
|
||||
Reference in New Issue
Block a user