2018-12-14 20:39:10 -08:00
|
|
|
use log::*;
|
2018-12-03 13:32:31 -08:00
|
|
|
use solana_sdk::account::KeyedAccount;
|
2019-03-23 20:12:27 -07:00
|
|
|
use solana_sdk::instruction::InstructionError;
|
2019-11-06 00:07:57 -08:00
|
|
|
use solana_sdk::instruction_processor_utils::{limited_deserialize, next_keyed_account};
|
2018-12-03 13:32:31 -08:00
|
|
|
use solana_sdk::pubkey::Pubkey;
|
2019-03-13 13:37:24 -07:00
|
|
|
use solana_sdk::system_instruction::{SystemError, SystemInstruction};
|
2018-12-03 13:32:31 -08:00
|
|
|
use solana_sdk::system_program;
|
2019-07-12 16:38:15 -07:00
|
|
|
use solana_sdk::sysvar;
|
2018-12-03 13:32:31 -08:00
|
|
|
|
2019-03-05 11:11:05 -08:00
|
|
|
fn create_system_account(
|
2019-10-10 16:43:49 -07:00
|
|
|
from: &mut KeyedAccount,
|
|
|
|
to: &mut KeyedAccount,
|
2019-03-05 16:28:14 -08:00
|
|
|
lamports: u64,
|
2019-03-05 11:11:05 -08:00
|
|
|
space: u64,
|
2019-03-09 19:28:43 -08:00
|
|
|
program_id: &Pubkey,
|
2019-10-10 16:43:49 -07:00
|
|
|
) -> Result<(), InstructionError> {
|
2019-10-19 18:23:27 -07:00
|
|
|
// if lamports == 0, the from account isn't touched
|
|
|
|
if lamports != 0 && from.signer_key().is_none() {
|
|
|
|
debug!("CreateAccount: from must sign");
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(InstructionError::MissingRequiredSignature);
|
|
|
|
}
|
|
|
|
|
2019-11-08 02:27:35 -08:00
|
|
|
if to.signer_key().is_none() {
|
|
|
|
debug!("CreateAccount: to must sign");
|
|
|
|
return Err(InstructionError::MissingRequiredSignature);
|
|
|
|
}
|
|
|
|
|
2019-10-19 18:23:27 -07:00
|
|
|
// if it looks like the to account is already in use, bail
|
|
|
|
if to.account.lamports != 0
|
|
|
|
|| !to.account.data.is_empty()
|
|
|
|
|| !system_program::check_id(&to.account.owner)
|
|
|
|
{
|
2019-03-28 11:45:34 -07:00
|
|
|
debug!(
|
2019-03-05 11:11:05 -08:00
|
|
|
"CreateAccount: invalid argument; account {} already in use",
|
2019-10-10 16:43:49 -07:00
|
|
|
to.unsigned_key()
|
2019-03-05 11:11:05 -08:00
|
|
|
);
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(SystemError::AccountAlreadyInUse.into());
|
2019-03-05 11:11:05 -08:00
|
|
|
}
|
2019-06-06 19:27:49 -07:00
|
|
|
|
2019-10-10 16:43:49 -07:00
|
|
|
if sysvar::is_sysvar_id(&to.unsigned_key()) {
|
2019-10-19 18:23:27 -07:00
|
|
|
debug!("CreateAccount: account id {} invalid", program_id);
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(SystemError::InvalidAccountId.into());
|
2019-06-06 19:27:49 -07:00
|
|
|
}
|
|
|
|
|
2019-10-10 16:43:49 -07:00
|
|
|
if lamports > from.account.lamports {
|
2019-03-28 11:45:34 -07:00
|
|
|
debug!(
|
2019-03-05 16:28:14 -08:00
|
|
|
"CreateAccount: insufficient lamports ({}, need {})",
|
2019-10-10 16:43:49 -07:00
|
|
|
from.account.lamports, lamports
|
2019-03-05 11:11:05 -08:00
|
|
|
);
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(SystemError::ResultWithNegativeLamports.into());
|
2019-03-05 11:11:05 -08:00
|
|
|
}
|
2019-11-18 19:39:29 -08:00
|
|
|
|
|
|
|
assign_account_to_program(to, program_id)?;
|
2019-10-10 16:43:49 -07:00
|
|
|
from.account.lamports -= lamports;
|
|
|
|
to.account.lamports += lamports;
|
|
|
|
to.account.data = vec![0; space as usize];
|
|
|
|
to.account.executable = false;
|
2019-03-05 11:11:05 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn assign_account_to_program(
|
2019-10-10 16:43:49 -07:00
|
|
|
account: &mut KeyedAccount,
|
2019-03-09 19:28:43 -08:00
|
|
|
program_id: &Pubkey,
|
2019-10-10 16:43:49 -07:00
|
|
|
) -> Result<(), InstructionError> {
|
|
|
|
if account.signer_key().is_none() {
|
2019-10-19 18:23:27 -07:00
|
|
|
debug!("Assign: account must sign");
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(InstructionError::MissingRequiredSignature);
|
|
|
|
}
|
|
|
|
|
2019-11-18 19:39:29 -08:00
|
|
|
// guard against sysvars being assigned
|
|
|
|
if sysvar::check_id(&program_id) {
|
|
|
|
debug!("Assign: program id {} invalid", program_id);
|
|
|
|
return Err(SystemError::InvalidProgramId.into());
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:43:49 -07:00
|
|
|
account.account.owner = *program_id;
|
2019-03-05 11:11:05 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
2019-10-19 18:23:27 -07:00
|
|
|
|
2019-04-23 12:30:42 -07:00
|
|
|
fn transfer_lamports(
|
2019-10-10 16:43:49 -07:00
|
|
|
from: &mut KeyedAccount,
|
|
|
|
to: &mut KeyedAccount,
|
2019-04-23 12:30:42 -07:00
|
|
|
lamports: u64,
|
2019-10-10 16:43:49 -07:00
|
|
|
) -> Result<(), InstructionError> {
|
2019-10-19 18:23:27 -07:00
|
|
|
if lamports == 0 {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:43:49 -07:00
|
|
|
if from.signer_key().is_none() {
|
2019-10-19 18:23:27 -07:00
|
|
|
debug!("Transfer: from must sign");
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(InstructionError::MissingRequiredSignature);
|
|
|
|
}
|
|
|
|
|
|
|
|
if lamports > from.account.lamports {
|
2019-03-28 11:45:34 -07:00
|
|
|
debug!(
|
2019-04-02 20:52:07 -07:00
|
|
|
"Transfer: insufficient lamports ({}, need {})",
|
2019-10-10 16:43:49 -07:00
|
|
|
from.account.lamports, lamports
|
2019-03-05 11:11:05 -08:00
|
|
|
);
|
2019-10-10 16:43:49 -07:00
|
|
|
return Err(SystemError::ResultWithNegativeLamports.into());
|
2019-03-05 11:11:05 -08:00
|
|
|
}
|
2019-10-10 16:43:49 -07:00
|
|
|
from.account.lamports -= lamports;
|
|
|
|
to.account.lamports += lamports;
|
2019-03-05 11:11:05 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-04-02 07:36:10 -07:00
|
|
|
pub fn process_instruction(
|
2018-12-03 13:32:31 -08:00
|
|
|
_program_id: &Pubkey,
|
|
|
|
keyed_accounts: &mut [KeyedAccount],
|
|
|
|
data: &[u8],
|
2019-03-18 09:05:03 -07:00
|
|
|
) -> Result<(), InstructionError> {
|
2019-11-06 00:07:57 -08:00
|
|
|
let instruction = limited_deserialize(data)?;
|
2019-10-10 16:43:49 -07:00
|
|
|
|
|
|
|
trace!("process_instruction: {:?}", instruction);
|
|
|
|
trace!("keyed_accounts: {:?}", keyed_accounts);
|
|
|
|
|
|
|
|
let keyed_accounts_iter = &mut keyed_accounts.iter_mut();
|
|
|
|
|
|
|
|
match instruction {
|
|
|
|
SystemInstruction::CreateAccount {
|
|
|
|
lamports,
|
|
|
|
space,
|
|
|
|
program_id,
|
|
|
|
} => {
|
|
|
|
let from = next_keyed_account(keyed_accounts_iter)?;
|
|
|
|
let to = next_keyed_account(keyed_accounts_iter)?;
|
|
|
|
create_system_account(from, to, lamports, space, &program_id)
|
2019-10-10 15:43:32 -07:00
|
|
|
}
|
2019-10-10 16:43:49 -07:00
|
|
|
SystemInstruction::Assign { program_id } => {
|
|
|
|
let account = next_keyed_account(keyed_accounts_iter)?;
|
|
|
|
assign_account_to_program(account, &program_id)
|
2018-12-03 13:32:31 -08:00
|
|
|
}
|
2019-10-10 16:43:49 -07:00
|
|
|
SystemInstruction::Transfer { lamports } => {
|
|
|
|
let from = next_keyed_account(keyed_accounts_iter)?;
|
|
|
|
let to = next_keyed_account(keyed_accounts_iter)?;
|
|
|
|
transfer_lamports(from, to, lamports)
|
2018-12-03 13:32:31 -08:00
|
|
|
}
|
2019-03-05 11:11:05 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2019-03-16 16:37:18 -07:00
|
|
|
use crate::bank::Bank;
|
|
|
|
use crate::bank_client::BankClient;
|
2019-04-11 11:41:12 -07:00
|
|
|
use bincode::serialize;
|
2019-03-05 11:11:05 -08:00
|
|
|
use solana_sdk::account::Account;
|
2019-04-11 00:25:14 -07:00
|
|
|
use solana_sdk::client::SyncClient;
|
2019-11-08 20:56:57 -08:00
|
|
|
use solana_sdk::genesis_config::create_genesis_config;
|
2019-03-23 20:12:27 -07:00
|
|
|
use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError};
|
2019-03-05 11:11:05 -08:00
|
|
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
2019-03-16 16:37:18 -07:00
|
|
|
use solana_sdk::system_program;
|
2019-03-23 20:12:27 -07:00
|
|
|
use solana_sdk::transaction::TransactionError;
|
2019-03-05 11:11:05 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_system_account() {
|
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
2019-03-30 20:37:33 -07:00
|
|
|
let from = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-03-30 20:37:33 -07:00
|
|
|
let to = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut to_account = Account::new(0, 0, &Pubkey::default());
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-10-19 18:23:27 -07:00
|
|
|
assert_eq!(
|
|
|
|
create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, true, &mut to_account),
|
2019-10-19 18:23:27 -07:00
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
),
|
|
|
|
Ok(())
|
|
|
|
);
|
|
|
|
|
2019-03-05 16:28:14 -08:00
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
let to_lamports = to_account.lamports;
|
2019-03-05 11:11:05 -08:00
|
|
|
let to_owner = to_account.owner;
|
2019-03-14 09:48:27 -07:00
|
|
|
let to_data = to_account.data.clone();
|
2019-03-05 16:28:14 -08:00
|
|
|
assert_eq!(from_lamports, 50);
|
|
|
|
assert_eq!(to_lamports, 50);
|
2019-03-05 11:11:05 -08:00
|
|
|
assert_eq!(to_owner, new_program_owner);
|
2019-03-14 09:48:27 -07:00
|
|
|
assert_eq!(to_data, [0, 0]);
|
2019-03-05 13:43:05 -08:00
|
|
|
}
|
2019-03-05 11:11:05 -08:00
|
|
|
|
2019-10-19 18:23:27 -07:00
|
|
|
#[test]
|
|
|
|
fn test_create_with_zero_lamports() {
|
|
|
|
// Attempt to create account with zero lamports
|
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
|
|
|
let from = Pubkey::new_rand();
|
|
|
|
let mut from_account = Account::new(100, 0, &Pubkey::new_rand()); // not from system account
|
|
|
|
|
|
|
|
let to = Pubkey::new_rand();
|
|
|
|
let mut to_account = Account::new(0, 0, &Pubkey::default());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, false, &mut from_account), // no signer
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, true, &mut to_account),
|
2019-10-19 18:23:27 -07:00
|
|
|
0,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
),
|
|
|
|
Ok(())
|
|
|
|
);
|
|
|
|
|
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
let to_lamports = to_account.lamports;
|
|
|
|
let to_owner = to_account.owner;
|
|
|
|
let to_data = to_account.data.clone();
|
|
|
|
assert_eq!(from_lamports, 100);
|
|
|
|
assert_eq!(to_lamports, 0);
|
|
|
|
assert_eq!(to_owner, new_program_owner);
|
|
|
|
assert_eq!(to_data, [0, 0]);
|
|
|
|
}
|
|
|
|
|
2019-03-05 13:43:05 -08:00
|
|
|
#[test]
|
2019-03-05 16:28:14 -08:00
|
|
|
fn test_create_negative_lamports() {
|
|
|
|
// Attempt to create account with more lamports than remaining in from_account
|
2019-03-05 13:43:05 -08:00
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
2019-03-30 20:37:33 -07:00
|
|
|
let from = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-03-30 20:37:33 -07:00
|
|
|
let to = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut to_account = Account::new(0, 0, &Pubkey::default());
|
2019-03-05 11:11:05 -08:00
|
|
|
let unchanged_account = to_account.clone();
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-10-10 16:43:49 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, true, &mut to_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
150,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::ResultWithNegativeLamports.into()));
|
2019-03-05 16:28:14 -08:00
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
assert_eq!(from_lamports, 100);
|
2019-03-05 11:11:05 -08:00
|
|
|
assert_eq!(to_account, unchanged_account);
|
2019-03-05 13:43:05 -08:00
|
|
|
}
|
2019-03-05 11:11:05 -08:00
|
|
|
|
2019-03-05 13:43:05 -08:00
|
|
|
#[test]
|
2019-10-19 18:23:27 -07:00
|
|
|
fn test_create_already_in_use() {
|
2019-03-05 11:11:05 -08:00
|
|
|
// Attempt to create system account in account already owned by another program
|
2019-03-05 13:43:05 -08:00
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
2019-03-30 20:37:33 -07:00
|
|
|
let from = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-03-05 11:11:05 -08:00
|
|
|
let original_program_owner = Pubkey::new(&[5; 32]);
|
2019-03-30 20:37:33 -07:00
|
|
|
let owned_key = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut owned_account = Account::new(0, 0, &original_program_owner);
|
2019-03-05 11:11:05 -08:00
|
|
|
let unchanged_account = owned_account.clone();
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-10-19 18:23:27 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&owned_key, true, &mut owned_account),
|
2019-10-19 18:23:27 -07:00
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::AccountAlreadyInUse.into()));
|
|
|
|
|
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
assert_eq!(from_lamports, 100);
|
|
|
|
assert_eq!(owned_account, unchanged_account);
|
|
|
|
|
|
|
|
let mut owned_account = Account::new(10, 0, &Pubkey::default());
|
|
|
|
let unchanged_account = owned_account.clone();
|
2019-10-10 16:43:49 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&owned_key, true, &mut owned_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::AccountAlreadyInUse.into()));
|
2019-03-05 16:28:14 -08:00
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
assert_eq!(from_lamports, 100);
|
2019-03-05 11:11:05 -08:00
|
|
|
assert_eq!(owned_account, unchanged_account);
|
2019-03-05 13:43:05 -08:00
|
|
|
}
|
2019-03-05 11:11:05 -08:00
|
|
|
|
2019-10-19 18:23:27 -07:00
|
|
|
#[test]
|
|
|
|
fn test_create_unsigned() {
|
|
|
|
// Attempt to create an account without signing the transfer
|
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
|
|
|
let from = Pubkey::new_rand();
|
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
|
|
|
|
|
|
|
let owned_key = Pubkey::new_rand();
|
|
|
|
let mut owned_account = Account::new(0, 0, &Pubkey::default());
|
|
|
|
let unchanged_account = owned_account.clone();
|
|
|
|
|
2019-11-08 02:27:35 -08:00
|
|
|
// Haven't signed from account
|
2019-10-19 18:23:27 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, false, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&owned_key, true, &mut owned_account),
|
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(InstructionError::MissingRequiredSignature));
|
|
|
|
assert_eq!(from_account.lamports, 100);
|
|
|
|
assert_eq!(owned_account, unchanged_account);
|
|
|
|
|
|
|
|
// Haven't signed to account
|
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-10-19 18:23:27 -07:00
|
|
|
&mut KeyedAccount::new(&owned_key, false, &mut owned_account),
|
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(InstructionError::MissingRequiredSignature));
|
|
|
|
assert_eq!(from_account.lamports, 100);
|
|
|
|
assert_eq!(owned_account, unchanged_account);
|
|
|
|
|
|
|
|
// support creation/assignment with zero lamports (ephemeral account)
|
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, false, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&owned_key, true, &mut owned_account),
|
2019-10-19 18:23:27 -07:00
|
|
|
0,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Ok(()));
|
|
|
|
assert_eq!(from_account.lamports, 100);
|
|
|
|
assert_eq!(owned_account.owner, new_program_owner);
|
|
|
|
}
|
|
|
|
|
2019-06-06 19:27:49 -07:00
|
|
|
#[test]
|
2019-07-12 16:38:15 -07:00
|
|
|
fn test_create_sysvar_invalid_id() {
|
2019-06-06 19:27:49 -07:00
|
|
|
// Attempt to create system account in account already owned by another program
|
|
|
|
let from = Pubkey::new_rand();
|
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
|
|
|
|
|
|
|
let to = Pubkey::new_rand();
|
|
|
|
let mut to_account = Account::default();
|
|
|
|
|
2019-07-12 16:38:15 -07:00
|
|
|
// fail to create a sysvar::id() owned account
|
2019-10-10 16:43:49 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, true, &mut to_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&sysvar::id(),
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::InvalidProgramId.into()));
|
2019-06-06 19:27:49 -07:00
|
|
|
|
2019-07-12 16:38:15 -07:00
|
|
|
let to = sysvar::fees::id();
|
2019-06-06 19:27:49 -07:00
|
|
|
let mut to_account = Account::default();
|
|
|
|
|
2019-07-12 16:38:15 -07:00
|
|
|
// fail to create an account with a sysvar id
|
2019-10-10 16:43:49 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, true, &mut to_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&system_program::id(),
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::InvalidAccountId.into()));
|
2019-06-06 19:27:49 -07:00
|
|
|
|
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
assert_eq!(from_lamports, 100);
|
|
|
|
}
|
|
|
|
|
2019-03-05 13:43:05 -08:00
|
|
|
#[test]
|
2019-03-14 09:48:27 -07:00
|
|
|
fn test_create_data_populated() {
|
|
|
|
// Attempt to create system account in account with populated data
|
2019-03-05 13:43:05 -08:00
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
2019-03-30 20:37:33 -07:00
|
|
|
let from = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-03-30 20:37:33 -07:00
|
|
|
let populated_key = Pubkey::new_rand();
|
2019-03-05 11:11:05 -08:00
|
|
|
let mut populated_account = Account {
|
2019-03-14 09:48:27 -07:00
|
|
|
data: vec![0, 1, 2, 3],
|
2019-08-23 14:04:53 -07:00
|
|
|
..Account::default()
|
2019-03-05 11:11:05 -08:00
|
|
|
};
|
|
|
|
let unchanged_account = populated_account.clone();
|
2019-03-05 13:43:05 -08:00
|
|
|
|
2019-10-10 16:43:49 -07:00
|
|
|
let result = create_system_account(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-08 02:27:35 -08:00
|
|
|
&mut KeyedAccount::new(&populated_key, true, &mut populated_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
50,
|
|
|
|
2,
|
|
|
|
&new_program_owner,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::AccountAlreadyInUse.into()));
|
2019-03-05 16:28:14 -08:00
|
|
|
assert_eq!(from_account.lamports, 100);
|
2019-03-05 11:11:05 -08:00
|
|
|
assert_eq!(populated_account, unchanged_account);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_assign_account_to_program() {
|
|
|
|
let new_program_owner = Pubkey::new(&[9; 32]);
|
|
|
|
|
2019-03-30 20:37:33 -07:00
|
|
|
let from = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
2019-10-19 18:23:27 -07:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
assign_account_to_program(
|
|
|
|
&mut KeyedAccount::new(&from, false, &mut from_account),
|
|
|
|
&new_program_owner,
|
|
|
|
),
|
|
|
|
Err(InstructionError::MissingRequiredSignature)
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
assign_account_to_program(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
|
|
|
&new_program_owner,
|
|
|
|
),
|
|
|
|
Ok(())
|
|
|
|
);
|
2019-03-05 11:11:05 -08:00
|
|
|
}
|
|
|
|
|
2019-11-18 19:39:29 -08:00
|
|
|
#[test]
|
|
|
|
fn test_assign_account_to_sysvar() {
|
|
|
|
let new_program_owner = sysvar::id();
|
|
|
|
|
|
|
|
let from = Pubkey::new_rand();
|
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
assign_account_to_program(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
|
|
|
&new_program_owner,
|
|
|
|
),
|
|
|
|
Err(SystemError::InvalidProgramId.into())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-10-10 15:43:32 -07:00
|
|
|
#[test]
|
|
|
|
fn test_process_bogus_instruction() {
|
|
|
|
// Attempt to assign with no accounts
|
|
|
|
let instruction = SystemInstruction::Assign {
|
|
|
|
program_id: Pubkey::new_rand(),
|
|
|
|
};
|
|
|
|
let data = serialize(&instruction).unwrap();
|
|
|
|
let result = process_instruction(&system_program::id(), &mut [], &data);
|
|
|
|
assert_eq!(result, Err(InstructionError::NotEnoughAccountKeys));
|
|
|
|
|
|
|
|
let from = Pubkey::new_rand();
|
|
|
|
let mut from_account = Account::new(100, 0, &system_program::id());
|
|
|
|
// Attempt to transfer with no destination
|
|
|
|
let instruction = SystemInstruction::Transfer { lamports: 0 };
|
|
|
|
let data = serialize(&instruction).unwrap();
|
|
|
|
let result = process_instruction(
|
|
|
|
&system_program::id(),
|
|
|
|
&mut [KeyedAccount::new(&from, true, &mut from_account)],
|
|
|
|
&data,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(InstructionError::NotEnoughAccountKeys));
|
|
|
|
}
|
|
|
|
|
2019-03-05 11:11:05 -08:00
|
|
|
#[test]
|
2019-04-23 12:30:42 -07:00
|
|
|
fn test_transfer_lamports() {
|
2019-03-30 20:37:33 -07:00
|
|
|
let from = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut from_account = Account::new(100, 0, &Pubkey::new(&[2; 32])); // account owner should not matter
|
2019-03-30 20:37:33 -07:00
|
|
|
let to = Pubkey::new_rand();
|
2019-03-09 19:28:43 -08:00
|
|
|
let mut to_account = Account::new(1, 0, &Pubkey::new(&[3; 32])); // account owner should not matter
|
2019-10-10 16:43:49 -07:00
|
|
|
transfer_lamports(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-05 08:38:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, false, &mut to_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
50,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2019-03-05 16:28:14 -08:00
|
|
|
let from_lamports = from_account.lamports;
|
|
|
|
let to_lamports = to_account.lamports;
|
|
|
|
assert_eq!(from_lamports, 50);
|
|
|
|
assert_eq!(to_lamports, 51);
|
2019-03-05 11:11:05 -08:00
|
|
|
|
2019-03-05 16:28:14 -08:00
|
|
|
// Attempt to move more lamports than remaining in from_account
|
2019-10-10 16:43:49 -07:00
|
|
|
let result = transfer_lamports(
|
|
|
|
&mut KeyedAccount::new(&from, true, &mut from_account),
|
2019-11-05 08:38:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, false, &mut to_account),
|
2019-10-10 16:43:49 -07:00
|
|
|
100,
|
|
|
|
);
|
|
|
|
assert_eq!(result, Err(SystemError::ResultWithNegativeLamports.into()));
|
2019-03-05 16:28:14 -08:00
|
|
|
assert_eq!(from_account.lamports, 50);
|
|
|
|
assert_eq!(to_account.lamports, 51);
|
2019-10-19 18:23:27 -07:00
|
|
|
|
|
|
|
// test unsigned transfer of zero
|
|
|
|
assert!(transfer_lamports(
|
|
|
|
&mut KeyedAccount::new(&from, false, &mut from_account),
|
2019-11-05 08:38:35 -08:00
|
|
|
&mut KeyedAccount::new(&to, false, &mut to_account),
|
2019-10-19 18:23:27 -07:00
|
|
|
0,
|
|
|
|
)
|
|
|
|
.is_ok(),);
|
|
|
|
assert_eq!(from_account.lamports, 50);
|
|
|
|
assert_eq!(to_account.lamports, 51);
|
2018-12-03 13:32:31 -08:00
|
|
|
}
|
2019-03-16 16:37:18 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_system_unsigned_transaction() {
|
2019-11-08 20:56:57 -08:00
|
|
|
let (genesis_config, alice_keypair) = create_genesis_config(100);
|
2019-03-27 06:34:01 -07:00
|
|
|
let alice_pubkey = alice_keypair.pubkey();
|
|
|
|
let mallory_keypair = Keypair::new();
|
|
|
|
let mallory_pubkey = mallory_keypair.pubkey();
|
2019-03-16 16:37:18 -07:00
|
|
|
|
|
|
|
// Fund to account to bypass AccountNotFound error
|
2019-11-08 20:56:57 -08:00
|
|
|
let bank = Bank::new(&genesis_config);
|
2019-04-11 11:29:59 -07:00
|
|
|
let bank_client = BankClient::new(bank);
|
2019-03-27 06:34:01 -07:00
|
|
|
bank_client
|
|
|
|
.transfer(50, &alice_keypair, &mallory_pubkey)
|
|
|
|
.unwrap();
|
2019-03-16 16:37:18 -07:00
|
|
|
|
|
|
|
// Erroneously sign transaction with recipient account key
|
|
|
|
// No signature case is tested by bank `test_zero_signatures()`
|
2019-03-19 12:03:20 -07:00
|
|
|
let account_metas = vec![
|
2019-03-19 14:25:48 -07:00
|
|
|
AccountMeta::new(alice_pubkey, false),
|
|
|
|
AccountMeta::new(mallory_pubkey, true),
|
2019-03-19 12:03:20 -07:00
|
|
|
];
|
2019-03-23 04:15:15 -07:00
|
|
|
let malicious_instruction = Instruction::new(
|
2019-03-16 16:37:18 -07:00
|
|
|
system_program::id(),
|
2019-04-02 20:52:07 -07:00
|
|
|
&SystemInstruction::Transfer { lamports: 10 },
|
2019-03-19 12:03:20 -07:00
|
|
|
account_metas,
|
2019-03-23 04:15:15 -07:00
|
|
|
);
|
2019-03-16 16:37:18 -07:00
|
|
|
assert_eq!(
|
2019-04-03 20:40:29 -07:00
|
|
|
bank_client
|
|
|
|
.send_instruction(&mallory_keypair, malicious_instruction)
|
|
|
|
.unwrap_err()
|
|
|
|
.unwrap(),
|
|
|
|
TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature)
|
2019-03-16 16:37:18 -07:00
|
|
|
);
|
2019-04-03 20:40:29 -07:00
|
|
|
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 50);
|
|
|
|
assert_eq!(bank_client.get_balance(&mallory_pubkey).unwrap(), 50);
|
2019-03-16 16:37:18 -07:00
|
|
|
}
|
2018-12-03 13:32:31 -08:00
|
|
|
}
|