Reboot program address derivation helpers

This commit is contained in:
Michael Vines 2021-03-31 22:24:35 -07:00
parent 8b989d562b
commit 48ab307cad
7 changed files with 143 additions and 178 deletions

View File

@ -79,9 +79,9 @@ pub(crate) fn get_stake_state(
Ok(stake_state) Ok(stake_state)
} }
pub(crate) fn get_stake_accounts_by_withdrawer( pub(crate) fn get_stake_accounts_by_withdraw_authority(
rpc_client: &RpcClient, rpc_client: &RpcClient,
withdrawer: &Pubkey, withdraw_authority: &Pubkey,
) -> Result<Vec<(Pubkey, u64, stake_program::StakeState)>, ClientError> { ) -> Result<Vec<(Pubkey, u64, stake_program::StakeState)>, ClientError> {
rpc_client rpc_client
.get_program_accounts_with_config( .get_program_accounts_with_config(
@ -89,7 +89,7 @@ pub(crate) fn get_stake_accounts_by_withdrawer(
RpcProgramAccountsConfig { RpcProgramAccountsConfig {
filters: Some(vec![RpcFilterType::Memcmp(Memcmp { filters: Some(vec![RpcFilterType::Memcmp(Memcmp {
offset: 44, // 44 is Withdrawer authority offset in stake account stake offset: 44, // 44 is Withdrawer authority offset in stake account stake
bytes: MemcmpEncodedBytes::Binary(format!("{}", withdrawer)), bytes: MemcmpEncodedBytes::Binary(format!("{}", withdraw_authority)),
encoding: None, encoding: None,
})]), })]),
account_config: RpcAccountInfoConfig { account_config: RpcAccountInfoConfig {

View File

@ -28,10 +28,10 @@ use {
spl_stake_pool::{ spl_stake_pool::{
self, self,
borsh::get_instance_packed_len, borsh::get_instance_packed_len,
create_pool_authority_address, find_authority_bump_seed, find_stake_address_for_validator, find_deposit_authority_program_address, find_stake_program_address,
find_withdraw_authority_program_address,
stake_program::{self, StakeAuthorize, StakeState}, stake_program::{self, StakeAuthorize, StakeState},
state::{StakePool, ValidatorList}, state::{StakePool, ValidatorList},
AUTHORITY_DEPOSIT, AUTHORITY_WITHDRAW,
}, },
std::process::exit, std::process::exit,
}; };
@ -133,11 +133,8 @@ fn command_create_pool(
let default_decimals = spl_token::native_mint::DECIMALS; let default_decimals = spl_token::native_mint::DECIMALS;
// Calculate withdraw authority used for minting pool tokens // Calculate withdraw authority used for minting pool tokens
let (withdraw_authority, _) = find_authority_bump_seed( let (withdraw_authority, _) =
&spl_stake_pool::id(), find_withdraw_authority_program_address(&spl_stake_pool::id(), &pool_account.pubkey());
&pool_account.pubkey(),
AUTHORITY_WITHDRAW,
);
if config.verbose { if config.verbose {
println!("Stake pool withdraw authority {}", withdraw_authority); println!("Stake pool withdraw authority {}", withdraw_authority);
@ -227,9 +224,13 @@ fn command_create_pool(
Ok(()) Ok(())
} }
fn command_vsa_create(config: &Config, pool: &Pubkey, vote_account: &Pubkey) -> CommandResult { fn command_vsa_create(
config: &Config,
stake_pool_address: &Pubkey,
vote_account: &Pubkey,
) -> CommandResult {
let (stake_account, _) = let (stake_account, _) =
find_stake_address_for_validator(&spl_stake_pool::id(), &vote_account, &pool); find_stake_program_address(&spl_stake_pool::id(), &vote_account, &stake_pool_address);
println!("Creating stake account {}", stake_account); println!("Creating stake account {}", stake_account);
@ -238,7 +239,7 @@ fn command_vsa_create(config: &Config, pool: &Pubkey, vote_account: &Pubkey) ->
// Create new validator stake account address // Create new validator stake account address
spl_stake_pool::instruction::create_validator_stake_account( spl_stake_pool::instruction::create_validator_stake_account(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&pool, &stake_pool_address,
&config.owner.pubkey(), &config.owner.pubkey(),
&config.fee_payer.pubkey(), &config.fee_payer.pubkey(),
&stake_account, &stake_account,
@ -260,7 +261,7 @@ fn command_vsa_create(config: &Config, pool: &Pubkey, vote_account: &Pubkey) ->
fn command_vsa_add( fn command_vsa_add(
config: &Config, config: &Config,
pool: &Pubkey, stake_pool_address: &Pubkey,
stake: &Pubkey, stake: &Pubkey,
token_receiver: &Option<Pubkey>, token_receiver: &Option<Pubkey>,
) -> CommandResult { ) -> CommandResult {
@ -269,10 +270,10 @@ fn command_vsa_add(
} }
if !config.no_update { if !config.no_update {
command_update(config, pool)?; command_update(config, stake_pool_address)?;
} }
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
let mut total_rent_free_balances: u64 = 0; let mut total_rent_free_balances: u64 = 0;
@ -295,20 +296,11 @@ fn command_vsa_add(
)?; )?;
// Calculate Deposit and Withdraw stake pool authorities // Calculate Deposit and Withdraw stake pool authorities
let pool_deposit_authority: Pubkey = create_pool_authority_address( let pool_deposit_authority =
&spl_stake_pool::id(), find_deposit_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
pool,
AUTHORITY_DEPOSIT, let pool_withdraw_authority =
stake_pool.deposit_bump_seed, find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
)
.unwrap();
let pool_withdraw_authority: Pubkey = create_pool_authority_address(
&spl_stake_pool::id(),
pool,
AUTHORITY_WITHDRAW,
stake_pool.withdraw_bump_seed,
)
.unwrap();
instructions.extend(vec![ instructions.extend(vec![
// Set Withdrawer on stake account to Deposit authority of the stake pool // Set Withdrawer on stake account to Deposit authority of the stake pool
@ -328,7 +320,7 @@ fn command_vsa_add(
// Add validator stake account to the pool // Add validator stake account to the pool
spl_stake_pool::instruction::add_validator_to_pool( spl_stake_pool::instruction::add_validator_to_pool(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&pool, &stake_pool_address,
&config.owner.pubkey(), &config.owner.pubkey(),
&pool_deposit_authority, &pool_deposit_authority,
&pool_withdraw_authority, &pool_withdraw_authority,
@ -356,23 +348,18 @@ fn command_vsa_add(
fn command_vsa_remove( fn command_vsa_remove(
config: &Config, config: &Config,
pool: &Pubkey, stake_pool_address: &Pubkey,
stake: &Pubkey, stake: &Pubkey,
withdraw_from: &Pubkey, withdraw_from: &Pubkey,
new_authority: &Option<Pubkey>, new_authority: &Option<Pubkey>,
) -> CommandResult { ) -> CommandResult {
if !config.no_update { if !config.no_update {
command_update(config, pool)?; command_update(config, stake_pool_address)?;
} }
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
let pool_withdraw_authority: Pubkey = create_pool_authority_address( let pool_withdraw_authority =
&spl_stake_pool::id(), find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
pool,
AUTHORITY_WITHDRAW,
stake_pool.withdraw_bump_seed,
)
.unwrap();
let owner_pubkey = config.owner.pubkey(); let owner_pubkey = config.owner.pubkey();
let new_authority = new_authority.as_ref().unwrap_or(&owner_pubkey); let new_authority = new_authority.as_ref().unwrap_or(&owner_pubkey);
@ -409,7 +396,7 @@ fn command_vsa_remove(
// Create new validator stake account address // Create new validator stake account address
spl_stake_pool::instruction::remove_validator_from_pool( spl_stake_pool::instruction::remove_validator_from_pool(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&pool, &stake_pool_address,
&config.owner.pubkey(), &config.owner.pubkey(),
&pool_withdraw_authority, &pool_withdraw_authority,
&new_authority, &new_authority,
@ -482,21 +469,21 @@ where
fn command_deposit( fn command_deposit(
config: &Config, config: &Config,
pool: &Pubkey, stake_pool_address: &Pubkey,
stake: &Pubkey, stake: &Pubkey,
token_receiver: &Option<Pubkey>, token_receiver: &Option<Pubkey>,
) -> CommandResult { ) -> CommandResult {
if !config.no_update { if !config.no_update {
command_update(config, pool)?; command_update(config, stake_pool_address)?;
} }
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
let stake_state = get_stake_state(&config.rpc_client, &stake)?; let stake_state = get_stake_state(&config.rpc_client, &stake)?;
if config.verbose { if config.verbose {
println!("Depositing stake account {:?}", stake_state); println!("Depositing stake account {:?}", stake_state);
} }
let vote_account: Pubkey = match stake_state { let vote_account = match stake_state {
StakeState::Stake(_, stake) => Ok(stake.delegation.voter_pubkey), StakeState::Stake(_, stake) => Ok(stake.delegation.voter_pubkey),
_ => Err("Wrong stake account state, must be delegated to validator"), _ => Err("Wrong stake account state, must be delegated to validator"),
}?; }?;
@ -509,7 +496,7 @@ fn command_deposit(
// Calculate validator stake account address linked to the pool // Calculate validator stake account address linked to the pool
let (validator_stake_account, _) = let (validator_stake_account, _) =
find_stake_address_for_validator(&spl_stake_pool::id(), &vote_account, pool); find_stake_program_address(&spl_stake_pool::id(), &vote_account, stake_pool_address);
let validator_stake_state = get_stake_state(&config.rpc_client, &validator_stake_account)?; let validator_stake_state = get_stake_state(&config.rpc_client, &validator_stake_account)?;
println!("Depositing into stake account {}", validator_stake_account); println!("Depositing into stake account {}", validator_stake_account);
@ -538,20 +525,11 @@ fn command_deposit(
)?; )?;
// Calculate Deposit and Withdraw stake pool authorities // Calculate Deposit and Withdraw stake pool authorities
let pool_deposit_authority: Pubkey = create_pool_authority_address( let pool_deposit_authority =
&spl_stake_pool::id(), find_deposit_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
pool,
AUTHORITY_DEPOSIT, let pool_withdraw_authority =
stake_pool.deposit_bump_seed, find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
)
.unwrap();
let pool_withdraw_authority: Pubkey = create_pool_authority_address(
&spl_stake_pool::id(),
pool,
AUTHORITY_WITHDRAW,
stake_pool.withdraw_bump_seed,
)
.unwrap();
instructions.extend(vec![ instructions.extend(vec![
// Set Withdrawer on stake account to Deposit authority of the stake pool // Set Withdrawer on stake account to Deposit authority of the stake pool
@ -571,7 +549,7 @@ fn command_deposit(
// Add stake account to the pool // Add stake account to the pool
spl_stake_pool::instruction::deposit( spl_stake_pool::instruction::deposit(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&pool, &stake_pool_address,
&stake_pool.validator_list, &stake_pool.validator_list,
&pool_deposit_authority, &pool_deposit_authority,
&pool_withdraw_authority, &pool_withdraw_authority,
@ -598,8 +576,8 @@ fn command_deposit(
Ok(()) Ok(())
} }
fn command_list(config: &Config, pool: &Pubkey) -> CommandResult { fn command_list(config: &Config, stake_pool_address: &Pubkey) -> CommandResult {
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
if config.verbose { if config.verbose {
println!("Current validator list"); println!("Current validator list");
@ -612,15 +590,11 @@ fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
} }
} }
let pool_withdraw_authority: Pubkey = create_pool_authority_address( let pool_withdraw_authority =
&spl_stake_pool::id(), find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
pool,
AUTHORITY_WITHDRAW,
stake_pool.withdraw_bump_seed,
)
.unwrap();
let accounts = get_stake_accounts_by_withdrawer(&config.rpc_client, &pool_withdraw_authority)?; let accounts =
get_stake_accounts_by_withdraw_authority(&config.rpc_client, &pool_withdraw_authority)?;
if accounts.is_empty() { if accounts.is_empty() {
return Err("No accounts found.".to_string().into()); return Err("No accounts found.".to_string().into());
} }
@ -640,8 +614,8 @@ fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
Ok(()) Ok(())
} }
fn command_update(config: &Config, pool: &Pubkey) -> CommandResult { fn command_update(config: &Config, stake_pool_address: &Pubkey) -> CommandResult {
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
let validator_list = get_validator_list(&config.rpc_client, &stake_pool.validator_list)?; let validator_list = get_validator_list(&config.rpc_client, &stake_pool.validator_list)?;
let epoch_info = config.rpc_client.get_epoch_info()?; let epoch_info = config.rpc_client.get_epoch_info()?;
@ -652,10 +626,10 @@ fn command_update(config: &Config, pool: &Pubkey) -> CommandResult {
if item.last_update_epoch >= epoch_info.epoch { if item.last_update_epoch >= epoch_info.epoch {
None None
} else { } else {
let (stake_account, _) = find_stake_address_for_validator( let (stake_account, _) = find_stake_program_address(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&item.vote_account, &item.vote_account,
&pool, &stake_pool_address,
); );
Some(stake_account) Some(stake_account)
} }
@ -679,7 +653,7 @@ fn command_update(config: &Config, pool: &Pubkey) -> CommandResult {
println!("Updating stake pool..."); println!("Updating stake pool...");
instructions.push(spl_stake_pool::instruction::update_stake_pool_balance( instructions.push(spl_stake_pool::instruction::update_stake_pool_balance(
&spl_stake_pool::id(), &spl_stake_pool::id(),
pool, stake_pool_address,
&stake_pool.validator_list, &stake_pool.validator_list,
)?); )?);
@ -706,7 +680,8 @@ fn prepare_withdraw_accounts(
pool_withdraw_authority: &Pubkey, pool_withdraw_authority: &Pubkey,
pool_amount: u64, pool_amount: u64,
) -> Result<Vec<WithdrawAccount>, Error> { ) -> Result<Vec<WithdrawAccount>, Error> {
let mut accounts = get_stake_accounts_by_withdrawer(rpc_client, &pool_withdraw_authority)?; let mut accounts =
get_stake_accounts_by_withdraw_authority(rpc_client, &pool_withdraw_authority)?;
if accounts.is_empty() { if accounts.is_empty() {
return Err("No accounts found.".to_string().into()); return Err("No accounts found.".to_string().into());
} }
@ -756,26 +731,21 @@ fn prepare_withdraw_accounts(
fn command_withdraw( fn command_withdraw(
config: &Config, config: &Config,
pool: &Pubkey, stake_pool_address: &Pubkey,
pool_amount: f64, pool_amount: f64,
withdraw_from: &Pubkey, withdraw_from: &Pubkey,
stake_receiver_param: &Option<Pubkey>, stake_receiver_param: &Option<Pubkey>,
) -> CommandResult { ) -> CommandResult {
if !config.no_update { if !config.no_update {
command_update(config, pool)?; command_update(config, stake_pool_address)?;
} }
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
let pool_mint = get_token_mint(&config.rpc_client, &stake_pool.pool_mint)?; let pool_mint = get_token_mint(&config.rpc_client, &stake_pool.pool_mint)?;
let pool_amount = spl_token::ui_amount_to_amount(pool_amount, pool_mint.decimals); let pool_amount = spl_token::ui_amount_to_amount(pool_amount, pool_mint.decimals);
let pool_withdraw_authority: Pubkey = create_pool_authority_address( let pool_withdraw_authority =
&spl_stake_pool::id(), find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
pool,
AUTHORITY_WITHDRAW,
stake_pool.withdraw_bump_seed,
)
.unwrap();
// Check withdraw_from account type // Check withdraw_from account type
let token_account = let token_account =
@ -866,7 +836,7 @@ fn command_withdraw(
instructions.push(spl_stake_pool::instruction::withdraw( instructions.push(spl_stake_pool::instruction::withdraw(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&pool, &stake_pool_address,
&stake_pool.validator_list, &stake_pool.validator_list,
&pool_withdraw_authority, &pool_withdraw_authority,
&withdraw_account.address, &withdraw_account.address,
@ -895,11 +865,11 @@ fn command_withdraw(
fn command_set_owner( fn command_set_owner(
config: &Config, config: &Config,
pool: &Pubkey, stake_pool_address: &Pubkey,
new_owner: &Option<Pubkey>, new_owner: &Option<Pubkey>,
new_fee_receiver: &Option<Pubkey>, new_fee_receiver: &Option<Pubkey>,
) -> CommandResult { ) -> CommandResult {
let stake_pool = get_stake_pool(&config.rpc_client, pool)?; let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
// If new accounts are missing in the arguments use the old ones // If new accounts are missing in the arguments use the old ones
let new_owner = match new_owner { let new_owner = match new_owner {
@ -924,7 +894,7 @@ fn command_set_owner(
let mut transaction = Transaction::new_with_payer( let mut transaction = Transaction::new_with_payer(
&[spl_stake_pool::instruction::set_owner( &[spl_stake_pool::instruction::set_owner(
&spl_stake_pool::id(), &spl_stake_pool::id(),
&pool, &stake_pool_address,
&config.owner.pubkey(), &config.owner.pubkey(),
&new_owner, &new_owner,
&new_fee_receiver, &new_fee_receiver,
@ -1327,20 +1297,20 @@ fn main() {
) )
} }
("create-validator-stake", Some(arg_matches)) => { ("create-validator-stake", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
let vote_account: Pubkey = pubkey_of(arg_matches, "vote_account").unwrap(); let vote_account = pubkey_of(arg_matches, "vote_account").unwrap();
command_vsa_create(&config, &pool_account, &vote_account) command_vsa_create(&config, &pool_account, &vote_account)
} }
("add-validator", Some(arg_matches)) => { ("add-validator", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
let stake_account: Pubkey = pubkey_of(arg_matches, "stake_account").unwrap(); let stake_account = pubkey_of(arg_matches, "stake_account").unwrap();
let token_receiver: Option<Pubkey> = pubkey_of(arg_matches, "token_receiver"); let token_receiver: Option<Pubkey> = pubkey_of(arg_matches, "token_receiver");
command_vsa_add(&config, &pool_account, &stake_account, &token_receiver) command_vsa_add(&config, &pool_account, &stake_account, &token_receiver)
} }
("remove-validator", Some(arg_matches)) => { ("remove-validator", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
let stake_account: Pubkey = pubkey_of(arg_matches, "stake_account").unwrap(); let stake_account = pubkey_of(arg_matches, "stake_account").unwrap();
let withdraw_from: Pubkey = pubkey_of(arg_matches, "withdraw_from").unwrap(); let withdraw_from = pubkey_of(arg_matches, "withdraw_from").unwrap();
let new_authority: Option<Pubkey> = pubkey_of(arg_matches, "new_authority"); let new_authority: Option<Pubkey> = pubkey_of(arg_matches, "new_authority");
command_vsa_remove( command_vsa_remove(
&config, &config,
@ -1351,22 +1321,22 @@ fn main() {
) )
} }
("deposit", Some(arg_matches)) => { ("deposit", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
let stake_account: Pubkey = pubkey_of(arg_matches, "stake_account").unwrap(); let stake_account = pubkey_of(arg_matches, "stake_account").unwrap();
let token_receiver: Option<Pubkey> = pubkey_of(arg_matches, "token_receiver"); let token_receiver: Option<Pubkey> = pubkey_of(arg_matches, "token_receiver");
command_deposit(&config, &pool_account, &stake_account, &token_receiver) command_deposit(&config, &pool_account, &stake_account, &token_receiver)
} }
("list", Some(arg_matches)) => { ("list", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
command_list(&config, &pool_account) command_list(&config, &pool_account)
} }
("update", Some(arg_matches)) => { ("update", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
command_update(&config, &pool_account) command_update(&config, &pool_account)
} }
("withdraw", Some(arg_matches)) => { ("withdraw", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
let withdraw_from: Pubkey = pubkey_of(arg_matches, "withdraw_from").unwrap(); let withdraw_from = pubkey_of(arg_matches, "withdraw_from").unwrap();
let pool_amount = value_t_or_exit!(arg_matches, "amount", f64); let pool_amount = value_t_or_exit!(arg_matches, "amount", f64);
let stake_receiver: Option<Pubkey> = pubkey_of(arg_matches, "stake_receiver"); let stake_receiver: Option<Pubkey> = pubkey_of(arg_matches, "stake_receiver");
command_withdraw( command_withdraw(
@ -1378,7 +1348,7 @@ fn main() {
) )
} }
("set-owner", Some(arg_matches)) => { ("set-owner", Some(arg_matches)) => {
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap(); let pool_account = pubkey_of(arg_matches, "pool").unwrap();
let new_owner: Option<Pubkey> = pubkey_of(arg_matches, "new_owner"); let new_owner: Option<Pubkey> = pubkey_of(arg_matches, "new_owner");
let new_fee_receiver: Option<Pubkey> = pubkey_of(arg_matches, "new_fee_receiver"); let new_fee_receiver: Option<Pubkey> = pubkey_of(arg_matches, "new_fee_receiver");
command_set_owner(&config, &pool_account, &new_owner, &new_fee_receiver) command_set_owner(&config, &pool_account, &new_owner, &new_fee_receiver)

View File

@ -1,6 +1,6 @@
#![deny(missing_docs)] #![deny(missing_docs)]
//! A program for creating pools of Solana stakes managed by a Stake-o-Matic //! A program for creating and managing pools of stake
pub mod borsh; pub mod borsh;
pub mod error; pub mod error;
@ -14,44 +14,47 @@ pub mod entrypoint;
// Export current sdk types for downstream users building with a different sdk version // Export current sdk types for downstream users building with a different sdk version
pub use solana_program; pub use solana_program;
use solana_program::{program_error::ProgramError, pubkey::Pubkey}; use solana_program::pubkey::Pubkey;
/// Seed for deposit authority seed /// Seed for deposit authority seed
pub const AUTHORITY_DEPOSIT: &[u8] = b"deposit"; const AUTHORITY_DEPOSIT: &[u8] = b"deposit";
/// Seed for withdraw authority seed /// Seed for withdraw authority seed
pub const AUTHORITY_WITHDRAW: &[u8] = b"withdraw"; const AUTHORITY_WITHDRAW: &[u8] = b"withdraw";
/// Calculates the authority address /// Generates the deposit authority program address for the stake pool
pub fn create_pool_authority_address( pub fn find_deposit_authority_program_address(
program_id: &Pubkey, program_id: &Pubkey,
stake_pool: &Pubkey, stake_pool_address: &Pubkey,
authority: &[u8],
bump_seed: u8,
) -> Result<Pubkey, ProgramError> {
Pubkey::create_program_address(
&[&stake_pool.to_bytes()[..32], authority, &[bump_seed]],
program_id,
)
.map_err(|_| crate::error::StakePoolError::InvalidProgramAddress.into())
}
/// Generates seed bump for stake pool authorities
pub fn find_authority_bump_seed(
program_id: &Pubkey,
stake_pool: &Pubkey,
authority: &[u8],
) -> (Pubkey, u8) {
Pubkey::find_program_address(&[&stake_pool.to_bytes()[..32], authority], program_id)
}
/// Generates stake account address for the validator
pub fn find_stake_address_for_validator(
program_id: &Pubkey,
validator: &Pubkey,
stake_pool: &Pubkey,
) -> (Pubkey, u8) { ) -> (Pubkey, u8) {
Pubkey::find_program_address( Pubkey::find_program_address(
&[&validator.to_bytes()[..32], &stake_pool.to_bytes()[..32]], &[&stake_pool_address.to_bytes()[..32], AUTHORITY_DEPOSIT],
program_id,
)
}
/// Generates the withdraw authority program address for the stake pool
pub fn find_withdraw_authority_program_address(
program_id: &Pubkey,
stake_pool_address: &Pubkey,
) -> (Pubkey, u8) {
Pubkey::find_program_address(
&[&stake_pool_address.to_bytes()[..32], AUTHORITY_WITHDRAW],
program_id,
)
}
/// Generates the stake program address for a validator's vote account
pub fn find_stake_program_address(
program_id: &Pubkey,
vote_account_address: &Pubkey,
stake_pool_address: &Pubkey,
) -> (Pubkey, u8) {
Pubkey::find_program_address(
&[
&vote_account_address.to_bytes()[..32],
&stake_pool_address.to_bytes()[..32],
],
program_id, program_id,
) )
} }

View File

@ -4,7 +4,6 @@ use {
crate::{ crate::{
borsh::try_from_slice_unchecked, borsh::try_from_slice_unchecked,
error::StakePoolError, error::StakePoolError,
find_authority_bump_seed, find_stake_address_for_validator,
instruction::{Fee, StakePoolInstruction}, instruction::{Fee, StakePoolInstruction},
stake_program, stake_program,
state::{AccountType, StakePool, ValidatorList, ValidatorStakeInfo}, state::{AccountType, StakePool, ValidatorList, ValidatorStakeInfo},
@ -56,7 +55,7 @@ impl Processor {
) -> bool { ) -> bool {
// Check stake account address validity // Check stake account address validity
let (stake_address, _) = let (stake_address, _) =
find_stake_address_for_validator(&program_id, &vote_account, &stake_pool_info.key); crate::find_stake_program_address(&program_id, &vote_account, &stake_pool_info.key);
stake_address == *stake_account_info.key stake_address == *stake_account_info.key
} }
@ -295,9 +294,9 @@ impl Processor {
} }
let (_, deposit_bump_seed) = let (_, deposit_bump_seed) =
find_authority_bump_seed(program_id, stake_pool_info.key, AUTHORITY_DEPOSIT); crate::find_deposit_authority_program_address(program_id, stake_pool_info.key);
let (withdraw_authority_key, withdraw_bump_seed) = let (withdraw_authority_key, withdraw_bump_seed) =
find_authority_bump_seed(program_id, stake_pool_info.key, AUTHORITY_WITHDRAW); crate::find_withdraw_authority_program_address(program_id, stake_pool_info.key);
let pool_mint = Mint::unpack_from_slice(&pool_mint_info.data.borrow())?; let pool_mint = Mint::unpack_from_slice(&pool_mint_info.data.borrow())?;
@ -361,7 +360,7 @@ impl Processor {
return Err(ProgramError::IncorrectProgramId); return Err(ProgramError::IncorrectProgramId);
} }
let (stake_address, bump_seed) = find_stake_address_for_validator( let (stake_address, bump_seed) = crate::find_stake_program_address(
&program_id, &program_id,
&validator_info.key, &validator_info.key,
&stake_pool_info.key, &stake_pool_info.key,

View File

@ -99,29 +99,32 @@ impl StakePool {
.ok() .ok()
} }
/// Checks withdraw or deposit authority /// Checks that the withdraw or deposit authority is valid
fn check_authority( fn check_authority(
authority: &Pubkey, authority_address: &Pubkey,
program_id: &Pubkey, program_id: &Pubkey,
stake_pool_address: &Pubkey, stake_pool_address: &Pubkey,
seed: &[u8], authority_seed: &[u8],
bump_seed: u8, bump_seed: u8,
) -> Result<(), ProgramError> { ) -> Result<(), ProgramError> {
if *authority if *authority_address
!= crate::create_pool_authority_address( == Pubkey::create_program_address(
&[
&stake_pool_address.to_bytes()[..32],
authority_seed,
&[bump_seed],
],
program_id, program_id,
stake_pool_address,
seed,
bump_seed,
)? )?
{ {
return Err(StakePoolError::InvalidProgramAddress.into()); Ok(())
} else {
Err(StakePoolError::InvalidProgramAddress.into())
} }
Ok(())
} }
/// Checks withdraw authority /// Checks that the withdraw authority is valid
pub fn check_authority_withdraw( pub(crate) fn check_authority_withdraw(
&self, &self,
withdraw_authority: &Pubkey, withdraw_authority: &Pubkey,
program_id: &Pubkey, program_id: &Pubkey,
@ -135,8 +138,8 @@ impl StakePool {
self.withdraw_bump_seed, self.withdraw_bump_seed,
) )
} }
/// Checks deposit authority /// Checks that the deposit authority is valid
pub fn check_authority_deposit( pub(crate) fn check_authority_deposit(
&self, &self,
deposit_authority: &Pubkey, deposit_authority: &Pubkey,
program_id: &Pubkey, program_id: &Pubkey,
@ -152,7 +155,7 @@ impl StakePool {
} }
/// Check owner validity and signature /// Check owner validity and signature
pub fn check_owner(&self, owner_info: &AccountInfo) -> Result<(), ProgramError> { pub(crate) fn check_owner(&self, owner_info: &AccountInfo) -> Result<(), ProgramError> {
if *owner_info.key != self.owner { if *owner_info.key != self.owner {
return Err(StakePoolError::WrongOwner.into()); return Err(StakePoolError::WrongOwner.into());
} }

View File

@ -13,8 +13,8 @@ use {
}, },
solana_vote_program::{self, vote_state::VoteState}, solana_vote_program::{self, vote_state::VoteState},
spl_stake_pool::{ spl_stake_pool::{
borsh::get_instance_packed_len, find_stake_address_for_validator, id, instruction, borsh::get_instance_packed_len, find_stake_program_address, id, instruction, processor,
processor, stake_program, state, stake_program, state,
}, },
}; };
@ -376,8 +376,7 @@ pub struct ValidatorStakeAccount {
impl ValidatorStakeAccount { impl ValidatorStakeAccount {
pub fn new_with_target_authority(authority: &Pubkey, stake_pool: &Pubkey) -> Self { pub fn new_with_target_authority(authority: &Pubkey, stake_pool: &Pubkey) -> Self {
let validator = Keypair::new(); let validator = Keypair::new();
let (stake_account, _) = let (stake_account, _) = find_stake_program_address(&id(), &validator.pubkey(), stake_pool);
find_stake_address_for_validator(&id(), &validator.pubkey(), stake_pool);
ValidatorStakeAccount { ValidatorStakeAccount {
stake_account, stake_account,
target_authority: *authority, target_authority: *authority,

View File

@ -18,7 +18,7 @@ use {
transaction::TransactionError, transaction::TransactionError,
transport::TransportError, transport::TransportError,
}, },
spl_stake_pool::{error, find_stake_address_for_validator, id, instruction, stake_program}, spl_stake_pool::{error, find_stake_program_address, id, instruction, stake_program},
}; };
#[tokio::test] #[tokio::test]
@ -33,7 +33,7 @@ async fn success_create_validator_stake_account() {
let validator = Keypair::new(); let validator = Keypair::new();
create_vote(&mut banks_client, &payer, &recent_blockhash, &validator).await; create_vote(&mut banks_client, &payer, &recent_blockhash, &validator).await;
let (stake_account, _) = find_stake_address_for_validator( let (stake_account, _) = find_stake_program_address(
&id(), &id(),
&validator.pubkey(), &validator.pubkey(),
&stake_pool_accounts.stake_pool.pubkey(), &stake_pool_accounts.stake_pool.pubkey(),
@ -81,11 +81,8 @@ async fn fail_create_validator_stake_account_on_non_vote_account() {
let validator = Pubkey::new_unique(); let validator = Pubkey::new_unique();
let (stake_account, _) = find_stake_address_for_validator( let (stake_account, _) =
&id(), find_stake_program_address(&id(), &validator, &stake_pool_accounts.stake_pool.pubkey());
&validator,
&stake_pool_accounts.stake_pool.pubkey(),
);
let mut transaction = Transaction::new_with_payer( let mut transaction = Transaction::new_with_payer(
&[instruction::create_validator_stake_account( &[instruction::create_validator_stake_account(
@ -124,11 +121,8 @@ async fn fail_create_validator_stake_account_with_wrong_system_program() {
let validator = Pubkey::new_unique(); let validator = Pubkey::new_unique();
let (stake_account, _) = find_stake_address_for_validator( let (stake_account, _) =
&id(), find_stake_program_address(&id(), &validator, &stake_pool_accounts.stake_pool.pubkey());
&validator,
&stake_pool_accounts.stake_pool.pubkey(),
);
let wrong_system_program = Pubkey::new_unique(); let wrong_system_program = Pubkey::new_unique();
let accounts = vec![ let accounts = vec![
AccountMeta::new_readonly(stake_pool_accounts.stake_pool.pubkey(), false), AccountMeta::new_readonly(stake_pool_accounts.stake_pool.pubkey(), false),
@ -177,11 +171,8 @@ async fn fail_create_validator_stake_account_with_wrong_stake_program() {
let validator = Pubkey::new_unique(); let validator = Pubkey::new_unique();
let (stake_account, _) = find_stake_address_for_validator( let (stake_account, _) =
&id(), find_stake_program_address(&id(), &validator, &stake_pool_accounts.stake_pool.pubkey());
&validator,
&stake_pool_accounts.stake_pool.pubkey(),
);
let wrong_stake_program = Pubkey::new_unique(); let wrong_stake_program = Pubkey::new_unique();
let accounts = vec![ let accounts = vec![
AccountMeta::new_readonly(stake_pool_accounts.stake_pool.pubkey(), false), AccountMeta::new_readonly(stake_pool_accounts.stake_pool.pubkey(), false),