require stake, vote and executable accounts to be rent exempt (#5928)
* require vote account to be exempt * make stake account rent exempt * add rent exempted system instruction * use rent exemption instruction in vote and stake api * use rent exempted account while creating executable account * updating chacha golden hash as instruction data has changed * rent will be initialized for genesis bank too
This commit is contained in:
parent
accd49f2e4
commit
11e6197a83
|
@ -871,7 +871,7 @@ fn process_deploy(
|
||||||
// Build transactions to calculate fees
|
// Build transactions to calculate fees
|
||||||
let mut messages: Vec<&Message> = Vec::new();
|
let mut messages: Vec<&Message> = Vec::new();
|
||||||
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||||
let mut create_account_tx = system_transaction::create_account(
|
let mut create_account_tx = system_transaction::create_rent_exempted_account(
|
||||||
&config.keypair,
|
&config.keypair,
|
||||||
&program_id.pubkey(),
|
&program_id.pubkey(),
|
||||||
blockhash,
|
blockhash,
|
||||||
|
|
|
@ -153,7 +153,7 @@ mod tests {
|
||||||
hasher.hash(&buf[..size]);
|
hasher.hash(&buf[..size]);
|
||||||
|
|
||||||
// golden needs to be updated if blob stuff changes....
|
// golden needs to be updated if blob stuff changes....
|
||||||
let golden: Hash = "CLGvEayebjdgnLdttFAweZE9rqVkehXqEStUifG9kiU9"
|
let golden: Hash = "7P2RmguCZaaBDzjvAej6RnqiA3v82s3PyaCX3uNzsjfc"
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -396,7 +396,8 @@ mod tests {
|
||||||
SystemInstruction::CreateAccount {
|
SystemInstruction::CreateAccount {
|
||||||
lamports: 2,
|
lamports: 2,
|
||||||
space: 0,
|
space: 0,
|
||||||
program_id: Pubkey::default()
|
program_id: Pubkey::default(),
|
||||||
|
require_rent_exemption: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ pub fn create_stake_account_with_lockup(
|
||||||
custodian: &Pubkey,
|
custodian: &Pubkey,
|
||||||
) -> Vec<Instruction> {
|
) -> Vec<Instruction> {
|
||||||
vec![
|
vec![
|
||||||
system_instruction::create_account(
|
system_instruction::create_rent_exempted_account(
|
||||||
from_pubkey,
|
from_pubkey,
|
||||||
stake_pubkey,
|
stake_pubkey,
|
||||||
lamports,
|
lamports,
|
||||||
|
|
|
@ -87,8 +87,13 @@ pub fn create_account(
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
) -> Vec<Instruction> {
|
) -> Vec<Instruction> {
|
||||||
let space = VoteState::size_of() as u64;
|
let space = VoteState::size_of() as u64;
|
||||||
let create_ix =
|
let create_ix = system_instruction::create_rent_exempted_account(
|
||||||
system_instruction::create_account(from_pubkey, vote_pubkey, lamports, space, &id());
|
from_pubkey,
|
||||||
|
vote_pubkey,
|
||||||
|
lamports,
|
||||||
|
space,
|
||||||
|
&id(),
|
||||||
|
);
|
||||||
let init_ix = initialize_account(vote_pubkey, node_pubkey, commission);
|
let init_ix = initialize_account(vote_pubkey, node_pubkey, commission);
|
||||||
vec![create_ix, init_ix]
|
vec![create_ix, init_ix]
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,6 +275,7 @@ impl Bank {
|
||||||
bank.update_stake_history(None);
|
bank.update_stake_history(None);
|
||||||
}
|
}
|
||||||
bank.update_clock();
|
bank.update_clock();
|
||||||
|
bank.update_rent();
|
||||||
bank
|
bank
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub fn load_program<T: Client>(
|
||||||
let program_keypair = Keypair::new();
|
let program_keypair = Keypair::new();
|
||||||
let program_pubkey = program_keypair.pubkey();
|
let program_pubkey = program_keypair.pubkey();
|
||||||
|
|
||||||
let instruction = system_instruction::create_account(
|
let instruction = system_instruction::create_rent_exempted_account(
|
||||||
&from_keypair.pubkey(),
|
&from_keypair.pubkey(),
|
||||||
&program_pubkey,
|
&program_pubkey,
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -2,18 +2,22 @@ use log::*;
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::account::KeyedAccount;
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::rent_calculator::RentCalculator;
|
||||||
use solana_sdk::system_instruction::{SystemError, SystemInstruction};
|
use solana_sdk::system_instruction::{SystemError, SystemInstruction};
|
||||||
use solana_sdk::system_program;
|
use solana_sdk::system_program;
|
||||||
use solana_sdk::sysvar;
|
use solana_sdk::sysvar;
|
||||||
|
use solana_sdk::sysvar::rent;
|
||||||
|
|
||||||
const FROM_ACCOUNT_INDEX: usize = 0;
|
const FROM_ACCOUNT_INDEX: usize = 0;
|
||||||
const TO_ACCOUNT_INDEX: usize = 1;
|
const TO_ACCOUNT_INDEX: usize = 1;
|
||||||
|
const RENT_SYSVAR_ACCOUNT_INDEX: usize = 2;
|
||||||
|
|
||||||
fn create_system_account(
|
fn create_system_account(
|
||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
space: u64,
|
space: u64,
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
|
rent_exemption_calculator: Option<RentCalculator>,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
if !system_program::check_id(&keyed_accounts[FROM_ACCOUNT_INDEX].account.owner) {
|
if !system_program::check_id(&keyed_accounts[FROM_ACCOUNT_INDEX].account.owner) {
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -56,6 +60,13 @@ fn create_system_account(
|
||||||
);
|
);
|
||||||
Err(SystemError::ResultWithNegativeLamports)?;
|
Err(SystemError::ResultWithNegativeLamports)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(calculator) = rent_exemption_calculator {
|
||||||
|
if !calculator.is_exempt(lamports, space as usize) {
|
||||||
|
Err(SystemError::InsufficientFunds)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keyed_accounts[FROM_ACCOUNT_INDEX].account.lamports -= lamports;
|
keyed_accounts[FROM_ACCOUNT_INDEX].account.lamports -= lamports;
|
||||||
keyed_accounts[TO_ACCOUNT_INDEX].account.lamports += lamports;
|
keyed_accounts[TO_ACCOUNT_INDEX].account.lamports += lamports;
|
||||||
keyed_accounts[TO_ACCOUNT_INDEX].account.owner = *program_id;
|
keyed_accounts[TO_ACCOUNT_INDEX].account.owner = *program_id;
|
||||||
|
@ -107,7 +118,28 @@ pub fn process_instruction(
|
||||||
lamports,
|
lamports,
|
||||||
space,
|
space,
|
||||||
program_id,
|
program_id,
|
||||||
} => create_system_account(keyed_accounts, lamports, space, &program_id),
|
require_rent_exemption,
|
||||||
|
} => {
|
||||||
|
let rent_exemption_calculator: Option<RentCalculator> = if require_rent_exemption {
|
||||||
|
if keyed_accounts.len() < (RENT_SYSVAR_ACCOUNT_INDEX + 1) {
|
||||||
|
Err(InstructionError::InvalidInstructionData)?;
|
||||||
|
}
|
||||||
|
Some(
|
||||||
|
rent::from_keyed_account(&keyed_accounts[RENT_SYSVAR_ACCOUNT_INDEX])?
|
||||||
|
.rent_calculator,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
create_system_account(
|
||||||
|
keyed_accounts,
|
||||||
|
lamports,
|
||||||
|
space,
|
||||||
|
&program_id,
|
||||||
|
rent_exemption_calculator,
|
||||||
|
)
|
||||||
|
}
|
||||||
SystemInstruction::Assign { program_id } => {
|
SystemInstruction::Assign { program_id } => {
|
||||||
if !system_program::check_id(&keyed_accounts[FROM_ACCOUNT_INDEX].account.owner) {
|
if !system_program::check_id(&keyed_accounts[FROM_ACCOUNT_INDEX].account.owner) {
|
||||||
Err(InstructionError::IncorrectProgramId)?;
|
Err(InstructionError::IncorrectProgramId)?;
|
||||||
|
@ -133,6 +165,7 @@ mod tests {
|
||||||
use solana_sdk::client::SyncClient;
|
use solana_sdk::client::SyncClient;
|
||||||
use solana_sdk::genesis_block::create_genesis_block;
|
use solana_sdk::genesis_block::create_genesis_block;
|
||||||
use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError};
|
use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError};
|
||||||
|
use solana_sdk::rent_calculator::RentCalculator;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_program;
|
use solana_sdk::system_program;
|
||||||
use solana_sdk::transaction::TransactionError;
|
use solana_sdk::transaction::TransactionError;
|
||||||
|
@ -150,7 +183,7 @@ mod tests {
|
||||||
KeyedAccount::new(&from, true, &mut from_account),
|
KeyedAccount::new(&from, true, &mut from_account),
|
||||||
KeyedAccount::new(&to, false, &mut to_account),
|
KeyedAccount::new(&to, false, &mut to_account),
|
||||||
];
|
];
|
||||||
create_system_account(&mut keyed_accounts, 50, 2, &new_program_owner).unwrap();
|
create_system_account(&mut keyed_accounts, 50, 2, &new_program_owner, None).unwrap();
|
||||||
let from_lamports = from_account.lamports;
|
let from_lamports = from_account.lamports;
|
||||||
let to_lamports = to_account.lamports;
|
let to_lamports = to_account.lamports;
|
||||||
let to_owner = to_account.owner;
|
let to_owner = to_account.owner;
|
||||||
|
@ -176,7 +209,7 @@ mod tests {
|
||||||
KeyedAccount::new(&from, true, &mut from_account),
|
KeyedAccount::new(&from, true, &mut from_account),
|
||||||
KeyedAccount::new(&to, false, &mut to_account),
|
KeyedAccount::new(&to, false, &mut to_account),
|
||||||
];
|
];
|
||||||
let result = create_system_account(&mut keyed_accounts, 150, 2, &new_program_owner);
|
let result = create_system_account(&mut keyed_accounts, 150, 2, &new_program_owner, None);
|
||||||
assert_eq!(result, Err(SystemError::ResultWithNegativeLamports));
|
assert_eq!(result, Err(SystemError::ResultWithNegativeLamports));
|
||||||
let from_lamports = from_account.lamports;
|
let from_lamports = from_account.lamports;
|
||||||
assert_eq!(from_lamports, 100);
|
assert_eq!(from_lamports, 100);
|
||||||
|
@ -199,7 +232,7 @@ mod tests {
|
||||||
KeyedAccount::new(&from, true, &mut from_account),
|
KeyedAccount::new(&from, true, &mut from_account),
|
||||||
KeyedAccount::new(&owned_key, false, &mut owned_account),
|
KeyedAccount::new(&owned_key, false, &mut owned_account),
|
||||||
];
|
];
|
||||||
let result = create_system_account(&mut keyed_accounts, 50, 2, &new_program_owner);
|
let result = create_system_account(&mut keyed_accounts, 50, 2, &new_program_owner, None);
|
||||||
assert_eq!(result, Err(SystemError::AccountAlreadyInUse));
|
assert_eq!(result, Err(SystemError::AccountAlreadyInUse));
|
||||||
let from_lamports = from_account.lamports;
|
let from_lamports = from_account.lamports;
|
||||||
assert_eq!(from_lamports, 100);
|
assert_eq!(from_lamports, 100);
|
||||||
|
@ -220,7 +253,7 @@ mod tests {
|
||||||
KeyedAccount::new(&to, false, &mut to_account),
|
KeyedAccount::new(&to, false, &mut to_account),
|
||||||
];
|
];
|
||||||
// fail to create a sysvar::id() owned account
|
// fail to create a sysvar::id() owned account
|
||||||
let result = create_system_account(&mut keyed_accounts, 50, 2, &sysvar::id());
|
let result = create_system_account(&mut keyed_accounts, 50, 2, &sysvar::id(), None);
|
||||||
assert_eq!(result, Err(SystemError::InvalidProgramId));
|
assert_eq!(result, Err(SystemError::InvalidProgramId));
|
||||||
|
|
||||||
let to = sysvar::fees::id();
|
let to = sysvar::fees::id();
|
||||||
|
@ -231,7 +264,7 @@ mod tests {
|
||||||
KeyedAccount::new(&to, false, &mut to_account),
|
KeyedAccount::new(&to, false, &mut to_account),
|
||||||
];
|
];
|
||||||
// fail to create an account with a sysvar id
|
// fail to create an account with a sysvar id
|
||||||
let result = create_system_account(&mut keyed_accounts, 50, 2, &system_program::id());
|
let result = create_system_account(&mut keyed_accounts, 50, 2, &system_program::id(), None);
|
||||||
assert_eq!(result, Err(SystemError::InvalidAccountId));
|
assert_eq!(result, Err(SystemError::InvalidAccountId));
|
||||||
|
|
||||||
let from_lamports = from_account.lamports;
|
let from_lamports = from_account.lamports;
|
||||||
|
@ -256,12 +289,66 @@ mod tests {
|
||||||
KeyedAccount::new(&from, true, &mut from_account),
|
KeyedAccount::new(&from, true, &mut from_account),
|
||||||
KeyedAccount::new(&populated_key, false, &mut populated_account),
|
KeyedAccount::new(&populated_key, false, &mut populated_account),
|
||||||
];
|
];
|
||||||
let result = create_system_account(&mut keyed_accounts, 50, 2, &new_program_owner);
|
let result = create_system_account(&mut keyed_accounts, 50, 2, &new_program_owner, None);
|
||||||
assert_eq!(result, Err(SystemError::AccountAlreadyInUse));
|
assert_eq!(result, Err(SystemError::AccountAlreadyInUse));
|
||||||
assert_eq!(from_account.lamports, 100);
|
assert_eq!(from_account.lamports, 100);
|
||||||
assert_eq!(populated_account, unchanged_account);
|
assert_eq!(populated_account, unchanged_account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_rent_exempt() {
|
||||||
|
let other_program = Pubkey::new(&[9; 32]);
|
||||||
|
|
||||||
|
let from = Pubkey::new_rand();
|
||||||
|
let mut from_account = Account::new(1000, 0, &system_program::id());
|
||||||
|
let to = Pubkey::new_rand();
|
||||||
|
let mut to_account = Account::new(0, 0, &Pubkey::default());
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let rent_calculator = RentCalculator {
|
||||||
|
lamports_per_byte_year: 50,
|
||||||
|
exemption_threshold: 2.0,
|
||||||
|
burn_percent: 0,
|
||||||
|
};
|
||||||
|
let mut rent_sysvar_account = rent::create_account(50, &rent_calculator);
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&from, true, &mut from_account),
|
||||||
|
KeyedAccount::new(&to, false, &mut to_account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_sysvar_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
// if rent exemption flag is false, then account will be created successfully.
|
||||||
|
let result = create_system_account(&mut keyed_accounts, 0, 2, &other_program, None);
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let to = Pubkey::new_rand();
|
||||||
|
let mut to_account = Account::new(0, 0, &Pubkey::default());
|
||||||
|
keyed_accounts[1] = KeyedAccount::new(&to, false, &mut to_account);
|
||||||
|
|
||||||
|
// there must be sufficient amount of lamport in account to be created as rent exempted
|
||||||
|
let result = create_system_account(
|
||||||
|
&mut keyed_accounts,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
&other_program,
|
||||||
|
Some(rent_calculator),
|
||||||
|
);
|
||||||
|
assert_eq!(result, Err(SystemError::InsufficientFunds));
|
||||||
|
|
||||||
|
let to = Pubkey::new_rand();
|
||||||
|
let mut to_account = Account::new(0, 0, &Pubkey::default());
|
||||||
|
keyed_accounts[1] = KeyedAccount::new(&to, false, &mut to_account);
|
||||||
|
|
||||||
|
// amount of lamports must be sufficient for account to be rent exempt
|
||||||
|
let result = create_system_account(
|
||||||
|
&mut keyed_accounts,
|
||||||
|
500,
|
||||||
|
2,
|
||||||
|
&other_program,
|
||||||
|
Some(rent_calculator),
|
||||||
|
);
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_not_system_account() {
|
fn test_create_not_system_account() {
|
||||||
let other_program = Pubkey::new(&[9; 32]);
|
let other_program = Pubkey::new(&[9; 32]);
|
||||||
|
@ -274,7 +361,7 @@ mod tests {
|
||||||
KeyedAccount::new(&from, true, &mut from_account),
|
KeyedAccount::new(&from, true, &mut from_account),
|
||||||
KeyedAccount::new(&to, false, &mut to_account),
|
KeyedAccount::new(&to, false, &mut to_account),
|
||||||
];
|
];
|
||||||
let result = create_system_account(&mut keyed_accounts, 50, 2, &other_program);
|
let result = create_system_account(&mut keyed_accounts, 50, 2, &other_program, None);
|
||||||
assert_eq!(result, Err(SystemError::SourceNotSystemAccount));
|
assert_eq!(result, Err(SystemError::SourceNotSystemAccount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::instruction::{AccountMeta, Instruction};
|
||||||
use crate::instruction_processor_utils::DecodeError;
|
use crate::instruction_processor_utils::DecodeError;
|
||||||
use crate::pubkey::Pubkey;
|
use crate::pubkey::Pubkey;
|
||||||
use crate::system_program;
|
use crate::system_program;
|
||||||
|
use crate::sysvar::rent;
|
||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone, PartialEq, FromPrimitive)]
|
#[derive(Serialize, Debug, Clone, PartialEq, FromPrimitive)]
|
||||||
|
@ -11,6 +12,7 @@ pub enum SystemError {
|
||||||
SourceNotSystemAccount,
|
SourceNotSystemAccount,
|
||||||
InvalidProgramId,
|
InvalidProgramId,
|
||||||
InvalidAccountId,
|
InvalidAccountId,
|
||||||
|
InsufficientFunds,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> DecodeError<T> for SystemError {
|
impl<T> DecodeError<T> for SystemError {
|
||||||
|
@ -31,13 +33,16 @@ pub enum SystemInstruction {
|
||||||
/// Create a new account
|
/// Create a new account
|
||||||
/// * Transaction::keys[0] - source
|
/// * Transaction::keys[0] - source
|
||||||
/// * Transaction::keys[1] - new account key
|
/// * Transaction::keys[1] - new account key
|
||||||
|
/// * Transaction::keys[2] - rent sysvar account key (Only required if require_rent_exemption is true)
|
||||||
/// * lamports - number of lamports to transfer to the new account
|
/// * lamports - number of lamports to transfer to the new account
|
||||||
/// * space - memory to allocate if greater then zero
|
/// * space - memory to allocate if greater then zero
|
||||||
/// * program_id - the program id of the new account
|
/// * program_id - the program id of the new account
|
||||||
|
/// * require_rent_exemption - if set to true, only allow account creation if it's rent exempt
|
||||||
CreateAccount {
|
CreateAccount {
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
space: u64,
|
space: u64,
|
||||||
program_id: Pubkey,
|
program_id: Pubkey,
|
||||||
|
require_rent_exemption: bool,
|
||||||
},
|
},
|
||||||
/// Assign account to a program
|
/// Assign account to a program
|
||||||
/// * Transaction::keys[0] - account to assign
|
/// * Transaction::keys[0] - account to assign
|
||||||
|
@ -55,16 +60,43 @@ pub fn create_account(
|
||||||
space: u64,
|
space: u64,
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
) -> Instruction {
|
) -> Instruction {
|
||||||
let account_metas = vec![
|
generate_create_account_instruction(from_pubkey, to_pubkey, lamports, space, program_id, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_rent_exempted_account(
|
||||||
|
from_pubkey: &Pubkey,
|
||||||
|
to_pubkey: &Pubkey,
|
||||||
|
lamports: u64,
|
||||||
|
space: u64,
|
||||||
|
program_id: &Pubkey,
|
||||||
|
) -> Instruction {
|
||||||
|
generate_create_account_instruction(from_pubkey, to_pubkey, lamports, space, program_id, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn generate_create_account_instruction(
|
||||||
|
from_pubkey: &Pubkey,
|
||||||
|
to_pubkey: &Pubkey,
|
||||||
|
lamports: u64,
|
||||||
|
space: u64,
|
||||||
|
program_id: &Pubkey,
|
||||||
|
require_rent_exemption: bool,
|
||||||
|
) -> Instruction {
|
||||||
|
let mut account_metas = vec![
|
||||||
AccountMeta::new(*from_pubkey, true),
|
AccountMeta::new(*from_pubkey, true),
|
||||||
AccountMeta::new(*to_pubkey, false),
|
AccountMeta::new(*to_pubkey, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if require_rent_exemption {
|
||||||
|
account_metas.push(AccountMeta::new(rent::id(), false));
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::new(
|
Instruction::new(
|
||||||
system_program::id(),
|
system_program::id(),
|
||||||
&SystemInstruction::CreateAccount {
|
&SystemInstruction::CreateAccount {
|
||||||
lamports,
|
lamports,
|
||||||
space,
|
space,
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
require_rent_exemption,
|
||||||
},
|
},
|
||||||
account_metas,
|
account_metas,
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,10 +15,55 @@ pub fn create_account(
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
space: u64,
|
space: u64,
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
|
) -> Transaction {
|
||||||
|
generate_create_account_tx(
|
||||||
|
from_keypair,
|
||||||
|
to,
|
||||||
|
recent_blockhash,
|
||||||
|
lamports,
|
||||||
|
space,
|
||||||
|
program_id,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_rent_exempted_account(
|
||||||
|
from_keypair: &Keypair,
|
||||||
|
to: &Pubkey,
|
||||||
|
recent_blockhash: Hash,
|
||||||
|
lamports: u64,
|
||||||
|
space: u64,
|
||||||
|
program_id: &Pubkey,
|
||||||
|
) -> Transaction {
|
||||||
|
generate_create_account_tx(
|
||||||
|
from_keypair,
|
||||||
|
to,
|
||||||
|
recent_blockhash,
|
||||||
|
lamports,
|
||||||
|
space,
|
||||||
|
program_id,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_create_account_tx(
|
||||||
|
from_keypair: &Keypair,
|
||||||
|
to: &Pubkey,
|
||||||
|
recent_blockhash: Hash,
|
||||||
|
lamports: u64,
|
||||||
|
space: u64,
|
||||||
|
program_id: &Pubkey,
|
||||||
|
require_rent_exemption: bool,
|
||||||
) -> Transaction {
|
) -> Transaction {
|
||||||
let from_pubkey = from_keypair.pubkey();
|
let from_pubkey = from_keypair.pubkey();
|
||||||
let create_instruction =
|
let create_instruction = system_instruction::generate_create_account_instruction(
|
||||||
system_instruction::create_account(&from_pubkey, to, lamports, space, program_id);
|
&from_pubkey,
|
||||||
|
to,
|
||||||
|
lamports,
|
||||||
|
space,
|
||||||
|
program_id,
|
||||||
|
require_rent_exemption,
|
||||||
|
);
|
||||||
let instructions = vec![create_instruction];
|
let instructions = vec![create_instruction];
|
||||||
Transaction::new_signed_instructions(&[from_keypair], instructions, recent_blockhash)
|
Transaction::new_signed_instructions(&[from_keypair], instructions, recent_blockhash)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,16 @@ pub fn create_account(lamports: u64, rent_calculator: &RentCalculator) -> Accoun
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::account::KeyedAccount;
|
||||||
|
use crate::instruction::InstructionError;
|
||||||
|
|
||||||
|
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Rent, InstructionError> {
|
||||||
|
if !check_id(account.unsigned_key()) {
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
|
Rent::from_account(account.account).ok_or(InstructionError::InvalidArgument)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue