Skip to content

Commit b684a61

Browse files
kianenigmagui1117
andauthored
Refactor CurrencyToVote (#6896)
* Refactor CurrencyToVote to avoid calls to total_issuance. * Update frame/support/src/traits.rs Co-authored-by: Guillaume Thiolliere <[email protected]> * Some grumbles * Fix last grumbles. * Fix comment * Final fix Co-authored-by: Guillaume Thiolliere <[email protected]>
1 parent a71af25 commit b684a61

File tree

5 files changed

+47
-76
lines changed

5 files changed

+47
-76
lines changed

fuzzer/src/mock.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
//! Mock file for staking fuzzing.
1919
20-
use sp_runtime::traits::{Convert, SaturatedConversion};
2120
use frame_support::{impl_outer_origin, impl_outer_dispatch, parameter_types};
2221

2322
type AccountId = u64;
@@ -41,18 +40,6 @@ impl_outer_dispatch! {
4140
}
4241
}
4342

44-
pub struct CurrencyToVoteHandler;
45-
impl Convert<u64, u64> for CurrencyToVoteHandler {
46-
fn convert(x: u64) -> u64 {
47-
x
48-
}
49-
}
50-
impl Convert<u128, u64> for CurrencyToVoteHandler {
51-
fn convert(x: u128) -> u64 {
52-
x.saturated_into()
53-
}
54-
}
55-
5643
#[derive(Clone, Eq, PartialEq, Debug)]
5744
pub struct Test;
5845

