@@ -25,7 +25,8 @@ use frame_benchmarking::{
2525use frame_support:: {
2626 assert_ok,
2727 codec:: Decode ,
28- traits:: { Currency , EnsureOrigin , Get } ,
28+ dispatch:: DispatchResult ,
29+ traits:: { Currency , EnsureOrigin , Get , ReservableCurrency } ,
2930} ;
3031use frame_system:: { EventRecord , RawOrigin } ;
3132use pallet_authorship:: EventHandler ;
@@ -106,6 +107,18 @@ fn register_candidates<T: Config>(count: u32) {
106107 }
107108}
108109
110+ fn min_candidates < T : Config > ( ) -> u32 {
111+ let min_collators = T :: MinEligibleCollators :: get ( ) ;
112+ let invulnerable_length = <Invulnerables < T > >:: get ( ) . len ( ) ;
113+ min_collators. saturating_sub ( invulnerable_length. try_into ( ) . unwrap ( ) )
114+ }
115+
116+ fn min_invulnerables < T : Config > ( ) -> u32 {
117+ let min_collators = T :: MinEligibleCollators :: get ( ) ;
118+ let candidates_length = <Candidates < T > >:: get ( ) . len ( ) ;
119+ min_collators. saturating_sub ( candidates_length. try_into ( ) . unwrap ( ) )
120+ }
121+
109122benchmarks ! {
110123 where_clause { where T : pallet_authorship:: Config + session:: Config }
111124
@@ -128,34 +141,67 @@ benchmarks! {
128141 }
129142
130143 add_invulnerable {
144+ let b in 1 .. T :: MaxInvulnerables :: get( ) - 1 ;
145+ let c in 1 .. T :: MaxCandidates :: get( ) - 1 ;
146+
131147 let origin =
132148 T :: UpdateOrigin :: try_successful_origin( ) . map_err( |_| BenchmarkError :: Weightless ) ?;
133- // we're going to add one, so need one less than max set as invulnerables to start
134- let b in 1 .. T :: MaxInvulnerables :: get( ) - 1 ;
149+
150+ // need to fill up candidates
151+ <CandidacyBond <T >>:: put( T :: Currency :: minimum_balance( ) ) ;
152+ <DesiredCandidates <T >>:: put( c) ;
153+ // get accounts and keys for the `c` candidates
154+ let mut candidates = ( 0 ..c) . map( |cc| validator:: <T >( cc) ) . collect:: <Vec <_>>( ) ;
155+ // add one more to the list. should not be in `b` (invulnerables) because it's the account
156+ // we will _add_ to invulnerables. we want it to be in `candidates` because we need the
157+ // weight associated with removing it.
158+ let ( new_invulnerable, new_invulnerable_keys) = validator:: <T >( b. max( c) + 1 ) ;
159+ candidates. push( ( new_invulnerable. clone( ) , new_invulnerable_keys) ) ;
160+ // set their keys ...
161+ for ( who, keys) in candidates. clone( ) {
162+ <session:: Pallet <T >>:: set_keys( RawOrigin :: Signed ( who) . into( ) , keys, Vec :: new( ) ) . unwrap( ) ;
163+ }
164+ // ... and register them.
165+ for ( who, _) in candidates {
166+ let deposit = <CandidacyBond <T >>:: get( ) ;
167+ T :: Currency :: make_free_balance_be( & who, deposit * 1000_u32 . into( ) ) ;
168+ let incoming = CandidateInfo { who: who. clone( ) , deposit } ;
169+ <Candidates <T >>:: try_mutate( |candidates| -> DispatchResult {
170+ if !candidates. iter( ) . any( |candidate| candidate. who == who) {
171+ T :: Currency :: reserve( & who, deposit) ?;
172+ candidates. try_push( incoming) . expect( "we've respected the bounded vec limit" ) ;
173+ <LastAuthoredBlock <T >>:: insert(
174+ who. clone( ) ,
175+ frame_system:: Pallet :: <T >:: block_number( ) + T :: KickThreshold :: get( ) ,
176+ ) ;
177+ }
178+ Ok ( ( ) )
179+ } ) . expect( "only returns ok" ) ;
180+ }
181+
182+ // now we need to fill up invulnerables
135183 let mut invulnerables = register_validators:: <T >( b) ;
136184 invulnerables. sort( ) ;
137- let invulnerables: frame_support:: BoundedVec <_, T :: MaxInvulnerables > = frame_support:: BoundedVec :: try_from( invulnerables) . unwrap( ) ;
185+ let invulnerables: frame_support:: BoundedVec <_, T :: MaxInvulnerables > =
186+ frame_support:: BoundedVec :: try_from( invulnerables) . unwrap( ) ;
138187 <Invulnerables <T >>:: put( invulnerables) ;
139-
140- // now let's set up a new one to add
141- let ( new, keys) = validator:: <T >( b + 1 ) ;
142- <session:: Pallet <T >>:: set_keys( RawOrigin :: Signed ( new. clone( ) ) . into( ) , keys, Vec :: new( ) ) . unwrap( ) ;
143188 } : {
144189 assert_ok!(
145- <CollatorSelection <T >>:: add_invulnerable( origin, new . clone( ) )
190+ <CollatorSelection <T >>:: add_invulnerable( origin, new_invulnerable . clone( ) )
146191 ) ;
147192 }
148193 verify {
149- assert_last_event:: <T >( Event :: InvulnerableAdded { account_id: new } . into( ) ) ;
194+ assert_last_event:: <T >( Event :: InvulnerableAdded { account_id: new_invulnerable } . into( ) ) ;
150195 }
151196
152197 remove_invulnerable {
153198 let origin =
154199 T :: UpdateOrigin :: try_successful_origin( ) . map_err( |_| BenchmarkError :: Weightless ) ?;
155- let b in 1 .. T :: MaxInvulnerables :: get( ) ;
200+ let b in ( min_invulnerables :: < T > ( ) + 1 ) .. T :: MaxInvulnerables :: get( ) ;
156201 let mut invulnerables = register_validators:: <T >( b) ;
157202 invulnerables. sort( ) ;
158- let invulnerables: frame_support:: BoundedVec <_, T :: MaxInvulnerables > = frame_support:: BoundedVec :: try_from( invulnerables) . unwrap( ) ;
203+ let invulnerables: frame_support:: BoundedVec <_, T :: MaxInvulnerables > =
204+ frame_support:: BoundedVec :: try_from( invulnerables) . unwrap( ) ;
159205 <Invulnerables <T >>:: put( invulnerables) ;
160206 let to_remove = <Invulnerables <T >>:: get( ) . first( ) . unwrap( ) . clone( ) ;
161207 } : {
@@ -221,7 +267,7 @@ benchmarks! {
221267
222268 // worse case is the last candidate leaving.
223269 leave_intent {
224- let c in ( T :: MinCandidates :: get ( ) + 1 ) .. T :: MaxCandidates :: get( ) ;
270+ let c in ( min_candidates :: < T > ( ) + 1 ) .. T :: MaxCandidates :: get( ) ;
225271 <CandidacyBond <T >>:: put( T :: Currency :: minimum_balance( ) ) ;
226272 <DesiredCandidates <T >>:: put( c) ;
227273
@@ -286,6 +332,7 @@ benchmarks! {
286332 }
287333 }
288334
335+ let min_candidates = min_candidates:: <T >( ) ;
289336 let pre_length = <Candidates <T >>:: get( ) . len( ) ;
290337
291338 frame_system:: Pallet :: <T >:: set_block_number( new_block) ;
@@ -294,11 +341,19 @@ benchmarks! {
294341 } : {
295342 <CollatorSelection <T > as SessionManager <_>>:: new_session( 0 )
296343 } verify {
297- if c > r && non_removals >= T :: MinCandidates :: get( ) {
344+ if c > r && non_removals >= min_candidates {
345+ // candidates > removals and remaining candidates > min candidates
346+ // => remaining candidates should be shorter than before removal, i.e. some were
347+ // actually removed.
298348 assert!( <Candidates <T >>:: get( ) . len( ) < pre_length) ;
299- } else if c > r && non_removals < T :: MinCandidates :: get( ) {
300- assert!( <Candidates <T >>:: get( ) . len( ) == T :: MinCandidates :: get( ) as usize ) ;
349+ } else if c > r && non_removals < min_candidates {
350+ // candidates > removals and remaining candidates would be less than min candidates
351+ // => remaining candidates should equal min candidates, i.e. some were removed up to
352+ // the minimum, but then any more were "forced" to stay in candidates.
353+ assert!( <Candidates <T >>:: get( ) . len( ) == min_candidates as usize ) ;
301354 } else {
355+ // removals >= candidates, non removals must == 0
356+ // can't remove more than exist
302357 assert!( <Candidates <T >>:: get( ) . len( ) == pre_length) ;
303358 }
304359 }
0 commit comments