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,
|
Deactivate,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(stake_pubkey: &Pubkey, authorized: &Authorized, lockup: &Lockup) -> Instruction {
|
fn initialize(stake_pubkey: &Pubkey, authorized: &Authorized, lockup: &Lockup) -> Instruction {
|
||||||
Instruction::new(
|
Instruction::new(
|
||||||
id(),
|
id(),
|
||||||
&StakeInstruction::Initialize(*authorized, *lockup),
|
&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(
|
pub fn split(
|
||||||
stake_pubkey: &Pubkey,
|
stake_pubkey: &Pubkey,
|
||||||
authorized_pubkey: &Pubkey,
|
authorized_pubkey: &Pubkey,
|
||||||
|
@ -188,21 +203,39 @@ pub fn split(
|
||||||
split_stake_pubkey: &Pubkey,
|
split_stake_pubkey: &Pubkey,
|
||||||
) -> Vec<Instruction> {
|
) -> Vec<Instruction> {
|
||||||
vec![
|
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,
|
stake_pubkey,
|
||||||
|
authorized_pubkey,
|
||||||
|
lamports,
|
||||||
split_stake_pubkey,
|
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,
|
std::mem::size_of::<StakeState>() as u64,
|
||||||
&id(),
|
&id(),
|
||||||
),
|
),
|
||||||
{
|
_split(
|
||||||
let account_metas = vec![
|
stake_pubkey,
|
||||||
AccountMeta::new(*stake_pubkey, false),
|
authorized_pubkey,
|
||||||
AccountMeta::new(*split_stake_pubkey, false),
|
lamports,
|
||||||
]
|
split_stake_pubkey,
|
||||||
.with_signer(authorized_pubkey);
|
),
|
||||||
Instruction::new(id(), &StakeInstruction::Split(lamports), account_metas)
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,6 +511,19 @@ mod tests {
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
100,
|
100,
|
||||||
&Pubkey::default()
|
&Pubkey::default()
|
||||||
|
)[2]
|
||||||
|
),
|
||||||
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
process_instruction(
|
||||||
|
&split_with_seed(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
100,
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
"seed"
|
||||||
)[1]
|
)[1]
|
||||||
),
|
),
|
||||||
Err(InstructionError::InvalidAccountData),
|
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]
|
#[test]
|
||||||
fn test_authorize_delegated_stake() {
|
fn test_authorize_delegated_stake() {
|
||||||
let stake_pubkey = Pubkey::new_rand();
|
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]
|
#[test]
|
||||||
fn test_stake_account_lifetime() {
|
fn test_stake_account_lifetime() {
|
||||||
let stake_keypair = Keypair::new();
|
let stake_keypair = Keypair::new();
|
||||||
|
|
Loading…
Reference in New Issue