diff --git a/cli/src/program.rs b/cli/src/program.rs index 8eadbe70be..1680915984 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -37,6 +37,7 @@ use { account_utils::StateMut, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, + feature_set::FeatureSet, instruction::{Instruction, InstructionError}, loader_instruction, message::Message, @@ -46,9 +47,7 @@ use { signature::{keypair_from_seed, read_keypair_file, Keypair, Signature, Signer}, system_instruction::{self, SystemError}, system_program, - sysvar::rent::Rent, transaction::{Transaction, TransactionError}, - transaction_context::TransactionContext, }, std::{ fs::File, @@ -2018,12 +2017,10 @@ fn read_and_verify_elf(program_location: &str) -> Result, Box { rent: Rent, pre_accounts: Vec, builtin_programs: &'a [BuiltinProgram], - pub sysvar_cache: Cow<'a, SysvarCache>, + sysvar_cache: &'a SysvarCache, pub trace_log_stack: Vec, log_collector: Option>>, compute_budget: ComputeBudget, @@ -138,7 +137,7 @@ impl<'a> InvokeContext<'a> { transaction_context: &'a mut TransactionContext, rent: Rent, builtin_programs: &'a [BuiltinProgram], - sysvar_cache: Cow<'a, SysvarCache>, + sysvar_cache: &'a SysvarCache, log_collector: Option>>, compute_budget: ComputeBudget, tx_executor_cache: Rc>, @@ -169,43 +168,6 @@ impl<'a> InvokeContext<'a> { } } - pub fn new_mock( - transaction_context: &'a mut TransactionContext, - builtin_programs: &'a [BuiltinProgram], - ) -> Self { - let mut sysvar_cache = SysvarCache::default(); - sysvar_cache.fill_missing_entries(|pubkey, callback| { - for index in 0..transaction_context.get_number_of_accounts() { - if transaction_context - .get_key_of_account_at_index(index) - .unwrap() - == pubkey - { - callback( - transaction_context - .get_account_at_index(index) - .unwrap() - .borrow() - .data(), - ); - } - } - }); - Self::new( - transaction_context, - Rent::default(), - builtin_programs, - Cow::Owned(sysvar_cache), - Some(LogCollector::new_ref()), - ComputeBudget::default(), - Rc::new(RefCell::new(TransactionExecutorCache::default())), - Arc::new(FeatureSet::all_enabled()), - Hash::default(), - 0, - 0, - ) - } - /// Push a stack frame onto the invocation stack pub fn push(&mut self) -> Result<(), InstructionError> { let instruction_context = self @@ -807,7 +769,7 @@ impl<'a> InvokeContext<'a> { /// Get cached sysvars pub fn get_sysvar_cache(&self) -> &SysvarCache { - &self.sysvar_cache + self.sysvar_cache } // Set this instruction syscall context @@ -881,16 +843,73 @@ impl<'a> InvokeContext<'a> { } } -pub struct MockInvokeContextPreparation { - pub transaction_accounts: Vec, - pub instruction_accounts: Vec, +#[macro_export] +macro_rules! with_mock_invoke_context { + ($invoke_context:ident, $transaction_context:ident, $transaction_accounts:expr) => { + use { + solana_sdk::{ + account::ReadableAccount, feature_set::FeatureSet, hash::Hash, sysvar::rent::Rent, + transaction_context::TransactionContext, + }, + std::{cell::RefCell, rc::Rc, sync::Arc}, + $crate::{ + compute_budget::ComputeBudget, executor_cache::TransactionExecutorCache, + invoke_context::InvokeContext, log_collector::LogCollector, + sysvar_cache::SysvarCache, + }, + }; + let compute_budget = ComputeBudget::default(); + let mut $transaction_context = TransactionContext::new( + $transaction_accounts, + Some(Rent::default()), + compute_budget.max_invoke_stack_height, + compute_budget.max_instruction_trace_length, + ); + $transaction_context.enable_cap_accounts_data_allocations_per_transaction(); + let mut sysvar_cache = SysvarCache::default(); + sysvar_cache.fill_missing_entries(|pubkey, callback| { + for index in 0..$transaction_context.get_number_of_accounts() { + if $transaction_context + .get_key_of_account_at_index(index) + .unwrap() + == pubkey + { + callback( + $transaction_context + .get_account_at_index(index) + .unwrap() + .borrow() + .data(), + ); + } + } + }); + let mut $invoke_context = InvokeContext::new( + &mut $transaction_context, + Rent::default(), + &[], + &sysvar_cache, + Some(LogCollector::new_ref()), + compute_budget, + Rc::new(RefCell::new(TransactionExecutorCache::default())), + Arc::new(FeatureSet::all_enabled()), + Hash::default(), + 0, + 0, + ); + }; } -pub fn prepare_mock_invoke_context( - transaction_accounts: Vec, +pub fn mock_process_instruction( + loader_id: &Pubkey, + mut program_indices: Vec, + instruction_data: &[u8], + mut transaction_accounts: Vec, instruction_account_metas: Vec, - _program_indices: &[IndexOfAccount], -) -> MockInvokeContextPreparation { + expected_result: Result<(), InstructionError>, + process_instruction: ProcessInstructionWithContext, + mut pre_adjustments: F, +) -> Vec { let mut instruction_accounts: Vec = Vec::with_capacity(instruction_account_metas.len()); for (instruction_account_index, account_meta) in instruction_account_metas.iter().enumerate() { @@ -915,97 +934,19 @@ pub fn prepare_mock_invoke_context( is_writable: account_meta.is_writable, }); } - MockInvokeContextPreparation { - transaction_accounts, - instruction_accounts, - } -} - -pub fn with_mock_invoke_context R>( - loader_id: Pubkey, - account_size: usize, - is_writable: bool, - mut callback: F, -) -> R { - let program_indices = vec![0, 1]; - let program_key = Pubkey::new_unique(); - let transaction_accounts = vec![ - ( - loader_id, - AccountSharedData::new(0, 0, &native_loader::id()), - ), - (program_key, AccountSharedData::new(1, 0, &loader_id)), - ( - Pubkey::new_unique(), - AccountSharedData::new(2, account_size, &program_key), - ), - ]; - let instruction_accounts = vec![AccountMeta { - pubkey: transaction_accounts.get(2).unwrap().0, - is_signer: false, - is_writable, - }]; - let preparation = - prepare_mock_invoke_context(transaction_accounts, instruction_accounts, &program_indices); - let compute_budget = ComputeBudget::default(); - let mut transaction_context = TransactionContext::new( - preparation.transaction_accounts, - Some(Rent::default()), - compute_budget.max_invoke_stack_height, - compute_budget.max_instruction_trace_length, - ); - transaction_context.enable_cap_accounts_data_allocations_per_transaction(); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); - invoke_context - .transaction_context - .get_next_instruction_context() - .unwrap() - .configure(&program_indices, &preparation.instruction_accounts, &[]); - invoke_context.push().unwrap(); - callback(&mut invoke_context) -} - -pub fn mock_process_instruction( - loader_id: &Pubkey, - mut program_indices: Vec, - instruction_data: &[u8], - transaction_accounts: Vec, - instruction_accounts: Vec, - sysvar_cache_override: Option<&SysvarCache>, - feature_set_override: Option>, - expected_result: Result<(), InstructionError>, - process_instruction: ProcessInstructionWithContext, -) -> Vec { program_indices.insert(0, transaction_accounts.len() as IndexOfAccount); - let mut preparation = - prepare_mock_invoke_context(transaction_accounts, instruction_accounts, &program_indices); let processor_account = AccountSharedData::new(0, 0, &native_loader::id()); - preparation - .transaction_accounts - .push((*loader_id, processor_account)); - let compute_budget = ComputeBudget::default(); - let mut transaction_context = TransactionContext::new( - preparation.transaction_accounts, - Some(Rent::default()), - compute_budget.max_invoke_stack_height, - compute_budget.max_instruction_trace_length, - ); - transaction_context.enable_cap_accounts_data_allocations_per_transaction(); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); - if let Some(sysvar_cache) = sysvar_cache_override { - invoke_context.sysvar_cache = Cow::Borrowed(sysvar_cache); - } - if let Some(feature_set) = feature_set_override { - invoke_context.feature_set = feature_set; - } + transaction_accounts.push((*loader_id, processor_account)); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); let builtin_programs = &[BuiltinProgram { program_id: *loader_id, process_instruction, }]; invoke_context.builtin_programs = builtin_programs; + pre_adjustments(&mut invoke_context); let result = invoke_context.process_instruction( instruction_data, - &preparation.instruction_accounts, + &instruction_accounts, &program_indices, &mut 0, &mut ExecuteTimings::default(), @@ -1171,13 +1112,15 @@ mod tests { #[test] fn test_instruction_stack_height() { - const MAX_DEPTH: usize = 10; + let one_more_than_max_depth = ComputeBudget::default() + .max_invoke_stack_height + .saturating_add(1); let mut invoke_stack = vec![]; - let mut accounts = vec![]; + let mut transaction_accounts = vec![]; let mut instruction_accounts = vec![]; - for index in 0..MAX_DEPTH { + for index in 0..one_more_than_max_depth { invoke_stack.push(solana_sdk::pubkey::new_rand()); - accounts.push(( + transaction_accounts.push(( solana_sdk::pubkey::new_rand(), AccountSharedData::new(index as u64, 1, invoke_stack.get(index).unwrap()), )); @@ -1190,7 +1133,7 @@ mod tests { }); } for (index, program_id) in invoke_stack.iter().enumerate() { - accounts.push(( + transaction_accounts.push(( *program_id, AccountSharedData::new(1, 1, &solana_sdk::pubkey::Pubkey::default()), )); @@ -1202,13 +1145,7 @@ mod tests { is_writable: false, }); } - let mut transaction_context = TransactionContext::new( - accounts, - Some(Rent::default()), - ComputeBudget::default().max_invoke_stack_height, - MAX_DEPTH, - ); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); // Check call depth increases and has a limit let mut depth_reached = 0; @@ -1218,17 +1155,17 @@ mod tests { .get_next_instruction_context() .unwrap() .configure( - &[(MAX_DEPTH + depth_reached) as IndexOfAccount], + &[one_more_than_max_depth.saturating_add(depth_reached) as IndexOfAccount], &instruction_accounts, &[], ); if Err(InstructionError::CallDepth) == invoke_context.push() { break; } - depth_reached += 1; + depth_reached = depth_reached.saturating_add(1); } assert_ne!(depth_reached, 0); - assert!(depth_reached < MAX_DEPTH); + assert!(depth_reached < one_more_than_max_depth); } #[test] @@ -1249,18 +1186,13 @@ mod tests { #[test] fn test_process_instruction() { let callee_program_id = solana_sdk::pubkey::new_rand(); - let builtin_programs = &[BuiltinProgram { - program_id: callee_program_id, - process_instruction: mock_process_instruction, - }]; - let owned_account = AccountSharedData::new(42, 1, &callee_program_id); let not_owned_account = AccountSharedData::new(84, 1, &solana_sdk::pubkey::new_rand()); let readonly_account = AccountSharedData::new(168, 1, &solana_sdk::pubkey::new_rand()); let loader_account = AccountSharedData::new(0, 0, &native_loader::id()); let mut program_account = AccountSharedData::new(1, 0, &native_loader::id()); program_account.set_executable(true); - let accounts = vec![ + let transaction_accounts = vec![ (solana_sdk::pubkey::new_rand(), owned_account), (solana_sdk::pubkey::new_rand(), not_owned_account), (solana_sdk::pubkey::new_rand(), readonly_account), @@ -1268,9 +1200,9 @@ mod tests { (solana_sdk::pubkey::new_rand(), loader_account), ]; let metas = vec![ - AccountMeta::new(accounts.get(0).unwrap().0, false), - AccountMeta::new(accounts.get(1).unwrap().0, false), - AccountMeta::new_readonly(accounts.get(2).unwrap().0, false), + AccountMeta::new(transaction_accounts.get(0).unwrap().0, false), + AccountMeta::new(transaction_accounts.get(1).unwrap().0, false), + AccountMeta::new_readonly(transaction_accounts.get(2).unwrap().0, false), ]; let instruction_accounts = (0..4) .map(|instruction_account_index| InstructionAccount { @@ -1281,10 +1213,12 @@ mod tests { is_writable: instruction_account_index < 2, }) .collect::>(); - let mut transaction_context = - TransactionContext::new(accounts, Some(Rent::default()), 2, 18); - let mut invoke_context = - InvokeContext::new_mock(&mut transaction_context, builtin_programs); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); + let builtin_programs = &[BuiltinProgram { + program_id: callee_program_id, + process_instruction: mock_process_instruction, + }]; + invoke_context.builtin_programs = builtin_programs; // Account modification tests let cases = vec![ @@ -1364,7 +1298,7 @@ mod tests { assert!(compute_units_consumed > 0); assert_eq!( compute_units_consumed, - compute_units_to_consume + MOCK_BUILTIN_COMPUTE_UNIT_COST + compute_units_to_consume.saturating_add(MOCK_BUILTIN_COMPUTE_UNIT_COST), ); assert_eq!(result, expected_result); @@ -1374,11 +1308,10 @@ mod tests { #[test] fn test_invoke_context_compute_budget() { - let accounts = vec![(solana_sdk::pubkey::new_rand(), AccountSharedData::default())]; + let transaction_accounts = + vec![(solana_sdk::pubkey::new_rand(), AccountSharedData::default())]; - let mut transaction_context = - TransactionContext::new(accounts, Some(Rent::default()), 1, 1); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); invoke_context.compute_budget = ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64); @@ -1404,22 +1337,11 @@ mod tests { let dummy_account = AccountSharedData::new(10, 0, &program_key); let mut program_account = AccountSharedData::new(500, 500, &native_loader::id()); program_account.set_executable(true); - let accounts = vec![ + let transaction_accounts = vec![ (Pubkey::new_unique(), user_account), (Pubkey::new_unique(), dummy_account), (program_key, program_account), ]; - - let builtin_programs = [BuiltinProgram { - program_id: program_key, - process_instruction: mock_process_instruction, - }]; - - let mut transaction_context = - TransactionContext::new(accounts, Some(Rent::default()), 1, 3); - let mut invoke_context = - InvokeContext::new_mock(&mut transaction_context, &builtin_programs); - let instruction_accounts = [ InstructionAccount { index_in_transaction: 0, @@ -1436,11 +1358,17 @@ mod tests { is_writable: false, }, ]; + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); + let builtin_programs = &[BuiltinProgram { + program_id: program_key, + process_instruction: mock_process_instruction, + }]; + invoke_context.builtin_programs = builtin_programs; // Test: Resize the account to *the same size*, so not consuming any additional size; this must succeed { let resize_delta: i64 = 0; - let new_len = (user_account_data_len as i64 + resize_delta) as u64; + let new_len = (user_account_data_len as i64).saturating_add(resize_delta) as u64; let instruction_data = bincode::serialize(&MockInstruction::Resize { new_len }).unwrap(); @@ -1465,7 +1393,7 @@ mod tests { // Test: Resize the account larger; this must succeed { let resize_delta: i64 = 1; - let new_len = (user_account_data_len as i64 + resize_delta) as u64; + let new_len = (user_account_data_len as i64).saturating_add(resize_delta) as u64; let instruction_data = bincode::serialize(&MockInstruction::Resize { new_len }).unwrap(); @@ -1490,7 +1418,7 @@ mod tests { // Test: Resize the account smaller; this must succeed { let resize_delta: i64 = -1; - let new_len = (user_account_data_len as i64 + resize_delta) as u64; + let new_len = (user_account_data_len as i64).saturating_add(resize_delta) as u64; let instruction_data = bincode::serialize(&MockInstruction::Resize { new_len }).unwrap(); diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index cfc8b93030..a2a4fb465e 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -1725,10 +1725,9 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - None, - None, expected_result, super::process_instruction, + |_invoke_context| {}, ) } @@ -2011,12 +2010,10 @@ mod tests { &[], vec![(program_id, program_account.clone())], Vec::new(), - None, - None, Err(InstructionError::ProgramFailedToComplete), - |invoke_context: &mut InvokeContext| { + super::process_instruction, + |invoke_context| { invoke_context.mock_set_remaining(0); - super::process_instruction(invoke_context) }, ); @@ -2557,10 +2554,9 @@ mod tests { &instruction_data, transaction_accounts, instruction_accounts, - None, - None, expected_result, super::process_instruction, + |_invoke_context| {}, ) } diff --git a/programs/bpf_loader/src/serialization.rs b/programs/bpf_loader/src/serialization.rs index 46cf2a3914..6b595e3c07 100644 --- a/programs/bpf_loader/src/serialization.rs +++ b/programs/bpf_loader/src/serialization.rs @@ -447,14 +447,14 @@ pub fn deserialize_parameters_aligned( mod tests { use { super::*, - solana_program_runtime::invoke_context::{prepare_mock_invoke_context, InvokeContext}, + solana_program_runtime::with_mock_invoke_context, solana_sdk::{ - account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, + account::{Account, AccountSharedData, WritableAccount}, account_info::AccountInfo, bpf_loader, entrypoint::deserialize, - instruction::AccountMeta, sysvar::rent::Rent, + transaction_context::InstructionAccount, }, std::{ cell::RefCell, @@ -537,13 +537,9 @@ mod tests { rent_epoch: 0, }), )]; - - let instruction_account_keys: Vec = - (0..num_ix_accounts).map(|_| Pubkey::new_unique()).collect(); - - for key in &instruction_account_keys { + for _ in 0..num_ix_accounts { transaction_accounts.push(( - *key, + Pubkey::new_unique(), AccountSharedData::from(Account { lamports: 0, data: vec![], @@ -553,22 +549,19 @@ mod tests { }), )); } - - let mut instruction_account_metas: Vec<_> = instruction_account_keys - .iter() - .map(|key| AccountMeta::new_readonly(*key, false)) + let mut instruction_accounts: Vec<_> = (0..num_ix_accounts as IndexOfAccount) + .map(|index_in_callee| InstructionAccount { + index_in_transaction: index_in_callee + 1, + index_in_caller: index_in_callee + 1, + index_in_callee, + is_signer: false, + is_writable: false, + }) .collect(); if append_dup_account { - instruction_account_metas.push(instruction_account_metas.last().cloned().unwrap()); + instruction_accounts.push(instruction_accounts.last().cloned().unwrap()); } - let program_indices = [0]; - let instruction_accounts = prepare_mock_invoke_context( - transaction_accounts.clone(), - instruction_account_metas, - &program_indices, - ) - .instruction_accounts; let instruction_data = vec![]; let mut transaction_context = @@ -693,41 +686,28 @@ mod tests { }), ), ]; - let instruction_accounts = [1, 1, 2, 3, 4, 4, 5, 6] + let instruction_accounts: Vec = [1, 1, 2, 3, 4, 4, 5, 6] .into_iter() .enumerate() .map( - |(instruction_account_index, index_in_transaction)| AccountMeta { - pubkey: transaction_accounts.get(index_in_transaction).unwrap().0, + |(index_in_instruction, index_in_transaction)| InstructionAccount { + index_in_transaction, + index_in_caller: index_in_transaction, + index_in_callee: index_in_transaction - 1, is_signer: false, - is_writable: instruction_account_index >= 4, + is_writable: index_in_instruction >= 4, }, ) .collect(); let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; let program_indices = [0]; let mut original_accounts = transaction_accounts.clone(); - let preparation = prepare_mock_invoke_context( - transaction_accounts, - instruction_accounts, - &program_indices, - ); - let mut transaction_context = TransactionContext::new( - preparation.transaction_accounts, - Some(Rent::default()), - 1, - 1, - ); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); invoke_context .transaction_context .get_next_instruction_context() .unwrap() - .configure( - &program_indices, - &preparation.instruction_accounts, - &instruction_data, - ); + .configure(&program_indices, &instruction_accounts, &instruction_data); invoke_context.push().unwrap(); let instruction_context = invoke_context .transaction_context diff --git a/programs/bpf_loader/src/syscalls/cpi.rs b/programs/bpf_loader/src/syscalls/cpi.rs index 45654be277..41315377c5 100644 --- a/programs/bpf_loader/src/syscalls/cpi.rs +++ b/programs/bpf_loader/src/syscalls/cpi.rs @@ -1123,6 +1123,7 @@ mod tests { use { super::*, crate::allocator_bump::BpfAllocator, + solana_program_runtime::with_mock_invoke_context, solana_rbpf::{ aligned_memory::AlignedMemory, ebpf::MM_INPUT_START, memory_region::MemoryRegion, vm::Config, @@ -1131,8 +1132,7 @@ mod tests { account::{Account, AccountSharedData}, clock::Epoch, instruction::Instruction, - rent::Rent, - transaction_context::{TransactionAccount, TransactionContext}, + transaction_context::TransactionAccount, }, std::{ cell::{Cell, RefCell}, @@ -1168,12 +1168,7 @@ mod tests { .into_iter() .map(|a| (a.0, a.1)) .collect::>(); - - let program_accounts = program_accounts; - let mut $transaction_context = - TransactionContext::new(transaction_accounts, Some(Rent::default()), 1, 1); - - let mut $invoke_context = InvokeContext::new_mock(&mut $transaction_context, &[]); + with_mock_invoke_context!($invoke_context, transaction_context, transaction_accounts); $invoke_context .transaction_context .get_next_instruction_context() diff --git a/programs/bpf_loader/src/syscalls/mod.rs b/programs/bpf_loader/src/syscalls/mod.rs index 3d7d321e40..bdeef057c3 100644 --- a/programs/bpf_loader/src/syscalls/mod.rs +++ b/programs/bpf_loader/src/syscalls/mod.rs @@ -1812,7 +1812,7 @@ mod tests { super::*, crate::BpfAllocator, core::slice, - solana_program_runtime::{invoke_context::InvokeContext, sysvar_cache::SysvarCache}, + solana_program_runtime::{invoke_context::InvokeContext, with_mock_invoke_context}, solana_rbpf::{ aligned_memory::AlignedMemory, ebpf::{self, HOST_ALIGN}, @@ -1820,17 +1820,16 @@ mod tests { vm::{BuiltInFunction, Config}, }, solana_sdk::{ - account::AccountSharedData, + account::{create_account_shared_data_for_test, AccountSharedData}, bpf_loader, fee_calculator::FeeCalculator, hash::hashv, instruction::Instruction, program::check_type_assumptions, stable_layout::stable_instruction::StableInstruction, - sysvar::{clock::Clock, epoch_schedule::EpochSchedule, rent::Rent}, - transaction_context::TransactionContext, + sysvar::{self, clock::Clock, epoch_schedule::EpochSchedule}, }, - std::{borrow::Cow, cell::RefCell, mem, rc::Rc, str::FromStr}, + std::{mem, str::FromStr}, }; macro_rules! assert_access_violation { @@ -1847,7 +1846,6 @@ mod tests { macro_rules! prepare_mockup { ($invoke_context:ident, - $transaction_context:ident, $program_key:ident, $loader_key:expr $(,)?) => { let $program_key = Pubkey::new_unique(); @@ -1858,9 +1856,7 @@ mod tests { ), ($program_key, AccountSharedData::new(0, 0, &$loader_key)), ]; - let mut $transaction_context = - TransactionContext::new(transaction_accounts, Some(Rent::default()), 1, 1); - let mut $invoke_context = InvokeContext::new_mock(&mut $transaction_context, &[]); + with_mock_invoke_context!($invoke_context, transaction_context, transaction_accounts); $invoke_context .transaction_context .get_next_instruction_context() @@ -2062,12 +2058,7 @@ mod tests { #[test] #[should_panic(expected = "UserError(SyscallError(Abort))")] fn test_syscall_abort() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let config = Config::default(); let mut memory_mapping = MemoryMapping::new(vec![], &config).unwrap(); let mut result = ProgramResult::Ok(0); @@ -2087,12 +2078,7 @@ mod tests { #[test] #[should_panic(expected = "UserError(SyscallError(Panic(\"Gaggablaghblagh!\", 42, 84)))")] fn test_syscall_sol_panic() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let string = "Gaggablaghblagh!"; let config = Config::default(); @@ -2138,12 +2124,7 @@ mod tests { #[test] fn test_syscall_sol_log() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let string = "Gaggablaghblagh!"; let config = Config::default(); @@ -2221,12 +2202,7 @@ mod tests { #[test] fn test_syscall_sol_log_u64() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let cost = invoke_context.get_compute_budget().log_64_units; invoke_context.mock_set_remaining(cost); @@ -2257,12 +2233,7 @@ mod tests { #[test] fn test_syscall_sol_pubkey() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let cost = invoke_context.get_compute_budget().log_pubkey_units; let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap(); @@ -2335,12 +2306,7 @@ mod tests { // large alloc { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let mut heap = AlignedMemory::::zero_filled(100); let mut memory_mapping = MemoryMapping::new( vec![ @@ -2400,12 +2366,7 @@ mod tests { // many small unaligned allocs { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let mut heap = AlignedMemory::::zero_filled(100); let mut memory_mapping = MemoryMapping::new( vec![ @@ -2455,12 +2416,7 @@ mod tests { // many small aligned allocs { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let mut heap = AlignedMemory::::zero_filled(100); let mut memory_mapping = MemoryMapping::new( vec![ @@ -2511,12 +2467,7 @@ mod tests { // aligned allocs fn aligned() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let mut heap = AlignedMemory::::zero_filled(100); let config = Config::default(); let mut memory_mapping = MemoryMapping::new( @@ -2565,12 +2516,7 @@ mod tests { #[test] fn test_syscall_sha256() { let config = Config::default(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader_deprecated::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader_deprecated::id()); let bytes1 = "Gaggablaghblagh!"; let bytes2 = "flurbos"; @@ -2685,12 +2631,7 @@ mod tests { use solana_zk_token_sdk::curve25519::curve_syscall_traits::CURVE25519_EDWARDS; let config = Config::default(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let valid_bytes: [u8; 32] = [ 201, 179, 241, 122, 180, 185, 239, 50, 183, 52, 221, 0, 153, 195, 43, 18, 22, 38, 187, @@ -2770,12 +2711,7 @@ mod tests { use solana_zk_token_sdk::curve25519::curve_syscall_traits::CURVE25519_RISTRETTO; let config = Config::default(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let valid_bytes: [u8; 32] = [ 226, 242, 174, 10, 106, 188, 78, 113, 168, 132, 169, 97, 197, 0, 81, 95, 88, 227, 11, @@ -2857,12 +2793,7 @@ mod tests { }; let config = Config::default(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let left_point: [u8; 32] = [ 33, 124, 71, 170, 117, 69, 151, 247, 59, 12, 95, 125, 133, 166, 64, 5, 2, 27, 90, 27, @@ -3034,12 +2965,7 @@ mod tests { }; let config = Config::default(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let left_point: [u8; 32] = [ 208, 165, 125, 204, 2, 100, 218, 17, 170, 194, 23, 9, 102, 156, 134, 136, 217, 190, 98, @@ -3213,12 +3139,7 @@ mod tests { }; let config = Config::default(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let scalar_a: [u8; 32] = [ 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250, @@ -3378,13 +3299,25 @@ mod tests { sysvar_cache.set_fees(src_fees.clone()); sysvar_cache.set_rent(src_rent); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); - invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); + let transaction_accounts = vec![ + ( + sysvar::clock::id(), + create_account_shared_data_for_test(&src_clock), + ), + ( + sysvar::epoch_schedule::id(), + create_account_shared_data_for_test(&src_epochschedule), + ), + ( + sysvar::fees::id(), + create_account_shared_data_for_test(&src_fees), + ), + ( + sysvar::rent::id(), + create_account_shared_data_for_test(&src_rent), + ), + ]; + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); // Test clock sysvar { @@ -3635,12 +3568,7 @@ mod tests { ) .unwrap(); - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let mut result = ProgramResult::Ok(0); SyscallSetReturnData::call( @@ -3700,13 +3628,20 @@ mod tests { }) .collect::>(); let instruction_trace = [1, 2, 3, 2, 2, 3, 4, 3]; - let mut transaction_context = - TransactionContext::new(transaction_accounts, None, 4, instruction_trace.len()); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); for (index_in_trace, stack_height) in instruction_trace.into_iter().enumerate() { - while stack_height <= transaction_context.get_instruction_context_stack_height() { - transaction_context.pop().unwrap(); + while stack_height + <= invoke_context + .transaction_context + .get_instruction_context_stack_height() + { + invoke_context.transaction_context.pop().unwrap(); } - if stack_height > transaction_context.get_instruction_context_stack_height() { + if stack_height + > invoke_context + .transaction_context + .get_instruction_context_stack_height() + { let instruction_accounts = [InstructionAccount { index_in_transaction: index_in_trace.saturating_add(1) as IndexOfAccount, index_in_caller: 0, // This is incorrect / inconsistent but not required @@ -3714,14 +3649,14 @@ mod tests { is_signer: false, is_writable: false, }]; - transaction_context + invoke_context + .transaction_context .get_next_instruction_context() .unwrap() .configure(&[0], &instruction_accounts, &[index_in_trace as u8]); - transaction_context.push().unwrap(); + invoke_context.transaction_context.push().unwrap(); } } - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let syscall_base_cost = invoke_context.get_compute_budget().syscall_base_cost; @@ -3840,12 +3775,7 @@ mod tests { fn test_create_program_address() { // These tests duplicate the direct tests in solana_program::pubkey - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let address = bpf_loader_upgradeable::id(); let exceeded_seed = &[127; MAX_SEED_LEN + 1]; @@ -3954,12 +3884,7 @@ mod tests { #[test] fn test_find_program_address() { - prepare_mockup!( - invoke_context, - transaction_context, - program_id, - bpf_loader::id(), - ); + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let cost = invoke_context .get_compute_budget() .create_program_address_units; diff --git a/programs/config/src/config_processor.rs b/programs/config/src/config_processor.rs index 0c15896701..3550d03f64 100644 --- a/programs/config/src/config_processor.rs +++ b/programs/config/src/config_processor.rs @@ -170,10 +170,9 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - None, - None, expected_result, super::process_instruction, + |_invoke_context| {}, ) } diff --git a/programs/loader-v3/src/lib.rs b/programs/loader-v3/src/lib.rs index 81eee362a3..474454c1af 100644 --- a/programs/loader-v3/src/lib.rs +++ b/programs/loader-v3/src/lib.rs @@ -642,10 +642,9 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - None, - None, expected_result, super::process_instruction, + |_invoke_context| {}, ) } diff --git a/programs/sbf/benches/bpf_loader.rs b/programs/sbf/benches/bpf_loader.rs index 11061c5fa1..8424635ae9 100644 --- a/programs/sbf/benches/bpf_loader.rs +++ b/programs/sbf/benches/bpf_loader.rs @@ -15,10 +15,7 @@ use { create_ebpf_vm, create_vm, serialization::serialize_parameters, syscalls::create_loader, }, solana_measure::measure::Measure, - solana_program_runtime::{ - compute_budget::ComputeBudget, - invoke_context::{with_mock_invoke_context, InvokeContext}, - }, + solana_program_runtime::{compute_budget::ComputeBudget, invoke_context::InvokeContext}, solana_rbpf::{ ebpf::MM_INPUT_START, elf::Executable, @@ -33,13 +30,17 @@ use { loader_utils::{load_program, load_program_from_file}, }, solana_sdk::{ + account::AccountSharedData, bpf_loader, client::SyncClient, entrypoint::SUCCESS, feature_set::FeatureSet, instruction::{AccountMeta, Instruction}, message::Message, + native_loader, + pubkey::Pubkey, signature::Signer, + transaction_context::InstructionAccount, }, std::{mem, sync::Arc}, test::Bencher, @@ -48,6 +49,41 @@ use { const ARMSTRONG_LIMIT: u64 = 500; const ARMSTRONG_EXPECTED: u64 = 5; +macro_rules! with_mock_invoke_context { + ($invoke_context:ident, $loader_id:expr, $account_size:expr) => { + let program_key = Pubkey::new_unique(); + let transaction_accounts = vec![ + ( + $loader_id, + AccountSharedData::new(0, 0, &native_loader::id()), + ), + (program_key, AccountSharedData::new(1, 0, &$loader_id)), + ( + Pubkey::new_unique(), + AccountSharedData::new(2, $account_size, &program_key), + ), + ]; + let instruction_accounts = vec![InstructionAccount { + index_in_transaction: 2, + index_in_caller: 2, + index_in_callee: 0, + is_signer: false, + is_writable: false, + }]; + solana_program_runtime::with_mock_invoke_context!( + $invoke_context, + transaction_context, + transaction_accounts + ); + $invoke_context + .transaction_context + .get_next_instruction_context() + .unwrap() + .configure(&[0, 1], &instruction_accounts, &[]); + $invoke_context.push().unwrap(); + }; +} + #[bench] fn bench_program_create_executable(bencher: &mut Bencher) { let elf = load_program_from_file("bench_alu"); @@ -75,82 +111,81 @@ fn bench_program_alu(bencher: &mut Bencher) { .unwrap(); inner_iter.write_u64::(0).unwrap(); let elf = load_program_from_file("bench_alu"); - let loader_id = bpf_loader::id(); - with_mock_invoke_context(loader_id, 10000001, false, |invoke_context| { - let loader = create_loader( - &invoke_context.feature_set, - &ComputeBudget::default(), - true, - true, - false, - ) - .unwrap(); - let executable = Executable::::from_elf(&elf, loader).unwrap(); + with_mock_invoke_context!(invoke_context, bpf_loader::id(), 10000001); - let mut verified_executable = - VerifiedExecutable::::from_executable(executable) - .unwrap(); + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, + ) + .unwrap(); + let executable = Executable::::from_elf(&elf, loader).unwrap(); - verified_executable.jit_compile().unwrap(); - create_vm!( - vm, - &verified_executable, - stack, - heap, - vec![MemoryRegion::new_writable(&mut inner_iter, MM_INPUT_START)], - vec![], - invoke_context - ); - let mut vm = vm.unwrap(); + let mut verified_executable = + VerifiedExecutable::::from_executable(executable) + .unwrap(); - println!("Interpreted:"); + verified_executable.jit_compile().unwrap(); + create_vm!( + vm, + &verified_executable, + stack, + heap, + vec![MemoryRegion::new_writable(&mut inner_iter, MM_INPUT_START)], + vec![], + &mut invoke_context + ); + let mut vm = vm.unwrap(); + + println!("Interpreted:"); + vm.env + .context_object_pointer + .mock_set_remaining(std::i64::MAX as u64); + let (instructions, result) = vm.execute_program(true); + assert_eq!(SUCCESS, result.unwrap()); + assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter)); + assert_eq!( + ARMSTRONG_EXPECTED, + LittleEndian::read_u64(&inner_iter[mem::size_of::()..]) + ); + + bencher.iter(|| { vm.env .context_object_pointer .mock_set_remaining(std::i64::MAX as u64); - let (instructions, result) = vm.execute_program(true); - assert_eq!(SUCCESS, result.unwrap()); - assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter)); - assert_eq!( - ARMSTRONG_EXPECTED, - LittleEndian::read_u64(&inner_iter[mem::size_of::()..]) - ); - - bencher.iter(|| { - vm.env - .context_object_pointer - .mock_set_remaining(std::i64::MAX as u64); - vm.execute_program(true).1.unwrap(); - }); - let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); - println!(" {:?} instructions", instructions); - println!(" {:?} ns/iter median", summary.median as u64); - assert!(0f64 != summary.median); - let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million; - println!(" {:?} MIPS", mips); - println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_interpreted_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips); - - println!("JIT to native:"); - assert_eq!(SUCCESS, vm.execute_program(false).1.unwrap()); - assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter)); - assert_eq!( - ARMSTRONG_EXPECTED, - LittleEndian::read_u64(&inner_iter[mem::size_of::()..]) - ); - - bencher.iter(|| { - vm.env - .context_object_pointer - .mock_set_remaining(std::i64::MAX as u64); - vm.execute_program(false).1.unwrap(); - }); - let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); - println!(" {:?} instructions", instructions); - println!(" {:?} ns/iter median", summary.median as u64); - assert!(0f64 != summary.median); - let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million; - println!(" {:?} MIPS", mips); - println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_jit_to_native_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips); + vm.execute_program(true).1.unwrap(); }); + let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); + println!(" {:?} instructions", instructions); + println!(" {:?} ns/iter median", summary.median as u64); + assert!(0f64 != summary.median); + let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million; + println!(" {:?} MIPS", mips); + println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_interpreted_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips); + + println!("JIT to native:"); + assert_eq!(SUCCESS, vm.execute_program(false).1.unwrap()); + assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter)); + assert_eq!( + ARMSTRONG_EXPECTED, + LittleEndian::read_u64(&inner_iter[mem::size_of::()..]) + ); + + bencher.iter(|| { + vm.env + .context_object_pointer + .mock_set_remaining(std::i64::MAX as u64); + vm.execute_program(false).1.unwrap(); + }); + let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); + println!(" {:?} instructions", instructions); + println!(" {:?} ns/iter median", summary.median as u64); + assert!(0f64 != summary.median); + let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million; + println!(" {:?} MIPS", mips); + println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_jit_to_native_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips); } #[bench] @@ -190,111 +225,107 @@ fn bench_program_execute_noop(bencher: &mut Bencher) { #[bench] fn bench_create_vm(bencher: &mut Bencher) { let elf = load_program_from_file("noop"); - let loader_id = bpf_loader::id(); - with_mock_invoke_context(loader_id, 10000001, false, |invoke_context| { - const BUDGET: u64 = 200_000; - invoke_context.mock_set_remaining(BUDGET); + with_mock_invoke_context!(invoke_context, bpf_loader::id(), 10000001); + const BUDGET: u64 = 200_000; + invoke_context.mock_set_remaining(BUDGET); - let loader = create_loader( - &invoke_context.feature_set, - &ComputeBudget::default(), - true, - true, - false, - ) - .unwrap(); - let executable = Executable::::from_elf(&elf, loader).unwrap(); + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, + ) + .unwrap(); + let executable = Executable::::from_elf(&elf, loader).unwrap(); - let verified_executable = - VerifiedExecutable::::from_executable(executable) - .unwrap(); + let verified_executable = + VerifiedExecutable::::from_executable(executable) + .unwrap(); - // Serialize account data - let (_serialized, regions, account_lengths) = serialize_parameters( - invoke_context.transaction_context, - invoke_context - .transaction_context - .get_current_instruction_context() - .unwrap(), - true, // should_cap_ix_accounts - ) - .unwrap(); + // Serialize account data + let (_serialized, regions, account_lengths) = serialize_parameters( + invoke_context.transaction_context, + invoke_context + .transaction_context + .get_current_instruction_context() + .unwrap(), + true, // should_cap_ix_accounts + ) + .unwrap(); - bencher.iter(|| { - create_vm!( - vm, - &verified_executable, - stack, - heap, - clone_regions(®ions), - account_lengths.clone(), - invoke_context - ); - let _ = vm.unwrap(); - }); + bencher.iter(|| { + create_vm!( + vm, + &verified_executable, + stack, + heap, + clone_regions(®ions), + account_lengths.clone(), + &mut invoke_context + ); + let _ = vm.unwrap(); }); } #[bench] fn bench_instruction_count_tuner(_bencher: &mut Bencher) { let elf = load_program_from_file("tuner"); - let loader_id = bpf_loader::id(); - with_mock_invoke_context(loader_id, 10000001, true, |invoke_context| { - const BUDGET: u64 = 200_000; - invoke_context.mock_set_remaining(BUDGET); + with_mock_invoke_context!(invoke_context, bpf_loader::id(), 10000001); + const BUDGET: u64 = 200_000; + invoke_context.mock_set_remaining(BUDGET); - // Serialize account data - let (_serialized, regions, account_lengths) = serialize_parameters( - invoke_context.transaction_context, - invoke_context - .transaction_context - .get_current_instruction_context() - .unwrap(), - true, // should_cap_ix_accounts - ) - .unwrap(); + // Serialize account data + let (_serialized, regions, account_lengths) = serialize_parameters( + invoke_context.transaction_context, + invoke_context + .transaction_context + .get_current_instruction_context() + .unwrap(), + true, // should_cap_ix_accounts + ) + .unwrap(); - let loader = create_loader( - &invoke_context.feature_set, - &ComputeBudget::default(), - true, - true, - false, - ) - .unwrap(); - let executable = Executable::::from_elf(&elf, loader).unwrap(); + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, + ) + .unwrap(); + let executable = Executable::::from_elf(&elf, loader).unwrap(); - let verified_executable = - VerifiedExecutable::::from_executable(executable) - .unwrap(); + let verified_executable = + VerifiedExecutable::::from_executable(executable) + .unwrap(); - create_vm!( - vm, - &verified_executable, - stack, - heap, - regions, - account_lengths, - invoke_context - ); - let mut vm = vm.unwrap(); + create_vm!( + vm, + &verified_executable, + stack, + heap, + regions, + account_lengths, + &mut invoke_context + ); + let mut vm = vm.unwrap(); - let mut measure = Measure::start("tune"); - let (instructions, _result) = vm.execute_program(true); - measure.stop(); + let mut measure = Measure::start("tune"); + let (instructions, _result) = vm.execute_program(true); + measure.stop(); - assert_eq!( - 0, - vm.env.context_object_pointer.get_remaining(), - "Tuner must consume the whole budget" - ); - println!( - "{:?} compute units took {:?} us ({:?} instructions)", - BUDGET - vm.env.context_object_pointer.get_remaining(), - measure.as_us(), - instructions, - ); - }); + assert_eq!( + 0, + vm.env.context_object_pointer.get_remaining(), + "Tuner must consume the whole budget" + ); + println!( + "{:?} compute units took {:?} us ({:?} instructions)", + BUDGET - vm.env.context_object_pointer.get_remaining(), + measure.as_us(), + instructions, + ); } fn clone_regions(regions: &[MemoryRegion]) -> Vec { diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 870e774a78..007cbde7bb 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -22,6 +22,7 @@ use { solana_program_runtime::{ compute_budget::ComputeBudget, invoke_context::InvokeContext, timings::ExecuteTimings, }, + solana_rbpf::vm::ContextObject, solana_runtime::{ bank::{ DurableNonceFee, InnerInstruction, TransactionBalancesSet, TransactionExecutionDetails, @@ -60,13 +61,7 @@ use { std::collections::HashMap, }; use { - solana_bpf_loader_program::{ - create_ebpf_vm, create_vm, - serialization::{deserialize_parameters, serialize_parameters}, - syscalls::create_loader, - }, - solana_program_runtime::invoke_context::with_mock_invoke_context, - solana_rbpf::{elf::Executable, verifier::RequisiteVerifier, vm::VerifiedExecutable}, + solana_program_runtime::invoke_context::mock_process_instruction, solana_runtime::{ bank::Bank, bank_client::BankClient, @@ -80,7 +75,6 @@ use { bpf_loader, bpf_loader_deprecated, client::SyncClient, clock::UnixTimestamp, - entrypoint::SUCCESS, fee_calculator::FeeRateGovernor, genesis_config::ClusterType, hash::Hash, @@ -95,131 +89,6 @@ use { std::{str::FromStr, sync::Arc, time::Duration}, }; -fn run_program(name: &str) -> u64 { - let elf = load_program_from_file(name); - let loader_id = bpf_loader::id(); - with_mock_invoke_context(loader_id, 0, false, |invoke_context| { - let loader = create_loader( - &invoke_context.feature_set, - &ComputeBudget::default(), - true, - true, - true, - ) - .unwrap(); - let executable = Executable::::from_elf(&elf, loader).unwrap(); - - #[allow(unused_mut)] - let mut verified_executable = - VerifiedExecutable::::from_executable(executable) - .unwrap(); - - let run_program_iterations = { - #[cfg(target_arch = "x86_64")] - { - verified_executable.jit_compile().unwrap(); - 2 - } - #[cfg(not(target_arch = "x86_64"))] - 1 - }; - - let mut instruction_count = 0; - let mut trace_log = None; - for i in 0..run_program_iterations { - let transaction_context = &mut invoke_context.transaction_context; - let instruction_context = transaction_context - .get_current_instruction_context() - .unwrap(); - let caller = *instruction_context - .get_last_program_key(transaction_context) - .unwrap(); - transaction_context - .set_return_data(caller, Vec::new()) - .unwrap(); - - let (parameter_bytes, regions, account_lengths) = serialize_parameters( - invoke_context.transaction_context, - invoke_context - .transaction_context - .get_current_instruction_context() - .unwrap(), - true, // should_cap_ix_accounts - ) - .unwrap(); - - { - create_vm!( - vm, - &verified_executable, - stack, - heap, - regions, - account_lengths.clone(), - invoke_context - ); - let mut vm = vm.unwrap(); - let (compute_units_consumed, result) = vm.execute_program(i == 0); - assert_eq!(SUCCESS, result.unwrap()); - if i == 1 { - assert_eq!(instruction_count, compute_units_consumed); - } - instruction_count = compute_units_consumed; - if i == 0 { - trace_log = Some( - vm.env - .context_object_pointer - .trace_log_stack - .last() - .expect("Inconsistent trace log stack") - .trace_log - .clone(), - ); - } else { - let interpreter = trace_log.as_ref().unwrap().as_slice(); - let mut jit = vm - .env - .context_object_pointer - .trace_log_stack - .last() - .expect("Inconsistent trace log stack") - .trace_log - .as_slice(); - if jit.len() > interpreter.len() { - jit = &jit[0..interpreter.len()]; - } - assert_eq!(interpreter, jit); - trace_log = None; - } - } - assert!(match deserialize_parameters( - invoke_context.transaction_context, - invoke_context - .transaction_context - .get_current_instruction_context() - .unwrap(), - parameter_bytes.as_slice(), - &account_lengths, - ) { - Ok(()) => true, - Err(InstructionError::ModifiedProgramId) => true, - Err(InstructionError::ExternalAccountLamportSpend) => true, - Err(InstructionError::ReadonlyLamportChange) => true, - Err(InstructionError::ExecutableLamportChange) => true, - Err(InstructionError::ExecutableAccountNotRentExempt) => true, - Err(InstructionError::ExecutableModified) => true, - Err(InstructionError::AccountDataSizeChanged) => true, - Err(InstructionError::InvalidRealloc) => true, - Err(InstructionError::ExecutableDataModified) => true, - Err(InstructionError::ReadonlyDataModified) => true, - Err(InstructionError::ExternalAccountDataModified) => true, - _ => false, - }); - } - instruction_count - }) -} - #[cfg(feature = "sbf_rust")] fn process_transaction_and_record_inner( bank: &Bank, @@ -1503,8 +1372,8 @@ fn assert_instruction_count() { ("noop++", 5), ("relative_call", 210), ("return_data", 980), - ("sanity", 2377), - ("sanity++", 2277), + ("sanity", 3259), + ("sanity++", 3159), ("secp256k1_recover", 25383), ("sha", 1355), ("struct_pass", 108), @@ -1526,30 +1395,70 @@ fn assert_instruction_count() { ("solana_sbf_rust_noop", 275), ("solana_sbf_rust_param_passing", 146), ("solana_sbf_rust_rand", 378), - ("solana_sbf_rust_sanity", 51931), + ("solana_sbf_rust_sanity", 10759), ("solana_sbf_rust_secp256k1_recover", 91185), ("solana_sbf_rust_sha", 24059), ]); } - let mut passed = true; println!("\n {:36} expected actual diff", "SBF program"); - for program in programs.iter() { - let count = run_program(program.0); - let diff: i64 = count as i64 - program.1 as i64; - println!( - " {:36} {:8} {:6} {:+5} ({:+3.0}%)", - program.0, - program.1, - count, - diff, - 100.0_f64 * count as f64 / program.1 as f64 - 100.0_f64, + for (program_name, expected_consumption) in programs.iter() { + let loader_id = bpf_loader::id(); + let program_key = Pubkey::new_unique(); + let mut transaction_accounts = vec![ + (program_key, AccountSharedData::new(0, 0, &loader_id)), + ( + Pubkey::new_unique(), + AccountSharedData::new(0, 8, &program_key), + ), + ]; + let instruction_accounts = vec![AccountMeta { + pubkey: transaction_accounts[1].0, + is_signer: false, + is_writable: false, + }]; + transaction_accounts[0] + .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(); + + print!(" {:36} {:8}", program_name, *expected_consumption); + mock_process_instruction( + &loader_id, + vec![0], + &[], + 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; + println!( + "{:6} {:+5} ({:+3.0}%)", + consumption, + diff, + 100.0_f64 * consumption as f64 / expected_consumption as f64 - 100.0_f64, + ); + assert_eq!(consumption, expected_consumption); + Ok(()) + }, + |_invoke_context| {}, ); - if count > program.1 { - passed = false; - } } - assert!(passed); } #[test] diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index a99407f73c..c24bb6bd12 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -11,6 +11,7 @@ use { invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check, }, solana_sdk::{ + clock::Clock, feature_set, instruction::InstructionError, program_utils::limited_deserialize, @@ -20,7 +21,6 @@ use { program::id, state::{Authorized, Lockup}, }, - sysvar::clock::Clock, transaction_context::{IndexOfAccount, InstructionContext, TransactionContext}, }, }; @@ -499,7 +499,10 @@ mod tests { invoke_context::mock_process_instruction, sysvar_cache::SysvarCache, }, solana_sdk::{ - account::{self, AccountSharedData, ReadableAccount, WritableAccount}, + account::{ + create_account_shared_data_for_test, AccountSharedData, ReadableAccount, + WritableAccount, + }, account_utils::StateMut, clock::{Epoch, UnixTimestamp}, feature_set::FeatureSet, @@ -517,7 +520,8 @@ mod tests { MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION, }, stake_history::{StakeHistory, StakeHistoryEntry}, - system_program, sysvar, + system_program, + sysvar::{clock, rent, rewards, stake_history}, }, solana_vote_program::vote_state::{self, VoteState, VoteStateVersions}, std::{ @@ -530,22 +534,26 @@ mod tests { }; /// The "new" behavior enables all features - fn feature_set_new_behavior() -> FeatureSet { - FeatureSet::all_enabled() + fn feature_set_new_behavior() -> Arc { + Arc::new(FeatureSet::all_enabled()) } /// The "old" behavior is before the stake minimum delegation was raised - fn feature_set_old_behavior() -> FeatureSet { + fn feature_set_old_behavior() -> Arc { let mut feature_set = feature_set_new_behavior(); - feature_set.deactivate(&feature_set::stake_raise_minimum_delegation_to_1_sol::id()); + Arc::get_mut(&mut feature_set) + .unwrap() + .deactivate(&feature_set::stake_raise_minimum_delegation_to_1_sol::id()); feature_set } /// The "old old" behavior is both before the stake minimum delegation was raised *and* before /// undelegated stake accounts could have zero lamports beyond rent - fn feature_set_old_old_behavior() -> FeatureSet { + fn feature_set_old_old_behavior() -> Arc { let mut feature_set = feature_set_old_behavior(); - feature_set.deactivate(&feature_set::stake_allow_zero_undelegated_amount::id()); + Arc::get_mut(&mut feature_set) + .unwrap() + .deactivate(&feature_set::stake_allow_zero_undelegated_amount::id()); feature_set } @@ -574,29 +582,11 @@ mod tests { } fn process_instruction( - feature_set: &FeatureSet, + feature_set: Arc, instruction_data: &[u8], transaction_accounts: Vec<(Pubkey, AccountSharedData)>, instruction_accounts: Vec, expected_result: Result<(), InstructionError>, - ) -> Vec { - process_instruction_with_overrides( - instruction_data, - transaction_accounts, - instruction_accounts, - None, - Some(Arc::new(feature_set.clone())), - expected_result, - ) - } - - fn process_instruction_with_overrides( - instruction_data: &[u8], - transaction_accounts: Vec<(Pubkey, AccountSharedData)>, - instruction_accounts: Vec, - sysvar_cache_override: Option<&SysvarCache>, - feature_set_override: Option>, - expected_result: Result<(), InstructionError>, ) -> Vec { mock_process_instruction( &id(), @@ -604,15 +594,16 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - sysvar_cache_override, - feature_set_override, expected_result, super::process_instruction, + |invoke_context| { + invoke_context.feature_set = Arc::clone(&feature_set); + }, ) } fn process_instruction_as_one_arg( - feature_set: &FeatureSet, + feature_set: Arc, instruction: &Instruction, expected_result: Result<(), InstructionError>, ) -> Vec { @@ -621,26 +612,22 @@ mod tests { .iter() .map(|meta| meta.pubkey) .collect(); - pubkeys.insert(sysvar::clock::id()); + pubkeys.insert(clock::id()); let transaction_accounts = pubkeys .iter() .map(|pubkey| { ( *pubkey, - if sysvar::clock::check_id(pubkey) { - account::create_account_shared_data_for_test( - &sysvar::clock::Clock::default(), - ) - } else if sysvar::rewards::check_id(pubkey) { - account::create_account_shared_data_for_test( - &sysvar::rewards::Rewards::new(0.0), - ) - } else if sysvar::stake_history::check_id(pubkey) { - account::create_account_shared_data_for_test(&StakeHistory::default()) + if clock::check_id(pubkey) { + create_account_shared_data_for_test(&clock::Clock::default()) + } else if rewards::check_id(pubkey) { + create_account_shared_data_for_test(&rewards::Rewards::new(0.0)) + } else if stake_history::check_id(pubkey) { + create_account_shared_data_for_test(&StakeHistory::default()) } else if stake_config::check_id(pubkey) { config::create_account(0, &stake_config::Config::default()) - } else if sysvar::rent::check_id(pubkey) { - account::create_account_shared_data_for_test(&Rent::default()) + } else if rent::check_id(pubkey) { + create_account_shared_data_for_test(&Rent::default()) } else if *pubkey == invalid_stake_state_pubkey() { AccountSharedData::new(0, 0, &id()) } else if *pubkey == invalid_vote_state_pubkey() { @@ -654,7 +641,7 @@ mod tests { }) .collect(); process_instruction( - feature_set, + Arc::clone(&feature_set), &instruction.data, transaction_accounts, instruction.accounts.clone(), @@ -677,9 +664,9 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_process_instruction(feature_set: FeatureSet) { + fn test_stake_process_instruction(feature_set: Arc) { process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::initialize( &Pubkey::new_unique(), &Authorized::default(), @@ -688,7 +675,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::authorize( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -699,7 +686,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::split( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -709,7 +696,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::merge( &Pubkey::new_unique(), &invalid_stake_state_pubkey(), @@ -718,7 +705,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::split_with_seed( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -730,7 +717,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::delegate_stake( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -739,7 +726,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::withdraw( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -750,12 +737,12 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::deactivate_stake(&Pubkey::new_unique(), &Pubkey::new_unique()), Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::set_lockup( &Pubkey::new_unique(), &LockupArgs::default(), @@ -764,7 +751,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::deactivate_delinquent_stake( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -773,7 +760,7 @@ mod tests { Err(InstructionError::IncorrectProgramId), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::deactivate_delinquent_stake( &Pubkey::new_unique(), &invalid_vote_state_pubkey(), @@ -782,7 +769,7 @@ mod tests { Err(InstructionError::InvalidAccountData), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::deactivate_delinquent_stake( &Pubkey::new_unique(), &invalid_vote_state_pubkey(), @@ -794,9 +781,9 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_spoofed_stake_accounts(feature_set: FeatureSet) { + fn test_spoofed_stake_accounts(feature_set: Arc) { process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::initialize( &spoofed_stake_state_pubkey(), &Authorized::default(), @@ -805,7 +792,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::authorize( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -816,7 +803,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::split( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -826,7 +813,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::split( &Pubkey::new_unique(), &Pubkey::new_unique(), @@ -836,7 +823,7 @@ mod tests { Err(InstructionError::IncorrectProgramId), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::merge( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -845,7 +832,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::merge( &Pubkey::new_unique(), &spoofed_stake_state_pubkey(), @@ -854,7 +841,7 @@ mod tests { Err(InstructionError::IncorrectProgramId), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::split_with_seed( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -866,7 +853,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::delegate_stake( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -875,7 +862,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::withdraw( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -886,12 +873,12 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::deactivate_stake(&spoofed_stake_state_pubkey(), &Pubkey::new_unique()), Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::set_lockup( &spoofed_stake_state_pubkey(), &LockupArgs::default(), @@ -900,7 +887,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::deactivate_delinquent_stake( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -909,7 +896,7 @@ mod tests { Err(InstructionError::InvalidAccountOwner), ); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction::redelegate( &spoofed_stake_state_pubkey(), &Pubkey::new_unique(), @@ -922,24 +909,21 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_process_instruction_decode_bail(feature_set: FeatureSet) { + fn test_stake_process_instruction_decode_bail(feature_set: Arc) { // these will not call stake_state, have bogus contents let stake_address = Pubkey::new_unique(); let stake_account = create_default_stake_account(); - let rent_address = sysvar::rent::id(); + let rent_address = rent::id(); let rent = Rent::default(); - let rent_account = account::create_account_shared_data_for_test(&rent); - let rewards_address = sysvar::rewards::id(); - let rewards_account = - account::create_account_shared_data_for_test(&sysvar::rewards::Rewards::new(0.0)); - let stake_history_address = sysvar::stake_history::id(); - let stake_history_account = - account::create_account_shared_data_for_test(&StakeHistory::default()); + let rent_account = create_account_shared_data_for_test(&rent); + let rewards_address = rewards::id(); + let rewards_account = create_account_shared_data_for_test(&rewards::Rewards::new(0.0)); + let stake_history_address = stake_history::id(); + let stake_history_account = create_account_shared_data_for_test(&StakeHistory::default()); let vote_address = Pubkey::new_unique(); let vote_account = AccountSharedData::new(0, 0, &solana_vote_program::id()); - let clock_address = sysvar::clock::id(); - let clock_account = - account::create_account_shared_data_for_test(&sysvar::clock::Clock::default()); + let clock_address = clock::id(); + let clock_account = create_account_shared_data_for_test(&clock::Clock::default()); let config_address = stake_config::id(); let config_account = config::create_account(0, &stake_config::Config::default()); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -948,7 +932,7 @@ mod tests { // gets the "is_empty()" check process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Initialize( Authorized::default(), Lockup::default(), @@ -961,7 +945,7 @@ mod tests { // no account for rent process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Initialize( Authorized::default(), Lockup::default(), @@ -978,7 +962,7 @@ mod tests { // fails to deserialize stake state process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Initialize( Authorized::default(), Lockup::default(), @@ -1005,7 +989,7 @@ mod tests { // gets the first check in delegate, wrong number of accounts process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), vec![(stake_address, stake_account.clone())], vec![AccountMeta { @@ -1018,7 +1002,7 @@ mod tests { // gets the sub-check for number of args process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), vec![(stake_address, stake_account.clone())], vec![AccountMeta { @@ -1031,7 +1015,7 @@ mod tests { // gets the check non-deserialize-able account in delegate_stake process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), vec![ (stake_address, stake_account.clone()), @@ -1072,7 +1056,7 @@ mod tests { // Tests 3rd keyed account is of correct type (Clock instead of rewards) in withdraw process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(withdrawal_amount)).unwrap(), vec![ (stake_address, stake_account.clone()), @@ -1107,7 +1091,7 @@ mod tests { // Tests correct number of accounts are provided in withdraw process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(withdrawal_amount)).unwrap(), vec![(stake_address, stake_account.clone())], vec![AccountMeta { @@ -1120,7 +1104,7 @@ mod tests { // Tests 2nd keyed account is of correct type (Clock instead of rewards) in deactivate process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), vec![ (stake_address, stake_account.clone()), @@ -1143,7 +1127,7 @@ mod tests { // Tests correct number of accounts are provided in deactivate process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), Vec::new(), Vec::new(), @@ -1152,14 +1136,14 @@ mod tests { // Tests correct number of accounts are provided in deactivate_delinquent process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DeactivateDelinquent).unwrap(), Vec::new(), Vec::new(), Err(InstructionError::NotEnoughAccountKeys), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DeactivateDelinquent).unwrap(), vec![(stake_address, stake_account.clone())], vec![AccountMeta { @@ -1170,7 +1154,7 @@ mod tests { Err(InstructionError::NotEnoughAccountKeys), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DeactivateDelinquent).unwrap(), vec![(stake_address, stake_account), (vote_address, vote_account)], vec![ @@ -1191,7 +1175,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_checked_instructions(feature_set: FeatureSet) { + fn test_stake_checked_instructions(feature_set: Arc) { let stake_address = Pubkey::new_unique(); let staker = Pubkey::new_unique(); let staker_account = create_default_account(); @@ -1200,13 +1184,13 @@ mod tests { let authorized_address = Pubkey::new_unique(); let authorized_account = create_default_account(); let new_authorized_account = create_default_account(); - let clock_address = sysvar::clock::id(); - let clock_account = account::create_account_shared_data_for_test(&Clock::default()); + let clock_address = clock::id(); + let clock_account = create_account_shared_data_for_test(&Clock::default()); let custodian = Pubkey::new_unique(); let custodian_account = create_default_account(); let rent = Rent::default(); - let rent_address = sysvar::rent::id(); - let rent_account = account::create_account_shared_data_for_test(&rent); + let rent_address = rent::id(); + let rent_account = create_account_shared_data_for_test(&rent); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -1215,7 +1199,7 @@ mod tests { initialize_checked(&stake_address, &Authorized { staker, withdrawer }); instruction.accounts[3] = AccountMeta::new_readonly(withdrawer, false); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction, Err(InstructionError::MissingRequiredSignature), ); @@ -1227,7 +1211,7 @@ mod tests { &id(), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::InitializeChecked).unwrap(), vec![ (stake_address, stake_account), @@ -1270,7 +1254,7 @@ mod tests { ); instruction.accounts[3] = AccountMeta::new_readonly(staker, false); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction, Err(InstructionError::MissingRequiredSignature), ); @@ -1284,7 +1268,7 @@ mod tests { ); instruction.accounts[3] = AccountMeta::new_readonly(withdrawer, false); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction, Err(InstructionError::MissingRequiredSignature), ); @@ -1298,7 +1282,7 @@ mod tests { ) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::AuthorizeChecked(StakeAuthorize::Staker)).unwrap(), vec![ (stake_address, stake_account.clone()), @@ -1332,7 +1316,7 @@ mod tests { ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::AuthorizeChecked( StakeAuthorize::Withdrawer, )) @@ -1384,7 +1368,7 @@ mod tests { ); instruction.accounts[3] = AccountMeta::new_readonly(staker, false); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction, Err(InstructionError::MissingRequiredSignature), ); @@ -1400,7 +1384,7 @@ mod tests { ); instruction.accounts[3] = AccountMeta::new_readonly(staker, false); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction, Err(InstructionError::MissingRequiredSignature), ); @@ -1414,7 +1398,7 @@ mod tests { ) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::AuthorizeCheckedWithSeed( AuthorizeCheckedWithSeedArgs { stake_authorize: StakeAuthorize::Staker, @@ -1455,7 +1439,7 @@ mod tests { ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::AuthorizeCheckedWithSeed( AuthorizeCheckedWithSeedArgs { stake_authorize: StakeAuthorize::Withdrawer, @@ -1507,7 +1491,7 @@ mod tests { ); instruction.accounts[2] = AccountMeta::new_readonly(custodian, false); process_instruction_as_one_arg( - &feature_set, + Arc::clone(&feature_set), &instruction, Err(InstructionError::MissingRequiredSignature), ); @@ -1522,7 +1506,7 @@ mod tests { .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction.data, vec![ (clock_address, clock_account), @@ -1553,7 +1537,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_initialize(feature_set: FeatureSet) { + fn test_stake_initialize(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let stake_lamports = rent_exempt_reserve; @@ -1572,10 +1556,7 @@ mod tests { .unwrap(); let mut transaction_accounts = vec![ (stake_address, stake_account.clone()), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; let instruction_accounts = vec![ AccountMeta { @@ -1584,7 +1565,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::rent::id(), + pubkey: rent::id(), is_signer: false, is_writable: false, }, @@ -1592,7 +1573,7 @@ mod tests { // should pass let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -1611,7 +1592,7 @@ mod tests { // 2nd time fails, can't move it from anything other than uninit->init transaction_accounts[0] = (stake_address, accounts[0].clone()); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -1621,14 +1602,14 @@ mod tests { // not enough balance for rent transaction_accounts[1] = ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&Rent { + rent::id(), + create_account_shared_data_for_test(&Rent { lamports_per_byte_year: rent.lamports_per_byte_year + 1, ..rent }), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -1640,7 +1621,7 @@ mod tests { AccountSharedData::new(stake_lamports, StakeState::size_of() + 1, &id()); transaction_accounts[0] = (stake_address, stake_account); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -1651,7 +1632,7 @@ mod tests { AccountSharedData::new(stake_lamports, StakeState::size_of() - 1, &id()); transaction_accounts[0] = (stake_address, stake_account); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts, instruction_accounts, @@ -1661,7 +1642,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_authorize(feature_set: FeatureSet) { + fn test_authorize(feature_set: Arc) { let authority_address = solana_sdk::pubkey::new_rand(); let authority_address_2 = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); @@ -1680,12 +1661,12 @@ mod tests { (to_address, to_account), (authority_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; let mut instruction_accounts = vec![ @@ -1695,7 +1676,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -1708,7 +1689,7 @@ mod tests { // should fail, uninit process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Staker, @@ -1729,7 +1710,7 @@ mod tests { .unwrap(); transaction_accounts[0] = (stake_address, stake_account); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Staker, @@ -1741,7 +1722,7 @@ mod tests { ); transaction_accounts[0] = (stake_address, accounts[0].clone()); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Withdrawer, @@ -1761,7 +1742,7 @@ mod tests { // A second authorization signed by the stake account should fail process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address_2, StakeAuthorize::Staker, @@ -1776,7 +1757,7 @@ mod tests { instruction_accounts[0].is_signer = false; instruction_accounts[2].is_signer = true; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address_2, StakeAuthorize::Staker, @@ -1805,12 +1786,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -1821,7 +1802,7 @@ mod tests { }, ]; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -1832,7 +1813,7 @@ mod tests { // Test that withdrawal to account fails without authorized withdrawer instruction_accounts[4].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts, @@ -1842,7 +1823,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_authorize_override(feature_set: FeatureSet) { + fn test_authorize_override(feature_set: Arc) { let authority_address = solana_sdk::pubkey::new_rand(); let mallory_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); @@ -1858,8 +1839,8 @@ mod tests { (stake_address, stake_account), (authority_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ]; let mut instruction_accounts = vec![ @@ -1869,7 +1850,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -1882,7 +1863,7 @@ mod tests { // Authorize a staker pubkey and move the withdrawer key into cold storage. let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Staker, @@ -1898,7 +1879,7 @@ mod tests { instruction_accounts[0].is_signer = false; instruction_accounts[2].is_signer = true; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( mallory_address, StakeAuthorize::Staker, @@ -1912,7 +1893,7 @@ mod tests { // Verify the original staker no longer has access. process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Staker, @@ -1927,7 +1908,7 @@ mod tests { instruction_accounts[0].is_signer = true; instruction_accounts[2].is_signer = false; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Withdrawer, @@ -1947,7 +1928,7 @@ mod tests { is_writable: false, }; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Withdrawer, @@ -1961,7 +1942,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_authorize_with_seed(feature_set: FeatureSet) { + fn test_authorize_with_seed(feature_set: Arc) { let authority_base_address = solana_sdk::pubkey::new_rand(); let authority_address = solana_sdk::pubkey::new_rand(); let seed = "42"; @@ -1978,8 +1959,8 @@ mod tests { (stake_address, stake_account), (authority_base_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ]; let mut instruction_accounts = vec![ @@ -1994,7 +1975,7 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -2002,7 +1983,7 @@ mod tests { // Wrong seed process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::AuthorizeWithSeed( AuthorizeWithSeedArgs { new_authorized_pubkey: authority_address, @@ -2029,7 +2010,7 @@ mod tests { )) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -2039,7 +2020,7 @@ mod tests { // Set stake authority let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -2058,7 +2039,7 @@ mod tests { )) .unwrap(); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -2068,7 +2049,7 @@ mod tests { // No longer withdraw authority process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts, instruction_accounts, @@ -2078,7 +2059,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_authorize_delegated_stake(feature_set: FeatureSet) { + fn test_authorize_delegated_stake(feature_set: Arc) { let authority_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -2106,12 +2087,12 @@ mod tests { AccountSharedData::new(42, 0, &system_program::id()), ), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -2130,12 +2111,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -2148,7 +2129,7 @@ mod tests { // delegate stake let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2158,7 +2139,7 @@ mod tests { // deactivate, so we can re-delegate let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), vec![ @@ -2168,7 +2149,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -2179,7 +2160,7 @@ mod tests { // authorize let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authority_address, StakeAuthorize::Staker, @@ -2193,7 +2174,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -2215,7 +2196,7 @@ mod tests { instruction_accounts[0].is_signer = false; instruction_accounts[1].pubkey = vote_address_2; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2229,7 +2210,7 @@ mod tests { is_writable: false, }); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts, @@ -2243,7 +2224,7 @@ mod tests { // Test another staking action process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts, vec![ @@ -2253,7 +2234,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -2269,7 +2250,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_delegate(feature_set: FeatureSet) { + fn test_stake_delegate(feature_set: Arc) { let mut vote_state = VoteState::default(); for i in 0..1000 { vote_state::process_slot_vote_unchecked(&mut vote_state, i); @@ -2311,13 +2292,10 @@ mod tests { (stake_address, stake_account.clone()), (vote_address, vote_account), (vote_address_2, vote_account_2.clone()), + (clock::id(), create_account_shared_data_for_test(&clock)), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -2336,12 +2314,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -2355,7 +2333,7 @@ mod tests { // should fail, unsigned stake account instruction_accounts[0].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2365,7 +2343,7 @@ mod tests { // should pass let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2389,12 +2367,9 @@ mod tests { // verify that delegate fails as stake is active and not deactivating clock.epoch += 1; transaction_accounts[0] = (stake_address, accounts[0].clone()); - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2403,7 +2378,7 @@ mod tests { // deactivate let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), vec![ @@ -2413,7 +2388,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -2426,7 +2401,7 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); instruction_accounts[1].pubkey = vote_address_2; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2437,7 +2412,7 @@ mod tests { // verify that delegate succeeds to same vote account // when stake is deactivating let accounts_2 = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2452,7 +2427,7 @@ mod tests { transaction_accounts[0] = (stake_address, accounts_2[0].clone()); instruction_accounts[1].pubkey = vote_address_2; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2461,15 +2436,12 @@ mod tests { // without stake history, cool down is instantaneous clock.epoch += 1; - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); // verify that delegate can be called to new vote account, 2nd is redelegate transaction_accounts[0] = (stake_address, accounts[0].clone()); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2497,7 +2469,7 @@ mod tests { .1 .set_owner(solana_sdk::pubkey::new_rand()); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2509,7 +2481,7 @@ mod tests { stake_account.set_state(&stake_state).unwrap(); transaction_accounts[0] = (stake_address, stake_account); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts, instruction_accounts, @@ -2519,7 +2491,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_redelegate_consider_balance_changes(feature_set: FeatureSet) { + fn test_redelegate_consider_balance_changes(feature_set: Arc) { let mut clock = Clock::default(); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -2549,13 +2521,10 @@ mod tests { AccountSharedData::new(1, 0, &system_program::id()), ), (authority_address, AccountSharedData::default()), + (clock::id(), create_account_shared_data_for_test(&clock)), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -2574,12 +2543,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -2601,7 +2570,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -2613,7 +2582,7 @@ mod tests { ]; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), delegate_instruction_accounts.clone(), @@ -2622,12 +2591,9 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); clock.epoch += 1; - transaction_accounts[2] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[2] = (clock::id(), create_account_shared_data_for_test(&clock)); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), deactivate_instruction_accounts.clone(), @@ -2637,13 +2603,10 @@ mod tests { // Once deactivated, we withdraw stake to new account clock.epoch += 1; - transaction_accounts[2] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[2] = (clock::id(), create_account_shared_data_for_test(&clock)); let withdraw_lamports = initial_lamports / 2; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(withdraw_lamports)).unwrap(), transaction_accounts.clone(), vec![ @@ -2658,12 +2621,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -2680,12 +2643,9 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); clock.epoch += 1; - transaction_accounts[2] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[2] = (clock::id(), create_account_shared_data_for_test(&clock)); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), delegate_instruction_accounts.clone(), @@ -2698,12 +2658,9 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); clock.epoch += 1; - transaction_accounts[2] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[2] = (clock::id(), create_account_shared_data_for_test(&clock)); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), deactivate_instruction_accounts, @@ -2718,12 +2675,9 @@ mod tests { .unwrap(); clock.epoch += 1; - transaction_accounts[2] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[2] = (clock::id(), create_account_shared_data_for_test(&clock)); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts, delegate_instruction_accounts, @@ -2737,7 +2691,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split(feature_set: FeatureSet) { + fn test_split(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = minimum_delegation * 2; @@ -2752,6 +2706,13 @@ mod tests { let mut transaction_accounts = vec![ (stake_address, AccountSharedData::default()), (split_to_address, split_to_account), + ( + rent::id(), + create_account_shared_data_for_test(&Rent { + lamports_per_byte_year: 0, + ..Rent::default() + }), + ), ]; let instruction_accounts = vec![ AccountMeta { @@ -2766,13 +2727,6 @@ mod tests { }, ]; - // Define rent here so that it's used consistently for setting the rent exempt reserve - // and in the sysvar cache used for mock instruction processing. - let mut sysvar_cache_override = SysvarCache::default(); - sysvar_cache_override.set_rent(Rent { - lamports_per_byte_year: 0, - ..Rent::default() - }); let feature_set = Arc::new(feature_set); for state in [ @@ -2789,22 +2743,20 @@ mod tests { transaction_accounts[0] = (stake_address, stake_account); // should fail, split more than available - process_instruction_with_overrides( + process_instruction( + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports + 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), - Some(&sysvar_cache_override), - Some(Arc::clone(&feature_set)), Err(InstructionError::InsufficientFunds), ); // should pass - let accounts = process_instruction_with_overrides( + let accounts = process_instruction( + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), - Some(&sysvar_cache_override), - Some(Arc::clone(&feature_set)), Ok(()), ); // no lamport leakage @@ -2835,19 +2787,18 @@ mod tests { ) .unwrap(); transaction_accounts[1] = (split_to_address, split_to_account); - process_instruction_with_overrides( + process_instruction( + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts, instruction_accounts, - Some(&sysvar_cache_override), - Some(Arc::clone(&feature_set)), Err(InstructionError::IncorrectProgramId), ); } #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_withdraw_stake(feature_set: FeatureSet) { + fn test_withdraw_stake(feature_set: Arc) { let recipient_address = solana_sdk::pubkey::new_rand(); let authority_address = solana_sdk::pubkey::new_rand(); let custodian_address = solana_sdk::pubkey::new_rand(); @@ -2877,16 +2828,16 @@ mod tests { ), (custodian_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&Rent::free()), + rent::id(), + create_account_shared_data_for_test(&Rent::free()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -2905,12 +2856,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -2924,7 +2875,7 @@ mod tests { // should fail, no signer instruction_accounts[4].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2934,7 +2885,7 @@ mod tests { // should pass, signed keyed account and uninitialized let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2950,7 +2901,7 @@ mod tests { custodian: custodian_address, }; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Initialize( Authorized::auto(&stake_address), lockup, @@ -2964,7 +2915,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::rent::id(), + pubkey: rent::id(), is_signer: false, is_writable: false, }, @@ -2975,7 +2926,7 @@ mod tests { // should fail, signed keyed account and locked up, more than available process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports + 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -2984,7 +2935,7 @@ mod tests { // Stake some lamports (available lamports for withdrawals will reduce to zero) let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), vec![ @@ -2999,12 +2950,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3023,7 +2974,7 @@ mod tests { // withdrawal before deactivate works for rewards amount process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(10)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3032,7 +2983,7 @@ mod tests { // withdrawal of rewards fails if not in excess of stake process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(11)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3041,7 +2992,7 @@ mod tests { // deactivate the stake before withdrawal let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), vec![ @@ -3051,7 +3002,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -3065,14 +3016,11 @@ mod tests { epoch: 100, ..Clock::default() }; - transaction_accounts[5] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[5] = (clock::id(), create_account_shared_data_for_test(&clock)); // Try to withdraw more than what's available process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports + 11)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3081,7 +3029,7 @@ mod tests { // Try to withdraw all lamports let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports + 10)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3111,7 +3059,7 @@ mod tests { transaction_accounts[2] = (recipient_address, stake_account); instruction_accounts[4].pubkey = authority_address; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(u64::MAX - 10)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3128,7 +3076,7 @@ mod tests { .unwrap(); transaction_accounts[0] = (stake_address, stake_account); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts, @@ -3138,7 +3086,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_withdraw_stake_before_warmup(feature_set: FeatureSet) { + fn test_withdraw_stake_before_warmup(feature_set: Arc) { let recipient_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -3165,13 +3113,10 @@ mod tests { (stake_address, stake_account), (vote_address, vote_account), (recipient_address, AccountSharedData::default()), + (clock::id(), create_account_shared_data_for_test(&clock)), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -3190,12 +3135,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3208,7 +3153,7 @@ mod tests { // Stake some lamports (available lamports for withdrawals will reduce to zero) let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), vec![ @@ -3223,12 +3168,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3249,16 +3194,13 @@ mod tests { &[stake_from(&accounts[0]).unwrap().delegation], ); transaction_accounts[4] = ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&stake_history), + stake_history::id(), + create_account_shared_data_for_test(&stake_history), ); clock.epoch = 0; - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw( total_lamports - stake_lamports + 1, )) @@ -3271,7 +3213,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_withdraw_lockup(feature_set: FeatureSet) { + fn test_withdraw_lockup(feature_set: Arc) { let recipient_address = solana_sdk::pubkey::new_rand(); let custodian_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); @@ -3296,13 +3238,10 @@ mod tests { (stake_address, stake_account.clone()), (recipient_address, AccountSharedData::default()), (custodian_address, AccountSharedData::default()), + (clock::id(), create_account_shared_data_for_test(&clock)), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; let mut instruction_accounts = vec![ @@ -3317,12 +3256,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3335,7 +3274,7 @@ mod tests { // should fail, lockup is still in force process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(total_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3349,7 +3288,7 @@ mod tests { is_writable: false, }); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(total_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3369,7 +3308,7 @@ mod tests { .unwrap(); transaction_accounts[0] = (stake_address, stake_account_self_as_custodian); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(total_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3381,12 +3320,9 @@ mod tests { // should pass, lockup has expired instruction_accounts.pop(); clock.epoch += 1; - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(total_lamports)).unwrap(), transaction_accounts, instruction_accounts, @@ -3397,7 +3333,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_withdraw_rent_exempt(feature_set: FeatureSet) { + fn test_withdraw_rent_exempt(feature_set: Arc) { let recipient_address = solana_sdk::pubkey::new_rand(); let custodian_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); @@ -3420,12 +3356,12 @@ mod tests { (recipient_address, AccountSharedData::default()), (custodian_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; let instruction_accounts = vec![ @@ -3440,12 +3376,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3458,7 +3394,7 @@ mod tests { // should pass, withdrawing initialized account down to minimum balance process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3467,7 +3403,7 @@ mod tests { // should fail, withdrawal that would leave less than rent-exempt reserve process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(stake_lamports + 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3476,7 +3412,7 @@ mod tests { // should pass, withdrawal of complete account process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw( stake_lamports + rent_exempt_reserve, )) @@ -3489,7 +3425,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_deactivate(feature_set: FeatureSet) { + fn test_deactivate(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = minimum_delegation; @@ -3510,12 +3446,12 @@ mod tests { (stake_address, stake_account), (vote_address, vote_account), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -3529,7 +3465,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -3538,7 +3474,7 @@ mod tests { // should fail, not signed instruction_accounts[0].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3548,7 +3484,7 @@ mod tests { // should fail, not staked yet process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3557,7 +3493,7 @@ mod tests { // Staking let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), vec![ @@ -3572,12 +3508,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3593,7 +3529,7 @@ mod tests { // should pass let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -3603,7 +3539,7 @@ mod tests { // should fail, only works once process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts, instruction_accounts, @@ -3613,7 +3549,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_set_lockup(feature_set: FeatureSet) { + fn test_set_lockup(feature_set: Arc) { let custodian_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); @@ -3644,16 +3580,16 @@ mod tests { (authorized_address, AccountSharedData::default()), (custodian_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&Rent::free()), + rent::id(), + create_account_shared_data_for_test(&Rent::free()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -3667,7 +3603,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -3680,7 +3616,7 @@ mod tests { // should fail, wrong state process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3694,7 +3630,7 @@ mod tests { custodian: custodian_address, }; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Initialize( Authorized::auto(&stake_address), lockup, @@ -3708,7 +3644,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::rent::id(), + pubkey: rent::id(), is_signer: false, is_writable: false, }, @@ -3720,7 +3656,7 @@ mod tests { // should fail, not signed instruction_accounts[2].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3730,7 +3666,7 @@ mod tests { // should pass process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3739,7 +3675,7 @@ mod tests { // Staking let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), vec![ @@ -3754,12 +3690,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -3776,7 +3712,7 @@ mod tests { // should fail, not signed instruction_accounts[2].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3786,7 +3722,7 @@ mod tests { // should pass process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3805,7 +3741,7 @@ mod tests { instruction_accounts[0].is_signer = true; instruction_accounts[2].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3816,7 +3752,7 @@ mod tests { // should pass, custodian can change it process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3829,14 +3765,11 @@ mod tests { epoch: Epoch::MAX, ..Clock::default() }; - transaction_accounts[4] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[4] = (clock::id(), create_account_shared_data_for_test(&clock)); // should fail, custodian cannot change it process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3847,7 +3780,7 @@ mod tests { instruction_accounts[0].is_signer = true; instruction_accounts[2].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts.clone(), instruction_accounts.clone(), @@ -3856,7 +3789,7 @@ mod tests { // Change authorized withdrawer let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Authorize( authorized_address, StakeAuthorize::Withdrawer, @@ -3870,7 +3803,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -3886,7 +3819,7 @@ mod tests { // should fail, previous authorized withdrawer cannot change the lockup anymore process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, transaction_accounts, instruction_accounts, @@ -3899,7 +3832,7 @@ mod tests { /// - Assert 2: accounts with a balance less-than the rent exemption do not initialize #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_initialize_minimum_balance(feature_set: FeatureSet) { + fn test_initialize_minimum_balance(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let stake_address = solana_sdk::pubkey::new_rand(); @@ -3915,7 +3848,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::rent::id(), + pubkey: rent::id(), is_signer: false, is_writable: false, }, @@ -3929,14 +3862,11 @@ mod tests { ] { let stake_account = AccountSharedData::new(lamports, StakeState::size_of(), &id()); process_instruction( - &feature_set, + Arc::clone(&feature_set), &instruction_data, vec![ (stake_address, stake_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ], instruction_accounts.clone(), expected_result, @@ -3957,7 +3887,7 @@ mod tests { /// more information.) #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_delegate_minimum_stake_delegation(feature_set: FeatureSet) { + fn test_delegate_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -3981,12 +3911,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -4015,18 +3945,18 @@ mod tests { ) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), vec![ (stake_address, stake_account), (vote_address, vote_account.clone()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -4052,7 +3982,7 @@ mod tests { /// LT | LT | Err #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_minimum_stake_delegation(feature_set: FeatureSet) { + fn test_split_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -4121,15 +4051,12 @@ mod tests { ) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(dest_reserve + delegation)).unwrap(), vec![ (source_address, source_account), (dest_address, dest_account.clone()), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ], instruction_accounts.clone(), expected_result.clone(), @@ -4147,7 +4074,7 @@ mod tests { /// delegation is not OK #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_full_amount_minimum_stake_delegation(feature_set: FeatureSet) { + fn test_split_full_amount_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -4198,15 +4125,12 @@ mod tests { ) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(source_account.lamports())).unwrap(), vec![ (source_address, source_account), (dest_address, dest_account.clone()), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ], instruction_accounts.clone(), expected_result.clone(), @@ -4220,7 +4144,7 @@ mod tests { /// the minimum split amount reduces accordingly. #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_initialized_split_destination_minimum_balance(feature_set: FeatureSet) { + fn test_initialized_split_destination_minimum_balance(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let source_address = Pubkey::new_unique(); @@ -4296,15 +4220,12 @@ mod tests { .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(split_amount)).unwrap(), vec![ (source_address, source_account), (destination_address, destination_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ], instruction_accounts.clone(), expected_result.clone(), @@ -4318,7 +4239,7 @@ mod tests { #[test_case(feature_set_old_behavior(), &[Ok(()), Ok(())]; "old_behavior")] #[test_case(feature_set_new_behavior(), &[ Err(InstructionError::InsufficientFunds), Err(InstructionError::InsufficientFunds) ] ; "new_behavior")] fn test_staked_split_destination_minimum_balance( - feature_set: FeatureSet, + feature_set: Arc, expected_results: &[Result<(), InstructionError>], ) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -4427,15 +4348,12 @@ mod tests { ) .unwrap(); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(split_amount)).unwrap(), vec![ (source_address, source_account.clone()), (destination_address, destination_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ], instruction_accounts.clone(), expected_result.clone(), @@ -4470,7 +4388,7 @@ mod tests { /// - Assert 2: withdrawing so remaining stake is less-than the minimum is not OK #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_withdraw_minimum_stake_delegation(feature_set: FeatureSet) { + fn test_withdraw_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -4492,12 +4410,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -4530,7 +4448,7 @@ mod tests { let withdraw_amount = (starting_stake_delegation + rewards_balance) - ending_stake_delegation; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(withdraw_amount)).unwrap(), vec![ (stake_address, stake_account), @@ -4539,16 +4457,16 @@ mod tests { AccountSharedData::new(rent_exempt_reserve, 0, &system_program::id()), ), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&Rent::free()), + rent::id(), + create_account_shared_data_for_test(&Rent::free()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), @@ -4581,7 +4499,7 @@ mod tests { #[test_case(feature_set_old_old_behavior(), Ok(()); "old_old_behavior")] #[test_case(feature_set_new_behavior(), Err(StakeError::InsufficientDelegation.into()); "new_behavior")] fn test_behavior_withdrawal_then_redelegate_with_less_than_minimum_stake_delegation( - feature_set: FeatureSet, + feature_set: Arc, expected_result: Result<(), InstructionError>, ) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -4605,22 +4523,16 @@ mod tests { recipient_address, AccountSharedData::new(rent_exempt_reserve, 0, &system_program::id()), ), + (clock::id(), create_account_shared_data_for_test(&clock)), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ( stake_config::id(), config::create_account(0, &stake_config::Config::default()), ), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; let instruction_accounts = vec![ AccountMeta { @@ -4634,12 +4546,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -4651,7 +4563,7 @@ mod tests { ]; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Initialize( Authorized::auto(&stake_address), Lockup::default(), @@ -4665,7 +4577,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::rent::id(), + pubkey: rent::id(), is_signer: false, is_writable: false, }, @@ -4675,7 +4587,7 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -4685,12 +4597,9 @@ mod tests { transaction_accounts[1] = (vote_address, accounts[1].clone()); clock.epoch += 1; - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Deactivate).unwrap(), transaction_accounts.clone(), vec![ @@ -4700,7 +4609,7 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, @@ -4710,14 +4619,11 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); clock.epoch += 1; - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); let withdraw_amount = accounts[0].lamports() - (rent_exempt_reserve + minimum_delegation - 1); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Withdraw(withdraw_amount)).unwrap(), transaction_accounts.clone(), vec![ @@ -4732,12 +4638,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -4752,7 +4658,7 @@ mod tests { transaction_accounts[0] = (stake_address, accounts[0].clone()); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), transaction_accounts, instruction_accounts, @@ -4762,7 +4668,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_source_uninitialized(feature_set: FeatureSet) { + fn test_split_source_uninitialized(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -4809,28 +4715,28 @@ mod tests { // // and splitting should fail when the split amount is greater than the balance process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(0)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), ); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports + 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -4841,7 +4747,7 @@ mod tests { // this should work instruction_accounts[1].pubkey = split_to_address; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -4852,7 +4758,7 @@ mod tests { // no signers should fail instruction_accounts[0].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts, instruction_accounts, @@ -4862,7 +4768,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_split_not_uninitialized(feature_set: FeatureSet) { + fn test_split_split_not_uninitialized(feature_set: Arc) { let stake_lamports = 42; let stake_address = solana_sdk::pubkey::new_rand(); let stake_account = AccountSharedData::new_data_with_space( @@ -4899,7 +4805,7 @@ mod tests { ) .unwrap(); process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), vec![ (stake_address, stake_account.clone()), @@ -4913,7 +4819,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_more_than_staked(feature_set: FeatureSet) { + fn test_split_more_than_staked(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -4943,10 +4849,7 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; let instruction_accounts = vec![ AccountMeta { @@ -4962,7 +4865,7 @@ mod tests { ]; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts, instruction_accounts, @@ -4972,7 +4875,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_with_rent(feature_set: FeatureSet) { + fn test_split_with_rent(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -5022,15 +4925,12 @@ mod tests { let mut transaction_accounts = vec![ (stake_address, stake_account), (split_to_address, split_to_account.clone()), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; // not enough to make a non-zero stake account process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(minimum_balance - 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -5039,7 +4939,7 @@ mod tests { // doesn't leave enough for initial stake to be non-zero process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split( stake_lamports - minimum_balance + 1, )) @@ -5052,7 +4952,7 @@ mod tests { // split account already has way enough lamports transaction_accounts[1].1.set_lamports(*minimum_balance); let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports - minimum_balance)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5082,7 +4982,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_to_account_with_rent_exempt_reserve(feature_set: FeatureSet) { + fn test_split_to_account_with_rent_exempt_reserve(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -5136,15 +5036,12 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account.clone()), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; // split more than available fails process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports + 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -5153,7 +5050,7 @@ mod tests { // should work let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5207,7 +5104,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_from_larger_sized_account(feature_set: FeatureSet) { + fn test_split_from_larger_sized_account(feature_set: Arc) { let rent = Rent::default(); let source_larger_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of() + 100); let split_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -5262,15 +5159,12 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account.clone()), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; // split more than available fails process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports + 1)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -5279,7 +5173,7 @@ mod tests { // should work let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports / 2)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -5338,7 +5232,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_from_smaller_sized_account(feature_set: FeatureSet) { + fn test_split_from_smaller_sized_account(feature_set: Arc) { let rent = Rent::default(); let source_smaller_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let split_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of() + 100); @@ -5389,15 +5283,12 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account.clone()), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; // should always return error when splitting to larger account process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(split_amount)).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -5406,7 +5297,7 @@ mod tests { // Splitting 100% of source should not make a difference process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5417,7 +5308,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_100_percent_of_source(feature_set: FeatureSet) { + fn test_split_100_percent_of_source(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -5464,15 +5355,12 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account), (split_to_address, split_to_account.clone()), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; // split 100% over to dest let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5513,7 +5401,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_100_percent_of_source_to_account_with_lamports(feature_set: FeatureSet) { + fn test_split_100_percent_of_source_to_account_with_lamports(feature_set: Arc) { let rent = Rent::default(); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -5567,15 +5455,12 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account.clone()), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; // split 100% over to dest let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5609,7 +5494,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_split_rent_exemptness(feature_set: FeatureSet) { + fn test_split_rent_exemptness(feature_set: Arc) { let rent = Rent::default(); let source_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of() + 100); let split_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); @@ -5657,13 +5542,10 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5689,13 +5571,10 @@ mod tests { let transaction_accounts = vec![ (stake_address, stake_account), (split_to_address, split_to_account), - ( - sysvar::rent::id(), - account::create_account_shared_data_for_test(&rent), - ), + (rent::id(), create_account_shared_data_for_test(&rent)), ]; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Split(stake_lamports)).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5747,7 +5626,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_merge(feature_set: FeatureSet) { + fn test_merge(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let merge_from_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); @@ -5765,12 +5644,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -5808,19 +5687,19 @@ mod tests { (merge_from_address, merge_from_account), (authorized_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; // Authorized staker signature required... instruction_accounts[4].is_signer = false; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -5829,7 +5708,7 @@ mod tests { instruction_accounts[4].is_signer = true; let accounts = process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -5877,7 +5756,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_merge_self_fails(feature_set: FeatureSet) { + fn test_merge_self_fails(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); @@ -5907,12 +5786,12 @@ mod tests { (stake_address, stake_account), (authorized_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; let instruction_accounts = vec![ @@ -5927,12 +5806,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -5944,7 +5823,7 @@ mod tests { ]; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts, instruction_accounts, @@ -5954,7 +5833,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_merge_incorrect_authorized_staker(feature_set: FeatureSet) { + fn test_merge_incorrect_authorized_staker(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let merge_from_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); @@ -5972,12 +5851,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -6016,18 +5895,18 @@ mod tests { (authorized_address, AccountSharedData::default()), (wrong_authorized_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; instruction_accounts[4].pubkey = wrong_authorized_address; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -6036,7 +5915,7 @@ mod tests { instruction_accounts[4].pubkey = authorized_address; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -6048,7 +5927,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_merge_invalid_account_data(feature_set: FeatureSet) { + fn test_merge_invalid_account_data(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let merge_from_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); @@ -6065,12 +5944,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -6107,17 +5986,17 @@ mod tests { (merge_from_address, merge_from_account), (authorized_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts, instruction_accounts.clone(), @@ -6129,7 +6008,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_merge_fake_stake_source(feature_set: FeatureSet) { + fn test_merge_fake_stake_source(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let merge_from_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); @@ -6153,12 +6032,12 @@ mod tests { (merge_from_address, merge_from_account), (authorized_address, AccountSharedData::default()), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), + clock::id(), + create_account_shared_data_for_test(&Clock::default()), ), ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), + stake_history::id(), + create_account_shared_data_for_test(&StakeHistory::default()), ), ]; let instruction_accounts = vec![ @@ -6173,12 +6052,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -6190,7 +6069,7 @@ mod tests { ]; process_instruction( - &feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts, instruction_accounts, @@ -6200,7 +6079,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_merge_active_stake(feature_set: FeatureSet) { + fn test_merge_active_stake(feature_set: Arc) { let stake_address = solana_sdk::pubkey::new_rand(); let merge_from_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); @@ -6263,13 +6142,10 @@ mod tests { (stake_address, stake_account), (merge_from_address, merge_from_account), (authorized_address, AccountSharedData::default()), + (clock::id(), create_account_shared_data_for_test(&clock)), ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&stake_history), + stake_history::id(), + create_account_shared_data_for_test(&stake_history), ), ]; let instruction_accounts = vec![ @@ -6284,12 +6160,12 @@ mod tests { is_writable: true, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -6301,7 +6177,7 @@ mod tests { ]; fn try_merge( - feature_set: &FeatureSet, + feature_set: Arc, transaction_accounts: Vec<(Pubkey, AccountSharedData)>, mut instruction_accounts: Vec, expected_result: Result<(), InstructionError>, @@ -6311,7 +6187,7 @@ mod tests { instruction_accounts.swap(0, 1); } let accounts = process_instruction( - feature_set, + Arc::clone(&feature_set), &serialize(&StakeInstruction::Merge).unwrap(), transaction_accounts.clone(), instruction_accounts.clone(), @@ -6328,7 +6204,7 @@ mod tests { // stake activation epoch, source initialized succeeds try_merge( - &feature_set, + Arc::clone(&feature_set), transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), @@ -6352,13 +6228,10 @@ mod tests { deactivating, }, ); - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); transaction_accounts[4] = ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&stake_history), + stake_history::id(), + create_account_shared_data_for_test(&stake_history), ); if stake_amount == stake.stake(clock.epoch, Some(&stake_history)) && merge_from_amount == merge_from_stake.stake(clock.epoch, Some(&stake_history)) @@ -6366,7 +6239,7 @@ mod tests { break; } try_merge( - &feature_set, + Arc::clone(&feature_set), transaction_accounts.clone(), instruction_accounts.clone(), Err(InstructionError::from(StakeError::MergeTransientStake)), @@ -6375,7 +6248,7 @@ mod tests { // Both fully activated works try_merge( - &feature_set, + Arc::clone(&feature_set), transaction_accounts.clone(), instruction_accounts.clone(), Ok(()), @@ -6428,13 +6301,10 @@ mod tests { deactivating, }, ); - transaction_accounts[3] = ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&clock), - ); + transaction_accounts[3] = (clock::id(), create_account_shared_data_for_test(&clock)); transaction_accounts[4] = ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&stake_history), + stake_history::id(), + create_account_shared_data_for_test(&stake_history), ); if 0 == stake.stake(clock.epoch, Some(&stake_history)) && 0 == merge_from_stake.stake(clock.epoch, Some(&stake_history)) @@ -6442,7 +6312,7 @@ mod tests { break; } try_merge( - &feature_set, + Arc::clone(&feature_set), transaction_accounts.clone(), instruction_accounts.clone(), Err(InstructionError::from(StakeError::MergeTransientStake)), @@ -6451,7 +6321,7 @@ mod tests { // Both fully deactivated works try_merge( - &feature_set, + Arc::clone(&feature_set), transaction_accounts, instruction_accounts, Ok(()), @@ -6460,7 +6330,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_get_minimum_delegation(feature_set: FeatureSet) { + fn test_stake_get_minimum_delegation(feature_set: Arc) { let stake_address = Pubkey::new_unique(); let stake_account = create_default_stake_account(); let instruction_data = serialize(&StakeInstruction::GetMinimumDelegation).unwrap(); @@ -6477,8 +6347,6 @@ mod tests { &instruction_data, transaction_accounts, instruction_accounts, - None, - Some(Arc::new(feature_set)), Ok(()), |invoke_context| { super::process_instruction(invoke_context)?; @@ -6489,6 +6357,9 @@ mod tests { assert_eq!(expected_minimum_delegation, actual_minimum_delegation); Ok(()) }, + |invoke_context| { + invoke_context.feature_set = Arc::clone(&feature_set); + }, ); } @@ -6515,10 +6386,10 @@ mod tests { // disabled | bad | none || Err NotEnoughAccountKeys #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_stake_process_instruction_error_ordering(feature_set: FeatureSet) { + fn test_stake_process_instruction_error_ordering(feature_set: Arc) { let rent = Rent::default(); - let rent_address = sysvar::rent::id(); - let rent_account = account::create_account_shared_data_for_test(&rent); + let rent_address = rent::id(); + let rent_account = create_account_shared_data_for_test(&rent); let good_stake_address = Pubkey::new_unique(); let good_stake_account = AccountSharedData::new(u64::MAX, StakeState::size_of(), &id()); @@ -6598,33 +6469,26 @@ mod tests { Err(InstructionError::NotEnoughAccountKeys), ), ] { - let mut feature_set = feature_set.clone(); + let mut feature_set = Arc::new(FeatureSet::clone(&feature_set)); if !is_feature_enabled { - feature_set.deactivate( + Arc::get_mut(&mut feature_set).unwrap().deactivate( &feature_set::add_get_minimum_delegation_instruction_to_stake_program::id(), ); } - mock_process_instruction( - &id(), - Vec::new(), + process_instruction( + feature_set, &instruction.data, transaction_accounts.clone(), instruction_accounts.clone(), - None, - Some(Arc::new(feature_set)), expected_result, - super::process_instruction, ); } } #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_deactivate_delinquent(feature_set: FeatureSet) { - let feature_set = Arc::new(feature_set); - let mut sysvar_cache_override = SysvarCache::default(); - + fn test_deactivate_delinquent(feature_set: Arc) { let reference_vote_address = Pubkey::new_unique(); let vote_address = Pubkey::new_unique(); let stake_address = Pubkey::new_unique(); @@ -6666,23 +6530,26 @@ mod tests { let current_epoch = 20; - sysvar_cache_override.set_clock(Clock { - epoch: current_epoch, - ..Clock::default() - }); - let process_instruction_deactivate_delinquent = |stake_address: &Pubkey, stake_account: &AccountSharedData, vote_account: &AccountSharedData, reference_vote_account: &AccountSharedData, expected_result| { - process_instruction_with_overrides( + process_instruction( + Arc::clone(&feature_set), &serialize(&StakeInstruction::DeactivateDelinquent).unwrap(), vec![ (*stake_address, stake_account.clone()), (vote_address, vote_account.clone()), (reference_vote_address, reference_vote_account.clone()), + ( + clock::id(), + create_account_shared_data_for_test(&Clock { + epoch: current_epoch, + ..Clock::default() + }), + ), ], vec![ AccountMeta { @@ -6701,8 +6568,6 @@ mod tests { is_writable: false, }, ], - Some(&sysvar_cache_override), - Some(Arc::clone(&feature_set)), expected_result, ) }; @@ -6891,7 +6756,7 @@ mod tests { #[test_case(feature_set_old_behavior(); "old_behavior")] #[test_case(feature_set_new_behavior(); "new_behavior")] - fn test_redelegate(feature_set: FeatureSet) { + fn test_redelegate(feature_set: Arc) { let feature_set = Arc::new(feature_set); let minimum_delegation = crate::get_minimum_delegation(&feature_set); @@ -6970,7 +6835,8 @@ mod tests { uninitialized_stake_address: &Pubkey, uninitialized_stake_account: &AccountSharedData, expected_result| { - process_instruction_with_overrides( + process_instruction( + Arc::clone(&feature_set), &serialize(&StakeInstruction::Redelegate).unwrap(), vec![ (*stake_address, stake_account.clone()), @@ -6979,11 +6845,23 @@ mod tests { uninitialized_stake_account.clone(), ), (*vote_address, vote_account.clone()), + (*authorized_staker, AccountSharedData::default()), ( stake_config::id(), config::create_account(0, &stake_config::Config::default()), ), - (*authorized_staker, AccountSharedData::default()), + ( + stake_history::id(), + create_account_shared_data_for_test(&stake_history), + ), + (rent::id(), create_account_shared_data_for_test(&rent)), + ( + clock::id(), + create_account_shared_data_for_test(&Clock { + epoch: current_epoch, + ..Clock::default() + }), + ), ], vec![ AccountMeta { @@ -7012,8 +6890,6 @@ mod tests { is_writable: false, }, ], - Some(&sysvar_cache_override), - Some(Arc::clone(&feature_set)), expected_result, ) }; @@ -7132,24 +7008,29 @@ mod tests { ), ]; for (deactivated_stake_account, expected_result) in deactivated_stake_accounts { - let _ = process_instruction_with_overrides( + process_instruction( + Arc::clone(&feature_set), &serialize(&StakeInstruction::DelegateStake).unwrap(), vec![ (stake_address, deactivated_stake_account), (vote_address, new_vote_account.clone()), - ( - sysvar::clock::id(), - account::create_account_shared_data_for_test(&Clock::default()), - ), - ( - sysvar::stake_history::id(), - account::create_account_shared_data_for_test(&StakeHistory::default()), - ), + (authorized_staker, AccountSharedData::default()), ( stake_config::id(), config::create_account(0, &stake_config::Config::default()), ), - (authorized_staker, AccountSharedData::default()), + ( + stake_history::id(), + create_account_shared_data_for_test(&stake_history), + ), + (rent::id(), create_account_shared_data_for_test(&rent)), + ( + clock::id(), + create_account_shared_data_for_test(&Clock { + epoch: current_epoch, + ..Clock::default() + }), + ), ], vec![ AccountMeta { @@ -7163,12 +7044,12 @@ mod tests { is_writable: false, }, AccountMeta { - pubkey: sysvar::clock::id(), + pubkey: clock::id(), is_signer: false, is_writable: false, }, AccountMeta { - pubkey: sysvar::stake_history::id(), + pubkey: stake_history::id(), is_signer: false, is_writable: false, }, @@ -7183,8 +7064,6 @@ mod tests { is_writable: false, }, ], - Some(&sysvar_cache_override), - Some(Arc::clone(&feature_set)), expected_result, ); } diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 1ee3077148..7ea50cbb61 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -1779,13 +1779,12 @@ mod tests { use { super::*, proptest::prelude::*, - solana_program_runtime::invoke_context::InvokeContext, + solana_program_runtime::with_mock_invoke_context, solana_sdk::{ account::{create_account_shared_data_for_test, AccountSharedData}, native_token, pubkey::Pubkey, sysvar::SysvarId, - transaction_context::TransactionContext, }, }; @@ -2916,18 +2915,6 @@ mod tests { ); } - fn create_mock_tx_context() -> TransactionContext { - TransactionContext::new( - vec![( - Rent::id(), - create_account_shared_data_for_test(&Rent::default()), - )], - Some(Rent::default()), - 1, - 1, - ) - } - #[test] fn test_lockup_is_expired() { let custodian = solana_sdk::pubkey::new_rand(); @@ -3034,9 +3021,7 @@ mod tests { #[test] fn test_things_can_merge() { - let mut transaction_context = - TransactionContext::new(Vec::new(), Some(Rent::default()), 1, 1); - let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, Vec::new()); let good_stake = Stake { credits_observed: 4242, delegation: Delegation { @@ -3134,9 +3119,7 @@ mod tests { #[test] fn test_metas_can_merge() { - let mut transaction_context = - TransactionContext::new(Vec::new(), Some(Rent::default()), 1, 1); - let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, Vec::new()); // Identical Metas can merge assert!(MergeKind::metas_can_merge( &invoke_context, @@ -3282,9 +3265,7 @@ mod tests { #[test] fn test_merge_kind_get_if_mergeable() { - let mut transaction_context = - TransactionContext::new(Vec::new(), Some(Rent::default()), 1, 1); - let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, Vec::new()); let authority_pubkey = Pubkey::new_unique(); let initial_lamports = 4242424242; let rent = Rent::default(); @@ -3522,9 +3503,7 @@ mod tests { #[test] fn test_merge_kind_merge() { - let mut transaction_context = - TransactionContext::new(Vec::new(), Some(Rent::default()), 1, 1); - let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, Vec::new()); let clock = Clock::default(); let lamports = 424242; let meta = Meta { @@ -3603,8 +3582,11 @@ mod tests { #[test] fn test_active_stake_merge() { - let mut transaction_context = create_mock_tx_context(); - let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + let transaction_accounts = vec![( + Rent::id(), + create_account_shared_data_for_test(&Rent::default()), + )]; + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); let clock = Clock::default(); let delegation_a = 4_242_424_242u64; let delegation_b = 6_200_000_000u64; diff --git a/programs/vote/benches/process_vote.rs b/programs/vote/benches/process_vote.rs index 694b607a1a..598b09ebec 100644 --- a/programs/vote/benches/process_vote.rs +++ b/programs/vote/benches/process_vote.rs @@ -3,7 +3,7 @@ extern crate test; use { - solana_program_runtime::invoke_context::InvokeContext, + solana_program_runtime::with_mock_invoke_context, solana_sdk::{ account::{create_account_for_test, Account, AccountSharedData}, clock::{Clock, Slot}, @@ -11,9 +11,7 @@ use { pubkey::Pubkey, slot_hashes::{SlotHashes, MAX_ENTRIES}, sysvar, - transaction_context::{ - IndexOfAccount, InstructionAccount, TransactionAccount, TransactionContext, - }, + transaction_context::{IndexOfAccount, InstructionAccount, TransactionAccount}, }, solana_vote_program::{ vote_instruction::VoteInstruction, @@ -109,13 +107,8 @@ fn bench_process_vote_instruction( instruction_data: Vec, ) { bencher.iter(|| { - let mut transaction_context = TransactionContext::new( - transaction_accounts.clone(), - Some(sysvar::rent::Rent::default()), - 1, - 1, - ); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + let transaction_accounts = transaction_accounts.clone(); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); invoke_context .transaction_context .get_next_instruction_context() diff --git a/programs/vote/src/vote_processor.rs b/programs/vote/src/vote_processor.rs index 159eb8ac00..bcc3fb879d 100644 --- a/programs/vote/src/vote_processor.rs +++ b/programs/vote/src/vote_processor.rs @@ -326,10 +326,9 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - None, - None, expected_result, super::process_instruction, + |_invoke_context| {}, ) } @@ -345,10 +344,11 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - None, - Some(std::sync::Arc::new(FeatureSet::default())), expected_result, super::process_instruction, + |invoke_context| { + invoke_context.feature_set = std::sync::Arc::new(FeatureSet::default()); + }, ) } diff --git a/rbpf-cli/src/main.rs b/rbpf-cli/src/main.rs index 933c54a328..f28a317ac9 100644 --- a/rbpf-cli/src/main.rs +++ b/rbpf-cli/src/main.rs @@ -5,17 +5,16 @@ use { solana_bpf_loader_program::{ create_ebpf_vm, create_vm, serialization::serialize_parameters, syscalls::create_loader, }, - solana_program_runtime::{ - compute_budget::ComputeBudget, - invoke_context::{prepare_mock_invoke_context, InvokeContext}, - }, + solana_program_runtime::{invoke_context::InvokeContext, with_mock_invoke_context}, solana_rbpf::{ assembler::assemble, elf::Executable, static_analysis::Analysis, verifier::RequisiteVerifier, vm::VerifiedExecutable, }, solana_sdk::{ - account::AccountSharedData, bpf_loader, instruction::AccountMeta, pubkey::Pubkey, - sysvar::rent::Rent, transaction_context::TransactionContext, + account::AccountSharedData, + bpf_loader, + pubkey::Pubkey, + transaction_context::{IndexOfAccount, InstructionAccount}, }, std::{ fmt::{Debug, Formatter}, @@ -186,8 +185,10 @@ before execting it in the virtual machine.", pubkey, AccountSharedData::new(0, allocation_size, &Pubkey::new_unique()), )); - instruction_accounts.push(AccountMeta { - pubkey, + instruction_accounts.push(InstructionAccount { + index_in_transaction: 0, + index_in_caller: 0, + index_in_callee: 0, is_signer: false, is_writable: true, }); @@ -195,43 +196,32 @@ before execting it in the virtual machine.", } Err(_) => { let input = load_accounts(Path::new(matches.value_of("input").unwrap())).unwrap(); - for account_info in input.accounts { + for (index, account_info) in input.accounts.into_iter().enumerate() { let mut account = AccountSharedData::new( account_info.lamports, account_info.data.len(), &account_info.owner, ); account.set_data(account_info.data); - instruction_accounts.push(AccountMeta { - pubkey: account_info.key, + transaction_accounts.push((account_info.key, account)); + instruction_accounts.push(InstructionAccount { + index_in_transaction: index as IndexOfAccount, + index_in_caller: index as IndexOfAccount, + index_in_callee: index as IndexOfAccount, is_signer: account_info.is_signer, is_writable: account_info.is_writable, }); - transaction_accounts.push((account_info.key, account)); } input.instruction_data } }; - let program_indices = [0, 1]; - let preparation = - prepare_mock_invoke_context(transaction_accounts, instruction_accounts, &program_indices); - let mut transaction_context = TransactionContext::new( - preparation.transaction_accounts, - Some(Rent::default()), - 1, - 1, - ); - let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts); invoke_context.enable_instruction_tracing = true; invoke_context .transaction_context .get_next_instruction_context() .unwrap() - .configure( - &program_indices, - &preparation.instruction_accounts, - &instruction_data, - ); + .configure(&[0, 1], &instruction_accounts, &instruction_data); invoke_context.push().unwrap(); let (_parameter_bytes, regions, account_lengths) = serialize_parameters( invoke_context.transaction_context, diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 8d21a4d7bc..f48638ea75 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -8050,10 +8050,9 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { (program_keypair.pubkey(), post_program_account), ], Vec::new(), - None, - None, Ok(()), solana_bpf_loader_program::process_instruction, + |_invoke_context| {}, ); // Test initialized program account diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index fde84281b9..bc85997001 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -21,7 +21,7 @@ use { transaction::TransactionError, transaction_context::{IndexOfAccount, InstructionAccount, TransactionContext}, }, - std::{borrow::Cow, cell::RefCell, rc::Rc, sync::Arc}, + std::{cell::RefCell, rc::Rc, sync::Arc}, }; #[derive(Debug, Default, Clone, Deserialize, Serialize)] @@ -71,7 +71,7 @@ impl MessageProcessor { transaction_context, rent, builtin_programs, - Cow::Borrowed(sysvar_cache), + sysvar_cache, log_collector, compute_budget, tx_executor_cache, diff --git a/runtime/src/nonce_keyed_account.rs b/runtime/src/nonce_keyed_account.rs index d24cb113c3..c0e2eb0f35 100644 --- a/runtime/src/nonce_keyed_account.rs +++ b/runtime/src/nonce_keyed_account.rs @@ -272,15 +272,15 @@ mod test { use { super::*, assert_matches::assert_matches, - solana_program_runtime::invoke_context::InvokeContext, + solana_program_runtime::with_mock_invoke_context, solana_sdk::{ account::AccountSharedData, - hash::{hash, Hash}, + hash::hash, nonce::{self, State}, nonce_account::{create_account, verify_nonce_account}, system_instruction::SystemError, system_program, - transaction_context::{InstructionAccount, TransactionContext}, + transaction_context::InstructionAccount, }, }; @@ -309,7 +309,7 @@ mod test { ..Rent::default() }; let from_lamports = $rent.minimum_balance(State::size()) + 42; - let accounts = vec![ + let transaction_accounts = vec![ ( Pubkey::new_unique(), create_account(from_lamports).into_inner(), @@ -333,9 +333,7 @@ mod test { is_writable: true, }, ]; - let mut transaction_context = - TransactionContext::new(accounts, Some(Rent::default()), 1, 1); - let mut $invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!($invoke_context, transaction_context, transaction_accounts); }; } diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index dca79ae134..058e915240 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -612,14 +612,14 @@ mod tests { system_instruction, system_program, sysvar::{self, recent_blockhashes::IterItem, rent::Rent}, transaction::TransactionError, - transaction_context::TransactionContext, }; use { super::*, crate::{bank::Bank, bank_client::BankClient}, bincode::serialize, - solana_program_runtime::invoke_context::{ - mock_process_instruction, InvokeContext, ProcessInstructionWithContext, + solana_program_runtime::{ + invoke_context::{mock_process_instruction, ProcessInstructionWithContext}, + with_mock_invoke_context, }, std::sync::Arc, }; @@ -646,10 +646,9 @@ mod tests { instruction_data, transaction_accounts, instruction_accounts, - None, - None, expected_result, process_instruction, + |_invoke_context| {}, ) } @@ -793,9 +792,7 @@ mod tests { #[test] fn test_address_create_with_seed_mismatch() { - let mut transaction_context = - TransactionContext::new(Vec::new(), Some(Rent::default()), 1, 1); - let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); + with_mock_invoke_context!(invoke_context, transaction_context, Vec::new()); let from = Pubkey::new_unique(); let seed = "dull boy"; let to = Pubkey::new_unique();