From 0cd57addcf4ae242e0d068d09fc0359a4249a5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Fri, 7 Apr 2023 12:53:19 +0200 Subject: [PATCH] Cleanup - mock_process_instruction() (#31088) * Uses declare_process_instruction!() in all tests. * Adds post_adjustments to mock_process_instruction(). Removes "solana_sbf_rust_external_spend" from assert_instruction_count() as it panics. --- program-runtime/src/invoke_context.rs | 209 ++++++++-------- .../address-lookup-table/src/processor.rs | 7 +- programs/bpf_loader/src/lib.rs | 3 + programs/compute-budget/src/lib.rs | 16 +- programs/config/src/config_processor.rs | 10 +- programs/loader-v3/src/lib.rs | 1 + programs/sbf/tests/programs.rs | 48 ++-- programs/stake/src/stake_instruction.rs | 20 +- programs/vote/src/vote_processor.rs | 11 +- programs/zk-token-proof/src/lib.rs | 7 +- runtime/src/bank/tests.rs | 223 ++++++------------ runtime/src/message_processor.rs | 41 ++-- runtime/src/system_instruction_processor.rs | 79 ++----- 13 files changed, 252 insertions(+), 423 deletions(-) diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 25c172c20b..9a124167bf 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -41,13 +41,18 @@ use { /// Adapter so we can unify the interfaces of built-in programs and syscalls #[macro_export] macro_rules! declare_process_instruction { - ($cu_to_consume:expr) => { - pub fn process_instruction( - invoke_context: &mut InvokeContext, - ) -> Result<(), Box> { + ($process_instruction:ident, $cu_to_consume:expr, |$invoke_context:ident| $inner:tt) => { + pub fn $process_instruction( + invoke_context: &mut $crate::invoke_context::InvokeContext, + ) -> std::result::Result<(), Box> { + fn process_instruction_inner( + $invoke_context: &mut $crate::invoke_context::InvokeContext, + ) -> std::result::Result<(), solana_sdk::instruction::InstructionError> { + $inner + } if invoke_context .feature_set - .is_active(&feature_set::native_programs_consume_cu::id()) + .is_active(&solana_sdk::feature_set::native_programs_consume_cu::id()) { invoke_context.consume_checked($cu_to_consume)?; } @@ -919,7 +924,7 @@ macro_rules! with_mock_invoke_context { }; } -pub fn mock_process_instruction( +pub fn mock_process_instruction( loader_id: &Pubkey, mut program_indices: Vec, instruction_data: &[u8], @@ -928,6 +933,7 @@ pub fn mock_process_instruction( expected_result: Result<(), InstructionError>, process_instruction: ProcessInstructionWithContext, mut pre_adjustments: F, + mut post_adjustments: G, ) -> Vec { let mut instruction_accounts: Vec = Vec::with_capacity(instruction_account_metas.len()); @@ -971,6 +977,7 @@ pub fn mock_process_instruction( &mut ExecuteTimings::default(), ); assert_eq!(result, expected_result); + post_adjustments(&mut invoke_context); let mut transaction_accounts = transaction_context.deconstruct_without_keys().unwrap(); transaction_accounts.pop(); transaction_accounts @@ -1030,105 +1037,105 @@ mod tests { const MOCK_BUILTIN_COMPUTE_UNIT_COST: u64 = 1; - #[allow(clippy::integer_arithmetic)] - fn mock_process_instruction( - invoke_context: &mut InvokeContext, - ) -> Result<(), Box> { - let transaction_context = &invoke_context.transaction_context; - let instruction_context = transaction_context.get_current_instruction_context()?; - let instruction_data = instruction_context.get_instruction_data(); - let program_id = instruction_context.get_last_program_key(transaction_context)?; - // mock builtin must consume units - invoke_context.consume_checked(MOCK_BUILTIN_COMPUTE_UNIT_COST)?; - let instruction_accounts = (0..4) - .map(|instruction_account_index| InstructionAccount { - index_in_transaction: instruction_account_index, - index_in_caller: instruction_account_index, - index_in_callee: instruction_account_index, - is_signer: false, - is_writable: false, - }) - .collect::>(); - assert_eq!( - program_id, - instruction_context - .try_borrow_instruction_account(transaction_context, 0)? - .get_owner() - ); - assert_ne!( - instruction_context - .try_borrow_instruction_account(transaction_context, 1)? - .get_owner(), - instruction_context - .try_borrow_instruction_account(transaction_context, 0)? - .get_key() - ); - - if let Ok(instruction) = bincode::deserialize(instruction_data) { - match instruction { - MockInstruction::NoopSuccess => (), - MockInstruction::NoopFail => return Err(Box::new(InstructionError::GenericError)), - MockInstruction::ModifyOwned => instruction_context + declare_process_instruction!( + process_instruction, + MOCK_BUILTIN_COMPUTE_UNIT_COST, + |invoke_context| { + let transaction_context = &invoke_context.transaction_context; + let instruction_context = transaction_context.get_current_instruction_context()?; + let instruction_data = instruction_context.get_instruction_data(); + let program_id = instruction_context.get_last_program_key(transaction_context)?; + let instruction_accounts = (0..4) + .map(|instruction_account_index| InstructionAccount { + index_in_transaction: instruction_account_index, + index_in_caller: instruction_account_index, + index_in_callee: instruction_account_index, + is_signer: false, + is_writable: false, + }) + .collect::>(); + assert_eq!( + program_id, + instruction_context .try_borrow_instruction_account(transaction_context, 0)? - .set_data_from_slice(&[1])?, - MockInstruction::ModifyNotOwned => instruction_context + .get_owner() + ); + assert_ne!( + instruction_context .try_borrow_instruction_account(transaction_context, 1)? - .set_data_from_slice(&[1])?, - MockInstruction::ModifyReadonly => instruction_context - .try_borrow_instruction_account(transaction_context, 2)? - .set_data_from_slice(&[1])?, - MockInstruction::UnbalancedPush => { - instruction_context + .get_owner(), + instruction_context + .try_borrow_instruction_account(transaction_context, 0)? + .get_key() + ); + + if let Ok(instruction) = bincode::deserialize(instruction_data) { + match instruction { + MockInstruction::NoopSuccess => (), + MockInstruction::NoopFail => return Err(InstructionError::GenericError), + MockInstruction::ModifyOwned => instruction_context .try_borrow_instruction_account(transaction_context, 0)? - .checked_add_lamports(1)?; - let program_id = *transaction_context.get_key_of_account_at_index(3)?; - let metas = vec![ - AccountMeta::new_readonly( - *transaction_context.get_key_of_account_at_index(0)?, - false, - ), - AccountMeta::new_readonly( - *transaction_context.get_key_of_account_at_index(1)?, - false, - ), - ]; - let inner_instruction = Instruction::new_with_bincode( - program_id, - &MockInstruction::NoopSuccess, - metas, - ); - invoke_context - .transaction_context - .get_next_instruction_context() - .unwrap() - .configure(&[3], &instruction_accounts, &[]); - let result = invoke_context.push(); - assert_eq!(result, Err(InstructionError::UnbalancedInstruction)); - result?; - invoke_context - .native_invoke(inner_instruction.into(), &[]) - .and(invoke_context.pop())?; + .set_data_from_slice(&[1])?, + MockInstruction::ModifyNotOwned => instruction_context + .try_borrow_instruction_account(transaction_context, 1)? + .set_data_from_slice(&[1])?, + MockInstruction::ModifyReadonly => instruction_context + .try_borrow_instruction_account(transaction_context, 2)? + .set_data_from_slice(&[1])?, + MockInstruction::UnbalancedPush => { + instruction_context + .try_borrow_instruction_account(transaction_context, 0)? + .checked_add_lamports(1)?; + let program_id = *transaction_context.get_key_of_account_at_index(3)?; + let metas = vec![ + AccountMeta::new_readonly( + *transaction_context.get_key_of_account_at_index(0)?, + false, + ), + AccountMeta::new_readonly( + *transaction_context.get_key_of_account_at_index(1)?, + false, + ), + ]; + let inner_instruction = Instruction::new_with_bincode( + program_id, + &MockInstruction::NoopSuccess, + metas, + ); + invoke_context + .transaction_context + .get_next_instruction_context() + .unwrap() + .configure(&[3], &instruction_accounts, &[]); + let result = invoke_context.push(); + assert_eq!(result, Err(InstructionError::UnbalancedInstruction)); + result?; + invoke_context + .native_invoke(inner_instruction.into(), &[]) + .and(invoke_context.pop())?; + } + MockInstruction::UnbalancedPop => instruction_context + .try_borrow_instruction_account(transaction_context, 0)? + .checked_add_lamports(1)?, + MockInstruction::ConsumeComputeUnits { + compute_units_to_consume, + desired_result, + } => { + invoke_context + .consume_checked(compute_units_to_consume) + .map_err(|_| InstructionError::ComputationalBudgetExceeded)?; + return desired_result; + } + MockInstruction::Resize { new_len } => instruction_context + .try_borrow_instruction_account(transaction_context, 0)? + .set_data(vec![0; new_len as usize])?, } - MockInstruction::UnbalancedPop => instruction_context - .try_borrow_instruction_account(transaction_context, 0)? - .checked_add_lamports(1)?, - MockInstruction::ConsumeComputeUnits { - compute_units_to_consume, - desired_result, - } => { - invoke_context.consume_checked(compute_units_to_consume)?; - return desired_result - .map_err(|err| Box::new(err) as Box); - } - MockInstruction::Resize { new_len } => instruction_context - .try_borrow_instruction_account(transaction_context, 0)? - .set_data(vec![0; new_len as usize])?, + } else { + return Err(InstructionError::InvalidInstructionData); } - } else { - return Err(Box::new(InstructionError::InvalidInstructionData)); + Ok(()) } - Ok(()) - } + ); #[test] fn test_instruction_stack_height() { @@ -1236,7 +1243,7 @@ mod tests { with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); let builtin_programs = &[BuiltinProgram { program_id: callee_program_id, - process_instruction: mock_process_instruction, + process_instruction, }]; invoke_context.builtin_programs = builtin_programs; @@ -1381,7 +1388,7 @@ mod tests { with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); let builtin_programs = &[BuiltinProgram { program_id: program_key, - process_instruction: mock_process_instruction, + process_instruction, }]; invoke_context.builtin_programs = builtin_programs; diff --git a/programs/address-lookup-table/src/processor.rs b/programs/address-lookup-table/src/processor.rs index 5103398d96..6e8fd96a43 100644 --- a/programs/address-lookup-table/src/processor.rs +++ b/programs/address-lookup-table/src/processor.rs @@ -18,10 +18,7 @@ use { std::convert::TryFrom, }; -declare_process_instruction!(750); -pub fn process_instruction_inner( - invoke_context: &mut InvokeContext, -) -> Result<(), InstructionError> { +declare_process_instruction!(process_instruction, 750, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); @@ -39,7 +36,7 @@ pub fn process_instruction_inner( } ProgramInstruction::CloseLookupTable => Processor::close_lookup_table(invoke_context), } -} +}); fn checked_add(a: usize, b: usize) -> Result { a.checked_add(b).ok_or(InstructionError::ArithmeticOverflow) diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 2855bcae03..6a259ee641 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -1696,6 +1696,7 @@ mod tests { expected_result, super::process_instruction, |_invoke_context| {}, + |_invoke_context| {}, ) } @@ -1982,6 +1983,7 @@ mod tests { |invoke_context| { invoke_context.mock_set_remaining(0); }, + |_invoke_context| {}, ); // Case: Account not a program @@ -2524,6 +2526,7 @@ mod tests { expected_result, super::process_instruction, |_invoke_context| {}, + |_invoke_context| {}, ) } diff --git a/programs/compute-budget/src/lib.rs b/programs/compute-budget/src/lib.rs index a12a41c0f6..8fe6cbcd85 100644 --- a/programs/compute-budget/src/lib.rs +++ b/programs/compute-budget/src/lib.rs @@ -1,16 +1,6 @@ -use {solana_program_runtime::invoke_context::InvokeContext, solana_sdk::feature_set}; - -pub fn process_instruction( - invoke_context: &mut InvokeContext, -) -> Result<(), Box> { - // Consume compute units if feature `native_programs_consume_cu` is activated, - if invoke_context - .feature_set - .is_active(&feature_set::native_programs_consume_cu::id()) - { - invoke_context.consume_checked(150)?; - } +use solana_program_runtime::declare_process_instruction; +declare_process_instruction!(process_instruction, 150, |_invoke_context| { // Do nothing, compute budget instructions handled by the runtime Ok(()) -} +}); diff --git a/programs/config/src/config_processor.rs b/programs/config/src/config_processor.rs index 5de1d79a26..1431b314ad 100644 --- a/programs/config/src/config_processor.rs +++ b/programs/config/src/config_processor.rs @@ -3,7 +3,7 @@ use { crate::ConfigKeys, bincode::deserialize, - solana_program_runtime::{declare_process_instruction, ic_msg, invoke_context::InvokeContext}, + solana_program_runtime::{declare_process_instruction, ic_msg}, solana_sdk::{ feature_set, instruction::InstructionError, program_utils::limited_deserialize, pubkey::Pubkey, transaction_context::IndexOfAccount, @@ -11,10 +11,7 @@ use { std::collections::BTreeSet, }; -declare_process_instruction!(450); -pub fn process_instruction_inner( - invoke_context: &mut InvokeContext, -) -> Result<(), InstructionError> { +declare_process_instruction!(process_instruction, 450, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let data = instruction_context.get_instruction_data(); @@ -134,7 +131,7 @@ pub fn process_instruction_inner( } config_account.get_data_mut()?[..data.len()].copy_from_slice(data); Ok(()) -} +}); #[cfg(test)] mod tests { @@ -168,6 +165,7 @@ mod tests { expected_result, super::process_instruction, |_invoke_context| {}, + |_invoke_context| {}, ) } diff --git a/programs/loader-v3/src/lib.rs b/programs/loader-v3/src/lib.rs index 35513977cf..a4c5928871 100644 --- a/programs/loader-v3/src/lib.rs +++ b/programs/loader-v3/src/lib.rs @@ -655,6 +655,7 @@ mod tests { expected_result, super::process_instruction, |_invoke_context| {}, + |_invoke_context| {}, ) } diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index a0604789b1..a06363a947 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -19,9 +19,7 @@ use { parse_bpf_upgradeable_loader, BpfUpgradeableLoaderAccountType, }, solana_ledger::token_balances::collect_token_balances, - solana_program_runtime::{ - compute_budget::ComputeBudget, invoke_context::InvokeContext, timings::ExecuteTimings, - }, + solana_program_runtime::{compute_budget::ComputeBudget, timings::ExecuteTimings}, solana_rbpf::vm::ContextObject, solana_runtime::{ bank::{ @@ -86,7 +84,7 @@ use { system_program, transaction::{SanitizedTransaction, Transaction, TransactionError}, }, - std::{str::FromStr, sync::Arc, time::Duration}, + std::{cell::RefCell, str::FromStr, sync::Arc, time::Duration}, }; #[cfg(feature = "sbf_rust")] @@ -1370,8 +1368,8 @@ fn assert_instruction_count() { ("noop++", 5), ("relative_call", 210), ("return_data", 980), - ("sanity", 3259), - ("sanity++", 3159), + ("sanity", 2377), + ("sanity++", 2277), ("secp256k1_recover", 25383), ("sha", 1355), ("struct_pass", 108), @@ -1385,7 +1383,6 @@ fn assert_instruction_count() { ("solana_sbf_rust_alloc", 5067), ("solana_sbf_rust_custom_heap", 398), ("solana_sbf_rust_dep_crate", 2), - ("solana_sbf_rust_external_spend", 288), ("solana_sbf_rust_iter", 1013), ("solana_sbf_rust_many_args", 1289), ("solana_sbf_rust_mem", 2067), @@ -1393,7 +1390,7 @@ fn assert_instruction_count() { ("solana_sbf_rust_noop", 275), ("solana_sbf_rust_param_passing", 146), ("solana_sbf_rust_rand", 378), - ("solana_sbf_rust_sanity", 10759), + ("solana_sbf_rust_sanity", 51931), ("solana_sbf_rust_secp256k1_recover", 91185), ("solana_sbf_rust_sha", 24059), ]); @@ -1407,7 +1404,7 @@ fn assert_instruction_count() { (program_key, AccountSharedData::new(0, 0, &loader_id)), ( Pubkey::new_unique(), - AccountSharedData::new(0, 8, &program_key), + AccountSharedData::new(0, 0, &program_key), ), ]; let instruction_accounts = vec![AccountMeta { @@ -1419,11 +1416,8 @@ fn assert_instruction_count() { .1 .set_data_from_slice(&load_program_from_file(program_name)); transaction_accounts[0].1.set_executable(true); - transaction_accounts[1] - .1 - .set_state(expected_consumption) - .unwrap(); + let prev_compute_meter = RefCell::new(0); print!(" {:36} {:8}", program_name, *expected_consumption); mock_process_instruction( &loader_id, @@ -1432,29 +1426,23 @@ fn assert_instruction_count() { transaction_accounts, instruction_accounts, Ok(()), - |invoke_context: &mut InvokeContext| { - let expected_consumption: u64 = invoke_context - .transaction_context - .get_current_instruction_context() - .unwrap() - .try_borrow_instruction_account(&invoke_context.transaction_context, 0) - .unwrap() - .get_state() - .unwrap(); - let prev_compute_meter = invoke_context.get_remaining(); - let _result = solana_bpf_loader_program::process_instruction(invoke_context); - let consumption = prev_compute_meter.saturating_sub(invoke_context.get_remaining()); - let diff: i64 = consumption as i64 - expected_consumption as i64; + solana_bpf_loader_program::process_instruction, + |invoke_context| { + *prev_compute_meter.borrow_mut() = invoke_context.get_remaining(); + }, + |invoke_context| { + let consumption = prev_compute_meter + .borrow() + .saturating_sub(invoke_context.get_remaining()); + let diff: i64 = consumption as i64 - *expected_consumption as i64; println!( "{:6} {:+5} ({:+3.0}%)", consumption, diff, - 100.0_f64 * consumption as f64 / expected_consumption as f64 - 100.0_f64, + 100.0_f64 * consumption as f64 / *expected_consumption as f64 - 100.0_f64, ); - assert_eq!(consumption, expected_consumption); - Ok(()) + assert_eq!(consumption, *expected_consumption); }, - |_invoke_context| {}, ); } } diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 602ca21fb2..f9c7e87d27 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -8,8 +8,7 @@ use { }, log::*, solana_program_runtime::{ - declare_process_instruction, invoke_context::InvokeContext, - sysvar_cache::get_sysvar_with_account_check, + declare_process_instruction, sysvar_cache::get_sysvar_with_account_check, }, solana_sdk::{ clock::Clock, @@ -52,10 +51,7 @@ fn get_optional_pubkey<'a>( ) } -declare_process_instruction!(750); -pub fn process_instruction_inner( - invoke_context: &mut InvokeContext, -) -> Result<(), InstructionError> { +declare_process_instruction!(process_instruction, 750, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let data = instruction_context.get_instruction_data(); @@ -479,7 +475,7 @@ pub fn process_instruction_inner( Err(err) } } -} +}); #[cfg(test)] mod tests { @@ -595,6 +591,7 @@ mod tests { |invoke_context| { invoke_context.feature_set = Arc::clone(&feature_set); }, + |_invoke_context| {}, ) } @@ -6344,17 +6341,16 @@ mod tests { transaction_accounts, instruction_accounts, Ok(()), + super::process_instruction, + |invoke_context| { + invoke_context.feature_set = Arc::clone(&feature_set); + }, |invoke_context| { - super::process_instruction(invoke_context)?; let expected_minimum_delegation = crate::get_minimum_delegation(&invoke_context.feature_set).to_le_bytes(); let actual_minimum_delegation = invoke_context.transaction_context.get_return_data().1; assert_eq!(expected_minimum_delegation, actual_minimum_delegation); - Ok(()) - }, - |invoke_context| { - invoke_context.feature_set = Arc::clone(&feature_set); }, ); } diff --git a/programs/vote/src/vote_processor.rs b/programs/vote/src/vote_processor.rs index c13a800db5..b9a2684771 100644 --- a/programs/vote/src/vote_processor.rs +++ b/programs/vote/src/vote_processor.rs @@ -56,12 +56,9 @@ fn process_authorize_with_seed_instruction( ) } -// Citing `runtime/src/block_cost_limit.rs`, vote has statically defined 2_100 +// Citing `runtime/src/block_cost_limit.rs`, vote has statically defined 2100 // units; can consume based on instructions in the future like `bpf_loader` does. -declare_process_instruction!(2_100); -pub fn process_instruction_inner( - invoke_context: &mut InvokeContext, -) -> Result<(), InstructionError> { +declare_process_instruction!(process_instruction, 2100, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let data = instruction_context.get_instruction_data(); @@ -260,7 +257,7 @@ pub fn process_instruction_inner( } } } -} +}); #[cfg(test)] mod tests { @@ -325,6 +322,7 @@ mod tests { expected_result, super::process_instruction, |_invoke_context| {}, + |_invoke_context| {}, ) } @@ -345,6 +343,7 @@ mod tests { |invoke_context| { invoke_context.feature_set = std::sync::Arc::new(FeatureSet::default()); }, + |_invoke_context| {}, ) } diff --git a/programs/zk-token-proof/src/lib.rs b/programs/zk-token-proof/src/lib.rs index e6e5a91613..786113a0d2 100644 --- a/programs/zk-token-proof/src/lib.rs +++ b/programs/zk-token-proof/src/lib.rs @@ -114,10 +114,7 @@ fn process_close_proof_context(invoke_context: &mut InvokeContext) -> Result<(), Ok(()) } -declare_process_instruction!(0); -pub fn process_instruction_inner( - invoke_context: &mut InvokeContext, -) -> Result<(), InstructionError> { +declare_process_instruction!(process_instruction, 0, |invoke_context| { if invoke_context.get_stack_height() != TRANSACTION_LEVEL_STACK_HEIGHT { // Not supported as an inner instruction return Err(InstructionError::UnsupportedProgramId); @@ -195,4 +192,4 @@ pub fn process_instruction_inner( process_verify_proof::(invoke_context) } } -} +}); diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index c8166e5a73..89e84049ec 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -34,8 +34,9 @@ use { solana_logger, solana_program_runtime::{ compute_budget::{self, ComputeBudget, MAX_COMPUTE_UNIT_LIMIT}, + declare_process_instruction, executor_cache::TransactionExecutorCache, - invoke_context::{mock_process_instruction, InvokeContext}, + invoke_context::mock_process_instruction, loaded_programs::{LoadedProgram, LoadedProgramType}, prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType}, timings::ExecuteTimings, @@ -107,7 +108,6 @@ use { fs::File, io::Read, rc::Rc, - result, str::FromStr, sync::{ atomic::{ @@ -752,6 +752,11 @@ fn assert_capitalization_diff( } } +declare_process_instruction!(process_instruction, 1, |_invoke_context| { + // Default for all tests which don't bring their own processor + Ok(()) +}); + #[test] fn test_store_account_and_update_capitalization_missing() { let bank = create_simple_test_bank(0); @@ -1340,9 +1345,7 @@ fn test_rent_complex() { Deduction, } - fn mock_process_instruction( - invoke_context: &mut InvokeContext, - ) -> result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); @@ -1359,9 +1362,9 @@ fn test_rent_complex() { } } } else { - Err(Box::new(InstructionError::InvalidInstructionData)) + Err(InstructionError::InvalidInstructionData) } - } + }); let (mut genesis_config, _mint_keypair) = create_genesis_config(10); let mut keypairs: Vec = Vec::with_capacity(14); @@ -1377,7 +1380,7 @@ fn test_rent_complex() { root_bank.restore_old_behavior_for_fragile_tests(); let root_bank = Arc::new(root_bank); let mut bank = create_child_bank_for_rent_test(&root_bank, &genesis_config); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin("mock_program", &mock_program_id, process_instruction); assert_eq!(bank.last_blockhash(), genesis_config.hash()); @@ -5070,23 +5073,21 @@ fn test_add_builtin() { fn mock_vote_program_id() -> Pubkey { Pubkey::from([42u8; 32]) } - fn mock_vote_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let program_id = instruction_context.get_last_program_key(transaction_context)?; if mock_vote_program_id() != *program_id { - return Err(Box::new(InstructionError::IncorrectProgramId)); + return Err(InstructionError::IncorrectProgramId); } - Err(Box::new(InstructionError::Custom(42))) - } + Err(InstructionError::Custom(42)) + }); assert!(bank.get_account(&mock_vote_program_id()).is_none()); bank.add_builtin( "mock_vote_program", &mock_vote_program_id(), - mock_vote_processor, + process_instruction, ); assert!(bank.get_account(&mock_vote_program_id()).is_some()); @@ -5128,13 +5129,9 @@ fn test_add_duplicate_static_program() { } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0); let mut bank = Bank::new_for_tests(&genesis_config); - fn mock_vote_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { - // mock builtin must consume units - invoke_context.consume_checked(1)?; - Err(Box::new(InstructionError::Custom(42))) - } + declare_process_instruction!(process_instruction, 1, |_invoke_context| { + Err(InstructionError::Custom(42)) + }); let mock_account = Keypair::new(); let mock_validator_identity = Keypair::new(); @@ -5159,7 +5156,7 @@ fn test_add_duplicate_static_program() { bank.add_builtin( "solana_vote_program", &solana_vote_program::id(), - mock_vote_processor, + process_instruction, ); let new_vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap(); // Vote loader account should not be updated since it was included in the genesis config. @@ -5178,13 +5175,9 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() { for pass in 0..5 { let mut bank = create_simple_test_bank(500); - fn mock_ix_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { - // mock builtin must consume units - invoke_context.consume_checked(1)?; - Err(Box::new(InstructionError::Custom(42))) - } + declare_process_instruction!(process_instruction, 1, |_invoke_context| { + Err(InstructionError::Custom(42)) + }); // Non-builtin loader accounts can not be used for instruction processing { @@ -5215,8 +5208,8 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() { continue; } - bank.add_builtin("mock_program1", &vote_id, mock_ix_processor); - bank.add_builtin("mock_program2", &stake_id, mock_ix_processor); + bank.add_builtin("mock_program1", &vote_id, process_instruction); + bank.add_builtin("mock_program2", &stake_id, process_instruction); { let stakes = bank.stakes_cache.stakes(); assert!(stakes.vote_accounts().as_ref().is_empty()); @@ -5239,8 +5232,8 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() { // Re-adding builtin programs should be no-op bank.update_accounts_hash_for_tests(); let old_hash = bank.get_accounts_hash().unwrap(); - bank.add_builtin("mock_program1", &vote_id, mock_ix_processor); - bank.add_builtin("mock_program2", &stake_id, mock_ix_processor); + bank.add_builtin("mock_program1", &vote_id, process_instruction); + bank.add_builtin("mock_program2", &stake_id, process_instruction); add_root_and_flush_write_cache(&bank); bank.update_accounts_hash_for_tests(); let new_hash = bank.get_accounts_hash().unwrap(); @@ -6470,15 +6463,11 @@ fn test_transaction_with_duplicate_accounts_in_instruction() { let (genesis_config, mint_keypair) = create_genesis_config(500); let mut bank = Bank::new_for_tests(&genesis_config); - fn mock_process_instruction( - invoke_context: &mut InvokeContext, - ) -> result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); let lamports = u64::from_le_bytes(instruction_data.try_into().unwrap()); - // mock builtin must consume units - invoke_context.consume_checked(1)?; instruction_context .try_borrow_instruction_account(transaction_context, 2)? .checked_sub_lamports(lamports)?; @@ -6492,10 +6481,10 @@ fn test_transaction_with_duplicate_accounts_in_instruction() { .try_borrow_instruction_account(transaction_context, 1)? .checked_add_lamports(lamports)?; Ok(()) - } + }); let mock_program_id = Pubkey::from([2u8; 32]); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin("mock_program", &mock_program_id, process_instruction); let from_pubkey = solana_sdk::pubkey::new_rand(); let to_pubkey = solana_sdk::pubkey::new_rand(); @@ -6530,17 +6519,8 @@ fn test_transaction_with_program_ids_passed_to_programs() { let (genesis_config, mint_keypair) = create_genesis_config(500); let mut bank = Bank::new_for_tests(&genesis_config); - #[allow(clippy::unnecessary_wraps)] - fn mock_process_instruction( - invoke_context: &mut InvokeContext, - ) -> result::Result<(), Box> { - // mock builtin must consume units - invoke_context.consume_checked(1)?; - Ok(()) - } - let mock_program_id = Pubkey::from([2u8; 32]); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin("mock_program", &mock_program_id, process_instruction); let from_pubkey = solana_sdk::pubkey::new_rand(); let to_pubkey = solana_sdk::pubkey::new_rand(); @@ -6592,11 +6572,7 @@ fn test_account_ids_after_program_ids() { tx.message.account_keys.push(solana_sdk::pubkey::new_rand()); - bank.add_builtin( - "mock_vote", - &solana_vote_program::id(), - mock_ok_vote_processor, - ); + bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction); let result = bank.process_transaction(&tx); assert_eq!(result, Ok(())); let account = bank.get_account(&solana_vote_program::id()).unwrap(); @@ -6646,11 +6622,7 @@ fn test_duplicate_account_key() { AccountMeta::new(to_pubkey, false), ]; - bank.add_builtin( - "mock_vote", - &solana_vote_program::id(), - mock_ok_vote_processor, - ); + bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); let mut tx = Transaction::new_signed_with_payer( @@ -6679,11 +6651,7 @@ fn test_process_transaction_with_too_many_account_locks() { AccountMeta::new(to_pubkey, false), ]; - bank.add_builtin( - "mock_vote", - &solana_vote_program::id(), - mock_ok_vote_processor, - ); + bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); let mut tx = Transaction::new_signed_with_payer( @@ -6716,11 +6684,7 @@ fn test_program_id_as_payer() { AccountMeta::new(to_pubkey, false), ]; - bank.add_builtin( - "mock_vote", - &solana_vote_program::id(), - mock_ok_vote_processor, - ); + bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); let mut tx = Transaction::new_signed_with_payer( @@ -6750,15 +6714,6 @@ fn test_program_id_as_payer() { assert_eq!(result, Err(TransactionError::SanitizeFailure)); } -#[allow(clippy::unnecessary_wraps)] -fn mock_ok_vote_processor( - invoke_context: &mut InvokeContext, -) -> std::result::Result<(), Box> { - // mock builtin must consume units - invoke_context.consume_checked(1)?; - Ok(()) -} - #[test] fn test_ref_account_key_after_program_id() { let (genesis_config, mint_keypair) = create_genesis_config(500); @@ -6772,11 +6727,7 @@ fn test_ref_account_key_after_program_id() { AccountMeta::new(to_pubkey, false), ]; - bank.add_builtin( - "mock_vote", - &solana_vote_program::id(), - mock_ok_vote_processor, - ); + bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); let mut tx = Transaction::new_signed_with_payer( @@ -6807,7 +6758,7 @@ fn test_fuzz_instructions() { .map(|i| { let key = solana_sdk::pubkey::new_rand(); let name = format!("program{i:?}"); - bank.add_builtin(&name, &key, mock_ok_vote_processor); + bank.add_builtin(&name, &key, process_instruction); (key, name.as_bytes().to_vec()) }) .collect(); @@ -6999,23 +6950,21 @@ fn test_bank_hash_consistency() { #[test] fn test_same_program_id_uses_unqiue_executable_accounts() { - fn nested_processor( - invoke_context: &mut InvokeContext, - ) -> result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let _ = instruction_context .try_borrow_program_account(transaction_context, 1)? .checked_add_lamports(1); Ok(()) - } + }); let (genesis_config, mint_keypair) = create_genesis_config(50000); let mut bank = Bank::new_for_tests(&genesis_config); // Add a new program let program1_pubkey = solana_sdk::pubkey::new_rand(); - bank.add_builtin("program", &program1_pubkey, nested_processor); + bank.add_builtin("program", &program1_pubkey, process_instruction); // Add a new program owned by the first let program2_pubkey = solana_sdk::pubkey::new_rand(); @@ -7220,13 +7169,6 @@ fn test_shrink_candidate_slots_cached() { #[test] fn test_add_builtin_no_overwrite() { - #[allow(clippy::unnecessary_wraps)] - fn mock_ix_processor( - _invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { - Ok(()) - } - let slot = 123; let program_id = solana_sdk::pubkey::new_rand(); @@ -7239,25 +7181,18 @@ fn test_add_builtin_no_overwrite() { Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &program_id, mock_ix_processor); + .add_builtin("mock_program", &program_id, process_instruction); assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot); let mut bank = Arc::new(new_from_parent(&bank)); Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &program_id, mock_ix_processor); + .add_builtin("mock_program", &program_id, process_instruction); assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot); } #[test] fn test_add_builtin_loader_no_overwrite() { - #[allow(clippy::unnecessary_wraps)] - fn mock_ix_processor( - _context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { - Ok(()) - } - let slot = 123; let loader_id = solana_sdk::pubkey::new_rand(); @@ -7270,13 +7205,13 @@ fn test_add_builtin_loader_no_overwrite() { Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &loader_id, mock_ix_processor); + .add_builtin("mock_program", &loader_id, process_instruction); assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot); let mut bank = Arc::new(new_from_parent(&bank)); Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &loader_id, mock_ix_processor); + .add_builtin("mock_program", &loader_id, process_instruction); assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot); } @@ -8053,6 +7988,7 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { Ok(()), solana_bpf_loader_program::process_instruction, |_invoke_context| {}, + |_invoke_context| {}, ); // Test initialized program account @@ -9999,10 +9935,7 @@ fn test_tx_return_data() { ); let mut bank = Bank::new_for_tests(&genesis_config); - let mock_program_id = Pubkey::from([2u8; 32]); - fn mock_process_instruction( - invoke_context: &mut InvokeContext, - ) -> result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let mock_program_id = Pubkey::from([2u8; 32]); let transaction_context = &mut invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; @@ -10016,9 +9949,11 @@ fn test_tx_return_data() { .unwrap(); } Ok(()) - } + }); + + let mock_program_id = Pubkey::from([2u8; 32]); let blockhash = bank.last_blockhash(); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin("mock_program", &mock_program_id, process_instruction); for index in [ None, @@ -10197,21 +10132,17 @@ fn test_transfer_sysvar() { ); let mut bank = Bank::new_for_tests(&genesis_config); - fn mock_ix_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - // mock builtin should consume units - let _ = invoke_context.consume_checked(1); instruction_context .try_borrow_instruction_account(transaction_context, 1)? .set_data(vec![0; 40])?; Ok(()) - } + }); let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program1", &program_id, mock_ix_processor); + bank.add_builtin("mock_program1", &program_id, process_instruction); let blockhash = bank.last_blockhash(); #[allow(deprecated)] @@ -10410,9 +10341,7 @@ fn test_compute_budget_program_noop() { ); let mut bank = Bank::new_for_tests(&genesis_config); - fn mock_ix_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let compute_budget = invoke_context.get_compute_budget(); assert_eq!( *compute_budget, @@ -10422,12 +10351,10 @@ fn test_compute_budget_program_noop() { ..ComputeBudget::default() } ); - // mock builtin should consume units - let _ = invoke_context.consume_checked(1); Ok(()) - } + }); let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program", &program_id, mock_ix_processor); + bank.add_builtin("mock_program", &program_id, process_instruction); let message = Message::new( &[ @@ -10457,9 +10384,7 @@ fn test_compute_request_instruction() { ); let mut bank = Bank::new_for_tests(&genesis_config); - fn mock_ix_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let compute_budget = invoke_context.get_compute_budget(); assert_eq!( *compute_budget, @@ -10469,12 +10394,10 @@ fn test_compute_request_instruction() { ..ComputeBudget::default() } ); - // mock builtin should consume units - let _ = invoke_context.consume_checked(1); Ok(()) - } + }); let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program", &program_id, mock_ix_processor); + bank.add_builtin("mock_program", &program_id, process_instruction); let message = Message::new( &[ @@ -10511,9 +10434,7 @@ fn test_failed_compute_request_instruction() { bank.transfer(10, &mint_keypair, &payer1_keypair.pubkey()) .unwrap(); - fn mock_ix_processor( - invoke_context: &mut InvokeContext, - ) -> std::result::Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let compute_budget = invoke_context.get_compute_budget(); assert_eq!( *compute_budget, @@ -10524,9 +10445,9 @@ fn test_failed_compute_request_instruction() { } ); Ok(()) - } + }); let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program", &program_id, mock_ix_processor); + bank.add_builtin("mock_program", &program_id, process_instruction); // This message will not be executed because the compute budget request is invalid let message0 = Message::new( @@ -11076,14 +10997,10 @@ enum MockTransferInstruction { Transfer(u64), } -fn mock_transfer_process_instruction( - invoke_context: &mut InvokeContext, -) -> result::Result<(), Box> { +declare_process_instruction!(mock_transfer_process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - // mock builtin must consume units - invoke_context.consume_checked(1)?; if let Ok(instruction) = bincode::deserialize(instruction_data) { match instruction { MockTransferInstruction::Transfer(amount) => { @@ -11097,9 +11014,9 @@ fn mock_transfer_process_instruction( } } } else { - Err(Box::new(InstructionError::InvalidInstructionData)) + Err(InstructionError::InvalidInstructionData) } -} +}); fn create_mock_transfer( payer: &Keypair, @@ -11888,14 +11805,10 @@ enum MockReallocInstruction { Realloc(usize, u64, Pubkey), } -fn mock_realloc_process_instruction( - invoke_context: &mut InvokeContext, -) -> result::Result<(), Box> { +declare_process_instruction!(mock_realloc_process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - // mock builtin must consume units - invoke_context.consume_checked(1)?; if let Ok(instruction) = bincode::deserialize(instruction_data) { match instruction { MockReallocInstruction::Realloc(new_size, new_balance, _) => { @@ -11929,9 +11842,9 @@ fn mock_realloc_process_instruction( } } } else { - Err(Box::new(InstructionError::InvalidInstructionData)) + Err(InstructionError::InvalidInstructionData) } -} +}); fn create_mock_realloc_tx( payer: &Keypair, diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index b1a6066e6a..b671dc7181 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -188,6 +188,7 @@ mod tests { use { super::*, crate::rent_collector::RentCollector, + solana_program_runtime::declare_process_instruction, solana_sdk::{ account::{AccountSharedData, ReadableAccount}, instruction::{AccountMeta, Instruction, InstructionError}, @@ -217,14 +218,10 @@ mod tests { ChangeData { data: u8 }, } - fn mock_system_process_instruction( - invoke_context: &mut InvokeContext, - ) -> Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - // mock builtin should consume units - let _ = invoke_context.consume_checked(1); if let Ok(instruction) = bincode::deserialize(instruction_data) { match instruction { MockSystemInstruction::Correct => Ok(()), @@ -245,9 +242,9 @@ mod tests { } } } else { - Err(Box::new(InstructionError::InvalidInstructionData)) + Err(InstructionError::InvalidInstructionData) } - } + }); let writable_pubkey = Pubkey::new_unique(); let readonly_pubkey = Pubkey::new_unique(); @@ -256,7 +253,7 @@ mod tests { let rent_collector = RentCollector::default(); let builtin_programs = &[BuiltinProgram { program_id: mock_system_program_id, - process_instruction: mock_system_process_instruction, + process_instruction, }]; let accounts = vec![ @@ -430,16 +427,12 @@ mod tests { DoWork { lamports: u64, data: u8 }, } - fn mock_system_process_instruction( - invoke_context: &mut InvokeContext, - ) -> Result<(), Box> { + declare_process_instruction!(process_instruction, 1, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); let mut to_account = instruction_context.try_borrow_instruction_account(transaction_context, 1)?; - // mock builtin should consume units - let _ = invoke_context.consume_checked(1); if let Ok(instruction) = bincode::deserialize(instruction_data) { match instruction { MockSystemInstruction::BorrowFail => { @@ -448,7 +441,7 @@ mod tests { let dup_account = instruction_context .try_borrow_instruction_account(transaction_context, 2)?; if from_account.get_lamports() != dup_account.get_lamports() { - return Err(Box::new(InstructionError::InvalidArgument)); + return Err(InstructionError::InvalidArgument); } Ok(()) } @@ -460,7 +453,7 @@ mod tests { .try_borrow_instruction_account(transaction_context, 2)? .get_lamports(); if lamports_a != lamports_b { - return Err(Box::new(InstructionError::InvalidArgument)); + return Err(InstructionError::InvalidArgument); } Ok(()) } @@ -479,15 +472,15 @@ mod tests { } } } else { - Err(Box::new(InstructionError::InvalidInstructionData)) + Err(InstructionError::InvalidInstructionData) } - } + }); let mock_program_id = Pubkey::from([2u8; 32]); let rent_collector = RentCollector::default(); let builtin_programs = &[BuiltinProgram { program_id: mock_program_id, - process_instruction: mock_system_process_instruction, + process_instruction, }]; let accounts = vec![ @@ -645,16 +638,12 @@ mod tests { #[test] fn test_precompile() { let mock_program_id = Pubkey::new_unique(); - fn mock_process_instruction( - invoke_context: &mut InvokeContext, - ) -> Result<(), Box> { - // mock builtin should consume units - let _ = invoke_context.consume_checked(1); - Err(Box::new(InstructionError::Custom(0xbabb1e))) - } + declare_process_instruction!(process_instruction, 1, |_invoke_context| { + Err(InstructionError::Custom(0xbabb1e)) + }); let builtin_programs = &[BuiltinProgram { program_id: mock_program_id, - process_instruction: mock_process_instruction, + process_instruction, }]; let mut secp256k1_account = AccountSharedData::new(1, 0, &native_loader::id()); diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index 3ca5c1ded1..367238b747 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -316,10 +316,7 @@ fn transfer_with_seed( ) } -declare_process_instruction!(150); -pub fn process_instruction_inner( - invoke_context: &mut InvokeContext, -) -> Result<(), InstructionError> { +declare_process_instruction!(process_instruction, 150, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); @@ -558,7 +555,7 @@ pub fn process_instruction_inner( assign(&mut account, &address, &owner, &signers, invoke_context) } } -} +}); #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum SystemAccountKind { @@ -614,8 +611,7 @@ mod tests { crate::{bank::Bank, bank_client::BankClient}, bincode::serialize, solana_program_runtime::{ - invoke_context::{mock_process_instruction, ProcessInstructionWithContext}, - with_mock_invoke_context, + invoke_context::mock_process_instruction, with_mock_invoke_context, }, std::sync::Arc, }; @@ -634,7 +630,6 @@ mod tests { transaction_accounts: Vec<(Pubkey, AccountSharedData)>, instruction_accounts: Vec, expected_result: Result<(), InstructionError>, - process_instruction: ProcessInstructionWithContext, ) -> Vec { mock_process_instruction( &system_program::id(), @@ -643,7 +638,8 @@ mod tests { transaction_accounts, instruction_accounts, expected_result, - process_instruction, + super::process_instruction, + |_invoke_context| {}, |_invoke_context| {}, ) } @@ -691,7 +687,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 50); assert_eq!(accounts[1].lamports(), 50); @@ -731,7 +726,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 50); assert_eq!(accounts[1].lamports(), 50); @@ -778,7 +772,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 50); assert_eq!(accounts[1].lamports(), 50); @@ -830,7 +823,6 @@ mod tests { }, ], Err(InstructionError::MissingRequiredSignature), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1], AccountSharedData::default()); @@ -866,7 +858,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1].lamports(), 0); @@ -904,7 +895,6 @@ mod tests { }, ], Err(SystemError::ResultWithNegativeLamports.into()), - super::process_instruction, ); } @@ -938,7 +928,6 @@ mod tests { vec![(from, from_account.clone()), (to, to_account.clone())], instruction_accounts.clone(), Err(SystemError::InvalidAccountDataLength.into()), - super::process_instruction, ); // Trying to request equal or less data length than permitted will be successful @@ -952,7 +941,6 @@ mod tests { vec![(from, from_account), (to, to_account)], instruction_accounts, Ok(()), - super::process_instruction, ); assert_eq!(accounts[1].lamports(), 50); assert_eq!(accounts[1].data().len() as u64, MAX_PERMITTED_DATA_LENGTH); @@ -990,7 +978,6 @@ mod tests { }, ], Err(SystemError::AccountAlreadyInUse.into()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1], unchanged_account); @@ -1019,7 +1006,6 @@ mod tests { }, ], Err(SystemError::AccountAlreadyInUse.into()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1], unchanged_account); @@ -1048,7 +1034,6 @@ mod tests { }, ], Err(SystemError::AccountAlreadyInUse.into()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1], unchanged_account); @@ -1088,7 +1073,6 @@ mod tests { }, ], Err(InstructionError::MissingRequiredSignature), - super::process_instruction, ); // Haven't signed to account @@ -1113,7 +1097,6 @@ mod tests { }, ], Err(InstructionError::MissingRequiredSignature), - super::process_instruction, ); // Don't support unsigned creation with zero lamports (ephemeral account) @@ -1139,7 +1122,6 @@ mod tests { }, ], Err(InstructionError::MissingRequiredSignature), - super::process_instruction, ); } @@ -1173,7 +1155,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); } @@ -1210,7 +1191,6 @@ mod tests { }, ], Err(SystemError::AccountAlreadyInUse.into()), - super::process_instruction, ); } @@ -1247,7 +1227,6 @@ mod tests { }, ], Err(InstructionError::InvalidArgument), - super::process_instruction, ); } @@ -1270,7 +1249,6 @@ mod tests { is_writable: true, }], Ok(()), - super::process_instruction, ); // owner does change, signature needed @@ -1283,7 +1261,6 @@ mod tests { is_writable: true, }], Err(InstructionError::MissingRequiredSignature), - super::process_instruction, ); process_instruction( @@ -1295,7 +1272,6 @@ mod tests { is_writable: true, }], Ok(()), - super::process_instruction, ); // assign to sysvar instead of system_program @@ -1311,7 +1287,6 @@ mod tests { is_writable: true, }], Ok(()), - super::process_instruction, ); } @@ -1327,7 +1302,6 @@ mod tests { Vec::new(), Vec::new(), Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); // Attempt to transfer with no destination @@ -1344,7 +1318,6 @@ mod tests { is_writable: false, }], Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -1374,7 +1347,6 @@ mod tests { transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 50); assert_eq!(accounts[1].lamports(), 51); @@ -1385,7 +1357,6 @@ mod tests { transaction_accounts.clone(), instruction_accounts.clone(), Err(SystemError::ResultWithNegativeLamports.into()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1].lamports(), 1); @@ -1396,7 +1367,6 @@ mod tests { transaction_accounts.clone(), instruction_accounts, Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1].lamports(), 1); @@ -1418,7 +1388,6 @@ mod tests { }, ], Err(InstructionError::MissingRequiredSignature), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[1].lamports(), 1); @@ -1465,7 +1434,6 @@ mod tests { transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 50); assert_eq!(accounts[2].lamports(), 51); @@ -1481,7 +1449,6 @@ mod tests { transaction_accounts.clone(), instruction_accounts.clone(), Err(SystemError::ResultWithNegativeLamports.into()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[2].lamports(), 1); @@ -1497,7 +1464,6 @@ mod tests { transaction_accounts, instruction_accounts, Ok(()), - super::process_instruction, ); assert_eq!(accounts[0].lamports(), 100); assert_eq!(accounts[2].lamports(), 1); @@ -1538,7 +1504,6 @@ mod tests { }, ], Err(InstructionError::InvalidArgument), - super::process_instruction, ); } @@ -1766,7 +1731,6 @@ mod tests { transaction_accounts, instruction.accounts, expected_result, - super::process_instruction, ) } @@ -1786,7 +1750,6 @@ mod tests { Vec::new(), Vec::new(), Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -1802,7 +1765,6 @@ mod tests { is_writable: true, }], Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -1837,7 +1799,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); let blockhash = hash(&serialize(&0).unwrap()); #[allow(deprecated)] @@ -1846,7 +1807,9 @@ mod tests { vec![IterItem(0u64, &blockhash, 0); sysvar::recent_blockhashes::MAX_ENTRIES] .into_iter(), ); - process_instruction( + mock_process_instruction( + &system_program::id(), + Vec::new(), &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(), vec![ (nonce_address, accounts[0].clone()), @@ -1865,10 +1828,11 @@ mod tests { }, ], Ok(()), + super::process_instruction, |invoke_context: &mut InvokeContext| { invoke_context.blockhash = hash(&serialize(&0).unwrap()); - super::process_instruction(invoke_context) }, + |_invoke_context| {}, ); } @@ -1893,7 +1857,6 @@ mod tests { Vec::new(), Vec::new(), Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -1909,7 +1872,6 @@ mod tests { is_writable: true, }], Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -1951,7 +1913,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); } @@ -1962,7 +1923,6 @@ mod tests { Vec::new(), Vec::new(), Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -1979,7 +1939,6 @@ mod tests { is_writable: true, }], Err(InstructionError::NotEnoughAccountKeys), - super::process_instruction, ); } @@ -2014,7 +1973,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); } @@ -2049,7 +2007,6 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); process_instruction( &serialize(&SystemInstruction::AuthorizeNonceAccount(nonce_address)).unwrap(), @@ -2060,7 +2017,6 @@ mod tests { is_writable: true, }], Ok(()), - super::process_instruction, ); } @@ -2162,7 +2118,6 @@ mod tests { }, ], Err(NonceError::NoRecentBlockhashes.into()), - super::process_instruction, ); } @@ -2197,14 +2152,15 @@ mod tests { }, ], Ok(()), - super::process_instruction, ); #[allow(deprecated)] let new_recent_blockhashes_account = solana_sdk::recent_blockhashes_account::create_account_with_data_for_test( vec![].into_iter(), ); - process_instruction( + mock_process_instruction( + &system_program::id(), + Vec::new(), &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(), vec![ (nonce_address, accounts[0].clone()), @@ -2223,10 +2179,11 @@ mod tests { }, ], Err(NonceError::NoRecentBlockhashes.into()), + super::process_instruction, |invoke_context: &mut InvokeContext| { invoke_context.blockhash = hash(&serialize(&0).unwrap()); - super::process_instruction(invoke_context) }, + |_invoke_context| {}, ); } @@ -2249,7 +2206,6 @@ mod tests { is_writable: true, }], Err(InstructionError::InvalidAccountOwner), - super::process_instruction, ); assert_eq!(accounts.len(), 1); assert_eq!(accounts[0], nonce_account); @@ -2283,7 +2239,6 @@ mod tests { is_writable: true, }], Err(InstructionError::InvalidArgument), - super::process_instruction, ); assert_eq!(accounts.len(), 1); assert_eq!(accounts[0], nonce_account); @@ -2298,7 +2253,6 @@ mod tests { is_writable: true, }], Err(InstructionError::InvalidArgument), - super::process_instruction, ); assert_eq!(accounts.len(), 1); assert_eq!(accounts[0], nonce_account); @@ -2322,7 +2276,6 @@ mod tests { is_writable: false, // Should fail! }], Err(InstructionError::InvalidArgument), - super::process_instruction, ); assert_eq!(accounts.len(), 1); assert_eq!(accounts[0], nonce_account); @@ -2335,7 +2288,6 @@ mod tests { is_writable: true, }], Ok(()), - super::process_instruction, ); assert_eq!(accounts.len(), 1); let nonce_account = accounts.remove(0); @@ -2360,7 +2312,6 @@ mod tests { is_writable: true, }], Err(InstructionError::InvalidArgument), - super::process_instruction, ); assert_eq!(accounts.len(), 1); assert_eq!(