From 81c82b5af9fb1c87e2c0b009d5465f85ee7a330d Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Thu, 24 Jan 2019 13:37:12 -0800 Subject: [PATCH] Add test for ignore ProgramErrors in process_entries (#2544) --- src/bank.rs | 57 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/bank.rs b/src/bank.rs index 0020dce7f8..6da5afad20 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -452,7 +452,11 @@ impl Bank { .iter() .zip(txs.iter()) .filter_map(|(r, x)| match r { - Ok(_) | Err(BankError::ProgramError(_, _)) => Some(x.clone()), + Ok(_) => Some(x.clone()), + Err(BankError::ProgramError(index, err)) => { + info!("program error {:?}, {:?}", index, err); + Some(x.clone()) + } Err(ref e) => { debug!("process transaction failed {:?}", e); None @@ -655,6 +659,22 @@ impl Bank { Ok(()) } + fn ignore_program_errors(results: Vec>) -> Vec> { + results + .into_iter() + .map(|result| match result { + // Entries that result in a ProgramError are still valid and are written in the + // ledger so map them to an ok return value + Err(BankError::ProgramError(index, err)) => { + info!("program error {:?}, {:?}", index, err); + inc_new_counter_info!("bank-ignore_program_err", 1); + Ok(()) + } + _ => result, + }) + .collect() + } + fn par_execute_entries(&self, entries: &[(&Entry, Vec>)]) -> Result<()> { inc_new_counter_info!("bank-par_execute_entries-count", entries.len()); let results: Vec> = entries @@ -665,17 +685,7 @@ impl Bank { lock_results.to_vec(), MAX_ENTRY_IDS, ); - let mut results = Vec::new(); - results.reserve(old_results.len()); - results = old_results - .into_iter() - .map(|result| match result { - // Entries that result in a ProgramError are still valid and are written in the - // ledger so map them to an ok return value - Err(BankError::ProgramError(_, _)) => Ok(()), - _ => result, - }) - .collect(); + let results = Bank::ignore_program_errors(old_results); self.unlock_accounts(&e.transactions, &results); Self::first_err(&results) }) @@ -1868,6 +1878,29 @@ mod tests { assert_eq!(entries[0].transactions.len(), transactions.len() - 1); } + #[test] + fn test_bank_ignore_program_errors() { + let expected_results = vec![Ok(()), Ok(())]; + let results = vec![Ok(()), Ok(())]; + let updated_results = Bank::ignore_program_errors(results); + assert_eq!(updated_results, expected_results); + + let results = vec![ + Err(BankError::ProgramError( + 1, + ProgramError::ResultWithNegativeTokens, + )), + Ok(()), + ]; + let updated_results = Bank::ignore_program_errors(results); + assert_eq!(updated_results, expected_results); + + // Other BankErrors should not be ignored + let results = vec![Err(BankError::AccountNotFound), Ok(())]; + let updated_results = Bank::ignore_program_errors(results); + assert_ne!(updated_results, expected_results); + } + #[test] fn test_bank_storage() { solana_logger::setup();