Skip to content

Commit

Permalink
stake-pool: Add DecreaseAdditionalValidatorStake instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
joncinque committed Dec 16, 2022
1 parent c750e03 commit 8e35844
Show file tree
Hide file tree
Showing 5 changed files with 701 additions and 206 deletions.
120 changes: 118 additions & 2 deletions stake-pool/program/src/instruction.rs
Expand Up @@ -4,8 +4,9 @@

use {
crate::{
find_deposit_authority_program_address, find_stake_program_address,
find_transient_stake_program_address, find_withdraw_authority_program_address,
find_deposit_authority_program_address, find_ephemeral_stake_program_address,
find_stake_program_address, find_transient_stake_program_address,
find_withdraw_authority_program_address,
state::{Fee, FeeType, StakePool, ValidatorList},
MAX_VALIDATORS_TO_UPDATE,
},
Expand Down Expand Up @@ -401,6 +402,37 @@ pub enum StakePoolInstruction {
/// URI of the uploaded metadata of the spl-token
uri: String,
},

/// (Staker only) Decrease active stake again from a validator, eventually moving it to the reserve
///
/// Works regardless if the transient stake account already exists.
///
/// Internally, this instruction splits a validator stake account into an
/// ephemeral stake account, deactivates it, then merges or splits it into
/// the transient stake account delegated to the appropriate validator.
///
/// The amount of lamports to move must be at least rent-exemption plus
/// `max(crate::MINIMUM_ACTIVE_STAKE, solana_program::stake::tools::get_minimum_delegation())`.
///
/// 0. `[]` Stake pool
/// 1. `[s]` Stake pool staker
/// 2. `[]` Stake pool withdraw authority
/// 3. `[w]` Validator list
/// 4. `[w]` Canonical stake account to split from
/// 5. `[w]` Uninitialized ephemeral stake account to receive stake
/// 6. `[w]` Transient stake account
/// 7. `[]` Clock sysvar
/// 8. '[]' Stake history sysvar
/// 9. `[]` System program
/// 10. `[]` Stake program
DecreaseAdditionalValidatorStake {
/// amount of lamports to split into the transient stake account
lamports: u64,
/// seed used to create transient stake account
transient_stake_seed: u64,
/// seed used to create ephemeral account.
ephemeral_stake_seed: u64,
},
}

/// Creates an 'initialize' instruction.
Expand Down Expand Up @@ -554,6 +586,47 @@ pub fn decrease_validator_stake(
}
}

/// Creates `DecreaseAdditionalValidatorStake` instruction (rebalance from
/// validator account to transient account)
pub fn decrease_additional_validator_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
validator_stake: &Pubkey,
ephemeral_stake: &Pubkey,
transient_stake: &Pubkey,
lamports: u64,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*validator_stake, false),
AccountMeta::new(*ephemeral_stake, false),
AccountMeta::new(*transient_stake, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: StakePoolInstruction::DecreaseAdditionalValidatorStake {
lamports,
transient_stake_seed,
ephemeral_stake_seed,
}
.try_to_vec()
.unwrap(),
}
}

/// Creates `IncreaseValidatorStake` instruction (rebalance from reserve account to
/// transient account)
pub fn increase_validator_stake(
Expand Down Expand Up @@ -762,6 +835,49 @@ pub fn decrease_validator_stake_with_vote(
)
}

/// Create a `DecreaseAdditionalValidatorStake` instruction given an existing
/// stake pool and vote account
pub fn decrease_additional_validator_stake_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
validator_stake_seed: Option<NonZeroU32>,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (validator_stake_address, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
validator_stake_seed,
);
let (ephemeral_stake_address, _) =
find_ephemeral_stake_program_address(program_id, stake_pool_address, ephemeral_stake_seed);
let (transient_stake_address, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
transient_stake_seed,
);
decrease_additional_validator_stake(
program_id,
stake_pool_address,
&stake_pool.staker,
&pool_withdraw_authority,
&stake_pool.validator_list,
&validator_stake_address,
&ephemeral_stake_address,
&transient_stake_address,
lamports,
transient_stake_seed,
ephemeral_stake_seed,
)
}

/// Creates `UpdateValidatorListBalance` instruction (update validator stake account balances)
pub fn update_validator_list_balance(
program_id: &Pubkey,
Expand Down
19 changes: 19 additions & 0 deletions stake-pool/program/src/lib.rs
Expand Up @@ -28,6 +28,9 @@ const AUTHORITY_WITHDRAW: &[u8] = b"withdraw";
/// Seed for transient stake account
const TRANSIENT_STAKE_SEED_PREFIX: &[u8] = b"transient";

/// Seed for ephemeral stake account
const EPHEMERAL_STAKE_SEED_PREFIX: &[u8] = b"ephemeral";

/// Minimum amount of staked lamports required in a validator stake account to allow
/// for merges without a mismatch on credits observed
pub const MINIMUM_ACTIVE_STAKE: u64 = 1_000_000;
Expand Down Expand Up @@ -138,6 +141,22 @@ pub fn find_transient_stake_program_address(
)
}

/// Generates the ephemeral program address for stake pool redelegation
pub fn find_ephemeral_stake_program_address(
program_id: &Pubkey,
stake_pool_address: &Pubkey,
seed: u64,
) -> (Pubkey, u8) {
Pubkey::find_program_address(
&[
EPHEMERAL_STAKE_SEED_PREFIX,
stake_pool_address.as_ref(),
&seed.to_le_bytes(),
],
program_id,
)
}

solana_program::declare_id!("SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy");

#[cfg(test)]
Expand Down

0 comments on commit 8e35844

Please sign in to comment.