From 505f77b10874ad386bc129d70afd6ad3bca0e0d7 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 7 Mar 2019 10:35:28 -0700 Subject: [PATCH] Move a more generic process_transaction to runtime.rs --- programs/budget/src/budget_program.rs | 19 ++-------------- runtime/src/runtime.rs | 31 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/programs/budget/src/budget_program.rs b/programs/budget/src/budget_program.rs index 7d96bdb4f..177d639ed 100644 --- a/programs/budget/src/budget_program.rs +++ b/programs/budget/src/budget_program.rs @@ -177,24 +177,9 @@ mod test { tx: &Transaction, tx_accounts: &mut [Account], ) -> Result<(), BudgetError> { - for ix in &tx.instructions { - let mut ix_accounts = runtime::get_subset_unchecked_mut(tx_accounts, &ix.accounts); - let mut keyed_accounts: Vec<_> = ix - .accounts - .iter() - .map(|&index| { - let index = index as usize; - let key = &tx.account_keys[index]; - (key, index < tx.signatures.len()) - }) - .zip(ix_accounts.iter_mut()) - .map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account)) - .collect(); - - process_instruction(&mut keyed_accounts, &ix.userdata)?; - } - Ok(()) + runtime::process_transaction(tx, tx_accounts, process_instruction) } + #[test] fn test_invalid_instruction() { let mut accounts = vec![Account::new(1, 0, id()), Account::new(0, 512, id())]; diff --git a/runtime/src/runtime.rs b/runtime/src/runtime.rs index 26b706109..2ef8f9216 100644 --- a/runtime/src/runtime.rs +++ b/runtime/src/runtime.rs @@ -143,7 +143,7 @@ pub fn has_duplicates(xs: &[T]) -> bool { } /// Get mut references to a subset of elements. -pub fn get_subset_unchecked_mut<'a, T>(xs: &'a mut [T], indexes: &[u8]) -> Vec<&'a mut T> { +fn get_subset_unchecked_mut<'a, T>(xs: &'a mut [T], indexes: &[u8]) -> Vec<&'a mut T> { // Since the compiler doesn't know the indexes are unique, dereferencing // multiple mut elements is assumed to be unsafe. If, however, all // indexes are unique, it's perfectly safe. The returned elements will share @@ -188,6 +188,35 @@ pub fn execute_transaction( Ok(()) } +/// A utility function for unit-tests. Same as execute_transaction(), but bypasses the loaders +/// for easier usage and better stack traces. +pub fn process_transaction( + tx: &Transaction, + tx_accounts: &mut [Account], + process_instruction: F, +) -> Result<(), E> +where + F: Fn(&mut [KeyedAccount], &[u8]) -> Result<(), E>, +{ + for ix in &tx.instructions { + let mut ix_accounts = get_subset_unchecked_mut(tx_accounts, &ix.accounts); + let mut keyed_accounts: Vec<_> = ix + .accounts + .iter() + .map(|&index| { + let index = index as usize; + let key = &tx.account_keys[index]; + (key, index < tx.signatures.len()) + }) + .zip(ix_accounts.iter_mut()) + .map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account)) + .collect(); + + process_instruction(&mut keyed_accounts, &ix.userdata)?; + } + Ok(()) +} + #[cfg(test)] mod tests { use super::*;