diff --git a/src/bank.rs b/src/bank.rs index 8b366cf7b6..2d1ec5cf47 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -536,12 +536,15 @@ impl Bank { // Call the contract method // It's up to the contract to implement its own rules on moving funds if SystemProgram::check_id(&tx_program_id) { - SystemProgram::process_transaction( + if SystemProgram::process_transaction( &tx, instruction_index, program_accounts, &self.loaded_contracts, - ) + ).is_err() + { + return Err(BankError::ProgramRuntimeError(instruction_index as u8)); + } } else if BudgetState::check_id(&tx_program_id) { if BudgetState::process_transaction(&tx, instruction_index, program_accounts).is_err() { return Err(BankError::ProgramRuntimeError(instruction_index as u8)); diff --git a/src/system_program.rs b/src/system_program.rs index f7176d741e..5d94959c80 100644 --- a/src/system_program.rs +++ b/src/system_program.rs @@ -4,10 +4,24 @@ use bincode::deserialize; use dynamic_program::DynamicProgram; use solana_program_interface::account::Account; use solana_program_interface::pubkey::Pubkey; +use std; use std::collections::HashMap; use std::sync::RwLock; use transaction::Transaction; +#[derive(Debug)] +pub enum Error { + InvalidArgument, +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "error") + } +} +impl std::error::Error for Error {} + +pub type Result = std::result::Result; + #[derive(Serialize, Deserialize, Debug, Clone)] pub enum SystemProgram { /// Create a new account @@ -52,7 +66,7 @@ impl SystemProgram { pix: usize, accounts: &mut [&mut Account], loaded_programs: &RwLock>, - ) { + ) -> Result<()> { if let Ok(syscall) = deserialize(tx.userdata(pix)) { trace!("process_transaction: {:?}", syscall); match syscall { @@ -62,13 +76,13 @@ impl SystemProgram { program_id, } => { if !Self::check_id(&accounts[0].program_id) { - return; + Err(Error::InvalidArgument)?; } if space > 0 && (!accounts[1].userdata.is_empty() || !Self::check_id(&accounts[1].program_id)) { - return; + Err(Error::InvalidArgument)?; } accounts[0].tokens -= tokens; accounts[1].tokens += tokens; @@ -77,7 +91,7 @@ impl SystemProgram { } SystemProgram::Assign { program_id } => { if !Self::check_id(&accounts[0].program_id) { - return; + Err(Error::InvalidArgument)?; } accounts[0].program_id = program_id; } @@ -91,8 +105,10 @@ impl SystemProgram { hashmap.insert(program_id, DynamicProgram::new_native(name)); } } + Ok(()) } else { info!("Invalid transaction userdata: {:?}", tx.userdata(pix)); + Err(Error::InvalidArgument) } } } @@ -113,10 +129,11 @@ mod test { tx: &Transaction, accounts: &mut [Account], loaded_programs: &RwLock>, - ) { + ) -> Result<()> { let mut refs: Vec<&mut Account> = accounts.iter_mut().collect(); SystemProgram::process_transaction(&tx, 0, &mut refs[..], loaded_programs) } + #[test] fn test_create_noop() { let from = Keypair::new(); @@ -124,7 +141,7 @@ mod test { let mut accounts = vec![Account::default(), Account::default()]; let tx = Transaction::system_new(&from, to.pubkey(), 0, Hash::default()); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + process_transaction(&tx, &mut accounts, &hash).unwrap(); assert_eq!(accounts[0].tokens, 0); assert_eq!(accounts[1].tokens, 0); } @@ -136,7 +153,7 @@ mod test { accounts[0].tokens = 1; let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default()); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + process_transaction(&tx, &mut accounts, &hash).unwrap(); assert_eq!(accounts[0].tokens, 0); assert_eq!(accounts[1].tokens, 1); } @@ -149,7 +166,7 @@ mod test { accounts[0].program_id = from.pubkey(); let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default()); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + assert!(process_transaction(&tx, &mut accounts, &hash).is_err()); assert_eq!(accounts[0].tokens, 1); assert_eq!(accounts[1].tokens, 0); } @@ -161,7 +178,7 @@ mod test { let tx = Transaction::system_create(&from, to.pubkey(), Hash::default(), 0, 1, to.pubkey(), 0); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + process_transaction(&tx, &mut accounts, &hash).unwrap(); assert!(accounts[0].userdata.is_empty()); assert_eq!(accounts[1].userdata.len(), 1); assert_eq!(accounts[1].program_id, to.pubkey()); @@ -182,7 +199,7 @@ mod test { 0, ); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + assert!(process_transaction(&tx, &mut accounts, &hash).is_err()); assert!(accounts[1].userdata.is_empty()); } #[test] @@ -201,7 +218,7 @@ mod test { 0, ); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + assert!(process_transaction(&tx, &mut accounts, &hash).is_err()); assert!(accounts[1].userdata.is_empty()); } #[test] @@ -220,7 +237,7 @@ mod test { 0, ); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + assert!(process_transaction(&tx, &mut accounts, &hash).is_err()); assert_eq!(accounts[1].userdata.len(), 3); } #[test] @@ -230,7 +247,7 @@ mod test { let mut accounts = vec![Account::default()]; let tx = Transaction::system_assign(&from, Hash::default(), program.pubkey(), 0); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + process_transaction(&tx, &mut accounts, &hash).unwrap(); assert_eq!(accounts[0].program_id, program.pubkey()); } #[test] @@ -241,7 +258,7 @@ mod test { accounts[0].tokens = 1; let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default()); let hash = RwLock::new(HashMap::new()); - process_transaction(&tx, &mut accounts, &hash); + process_transaction(&tx, &mut accounts, &hash).unwrap(); assert_eq!(accounts[0].tokens, 0); assert_eq!(accounts[1].tokens, 1); } diff --git a/tests/programs.rs b/tests/programs.rs index e5e62bbc46..54efa63463 100644 --- a/tests/programs.rs +++ b/tests/programs.rs @@ -236,7 +236,7 @@ fn process_transaction( loaded_programs: &RwLock>, ) { let mut refs: Vec<&mut Account> = accounts.iter_mut().collect(); - SystemProgram::process_transaction(&tx, 0, &mut refs[..], loaded_programs) + SystemProgram::process_transaction(&tx, 0, &mut refs[..], loaded_programs).unwrap(); } #[test]