43
43
//! ### Voting
44
44
//!
45
45
//! Voters can vote for a limited number of the candidates by providing a list of account ids,
46
- //! bounded by [`MAXIMUM_VOTE `]. Invalid votes (voting for non-candidates) and duplicate votes are
47
- //! ignored during election. Yet, a voter _might_ vote for a future candidate. Voters reserve a bond
48
- //! as they vote. Each vote defines a `value`. This amount is locked from the account of the voter
49
- //! and indicates the weight of the vote. Voters can update their votes at any time by calling
50
- //! `vote()` again. This can update the vote targets (which might update the deposit) or update the
51
- //! vote's stake ([`Voter::stake`]). After a round, votes are kept and might still be valid for
52
- //! further rounds. A voter is responsible for calling `remove_voter` once they are done to have
53
- //! their bond back and remove the lock.
46
+ //! bounded by [`Config::MaxVotesPerVoter `]. Invalid votes (voting for non-candidates) and duplicate
47
+ //! votes are ignored during election. Yet, a voter _might_ vote for a future candidate. Voters
48
+ //! reserve a bond as they vote. Each vote defines a `value`. This amount is locked from the account
49
+ //! of the voter and indicates the weight of the vote. Voters can update their votes at any time by
50
+ //! calling `vote()` again. This can update the vote targets (which might update the deposit) or
51
+ //! update the vote's stake ([`Voter::stake`]). After a round, votes are kept and might still be
52
+ //! valid for further rounds. A voter is responsible for calling `remove_voter` once they are done
53
+ //! to have their bond back and remove the lock.
54
54
//!
55
55
//! See [`Call::vote`], [`Call::remove_voter`].
56
56
//!
@@ -124,9 +124,6 @@ pub mod migrations;
124
124
125
125
const LOG_TARGET : & str = "runtime::elections-phragmen" ;
126
126
127
- /// The maximum votes allowed per voter.
128
- pub const MAXIMUM_VOTE : usize = 16 ;
129
-
130
127
type BalanceOf < T > =
131
128
<<T as Config >:: Currency as Currency < <T as frame_system:: Config >:: AccountId > >:: Balance ;
132
129
type NegativeImbalanceOf < T > = <<T as Config >:: Currency as Currency <
@@ -254,19 +251,29 @@ pub mod pallet {
254
251
255
252
/// The maximum number of candidates in a phragmen election.
256
253
///
257
- /// Warning: The election happens onchain, and this value will determine
258
- /// the size of the election. When this limit is reached no more
259
- /// candidates are accepted in the election.
254
+ /// Warning: This impacts the size of the election which is run onchain. Chose wisely, and
255
+ /// consider how it will impact `T::WeightInfo::election_phragmen`.
256
+ ///
257
+ /// When this limit is reached no more candidates are accepted in the election.
260
258
#[ pallet:: constant]
261
259
type MaxCandidates : Get < u32 > ;
262
260
263
261
/// The maximum number of voters to allow in a phragmen election.
264
262
///
265
- /// Warning: This impacts the size of the election which is run onchain.
263
+ /// Warning: This impacts the size of the election which is run onchain. Chose wisely, and
264
+ /// consider how it will impact `T::WeightInfo::election_phragmen`.
265
+ ///
266
266
/// When the limit is reached the new voters are ignored.
267
267
#[ pallet:: constant]
268
268
type MaxVoters : Get < u32 > ;
269
269
270
+ /// Maximum numbers of votes per voter.
271
+ ///
272
+ /// Warning: This impacts the size of the election which is run onchain. Chose wisely, and
273
+ /// consider how it will impact `T::WeightInfo::election_phragmen`.
274
+ #[ pallet:: constant]
275
+ type MaxVotesPerVoter : Get < u32 > ;
276
+
270
277
/// Weight information for extrinsics in this pallet.
271
278
type WeightInfo : WeightInfo ;
272
279
}
@@ -284,6 +291,41 @@ pub mod pallet {
284
291
Weight :: zero ( )
285
292
}
286
293
}
294
+
295
+ fn integrity_test ( ) {
296
+ let block_weight = T :: BlockWeights :: get ( ) . max_block ;
297
+ // mind the order.
298
+ let election_weight = T :: WeightInfo :: election_phragmen (
299
+ T :: MaxCandidates :: get ( ) ,
300
+ T :: MaxVoters :: get ( ) ,
301
+ T :: MaxVotesPerVoter :: get ( ) * T :: MaxVoters :: get ( ) ,
302
+ ) ;
303
+
304
+ let to_seconds = |w : & Weight | {
305
+ w. ref_time ( ) as f32 /
306
+ frame_support:: weights:: constants:: WEIGHT_REF_TIME_PER_SECOND as f32
307
+ } ;
308
+
309
+ frame_support:: log:: debug!(
310
+ target: LOG_TARGET ,
311
+ "election weight {}s ({:?}) // chain's block weight {}s ({:?})" ,
312
+ to_seconds( & election_weight) ,
313
+ election_weight,
314
+ to_seconds( & block_weight) ,
315
+ block_weight,
316
+ ) ;
317
+ assert ! (
318
+ election_weight. all_lt( block_weight) ,
319
+ "election weight {}s ({:?}) will exceed a {}s chain's block weight ({:?}) (MaxCandidates {}, MaxVoters {}, MaxVotesPerVoter {} -- tweak these parameters)" ,
320
+ election_weight,
321
+ to_seconds( & election_weight) ,
322
+ to_seconds( & block_weight) ,
323
+ block_weight,
324
+ T :: MaxCandidates :: get( ) ,
325
+ T :: MaxVoters :: get( ) ,
326
+ T :: MaxVotesPerVoter :: get( ) ,
327
+ ) ;
328
+ }
287
329
}
288
330
289
331
#[ pallet:: call]
@@ -307,10 +349,6 @@ pub mod pallet {
307
349
///
308
350
/// It is the responsibility of the caller to **NOT** place all of their balance into the
309
351
/// lock and keep some for further operations.
310
- ///
311
- /// # <weight>
312
- /// We assume the maximum weight among all 3 cases: vote_equal, vote_more and vote_less.
313
- /// # </weight>
314
352
#[ pallet:: call_index( 0 ) ]
315
353
#[ pallet:: weight(
316
354
T :: WeightInfo :: vote_more( votes. len( ) as u32 )
@@ -324,8 +362,10 @@ pub mod pallet {
324
362
) -> DispatchResultWithPostInfo {
325
363
let who = ensure_signed ( origin) ?;
326
364
327
- // votes should not be empty and more than `MAXIMUM_VOTE` in any case.
328
- ensure ! ( votes. len( ) <= MAXIMUM_VOTE , Error :: <T >:: MaximumVotesExceeded ) ;
365
+ ensure ! (
366
+ votes. len( ) <= T :: MaxVotesPerVoter :: get( ) as usize ,
367
+ Error :: <T >:: MaximumVotesExceeded
368
+ ) ;
329
369
ensure ! ( !votes. is_empty( ) , Error :: <T >:: NoVotes ) ;
330
370
331
371
let candidates_count = <Candidates < T > >:: decode_len ( ) . unwrap_or ( 0 ) ;
@@ -1006,15 +1046,15 @@ impl<T: Config> Pallet<T> {
1006
1046
// count](https://en.wikipedia.org/wiki/Borda_count). We weigh everyone's vote for
1007
1047
// that new member by a multiplier based on the order of the votes. i.e. the
1008
1048
// first person a voter votes for gets a 16x multiplier, the next person gets a
1009
- // 15x multiplier, an so on... (assuming `MAXIMUM_VOTE ` = 16)
1049
+ // 15x multiplier, an so on... (assuming `T::MaxVotesPerVoter ` = 16)
1010
1050
let mut prime_votes = new_members_sorted_by_id
1011
1051
. iter ( )
1012
1052
. map ( |c| ( & c. 0 , BalanceOf :: < T > :: zero ( ) ) )
1013
1053
. collect :: < Vec < _ > > ( ) ;
1014
1054
for ( _, stake, votes) in voters_and_stakes. into_iter ( ) {
1015
1055
for ( vote_multiplier, who) in
1016
1056
votes. iter ( ) . enumerate ( ) . map ( |( vote_position, who) | {
1017
- ( ( MAXIMUM_VOTE - vote_position) as u32 , who)
1057
+ ( ( T :: MaxVotesPerVoter :: get ( ) as usize - vote_position) as u32 , who)
1018
1058
} ) {
1019
1059
if let Ok ( i) = prime_votes. binary_search_by_key ( & who, |k| k. 0 ) {
1020
1060
prime_votes[ i] . 1 = prime_votes[ i]
@@ -1173,16 +1213,9 @@ mod tests {
1173
1213
} ;
1174
1214
use substrate_test_utils:: assert_eq_uvec;
1175
1215
1176
- parameter_types ! {
1177
- pub BlockWeights : frame_system:: limits:: BlockWeights =
1178
- frame_system:: limits:: BlockWeights :: simple_max(
1179
- frame_support:: weights:: Weight :: from_ref_time( 1024 ) . set_proof_size( u64 :: MAX ) ,
1180
- ) ;
1181
- }
1182
-
1183
1216
impl frame_system:: Config for Test {
1184
1217
type BaseCallFilter = frame_support:: traits:: Everything ;
1185
- type BlockWeights = BlockWeights ;
1218
+ type BlockWeights = ( ) ;
1186
1219
type BlockLength = ( ) ;
1187
1220
type DbWeight = ( ) ;
1188
1221
type RuntimeOrigin = RuntimeOrigin ;
@@ -1297,6 +1330,7 @@ mod tests {
1297
1330
type KickedMember = ( ) ;
1298
1331
type WeightInfo = ( ) ;
1299
1332
type MaxVoters = PhragmenMaxVoters ;
1333
+ type MaxVotesPerVoter = ConstU32 < 16 > ;
1300
1334
type MaxCandidates = PhragmenMaxCandidates ;
1301
1335
}
1302
1336
0 commit comments