Remove keypairs from BankClient

Bring its interface closer to the other clients.
This commit is contained in:
Greg Fitzgerald 2019-03-27 07:34:01 -06:00
parent cecdb7061e
commit 3fc09fb23f
11 changed files with 303 additions and 237 deletions

View File

@ -28,6 +28,7 @@ mod bpf {
mod bpf_c {
use super::*;
use solana_sdk::bpf_loader;
use solana_sdk::signature::KeypairUtil;
use std::io::Read;
#[test]
@ -38,14 +39,16 @@ mod bpf {
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let (genesis_block, mint_keypair) = GenesisBlock::new(50);
let (genesis_block, alice_keypair) = GenesisBlock::new(50);
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let bank_client = BankClient::new(&bank);
// Call user program
let program_id = load_program(&bank, &alice_client, &bpf_loader::id(), elf);
let instruction = create_invoke_instruction(alice_client.pubkey(), program_id, &1u8);
alice_client.process_instruction(instruction).unwrap();
let program_id = load_program(&bank_client, &alice_keypair, &bpf_loader::id(), elf);
let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap();
}
#[test]
@ -67,22 +70,24 @@ mod bpf {
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let (genesis_block, mint_keypair) = GenesisBlock::new(50);
let (genesis_block, alice_keypair) = GenesisBlock::new(50);
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let bank_client = BankClient::new(&bank);
let loader_id = load_program(
&bank,
&alice_client,
&bank_client,
&alice_keypair,
&native_loader::id(),
"solana_bpf_loader".as_bytes().to_vec(),
);
// Call user program
let program_id = load_program(&bank, &alice_client, &loader_id, elf);
let program_id = load_program(&bank_client, &alice_keypair, &loader_id, elf);
let instruction =
create_invoke_instruction(alice_client.pubkey(), program_id, &1u8);
alice_client.process_instruction(instruction).unwrap();
create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap();
}
}
}
@ -94,6 +99,7 @@ mod bpf {
#[cfg(feature = "bpf_rust")]
mod bpf_rust {
use super::*;
use solana_sdk::signature::KeypairUtil;
use std::io::Read;
#[test]
@ -108,22 +114,24 @@ mod bpf {
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let (genesis_block, mint_keypair) = GenesisBlock::new(50);
let (genesis_block, alice_keypair) = GenesisBlock::new(50);
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let bank_client = BankClient::new(&bank);
let loader_id = load_program(
&bank,
&alice_client,
&bank_client,
&alice_keypair,
&native_loader::id(),
"solana_bpf_loader".as_bytes().to_vec(),
);
// Call user program
let program_id = load_program(&bank, &alice_client, &loader_id, elf);
let program_id = load_program(&bank_client, &alice_keypair, &loader_id, elf);
let instruction =
create_invoke_instruction(alice_client.pubkey(), program_id, &1u8);
alice_client.process_instruction(instruction).unwrap();
create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap();
}
}
}

View File

