33#![ allow( clippy:: too_many_arguments) ]
44
55use {
6- crate :: { stake_program, state:: Fee } ,
6+ crate :: {
7+ find_stake_program_address, find_transient_stake_program_address, stake_program, state:: Fee ,
8+ } ,
79 borsh:: { BorshDeserialize , BorshSchema , BorshSerialize } ,
810 solana_program:: {
911 instruction:: { AccountMeta , Instruction } ,
@@ -88,8 +90,9 @@ pub enum StakePoolInstruction {
8890 /// 3. `[]` New withdraw/staker authority to set in the stake account
8991 /// 4. `[w]` Validator stake list storage account
9092 /// 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,
9396 RemoveValidatorFromPool ,
9497
9598 /// (Staker only) Decrease active stake on a validator, eventually moving it to the reserve
@@ -132,7 +135,7 @@ pub enum StakePoolInstruction {
132135 /// 0. `[]` Stake pool
133136 /// 1. `[s]` Stake pool staker
134137 /// 2. `[]` Stake pool withdraw authority
135- /// 3. `[]` Validator list
138+ /// 3. `[w ]` Validator list
136139 /// 4. `[w]` Stake pool reserve stake
137140 /// 5. `[w]` Transient stake account
138141 /// 6. `[]` Validator vote account to delegate to
@@ -149,26 +152,36 @@ pub enum StakePoolInstruction {
149152 ///
150153 /// While going through the pairs of validator and transient stake accounts,
151154 /// 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
153156 /// observed, it is merged into the canonical validator stake account. In
154157 /// all other states, nothing is done, and the balance is simply added to
155158 /// the canonical stake account balance.
156159 ///
157160 /// 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+ } ,
165178
166179 /// Updates total pool balance based on balances in the reserve and validator list
167180 ///
168181 /// 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
172185 /// 4. `[w]` Account to receive pool fee tokens
173186 /// 5. `[w]` Pool mint account
174187 /// 6. `[]` Sysvar clock account
@@ -347,6 +360,7 @@ pub fn remove_validator_from_pool(
347360 new_stake_authority : & Pubkey ,
348361 validator_list : & Pubkey ,
349362 stake_account : & Pubkey ,
363+ transient_stake_account : & Pubkey ,
350364) -> Result < Instruction , ProgramError > {
351365 let accounts = vec ! [
352366 AccountMeta :: new( * stake_pool, false ) ,
@@ -355,6 +369,7 @@ pub fn remove_validator_from_pool(
355369 AccountMeta :: new_readonly( * new_stake_authority, false ) ,
356370 AccountMeta :: new( * validator_list, false ) ,
357371 AccountMeta :: new( * stake_account, false ) ,
372+ AccountMeta :: new_readonly( * transient_stake_account, false ) ,
358373 AccountMeta :: new_readonly( sysvar:: clock:: id( ) , false ) ,
359374 AccountMeta :: new_readonly( stake_program:: id( ) , false ) ,
360375 ] ;
@@ -413,7 +428,7 @@ pub fn increase_validator_stake(
413428 AccountMeta :: new_readonly( * stake_pool, false ) ,
414429 AccountMeta :: new_readonly( * staker, true ) ,
415430 AccountMeta :: new_readonly( * stake_pool_withdraw_authority, false ) ,
416- AccountMeta :: new_readonly ( * validator_list, false ) ,
431+ AccountMeta :: new ( * validator_list, false ) ,
417432 AccountMeta :: new( * reserve_stake, false ) ,
418433 AccountMeta :: new( * transient_stake, false ) ,
419434 AccountMeta :: new_readonly( * validator, false ) ,
@@ -434,45 +449,80 @@ pub fn increase_validator_stake(
434449/// Creates `UpdateValidatorListBalance` instruction (update validator stake account balances)
435450pub fn update_validator_list_balance (
436451 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 {
447488 program_id : * program_id,
448489 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+ }
451497}
452498
453499/// Creates `UpdateStakePoolBalance` instruction (pool balance from the stake account list balances)
454500pub fn update_stake_pool_balance (
455501 program_id : & Pubkey ,
456502 stake_pool : & Pubkey ,
457- validator_list_storage : & Pubkey ,
458503 withdraw_authority : & Pubkey ,
504+ validator_list_storage : & Pubkey ,
505+ reserve_stake : & Pubkey ,
459506 manager_fee_account : & Pubkey ,
460507 stake_pool_mint : & Pubkey ,
461- ) -> Result < Instruction , ProgramError > {
508+ ) -> Instruction {
462509 let accounts = vec ! [
463510 AccountMeta :: new( * stake_pool, false ) ,
464- AccountMeta :: new( * validator_list_storage, false ) ,
465511 AccountMeta :: new_readonly( * withdraw_authority, false ) ,
512+ AccountMeta :: new_readonly( * validator_list_storage, false ) ,
513+ AccountMeta :: new_readonly( * reserve_stake, false ) ,
466514 AccountMeta :: new( * manager_fee_account, false ) ,
467515 AccountMeta :: new( * stake_pool_mint, false ) ,
468516 AccountMeta :: new_readonly( sysvar:: clock:: id( ) , false ) ,
469517 AccountMeta :: new_readonly( spl_token:: id( ) , false ) ,
470518 ] ;
471- Ok ( Instruction {
519+ Instruction {
472520 program_id : * program_id,
473521 accounts,
474- data : StakePoolInstruction :: UpdateStakePoolBalance . try_to_vec ( ) ?,
475- } )
522+ data : StakePoolInstruction :: UpdateStakePoolBalance
523+ . try_to_vec ( )
524+ . unwrap ( ) ,
525+ }
476526}
477527
478528/// Creates a 'Deposit' instruction.
0 commit comments