diff --git a/programs/budget/src/budget_processor.rs b/programs/budget/src/budget_processor.rs index 20851aa14c..d3a2a9b4da 100644 --- a/programs/budget/src/budget_processor.rs +++ b/programs/budget/src/budget_processor.rs @@ -292,7 +292,7 @@ mod test { dt, ); assert_eq!( - alice_client.process_script(vec![instruction]).unwrap_err(), + alice_client.process_instruction(instruction).unwrap_err(), TransactionError::InstructionError( 0, InstructionError::ProgramError(ProgramError::CustomError( @@ -312,7 +312,7 @@ mod test { // that pubkey's funds are now available. let instruction = BudgetInstruction::new_apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt); - alice_client.process_script(vec![instruction]).unwrap(); + alice_client.process_instruction(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); @@ -353,7 +353,7 @@ mod test { let instruction = BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey); - mallory_client.process_script(vec![instruction]).unwrap(); + mallory_client.process_instruction(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); @@ -362,7 +362,7 @@ mod test { // Now, cancel the transaction. mint gets her funds back let instruction = BudgetInstruction::new_apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey); - alice_client.process_script(vec![instruction]).unwrap(); + alice_client.process_instruction(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); diff --git a/programs/budget_api/src/budget_instruction.rs b/programs/budget_api/src/budget_instruction.rs index 8fe44a3809..42a950af59 100644 --- a/programs/budget_api/src/budget_instruction.rs +++ b/programs/budget_api/src/budget_instruction.rs @@ -5,9 +5,10 @@ use bincode::serialized_size; use chrono::prelude::{DateTime, Utc}; use serde_derive::{Deserialize, Serialize}; use solana_sdk::pubkey::Pubkey; +use solana_sdk::script::Script; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; -use solana_sdk::transaction::{Instruction, Script}; +use solana_sdk::transaction::Instruction; /// A smart contract. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] @@ -48,10 +49,10 @@ impl BudgetInstruction { expr: BudgetExpr, ) -> Script { let space = serialized_size(&BudgetState::new(expr.clone())).unwrap(); - vec![ + Script::new(vec![ SystemInstruction::new_program_account(&from, contract, lamports, space, &id()), Self::new_initialize_account(contract, expr), - ] + ]) } /// Create a new payment script. diff --git a/programs/budget_api/src/budget_transaction.rs b/programs/budget_api/src/budget_transaction.rs index 2b658e64ad..0f3a1c43e5 100644 --- a/programs/budget_api/src/budget_transaction.rs +++ b/programs/budget_api/src/budget_transaction.rs @@ -5,9 +5,10 @@ use bincode::deserialize; use chrono::prelude::*; use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; +use solana_sdk::script::Script; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; -use solana_sdk::transaction::{Script, Transaction}; +use solana_sdk::transaction::Transaction; pub struct BudgetTransaction {} @@ -18,7 +19,7 @@ impl BudgetTransaction { recent_blockhash: Hash, fee: u64, ) -> Transaction { - let mut tx = Transaction::new(script); + let mut tx = script.compile(); tx.fee = fee; tx.sign(&[from_keypair], recent_blockhash); tx diff --git a/programs/config/src/lib.rs b/programs/config/src/lib.rs index dc91669734..1cbc551cfb 100644 --- a/programs/config/src/lib.rs +++ b/programs/config/src/lib.rs @@ -55,9 +55,10 @@ mod tests { use solana_runtime::bank::Bank; use solana_runtime::bank_client::BankClient; use solana_sdk::genesis_block::GenesisBlock; + use solana_sdk::script::Script; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; - use solana_sdk::transaction::{Instruction, Transaction}; + use solana_sdk::transaction::Instruction; #[derive(Serialize, Deserialize, Default, Debug, PartialEq)] struct MyConfig { @@ -96,7 +97,7 @@ mod tests { let config_pubkey = config_client.pubkey(); let instruction = create_account_instruction(&from_pubkey, &config_pubkey); - from_client.process_script(vec![instruction]).unwrap(); + from_client.process_instruction(instruction).unwrap(); config_client } @@ -123,7 +124,7 @@ mod tests { let my_config = MyConfig::new(42); let instruction = ConfigInstruction::new_store(&config_pubkey, &my_config); - config_client.process_script(vec![instruction]).unwrap(); + config_client.process_instruction(instruction).unwrap(); let config_account = bank.get_account(&config_pubkey).unwrap(); assert_eq!( @@ -143,7 +144,8 @@ mod tests { let instruction = ConfigInstruction::new_store(&config_pubkey, &my_config); // Replace instruction data with a vector that's too large - let mut transaction = Transaction::new(vec![instruction]); + let script = Script::new(vec![instruction]); + let mut transaction = script.compile(); transaction.instructions[0].data = vec![0; 123]; config_client.process_transaction(transaction).unwrap_err(); } @@ -164,7 +166,8 @@ mod tests { let store_instruction = ConfigInstruction::new_store(&config_pubkey, &my_config); // Don't sign the transaction with `config_client` - let mut transaction = Transaction::new(vec![move_instruction, store_instruction]); + let script = Script::new(vec![move_instruction, store_instruction]); + let mut transaction = script.compile(); transaction.sign_unchecked(&[&system_keypair], bank.last_blockhash()); let system_client = BankClient::new(&bank, system_keypair); system_client.process_transaction(transaction).unwrap_err(); diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index 6b54df48ad..e0a61a333f 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -1,8 +1,9 @@ use crate::bank::Bank; use solana_sdk::pubkey::Pubkey; +use solana_sdk::script::Script; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; -use solana_sdk::transaction::{Script, Transaction, TransactionError}; +use solana_sdk::transaction::{Instruction, Transaction, TransactionError}; pub struct BankClient<'a> { bank: &'a Bank, @@ -25,12 +26,25 @@ impl<'a> BankClient<'a> { /// Create and process a transaction. pub fn process_script(&self, script: Script) -> Result<(), TransactionError> { - self.process_transaction(Transaction::new(script)) + self.process_transaction(script.compile()) + } + + /// Create and process a transaction from a list of instructions. + pub fn process_instructions( + &self, + instructions: Vec, + ) -> Result<(), TransactionError> { + self.process_script(Script::new(instructions)) + } + + /// Create and process a transaction from a single instruction. + pub fn process_instruction(&self, instruction: Instruction) -> Result<(), TransactionError> { + self.process_instructions(vec![instruction]) } /// 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_script(vec![move_instruction]) + self.process_instruction(move_instruction) } } diff --git a/runtime/src/system_program.rs b/runtime/src/system_program.rs index 52c226a2f4..d1d38efa9e 100644 --- a/runtime/src/system_program.rs +++ b/runtime/src/system_program.rs @@ -109,6 +109,7 @@ mod tests { use solana_sdk::account::Account; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::native_program::ProgramError; + use solana_sdk::script::Script; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::system_program; @@ -291,11 +292,11 @@ mod tests { // Erroneously sign transaction with recipient account key // No signature case is tested by bank `test_zero_signatures()` - let malicious_script = vec![Instruction::new( + let malicious_script = Script::new(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( diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index df1ccea277..cacbe83431 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -9,6 +9,7 @@ pub mod native_program; pub mod packet; pub mod pubkey; pub mod rpc_port; +pub mod script; pub mod shortvec; pub mod signature; pub mod system_instruction; @@ -16,7 +17,6 @@ pub mod system_program; pub mod system_transaction; pub mod timing; pub mod transaction; -mod transaction_compiler; #[macro_use] extern crate serde_derive; diff --git a/sdk/src/transaction_compiler.rs b/sdk/src/script.rs similarity index 89% rename from sdk/src/transaction_compiler.rs rename to sdk/src/script.rs index 3ba66e0c01..3a2b524d76 100644 --- a/sdk/src/transaction_compiler.rs +++ b/sdk/src/script.rs @@ -1,4 +1,4 @@ -//! A library for composing transactions. +//! A library for building scripts and compiling them into transactions. use crate::hash::Hash; use crate::pubkey::Pubkey; @@ -33,11 +33,11 @@ fn compile_instructions( } /// A utility for constructing transactions -pub struct TransactionCompiler { +pub struct Script { instructions: Vec, } -impl TransactionCompiler { +impl Script { /// Create a new unsigned transaction from a single instruction pub fn new(instructions: Vec) -> Self { Self { instructions } @@ -100,7 +100,7 @@ mod tests { #[test] fn test_transaction_builder_unique_program_ids() { let program_id0 = Pubkey::default(); - let program_ids = TransactionCompiler::new(vec![ + let program_ids = Script::new(vec![ Instruction::new(program_id0, &0, vec![]), Instruction::new(program_id0, &0, vec![]), ]) @@ -112,7 +112,7 @@ mod tests { fn test_transaction_builder_unique_program_ids_not_adjacent() { let program_id0 = Pubkey::default(); let program_id1 = Keypair::new().pubkey(); - let program_ids = TransactionCompiler::new(vec![ + let program_ids = Script::new(vec![ Instruction::new(program_id0, &0, vec![]), Instruction::new(program_id1, &0, vec![]), Instruction::new(program_id0, &0, vec![]), @@ -125,7 +125,7 @@ mod tests { fn test_transaction_builder_unique_program_ids_order_preserved() { let program_id0 = Keypair::new().pubkey(); let program_id1 = Pubkey::default(); // Key less than program_id0 - let program_ids = TransactionCompiler::new(vec![ + let program_ids = Script::new(vec![ Instruction::new(program_id0, &0, vec![]), Instruction::new(program_id1, &0, vec![]), Instruction::new(program_id0, &0, vec![]), @@ -138,7 +138,7 @@ mod tests { fn test_transaction_builder_unique_keys_both_signed() { let program_id = Pubkey::default(); let id0 = Pubkey::default(); - let keys = TransactionCompiler::new(vec![ + let keys = Script::new(vec![ Instruction::new(program_id, &0, vec![(id0, true)]), Instruction::new(program_id, &0, vec![(id0, true)]), ]) @@ -150,7 +150,7 @@ mod tests { fn test_transaction_builder_unique_keys_one_signed() { let program_id = Pubkey::default(); let id0 = Pubkey::default(); - let keys = TransactionCompiler::new(vec![ + let keys = Script::new(vec![ Instruction::new(program_id, &0, vec![(id0, false)]), Instruction::new(program_id, &0, vec![(id0, true)]), ]) @@ -163,7 +163,7 @@ mod tests { let program_id = Pubkey::default(); let id0 = Keypair::new().pubkey(); let id1 = Pubkey::default(); // Key less than id0 - let keys = TransactionCompiler::new(vec![ + let keys = Script::new(vec![ Instruction::new(program_id, &0, vec![(id0, false)]), Instruction::new(program_id, &0, vec![(id1, false)]), ]) @@ -176,7 +176,7 @@ mod tests { let program_id = Pubkey::default(); let id0 = Pubkey::default(); let id1 = Keypair::new().pubkey(); - let keys = TransactionCompiler::new(vec![ + let keys = Script::new(vec![ Instruction::new(program_id, &0, vec![(id0, false)]), Instruction::new(program_id, &0, vec![(id1, false)]), Instruction::new(program_id, &0, vec![(id0, true)]), @@ -190,7 +190,7 @@ mod tests { let program_id = Pubkey::default(); let id0 = Pubkey::default(); let id1 = Keypair::new().pubkey(); - let keys = TransactionCompiler::new(vec![ + let keys = Script::new(vec![ Instruction::new(program_id, &0, vec![(id0, false)]), Instruction::new(program_id, &0, vec![(id1, true)]), ]) @@ -203,14 +203,10 @@ mod tests { fn test_transaction_builder_signed_keys_len() { let program_id = Pubkey::default(); let id0 = Pubkey::default(); - let tx = - TransactionCompiler::new(vec![Instruction::new(program_id, &0, vec![(id0, false)])]) - .compile(); + let tx = Script::new(vec![Instruction::new(program_id, &0, vec![(id0, false)])]).compile(); assert_eq!(tx.signatures.capacity(), 0); - let tx = - TransactionCompiler::new(vec![Instruction::new(program_id, &0, vec![(id0, true)])]) - .compile(); + let tx = Script::new(vec![Instruction::new(program_id, &0, vec![(id0, true)])]).compile(); assert_eq!(tx.signatures.capacity(), 1); } @@ -221,7 +217,7 @@ mod tests { let id0 = Pubkey::default(); let keypair1 = Keypair::new(); let id1 = keypair1.pubkey(); - let tx = TransactionCompiler::new(vec![ + let tx = Script::new(vec![ Instruction::new(program_id0, &0, vec![(id0, false)]), Instruction::new(program_id1, &0, vec![(id1, true)]), Instruction::new(program_id0, &0, vec![(id1, false)]), diff --git a/sdk/src/transaction.rs b/sdk/src/transaction.rs index 1ac7087851..1e90e16a9c 100644 --- a/sdk/src/transaction.rs +++ b/sdk/src/transaction.rs @@ -4,13 +4,13 @@ use crate::hash::{Hash, Hasher}; use crate::native_program::ProgramError; use crate::packet::PACKET_DATA_SIZE; use crate::pubkey::Pubkey; +use crate::script::Script; use crate::shortvec::{ deserialize_vec_bytes, deserialize_vec_with, encode_len, serialize_vec_bytes, serialize_vec_with, }; use crate::signature::{KeypairUtil, Signature}; use crate::system_instruction::SystemError; -use crate::transaction_compiler::TransactionCompiler; use bincode::{serialize, Error}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use serde::{Deserialize, Serialize, Serializer}; @@ -71,10 +71,7 @@ impl GenericInstruction { } pub type Instruction = GenericInstruction; -pub type Script = Vec; - pub type CompiledInstruction = GenericInstruction; -pub type CompiledScript = Vec; impl CompiledInstruction { pub fn serialize_with(mut writer: &mut Cursor<&mut [u8]>, ix: &Self) -> Result<(), Error> { @@ -166,12 +163,12 @@ pub struct Transaction { pub program_ids: Vec, /// Programs that will be executed in sequence and committed in one atomic transaction if all /// succeed. - pub instructions: CompiledScript, + pub instructions: Vec, } impl Transaction { - pub fn new(script: Script) -> Self { - TransactionCompiler::new(script).compile() + pub fn new(instructions: Vec) -> Self { + Script::new(instructions).compile() } pub fn new_with_blockhash_and_fee( @@ -227,7 +224,7 @@ impl Transaction { recent_blockhash: Hash, fee: u64, program_ids: Vec, - instructions: CompiledScript, + instructions: Vec, ) -> Self { let mut account_keys: Vec<_> = from_keypairs .iter() @@ -469,7 +466,7 @@ impl<'a> serde::de::Visitor<'a> for TransactionVisitor { let program_ids: Vec = deserialize_vec_with(&mut rd, Transaction::deserialize_pubkey) .map_err(Error::custom)?; - let instructions: CompiledScript = + let instructions: Vec = deserialize_vec_with(&mut rd, CompiledInstruction::deserialize_from) .map_err(Error::custom)?; Ok(Transaction {