stake-pool: Remove copied stake program code (mostly) (#2526)
* stake-pool: Remove (mostly) the copied stake program * Remove references to stake_program in CLI
This commit is contained in:
parent
d6d0b92ae7
commit
1a48523a80
|
@ -7,11 +7,8 @@ use {
|
||||||
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
|
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
|
||||||
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
||||||
},
|
},
|
||||||
solana_program::{borsh::try_from_slice_unchecked, program_pack::Pack, pubkey::Pubkey},
|
solana_program::{borsh::try_from_slice_unchecked, program_pack::Pack, pubkey::Pubkey, stake},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::state::{StakePool, ValidatorList},
|
||||||
stake_program,
|
|
||||||
state::{StakePool, ValidatorList},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Error = Box<dyn std::error::Error>;
|
type Error = Box<dyn std::error::Error>;
|
||||||
|
@ -70,7 +67,7 @@ pub fn get_token_mint(
|
||||||
pub(crate) fn get_stake_state(
|
pub(crate) fn get_stake_state(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
stake_address: &Pubkey,
|
stake_address: &Pubkey,
|
||||||
) -> Result<stake_program::StakeState, Error> {
|
) -> Result<stake::state::StakeState, Error> {
|
||||||
let account_data = rpc_client.get_account_data(stake_address)?;
|
let account_data = rpc_client.get_account_data(stake_address)?;
|
||||||
let stake_state = deserialize(account_data.as_slice())
|
let stake_state = deserialize(account_data.as_slice())
|
||||||
.map_err(|err| format!("Invalid stake account {}: {}", stake_address, err))?;
|
.map_err(|err| format!("Invalid stake account {}: {}", stake_address, err))?;
|
||||||
|
|
|
@ -20,6 +20,7 @@ use {
|
||||||
instruction::Instruction,
|
instruction::Instruction,
|
||||||
program_pack::Pack,
|
program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
|
stake,
|
||||||
},
|
},
|
||||||
solana_remote_wallet::remote_wallet::RemoteWalletManager,
|
solana_remote_wallet::remote_wallet::RemoteWalletManager,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -36,7 +37,6 @@ use {
|
||||||
self, find_stake_program_address, find_transient_stake_program_address,
|
self, find_stake_program_address, find_transient_stake_program_address,
|
||||||
find_withdraw_authority_program_address,
|
find_withdraw_authority_program_address,
|
||||||
instruction::{FundingType, PreferredValidatorType},
|
instruction::{FundingType, PreferredValidatorType},
|
||||||
stake_program::{self, StakeState},
|
|
||||||
state::{Fee, FeeType, StakePool, ValidatorList},
|
state::{Fee, FeeType, StakePool, ValidatorList},
|
||||||
MINIMUM_ACTIVE_STAKE,
|
MINIMUM_ACTIVE_STAKE,
|
||||||
},
|
},
|
||||||
|
@ -168,7 +168,7 @@ fn new_stake_account(
|
||||||
&stake_receiver_pubkey,
|
&stake_receiver_pubkey,
|
||||||
lamports,
|
lamports,
|
||||||
STAKE_STATE_LEN as u64,
|
STAKE_STATE_LEN as u64,
|
||||||
&stake_program::id(),
|
&stake::program::id(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -241,15 +241,15 @@ fn command_create_pool(
|
||||||
&reserve_keypair.pubkey(),
|
&reserve_keypair.pubkey(),
|
||||||
reserve_stake_balance,
|
reserve_stake_balance,
|
||||||
STAKE_STATE_LEN as u64,
|
STAKE_STATE_LEN as u64,
|
||||||
&stake_program::id(),
|
&stake::program::id(),
|
||||||
),
|
),
|
||||||
stake_program::initialize(
|
stake::instruction::initialize(
|
||||||
&reserve_keypair.pubkey(),
|
&reserve_keypair.pubkey(),
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: withdraw_authority,
|
staker: withdraw_authority,
|
||||||
withdrawer: withdraw_authority,
|
withdrawer: withdraw_authority,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
),
|
),
|
||||||
// Account for the stake pool mint
|
// Account for the stake pool mint
|
||||||
system_instruction::create_account(
|
system_instruction::create_account(
|
||||||
|
@ -610,7 +610,7 @@ fn command_deposit_stake(
|
||||||
println!("Depositing stake account {:?}", stake_state);
|
println!("Depositing stake account {:?}", stake_state);
|
||||||
}
|
}
|
||||||
let vote_account = match stake_state {
|
let vote_account = match stake_state {
|
||||||
StakeState::Stake(_, stake) => Ok(stake.delegation.voter_pubkey),
|
stake::state::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"),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
find_deposit_authority_program_address, find_stake_program_address,
|
find_deposit_authority_program_address, find_stake_program_address,
|
||||||
find_transient_stake_program_address, find_withdraw_authority_program_address,
|
find_transient_stake_program_address, find_withdraw_authority_program_address,
|
||||||
stake_program,
|
|
||||||
state::{Fee, FeeType, StakePool, ValidatorList},
|
state::{Fee, FeeType, StakePool, ValidatorList},
|
||||||
MAX_VALIDATORS_TO_UPDATE,
|
MAX_VALIDATORS_TO_UPDATE,
|
||||||
},
|
},
|
||||||
|
@ -13,7 +12,7 @@ use {
|
||||||
solana_program::{
|
solana_program::{
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_program, sysvar,
|
stake, system_program, sysvar,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -443,9 +442,9 @@ pub fn add_validator_to_pool(
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::config_id(), false),
|
AccountMeta::new_readonly(stake::config::id(), false),
|
||||||
AccountMeta::new_readonly(system_program::id(), false),
|
AccountMeta::new_readonly(system_program::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -478,7 +477,7 @@ pub fn remove_validator_from_pool(
|
||||||
AccountMeta::new_readonly(*transient_stake_account, false),
|
AccountMeta::new_readonly(*transient_stake_account, false),
|
||||||
AccountMeta::new(*destination_stake_account, false),
|
AccountMeta::new(*destination_stake_account, false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -512,7 +511,7 @@ pub fn decrease_validator_stake(
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||||
AccountMeta::new_readonly(system_program::id(), false),
|
AccountMeta::new_readonly(system_program::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -551,9 +550,9 @@ pub fn increase_validator_stake(
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::config_id(), false),
|
AccountMeta::new_readonly(stake::config::id(), false),
|
||||||
AccountMeta::new_readonly(system_program::id(), false),
|
AccountMeta::new_readonly(system_program::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -736,7 +735,7 @@ pub fn update_validator_list_balance(
|
||||||
AccountMeta::new(*reserve_stake, false),
|
AccountMeta::new(*reserve_stake, false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
accounts.append(
|
accounts.append(
|
||||||
&mut validator_vote_accounts
|
&mut validator_vote_accounts
|
||||||
|
@ -911,20 +910,22 @@ pub fn deposit_stake(
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(*token_program_id, false),
|
AccountMeta::new_readonly(*token_program_id, false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
vec![
|
vec![
|
||||||
stake_program::authorize(
|
stake::instruction::authorize(
|
||||||
deposit_stake_address,
|
deposit_stake_address,
|
||||||
deposit_stake_withdraw_authority,
|
deposit_stake_withdraw_authority,
|
||||||
&stake_pool_deposit_authority,
|
&stake_pool_deposit_authority,
|
||||||
stake_program::StakeAuthorize::Staker,
|
stake::state::StakeAuthorize::Staker,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
stake_program::authorize(
|
stake::instruction::authorize(
|
||||||
deposit_stake_address,
|
deposit_stake_address,
|
||||||
deposit_stake_withdraw_authority,
|
deposit_stake_withdraw_authority,
|
||||||
&stake_pool_deposit_authority,
|
&stake_pool_deposit_authority,
|
||||||
stake_program::StakeAuthorize::Withdrawer,
|
stake::state::StakeAuthorize::Withdrawer,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -968,20 +969,22 @@ pub fn deposit_stake_with_authority(
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(*token_program_id, false),
|
AccountMeta::new_readonly(*token_program_id, false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
vec![
|
vec![
|
||||||
stake_program::authorize(
|
stake::instruction::authorize(
|
||||||
deposit_stake_address,
|
deposit_stake_address,
|
||||||
deposit_stake_withdraw_authority,
|
deposit_stake_withdraw_authority,
|
||||||
stake_pool_deposit_authority,
|
stake_pool_deposit_authority,
|
||||||
stake_program::StakeAuthorize::Staker,
|
stake::state::StakeAuthorize::Staker,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
stake_program::authorize(
|
stake::instruction::authorize(
|
||||||
deposit_stake_address,
|
deposit_stake_address,
|
||||||
deposit_stake_withdraw_authority,
|
deposit_stake_withdraw_authority,
|
||||||
stake_pool_deposit_authority,
|
stake_pool_deposit_authority,
|
||||||
stake_program::StakeAuthorize::Withdrawer,
|
stake::state::StakeAuthorize::Withdrawer,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -1094,7 +1097,7 @@ pub fn withdraw_stake(
|
||||||
AccountMeta::new(*pool_mint, false),
|
AccountMeta::new(*pool_mint, false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(*token_program_id, false),
|
AccountMeta::new_readonly(*token_program_id, false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -1130,7 +1133,7 @@ pub fn withdraw_sol(
|
||||||
AccountMeta::new(*pool_mint, false),
|
AccountMeta::new(*pool_mint, false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
AccountMeta::new_readonly(*token_program_id, false),
|
AccountMeta::new_readonly(*token_program_id, false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
|
@ -1170,7 +1173,7 @@ pub fn withdraw_sol_with_authority(
|
||||||
AccountMeta::new(*pool_mint, false),
|
AccountMeta::new(*pool_mint, false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
AccountMeta::new_readonly(*token_program_id, false),
|
AccountMeta::new_readonly(*token_program_id, false),
|
||||||
AccountMeta::new_readonly(*sol_withdraw_authority, true),
|
AccountMeta::new_readonly(*sol_withdraw_authority, true),
|
||||||
];
|
];
|
||||||
|
|
|
@ -15,8 +15,8 @@ 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 {
|
use {
|
||||||
crate::{stake_program::Meta, state::Fee},
|
crate::state::Fee,
|
||||||
solana_program::{native_token::LAMPORTS_PER_SOL, pubkey::Pubkey},
|
solana_program::{native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, stake::state::Meta},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Seed for deposit authority seed
|
/// Seed for deposit authority seed
|
||||||
|
|
|
@ -28,7 +28,7 @@ use {
|
||||||
program_pack::Pack,
|
program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
system_instruction, system_program,
|
stake, system_instruction, system_program,
|
||||||
sysvar::Sysvar,
|
sysvar::Sysvar,
|
||||||
},
|
},
|
||||||
spl_token::state::Mint,
|
spl_token::state::Mint,
|
||||||
|
@ -37,11 +37,11 @@ use {
|
||||||
/// Deserialize the stake state from AccountInfo
|
/// Deserialize the stake state from AccountInfo
|
||||||
fn get_stake_state(
|
fn get_stake_state(
|
||||||
stake_account_info: &AccountInfo,
|
stake_account_info: &AccountInfo,
|
||||||
) -> Result<(stake_program::Meta, stake_program::Stake), ProgramError> {
|
) -> Result<(stake::state::Meta, stake::state::Stake), ProgramError> {
|
||||||
let stake_state =
|
let stake_state =
|
||||||
try_from_slice_unchecked::<stake_program::StakeState>(&stake_account_info.data.borrow())?;
|
try_from_slice_unchecked::<stake::state::StakeState>(&stake_account_info.data.borrow())?;
|
||||||
match stake_state {
|
match stake_state {
|
||||||
stake_program::StakeState::Stake(meta, stake) => Ok((meta, stake)),
|
stake::state::StakeState::Stake(meta, stake) => Ok((meta, stake)),
|
||||||
_ => Err(StakePoolError::WrongStakeState.into()),
|
_ => Err(StakePoolError::WrongStakeState.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,10 +107,10 @@ fn check_system_program(program_id: &Pubkey) -> Result<(), ProgramError> {
|
||||||
|
|
||||||
/// Check stake program address
|
/// Check stake program address
|
||||||
fn check_stake_program(program_id: &Pubkey) -> Result<(), ProgramError> {
|
fn check_stake_program(program_id: &Pubkey) -> Result<(), ProgramError> {
|
||||||
if *program_id != stake_program::id() {
|
if *program_id != stake::program::id() {
|
||||||
msg!(
|
msg!(
|
||||||
"Expected stake program {}, received {}",
|
"Expected stake program {}, received {}",
|
||||||
stake_program::id(),
|
stake::program::id(),
|
||||||
program_id
|
program_id
|
||||||
);
|
);
|
||||||
Err(ProgramError::IncorrectProgramId)
|
Err(ProgramError::IncorrectProgramId)
|
||||||
|
@ -145,7 +145,7 @@ fn create_transient_stake_account<'a>(
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
&system_instruction::allocate(
|
&system_instruction::allocate(
|
||||||
transient_stake_account_info.key,
|
transient_stake_account_info.key,
|
||||||
std::mem::size_of::<stake_program::StakeState>() as u64,
|
std::mem::size_of::<stake::state::StakeState>() as u64,
|
||||||
),
|
),
|
||||||
&[
|
&[
|
||||||
transient_stake_account_info.clone(),
|
transient_stake_account_info.clone(),
|
||||||
|
@ -154,7 +154,7 @@ fn create_transient_stake_account<'a>(
|
||||||
&[transient_stake_account_signer_seeds],
|
&[transient_stake_account_signer_seeds],
|
||||||
)?;
|
)?;
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
&system_instruction::assign(transient_stake_account_info.key, &stake_program::id()),
|
&system_instruction::assign(transient_stake_account_info.key, &stake::program::id()),
|
||||||
&[transient_stake_account_info, system_program_info],
|
&[transient_stake_account_info, system_program_info],
|
||||||
&[transient_stake_account_signer_seeds],
|
&[transient_stake_account_signer_seeds],
|
||||||
)
|
)
|
||||||
|
@ -180,7 +180,7 @@ impl Processor {
|
||||||
[&stake_pool.to_bytes()[..32], authority_type, &[bump_seed]];
|
[&stake_pool.to_bytes()[..32], authority_type, &[bump_seed]];
|
||||||
let signers = &[&authority_signature_seeds[..]];
|
let signers = &[&authority_signature_seeds[..]];
|
||||||
|
|
||||||
let ix = stake_program::delegate_stake(
|
let ix = stake::instruction::delegate_stake(
|
||||||
stake_info.key,
|
stake_info.key,
|
||||||
authority_info.key,
|
authority_info.key,
|
||||||
vote_account_info.key,
|
vote_account_info.key,
|
||||||
|
@ -213,7 +213,7 @@ impl Processor {
|
||||||
[&stake_pool.to_bytes()[..32], authority_type, &[bump_seed]];
|
[&stake_pool.to_bytes()[..32], authority_type, &[bump_seed]];
|
||||||
let signers = &[&authority_signature_seeds[..]];
|
let signers = &[&authority_signature_seeds[..]];
|
||||||
|
|
||||||
let ix = stake_program::deactivate_stake(stake_info.key, authority_info.key);
|
let ix = stake::instruction::deactivate_stake(stake_info.key, authority_info.key);
|
||||||
|
|
||||||
invoke_signed(&ix, &[stake_info, clock_info, authority_info], signers)
|
invoke_signed(&ix, &[stake_info, clock_info, authority_info], signers)
|
||||||
}
|
}
|
||||||
|
@ -233,10 +233,10 @@ impl Processor {
|
||||||
let signers = &[&authority_signature_seeds[..]];
|
let signers = &[&authority_signature_seeds[..]];
|
||||||
|
|
||||||
let split_instruction =
|
let split_instruction =
|
||||||
stake_program::split_only(stake_account.key, authority.key, amount, split_stake.key);
|
stake::instruction::split(stake_account.key, authority.key, amount, split_stake.key);
|
||||||
|
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
&split_instruction,
|
split_instruction.last().unwrap(),
|
||||||
&[stake_account, split_stake, authority],
|
&[stake_account, split_stake, authority],
|
||||||
signers,
|
signers,
|
||||||
)
|
)
|
||||||
|
@ -260,10 +260,10 @@ impl Processor {
|
||||||
let signers = &[&authority_signature_seeds[..]];
|
let signers = &[&authority_signature_seeds[..]];
|
||||||
|
|
||||||
let merge_instruction =
|
let merge_instruction =
|
||||||
stake_program::merge(destination_account.key, source_account.key, authority.key);
|
stake::instruction::merge(destination_account.key, source_account.key, authority.key);
|
||||||
|
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
&merge_instruction,
|
&merge_instruction[0],
|
||||||
&[
|
&[
|
||||||
destination_account,
|
destination_account,
|
||||||
source_account,
|
source_account,
|
||||||
|
@ -276,7 +276,7 @@ impl Processor {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Issue stake_program::authorize instructions to update both authorities
|
/// Issue stake::instruction::authorize instructions to update both authorities
|
||||||
fn stake_authorize<'a>(
|
fn stake_authorize<'a>(
|
||||||
stake_account: AccountInfo<'a>,
|
stake_account: AccountInfo<'a>,
|
||||||
stake_authority: AccountInfo<'a>,
|
stake_authority: AccountInfo<'a>,
|
||||||
|
@ -284,11 +284,12 @@ impl Processor {
|
||||||
clock: AccountInfo<'a>,
|
clock: AccountInfo<'a>,
|
||||||
stake_program_info: AccountInfo<'a>,
|
stake_program_info: AccountInfo<'a>,
|
||||||
) -> Result<(), ProgramError> {
|
) -> Result<(), ProgramError> {
|
||||||
let authorize_instruction = stake_program::authorize(
|
let authorize_instruction = stake::instruction::authorize(
|
||||||
stake_account.key,
|
stake_account.key,
|
||||||
stake_authority.key,
|
stake_authority.key,
|
||||||
new_stake_authority,
|
new_stake_authority,
|
||||||
stake_program::StakeAuthorize::Staker,
|
stake::state::StakeAuthorize::Staker,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
invoke(
|
invoke(
|
||||||
|
@ -301,11 +302,12 @@ impl Processor {
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let authorize_instruction = stake_program::authorize(
|
let authorize_instruction = stake::instruction::authorize(
|
||||||
stake_account.key,
|
stake_account.key,
|
||||||
stake_authority.key,
|
stake_authority.key,
|
||||||
new_stake_authority,
|
new_stake_authority,
|
||||||
stake_program::StakeAuthorize::Withdrawer,
|
stake::state::StakeAuthorize::Withdrawer,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
invoke(
|
invoke(
|
||||||
|
@ -314,7 +316,7 @@ impl Processor {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Issue stake_program::authorize instructions to update both authorities
|
/// Issue stake::instruction::authorize instructions to update both authorities
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn stake_authorize_signed<'a>(
|
fn stake_authorize_signed<'a>(
|
||||||
stake_pool: &Pubkey,
|
stake_pool: &Pubkey,
|
||||||
|
@ -330,11 +332,12 @@ impl Processor {
|
||||||
let authority_signature_seeds = [&me_bytes[..32], authority_type, &[bump_seed]];
|
let authority_signature_seeds = [&me_bytes[..32], authority_type, &[bump_seed]];
|
||||||
let signers = &[&authority_signature_seeds[..]];
|
let signers = &[&authority_signature_seeds[..]];
|
||||||
|
|
||||||
let authorize_instruction = stake_program::authorize(
|
let authorize_instruction = stake::instruction::authorize(
|
||||||
stake_account.key,
|
stake_account.key,
|
||||||
stake_authority.key,
|
stake_authority.key,
|
||||||
new_stake_authority,
|
new_stake_authority,
|
||||||
stake_program::StakeAuthorize::Staker,
|
stake::state::StakeAuthorize::Staker,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
|
@ -348,11 +351,12 @@ impl Processor {
|
||||||
signers,
|
signers,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let authorize_instruction = stake_program::authorize(
|
let authorize_instruction = stake::instruction::authorize(
|
||||||
stake_account.key,
|
stake_account.key,
|
||||||
stake_authority.key,
|
stake_authority.key,
|
||||||
new_stake_authority,
|
new_stake_authority,
|
||||||
stake_program::StakeAuthorize::Withdrawer,
|
stake::state::StakeAuthorize::Withdrawer,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
&authorize_instruction,
|
&authorize_instruction,
|
||||||
|
@ -361,7 +365,7 @@ impl Processor {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Issue stake_program::withdraw instruction to move additional lamports
|
/// Issue stake::instruction::withdraw instruction to move additional lamports
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn stake_withdraw<'a>(
|
fn stake_withdraw<'a>(
|
||||||
stake_pool: &Pubkey,
|
stake_pool: &Pubkey,
|
||||||
|
@ -380,7 +384,7 @@ impl Processor {
|
||||||
let signers = &[&authority_signature_seeds[..]];
|
let signers = &[&authority_signature_seeds[..]];
|
||||||
let custodian_pubkey = None;
|
let custodian_pubkey = None;
|
||||||
|
|
||||||
let withdraw_instruction = stake_program::withdraw(
|
let withdraw_instruction = stake::instruction::withdraw(
|
||||||
source_account.key,
|
source_account.key,
|
||||||
authority.key,
|
authority.key,
|
||||||
destination_account.key,
|
destination_account.key,
|
||||||
|
@ -609,15 +613,15 @@ impl Processor {
|
||||||
return Err(StakePoolError::InvalidMintFreezeAuthority.into());
|
return Err(StakePoolError::InvalidMintFreezeAuthority.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if *reserve_stake_info.owner != stake_program::id() {
|
if *reserve_stake_info.owner != stake::program::id() {
|
||||||
msg!("Reserve stake account not owned by stake program");
|
msg!("Reserve stake account not owned by stake program");
|
||||||
return Err(ProgramError::IncorrectProgramId);
|
return Err(ProgramError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
let stake_state = try_from_slice_unchecked::<stake_program::StakeState>(
|
let stake_state = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&reserve_stake_info.data.borrow(),
|
&reserve_stake_info.data.borrow(),
|
||||||
)?;
|
)?;
|
||||||
let total_lamports = if let stake_program::StakeState::Initialized(meta) = stake_state {
|
let total_lamports = if let stake::state::StakeState::Initialized(meta) = stake_state {
|
||||||
if meta.lockup != stake_program::Lockup::default() {
|
if meta.lockup != stake::state::Lockup::default() {
|
||||||
msg!("Reserve stake account has some lockup");
|
msg!("Reserve stake account has some lockup");
|
||||||
return Err(StakePoolError::WrongStakeState.into());
|
return Err(StakePoolError::WrongStakeState.into());
|
||||||
}
|
}
|
||||||
|
@ -766,7 +770,7 @@ impl Processor {
|
||||||
|
|
||||||
// Fund the stake account with the minimum + rent-exempt balance
|
// Fund the stake account with the minimum + rent-exempt balance
|
||||||
let required_lamports = MINIMUM_ACTIVE_STAKE
|
let required_lamports = MINIMUM_ACTIVE_STAKE
|
||||||
+ rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
+ rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
// Create new stake account
|
// Create new stake account
|
||||||
invoke_signed(
|
invoke_signed(
|
||||||
|
@ -774,21 +778,21 @@ impl Processor {
|
||||||
funder_info.key,
|
funder_info.key,
|
||||||
stake_info.key,
|
stake_info.key,
|
||||||
required_lamports,
|
required_lamports,
|
||||||
std::mem::size_of::<stake_program::StakeState>() as u64,
|
std::mem::size_of::<stake::state::StakeState>() as u64,
|
||||||
&stake_program::id(),
|
&stake::program::id(),
|
||||||
),
|
),
|
||||||
&[funder_info.clone(), stake_info.clone()],
|
&[funder_info.clone(), stake_info.clone()],
|
||||||
&[stake_account_signer_seeds],
|
&[stake_account_signer_seeds],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
invoke(
|
invoke(
|
||||||
&stake_program::initialize(
|
&stake::instruction::initialize(
|
||||||
stake_info.key,
|
stake_info.key,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: *withdraw_authority_info.key,
|
staker: *withdraw_authority_info.key,
|
||||||
withdrawer: *withdraw_authority_info.key,
|
withdrawer: *withdraw_authority_info.key,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
),
|
),
|
||||||
&[
|
&[
|
||||||
stake_info.clone(),
|
stake_info.clone(),
|
||||||
|
@ -1072,7 +1076,7 @@ impl Processor {
|
||||||
&[transient_stake_bump_seed],
|
&[transient_stake_bump_seed],
|
||||||
];
|
];
|
||||||
|
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
if lamports <= stake_rent {
|
if lamports <= stake_rent {
|
||||||
msg!(
|
msg!(
|
||||||
"Need more than {} lamports for transient stake to be rent-exempt, {} provided",
|
"Need more than {} lamports for transient stake to be rent-exempt, {} provided",
|
||||||
|
@ -1228,7 +1232,7 @@ impl Processor {
|
||||||
return Err(StakePoolError::ValidatorNotFound.into());
|
return Err(StakePoolError::ValidatorNotFound.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
if lamports < MINIMUM_ACTIVE_STAKE {
|
if lamports < MINIMUM_ACTIVE_STAKE {
|
||||||
msg!(
|
msg!(
|
||||||
"Need more than {} lamports for transient stake to be rent-exempt and mergeable, {} provided",
|
"Need more than {} lamports for transient stake to be rent-exempt and mergeable, {} provided",
|
||||||
|
@ -1443,11 +1447,11 @@ impl Processor {
|
||||||
|
|
||||||
let mut active_stake_lamports = 0;
|
let mut active_stake_lamports = 0;
|
||||||
let mut transient_stake_lamports = 0;
|
let mut transient_stake_lamports = 0;
|
||||||
let validator_stake_state = try_from_slice_unchecked::<stake_program::StakeState>(
|
let validator_stake_state = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&validator_stake_info.data.borrow(),
|
&validator_stake_info.data.borrow(),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
let transient_stake_state = try_from_slice_unchecked::<stake_program::StakeState>(
|
let transient_stake_state = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&transient_stake_info.data.borrow(),
|
&transient_stake_info.data.borrow(),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
|
@ -1459,7 +1463,7 @@ impl Processor {
|
||||||
// * inactive -> merge into reserve stake
|
// * inactive -> merge into reserve stake
|
||||||
// * not a stake -> ignore
|
// * not a stake -> ignore
|
||||||
match transient_stake_state {
|
match transient_stake_state {
|
||||||
Some(stake_program::StakeState::Initialized(meta)) => {
|
Some(stake::state::StakeState::Initialized(meta)) => {
|
||||||
// if transient account was hijacked, ignore it
|
// if transient account was hijacked, ignore it
|
||||||
if meta.authorized.staker == *withdraw_authority_info.key
|
if meta.authorized.staker == *withdraw_authority_info.key
|
||||||
&& meta.authorized.withdrawer == *withdraw_authority_info.key
|
&& meta.authorized.withdrawer == *withdraw_authority_info.key
|
||||||
|
@ -1487,7 +1491,7 @@ impl Processor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(stake_program::StakeState::Stake(meta, stake)) => {
|
Some(stake::state::StakeState::Stake(meta, stake)) => {
|
||||||
// if transient account was hijacked, ignore it
|
// if transient account was hijacked, ignore it
|
||||||
if meta.authorized.staker == *withdraw_authority_info.key
|
if meta.authorized.staker == *withdraw_authority_info.key
|
||||||
&& meta.authorized.withdrawer == *withdraw_authority_info.key
|
&& meta.authorized.withdrawer == *withdraw_authority_info.key
|
||||||
|
@ -1516,7 +1520,7 @@ impl Processor {
|
||||||
validator_stake_record.status = StakeStatus::ReadyForRemoval;
|
validator_stake_record.status = StakeStatus::ReadyForRemoval;
|
||||||
}
|
}
|
||||||
} else if stake.delegation.activation_epoch < clock.epoch {
|
} else if stake.delegation.activation_epoch < clock.epoch {
|
||||||
if let Some(stake_program::StakeState::Stake(_, validator_stake)) =
|
if let Some(stake::state::StakeState::Stake(_, validator_stake)) =
|
||||||
validator_stake_state
|
validator_stake_state
|
||||||
{
|
{
|
||||||
if stake_program::active_stakes_can_merge(&stake, &validator_stake)
|
if stake_program::active_stakes_can_merge(&stake, &validator_stake)
|
||||||
|
@ -1568,19 +1572,19 @@ impl Processor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
| Some(stake_program::StakeState::Uninitialized)
|
| Some(stake::state::StakeState::Uninitialized)
|
||||||
| Some(stake_program::StakeState::RewardsPool) => {} // do nothing
|
| Some(stake::state::StakeState::RewardsPool) => {} // do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status for validator stake
|
// Status for validator stake
|
||||||
// * active -> do everything
|
// * active -> do everything
|
||||||
// * any other state / not a stake -> error state, but account for transient stake
|
// * any other state / not a stake -> error state, but account for transient stake
|
||||||
let validator_stake_state = try_from_slice_unchecked::<stake_program::StakeState>(
|
let validator_stake_state = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&validator_stake_info.data.borrow(),
|
&validator_stake_info.data.borrow(),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
match validator_stake_state {
|
match validator_stake_state {
|
||||||
Some(stake_program::StakeState::Stake(_, stake)) => {
|
Some(stake::state::StakeState::Stake(_, stake)) => {
|
||||||
if validator_stake_record.status == StakeStatus::Active {
|
if validator_stake_record.status == StakeStatus::Active {
|
||||||
active_stake_lamports = stake
|
active_stake_lamports = stake
|
||||||
.delegation
|
.delegation
|
||||||
|
@ -1591,9 +1595,9 @@ impl Processor {
|
||||||
msg!("Validator stake account no longer part of the pool, ignoring");
|
msg!("Validator stake account no longer part of the pool, ignoring");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(stake_program::StakeState::Initialized(_))
|
Some(stake::state::StakeState::Initialized(_))
|
||||||
| Some(stake_program::StakeState::Uninitialized)
|
| Some(stake::state::StakeState::Uninitialized)
|
||||||
| Some(stake_program::StakeState::RewardsPool)
|
| Some(stake::state::StakeState::RewardsPool)
|
||||||
| None => {
|
| None => {
|
||||||
msg!("Validator stake account no longer part of the pool, ignoring");
|
msg!("Validator stake account no longer part of the pool, ignoring");
|
||||||
}
|
}
|
||||||
|
@ -1652,10 +1656,10 @@ impl Processor {
|
||||||
|
|
||||||
let previous_lamports = stake_pool.total_lamports;
|
let previous_lamports = stake_pool.total_lamports;
|
||||||
let previous_pool_token_supply = stake_pool.pool_token_supply;
|
let previous_pool_token_supply = stake_pool.pool_token_supply;
|
||||||
let reserve_stake = try_from_slice_unchecked::<stake_program::StakeState>(
|
let reserve_stake = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&reserve_stake_info.data.borrow(),
|
&reserve_stake_info.data.borrow(),
|
||||||
)?;
|
)?;
|
||||||
let mut total_lamports = if let stake_program::StakeState::Initialized(meta) = reserve_stake
|
let mut total_lamports = if let stake::state::StakeState::Initialized(meta) = reserve_stake
|
||||||
{
|
{
|
||||||
reserve_stake_info
|
reserve_stake_info
|
||||||
.lamports()
|
.lamports()
|
||||||
|
@ -2255,13 +2259,13 @@ impl Processor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that reserve has enough (should never fail, but who knows?)
|
// check that reserve has enough (should never fail, but who knows?)
|
||||||
let stake_state = try_from_slice_unchecked::<stake_program::StakeState>(
|
let stake_state = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&stake_split_from.data.borrow(),
|
&stake_split_from.data.borrow(),
|
||||||
)?;
|
)?;
|
||||||
let meta = stake_state.meta().ok_or(StakePoolError::WrongStakeState)?;
|
let meta = stake_state.meta().ok_or(StakePoolError::WrongStakeState)?;
|
||||||
stake_split_from
|
stake_split_from
|
||||||
.lamports()
|
.lamports()
|
||||||
.checked_sub(minimum_reserve_lamports(meta))
|
.checked_sub(minimum_reserve_lamports(&meta))
|
||||||
.ok_or(StakePoolError::StakeLamportsNotEqualToMinimum)?;
|
.ok_or(StakePoolError::StakeLamportsNotEqualToMinimum)?;
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -2472,10 +2476,10 @@ impl Processor {
|
||||||
let new_reserve_lamports = reserve_stake_info
|
let new_reserve_lamports = reserve_stake_info
|
||||||
.lamports()
|
.lamports()
|
||||||
.saturating_sub(withdraw_lamports);
|
.saturating_sub(withdraw_lamports);
|
||||||
let stake_state = try_from_slice_unchecked::<stake_program::StakeState>(
|
let stake_state = try_from_slice_unchecked::<stake::state::StakeState>(
|
||||||
&reserve_stake_info.data.borrow(),
|
&reserve_stake_info.data.borrow(),
|
||||||
)?;
|
)?;
|
||||||
if let stake_program::StakeState::Initialized(meta) = stake_state {
|
if let stake::state::StakeState::Initialized(meta) = stake_state {
|
||||||
let minimum_reserve_lamports = minimum_reserve_lamports(&meta);
|
let minimum_reserve_lamports = minimum_reserve_lamports(&meta);
|
||||||
if new_reserve_lamports < minimum_reserve_lamports {
|
if new_reserve_lamports < minimum_reserve_lamports {
|
||||||
msg!("Attempting to withdraw {} lamports, maximum possible SOL withdrawal is {} lamports",
|
msg!("Attempting to withdraw {} lamports, maximum possible SOL withdrawal is {} lamports",
|
||||||
|
|
|
@ -1,265 +1,19 @@
|
||||||
//! FIXME copied from the solana stake program
|
//! FIXME copied from the solana stake program
|
||||||
|
|
||||||
use {
|
use {
|
||||||
borsh::{
|
borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
|
||||||
maybestd::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult},
|
|
||||||
BorshDeserialize, BorshSchema, BorshSerialize,
|
|
||||||
},
|
|
||||||
serde_derive::{Deserialize, Serialize},
|
serde_derive::{Deserialize, Serialize},
|
||||||
solana_program::{
|
solana_program::{
|
||||||
clock::{Epoch, UnixTimestamp},
|
clock::{Epoch, UnixTimestamp},
|
||||||
instruction::{AccountMeta, Instruction},
|
|
||||||
msg,
|
msg,
|
||||||
program_error::ProgramError,
|
program_error::ProgramError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
stake_history::StakeHistory,
|
stake,
|
||||||
system_instruction, sysvar,
|
|
||||||
},
|
},
|
||||||
std::str::FromStr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
solana_program::declare_id!("Stake11111111111111111111111111111111111111");
|
/// FIXME copied from the stake program, once https://github.com/solana-labs/solana/pull/20784
|
||||||
|
/// lands this can be removed
|
||||||
const STAKE_CONFIG: &str = "StakeConfig11111111111111111111111111111111";
|
|
||||||
/// Id for stake config account
|
|
||||||
pub fn config_id() -> Pubkey {
|
|
||||||
Pubkey::from_str(STAKE_CONFIG).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from solana stake program
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
|
||||||
pub enum StakeInstruction {
|
|
||||||
/// Initialize a stake with lockup and authorization information
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Uninitialized stake account
|
|
||||||
/// 1. `[]` Rent sysvar
|
|
||||||
///
|
|
||||||
/// Authorized carries pubkeys that must sign staker transactions
|
|
||||||
/// and withdrawer transactions.
|
|
||||||
/// Lockup carries information about withdrawal restrictions
|
|
||||||
Initialize(Authorized, Lockup),
|
|
||||||
|
|
||||||
/// Authorize a key to manage stake or withdrawal
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Stake account to be updated
|
|
||||||
/// 1. `[]` (reserved for future use) Clock sysvar
|
|
||||||
/// 2. `[SIGNER]` The stake or withdraw authority
|
|
||||||
Authorize(Pubkey, StakeAuthorize),
|
|
||||||
|
|
||||||
/// Delegate a stake to a particular vote account
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Initialized stake account to be delegated
|
|
||||||
/// 1. `[]` Vote account to which this stake will be delegated
|
|
||||||
/// 2. `[]` Clock sysvar
|
|
||||||
/// 3. `[]` Stake history sysvar that carries stake warmup/cooldown history
|
|
||||||
/// 4. `[]` Address of config account that carries stake config
|
|
||||||
/// 5. `[SIGNER]` Stake authority
|
|
||||||
///
|
|
||||||
/// The entire balance of the staking account is staked. DelegateStake
|
|
||||||
/// can be called multiple times, but re-delegation is delayed
|
|
||||||
/// by one epoch
|
|
||||||
DelegateStake,
|
|
||||||
|
|
||||||
/// Split u64 tokens and stake off a stake account into another stake account.
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Stake account to be split; must be in the Initialized or Stake state
|
|
||||||
/// 1. `[WRITE]` Uninitialized stake account that will take the split-off amount
|
|
||||||
/// 2. `[SIGNER]` Stake authority
|
|
||||||
Split(u64),
|
|
||||||
|
|
||||||
/// Withdraw unstaked lamports from the stake account
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Stake account from which to withdraw
|
|
||||||
/// 1. `[WRITE]` Recipient account
|
|
||||||
/// 2. `[]` Clock sysvar
|
|
||||||
/// 3. `[]` Stake history sysvar that carries stake warmup/cooldown history
|
|
||||||
/// 4. `[SIGNER]` Withdraw authority
|
|
||||||
/// 5. Optional: `[SIGNER]` Lockup authority, if before lockup expiration
|
|
||||||
///
|
|
||||||
/// The u64 is the portion of the stake account balance to be withdrawn,
|
|
||||||
/// must be `<= ValidatorStakeAccount.lamports - staked_lamports`.
|
|
||||||
Withdraw(u64),
|
|
||||||
|
|
||||||
/// Deactivates the stake in the account
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Delegated stake account
|
|
||||||
/// 1. `[]` Clock sysvar
|
|
||||||
/// 2. `[SIGNER]` Stake authority
|
|
||||||
Deactivate,
|
|
||||||
|
|
||||||
/// Set stake lockup
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Initialized stake account
|
|
||||||
/// 1. `[SIGNER]` Lockup authority
|
|
||||||
SetLockup,
|
|
||||||
|
|
||||||
/// Merge two stake accounts. Both accounts must be deactivated and have identical lockup and
|
|
||||||
/// authority keys.
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Destination stake account for the merge
|
|
||||||
/// 1. `[WRITE]` Source stake account for to merge. This account will be drained
|
|
||||||
/// 2. `[]` Clock sysvar
|
|
||||||
/// 3. `[]` Stake history sysvar that carries stake warmup/cooldown history
|
|
||||||
/// 4. `[SIGNER]` Stake authority
|
|
||||||
Merge,
|
|
||||||
|
|
||||||
/// Authorize a key to manage stake or withdrawal with a derived key
|
|
||||||
///
|
|
||||||
/// # Account references
|
|
||||||
/// 0. `[WRITE]` Stake account to be updated
|
|
||||||
/// 1. `[SIGNER]` Base key of stake or withdraw authority
|
|
||||||
AuthorizeWithSeed,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
|
||||||
pub enum StakeState {
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
Uninitialized,
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
Initialized(Meta),
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
Stake(Meta, Stake),
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
RewardsPool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BorshDeserialize for StakeState {
|
|
||||||
fn deserialize(buf: &mut &[u8]) -> IoResult<Self> {
|
|
||||||
let u: u32 = BorshDeserialize::deserialize(buf)?;
|
|
||||||
match u {
|
|
||||||
0 => Ok(StakeState::Uninitialized),
|
|
||||||
1 => {
|
|
||||||
let meta: Meta = BorshDeserialize::deserialize(buf)?;
|
|
||||||
Ok(StakeState::Initialized(meta))
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
let meta: Meta = BorshDeserialize::deserialize(buf)?;
|
|
||||||
let stake: Stake = BorshDeserialize::deserialize(buf)?;
|
|
||||||
Ok(StakeState::Stake(meta, stake))
|
|
||||||
}
|
|
||||||
3 => Ok(StakeState::RewardsPool),
|
|
||||||
_ => Err(IoError::new(IoErrorKind::InvalidData, "Invalid enum value")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(
|
|
||||||
BorshSerialize,
|
|
||||||
BorshDeserialize,
|
|
||||||
BorshSchema,
|
|
||||||
Default,
|
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
)]
|
|
||||||
pub struct Meta {
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub rent_exempt_reserve: u64,
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub authorized: Authorized,
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub lockup: Lockup,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(
|
|
||||||
BorshSerialize,
|
|
||||||
BorshDeserialize,
|
|
||||||
BorshSchema,
|
|
||||||
Debug,
|
|
||||||
Default,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
)]
|
|
||||||
pub struct Stake {
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub delegation: Delegation,
|
|
||||||
/// credits observed is credits from vote account state when delegated or redeemed
|
|
||||||
pub credits_observed: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(
|
|
||||||
BorshSerialize,
|
|
||||||
BorshDeserialize,
|
|
||||||
BorshSchema,
|
|
||||||
Debug,
|
|
||||||
Default,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
)]
|
|
||||||
pub struct Delegation {
|
|
||||||
/// to whom the stake is delegated
|
|
||||||
pub voter_pubkey: Pubkey,
|
|
||||||
/// activated stake amount, set at delegate() time
|
|
||||||
pub stake: u64,
|
|
||||||
/// epoch at which this stake was activated, std::Epoch::MAX if is a bootstrap stake
|
|
||||||
pub activation_epoch: Epoch,
|
|
||||||
/// epoch the stake was deactivated, std::Epoch::MAX if not deactivated
|
|
||||||
pub deactivation_epoch: Epoch,
|
|
||||||
/// how much stake we can activate per-epoch as a fraction of currently effective stake
|
|
||||||
pub warmup_cooldown_rate: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(
|
|
||||||
BorshSerialize,
|
|
||||||
BorshDeserialize,
|
|
||||||
BorshSchema,
|
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
)]
|
|
||||||
pub enum StakeAuthorize {
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
Staker,
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
Withdrawer,
|
|
||||||
}
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(
|
|
||||||
BorshSerialize,
|
|
||||||
BorshDeserialize,
|
|
||||||
BorshSchema,
|
|
||||||
Default,
|
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
)]
|
|
||||||
pub struct Authorized {
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub staker: Pubkey,
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub withdrawer: Pubkey,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
#[derive(
|
#[derive(
|
||||||
BorshSerialize,
|
BorshSerialize,
|
||||||
BorshDeserialize,
|
BorshDeserialize,
|
||||||
|
@ -284,226 +38,12 @@ pub struct Lockup {
|
||||||
pub custodian: Pubkey,
|
pub custodian: Pubkey,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
impl StakeState {
|
|
||||||
/// Get Delegation
|
|
||||||
pub fn delegation(&self) -> Option<Delegation> {
|
|
||||||
match self {
|
|
||||||
StakeState::Stake(_meta, stake) => Some(stake.delegation),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Get meta
|
|
||||||
pub fn meta(&self) -> Option<&Meta> {
|
|
||||||
match self {
|
|
||||||
StakeState::Initialized(meta) => Some(meta),
|
|
||||||
StakeState::Stake(meta, _) => Some(meta),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
impl Delegation {
|
|
||||||
/// Create new Delegation
|
|
||||||
pub fn new(
|
|
||||||
voter_pubkey: &Pubkey,
|
|
||||||
stake: u64,
|
|
||||||
activation_epoch: Epoch,
|
|
||||||
warmup_cooldown_rate: f64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
voter_pubkey: *voter_pubkey,
|
|
||||||
stake,
|
|
||||||
activation_epoch,
|
|
||||||
warmup_cooldown_rate,
|
|
||||||
..Delegation::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Check if it bootstrap
|
|
||||||
pub fn is_bootstrap(&self) -> bool {
|
|
||||||
self.activation_epoch == std::u64::MAX
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return tuple (effective, activating, deactivating) stake
|
|
||||||
#[allow(clippy::comparison_chain)]
|
|
||||||
pub fn stake_activating_and_deactivating(
|
|
||||||
&self,
|
|
||||||
target_epoch: Epoch,
|
|
||||||
history: Option<&StakeHistory>,
|
|
||||||
fix_stake_deactivate: bool,
|
|
||||||
) -> (u64, u64, u64) {
|
|
||||||
let delegated_stake = self.stake;
|
|
||||||
|
|
||||||
// first, calculate an effective and activating stake
|
|
||||||
let (effective_stake, activating_stake) =
|
|
||||||
self.stake_and_activating(target_epoch, history, fix_stake_deactivate);
|
|
||||||
|
|
||||||
// then de-activate some portion if necessary
|
|
||||||
if target_epoch < self.deactivation_epoch {
|
|
||||||
// not deactivated
|
|
||||||
(effective_stake, activating_stake, 0)
|
|
||||||
} else if target_epoch == self.deactivation_epoch {
|
|
||||||
// can only deactivate what's activated
|
|
||||||
(effective_stake, 0, effective_stake.min(delegated_stake))
|
|
||||||
} else if let Some((history, mut prev_epoch, mut prev_cluster_stake)) =
|
|
||||||
history.and_then(|history| {
|
|
||||||
history
|
|
||||||
.get(&self.deactivation_epoch)
|
|
||||||
.map(|cluster_stake_at_deactivation_epoch| {
|
|
||||||
(
|
|
||||||
history,
|
|
||||||
self.deactivation_epoch,
|
|
||||||
cluster_stake_at_deactivation_epoch,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
{
|
|
||||||
// target_epoch > self.deactivation_epoch
|
|
||||||
|
|
||||||
// loop from my deactivation epoch until the target epoch
|
|
||||||
// current effective stake is updated using its previous epoch's cluster stake
|
|
||||||
let mut current_epoch;
|
|
||||||
let mut current_effective_stake = effective_stake;
|
|
||||||
loop {
|
|
||||||
current_epoch = prev_epoch + 1;
|
|
||||||
// if there is no deactivating stake at prev epoch, we should have been
|
|
||||||
// fully undelegated at this moment
|
|
||||||
if prev_cluster_stake.deactivating == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// I'm trying to get to zero, how much of the deactivation in stake
|
|
||||||
// this account is entitled to take
|
|
||||||
let weight =
|
|
||||||
current_effective_stake as f64 / prev_cluster_stake.deactivating as f64;
|
|
||||||
|
|
||||||
// portion of newly not-effective cluster stake I'm entitled to at current epoch
|
|
||||||
let newly_not_effective_cluster_stake =
|
|
||||||
prev_cluster_stake.effective as f64 * self.warmup_cooldown_rate;
|
|
||||||
let newly_not_effective_stake =
|
|
||||||
((weight * newly_not_effective_cluster_stake) as u64).max(1);
|
|
||||||
|
|
||||||
current_effective_stake =
|
|
||||||
current_effective_stake.saturating_sub(newly_not_effective_stake);
|
|
||||||
if current_effective_stake == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if current_epoch >= target_epoch {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if let Some(current_cluster_stake) = history.get(¤t_epoch) {
|
|
||||||
prev_epoch = current_epoch;
|
|
||||||
prev_cluster_stake = current_cluster_stake;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deactivating stake should equal to all of currently remaining effective stake
|
|
||||||
(current_effective_stake, 0, current_effective_stake)
|
|
||||||
} else {
|
|
||||||
// no history or I've dropped out of history, so assume fully deactivated
|
|
||||||
(0, 0, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// returned tuple is (effective, activating) stake
|
|
||||||
fn stake_and_activating(
|
|
||||||
&self,
|
|
||||||
target_epoch: Epoch,
|
|
||||||
history: Option<&StakeHistory>,
|
|
||||||
fix_stake_deactivate: bool,
|
|
||||||
) -> (u64, u64) {
|
|
||||||
let delegated_stake = self.stake;
|
|
||||||
|
|
||||||
if self.is_bootstrap() {
|
|
||||||
// fully effective immediately
|
|
||||||
(delegated_stake, 0)
|
|
||||||
} else if fix_stake_deactivate && self.activation_epoch == self.deactivation_epoch {
|
|
||||||
// activated but instantly deactivated; no stake at all regardless of target_epoch
|
|
||||||
// this must be after the bootstrap check and before all-is-activating check
|
|
||||||
(0, 0)
|
|
||||||
} else if target_epoch == self.activation_epoch {
|
|
||||||
// all is activating
|
|
||||||
(0, delegated_stake)
|
|
||||||
} else if target_epoch < self.activation_epoch {
|
|
||||||
// not yet enabled
|
|
||||||
(0, 0)
|
|
||||||
} else if let Some((history, mut prev_epoch, mut prev_cluster_stake)) =
|
|
||||||
history.and_then(|history| {
|
|
||||||
history
|
|
||||||
.get(&self.activation_epoch)
|
|
||||||
.map(|cluster_stake_at_activation_epoch| {
|
|
||||||
(
|
|
||||||
history,
|
|
||||||
self.activation_epoch,
|
|
||||||
cluster_stake_at_activation_epoch,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
{
|
|
||||||
// target_epoch > self.activation_epoch
|
|
||||||
|
|
||||||
// loop from my activation epoch until the target epoch summing up my entitlement
|
|
||||||
// current effective stake is updated using its previous epoch's cluster stake
|
|
||||||
let mut current_epoch;
|
|
||||||
let mut current_effective_stake = 0;
|
|
||||||
loop {
|
|
||||||
current_epoch = prev_epoch + 1;
|
|
||||||
// if there is no activating stake at prev epoch, we should have been
|
|
||||||
// fully effective at this moment
|
|
||||||
if prev_cluster_stake.activating == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// how much of the growth in stake this account is
|
|
||||||
// entitled to take
|
|
||||||
let remaining_activating_stake = delegated_stake - current_effective_stake;
|
|
||||||
let weight =
|
|
||||||
remaining_activating_stake as f64 / prev_cluster_stake.activating as f64;
|
|
||||||
|
|
||||||
// portion of newly effective cluster stake I'm entitled to at current epoch
|
|
||||||
let newly_effective_cluster_stake =
|
|
||||||
prev_cluster_stake.effective as f64 * self.warmup_cooldown_rate;
|
|
||||||
let newly_effective_stake =
|
|
||||||
((weight * newly_effective_cluster_stake) as u64).max(1);
|
|
||||||
|
|
||||||
current_effective_stake += newly_effective_stake;
|
|
||||||
if current_effective_stake >= delegated_stake {
|
|
||||||
current_effective_stake = delegated_stake;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if current_epoch >= target_epoch || current_epoch >= self.deactivation_epoch {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if let Some(current_cluster_stake) = history.get(¤t_epoch) {
|
|
||||||
prev_epoch = current_epoch;
|
|
||||||
prev_cluster_stake = current_cluster_stake;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
|
||||||
current_effective_stake,
|
|
||||||
delegated_stake - current_effective_stake,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// no history or I've dropped out of history, so assume fully effective
|
|
||||||
(delegated_stake, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from stake program
|
/// FIXME copied from stake program
|
||||||
/// Checks if two active delegations are mergeable, required since we cannot recover
|
/// Checks if two active delegations are mergeable, required since we cannot recover
|
||||||
/// from a CPI error.
|
/// from a CPI error.
|
||||||
pub fn active_delegations_can_merge(
|
pub fn active_delegations_can_merge(
|
||||||
stake: &Delegation,
|
stake: &stake::state::Delegation,
|
||||||
source: &Delegation,
|
source: &stake::state::Delegation,
|
||||||
) -> Result<(), ProgramError> {
|
) -> Result<(), ProgramError> {
|
||||||
if stake.voter_pubkey != source.voter_pubkey {
|
if stake.voter_pubkey != source.voter_pubkey {
|
||||||
msg!("Unable to merge due to voter mismatch");
|
msg!("Unable to merge due to voter mismatch");
|
||||||
|
@ -522,7 +62,10 @@ pub fn active_delegations_can_merge(
|
||||||
/// FIXME copied from stake program
|
/// FIXME copied from stake program
|
||||||
/// Checks if two active stakes are mergeable, required since we cannot recover
|
/// Checks if two active stakes are mergeable, required since we cannot recover
|
||||||
/// from a CPI error.
|
/// from a CPI error.
|
||||||
pub fn active_stakes_can_merge(stake: &Stake, source: &Stake) -> Result<(), ProgramError> {
|
pub fn active_stakes_can_merge(
|
||||||
|
stake: &stake::state::Stake,
|
||||||
|
source: &stake::state::Stake,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
active_delegations_can_merge(&stake.delegation, &source.delegation)?;
|
active_delegations_can_merge(&stake.delegation, &source.delegation)?;
|
||||||
|
|
||||||
if stake.credits_observed == source.credits_observed {
|
if stake.credits_observed == source.credits_observed {
|
||||||
|
@ -532,199 +75,3 @@ pub fn active_stakes_can_merge(stake: &Stake, source: &Stake) -> Result<(), Prog
|
||||||
Err(ProgramError::InvalidAccountData)
|
Err(ProgramError::InvalidAccountData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn split_only(
|
|
||||||
stake_pubkey: &Pubkey,
|
|
||||||
authorized_pubkey: &Pubkey,
|
|
||||||
lamports: u64,
|
|
||||||
split_stake_pubkey: &Pubkey,
|
|
||||||
) -> Instruction {
|
|
||||||
let account_metas = vec![
|
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
|
||||||
AccountMeta::new(*split_stake_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(*authorized_pubkey, true),
|
|
||||||
];
|
|
||||||
|
|
||||||
Instruction::new_with_bincode(id(), &StakeInstruction::Split(lamports), account_metas)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn authorize(
|
|
||||||
stake_pubkey: &Pubkey,
|
|
||||||
authorized_pubkey: &Pubkey,
|
|
||||||
new_authorized_pubkey: &Pubkey,
|
|
||||||
stake_authorize: StakeAuthorize,
|
|
||||||
) -> Instruction {
|
|
||||||
let account_metas = vec![
|
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
|
||||||
AccountMeta::new_readonly(*authorized_pubkey, true),
|
|
||||||
];
|
|
||||||
|
|
||||||
Instruction::new_with_bincode(
|
|
||||||
id(),
|
|
||||||
&StakeInstruction::Authorize(*new_authorized_pubkey, stake_authorize),
|
|
||||||
account_metas,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn merge(
|
|
||||||
destination_stake_pubkey: &Pubkey,
|
|
||||||
source_stake_pubkey: &Pubkey,
|
|
||||||
authorized_pubkey: &Pubkey,
|
|
||||||
) -> Instruction {
|
|
||||||
let account_metas = vec![
|
|
||||||
AccountMeta::new(*destination_stake_pubkey, false),
|
|
||||||
AccountMeta::new(*source_stake_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
|
||||||
AccountMeta::new_readonly(*authorized_pubkey, true),
|
|
||||||
];
|
|
||||||
|
|
||||||
Instruction::new_with_bincode(id(), &StakeInstruction::Merge, account_metas)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn create_account(
|
|
||||||
from_pubkey: &Pubkey,
|
|
||||||
stake_pubkey: &Pubkey,
|
|
||||||
authorized: &Authorized,
|
|
||||||
lockup: &Lockup,
|
|
||||||
lamports: u64,
|
|
||||||
) -> Vec<Instruction> {
|
|
||||||
vec![
|
|
||||||
system_instruction::create_account(
|
|
||||||
from_pubkey,
|
|
||||||
stake_pubkey,
|
|
||||||
lamports,
|
|
||||||
std::mem::size_of::<StakeState>() as u64,
|
|
||||||
&id(),
|
|
||||||
),
|
|
||||||
initialize(stake_pubkey, authorized, lockup),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn initialize(stake_pubkey: &Pubkey, authorized: &Authorized, lockup: &Lockup) -> Instruction {
|
|
||||||
Instruction::new_with_bincode(
|
|
||||||
id(),
|
|
||||||
&StakeInstruction::Initialize(*authorized, *lockup),
|
|
||||||
vec![
|
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn delegate_stake(
|
|
||||||
stake_pubkey: &Pubkey,
|
|
||||||
authorized_pubkey: &Pubkey,
|
|
||||||
vote_pubkey: &Pubkey,
|
|
||||||
) -> Instruction {
|
|
||||||
let account_metas = vec![
|
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(*vote_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
|
||||||
AccountMeta::new_readonly(config_id(), false),
|
|
||||||
AccountMeta::new_readonly(*authorized_pubkey, true),
|
|
||||||
];
|
|
||||||
Instruction::new_with_bincode(id(), &StakeInstruction::DelegateStake, account_metas)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from stake program
|
|
||||||
pub fn deactivate_stake(stake_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction {
|
|
||||||
let account_metas = vec![
|
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
|
||||||
AccountMeta::new_readonly(*authorized_pubkey, true),
|
|
||||||
];
|
|
||||||
Instruction::new_with_bincode(id(), &StakeInstruction::Deactivate, account_metas)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIXME copied from the stake program
|
|
||||||
pub fn withdraw(
|
|
||||||
stake_pubkey: &Pubkey,
|
|
||||||
withdrawer_pubkey: &Pubkey,
|
|
||||||
to_pubkey: &Pubkey,
|
|
||||||
lamports: u64,
|
|
||||||
custodian_pubkey: Option<&Pubkey>,
|
|
||||||
) -> Instruction {
|
|
||||||
let mut account_metas = vec![
|
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
|
||||||
AccountMeta::new(*to_pubkey, false),
|
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
|
||||||
AccountMeta::new_readonly(*withdrawer_pubkey, true),
|
|
||||||
];
|
|
||||||
|
|
||||||
if let Some(custodian_pubkey) = custodian_pubkey {
|
|
||||||
account_metas.push(AccountMeta::new_readonly(*custodian_pubkey, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction::new_with_bincode(id(), &StakeInstruction::Withdraw(lamports), account_metas)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use {super::*, bincode::serialize, solana_program::borsh::try_from_slice_unchecked};
|
|
||||||
|
|
||||||
fn check_borsh_deserialization(stake: StakeState) {
|
|
||||||
let serialized = serialize(&stake).unwrap();
|
|
||||||
let deserialized = StakeState::try_from_slice(&serialized).unwrap();
|
|
||||||
assert_eq!(stake, deserialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bincode_vs_borsh() {
|
|
||||||
check_borsh_deserialization(StakeState::Uninitialized);
|
|
||||||
check_borsh_deserialization(StakeState::RewardsPool);
|
|
||||||
check_borsh_deserialization(StakeState::Initialized(Meta {
|
|
||||||
rent_exempt_reserve: u64::MAX,
|
|
||||||
authorized: Authorized {
|
|
||||||
staker: Pubkey::new_unique(),
|
|
||||||
withdrawer: Pubkey::new_unique(),
|
|
||||||
},
|
|
||||||
lockup: Lockup::default(),
|
|
||||||
}));
|
|
||||||
check_borsh_deserialization(StakeState::Stake(
|
|
||||||
Meta {
|
|
||||||
rent_exempt_reserve: 1,
|
|
||||||
authorized: Authorized {
|
|
||||||
staker: Pubkey::new_unique(),
|
|
||||||
withdrawer: Pubkey::new_unique(),
|
|
||||||
},
|
|
||||||
lockup: Lockup::default(),
|
|
||||||
},
|
|
||||||
Stake {
|
|
||||||
delegation: Delegation {
|
|
||||||
voter_pubkey: Pubkey::new_unique(),
|
|
||||||
stake: u64::MAX,
|
|
||||||
activation_epoch: Epoch::MAX,
|
|
||||||
deactivation_epoch: Epoch::MAX,
|
|
||||||
warmup_cooldown_rate: f64::MAX,
|
|
||||||
},
|
|
||||||
credits_observed: 1,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn borsh_deserialization_live_data() {
|
|
||||||
let data = [
|
|
||||||
1, 0, 0, 0, 128, 213, 34, 0, 0, 0, 0, 0, 133, 0, 79, 231, 141, 29, 73, 61, 232, 35,
|
|
||||||
119, 124, 168, 12, 120, 216, 195, 29, 12, 166, 139, 28, 36, 182, 186, 154, 246, 149,
|
|
||||||
224, 109, 52, 100, 133, 0, 79, 231, 141, 29, 73, 61, 232, 35, 119, 124, 168, 12, 120,
|
|
||||||
216, 195, 29, 12, 166, 139, 28, 36, 182, 186, 154, 246, 149, 224, 109, 52, 100, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
];
|
|
||||||
let _deserialized = try_from_slice_unchecked::<StakeState>(&data).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,14 +5,16 @@ mod helpers;
|
||||||
use {
|
use {
|
||||||
bincode::deserialize,
|
bincode::deserialize,
|
||||||
helpers::*,
|
helpers::*,
|
||||||
solana_program::{clock::Epoch, hash::Hash, instruction::InstructionError, pubkey::Pubkey},
|
solana_program::{
|
||||||
|
clock::Epoch, hash::Hash, instruction::InstructionError, pubkey::Pubkey, stake,
|
||||||
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{
|
||||||
error::StakePoolError, find_transient_stake_program_address, id, instruction, stake_program,
|
error::StakePoolError, find_transient_stake_program_address, id, instruction,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,7 +106,7 @@ async fn success() {
|
||||||
let validator_stake_account =
|
let validator_stake_account =
|
||||||
get_account(&mut banks_client, &validator_stake.stake_account).await;
|
get_account(&mut banks_client, &validator_stake.stake_account).await;
|
||||||
let validator_stake_state =
|
let validator_stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&validator_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&validator_stake_account.data).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pre_validator_stake_account.lamports - decrease_lamports,
|
pre_validator_stake_account.lamports - decrease_lamports,
|
||||||
validator_stake_account.lamports
|
validator_stake_account.lamports
|
||||||
|
@ -121,7 +123,7 @@ async fn success() {
|
||||||
let transient_stake_account =
|
let transient_stake_account =
|
||||||
get_account(&mut banks_client, &validator_stake.transient_stake_account).await;
|
get_account(&mut banks_client, &validator_stake.transient_stake_account).await;
|
||||||
let transient_stake_state =
|
let transient_stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&transient_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&transient_stake_account.data).unwrap();
|
||||||
assert_eq!(transient_stake_account.lamports, decrease_lamports);
|
assert_eq!(transient_stake_account.lamports, decrease_lamports);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
transient_stake_state
|
transient_stake_state
|
||||||
|
@ -344,7 +346,7 @@ async fn fail_with_small_lamport_amount() {
|
||||||
) = setup().await;
|
) = setup().await;
|
||||||
|
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let lamports = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let lamports = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
let error = stake_pool_accounts
|
let error = stake_pool_accounts
|
||||||
.decrease_validator_stake(
|
.decrease_validator_stake(
|
||||||
|
@ -411,7 +413,7 @@ async fn fail_overdraw() {
|
||||||
) = setup().await;
|
) = setup().await;
|
||||||
|
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
let error = stake_pool_accounts
|
let error = stake_pool_accounts
|
||||||
.decrease_validator_stake(
|
.decrease_validator_stake(
|
||||||
|
|
|
@ -10,7 +10,7 @@ use {
|
||||||
borsh::try_from_slice_unchecked,
|
borsh::try_from_slice_unchecked,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sysvar,
|
stake, sysvar,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -19,9 +19,7 @@ use {
|
||||||
transaction::TransactionError,
|
transaction::TransactionError,
|
||||||
transport::TransportError,
|
transport::TransportError,
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{error::StakePoolError, id, instruction, minimum_stake_lamports, state},
|
||||||
error::StakePoolError, id, instruction, minimum_stake_lamports, stake_program, state,
|
|
||||||
},
|
|
||||||
spl_token::error as token_error,
|
spl_token::error as token_error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,9 +61,9 @@ async fn setup() -> (
|
||||||
let user = Keypair::new();
|
let user = Keypair::new();
|
||||||
// make stake account
|
// make stake account
|
||||||
let deposit_stake = Keypair::new();
|
let deposit_stake = Keypair::new();
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
|
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: user.pubkey(),
|
staker: user.pubkey(),
|
||||||
withdrawer: user.pubkey(),
|
withdrawer: user.pubkey(),
|
||||||
};
|
};
|
||||||
|
@ -140,7 +138,7 @@ async fn success() {
|
||||||
) = setup().await;
|
) = setup().await;
|
||||||
|
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
// Save stake pool state before depositing
|
// Save stake pool state before depositing
|
||||||
let pre_stake_pool = get_account(
|
let pre_stake_pool = get_account(
|
||||||
|
@ -246,10 +244,10 @@ async fn success() {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let stake_state =
|
let stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&validator_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&validator_stake_account.data).unwrap();
|
||||||
let meta = stake_state.meta().unwrap();
|
let meta = stake_state.meta().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
validator_stake_account.lamports - minimum_stake_lamports(meta),
|
validator_stake_account.lamports - minimum_stake_lamports(&meta),
|
||||||
post_validator_stake_item.stake_lamports()
|
post_validator_stake_item.stake_lamports()
|
||||||
);
|
);
|
||||||
assert_eq!(post_validator_stake_item.transient_stake_lamports, 0);
|
assert_eq!(post_validator_stake_item.transient_stake_lamports, 0);
|
||||||
|
@ -310,7 +308,7 @@ async fn success_with_extra_stake_lamports() {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
// Save stake pool state before depositing
|
// Save stake pool state before depositing
|
||||||
let pre_stake_pool = get_account(
|
let pre_stake_pool = get_account(
|
||||||
|
@ -441,10 +439,10 @@ async fn success_with_extra_stake_lamports() {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let stake_state =
|
let stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&validator_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&validator_stake_account.data).unwrap();
|
||||||
let meta = stake_state.meta().unwrap();
|
let meta = stake_state.meta().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
validator_stake_account.lamports - minimum_stake_lamports(meta),
|
validator_stake_account.lamports - minimum_stake_lamports(&meta),
|
||||||
post_validator_stake_item.stake_lamports()
|
post_validator_stake_item.stake_lamports()
|
||||||
);
|
);
|
||||||
assert_eq!(post_validator_stake_item.transient_stake_lamports, 0);
|
assert_eq!(post_validator_stake_item.transient_stake_lamports, 0);
|
||||||
|
@ -641,8 +639,8 @@ async fn fail_with_unknown_validator() {
|
||||||
|
|
||||||
// make stake account
|
// make stake account
|
||||||
let user_stake = Keypair::new();
|
let user_stake = Keypair::new();
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: user.pubkey(),
|
staker: user.pubkey(),
|
||||||
withdrawer: user.pubkey(),
|
withdrawer: user.pubkey(),
|
||||||
};
|
};
|
||||||
|
@ -816,8 +814,8 @@ async fn success_with_stake_deposit_authority() {
|
||||||
|
|
||||||
let user = Keypair::new();
|
let user = Keypair::new();
|
||||||
let user_stake = Keypair::new();
|
let user_stake = Keypair::new();
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: user.pubkey(),
|
staker: user.pubkey(),
|
||||||
withdrawer: user.pubkey(),
|
withdrawer: user.pubkey(),
|
||||||
};
|
};
|
||||||
|
@ -898,8 +896,8 @@ async fn fail_without_stake_deposit_authority_signature() {
|
||||||
|
|
||||||
let user = Keypair::new();
|
let user = Keypair::new();
|
||||||
let user_stake = Keypair::new();
|
let user_stake = Keypair::new();
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: user.pubkey(),
|
staker: user.pubkey(),
|
||||||
withdrawer: user.pubkey(),
|
withdrawer: user.pubkey(),
|
||||||
};
|
};
|
||||||
|
@ -1127,7 +1125,7 @@ async fn success_with_referral_fee() {
|
||||||
let stake_pool =
|
let stake_pool =
|
||||||
try_from_slice_unchecked::<state::StakePool>(stake_pool.data.as_slice()).unwrap();
|
try_from_slice_unchecked::<state::StakePool>(stake_pool.data.as_slice()).unwrap();
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
let fee_tokens = stake_pool
|
let fee_tokens = stake_pool
|
||||||
.calc_pool_tokens_sol_deposit_fee(stake_rent)
|
.calc_pool_tokens_sol_deposit_fee(stake_rent)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -6,7 +6,7 @@ use {
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
program_pack::Pack,
|
program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction, system_program,
|
stake, system_instruction, system_program,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -21,7 +21,7 @@ use {
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{
|
||||||
find_stake_program_address, find_transient_stake_program_address, id, instruction,
|
find_stake_program_address, find_transient_stake_program_address, id, instruction,
|
||||||
processor, stake_program,
|
processor,
|
||||||
state::{self, FeeType, ValidatorList},
|
state::{self, FeeType, ValidatorList},
|
||||||
MINIMUM_ACTIVE_STAKE,
|
MINIMUM_ACTIVE_STAKE,
|
||||||
},
|
},
|
||||||
|
@ -431,16 +431,16 @@ pub async fn create_independent_stake_account(
|
||||||
payer: &Keypair,
|
payer: &Keypair,
|
||||||
recent_blockhash: &Hash,
|
recent_blockhash: &Hash,
|
||||||
stake: &Keypair,
|
stake: &Keypair,
|
||||||
authorized: &stake_program::Authorized,
|
authorized: &stake::state::Authorized,
|
||||||
lockup: &stake_program::Lockup,
|
lockup: &stake::state::Lockup,
|
||||||
stake_amount: u64,
|
stake_amount: u64,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let lamports =
|
let lamports =
|
||||||
rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>()) + stake_amount;
|
rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>()) + stake_amount;
|
||||||
|
|
||||||
let transaction = Transaction::new_signed_with_payer(
|
let transaction = Transaction::new_signed_with_payer(
|
||||||
&stake_program::create_account(
|
&stake::instruction::create_account(
|
||||||
&payer.pubkey(),
|
&payer.pubkey(),
|
||||||
&stake.pubkey(),
|
&stake.pubkey(),
|
||||||
authorized,
|
authorized,
|
||||||
|
@ -463,15 +463,15 @@ pub async fn create_blank_stake_account(
|
||||||
stake: &Keypair,
|
stake: &Keypair,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let lamports = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>()) + 1;
|
let lamports = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>()) + 1;
|
||||||
|
|
||||||
let transaction = Transaction::new_signed_with_payer(
|
let transaction = Transaction::new_signed_with_payer(
|
||||||
&[system_instruction::create_account(
|
&[system_instruction::create_account(
|
||||||
&payer.pubkey(),
|
&payer.pubkey(),
|
||||||
&stake.pubkey(),
|
&stake.pubkey(),
|
||||||
lamports,
|
lamports,
|
||||||
std::mem::size_of::<stake_program::StakeState>() as u64,
|
std::mem::size_of::<stake::state::StakeState>() as u64,
|
||||||
&stake_program::id(),
|
&stake::program::id(),
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
&[payer, stake],
|
&[payer, stake],
|
||||||
|
@ -491,7 +491,7 @@ pub async fn delegate_stake_account(
|
||||||
vote: &Pubkey,
|
vote: &Pubkey,
|
||||||
) {
|
) {
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let mut transaction = Transaction::new_with_payer(
|
||||||
&[stake_program::delegate_stake(
|
&[stake::instruction::delegate_stake(
|
||||||
stake,
|
stake,
|
||||||
&authorized.pubkey(),
|
&authorized.pubkey(),
|
||||||
vote,
|
vote,
|
||||||
|
@ -509,14 +509,15 @@ pub async fn authorize_stake_account(
|
||||||
stake: &Pubkey,
|
stake: &Pubkey,
|
||||||
authorized: &Keypair,
|
authorized: &Keypair,
|
||||||
new_authorized: &Pubkey,
|
new_authorized: &Pubkey,
|
||||||
stake_authorize: stake_program::StakeAuthorize,
|
stake_authorize: stake::state::StakeAuthorize,
|
||||||
) {
|
) {
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let mut transaction = Transaction::new_with_payer(
|
||||||
&[stake_program::authorize(
|
&[stake::instruction::authorize(
|
||||||
stake,
|
stake,
|
||||||
&authorized.pubkey(),
|
&authorized.pubkey(),
|
||||||
new_authorized,
|
new_authorized,
|
||||||
stake_authorize,
|
stake_authorize,
|
||||||
|
None,
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
);
|
);
|
||||||
|
@ -546,11 +547,11 @@ pub async fn create_unknown_validator_stake(
|
||||||
payer,
|
payer,
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
&fake_validator_stake,
|
&fake_validator_stake,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: user.pubkey(),
|
staker: user.pubkey(),
|
||||||
withdrawer: user.pubkey(),
|
withdrawer: user.pubkey(),
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
MINIMUM_ACTIVE_STAKE,
|
MINIMUM_ACTIVE_STAKE,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -726,11 +727,11 @@ impl StakePoolAccounts {
|
||||||
payer,
|
payer,
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
&self.reserve_stake,
|
&self.reserve_stake,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: self.withdraw_authority,
|
staker: self.withdraw_authority,
|
||||||
withdrawer: self.withdraw_authority,
|
withdrawer: self.withdraw_authority,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
reserve_lamports,
|
reserve_lamports,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1144,8 +1145,8 @@ impl StakePoolAccounts {
|
||||||
&payer.pubkey(),
|
&payer.pubkey(),
|
||||||
&destination_stake.pubkey(),
|
&destination_stake.pubkey(),
|
||||||
0,
|
0,
|
||||||
std::mem::size_of::<stake_program::StakeState>() as u64,
|
std::mem::size_of::<stake::state::StakeState>() as u64,
|
||||||
&stake_program::id(),
|
&stake::program::id(),
|
||||||
),
|
),
|
||||||
instruction::remove_validator_from_pool(
|
instruction::remove_validator_from_pool(
|
||||||
&id(),
|
&id(),
|
||||||
|
@ -1323,8 +1324,8 @@ impl DepositStakeAccount {
|
||||||
payer: &Keypair,
|
payer: &Keypair,
|
||||||
recent_blockhash: &Hash,
|
recent_blockhash: &Hash,
|
||||||
) {
|
) {
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: self.authority.pubkey(),
|
staker: self.authority.pubkey(),
|
||||||
withdrawer: self.authority.pubkey(),
|
withdrawer: self.authority.pubkey(),
|
||||||
};
|
};
|
||||||
|
@ -1395,8 +1396,8 @@ pub async fn simple_deposit_stake(
|
||||||
let authority = Keypair::new();
|
let authority = Keypair::new();
|
||||||
// make stake account
|
// make stake account
|
||||||
let stake = Keypair::new();
|
let stake = Keypair::new();
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: authority.pubkey(),
|
staker: authority.pubkey(),
|
||||||
withdrawer: authority.pubkey(),
|
withdrawer: authority.pubkey(),
|
||||||
};
|
};
|
||||||
|
@ -1487,6 +1488,6 @@ pub async fn get_validator_list_sum(
|
||||||
.map(|info| info.stake_lamports())
|
.map(|info| info.stake_lamports())
|
||||||
.sum();
|
.sum();
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
validator_sum + reserve_stake.lamports - rent - 1
|
validator_sum + reserve_stake.lamports - rent - 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use {
|
||||||
helpers::*,
|
helpers::*,
|
||||||
solana_program::{
|
solana_program::{
|
||||||
borsh::try_from_slice_unchecked, program_option::COption, program_pack::Pack,
|
borsh::try_from_slice_unchecked, program_option::COption, program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey, stake,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -98,13 +98,13 @@ async fn setup(
|
||||||
let authorized_withdrawer = Pubkey::new_unique();
|
let authorized_withdrawer = Pubkey::new_unique();
|
||||||
let commission = 1;
|
let commission = 1;
|
||||||
|
|
||||||
let meta = stake_program::Meta {
|
let meta = stake::state::Meta {
|
||||||
rent_exempt_reserve: STAKE_ACCOUNT_RENT_EXEMPTION,
|
rent_exempt_reserve: STAKE_ACCOUNT_RENT_EXEMPTION,
|
||||||
authorized: stake_program::Authorized {
|
authorized: stake::state::Authorized {
|
||||||
staker: stake_pool_accounts.withdraw_authority,
|
staker: stake_pool_accounts.withdraw_authority,
|
||||||
withdrawer: stake_pool_accounts.withdraw_authority,
|
withdrawer: stake_pool_accounts.withdraw_authority,
|
||||||
},
|
},
|
||||||
lockup: stake_program::Lockup::default(),
|
lockup: stake::state::Lockup::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for _ in 0..max_validators {
|
for _ in 0..max_validators {
|
||||||
|
@ -133,8 +133,8 @@ async fn setup(
|
||||||
|
|
||||||
for vote_account_address in vote_account_pubkeys.iter().take(num_validators as usize) {
|
for vote_account_address in vote_account_pubkeys.iter().take(num_validators as usize) {
|
||||||
// create validator stake account
|
// create validator stake account
|
||||||
let stake = stake_program::Stake {
|
let stake = stake::state::Stake {
|
||||||
delegation: stake_program::Delegation {
|
delegation: stake::state::Delegation {
|
||||||
voter_pubkey: *vote_account_address,
|
voter_pubkey: *vote_account_address,
|
||||||
stake: stake_amount,
|
stake: stake_amount,
|
||||||
activation_epoch: 0,
|
activation_epoch: 0,
|
||||||
|
@ -146,11 +146,11 @@ async fn setup(
|
||||||
|
|
||||||
let stake_account = Account::create(
|
let stake_account = Account::create(
|
||||||
stake_amount + STAKE_ACCOUNT_RENT_EXEMPTION,
|
stake_amount + STAKE_ACCOUNT_RENT_EXEMPTION,
|
||||||
bincode::serialize::<stake_program::StakeState>(&stake_program::StakeState::Stake(
|
bincode::serialize::<stake::state::StakeState>(&stake::state::StakeState::Stake(
|
||||||
meta, stake,
|
meta, stake,
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
stake_program::id(),
|
stake::program::id(),
|
||||||
false,
|
false,
|
||||||
Epoch::default(),
|
Epoch::default(),
|
||||||
);
|
);
|
||||||
|
@ -183,11 +183,11 @@ async fn setup(
|
||||||
|
|
||||||
let reserve_stake_account = Account::create(
|
let reserve_stake_account = Account::create(
|
||||||
stake_amount + STAKE_ACCOUNT_RENT_EXEMPTION,
|
stake_amount + STAKE_ACCOUNT_RENT_EXEMPTION,
|
||||||
bincode::serialize::<stake_program::StakeState>(&stake_program::StakeState::Initialized(
|
bincode::serialize::<stake::state::StakeState>(&stake::state::StakeState::Initialized(
|
||||||
meta,
|
meta,
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
stake_program::id(),
|
stake::program::id(),
|
||||||
false,
|
false,
|
||||||
Epoch::default(),
|
Epoch::default(),
|
||||||
);
|
);
|
||||||
|
@ -266,9 +266,9 @@ async fn setup(
|
||||||
// make stake account
|
// make stake account
|
||||||
let user = Keypair::new();
|
let user = Keypair::new();
|
||||||
let deposit_stake = Keypair::new();
|
let deposit_stake = Keypair::new();
|
||||||
let lockup = stake_program::Lockup::default();
|
let lockup = stake::state::Lockup::default();
|
||||||
|
|
||||||
let authorized = stake_program::Authorized {
|
let authorized = stake::state::Authorized {
|
||||||
staker: user.pubkey(),
|
staker: user.pubkey(),
|
||||||
withdrawer: user.pubkey(),
|
withdrawer: user.pubkey(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,9 @@ mod helpers;
|
||||||
use {
|
use {
|
||||||
bincode::deserialize,
|
bincode::deserialize,
|
||||||
helpers::*,
|
helpers::*,
|
||||||
solana_program::{clock::Epoch, hash::Hash, instruction::InstructionError, pubkey::Pubkey},
|
solana_program::{
|
||||||
|
clock::Epoch, hash::Hash, instruction::InstructionError, pubkey::Pubkey, stake,
|
||||||
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
|
@ -13,7 +15,7 @@ use {
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{
|
||||||
error::StakePoolError, find_transient_stake_program_address, id, instruction,
|
error::StakePoolError, find_transient_stake_program_address, id, instruction,
|
||||||
stake_program, MINIMUM_ACTIVE_STAKE,
|
MINIMUM_ACTIVE_STAKE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,7 +95,7 @@ async fn success() {
|
||||||
assert!(transient_account.is_none());
|
assert!(transient_account.is_none());
|
||||||
|
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
let increase_amount = reserve_lamports - stake_rent - 1;
|
let increase_amount = reserve_lamports - stake_rent - 1;
|
||||||
let error = stake_pool_accounts
|
let error = stake_pool_accounts
|
||||||
.increase_validator_stake(
|
.increase_validator_stake(
|
||||||
|
@ -115,7 +117,7 @@ async fn success() {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let reserve_stake_state =
|
let reserve_stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&reserve_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&reserve_stake_account.data).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pre_reserve_stake_account.lamports - increase_amount - stake_rent,
|
pre_reserve_stake_account.lamports - increase_amount - stake_rent,
|
||||||
reserve_stake_account.lamports
|
reserve_stake_account.lamports
|
||||||
|
@ -126,7 +128,7 @@ async fn success() {
|
||||||
let transient_stake_account =
|
let transient_stake_account =
|
||||||
get_account(&mut banks_client, &validator_stake.transient_stake_account).await;
|
get_account(&mut banks_client, &validator_stake.transient_stake_account).await;
|
||||||
let transient_stake_state =
|
let transient_stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&transient_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&transient_stake_account.data).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
transient_stake_account.lamports,
|
transient_stake_account.lamports,
|
||||||
increase_amount + stake_rent
|
increase_amount + stake_rent
|
||||||
|
|
|
@ -11,14 +11,14 @@ use {
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
program_pack::Pack,
|
program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction, sysvar,
|
stake, system_instruction, sysvar,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
instruction::InstructionError, signature::Keypair, signature::Signer,
|
instruction::InstructionError, signature::Keypair, signature::Signer,
|
||||||
transaction::Transaction, transaction::TransactionError, transport::TransportError,
|
transaction::Transaction, transaction::TransactionError, transport::TransportError,
|
||||||
},
|
},
|
||||||
spl_stake_pool::{error, id, instruction, stake_program, state},
|
spl_stake_pool::{error, id, instruction, state},
|
||||||
};
|
};
|
||||||
|
|
||||||
async fn create_required_accounts(
|
async fn create_required_accounts(
|
||||||
|
@ -53,11 +53,11 @@ async fn create_required_accounts(
|
||||||
payer,
|
payer,
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
&stake_pool_accounts.reserve_stake,
|
&stake_pool_accounts.reserve_stake,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: stake_pool_accounts.withdraw_authority,
|
staker: stake_pool_accounts.withdraw_authority,
|
||||||
withdrawer: stake_pool_accounts.withdraw_authority,
|
withdrawer: stake_pool_accounts.withdraw_authority,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1074,11 +1074,11 @@ async fn fail_with_bad_reserve() {
|
||||||
&payer,
|
&payer,
|
||||||
&recent_blockhash,
|
&recent_blockhash,
|
||||||
&bad_stake,
|
&bad_stake,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: wrong_authority,
|
staker: wrong_authority,
|
||||||
withdrawer: stake_pool_accounts.withdraw_authority,
|
withdrawer: stake_pool_accounts.withdraw_authority,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1124,11 +1124,11 @@ async fn fail_with_bad_reserve() {
|
||||||
&payer,
|
&payer,
|
||||||
&recent_blockhash,
|
&recent_blockhash,
|
||||||
&bad_stake,
|
&bad_stake,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: stake_pool_accounts.withdraw_authority,
|
staker: stake_pool_accounts.withdraw_authority,
|
||||||
withdrawer: wrong_authority,
|
withdrawer: wrong_authority,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1174,13 +1174,13 @@ async fn fail_with_bad_reserve() {
|
||||||
&payer,
|
&payer,
|
||||||
&recent_blockhash,
|
&recent_blockhash,
|
||||||
&bad_stake,
|
&bad_stake,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: stake_pool_accounts.withdraw_authority,
|
staker: stake_pool_accounts.withdraw_authority,
|
||||||
withdrawer: stake_pool_accounts.withdraw_authority,
|
withdrawer: stake_pool_accounts.withdraw_authority,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup {
|
&stake::state::Lockup {
|
||||||
custodian: wrong_authority,
|
custodian: wrong_authority,
|
||||||
..stake_program::Lockup::default()
|
..stake::state::Lockup::default()
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
@ -1223,15 +1223,15 @@ async fn fail_with_bad_reserve() {
|
||||||
{
|
{
|
||||||
let bad_stake = Keypair::new();
|
let bad_stake = Keypair::new();
|
||||||
let rent = banks_client.get_rent().await.unwrap();
|
let rent = banks_client.get_rent().await.unwrap();
|
||||||
let lamports = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let lamports = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
let transaction = Transaction::new_signed_with_payer(
|
let transaction = Transaction::new_signed_with_payer(
|
||||||
&[system_instruction::create_account(
|
&[system_instruction::create_account(
|
||||||
&payer.pubkey(),
|
&payer.pubkey(),
|
||||||
&bad_stake.pubkey(),
|
&bad_stake.pubkey(),
|
||||||
lamports,
|
lamports,
|
||||||
std::mem::size_of::<stake_program::StakeState>() as u64,
|
std::mem::size_of::<stake::state::StakeState>() as u64,
|
||||||
&stake_program::id(),
|
&stake::program::id(),
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
&[&payer, &bad_stake],
|
&[&payer, &bad_stake],
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod helpers;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
helpers::*,
|
helpers::*,
|
||||||
solana_program::{borsh::try_from_slice_unchecked, program_pack::Pack, pubkey::Pubkey},
|
solana_program::{borsh::try_from_slice_unchecked, program_pack::Pack, pubkey::Pubkey, stake},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
|
@ -12,7 +12,7 @@ use {
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{
|
||||||
find_transient_stake_program_address, id, instruction, stake_program,
|
find_transient_stake_program_address, id, instruction,
|
||||||
state::{StakePool, StakeStatus, ValidatorList},
|
state::{StakePool, StakeStatus, ValidatorList},
|
||||||
MAX_VALIDATORS_TO_UPDATE, MINIMUM_ACTIVE_STAKE,
|
MAX_VALIDATORS_TO_UPDATE, MINIMUM_ACTIVE_STAKE,
|
||||||
},
|
},
|
||||||
|
@ -163,7 +163,7 @@ async fn success() {
|
||||||
|
|
||||||
// Check current balance in the list
|
// Check current balance in the list
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
// initially, have all of the deposits plus their rent, and the reserve stake
|
// initially, have all of the deposits plus their rent, and the reserve stake
|
||||||
let initial_lamports =
|
let initial_lamports =
|
||||||
(validator_lamports + stake_rent) * num_validators as u64 + reserve_lamports;
|
(validator_lamports + stake_rent) * num_validators as u64 + reserve_lamports;
|
||||||
|
@ -436,7 +436,7 @@ async fn merge_into_validator_stake() {
|
||||||
|
|
||||||
// Check validator stake accounts have the expected balance now:
|
// Check validator stake accounts have the expected balance now:
|
||||||
// validator stake account minimum + deposited lamports + rents + increased lamports
|
// validator stake account minimum + deposited lamports + rents + increased lamports
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
let expected_lamports = MINIMUM_ACTIVE_STAKE
|
let expected_lamports = MINIMUM_ACTIVE_STAKE
|
||||||
+ lamports
|
+ lamports
|
||||||
+ reserve_lamports / stake_accounts.len() as u64
|
+ reserve_lamports / stake_accounts.len() as u64
|
||||||
|
@ -466,7 +466,7 @@ async fn merge_transient_stake_after_remove() {
|
||||||
setup(1).await;
|
setup(1).await;
|
||||||
|
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
let deactivated_lamports = lamports;
|
let deactivated_lamports = lamports;
|
||||||
let new_authority = Pubkey::new_unique();
|
let new_authority = Pubkey::new_unique();
|
||||||
let destination_stake = Keypair::new();
|
let destination_stake = Keypair::new();
|
||||||
|
@ -739,13 +739,13 @@ async fn success_ignoring_hijacked_transient_stake() {
|
||||||
&transient_stake_address,
|
&transient_stake_address,
|
||||||
1_000_000_000,
|
1_000_000_000,
|
||||||
),
|
),
|
||||||
stake_program::initialize(
|
stake::instruction::initialize(
|
||||||
&transient_stake_address,
|
&transient_stake_address,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: hijacker,
|
staker: hijacker,
|
||||||
withdrawer: hijacker,
|
withdrawer: hijacker,
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
),
|
),
|
||||||
instruction::update_stake_pool_balance(
|
instruction::update_stake_pool_balance(
|
||||||
&id(),
|
&id(),
|
||||||
|
|
|
@ -11,7 +11,7 @@ use {
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_program, sysvar,
|
stake, system_program, sysvar,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -19,9 +19,7 @@ use {
|
||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
transport::TransportError,
|
transport::TransportError,
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{error::StakePoolError, find_stake_program_address, id, instruction, state},
|
||||||
error::StakePoolError, find_stake_program_address, id, instruction, stake_program, state,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async fn setup() -> (
|
async fn setup() -> (
|
||||||
|
@ -102,9 +100,9 @@ async fn success() {
|
||||||
|
|
||||||
// Check stake account existence and authority
|
// Check stake account existence and authority
|
||||||
let stake = get_account(&mut banks_client, &validator_stake.stake_account).await;
|
let stake = get_account(&mut banks_client, &validator_stake.stake_account).await;
|
||||||
let stake_state = deserialize::<stake_program::StakeState>(&stake.data).unwrap();
|
let stake_state = deserialize::<stake::state::StakeState>(&stake.data).unwrap();
|
||||||
match stake_state {
|
match stake_state {
|
||||||
stake_program::StakeState::Stake(meta, _) => {
|
stake::state::StakeState::Stake(meta, _) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&meta.authorized.staker,
|
&meta.authorized.staker,
|
||||||
&stake_pool_accounts.withdraw_authority
|
&stake_pool_accounts.withdraw_authority
|
||||||
|
@ -252,9 +250,9 @@ async fn fail_without_signature() {
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::config_id(), false),
|
AccountMeta::new_readonly(stake::config::id(), false),
|
||||||
AccountMeta::new_readonly(system_program::id(), false),
|
AccountMeta::new_readonly(system_program::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
let instruction = Instruction {
|
let instruction = Instruction {
|
||||||
program_id: id(),
|
program_id: id(),
|
||||||
|
@ -301,7 +299,7 @@ async fn fail_with_wrong_stake_program_id() {
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::config_id(), false),
|
AccountMeta::new_readonly(stake::config::id(), false),
|
||||||
AccountMeta::new_readonly(system_program::id(), false),
|
AccountMeta::new_readonly(system_program::id(), false),
|
||||||
AccountMeta::new_readonly(wrong_stake_program, false),
|
AccountMeta::new_readonly(wrong_stake_program, false),
|
||||||
];
|
];
|
||||||
|
@ -348,9 +346,9 @@ async fn fail_with_wrong_system_program_id() {
|
||||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::config_id(), false),
|
AccountMeta::new_readonly(stake::config::id(), false),
|
||||||
AccountMeta::new_readonly(wrong_system_program, false),
|
AccountMeta::new_readonly(wrong_system_program, false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
let instruction = Instruction {
|
let instruction = Instruction {
|
||||||
program_id: id(),
|
program_id: id(),
|
||||||
|
|
|
@ -10,7 +10,7 @@ use {
|
||||||
borsh::try_from_slice_unchecked,
|
borsh::try_from_slice_unchecked,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction, sysvar,
|
stake, system_instruction, sysvar,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -19,8 +19,7 @@ use {
|
||||||
transport::TransportError,
|
transport::TransportError,
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{
|
||||||
error::StakePoolError, find_transient_stake_program_address, id, instruction,
|
error::StakePoolError, find_transient_stake_program_address, id, instruction, state,
|
||||||
stake_program, state,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,9 +130,9 @@ async fn success() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(account.is_none());
|
assert!(account.is_none());
|
||||||
let stake = get_account(&mut context.banks_client, &destination_stake.pubkey()).await;
|
let stake = get_account(&mut context.banks_client, &destination_stake.pubkey()).await;
|
||||||
let stake_state = deserialize::<stake_program::StakeState>(&stake.data).unwrap();
|
let stake_state = deserialize::<stake::state::StakeState>(&stake.data).unwrap();
|
||||||
match stake_state {
|
match stake_state {
|
||||||
stake_program::StakeState::Stake(meta, _) => {
|
stake::state::StakeState::Stake(meta, _) => {
|
||||||
assert_eq!(&meta.authorized.staker, &new_authority);
|
assert_eq!(&meta.authorized.staker, &new_authority);
|
||||||
assert_eq!(&meta.authorized.withdrawer, &new_authority);
|
assert_eq!(&meta.authorized.withdrawer, &new_authority);
|
||||||
}
|
}
|
||||||
|
@ -380,7 +379,7 @@ async fn fail_no_signature() {
|
||||||
AccountMeta::new_readonly(validator_stake.transient_stake_account, false),
|
AccountMeta::new_readonly(validator_stake.transient_stake_account, false),
|
||||||
AccountMeta::new(destination_stake.pubkey(), false),
|
AccountMeta::new(destination_stake.pubkey(), false),
|
||||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||||
AccountMeta::new_readonly(stake_program::id(), false),
|
AccountMeta::new_readonly(stake::program::id(), false),
|
||||||
];
|
];
|
||||||
let instruction = Instruction {
|
let instruction = Instruction {
|
||||||
program_id: id(),
|
program_id: id(),
|
||||||
|
@ -465,7 +464,7 @@ async fn success_with_deactivating_transient_stake() {
|
||||||
setup().await;
|
setup().await;
|
||||||
|
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
let deposit_info = simple_deposit_stake(
|
let deposit_info = simple_deposit_stake(
|
||||||
&mut context.banks_client,
|
&mut context.banks_client,
|
||||||
&context.payer,
|
&context.payer,
|
||||||
|
@ -667,9 +666,9 @@ async fn success_resets_preferred_validator() {
|
||||||
|
|
||||||
// Check of stake account authority has changed
|
// Check of stake account authority has changed
|
||||||
let stake = get_account(&mut context.banks_client, &destination_stake.pubkey()).await;
|
let stake = get_account(&mut context.banks_client, &destination_stake.pubkey()).await;
|
||||||
let stake_state = deserialize::<stake_program::StakeState>(&stake.data).unwrap();
|
let stake_state = deserialize::<stake::state::StakeState>(&stake.data).unwrap();
|
||||||
match stake_state {
|
match stake_state {
|
||||||
stake_program::StakeState::Stake(meta, _) => {
|
stake::state::StakeState::Stake(meta, _) => {
|
||||||
assert_eq!(&meta.authorized.staker, &new_authority);
|
assert_eq!(&meta.authorized.staker, &new_authority);
|
||||||
assert_eq!(&meta.authorized.withdrawer, &new_authority);
|
assert_eq!(&meta.authorized.withdrawer, &new_authority);
|
||||||
}
|
}
|
||||||
|
@ -756,13 +755,13 @@ async fn success_with_hijacked_transient_account() {
|
||||||
&transient_stake_address,
|
&transient_stake_address,
|
||||||
1_000_000_000,
|
1_000_000_000,
|
||||||
),
|
),
|
||||||
stake_program::initialize(
|
stake::instruction::initialize(
|
||||||
&transient_stake_address,
|
&transient_stake_address,
|
||||||
&stake_program::Authorized {
|
&stake::state::Authorized {
|
||||||
staker: hijacker.pubkey(),
|
staker: hijacker.pubkey(),
|
||||||
withdrawer: hijacker.pubkey(),
|
withdrawer: hijacker.pubkey(),
|
||||||
},
|
},
|
||||||
&stake_program::Lockup::default(),
|
&stake::state::Lockup::default(),
|
||||||
),
|
),
|
||||||
instruction::update_stake_pool_balance(
|
instruction::update_stake_pool_balance(
|
||||||
&id(),
|
&id(),
|
||||||
|
|
|
@ -11,7 +11,7 @@ use {
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sysvar,
|
stake, sysvar,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -19,9 +19,7 @@ use {
|
||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
transport::TransportError,
|
transport::TransportError,
|
||||||
},
|
},
|
||||||
spl_stake_pool::{
|
spl_stake_pool::{error::StakePoolError, id, instruction, minimum_stake_lamports, state},
|
||||||
error::StakePoolError, id, instruction, minimum_stake_lamports, stake_program, state,
|
|
||||||
},
|
|
||||||
spl_token::error::TokenError,
|
spl_token::error::TokenError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -298,10 +296,10 @@ async fn _success(test_type: SuccessTestType) {
|
||||||
let validator_stake_account =
|
let validator_stake_account =
|
||||||
get_account(&mut banks_client, &validator_stake_account.stake_account).await;
|
get_account(&mut banks_client, &validator_stake_account.stake_account).await;
|
||||||
let stake_state =
|
let stake_state =
|
||||||
deserialize::<stake_program::StakeState>(&validator_stake_account.data).unwrap();
|
deserialize::<stake::state::StakeState>(&validator_stake_account.data).unwrap();
|
||||||
let meta = stake_state.meta().unwrap();
|
let meta = stake_state.meta().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
validator_stake_account.lamports - minimum_stake_lamports(meta),
|
validator_stake_account.lamports - minimum_stake_lamports(&meta),
|
||||||
validator_stake_item.active_stake_lamports
|
validator_stake_item.active_stake_lamports
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -856,7 +854,7 @@ async fn success_with_reserve() {
|
||||||
|
|
||||||
let deposit_lamports = TEST_STAKE_AMOUNT;
|
let deposit_lamports = TEST_STAKE_AMOUNT;
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
let deposit_info = simple_deposit_stake(
|
let deposit_info = simple_deposit_stake(
|
||||||
&mut context.banks_client,
|
&mut context.banks_client,
|
||||||
|
@ -1032,8 +1030,7 @@ async fn success_with_reserve() {
|
||||||
&stake_pool_accounts.reserve_stake.pubkey(),
|
&stake_pool_accounts.reserve_stake.pubkey(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let stake_state =
|
let stake_state = deserialize::<stake::state::StakeState>(&reserve_stake_account.data).unwrap();
|
||||||
deserialize::<stake_program::StakeState>(&reserve_stake_account.data).unwrap();
|
|
||||||
let meta = stake_state.meta().unwrap();
|
let meta = stake_state.meta().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
initial_reserve_lamports + meta.rent_exempt_reserve + withdrawal_fee + deposit_fee,
|
initial_reserve_lamports + meta.rent_exempt_reserve + withdrawal_fee + deposit_fee,
|
||||||
|
@ -1233,7 +1230,7 @@ async fn success_withdraw_from_transient() {
|
||||||
|
|
||||||
let deposit_lamports = TEST_STAKE_AMOUNT;
|
let deposit_lamports = TEST_STAKE_AMOUNT;
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
|
|
||||||
let deposit_info = simple_deposit_stake(
|
let deposit_info = simple_deposit_stake(
|
||||||
&mut context.banks_client,
|
&mut context.banks_client,
|
||||||
|
|
|
@ -5,7 +5,7 @@ mod helpers;
|
||||||
use {
|
use {
|
||||||
helpers::*,
|
helpers::*,
|
||||||
solana_program::{
|
solana_program::{
|
||||||
borsh::try_from_slice_unchecked, instruction::InstructionError, pubkey::Pubkey,
|
borsh::try_from_slice_unchecked, instruction::InstructionError, pubkey::Pubkey, stake,
|
||||||
},
|
},
|
||||||
solana_program_test::*,
|
solana_program_test::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -17,7 +17,7 @@ use {
|
||||||
error::StakePoolError,
|
error::StakePoolError,
|
||||||
id,
|
id,
|
||||||
instruction::{self, FundingType},
|
instruction::{self, FundingType},
|
||||||
stake_program, state,
|
state,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ async fn fail_overdraw_reserve() {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let rent = context.banks_client.get_rent().await.unwrap();
|
let rent = context.banks_client.get_rent().await.unwrap();
|
||||||
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake_program::StakeState>());
|
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
|
||||||
let error = stake_pool_accounts
|
let error = stake_pool_accounts
|
||||||
.increase_validator_stake(
|
.increase_validator_stake(
|
||||||
&mut context.banks_client,
|
&mut context.banks_client,
|
||||||
|
|
Loading…
Reference in New Issue