1
+ use std:: collections:: HashSet ;
2
+
1
3
use aleph_client:: {
2
4
pallets:: {
3
5
elections:: { ElectionsApi , ElectionsSudoApi } ,
4
6
session:: SessionApi ,
5
- staking:: StakingApi ,
7
+ staking:: { StakingApi , StakingUserApi } ,
6
8
} ,
7
- primitives:: { BanInfo , BanReason } ,
9
+ primitives:: { BanInfo , BanReason , CommitteeSeats , ElectionOpenness } ,
8
10
sp_core:: bounded:: bounded_vec:: BoundedVec ,
9
11
waiting:: { BlockStatus , WaitingExt } ,
10
12
SignedConnection , TxStatus ,
@@ -16,14 +18,15 @@ use primitives::{
16
18
} ;
17
19
18
20
use crate :: {
19
- accounts:: { get_validator_seed, NodeKeys } ,
21
+ accounts:: { account_ids_from_keys , get_validator_seed, NodeKeys } ,
20
22
ban:: {
21
23
check_ban_config, check_ban_event, check_ban_info_for_validator,
22
24
check_underperformed_count_for_sessions, check_underperformed_validator_reason,
23
25
check_underperformed_validator_session_count, check_validators, setup_test,
24
26
} ,
25
27
config,
26
28
rewards:: set_invalid_keys_for_validator,
29
+ validators:: get_test_validators,
27
30
} ;
28
31
29
32
const SESSIONS_TO_CHECK : SessionCount = 5 ;
@@ -50,6 +53,17 @@ async fn disable_validator(validator_address: &str, validator_seed: u32) -> anyh
50
53
set_invalid_keys_for_validator ( & connection_to_disable) . await
51
54
}
52
55
56
+ async fn signed_connection_for_disabled_controller ( ) -> SignedConnection {
57
+ let validator_seed = get_validator_seed ( VALIDATOR_TO_DISABLE_OVERALL_INDEX ) ;
58
+ let stash_controller = NodeKeys :: from ( validator_seed) ;
59
+ let controller_key_to_disable = stash_controller. controller ;
60
+ SignedConnection :: new (
61
+ NODE_TO_DISABLE_ADDRESS . to_string ( ) ,
62
+ controller_key_to_disable,
63
+ )
64
+ . await
65
+ }
66
+
53
67
/// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the
54
68
/// validators. Waits for the offending validator to hit the ban threshold of sessions without
55
69
/// producing blocks. Verifies that the offending validator has in fact been banned out for the
@@ -272,6 +286,83 @@ pub async fn clearing_session_count() -> anyhow::Result<()> {
272
286
Ok ( ( ) )
273
287
}
274
288
289
+ /// Setup reserved validators, non_reserved are set to empty vec. Set ban config ban_period to 2.
290
+ /// Set Openness to Permissionless.
291
+ /// Ban manually one validator. Check if the banned validator is out of the non_reserved and is back
292
+ /// after ban period.
293
+ #[ tokio:: test]
294
+ pub async fn permissionless_ban ( ) -> anyhow:: Result < ( ) > {
295
+ let config = config:: setup_test ( ) ;
296
+ let root_connection = config. create_root_connection ( ) . await ;
297
+
298
+ let validator_keys = get_test_validators ( config) ;
299
+ let reserved_validators = account_ids_from_keys ( & validator_keys. reserved ) ;
300
+ let non_reserved_validators = account_ids_from_keys ( & validator_keys. non_reserved ) ;
301
+
302
+ let seats = CommitteeSeats {
303
+ reserved_seats : 2 ,
304
+ non_reserved_seats : 2 ,
305
+ } ;
306
+
307
+ let validator_to_ban =
308
+ & non_reserved_validators[ VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize ] ;
309
+ let mut non_reserved_without_banned = non_reserved_validators. to_vec ( ) ;
310
+ non_reserved_without_banned. remove ( VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize ) ;
311
+
312
+ let ban_period = 2 ;
313
+ root_connection
314
+ . change_validators (
315
+ Some ( reserved_validators) ,
316
+ Some ( non_reserved_validators. clone ( ) ) ,
317
+ Some ( seats) ,
318
+ TxStatus :: InBlock ,
319
+ )
320
+ . await ?;
321
+ root_connection
322
+ . set_election_openness ( ElectionOpenness :: Permissionless , TxStatus :: InBlock )
323
+ . await ?;
324
+ root_connection
325
+ . set_ban_config ( None , None , None , Some ( ban_period) , TxStatus :: InBlock )
326
+ . await ?;
327
+ root_connection
328
+ . ban_from_committee ( validator_to_ban. clone ( ) , vec ! [ ] , TxStatus :: InBlock )
329
+ . await ?;
330
+ root_connection
331
+ . connection
332
+ . wait_for_n_eras ( 2 , BlockStatus :: Finalized )
333
+ . await ;
334
+
335
+ let without_banned = HashSet :: < _ > :: from_iter ( non_reserved_without_banned) ;
336
+ let non_reserved = HashSet :: < _ > :: from_iter (
337
+ root_connection
338
+ . connection
339
+ . get_current_era_validators ( None )
340
+ . await
341
+ . non_reserved ,
342
+ ) ;
343
+ assert_eq ! ( without_banned, non_reserved) ;
344
+
345
+ let signed_connection = signed_connection_for_disabled_controller ( ) . await ;
346
+ // validate again
347
+ signed_connection. validate ( 0 , TxStatus :: InBlock ) . await ?;
348
+ root_connection
349
+ . connection
350
+ . wait_for_n_eras ( 2 , BlockStatus :: Finalized )
351
+ . await ;
352
+ let expected_non_reserved = HashSet :: < _ > :: from_iter ( non_reserved_validators) ;
353
+ let non_reserved = HashSet :: < _ > :: from_iter (
354
+ root_connection
355
+ . connection
356
+ . get_current_era_validators ( None )
357
+ . await
358
+ . non_reserved ,
359
+ ) ;
360
+
361
+ assert_eq ! ( expected_non_reserved, non_reserved) ;
362
+
363
+ Ok ( ( ) )
364
+ }
365
+
275
366
/// Runs a chain, sets up a committee and validators. Changes the ban config to require 100%
276
367
/// performance. Checks that each validator has all the sessions in which they were chosen for the
277
368
/// committee marked as ones in which they underperformed.
0 commit comments