@@ -177,7 +164,7 @@ impl<C> frame_system::offchain::SendTransactionTypes<C> for Test where
177164
impl pallet_staking::Trait for Test {
178165
type Currency = Balances;
179166
type UnixTime = pallet_timestamp::Module<Self>;
180-
type CurrencyToVote = CurrencyToVoteHandler;
167+
type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote;
181168
type RewardRemainder = ();
182169
type Event = ();
183170
type Slash = ();

src/lib.rs

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ use frame_support::{
299299
},
300300
traits::{
301301
Currency, LockIdentifier, LockableCurrency, WithdrawReasons, OnUnbalanced, Imbalance, Get,
302-
UnixTime, EstimateNextNewSession, EnsureOrigin,
302+
UnixTime, EstimateNextNewSession, EnsureOrigin, CurrencyToVote,
303303
}
304304
};
305305
use pallet_session::historical;
@@ -811,7 +811,7 @@ pub trait Trait: frame_system::Trait + SendTransactionTypes<Call<Self>> {
811811
/// [`sp_npos_elections`] crate which accepts u64 numbers and does operations in 128.
812812
/// Consequently, the backward convert is used convert the u128s from sp-elections back to a
813813
/// [`BalanceOf`].
814-
type CurrencyToVote: Convert<BalanceOf<Self>, VoteWeight> + Convert<u128, BalanceOf<Self>>;
814+
type CurrencyToVote: CurrencyToVote<BalanceOf<Self>>;
815815

816816
/// Tokens have been minted and are unused for validator-reward.
817817
/// See [Era payout](./index.html#era-payout).
@@ -2192,11 +2192,22 @@ impl<T: Trait> Module<T> {
21922192
Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default()
21932193
}
21942194

2195-
/// internal impl of [`slashable_balance_of`] that returns [`VoteWeight`].
2196-
pub fn slashable_balance_of_vote_weight(stash: &T::AccountId) -> VoteWeight {
2197-
<T::CurrencyToVote as Convert<BalanceOf<T>, VoteWeight>>::convert(
2198-
Self::slashable_balance_of(stash)
2199-
)
2195+
/// Internal impl of [`slashable_balance_of`] that returns [`VoteWeight`].
2196+
pub fn slashable_balance_of_vote_weight(stash: &T::AccountId, issuance: BalanceOf<T>) -> VoteWeight {
2197+
T::CurrencyToVote::to_vote(Self::slashable_balance_of(stash), issuance)
2198+
}
2199+
2200+
/// Returns a closure around `slashable_balance_of_vote_weight` that can be passed around.
2201+
///
2202+
/// This prevents call sites from repeatedly requesting `total_issuance` from backend. But it is
2203+
/// important to be only used while the total issuance is not changing.
2204+
pub fn slashable_balance_of_fn() -> Box<dyn Fn(&T::AccountId) -> VoteWeight> {
2205+
// NOTE: changing this to unboxed `impl Fn(..)` return type and the module will still
2206+
// compile, while some types in mock fail to resolve.
2207+
let issuance = T::Currency::total_issuance();
2208+
Box::new(move |who: &T::AccountId| -> VoteWeight {
2209+
Self::slashable_balance_of_vote_weight(who, issuance)
2210+
})
22002211
}
22012212

22022213
/// Dump the list of validators and nominators into vectors and keep them on-chain.
@@ -2601,7 +2612,7 @@ impl<T: Trait> Module<T> {
26012612
// convert into staked assignments.
26022613
let staked_assignments = sp_npos_elections::assignment_ratio_to_staked(
26032614
assignments,
2604-
Self::slashable_balance_of_vote_weight,
2615+
Self::slashable_balance_of_fn(),
26052616
);
26062617

26072618
// build the support map thereof in order to evaluate.
@@ -2852,7 +2863,7 @@ impl<T: Trait> Module<T> {
28522863
/// `PrimitiveElectionResult` into `ElectionResult`.
28532864
///
28542865
/// No storage item is updated.
2855-
fn do_on_chain_phragmen() -> Option<ElectionResult<T::AccountId, BalanceOf<T>>> {
2866+
pub fn do_on_chain_phragmen() -> Option<ElectionResult<T::AccountId, BalanceOf<T>>> {
28562867
if let Some(phragmen_result) = Self::do_phragmen::<ChainAccuracy>(0) {
28572868
let elected_stashes = phragmen_result.winners.iter()
28582869
.map(|(s, _)| s.clone())
@@ -2861,7 +2872,7 @@ impl<T: Trait> Module<T> {
28612872

28622873
let staked_assignments = sp_npos_elections::assignment_ratio_to_staked(
28632874
assignments,
2864-
Self::slashable_balance_of_vote_weight,
2875+
Self::slashable_balance_of_fn(),
28652876
);
28662877

28672878
let supports = build_support_map::<T::AccountId>(
@@ -2903,16 +2914,16 @@ impl<T: Trait> Module<T> {
29032914
/// Self votes are added and nominations before the most recent slashing span are ignored.
29042915
///
29052916
/// No storage item is updated.
2906-
pub fn do_phragmen<Accuracy: PerThing>(
2907-
iterations: usize,
2908-
) -> Option<PrimitiveElectionResult<T::AccountId, Accuracy>>
2917+
pub fn do_phragmen<Accuracy: PerThing>(iterations: usize)
2918+
-> Option<PrimitiveElectionResult<T::AccountId, Accuracy>>
29092919
where ExtendedBalance: From<InnerOf<Accuracy>>
29102920
{
2921+
let weight_of = Self::slashable_balance_of_fn();
29112922
let mut all_nominators: Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> = Vec::new();
29122923
let mut all_validators = Vec::new();
29132924
for (validator, _) in <Validators<T>>::iter() {
29142925
// append self vote
2915-
let self_vote = (validator.clone(), Self::slashable_balance_of_vote_weight(&validator), vec![validator.clone()]);
2926+
let self_vote = (validator.clone(), weight_of(&validator), vec![validator.clone()]);
29162927
all_nominators.push(self_vote);
29172928
all_validators.push(validator);
29182929
}
@@ -2932,7 +2943,7 @@ impl<T: Trait> Module<T> {
29322943
(nominator, targets)
29332944
});
29342945
all_nominators.extend(nominator_votes.map(|(n, ns)| {
2935-
let s = Self::slashable_balance_of_vote_weight(&n);
2946+
let s = weight_of(&n);
29362947
(n, s, ns)
29372948
}));
29382949

@@ -2956,8 +2967,8 @@ impl<T: Trait> Module<T> {
29562967
fn collect_exposure(
29572968
supports: SupportMap<T::AccountId>,
29582969
) -> Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)> {
2959-
let to_balance = |e: ExtendedBalance|
2960-
<T::CurrencyToVote as Convert<ExtendedBalance, BalanceOf<T>>>::convert(e);
2970+
let total_issuance = T::Currency::total_issuance();
2971+
let to_currency = |e: ExtendedBalance| T::CurrencyToVote::to_currency(e, total_issuance);
29612972

29622973
supports.into_iter().map(|(validator, support)| {
29632974
// build `struct exposure` from `support`
@@ -2966,7 +2977,7 @@ impl<T: Trait> Module<T> {
29662977
let mut total: BalanceOf<T> = Zero::zero();
29672978
support.voters
29682979
.into_iter()
2969-
.map(|(nominator, weight)| (nominator, to_balance(weight)))
2980+
.map(|(nominator, weight)| (nominator, to_currency(weight)))
29702981
.for_each(|(nominator, stake)| {
29712982
if nominator == validator {
29722983
own = own.saturating_add(stake);

src/mock.rs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,14 @@ use frame_support::{
2727
use sp_core::H256;
2828
use sp_io;
2929
use sp_npos_elections::{
30-
build_support_map, evaluate_support, reduce, ElectionScore, ExtendedBalance, StakedAssignment,
30+
build_support_map, evaluate_support, reduce, ExtendedBalance, StakedAssignment, ElectionScore,
3131
};
3232
use sp_runtime::{
3333
curve::PiecewiseLinear,
3434
testing::{Header, TestXt, UintAuthorityId},
35-
traits::{Convert, IdentityLookup, SaturatedConversion, Zero},
36-
Perbill,
37-
};
38-
use sp_staking::{
39-
offence::{OffenceDetails, OnOffenceHandler},
40-
SessionIndex,
35+
traits::{IdentityLookup, Zero},
4136
};
37+
use sp_staking::offence::{OffenceDetails, OnOffenceHandler};
4238
use std::{cell::RefCell, collections::HashSet};
4339

4440
pub const INIT_TIMESTAMP: u64 = 30_000;
@@ -49,19 +45,6 @@ pub(crate) type AccountIndex = u64;
4945
pub(crate) type BlockNumber = u64;
5046
pub(crate) type Balance = u128;
5147

52-
/// Simple structure that exposes how u64 currency can be represented as... u64.
53-
pub struct CurrencyToVoteHandler;
54-
impl Convert<Balance, u64> for CurrencyToVoteHandler {
55-
fn convert(x: Balance) -> u64 {
56-
x.saturated_into()
57-
}
58-
}
59-
impl Convert<u128, Balance> for CurrencyToVoteHandler {
60-
fn convert(x: u128) -> Balance {
61-
x
62-
}
63-
}
64-
6548
thread_local! {
6649
static SESSION: RefCell<(Vec<AccountId>, HashSet<AccountId>)> = RefCell::new(Default::default());
6750
static SESSION_PER_ERA: RefCell<SessionIndex> = RefCell::new(3);
@@ -319,7 +302,7 @@ impl OnUnbalanced<NegativeImbalanceOf<Test>> for RewardRemainderMock {
319302
impl Trait for Test {
320303
type Currency = Balances;
321304
type UnixTime = Timestamp;
322-
type CurrencyToVote = CurrencyToVoteHandler;
305+
type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote;
323306
type RewardRemainder = RewardRemainderMock;
324307
type Event = MetaEvent;
325308
type Slash = ();
@@ -926,7 +909,7 @@ pub(crate) fn prepare_submission_with(
926909

927910
let mut staked = sp_npos_elections::assignment_ratio_to_staked(
928911
assignments,
929-
Staking::slashable_balance_of_vote_weight,
912+
Staking::slashable_balance_of_fn(),
930913
);
931914

932915
// apply custom tweaks. awesome for testing.
@@ -964,7 +947,7 @@ pub(crate) fn prepare_submission_with(
964947
let score = if compute_real_score {
965948
let staked = sp_npos_elections::assignment_ratio_to_staked(
966949
assignments_reduced.clone(),
967-
Staking::slashable_balance_of_vote_weight,
950+
Staking::slashable_balance_of_fn(),
968951
);
969952

970953
let support_map = build_support_map::<AccountId>(
@@ -978,10 +961,8 @@ pub(crate) fn prepare_submission_with(
978961

979962
let compact =
980963
CompactAssignments::from_assignment(assignments_reduced, nominator_index, validator_index)
981-
.map_err(|e| { println!("error in compact: {:?}", e); e })
982964
.expect("Failed to create compact");
983965

984-
985966
// winner ids to index
986967
let winners = winners.into_iter().map(|w| validator_index(&w).unwrap()).collect::<Vec<_>>();
987968

src/offchain_election.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,9 @@ where
268268
match compact.len().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.
271+
let balance_of = <Module<T>>::slashable_balance_of_fn();
271272
let mut voters_sorted = <Nominators<T>>::iter()
272-
.map(|(who, _)| {
273-
(
274-
who.clone(),
275-
<Module<T>>::slashable_balance_of_vote_weight(&who),
276-
)
277-
})
273+
.map(|(who, _)| (who.clone(), balance_of(&who)))
278274
.collect::<Vec<_>>();
279275
voters_sorted.sort_by_key(|(_, y)| *y);
280276

@@ -378,7 +374,7 @@ where
378374
// convert into absolute value and to obtain the reduced version.
379375
let mut staked = sp_npos_elections::assignment_ratio_to_staked(
380376
assignments,
381-
<Module<T>>::slashable_balance_of_vote_weight,
377+
<Module<T>>::slashable_balance_of_fn(),
382378
);
383379

384380
// reduce
@@ -423,8 +419,8 @@ where
423419
let compact = compact.clone();
424420
let assignments = compact.into_assignment(nominator_at, validator_at).unwrap();
425421
let staked = sp_npos_elections::assignment_ratio_to_staked(
426-
assignments,
427-
<Module<T>>::slashable_balance_of_vote_weight,
422+
assignments.clone(),
423+
<Module<T>>::slashable_balance_of_fn(),
428424
);
429425

430426
let support_map = build_support_map::<T::AccountId>(&winners, &staked)

src/testing_utils.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,10 @@ pub fn get_weak_solution<T: Trait>(
193193
who: w.clone(),
194194
distribution: vec![(
195195
w.clone(),
196-
<T::CurrencyToVote as Convert<BalanceOf<T>, u64>>::convert(
197-
<Module<T>>::slashable_balance_of(&w),
198-
) as ExtendedBalance,
196+
<Module<T>>::slashable_balance_of_vote_weight(
197+
&w,
198+
T::Currency::total_issuance(),
199+
).into(),
199200
)],
200201
})
201202
});
@@ -220,11 +221,6 @@ pub fn get_weak_solution<T: Trait>(
220221
.position(|x| x == a)
221222
.and_then(|i| <usize as TryInto<ValidatorIndex>>::try_into(i).ok())
222223
};
223-
let stake_of = |who: &T::AccountId| -> VoteWeight {
224-
<T::CurrencyToVote as Convert<BalanceOf<T>, u64>>::convert(
225-
<Module<T>>::slashable_balance_of(who),
226-
)
227-
};
228224

229225
// convert back to ratio assignment. This takes less space.
230226
let low_accuracy_assignment = assignment_staked_to_ratio_normalized(staked_assignments)
@@ -234,7 +230,7 @@ pub fn get_weak_solution<T: Trait>(
234230
let score = {
235231
let staked = assignment_ratio_to_staked::<_, OffchainAccuracy, _>(
236232
low_accuracy_assignment.clone(),
237-
stake_of
233+
<Module<T>>::slashable_balance_of_fn(),
238234
);
239235

240236
let support_map = build_support_map::<T::AccountId>(
@@ -325,7 +321,7 @@ pub fn get_single_winner_solution<T: Trait>(
325321

326322
let stake = <Staking<T>>::slashable_balance_of(&winner);
327323
let stake =
328-
<T::CurrencyToVote as Convert<BalanceOf<T>, VoteWeight>>::convert(stake) as ExtendedBalance;
324+
<T::CurrencyToVote>::to_vote(stake, T::Currency::total_issuance()) as ExtendedBalance;
329325

330326
let val_index = val_index as ValidatorIndex;
331327
let nom_index = nom_index as NominatorIndex;

0 commit comments

Comments
 (0)