Add support for stake::split() via create_account_with_seed() (#7879)
* Add split with seed * move to new system_program APIs * de-replicode
This commit is contained in:
parent
82b75796f9
commit
cc299053cc
|
@ -128,7 +128,7 @@ pub enum StakeInstruction {
|
|||
Deactivate,
|
||||
}
|
||||
|
||||
pub fn initialize(stake_pubkey: &Pubkey, authorized: &Authorized, lockup: &Lockup) -> Instruction {
|
||||
fn initialize(stake_pubkey: &Pubkey, authorized: &Authorized, lockup: &Lockup) -> Instruction {
|
||||
Instruction::new(
|
||||
id(),
|
||||
&StakeInstruction::Initialize(*authorized, *lockup),
|
||||
|
@ -181,6 +181,21 @@ pub fn create_account(
|
|||
]
|
||||
}
|
||||
|
||||
fn _split(
|
||||
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),
|
||||
]
|
||||
.with_signer(authorized_pubkey);
|
||||
|
||||
Instruction::new(id(), &StakeInstruction::Split(lamports), account_metas)
|
||||
}
|
||||
|
||||
pub fn split(
|
||||
stake_pubkey: &Pubkey,
|
||||
authorized_pubkey: &Pubkey,
|
||||
|
@ -188,21 +203,39 @@ pub fn split(
|
|||
split_stake_pubkey: &Pubkey,
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::create_account(
|
||||
system_instruction::allocate(split_stake_pubkey, std::mem::size_of::<StakeState>() as u64),
|
||||
system_instruction::assign(split_stake_pubkey, &id()),
|
||||
_split(
|
||||
stake_pubkey,
|
||||
authorized_pubkey,
|
||||
lamports,
|
||||
split_stake_pubkey,
|
||||
0, // creates an ephemeral, uninitialized Stake
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn split_with_seed(
|
||||
stake_pubkey: &Pubkey,
|
||||
authorized_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
split_stake_pubkey: &Pubkey, // derived using create_address_with_seed()
|
||||
base: &Pubkey, // base
|
||||
seed: &str, // seed
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::allocate_with_seed(
|
||||
split_stake_pubkey,
|
||||
base,
|
||||
seed,
|
||||
std::mem::size_of::<StakeState>() as u64,
|
||||
&id(),
|
||||
),
|
||||
{
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*stake_pubkey, false),
|
||||
AccountMeta::new(*split_stake_pubkey, false),
|
||||
]
|
||||
.with_signer(authorized_pubkey);
|
||||
Instruction::new(id(), &StakeInstruction::Split(lamports), account_metas)
|
||||
},
|
||||
_split(
|
||||
stake_pubkey,
|
||||
authorized_pubkey,
|
||||
lamports,
|
||||
split_stake_pubkey,
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -478,6 +511,19 @@ mod tests {
|
|||
&Pubkey::default(),
|
||||
100,
|
||||
&Pubkey::default()
|
||||
)[2]
|
||||
),
|
||||
Err(InstructionError::InvalidAccountData),
|
||||
);
|
||||
assert_eq!(
|
||||
process_instruction(
|
||||
&split_with_seed(
|
||||
&Pubkey::default(),
|
||||
&Pubkey::default(),
|
||||
100,
|
||||
&Pubkey::default(),
|
||||
&Pubkey::default(),
|
||||
"seed"
|
||||
)[1]
|
||||
),
|
||||
Err(InstructionError::InvalidAccountData),
|
||||
|
|
|
@ -2779,6 +2779,18 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
#[should_panic]
|
||||
fn test_dbg_stake_minimum_balance() {
|
||||
let minimum_balance = Rent::default().minimum_balance(std::mem::size_of::<StakeState>());
|
||||
panic!(
|
||||
"stake minimum_balance: {} lamports, {} SOL",
|
||||
minimum_balance,
|
||||
minimum_balance as f64 / solana_sdk::native_token::LAMPORTS_PER_SOL as f64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_authorize_delegated_stake() {
|
||||
let stake_pubkey = Pubkey::new_rand();
|
||||
|
|
|
@ -97,6 +97,67 @@ fn get_staked(bank: &Bank, stake_pubkey: &Pubkey) -> u64 {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stake_create_and_split_single_signature() {
|
||||
solana_logger::setup();
|
||||
|
||||
let GenesisConfigInfo {
|
||||
mut genesis_config,
|
||||
mint_keypair: staker_keypair,
|
||||
..
|
||||
} = create_genesis_config_with_leader(100_000_000_000, &Pubkey::new_rand(), 1_000_000);
|
||||
genesis_config
|
||||
.native_instruction_processors
|
||||
.push(solana_stake_program::solana_stake_program!());
|
||||
|
||||
let staker_pubkey = staker_keypair.pubkey();
|
||||
|
||||
let bank_client = BankClient::new_shared(&Arc::new(Bank::new(&genesis_config)));
|
||||
|
||||
let stake_address =
|
||||
create_address_with_seed(&staker_pubkey, "stake", &solana_stake_program::id()).unwrap();
|
||||
|
||||
let authorized = stake_state::Authorized::auto(&staker_pubkey);
|
||||
|
||||
let lamports = 1_000_000;
|
||||
|
||||
// Create stake account with seed
|
||||
let message = Message::new(stake_instruction::create_account_with_seed(
|
||||
&staker_pubkey, // from
|
||||
&stake_address, // to
|
||||
&staker_pubkey, // base
|
||||
"stake", // seed
|
||||
&authorized,
|
||||
&stake_state::Lockup::default(),
|
||||
lamports,
|
||||
));
|
||||
|
||||
// only one signature required
|
||||
bank_client
|
||||
.send_message(&[&staker_keypair], message)
|
||||
.expect("failed to create and delegate stake account");
|
||||
|
||||
// split the stake
|
||||
let split_stake_address =
|
||||
create_address_with_seed(&staker_pubkey, "split_stake", &solana_stake_program::id())
|
||||
.unwrap();
|
||||
// Test split
|
||||
let message = Message::new(stake_instruction::split_with_seed(
|
||||
&stake_address, // original
|
||||
&staker_pubkey, // authorized
|
||||
lamports / 2,
|
||||
&split_stake_address, // new address
|
||||
&staker_pubkey, // base
|
||||
"split_stake", // seed
|
||||
));
|
||||
|
||||
assert!(bank_client
|
||||
.send_message(&[&staker_keypair], message)
|
||||
.is_ok());
|
||||
|
||||
// w00t!
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stake_account_lifetime() {
|
||||
let stake_keypair = Keypair::new();
|
||||
|
|
Loading…
Reference in New Issue