11
11
solana_cli_output:: { parse_sign_only_reply_string, OutputFormat } ,
12
12
solana_faucet:: faucet:: run_local_faucet,
13
13
solana_rpc_client:: rpc_client:: RpcClient ,
14
- solana_rpc_client_api:: response:: { RpcStakeActivation , StakeActivationState } ,
14
+ solana_rpc_client_api:: {
15
+ request:: DELINQUENT_VALIDATOR_SLOT_DISTANCE ,
16
+ response:: { RpcStakeActivation , StakeActivationState } ,
17
+ } ,
15
18
solana_rpc_client_nonce_utils:: blockhash_query:: { self , BlockhashQuery } ,
16
19
solana_sdk:: {
17
20
account_utils:: StateMut ,
@@ -295,8 +298,23 @@ fn test_stake_delegation_force() {
295
298
let mint_pubkey = mint_keypair. pubkey ( ) ;
296
299
let authorized_withdrawer = Keypair :: new ( ) . pubkey ( ) ;
297
300
let faucet_addr = run_local_faucet ( mint_keypair, None ) ;
298
- let test_validator =
299
- TestValidator :: with_no_fees ( mint_pubkey, Some ( faucet_addr) , SocketAddrSpace :: Unspecified ) ;
301
+ let slots_per_epoch = 32 ;
302
+ let test_validator = TestValidatorGenesis :: default ( )
303
+ . fee_rate_governor ( FeeRateGovernor :: new ( 0 , 0 ) )
304
+ . rent ( Rent {
305
+ lamports_per_byte_year : 1 ,
306
+ exemption_threshold : 1.0 ,
307
+ ..Rent :: default ( )
308
+ } )
309
+ . epoch_schedule ( EpochSchedule :: custom (
310
+ slots_per_epoch,
311
+ slots_per_epoch,
312
+ /* enable_warmup_epochs = */ false ,
313
+ ) )
314
+ . faucet_addr ( Some ( faucet_addr) )
315
+ . warp_slot ( DELINQUENT_VALIDATOR_SLOT_DISTANCE * 2 ) // get out in front of the cli voter delinquency check
316
+ . start_with_mint_address ( mint_pubkey, SocketAddrSpace :: Unspecified )
317
+ . expect ( "validator start failed" ) ;
300
318
301
319
let rpc_client =
302
320
RpcClient :: new_with_commitment ( test_validator. rpc_url ( ) , CommitmentConfig :: processed ( ) ) ;
@@ -345,7 +363,7 @@ fn test_stake_delegation_force() {
345
363
withdrawer : None ,
346
364
withdrawer_signer : None ,
347
365
lockup : Lockup :: default ( ) ,
348
- amount : SpendAmount :: Some ( 50_000_000_000 ) ,
366
+ amount : SpendAmount :: Some ( 25_000_000_000 ) ,
349
367
sign_only : false ,
350
368
dump_transaction_message : false ,
351
369
blockhash_query : BlockhashQuery :: All ( blockhash_query:: Source :: Cluster ) ,
@@ -358,7 +376,7 @@ fn test_stake_delegation_force() {
358
376
} ;
359
377
process_command ( & config) . unwrap ( ) ;
360
378
361
- // Delegate stake fails (vote account had never voted)
379
+ // Delegate stake succeeds despite no votes, because voter has zero stake
362
380
config. signers = vec ! [ & default_signer] ;
363
381
config. command = CliCommand :: DelegateStake {
364
382
stake_account_pubkey : stake_keypair. pubkey ( ) ,
@@ -375,11 +393,55 @@ fn test_stake_delegation_force() {
375
393
redelegation_stake_account : None ,
376
394
compute_unit_price : None ,
377
395
} ;
396
+ process_command ( & config) . unwrap ( ) ;
397
+
398
+ // Create a second stake account
399
+ let stake_keypair2 = Keypair :: new ( ) ;
400
+ config. signers = vec ! [ & default_signer, & stake_keypair2] ;
401
+ config. command = CliCommand :: CreateStakeAccount {
402
+ stake_account : 1 ,
403
+ seed : None ,
404
+ staker : None ,
405
+ withdrawer : None ,
406
+ withdrawer_signer : None ,
407
+ lockup : Lockup :: default ( ) ,
408
+ amount : SpendAmount :: Some ( 25_000_000_000 ) ,
409
+ sign_only : false ,
410
+ dump_transaction_message : false ,
411
+ blockhash_query : BlockhashQuery :: All ( blockhash_query:: Source :: Cluster ) ,
412
+ nonce_account : None ,
413
+ nonce_authority : 0 ,
414
+ memo : None ,
415
+ fee_payer : 0 ,
416
+ from : 0 ,
417
+ compute_unit_price : None ,
418
+ } ;
419
+ process_command ( & config) . unwrap ( ) ;
420
+
421
+ wait_for_next_epoch_plus_n_slots ( & rpc_client, 1 ) ;
422
+
423
+ // Delegate stake2 fails because voter has not voted, but is now staked
424
+ config. signers = vec ! [ & default_signer] ;
425
+ config. command = CliCommand :: DelegateStake {
426
+ stake_account_pubkey : stake_keypair2. pubkey ( ) ,
427
+ vote_account_pubkey : vote_keypair. pubkey ( ) ,
428
+ stake_authority : 0 ,
429
+ force : false ,
430
+ sign_only : false ,
431
+ dump_transaction_message : false ,
432
+ blockhash_query : BlockhashQuery :: default ( ) ,
433
+ nonce_account : None ,
434
+ nonce_authority : 0 ,
435
+ memo : None ,
436
+ fee_payer : 0 ,
437
+ redelegation_stake_account : None ,
438
+ compute_unit_price : None ,
439
+ } ;
378
440
process_command ( & config) . unwrap_err ( ) ;
379
441
380
442
// But if we force it, it works anyway!
381
443
config. command = CliCommand :: DelegateStake {
382
- stake_account_pubkey : stake_keypair . pubkey ( ) ,
444
+ stake_account_pubkey : stake_keypair2 . pubkey ( ) ,
383
445
vote_account_pubkey : vote_keypair. pubkey ( ) ,
384
446
stake_authority : 0 ,
385
447
force : true ,
0 commit comments