@ -162,21 +162,23 @@ mod tests {
#[test]
fn test_budget_payment() {
let (bank, mint_keypair) = create_bank(10_000);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let (bank, alice_keypair) = create_bank(10_000);
let bank_client = BankClient::new(&bank);
let alice_pubkey = alice_keypair.pubkey();
let bob_pubkey = Keypair::new().pubkey();
let instructions = BudgetInstruction::new_payment(&alice_pubkey, &bob_pubkey, 100);
let message = Message::new(instructions);
alice_client.process_message(message).unwrap();
bank_client
.process_message(&[&alice_keypair], message)
.unwrap();
assert_eq!(bank.get_balance(&bob_pubkey), 100);
}
#[test]
fn test_unsigned_witness_key() {
let (bank, mint_keypair) = create_bank(10_000);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let (bank, alice_keypair) = create_bank(10_000);
let bank_client = BankClient::new(&bank);
let alice_pubkey = alice_keypair.pubkey();
// Initialize BudgetState
let budget_pubkey = Keypair::new().pubkey();
@ -191,12 +193,16 @@ mod tests {
1,
);
let message = Message::new(instructions);
alice_client.process_message(message).unwrap();
bank_client
.process_message(&[&alice_keypair], message)
.unwrap();
// Attack! Part 1: Sign a witness transaction with a random key.
let mallory_client = BankClient::new(&bank, Keypair::new());
let mallory_pubkey = mallory_client.pubkey();
alice_client.transfer(1, &mallory_pubkey).unwrap();
let mallory_keypair = Keypair::new();
let mallory_pubkey = mallory_keypair.pubkey();
bank_client
.transfer(1, &alice_keypair, &mallory_pubkey)
.unwrap();
let instruction =
BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
let mut message = Message::new(vec![instruction]);
@ -207,7 +213,7 @@ mod tests {
// Ensure the transaction fails because of the unsigned key.
assert_eq!(
mallory_client.process_message(message),
bank_client.process_message(&[&mallory_keypair], message),
Err(TransactionError::InstructionError(
0,
InstructionError::MissingRequiredSignature
@ -217,9 +223,9 @@ mod tests {
#[test]
fn test_unsigned_timestamp() {
let (bank, mint_keypair) = create_bank(10_000);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let (bank, alice_keypair) = create_bank(10_000);
let bank_client = BankClient::new(&bank);
let alice_pubkey = alice_keypair.pubkey();
// Initialize BudgetState
let budget_pubkey = Keypair::new().pubkey();
@ -235,12 +241,16 @@ mod tests {
1,
);
let message = Message::new(instructions);
alice_client.process_message(message).unwrap();
bank_client
.process_message(&[&alice_keypair], message)
.unwrap();
// Attack! Part 1: Sign a timestamp transaction with a random key.
let mallory_client = BankClient::new(&bank, Keypair::new());
let mallory_pubkey = mallory_client.pubkey();
alice_client.transfer(1, &mallory_pubkey).unwrap();
let mallory_keypair = Keypair::new();
let mallory_pubkey = mallory_keypair.pubkey();
bank_client
.transfer(1, &alice_keypair, &mallory_pubkey)
.unwrap();
let instruction = BudgetInstruction::new_apply_timestamp(
&mallory_pubkey,
&budget_pubkey,
@ -255,7 +265,7 @@ mod tests {
// Ensure the transaction fails because of the unsigned key.
assert_eq!(
mallory_client.process_message(message),
bank_client.process_message(&[&mallory_keypair], message),
Err(TransactionError::InstructionError(
0,
InstructionError::MissingRequiredSignature
@ -265,9 +275,9 @@ mod tests {
#[test]
fn test_pay_on_date() {
let (bank, mint_keypair) = create_bank(2);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let (bank, alice_keypair) = create_bank(2);
let bank_client = BankClient::new(&bank);
let alice_pubkey = alice_keypair.pubkey();
let budget_pubkey = Keypair::new().pubkey();
let bob_pubkey = Keypair::new().pubkey();
let mallory_pubkey = Keypair::new().pubkey();
@ -282,7 +292,9 @@ mod tests {
1,
);
let message = Message::new(instructions);
alice_client.process_message(message).unwrap();
bank_client
.process_message(&[&alice_keypair], message)
.unwrap();
assert_eq!(bank.get_balance(&alice_pubkey), 1);
assert_eq!(bank.get_balance(&budget_pubkey), 1);
@ -298,7 +310,9 @@ mod tests {
dt,
);
assert_eq!(
alice_client.process_instruction(instruction).unwrap_err(),
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap_err(),
TransactionError::InstructionError(
0,
InstructionError::CustomError(serialize(&BudgetError::DestinationMissing).unwrap())
@ -316,7 +330,9 @@ mod tests {
// that pubkey's funds are now available.
let instruction =
BudgetInstruction::new_apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt);
alice_client.process_instruction(instruction).unwrap();
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap();
assert_eq!(bank.get_balance(&alice_pubkey), 1);
assert_eq!(bank.get_balance(&budget_pubkey), 0);
assert_eq!(bank.get_balance(&bob_pubkey), 1);
@ -325,9 +341,9 @@ mod tests {
#[test]
fn test_cancel_payment() {
let (bank, mint_keypair) = create_bank(3);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let (bank, alice_keypair) = create_bank(3);
let bank_client = BankClient::new(&bank);
let alice_pubkey = alice_keypair.pubkey();
let budget_pubkey = Keypair::new().pubkey();
let bob_pubkey = Keypair::new().pubkey();
let dt = Utc::now();
@ -342,7 +358,9 @@ mod tests {
1,
);
let message = Message::new(instructions);
alice_client.process_message(message).unwrap();
bank_client
.process_message(&[&alice_keypair], message)
.unwrap();
assert_eq!(bank.get_balance(&alice_pubkey), 2);
assert_eq!(bank.get_balance(&budget_pubkey), 1);
@ -351,14 +369,18 @@ mod tests {
assert!(budget_state.is_pending());
// Attack! try to put the lamports into the wrong account with cancel
let mallory_client = BankClient::new(&bank, Keypair::new());
let mallory_pubkey = mallory_client.pubkey();
alice_client.transfer(1, &mallory_pubkey).unwrap();
let mallory_keypair = Keypair::new();
let mallory_pubkey = mallory_keypair.pubkey();
bank_client
.transfer(1, &alice_keypair, &mallory_pubkey)
.unwrap();
assert_eq!(bank.get_balance(&alice_pubkey), 1);
let instruction =
BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
mallory_client.process_instruction(instruction).unwrap();
bank_client
.process_instruction(&mallory_keypair, instruction)
.unwrap();
// nothing should be changed because apply witness didn't finalize a payment
assert_eq!(bank.get_balance(&alice_pubkey), 1);
assert_eq!(bank.get_balance(&budget_pubkey), 1);
@ -367,7 +389,9 @@ mod tests {
// Now, cancel the transaction. mint gets her funds back
let instruction =
BudgetInstruction::new_apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey);
alice_client.process_instruction(instruction).unwrap();
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap();
assert_eq!(bank.get_balance(&alice_pubkey), 2);
assert_eq!(bank.get_account(&budget_pubkey), None);
assert_eq!(bank.get_account(&bob_pubkey), None);

View File

@ -64,39 +64,37 @@ mod tests {
(bank, mint_keypair)
}
fn create_config_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Pubkey, Pubkey) {
let config_client =
BankClient::new_with_keypairs(&bank, vec![Keypair::new(), Keypair::new()]);
fn create_config_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Keypair, Keypair) {
let from_keypair = Keypair::new();
let from_pubkey = from_keypair.pubkey();
let config_keypair = Keypair::new();
let config_pubkey = config_keypair.pubkey();
let from_pubkey = config_client.pubkeys()[0];
let config_pubkey = config_client.pubkeys()[1];
let bank_client = BankClient::new(&bank);
bank_client
.transfer(42, &mint_keypair, &from_pubkey)
.unwrap();
let mint_client = BankClient::new(&bank, mint_keypair);
mint_client
.process_instruction(SystemInstruction::new_move(
&mint_client.pubkey(),
&from_pubkey,
42,
))
.expect("new_move");
mint_client
.process_instruction(ConfigInstruction::new_account::<MyConfig>(
&mint_client.pubkey(),
&config_pubkey,
1,
))
bank_client
.process_instruction(
&mint_keypair,
ConfigInstruction::new_account::<MyConfig>(
&mint_keypair.pubkey(),
&config_pubkey,
1,
),
)
.expect("new_account");
(config_client, from_pubkey, config_pubkey)
(bank_client, from_keypair, config_keypair)
}
#[test]
fn test_process_create_ok() {
solana_logger::setup();
let (bank, from_keypair) = create_bank(10_000);
let (config_client, _, _) = create_config_client(&bank, from_keypair);
let config_account = bank.get_account(&config_client.pubkeys()[1]).unwrap();
let (_bank_client, _, config_keypair) = create_config_client(&bank, from_keypair);
let config_account = bank.get_account(&config_keypair.pubkey()).unwrap();
assert_eq!(id(), config_account.owner);
assert_eq!(
MyConfig::default(),
@ -108,11 +106,16 @@ mod tests {
fn test_process_store_ok() {
solana_logger::setup();
let (bank, mint_keypair) = create_bank(10_000);
let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair);
let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair);
let config_pubkey = config_keypair.pubkey();
let my_config = MyConfig::new(42);
let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config);
config_client.process_instruction(instruction).unwrap();
let instruction =
ConfigInstruction::new_store(&from_keypair.pubkey(), &config_pubkey, &my_config);
let message = Message::new(vec![instruction]);
bank_client
.process_message(&[&from_keypair, &config_keypair], message)
.unwrap();
let config_account = bank.get_account(&config_pubkey).unwrap();
assert_eq!(
@ -125,15 +128,22 @@ mod tests {
fn test_process_store_fail_instruction_data_too_large() {
solana_logger::setup();
let (bank, mint_keypair) = create_bank(10_000);
let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair);
let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair);
let my_config = MyConfig::new(42);
let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config);
// Replace instruction data with a vector that's too large
let mut message = Message::new(vec![instruction]);
message.instructions[0].data = vec![0; 123];
config_client.process_message(message).unwrap_err();
let mut instruction = ConfigInstruction::new_store(
&from_keypair.pubkey(),
&config_keypair.pubkey(),
&my_config,
);
instruction.data = vec![0; 123];
let message = Message::new(vec![instruction]);
bank_client
.process_message(&[&from_keypair, &config_keypair], message)
.unwrap_err();
}
#[test]
@ -143,19 +153,22 @@ mod tests {
let system_keypair = Keypair::new();
let system_pubkey = system_keypair.pubkey();
bank.transfer(42, &mint_keypair, &system_pubkey).unwrap();
let (_config_client, from_pubkey, config_pubkey) =
create_config_client(&bank, mint_keypair);
let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair);
let move_instruction = SystemInstruction::new_move(&system_pubkey, &Pubkey::default(), 42);
let my_config = MyConfig::new(42);
let mut store_instruction =
ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config);
let mut store_instruction = ConfigInstruction::new_store(
&from_keypair.pubkey(),
&config_keypair.pubkey(),
&my_config,
);
store_instruction.accounts[0].is_signer = false;
store_instruction.accounts[1].is_signer = false;
// Don't sign the transaction with `config_client`
let message = Message::new(vec![move_instruction, store_instruction]);
let system_client = BankClient::new(&bank, system_keypair);
system_client.process_message(message).unwrap_err();
bank_client
.process_message(&[&system_keypair], message)
.unwrap_err();
}
}

View File

@ -509,68 +509,61 @@ mod test {
(bank, mint_keypair)
}
fn create_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Pubkey) {
fn create_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Keypair) {
let owner = Keypair::new();
let pubkey = owner.pubkey();
let mint_client = BankClient::new(&bank, mint_keypair);
mint_client
.process_instruction(SystemInstruction::new_move(
&mint_client.pubkey(),
&owner.pubkey(),
42,
))
.expect("new_move");
let bank_client = BankClient::new(&bank);
bank_client
.transfer(42, &mint_keypair, &owner.pubkey())
.unwrap();
let client = BankClient::new(&bank, owner);
(client, pubkey)
(bank_client, owner)
}
fn create_account(client: &BankClient, owner: &Pubkey) -> Pubkey {
fn create_account(client: &BankClient, owner: &Keypair) -> Pubkey {
let new = Keypair::new().pubkey();
let instruction = SystemInstruction::new_program_account(
&owner,
&owner.pubkey(),
&new,
1,
mem::size_of::<ExchangeState>() as u64,
&id(),
);
client
.process_instruction(instruction)
.process_instruction(&owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
new
}
fn create_token_account(client: &BankClient, owner: &Pubkey) -> Pubkey {
fn create_token_account(client: &BankClient, owner: &Keypair) -> Pubkey {
let new = Keypair::new().pubkey();
let instruction = SystemInstruction::new_program_account(
&owner,
&owner.pubkey(),
&new,
1,
mem::size_of::<ExchangeState>() as u64,
&id(),
);
client
.process_instruction(instruction)
.process_instruction(owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
let instruction = ExchangeInstruction::new_account_request(&owner, &new);
let instruction = ExchangeInstruction::new_account_request(&owner.pubkey(), &new);
client
.process_instruction(instruction)
.process_instruction(owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
new
}
fn transfer(client: &BankClient, owner: &Pubkey, to: &Pubkey, token: Token, tokens: u64) {
fn transfer(client: &BankClient, owner: &Keypair, to: &Pubkey, token: Token, tokens: u64) {
let instruction =
ExchangeInstruction::new_transfer_request(owner, to, &id(), token, tokens);
ExchangeInstruction::new_transfer_request(&owner.pubkey(), to, &id(), token, tokens);
client
.process_instruction(instruction)
.process_instruction(owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
}
fn trade(
client: &BankClient,
owner: &Pubkey,
owner: &Keypair,
direction: Direction,
pair: TokenPair,
from_token: Token,
@ -584,7 +577,7 @@ mod test {
transfer(&client, &owner, &src, from_token, src_tokens);
let instruction = ExchangeInstruction::new_trade_request(
owner,
&owner.pubkey(),
&trade,
direction,
pair,
@ -594,7 +587,7 @@ mod test {
&dst,
);
client
.process_instruction(instruction)
.process_instruction(owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
(trade, src, dst)
}
@ -620,7 +613,7 @@ mod test {
// Check results
assert_eq!(
TokenAccountInfo::default().owner(&owner),
TokenAccountInfo::default().owner(&owner.pubkey()),
ExchangeProcessor::deserialize_account(&new_account.data[..]).unwrap()
);
}
@ -632,9 +625,9 @@ mod test {
let (client, owner) = create_client(&bank, mint_keypair);
let new = create_token_account(&client, &owner);
let instruction = ExchangeInstruction::new_account_request(&owner, &new);
let instruction = ExchangeInstruction::new_account_request(&owner.pubkey(), &new);
client
.process_instruction(instruction)
.process_instruction(&owner, instruction)
.expect_err(&format!("{}:{}", line!(), file!()));
}
@ -647,9 +640,9 @@ mod test {
let new = create_token_account(&client, &owner);
let instruction =
ExchangeInstruction::new_transfer_request(&owner, &new, &id(), Token::A, 42);
ExchangeInstruction::new_transfer_request(&owner.pubkey(), &new, &id(), Token::A, 42);
client
.process_instruction(instruction)
.process_instruction(&owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
let new_account = bank.get_account(&new).unwrap();
@ -658,7 +651,7 @@ mod test {
assert_eq!(
TokenAccountInfo::default()
.owner(&owner)
.owner(&owner.pubkey())
.tokens(42, 0, 0, 0),
ExchangeProcessor::deserialize_account(&new_account.data[..]).unwrap()
);
@ -689,7 +682,7 @@ mod test {
assert_eq!(
TradeOrderInfo {
owner: owner,
owner: owner.pubkey(),
direction: Direction::To,
pair: TokenPair::AB,
tokens: 2,
@ -701,12 +694,14 @@ mod test {
);
assert_eq!(
TokenAccountInfo::default()
.owner(&owner)
.owner(&owner.pubkey())
.tokens(40, 0, 0, 0),
ExchangeProcessor::deserialize_account(&src_account.data[..]).unwrap()
);
assert_eq!(
TokenAccountInfo::default().owner(&owner).tokens(0, 0, 0, 0),
TokenAccountInfo::default()
.owner(&owner.pubkey())
.tokens(0, 0, 0, 0),
ExchangeProcessor::deserialize_account(&dst_account.data[..]).unwrap()
);
}
@ -741,7 +736,7 @@ mod test {
);
let instruction = ExchangeInstruction::new_swap_request(
&owner,
&owner.pubkey(),
&swap,
&to_trade,
&from_trade,
@ -750,7 +745,7 @@ mod test {
&profit,
);
client
.process_instruction(instruction)
.process_instruction(&owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
let to_trade_account = bank.get_account(&to_trade).unwrap();
@ -766,7 +761,7 @@ mod test {
assert_eq!(
TradeOrderInfo {
owner: owner,
owner: owner.pubkey(),
direction: Direction::To,
pair: TokenPair::AB,
tokens: 1,
@ -777,16 +772,20 @@ mod test {
ExchangeProcessor::deserialize_trade(&to_trade_account.data[..]).unwrap()
);
assert_eq!(
TokenAccountInfo::default().owner(&owner).tokens(0, 0, 0, 0),
TokenAccountInfo::default()
.owner(&owner.pubkey())
.tokens(0, 0, 0, 0),
ExchangeProcessor::deserialize_account(&to_src_account.data[..]).unwrap()
);
assert_eq!(
TokenAccountInfo::default().owner(&owner).tokens(0, 2, 0, 0),
TokenAccountInfo::default()
.owner(&owner.pubkey())
.tokens(0, 2, 0, 0),
ExchangeProcessor::deserialize_account(&to_dst_account.data[..]).unwrap()
);
assert_eq!(
TradeOrderInfo {
owner: owner,
owner: owner.pubkey(),
direction: Direction::From,
pair: TokenPair::AB,
tokens: 0,
@ -797,15 +796,21 @@ mod test {
ExchangeProcessor::deserialize_trade(&from_trade_account.data[..]).unwrap()
);
assert_eq!(
TokenAccountInfo::default().owner(&owner).tokens(0, 0, 0, 0),
TokenAccountInfo::default()
.owner(&owner.pubkey())
.tokens(0, 0, 0, 0),
ExchangeProcessor::deserialize_account(&from_src_account.data[..]).unwrap()
);
assert_eq!(
TokenAccountInfo::default().owner(&owner).tokens(1, 0, 0, 0),
TokenAccountInfo::default()
.owner(&owner.pubkey())
.tokens(1, 0, 0, 0),
ExchangeProcessor::deserialize_account(&from_dst_account.data[..]).unwrap()
);
assert_eq!(
TokenAccountInfo::default().owner(&owner).tokens(0, 1, 0, 0),
TokenAccountInfo::default()
.owner(&owner.pubkey())
.tokens(0, 1, 0, 0),
ExchangeProcessor::deserialize_account(&profit_account.data[..]).unwrap()
);
assert_eq!(

View File

@ -4,21 +4,22 @@ use solana_runtime::loader_utils::{create_invoke_instruction, load_program};
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::instruction::InstructionError;
use solana_sdk::native_loader;
use solana_sdk::signature::KeypairUtil;
use solana_sdk::transaction::TransactionError;
#[test]
fn test_program_native_failure() {
let (genesis_block, mint_keypair) = GenesisBlock::new(50);
let (genesis_block, alice_keypair) = GenesisBlock::new(50);
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let bank_client = BankClient::new(&bank);
let program = "failure".as_bytes().to_vec();
let program_id = load_program(&bank, &alice_client, &native_loader::id(), program);
let program_id = load_program(&bank_client, &alice_keypair, &native_loader::id(), program);
// Call user program
let instruction = create_invoke_instruction(alice_client.pubkey(), program_id, &1u8);
let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
assert_eq!(
alice_client.process_instruction(instruction),
bank_client.process_instruction(&alice_keypair, instruction),
Err(TransactionError::InstructionError(
0,
InstructionError::GenericError

View File

@ -3,19 +3,22 @@ use solana_runtime::bank_client::BankClient;
use solana_runtime::loader_utils::{create_invoke_instruction, load_program};
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::native_loader;
use solana_sdk::signature::KeypairUtil;
#[test]
fn test_program_native_noop() {
solana_logger::setup();
let (genesis_block, mint_keypair) = GenesisBlock::new(50);
let (genesis_block, alice_keypair) = GenesisBlock::new(50);
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let bank_client = BankClient::new(&bank);
let program = "noop".as_bytes().to_vec();
let program_id = load_program(&bank, &alice_client, &native_loader::id(), program);
let program_id = load_program(&bank_client, &alice_keypair, &native_loader::id(), program);
// Call user program
let instruction = create_invoke_instruction(alice_client.pubkey(), program_id, &1u8);
alice_client.process_instruction(instruction).unwrap();
let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
bank_client
.process_instruction(&alice_keypair, instruction)
.unwrap();
}

View File

@ -358,19 +358,19 @@ mod tests {
#[test]
fn test_bank_storage() {
let (mut genesis_block, mint_keypair) = GenesisBlock::new(1000);
let (mut genesis_block, alice_keypair) = GenesisBlock::new(1000);
genesis_block
.native_programs
.push(("solana_storage_program".to_string(), id()));
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let alice_pubkey = alice_keypair.pubkey();
let bob_keypair = Keypair::new();
let bob_client = BankClient::new(&bank, bob_keypair);
let bob_pubkey = bob_client.pubkey();
let bob_pubkey = bob_keypair.pubkey();
let jack_pubkey = Keypair::new().pubkey();
let jill_pubkey = Keypair::new().pubkey();
let bank = Bank::new(&genesis_block);
let bank_client = BankClient::new(&bank);
let x = 42;
let blockhash = genesis_block.hash();
let x2 = x * 2;
@ -378,14 +378,20 @@ mod tests {
bank.register_tick(&blockhash);
alice_client.transfer(10, &jill_pubkey).unwrap();
alice_client.transfer(10, &bob_pubkey).unwrap();
alice_client.transfer(10, &jack_pubkey).unwrap();
bank_client
.transfer(10, &alice_keypair, &jill_pubkey)
.unwrap();
bank_client
.transfer(10, &alice_keypair, &bob_pubkey)
.unwrap();
bank_client
.transfer(10, &alice_keypair, &jack_pubkey)
.unwrap();
let ix =
SystemInstruction::new_program_account(&alice_pubkey, &bob_pubkey, 1, 4 * 1024, &id());
alice_client.process_instruction(ix).unwrap();
bank_client.process_instruction(&alice_keypair, ix).unwrap();
let ix = StorageInstruction::new_advertise_recent_blockhash(
&bob_pubkey,
@ -393,7 +399,7 @@ mod tests {
ENTRIES_PER_SEGMENT,
);
bob_client.process_instruction(ix).unwrap();
bank_client.process_instruction(&bob_keypair, ix).unwrap();
let entry_height = 0;
let ix = StorageInstruction::new_mining_proof(
@ -402,7 +408,7 @@ mod tests {
entry_height,
Signature::default(),
);
let _result = bob_client.process_instruction(ix).unwrap();
let _result = bank_client.process_instruction(&bob_keypair, ix).unwrap();
assert_eq!(
get_storage_entry_height(&bank, &bob_pubkey),

View File

@ -50,7 +50,7 @@ mod tests {
use solana_runtime::bank::{Bank, Result};
use solana_runtime::bank_client::BankClient;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError};
use solana_sdk::instruction::InstructionError;
use solana_sdk::message::Message;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
@ -66,49 +66,51 @@ mod tests {
fn create_vote_account(
bank_client: &BankClient,
from_keypair: &Keypair,
vote_id: &Pubkey,
lamports: u64,
) -> Result<()> {
let ixs = VoteInstruction::new_account(&bank_client.pubkey(), vote_id, lamports);
let ixs = VoteInstruction::new_account(&from_keypair.pubkey(), vote_id, lamports);
let message = Message::new(ixs);
bank_client.process_message(message)
bank_client.process_message(&[from_keypair], message)
}
fn create_vote_account_with_delegate(
bank_client: &BankClient,
from_keypair: &Keypair,
vote_keypair: &Keypair,
delegate_id: &Pubkey,
lamports: u64,
) -> Result<()> {
let vote_id = bank_client.pubkeys()[1];
let mut ixs = VoteInstruction::new_account(&bank_client.pubkey(), &vote_id, lamports);
let vote_id = vote_keypair.pubkey();
let mut ixs = VoteInstruction::new_account(&from_keypair.pubkey(), &vote_id, lamports);
let delegate_ix = VoteInstruction::new_delegate_stake(&vote_id, delegate_id);
ixs.push(delegate_ix);
let message = Message::new(ixs);
bank_client.process_message(message)
bank_client.process_message(&[&from_keypair, vote_keypair], message)
}
fn submit_vote(
bank_client: &BankClient,
staking_account: &Pubkey,
vote_keypair: &Keypair,
tick_height: u64,
) -> Result<()> {
let vote_ix = VoteInstruction::new_vote(staking_account, Vote::new(tick_height));
bank_client.process_instruction(vote_ix)
let vote_ix = VoteInstruction::new_vote(&vote_keypair.pubkey(), Vote::new(tick_height));
bank_client.process_instruction(&vote_keypair, vote_ix)
}
#[test]
fn test_vote_bank_basic() {
let (bank, from_keypair) = create_bank(10_000);
let alice_client = BankClient::new(&bank, from_keypair);
let bank_client = BankClient::new(&bank);
let vote_keypair = Keypair::new();
let vote_client = BankClient::new(&bank, vote_keypair);
let vote_id = vote_client.pubkey();
let vote_id = vote_keypair.pubkey();
create_vote_account(&alice_client, &vote_id, 100).unwrap();
submit_vote(&vote_client, &vote_id, 0).unwrap();
create_vote_account(&bank_client, &from_keypair, &vote_id, 100).unwrap();
submit_vote(&bank_client, &vote_keypair, 0).unwrap();
let vote_account = bank.get_account(&vote_client.pubkey()).unwrap();
let vote_account = bank.get_account(&vote_id).unwrap();
let vote_state = VoteState::deserialize(&vote_account.data).unwrap();
assert_eq!(vote_state.votes.len(), 1);
}
@ -117,36 +119,38 @@ mod tests {
fn test_vote_bank_delegate() {
let (bank, from_keypair) = create_bank(10_000);
let vote_keypair = Keypair::new();
let alice_and_vote_client =
BankClient::new_with_keypairs(&bank, vec![from_keypair, vote_keypair]);
let bank_client = BankClient::new(&bank);
let delegate_id = Keypair::new().pubkey();
create_vote_account_with_delegate(&alice_and_vote_client, &delegate_id, 100).unwrap();
create_vote_account_with_delegate(
&bank_client,
&from_keypair,
&vote_keypair,
&delegate_id,
100,
)
.unwrap();
}
#[test]
fn test_vote_via_bank_with_no_signature() {
let (bank, from_keypair) = create_bank(10_000);
let mallory_client = BankClient::new(&bank, from_keypair);
let (bank, mallory_keypair) = create_bank(10_000);
let bank_client = BankClient::new(&bank);
let vote_keypair = Keypair::new();
let vote_client = BankClient::new(&bank, vote_keypair);
let vote_id = vote_client.pubkey();
let vote_id = vote_keypair.pubkey();
create_vote_account(&mallory_client, &vote_id, 100).unwrap();
create_vote_account(&bank_client, &mallory_keypair, &vote_id, 100).unwrap();
let mallory_id = mallory_client.pubkey();
let vote_ix = Instruction::new(
id(),
&VoteInstruction::Vote(Vote::new(0)),
vec![AccountMeta::new(vote_id, false)], // <--- attack!! No signer required.
);
let mallory_id = mallory_keypair.pubkey();
let mut vote_ix = VoteInstruction::new_vote(&vote_id, Vote::new(0));
vote_ix.accounts[0].is_signer = false; // <--- attack!! No signer required.
// Sneak in an instruction so that the transaction is signed but
// the 0th account in the second instruction is not! The program
// needs to check that it's signed.
let move_ix = SystemInstruction::new_move(&mallory_id, &vote_id, 1);
let message = Message::new(vec![move_ix, vote_ix]);
let result = mallory_client.process_message(message);
let result = bank_client.process_message(&[&mallory_keypair], message);
// And ensure there's no vote.
let vote_account = bank.get_account(&vote_id).unwrap();

View File

@ -8,44 +8,42 @@ use solana_sdk::transaction::{Transaction, TransactionError};
pub struct BankClient<'a> {
bank: &'a Bank,
keypairs: Vec<Keypair>,
}
impl<'a> BankClient<'a> {
pub fn new_with_keypairs(bank: &'a Bank, keypairs: Vec<Keypair>) -> Self {
assert!(!keypairs.is_empty());
Self { bank, keypairs }
pub fn new(bank: &'a Bank) -> Self {
Self { bank }
}
pub fn new(bank: &'a Bank, keypair: Keypair) -> Self {
Self::new_with_keypairs(bank, vec![keypair])
}
pub fn pubkey(&self) -> Pubkey {
self.keypairs[0].pubkey()
}
pub fn pubkeys(&self) -> Vec<Pubkey> {
self.keypairs.iter().map(|x| x.pubkey()).collect()
}
pub fn process_message(&self, message: Message) -> Result<(), TransactionError> {
let keypairs: Vec<_> = self.keypairs.iter().collect();
pub fn process_message(
&self,
keypairs: &[&Keypair],
message: Message,
) -> Result<(), TransactionError> {
let blockhash = self.bank.last_blockhash();
let transaction = Transaction::new(&keypairs, message, blockhash);
self.bank.process_transaction(&transaction)
}
/// Create and process a transaction from a single instruction.
pub fn process_instruction(&self, instruction: Instruction) -> Result<(), TransactionError> {
pub fn process_instruction(
&self,
keypair: &Keypair,
instruction: Instruction,
) -> Result<(), TransactionError> {
let message = Message::new(vec![instruction]);
self.process_message(message)
self.process_message(&[keypair], message)
}
/// Transfer lamports to pubkey
pub fn transfer(&self, lamports: u64, pubkey: &Pubkey) -> Result<(), TransactionError> {
let move_instruction = SystemInstruction::new_move(&self.pubkey(), pubkey, lamports);
self.process_instruction(move_instruction)
/// Transfer `lamports` from `keypair` to `pubkey`
pub fn transfer(
&self,
lamports: u64,
keypair: &Keypair,
pubkey: &Pubkey,
) -> Result<(), TransactionError> {
let move_instruction = SystemInstruction::new_move(&keypair.pubkey(), pubkey, lamports);
self.process_instruction(keypair, move_instruction)
}
}
@ -58,21 +56,22 @@ mod tests {
#[test]
fn test_bank_client_new_with_keypairs() {
let (genesis_block, john_doe_keypair) = GenesisBlock::new(10_000);
let john_pubkey = john_doe_keypair.pubkey();
let jane_doe_keypair = Keypair::new();
let doe_keypairs = vec![john_doe_keypair, jane_doe_keypair];
let jane_pubkey = jane_doe_keypair.pubkey();
let doe_keypairs = vec![&john_doe_keypair, &jane_doe_keypair];
let bank = Bank::new(&genesis_block);
let doe_client = BankClient::new_with_keypairs(&bank, doe_keypairs);
let jane_pubkey = doe_client.pubkeys()[1];
let bank_client = BankClient::new(&bank);
// Create 2-2 Multisig Move instruction.
let bob_pubkey = Keypair::new().pubkey();
let mut move_instruction =
SystemInstruction::new_move(&doe_client.pubkey(), &bob_pubkey, 42);
let mut move_instruction = SystemInstruction::new_move(&john_pubkey, &bob_pubkey, 42);
move_instruction
.accounts
.push(AccountMeta::new(jane_pubkey, true));
doe_client.process_instruction(move_instruction).unwrap();
let message = Message::new(vec![move_instruction]);
bank_client.process_message(&doe_keypairs, message).unwrap();
assert_eq!(bank.get_balance(&bob_pubkey), 42);
}
}

View File

@ -1,4 +1,3 @@
use crate::bank::Bank;
use crate::bank_client::BankClient;
use serde::Serialize;
use solana_sdk::instruction::{AccountMeta, Instruction};
@ -8,8 +7,8 @@ use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_instruction::SystemInstruction;
pub fn load_program(
bank: &Bank,
from_client: &BankClient,
bank_client: &BankClient,
from_keypair: &Keypair,
loader_id: &Pubkey,
program: Vec<u8>,
) -> Pubkey {
@ -17,27 +16,31 @@ pub fn load_program(
let program_pubkey = program_keypair.pubkey();
let instruction = SystemInstruction::new_program_account(
&from_client.pubkey(),
&from_keypair.pubkey(),
&program_pubkey,
1,
program.len() as u64,
loader_id,
);
from_client.process_instruction(instruction).unwrap();
let program_client = BankClient::new(bank, program_keypair);
bank_client
.process_instruction(&from_keypair, instruction)
.unwrap();
let chunk_size = 256; // Size of chunk just needs to fit into tx
let mut offset = 0;
for chunk in program.chunks(chunk_size) {
let instruction =
LoaderInstruction::new_write(&program_pubkey, loader_id, offset, chunk.to_vec());
program_client.process_instruction(instruction).unwrap();
bank_client
.process_instruction(&program_keypair, instruction)
.unwrap();
offset += chunk_size as u32;
}
let instruction = LoaderInstruction::new_finalize(&program_pubkey, loader_id);
program_client.process_instruction(instruction).unwrap();
bank_client
.process_instruction(&program_keypair, instruction)
.unwrap();
program_pubkey
}

View File

@ -277,17 +277,17 @@ mod tests {
#[test]
fn test_system_unsigned_transaction() {
let (genesis_block, mint_keypair) = GenesisBlock::new(100);
let bank = Bank::new(&genesis_block);
let alice_client = BankClient::new(&bank, mint_keypair);
let alice_pubkey = alice_client.pubkey();
let mallory_client = BankClient::new(&bank, Keypair::new());
let mallory_pubkey = mallory_client.pubkey();
let (genesis_block, alice_keypair) = GenesisBlock::new(100);
let alice_pubkey = alice_keypair.pubkey();
let mallory_keypair = Keypair::new();
let mallory_pubkey = mallory_keypair.pubkey();
// Fund to account to bypass AccountNotFound error
alice_client.transfer(50, &mallory_pubkey).unwrap();
let bank = Bank::new(&genesis_block);
let bank_client = BankClient::new(&bank);
bank_client
.transfer(50, &alice_keypair, &mallory_pubkey)
.unwrap();
// Erroneously sign transaction with recipient account key
// No signature case is tested by bank `test_zero_signatures()`
@ -301,7 +301,7 @@ mod tests {
account_metas,
);
assert_eq!(
mallory_client.process_instruction(malicious_instruction),
bank_client.process_instruction(&mallory_keypair, malicious_instruction),
Err(TransactionError::InstructionError(
0,
InstructionError::MissingRequiredSignature