From 0c0716abfba38fd2a922e42e5d0185b39acedca4 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 16 Mar 2019 17:37:18 -0600 Subject: [PATCH] Move Bank-based tests into unit-tests --- ...{budget_program.rs => budget_processor.rs} | 11 +++++ programs/budget/src/lib.rs | 4 +- programs/budget_api/src/budget_instruction.rs | 8 ++++ programs/budget_api/src/budget_transaction.rs | 38 ++---------------- runtime/src/bank_client.rs | 2 +- runtime/src/system_program.rs | 39 ++++++++++++++++++ runtime/tests/system.rs | 40 ------------------- 7 files changed, 64 insertions(+), 78 deletions(-) rename programs/budget/src/{budget_program.rs => budget_processor.rs} (96%) delete mode 100644 runtime/tests/system.rs diff --git a/programs/budget/src/budget_program.rs b/programs/budget/src/budget_processor.rs similarity index 96% rename from programs/budget/src/budget_program.rs rename to programs/budget/src/budget_processor.rs index 0bf4da7404..20851aa14c 100644 --- a/programs/budget/src/budget_program.rs +++ b/programs/budget/src/budget_processor.rs @@ -158,6 +158,17 @@ mod test { (bank, mint_keypair) } + #[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 bob_pubkey = Keypair::new().pubkey(); + let script = BudgetInstruction::new_payment_script(&alice_pubkey, &bob_pubkey, 100); + alice_client.process_script(script).unwrap(); + assert_eq!(bank.get_balance(&bob_pubkey), 100); + } + #[test] fn test_unsigned_witness_key() { let (bank, mint_keypair) = create_bank(10_000); diff --git a/programs/budget/src/lib.rs b/programs/budget/src/lib.rs index 93e31cdb04..30f0dc2646 100644 --- a/programs/budget/src/lib.rs +++ b/programs/budget/src/lib.rs @@ -1,6 +1,6 @@ -mod budget_program; +mod budget_processor; -use crate::budget_program::process_instruction; +use crate::budget_processor::process_instruction; use log::*; use solana_sdk::account::KeyedAccount; use solana_sdk::native_program::ProgramError; diff --git a/programs/budget_api/src/budget_instruction.rs b/programs/budget_api/src/budget_instruction.rs index 0bcb0eb3a5..8fe44a3809 100644 --- a/programs/budget_api/src/budget_instruction.rs +++ b/programs/budget_api/src/budget_instruction.rs @@ -5,6 +5,7 @@ use bincode::serialized_size; use chrono::prelude::{DateTime, Utc}; use serde_derive::{Deserialize, Serialize}; use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::transaction::{Instruction, Script}; @@ -53,6 +54,13 @@ impl BudgetInstruction { ] } + /// Create a new payment script. + pub fn new_payment_script(from: &Pubkey, to: &Pubkey, lamports: u64) -> Script { + let contract = Keypair::new().pubkey(); + let expr = BudgetExpr::new_payment(lamports, to); + Self::new_initialize_account_script(from, &contract, lamports, expr) + } + /// Create a postdated payment script. pub fn new_on_date_script( from: &Pubkey, diff --git a/programs/budget_api/src/budget_transaction.rs b/programs/budget_api/src/budget_transaction.rs index 481a16ac7d..02c0075b13 100644 --- a/programs/budget_api/src/budget_transaction.rs +++ b/programs/budget_api/src/budget_transaction.rs @@ -1,10 +1,7 @@ //! The `budget_transaction` module provides functionality for creating Budget transactions. -use crate::budget_expr::BudgetExpr; use crate::budget_instruction::BudgetInstruction; -use crate::budget_state::BudgetState; -use crate::id; -use bincode::{deserialize, serialized_size}; +use bincode::deserialize; use chrono::prelude::*; use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; @@ -15,27 +12,6 @@ use solana_sdk::transaction::{Script, Transaction}; pub struct BudgetTransaction {} impl BudgetTransaction { - /// Create and sign a new Transaction. Used for unit-testing. - #[allow(clippy::new_ret_no_self)] - fn new( - from_keypair: &Keypair, - contract: &Pubkey, - expr: BudgetExpr, - lamports: u64, - recent_blockhash: Hash, - fee: u64, - ) -> Transaction { - let from = from_keypair.pubkey(); - let space = serialized_size(&BudgetState::new(expr.clone())).unwrap(); - let create_ix = - SystemInstruction::new_program_account(&from, contract, lamports, space, &id()); - let init_ix = BudgetInstruction::new_initialize_account(contract, expr); - let mut tx = Transaction::new(vec![create_ix, init_ix]); - tx.fee = fee; - tx.sign(&[from_keypair], recent_blockhash); - tx - } - fn new_signed( from_keypair: &Keypair, script: Script, @@ -56,16 +32,8 @@ impl BudgetTransaction { recent_blockhash: Hash, fee: u64, ) -> Transaction { - let contract = Keypair::new().pubkey(); - let expr = BudgetExpr::new_payment(lamports, to); - Self::new( - from_keypair, - &contract, - expr, - lamports, - recent_blockhash, - fee, - ) + let script = BudgetInstruction::new_payment_script(&from_keypair.pubkey(), to, lamports); + Self::new_signed(from_keypair, script, recent_blockhash, fee) } /// Create and sign a new Witness Timestamp. Used for unit-testing. diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index 07e6a943de..6b54df48ad 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -20,7 +20,7 @@ impl<'a> BankClient<'a> { pub fn process_transaction(&self, mut tx: Transaction) -> Result<(), TransactionError> { tx.sign(&[&self.keypair], self.bank.last_blockhash()); - self.bank.process_transaction(&mut tx) + self.bank.process_transaction(&tx) } /// Create and process a transaction. diff --git a/runtime/src/system_program.rs b/runtime/src/system_program.rs index 1fc01f9848..52c226a2f4 100644 --- a/runtime/src/system_program.rs +++ b/runtime/src/system_program.rs @@ -104,8 +104,15 @@ pub fn entrypoint( #[cfg(test)] mod tests { use super::*; + use crate::bank::Bank; + use crate::bank_client::BankClient; use solana_sdk::account::Account; + use solana_sdk::genesis_block::GenesisBlock; + use solana_sdk::native_program::ProgramError; use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::system_instruction::SystemInstruction; + use solana_sdk::system_program; + use solana_sdk::transaction::{Instruction, InstructionError, TransactionError}; #[test] fn test_create_system_account() { @@ -267,4 +274,36 @@ mod tests { assert_eq!(from_account.lamports, 50); assert_eq!(to_account.lamports, 51); } + + #[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(); + + // Fund to account to bypass AccountNotFound error + alice_client.transfer(50, &mallory_pubkey).unwrap(); + + // Erroneously sign transaction with recipient account key + // No signature case is tested by bank `test_zero_signatures()` + let malicious_script = vec![Instruction::new( + system_program::id(), + &SystemInstruction::Move { lamports: 10 }, + vec![(alice_pubkey, false), (mallory_pubkey, true)], + )]; + assert_eq!( + mallory_client.process_script(malicious_script), + Err(TransactionError::InstructionError( + 0, + InstructionError::ProgramError(ProgramError::MissingRequiredSignature) + )) + ); + assert_eq!(bank.get_balance(&alice_pubkey), 50); + assert_eq!(bank.get_balance(&mallory_pubkey), 50); + } } diff --git a/runtime/tests/system.rs b/runtime/tests/system.rs deleted file mode 100644 index f815ae78e9..0000000000 --- a/runtime/tests/system.rs +++ /dev/null @@ -1,40 +0,0 @@ -use solana_runtime::bank::Bank; -use solana_runtime::bank_client::BankClient; -use solana_sdk::genesis_block::GenesisBlock; -use solana_sdk::native_program::ProgramError; -use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::system_instruction::SystemInstruction; -use solana_sdk::system_program; -use solana_sdk::transaction::{Instruction, InstructionError, TransactionError}; - -#[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(); - - // Fund to account to bypass AccountNotFound error - alice_client.transfer(50, &mallory_pubkey).unwrap(); - - // Erroneously sign transaction with recipient account key - // No signature case is tested by bank `test_zero_signatures()` - let malicious_script = vec![Instruction::new( - system_program::id(), - &SystemInstruction::Move { lamports: 10 }, - vec![(alice_pubkey, false), (mallory_pubkey, true)], - )]; - assert_eq!( - mallory_client.process_script(malicious_script), - Err(TransactionError::InstructionError( - 0, - InstructionError::ProgramError(ProgramError::MissingRequiredSignature) - )) - ); - assert_eq!(bank.get_balance(&alice_pubkey), 50); - assert_eq!(bank.get_balance(&mallory_pubkey), 50); -}