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

Commit 9e9e4d3

Browse files
kianenigmaemostovggwpez
authored
Use proper bounded vector type for nominations (#10601)
* Use proper bounded vector type for nominations * add docs and tweak chill_other for cleanup purposes * Fix the build * remove TODO * add a bit more doc * even more docs gushc * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov <[email protected]> * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov <[email protected]> * Fix the nasty bug * also bound the Snapshot type * fix doc test * document bounded_vec * self-review * remove unused * Fix build * frame-support: repetition overload for bounded_vec Signed-off-by: Oliver Tale-Yazdi <[email protected]> * fix * remove the need to allocate into unbounded voters etc etc * Don't expect * unbreal the build again * handle macro a bit better Co-authored-by: Zeke Mostov <[email protected]> Co-authored-by: Oliver Tale-Yazdi <[email protected]>
1 parent 31d90c2 commit 9e9e4d3

File tree

34 files changed

+419
-252
lines changed

34 files changed

+419
-252
lines changed

bin/node/cli/src/chain_spec.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use hex_literal::hex;
2323
use node_runtime::{
2424
constants::currency::*, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig,
2525
BalancesConfig, Block, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig,
26-
ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, SocietyConfig, StakerStatus,
27-
StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, MAX_NOMINATIONS,
26+
ImOnlineConfig, IndicesConfig, MaxNominations, SessionConfig, SessionKeys, SocietyConfig,
27+
StakerStatus, StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig,
2828
};
2929
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
3030
use sc_chain_spec::ChainSpecExtension;
@@ -278,7 +278,7 @@ pub fn testnet_genesis(
278278
.map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator))
279279
.chain(initial_nominators.iter().map(|x| {
280280
use rand::{seq::SliceRandom, Rng};
281-
let limit = (MAX_NOMINATIONS as usize).min(initial_authorities.len());
281+
let limit = (MaxNominations::get() as usize).min(initial_authorities.len());
282282
let count = rng.gen::<usize>() % limit;
283283
let nominations = initial_authorities
284284
.as_slice()

bin/node/runtime/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig {
541541
}
542542

543543
impl pallet_staking::Config for Runtime {
544-
const MAX_NOMINATIONS: u32 = MAX_NOMINATIONS;
544+
type MaxNominations = MaxNominations;
545545
type Currency = Balances;
546546
type UnixTime = Timestamp;
547547
type CurrencyToVote = U128CurrencyToVote;
@@ -605,7 +605,9 @@ sp_npos_elections::generate_solution_type!(
605605
>(16)
606606
);
607607

608-
pub const MAX_NOMINATIONS: u32 = <NposSolution16 as sp_npos_elections::NposSolution>::LIMIT as u32;
608+
parameter_types! {
609+
pub MaxNominations: u32 = <NposSolution16 as sp_npos_elections::NposSolution>::LIMIT as u32;
610+
}
609611

610612
/// The numbers configured here could always be more than the the maximum limits of staking pallet
611613
/// to ensure election snapshot will not run out of memory. For now, we set them to smaller values
@@ -1792,7 +1794,7 @@ mod tests {
17921794
#[test]
17931795
fn perbill_as_onchain_accuracy() {
17941796
type OnChainAccuracy = <Runtime as onchain::Config>::Accuracy;
1795-
let maximum_chain_accuracy: Vec<UpperOf<OnChainAccuracy>> = (0..MAX_NOMINATIONS)
1797+
let maximum_chain_accuracy: Vec<UpperOf<OnChainAccuracy>> = (0..MaxNominations::get())
17961798
.map(|_| <UpperOf<OnChainAccuracy>>::from(OnChainAccuracy::one().deconstruct()))
17971799
.collect();
17981800
let _: UpperOf<OnChainAccuracy> =

frame/babe/src/mock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl onchain::Config for Test {
178178
}
179179

180180
impl pallet_staking::Config for Test {
181-
const MAX_NOMINATIONS: u32 = 16;
181+
type MaxNominations = ConstU32<16>;
182182
type RewardRemainder = ();
183183
type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote;
184184
type Event = Event;

frame/election-provider-multi-phase/src/benchmarking.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
use super::*;
2121
use crate::{unsigned::IndexAssignmentOf, Pallet as MultiPhase};
2222
use frame_benchmarking::account;
23-
use frame_support::{assert_ok, traits::Hooks};
23+
use frame_support::{
24+
assert_ok,
25+
traits::{Hooks, TryCollect},
26+
BoundedVec,
27+
};
2428
use frame_system::RawOrigin;
2529
use rand::{prelude::SliceRandom, rngs::SmallRng, SeedableRng};
2630
use sp_arithmetic::{per_things::Percent, traits::One};
@@ -69,11 +73,12 @@ fn solution_with_size<T: Config>(
6973
let active_voters = (0..active_voters_count)
7074
.map(|i| {
7175
// chose a random subset of winners.
72-
let winner_votes = winners
76+
let winner_votes: BoundedVec<_, _> = winners
7377
.as_slice()
7478
.choose_multiple(&mut rng, <SolutionOf<T>>::LIMIT)
7579
.cloned()
76-
.collect::<Vec<_>>();
80+
.try_collect()
81+
.expect("<SolutionOf<T>>::LIMIT is the correct bound; qed.");
7782
let voter = frame_benchmarking::account::<T::AccountId>("Voter", i, SEED);
7883
(voter, stake, winner_votes)
7984
})
@@ -87,10 +92,11 @@ fn solution_with_size<T: Config>(
8792
.collect::<Vec<T::AccountId>>();
8893
let rest_voters = (active_voters_count..size.voters)
8994
.map(|i| {
90-
let votes = (&non_winners)
95+
let votes: BoundedVec<_, _> = (&non_winners)
9196
.choose_multiple(&mut rng, <SolutionOf<T>>::LIMIT)
9297
.cloned()
93-
.collect::<Vec<T::AccountId>>();
98+
.try_collect()
99+
.expect("<SolutionOf<T>>::LIMIT is the correct bound; qed.");
94100
let voter = frame_benchmarking::account::<T::AccountId>("Voter", i, SEED);
95101
(voter, stake, votes)
96102
})
@@ -152,7 +158,7 @@ fn set_up_data_provider<T: Config>(v: u32, t: u32) {
152158
info,
153159
"setting up with voters = {} [degree = {}], targets = {}",
154160
v,
155-
T::DataProvider::MAXIMUM_VOTES_PER_VOTER,
161+
<T::DataProvider as ElectionDataProvider>::MaxVotesPerVoter::get(),
156162
t
157163
);
158164

@@ -165,14 +171,16 @@ fn set_up_data_provider<T: Config>(v: u32, t: u32) {
165171
})
166172
.collect::<Vec<_>>();
167173
// we should always have enough voters to fill.
168-
assert!(targets.len() > T::DataProvider::MAXIMUM_VOTES_PER_VOTER as usize);
169-
targets.truncate(T::DataProvider::MAXIMUM_VOTES_PER_VOTER as usize);
174+
assert!(
175+
targets.len() > <T::DataProvider as ElectionDataProvider>::MaxVotesPerVoter::get() as usize
176+
);
177+
targets.truncate(<T::DataProvider as ElectionDataProvider>::MaxVotesPerVoter::get() as usize);
170178

171179
// fill voters.
172180
(0..v).for_each(|i| {
173181
let voter = frame_benchmarking::account::<T::AccountId>("Voter", i, SEED);
174182
let weight = T::Currency::minimum_balance().saturated_into::<u64>() * 1000;
175-
T::DataProvider::add_voter(voter, weight, targets.clone());
183+
T::DataProvider::add_voter(voter, weight, targets.clone().try_into().unwrap());
176184
});
177185
}
178186

frame/election-provider-multi-phase/src/helpers.rs

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

1818
//! Some helper functions/macros for this crate.
1919
20-
use super::{Config, SolutionTargetIndexOf, SolutionVoterIndexOf, VoteWeight};
20+
use crate::{unsigned::VoterOf, Config, SolutionTargetIndexOf, SolutionVoterIndexOf, VoteWeight};
2121
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
2222

2323
#[macro_export]
@@ -34,7 +34,7 @@ macro_rules! log {
3434
///
3535
/// This can be used to efficiently build index getter closures.
3636
pub fn generate_voter_cache<T: Config>(
37-
snapshot: &Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
37+
snapshot: &Vec<VoterOf<T>>,
3838
) -> BTreeMap<T::AccountId, usize> {
3939
let mut cache: BTreeMap<T::AccountId, usize> = BTreeMap::new();
4040
snapshot.iter().enumerate().for_each(|(i, (x, _, _))| {
@@ -97,7 +97,7 @@ pub fn voter_index_fn_usize<T: Config>(
9797
/// Not meant to be used in production.
9898
#[cfg(test)]
9999
pub fn voter_index_fn_linear<T: Config>(
100-
snapshot: &Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
100+
snapshot: &Vec<VoterOf<T>>,
101101
) -> impl Fn(&T::AccountId) -> Option<SolutionVoterIndexOf<T>> + '_ {
102102
move |who| {
103103
snapshot
@@ -148,7 +148,7 @@ pub fn target_index_fn_linear<T: Config>(
148148
/// Create a function that can map a voter index ([`SolutionVoterIndexOf`]) to the actual voter
149149
/// account using a linearly indexible snapshot.
150150
pub fn voter_at_fn<T: Config>(
151-
snapshot: &Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
151+
snapshot: &Vec<VoterOf<T>>,
152152
) -> impl Fn(SolutionVoterIndexOf<T>) -> Option<T::AccountId> + '_ {
153153
move |i| {
154154
<SolutionVoterIndexOf<T> as TryInto<usize>>::try_into(i)
@@ -174,7 +174,7 @@ pub fn target_at_fn<T: Config>(
174174
/// This is not optimized and uses a linear search.
175175
#[cfg(test)]
176176
pub fn stake_of_fn_linear<T: Config>(
177-
snapshot: &Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
177+
snapshot: &Vec<VoterOf<T>>,
178178
) -> impl Fn(&T::AccountId) -> VoteWeight + '_ {
179179
move |who| {
180180
snapshot
@@ -192,7 +192,7 @@ pub fn stake_of_fn_linear<T: Config>(
192192
/// The cache need must be derived from the same snapshot. Zero is returned if a voter is
193193
/// non-existent.
194194
pub fn stake_of_fn<'a, T: Config>(
195-
snapshot: &'a Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)>,
195+
snapshot: &'a Vec<VoterOf<T>>,
196196
cache: &'a BTreeMap<T::AccountId, usize>,
197197
) -> impl Fn(&T::AccountId) -> VoteWeight + 'a {
198198
move |who| {

frame/election-provider-multi-phase/src/lib.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ const LOG_TARGET: &'static str = "runtime::election-provider";
269269
pub mod signed;
270270
pub mod unsigned;
271271
pub mod weights;
272+
use unsigned::VoterOf;
272273
pub use weights::WeightInfo;
273274

274275
pub use signed::{
@@ -448,11 +449,13 @@ pub struct ReadySolution<A> {
448449
///
449450
/// These are stored together because they are often accessed together.
450451
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, TypeInfo)]
451-
pub struct RoundSnapshot<A> {
452+
#[codec(mel_bound(T: Config))]
453+
#[scale_info(skip_type_params(T))]
454+
pub struct RoundSnapshot<T: Config> {
452455
/// All of the voters.
453-
pub voters: Vec<(A, VoteWeight, Vec<A>)>,
456+
pub voters: Vec<VoterOf<T>>,
454457
/// All of the targets.
455-
pub targets: Vec<A>,
458+
pub targets: Vec<T::AccountId>,
456459
}
457460

458461
/// Encodes the length of a solution or a snapshot.
@@ -820,7 +823,7 @@ pub mod pallet {
820823
// NOTE that this pallet does not really need to enforce this in runtime. The
821824
// solution cannot represent any voters more than `LIMIT` anyhow.
822825
assert_eq!(
823-
<T::DataProvider as ElectionDataProvider>::MAXIMUM_VOTES_PER_VOTER,
826+
<T::DataProvider as ElectionDataProvider>::MaxVotesPerVoter::get(),
824827
<SolutionOf<T> as NposSolution>::LIMIT as u32,
825828
);
826829
}
@@ -1140,7 +1143,7 @@ pub mod pallet {
11401143
/// This is created at the beginning of the signed phase and cleared upon calling `elect`.
11411144
#[pallet::storage]
11421145
#[pallet::getter(fn snapshot)]
1143-
pub type Snapshot<T: Config> = StorageValue<_, RoundSnapshot<T::AccountId>>;
1146+
pub type Snapshot<T: Config> = StorageValue<_, RoundSnapshot<T>>;
11441147

11451148
/// Desired number of targets to elect for this round.
11461149
///
@@ -1257,7 +1260,7 @@ impl<T: Config> Pallet<T> {
12571260
/// Extracted for easier weight calculation.
12581261
fn create_snapshot_internal(
12591262
targets: Vec<T::AccountId>,
1260-
voters: Vec<crate::unsigned::Voter<T>>,
1263+
voters: Vec<VoterOf<T>>,
12611264
desired_targets: u32,
12621265
) {
12631266
let metadata =
@@ -1270,7 +1273,7 @@ impl<T: Config> Pallet<T> {
12701273
// instead of using storage APIs, we do a manual encoding into a fixed-size buffer.
12711274
// `encoded_size` encodes it without storing it anywhere, this should not cause any
12721275
// allocation.
1273-
let snapshot = RoundSnapshot { voters, targets };
1276+
let snapshot = RoundSnapshot::<T> { voters, targets };
12741277
let size = snapshot.encoded_size();
12751278
log!(debug, "snapshot pre-calculated size {:?}", size);
12761279
let mut buffer = Vec::with_capacity(size);
@@ -1288,7 +1291,7 @@ impl<T: Config> Pallet<T> {
12881291
///
12891292
/// Extracted for easier weight calculation.
12901293
fn create_snapshot_external(
1291-
) -> Result<(Vec<T::AccountId>, Vec<crate::unsigned::Voter<T>>, u32), ElectionError<T>> {
1294+
) -> Result<(Vec<T::AccountId>, Vec<VoterOf<T>>, u32), ElectionError<T>> {
12921295
let target_limit = <SolutionTargetIndexOf<T>>::max_value().saturated_into::<usize>();
12931296
// for now we have just a single block snapshot.
12941297
let voter_limit = T::VoterSnapshotPerBlock::get().saturated_into::<usize>();

0 commit comments

Comments
 (0)