3
3
#![ allow( clippy:: too_many_arguments) ]
4
4
5
5
use {
6
- crate :: { stake_program, state:: Fee } ,
6
+ crate :: {
7
+ find_stake_program_address, find_transient_stake_program_address, stake_program, state:: Fee ,
8
+ } ,
7
9
borsh:: { BorshDeserialize , BorshSchema , BorshSerialize } ,
8
10
solana_program:: {
9
11
instruction:: { AccountMeta , Instruction } ,
@@ -88,8 +90,9 @@ pub enum StakePoolInstruction {
88
90
/// 3. `[]` New withdraw/staker authority to set in the stake account
89
91
/// 4. `[w]` Validator stake list storage account
90
92
/// 5. `[w]` Stake account to remove from the pool
91
- /// 8. '[]' Sysvar clock
92
- /// 10. `[]` Stake program id,
93
+ /// 6. `[]` Transient stake account, to check that that we're not trying to activate
94
+ /// 7. '[]' Sysvar clock
95
+ /// 8. `[]` Stake program id,
93
96
RemoveValidatorFromPool ,
94
97
95
98
/// (Staker only) Decrease active stake on a validator, eventually moving it to the reserve
@@ -132,7 +135,7 @@ pub enum StakePoolInstruction {
132
135
/// 0. `[]` Stake pool
133
136
/// 1. `[s]` Stake pool staker
134
137
/// 2. `[]` Stake pool withdraw authority
135
- /// 3. `[]` Validator list
138
+ /// 3. `[w ]` Validator list
136
139
/// 4. `[w]` Stake pool reserve stake
137
140
/// 5. `[w]` Transient stake account
138
141
/// 6. `[]` Validator vote account to delegate to
@@ -149,26 +152,36 @@ pub enum StakePoolInstruction {
149
152
///
150
153
/// While going through the pairs of validator and transient stake accounts,
151
154
/// if the transient stake is inactive, it is merged into the reserve stake
152
- /// account. If the transient stake is active and has matching credits
155
+ /// account. If the transient stake is active and has matching credits
153
156
/// observed, it is merged into the canonical validator stake account. In
154
157
/// all other states, nothing is done, and the balance is simply added to
155
158
/// the canonical stake account balance.
156
159
///
157
160
/// 0. `[]` Stake pool
158
- /// 1. `[w]` Validator stake list storage account
159
- /// 2. `[w]` Reserve stake account
160
- /// 3. `[]` Stake pool withdraw authority
161
- /// 4. `[]` Sysvar clock account
162
- /// 5. `[]` Stake program
163
- /// 6. ..6+N ` [] N pairs of validator and transient stake accounts
164
- UpdateValidatorListBalance ,
161
+ /// 1. `[]` Stake pool withdraw authority
162
+ /// 2. `[w]` Validator stake list storage account
163
+ /// 3. `[w]` Reserve stake account
164
+ /// 4. `[]` Sysvar clock
165
+ /// 5. `[]` Sysvar stake history
166
+ /// 6. `[]` Stake program
167
+ /// 7. ..7+N ` [] N pairs of validator and transient stake accounts
168
+ UpdateValidatorListBalance {
169
+ /// Index to start updating on the validator list
170
+ #[ allow( dead_code) ] // but it's not
171
+ start_index : u32 ,
172
+ /// If true, don't try merging transient stake accounts into the reserve or
173
+ /// validator stake account. Useful for testing or if a particular stake
174
+ /// account is in a bad state, but we still want to update
175
+ #[ allow( dead_code) ] // but it's not
176
+ no_merge : bool ,
177
+ } ,
165
178
166
179
/// Updates total pool balance based on balances in the reserve and validator list
167
180
///
168
181
/// 0. `[w]` Stake pool
169
- /// 1. `[]` Validator stake list storage account
170
- /// 2. `[]` Reserve stake account
171
- /// 3. `[]` Stake pool withdraw authority
182
+ /// 1. `[]` Stake pool withdraw authority
183
+ /// 2. `[]` Validator stake list storage account
184
+ /// 3. `[]` Reserve stake account
172
185
/// 4. `[w]` Account to receive pool fee tokens
173
186
/// 5. `[w]` Pool mint account
174
187
/// 6. `[]` Sysvar clock account
@@ -347,6 +360,7 @@ pub fn remove_validator_from_pool(
347
360
new_stake_authority : & Pubkey ,
348
361
validator_list : & Pubkey ,
349
362
stake_account : & Pubkey ,
363
+ transient_stake_account : & Pubkey ,
350
364
) -> Result < Instruction , ProgramError > {
351
365
let accounts = vec ! [
352
366
AccountMeta :: new( * stake_pool, false ) ,
@@ -355,6 +369,7 @@ pub fn remove_validator_from_pool(
355
369
AccountMeta :: new_readonly( * new_stake_authority, false ) ,
356
370
AccountMeta :: new( * validator_list, false ) ,
357
371
AccountMeta :: new( * stake_account, false ) ,
372
+ AccountMeta :: new_readonly( * transient_stake_account, false ) ,
358
373
AccountMeta :: new_readonly( sysvar:: clock:: id( ) , false ) ,
359
374
AccountMeta :: new_readonly( stake_program:: id( ) , false ) ,
360
375
] ;
@@ -413,7 +428,7 @@ pub fn increase_validator_stake(
413
428
AccountMeta :: new_readonly( * stake_pool, false ) ,
414
429
AccountMeta :: new_readonly( * staker, true ) ,
415
430
AccountMeta :: new_readonly( * stake_pool_withdraw_authority, false ) ,
416
- AccountMeta :: new_readonly ( * validator_list, false ) ,
431
+ AccountMeta :: new ( * validator_list, false ) ,
417
432
AccountMeta :: new( * reserve_stake, false ) ,
418
433
AccountMeta :: new( * transient_stake, false ) ,
419
434
AccountMeta :: new_readonly( * validator, false ) ,
@@ -434,45 +449,80 @@ pub fn increase_validator_stake(
434
449
/// Creates `UpdateValidatorListBalance` instruction (update validator stake account balances)
435
450
pub fn update_validator_list_balance (
436
451
program_id : & Pubkey ,
437
- validator_list_storage : & Pubkey ,
438
- validator_list : & [ Pubkey ] ,
439
- ) -> Result < Instruction , ProgramError > {
440
- let mut accounts: Vec < AccountMeta > = validator_list
441
- . iter ( )
442
- . map ( |pubkey| AccountMeta :: new_readonly ( * pubkey, false ) )
443
- . collect ( ) ;
444
- accounts. insert ( 0 , AccountMeta :: new ( * validator_list_storage, false ) ) ;
445
- accounts. insert ( 1 , AccountMeta :: new_readonly ( sysvar:: clock:: id ( ) , false ) ) ;
446
- Ok ( Instruction {
452
+ stake_pool : & Pubkey ,
453
+ stake_pool_withdraw_authority : & Pubkey ,
454
+ validator_list : & Pubkey ,
455
+ reserve_stake : & Pubkey ,
456
+ validator_vote_accounts : & [ Pubkey ] ,
457
+ start_index : u32 ,
458
+ no_merge : bool ,
459
+ ) -> Instruction {
460
+ let mut accounts = vec ! [
461
+ AccountMeta :: new_readonly( * stake_pool, false ) ,
462
+ AccountMeta :: new_readonly( * stake_pool_withdraw_authority, false ) ,
463
+ AccountMeta :: new( * validator_list, false ) ,
464
+ AccountMeta :: new( * reserve_stake, false ) ,
465
+ AccountMeta :: new_readonly( sysvar:: clock:: id( ) , false ) ,
466
+ AccountMeta :: new_readonly( sysvar:: stake_history:: id( ) , false ) ,
467
+ AccountMeta :: new_readonly( stake_program:: id( ) , false ) ,
468
+ ] ;
469
+ accounts. append (
470
+ & mut validator_vote_accounts
471
+ . iter ( )
472
+ . flat_map ( |vote_account_address| {
473
+ let ( validator_stake_account, _) =
474
+ find_stake_program_address ( program_id, vote_account_address, stake_pool) ;
475
+ let ( transient_stake_account, _) = find_transient_stake_program_address (
476
+ program_id,
477
+ vote_account_address,
478
+ stake_pool,
479
+ ) ;
480
+ vec ! [
481
+ AccountMeta :: new( validator_stake_account, false ) ,
482
+ AccountMeta :: new( transient_stake_account, false ) ,
483
+ ]
484
+ } )
485
+ . collect :: < Vec < AccountMeta > > ( ) ,
486
+ ) ;
487
+ Instruction {
447
488
program_id : * program_id,
448
489
accounts,
449
- data : StakePoolInstruction :: UpdateValidatorListBalance . try_to_vec ( ) ?,
450
- } )
490
+ data : StakePoolInstruction :: UpdateValidatorListBalance {
491
+ start_index,
492
+ no_merge,
493
+ }
494
+ . try_to_vec ( )
495
+ . unwrap ( ) ,
496
+ }
451
497
}
452
498
453
499
/// Creates `UpdateStakePoolBalance` instruction (pool balance from the stake account list balances)
454
500
pub fn update_stake_pool_balance (
455
501
program_id : & Pubkey ,
456
502
stake_pool : & Pubkey ,
457
- validator_list_storage : & Pubkey ,
458
503
withdraw_authority : & Pubkey ,
504
+ validator_list_storage : & Pubkey ,
505
+ reserve_stake : & Pubkey ,
459
506
manager_fee_account : & Pubkey ,
460
507
stake_pool_mint : & Pubkey ,
461
- ) -> Result < Instruction , ProgramError > {
508
+ ) -> Instruction {
462
509
let accounts = vec ! [
463
510
AccountMeta :: new( * stake_pool, false ) ,
464
- AccountMeta :: new( * validator_list_storage, false ) ,
465
511
AccountMeta :: new_readonly( * withdraw_authority, false ) ,
512
+ AccountMeta :: new_readonly( * validator_list_storage, false ) ,
513
+ AccountMeta :: new_readonly( * reserve_stake, false ) ,
466
514
AccountMeta :: new( * manager_fee_account, false ) ,
467
515
AccountMeta :: new( * stake_pool_mint, false ) ,
468
516
AccountMeta :: new_readonly( sysvar:: clock:: id( ) , false ) ,
469
517
AccountMeta :: new_readonly( spl_token:: id( ) , false ) ,
470
518
] ;
471
- Ok ( Instruction {
519
+ Instruction {
472
520
program_id : * program_id,
473
521
accounts,
474
- data : StakePoolInstruction :: UpdateStakePoolBalance . try_to_vec ( ) ?,
475
- } )
522
+ data : StakePoolInstruction :: UpdateStakePoolBalance
523
+ . try_to_vec ( )
524
+ . unwrap ( ) ,
525
+ }
476
526
}
477
527
478
528
/// Creates a 'Deposit' instruction.
0 commit comments