|
4 | 4 |
|
5 | 5 | use {
|
6 | 6 | crate::{
|
7 |
| - find_deposit_authority_program_address, find_stake_program_address, |
8 |
| - find_transient_stake_program_address, find_withdraw_authority_program_address, |
| 7 | + find_deposit_authority_program_address, find_ephemeral_stake_program_address, |
| 8 | + find_stake_program_address, find_transient_stake_program_address, |
| 9 | + find_withdraw_authority_program_address, |
9 | 10 | state::{Fee, FeeType, StakePool, ValidatorList},
|
10 | 11 | MAX_VALIDATORS_TO_UPDATE,
|
11 | 12 | },
|
@@ -401,6 +402,46 @@ pub enum StakePoolInstruction {
|
401 | 402 | /// URI of the uploaded metadata of the spl-token
|
402 | 403 | uri: String,
|
403 | 404 | },
|
| 405 | + |
| 406 | + /// (Staker only) Increase stake on a validator again in an epoch. |
| 407 | + /// |
| 408 | + /// Works regardless if the transient stake account exists. |
| 409 | + /// |
| 410 | + /// Internally, this instruction splits reserve stake into an ephemeral stake |
| 411 | + /// account, activates it, then merges or splits it into the transient stake |
| 412 | + /// account delegated to the appropriate validator. `UpdateValidatorListBalance` |
| 413 | + /// will do the work of merging once it's ready. |
| 414 | + /// |
| 415 | + /// The minimum amount to move is rent-exemption plus |
| 416 | + /// `max(crate::MINIMUM_ACTIVE_STAKE, solana_program::stake::tools::get_minimum_delegation())`. |
| 417 | + /// |
| 418 | + /// 0. `[]` Stake pool |
| 419 | + /// 1. `[s]` Stake pool staker |
| 420 | + /// 2. `[]` Stake pool withdraw authority |
| 421 | + /// 3. `[w]` Validator list |
| 422 | + /// 4. `[w]` Stake pool reserve stake |
| 423 | + /// 5. `[w]` Uninitialized ephemeral stake account to receive stake |
| 424 | + /// 6. `[w]` Transient stake account |
| 425 | + /// 7. `[]` Validator stake account |
| 426 | + /// 8. `[]` Validator vote account to delegate to |
| 427 | + /// 9. '[]' Clock sysvar |
| 428 | + /// 10. `[]` Stake History sysvar |
| 429 | + /// 11. `[]` Stake Config sysvar |
| 430 | + /// 12. `[]` System program |
| 431 | + /// 13. `[]` Stake program |
| 432 | + /// userdata: amount of lamports to increase on the given validator. |
| 433 | + /// The actual amount split into the transient stake account is: |
| 434 | + /// `lamports + stake_rent_exemption` |
| 435 | + /// The rent-exemption of the stake account is withdrawn back to the reserve |
| 436 | + /// after it is merged. |
| 437 | + IncreaseAdditionalValidatorStake { |
| 438 | + /// amount of lamports to increase on the given validator |
| 439 | + lamports: u64, |
| 440 | + /// seed used to create transient stake account |
| 441 | + transient_stake_seed: u64, |
| 442 | + /// seed used to create ephemeral account. |
| 443 | + ephemeral_stake_seed: u64, |
| 444 | + }, |
404 | 445 | }
|
405 | 446 |
|
406 | 447 | /// Creates an 'initialize' instruction.
|
@@ -597,6 +638,52 @@ pub fn increase_validator_stake(
|
597 | 638 | }
|
598 | 639 | }
|
599 | 640 |
|
| 641 | +/// Creates `IncreaseAdditionalValidatorStake` instruction (rebalance from reserve account to |
| 642 | +/// transient account) |
| 643 | +pub fn increase_additional_validator_stake( |
| 644 | + program_id: &Pubkey, |
| 645 | + stake_pool: &Pubkey, |
| 646 | + staker: &Pubkey, |
| 647 | + stake_pool_withdraw_authority: &Pubkey, |
| 648 | + validator_list: &Pubkey, |
| 649 | + reserve_stake: &Pubkey, |
| 650 | + ephemeral_stake: &Pubkey, |
| 651 | + transient_stake: &Pubkey, |
| 652 | + validator_stake: &Pubkey, |
| 653 | + validator: &Pubkey, |
| 654 | + lamports: u64, |
| 655 | + transient_stake_seed: u64, |
| 656 | + ephemeral_stake_seed: u64, |
| 657 | +) -> Instruction { |
| 658 | + let accounts = vec![ |
| 659 | + AccountMeta::new_readonly(*stake_pool, false), |
| 660 | + AccountMeta::new_readonly(*staker, true), |
| 661 | + AccountMeta::new_readonly(*stake_pool_withdraw_authority, false), |
| 662 | + AccountMeta::new(*validator_list, false), |
| 663 | + AccountMeta::new(*reserve_stake, false), |
| 664 | + AccountMeta::new(*ephemeral_stake, false), |
| 665 | + AccountMeta::new(*transient_stake, false), |
| 666 | + AccountMeta::new_readonly(*validator_stake, false), |
| 667 | + AccountMeta::new_readonly(*validator, false), |
| 668 | + AccountMeta::new_readonly(sysvar::clock::id(), false), |
| 669 | + AccountMeta::new_readonly(sysvar::stake_history::id(), false), |
| 670 | + AccountMeta::new_readonly(stake::config::id(), false), |
| 671 | + AccountMeta::new_readonly(system_program::id(), false), |
| 672 | + AccountMeta::new_readonly(stake::program::id(), false), |
| 673 | + ]; |
| 674 | + Instruction { |
| 675 | + program_id: *program_id, |
| 676 | + accounts, |
| 677 | + data: StakePoolInstruction::IncreaseAdditionalValidatorStake { |
| 678 | + lamports, |
| 679 | + transient_stake_seed, |
| 680 | + ephemeral_stake_seed, |
| 681 | + } |
| 682 | + .try_to_vec() |
| 683 | + .unwrap(), |
| 684 | + } |
| 685 | +} |
| 686 | + |
600 | 687 | /// Creates `SetPreferredDepositValidator` instruction
|
601 | 688 | pub fn set_preferred_validator(
|
602 | 689 | program_id: &Pubkey,
|
@@ -724,6 +811,52 @@ pub fn increase_validator_stake_with_vote(
|
724 | 811 | )
|
725 | 812 | }
|
726 | 813 |
|
| 814 | +/// Create an `IncreaseAdditionalValidatorStake` instruction given an existing |
| 815 | +/// stake pool and vote account |
| 816 | +pub fn increase_additional_validator_stake_with_vote( |
| 817 | + program_id: &Pubkey, |
| 818 | + stake_pool: &StakePool, |
| 819 | + stake_pool_address: &Pubkey, |
| 820 | + vote_account_address: &Pubkey, |
| 821 | + lamports: u64, |
| 822 | + validator_stake_seed: Option<NonZeroU32>, |
| 823 | + transient_stake_seed: u64, |
| 824 | + ephemeral_stake_seed: u64, |
| 825 | +) -> Instruction { |
| 826 | + let pool_withdraw_authority = |
| 827 | + find_withdraw_authority_program_address(program_id, stake_pool_address).0; |
| 828 | + let (ephemeral_stake_address, _) = |
| 829 | + find_ephemeral_stake_program_address(program_id, stake_pool_address, ephemeral_stake_seed); |
| 830 | + let (transient_stake_address, _) = find_transient_stake_program_address( |
| 831 | + program_id, |
| 832 | + vote_account_address, |
| 833 | + stake_pool_address, |
| 834 | + transient_stake_seed, |
| 835 | + ); |
| 836 | + let (validator_stake_address, _) = find_stake_program_address( |
| 837 | + program_id, |
| 838 | + vote_account_address, |
| 839 | + stake_pool_address, |
| 840 | + validator_stake_seed, |
| 841 | + ); |
| 842 | + |
| 843 | + increase_additional_validator_stake( |
| 844 | + program_id, |
| 845 | + stake_pool_address, |
| 846 | + &stake_pool.staker, |
| 847 | + &pool_withdraw_authority, |
| 848 | + &stake_pool.validator_list, |
| 849 | + &stake_pool.reserve_stake, |
| 850 | + &ephemeral_stake_address, |
| 851 | + &transient_stake_address, |
| 852 | + &validator_stake_address, |
| 853 | + vote_account_address, |
| 854 | + lamports, |
| 855 | + transient_stake_seed, |
| 856 | + ephemeral_stake_seed, |
| 857 | + ) |
| 858 | +} |
| 859 | + |
727 | 860 | /// Create a `DecreaseValidatorStake` instruction given an existing stake pool and
|
728 | 861 | /// vote account
|
729 | 862 | pub fn decrease_validator_stake_with_vote(
|
|
0 commit comments