Reboot program address derivation helpers
This commit is contained in:
parent
8b989d562b
commit
48ab307cad
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(StakePoolError::InvalidProgramAddress.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in New Issue