diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 2ccf79f9f..ed064ccd3 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -131,24 +131,23 @@ impl<'a> StackFrame<'a> { } pub struct InvokeContext<'a> { - instruction_index: usize, invoke_stack: Vec>, rent: Rent, pre_accounts: Vec, accounts: &'a [(Pubkey, Rc>)], builtin_programs: &'a [BuiltinProgram], - sysvars: &'a [(Pubkey, Vec)], + pub sysvars: &'a [(Pubkey, Vec)], log_collector: Option>>, compute_budget: ComputeBudget, current_compute_budget: ComputeBudget, compute_meter: Rc>, executors: Rc>, - instruction_recorders: Option<&'a [InstructionRecorder]>, - feature_set: Arc, + pub instruction_recorder: Option<&'a InstructionRecorder>, + pub feature_set: Arc, pub timings: ExecuteDetailsTimings, - blockhash: Hash, - lamports_per_signature: u64, - return_data: (Pubkey, Vec), + pub blockhash: Hash, + pub lamports_per_signature: u64, + pub return_data: (Pubkey, Vec), } impl<'a> InvokeContext<'a> { @@ -160,15 +159,12 @@ impl<'a> InvokeContext<'a> { sysvars: &'a [(Pubkey, Vec)], log_collector: Option>>, compute_budget: ComputeBudget, - compute_meter: Rc>, executors: Rc>, - instruction_recorders: Option<&'a [InstructionRecorder]>, feature_set: Arc, blockhash: Hash, lamports_per_signature: u64, ) -> Self { Self { - instruction_index: 0, invoke_stack: Vec::with_capacity(compute_budget.max_invoke_depth), rent, pre_accounts: Vec::new(), @@ -178,9 +174,9 @@ impl<'a> InvokeContext<'a> { log_collector, current_compute_budget: compute_budget, compute_budget, - compute_meter, + compute_meter: ComputeMeter::new_ref(compute_budget.max_units), executors, - instruction_recorders, + instruction_recorder: None, feature_set, timings: ExecuteDetailsTimings::default(), blockhash, @@ -189,40 +185,24 @@ impl<'a> InvokeContext<'a> { } } - pub fn new_mock_with_sysvars_and_features( + pub fn new_mock( accounts: &'a [(Pubkey, Rc>)], builtin_programs: &'a [BuiltinProgram], - sysvars: &'a [(Pubkey, Vec)], - feature_set: Arc, ) -> Self { Self::new( Rent::default(), accounts, builtin_programs, - sysvars, + &[], Some(LogCollector::new_ref()), ComputeBudget::default(), - ComputeMeter::new_ref(std::i64::MAX as u64), Rc::new(RefCell::new(Executors::default())), - None, - feature_set, + Arc::new(FeatureSet::all_enabled()), Hash::default(), 0, ) } - pub fn new_mock( - accounts: &'a [(Pubkey, Rc>)], - builtin_programs: &'a [BuiltinProgram], - ) -> Self { - Self::new_mock_with_sysvars_and_features( - accounts, - builtin_programs, - &[], - Arc::new(FeatureSet::all_enabled()), - ) - } - /// Push a stack frame onto the invocation stack pub fn push( &mut self, @@ -240,15 +220,15 @@ impl<'a> InvokeContext<'a> { .map(|index_of_program_id| &self.accounts[*index_of_program_id].0); if self.invoke_stack.is_empty() { let mut compute_budget = self.compute_budget; - if !self.is_feature_active(&tx_wide_compute_cap::id()) - && self.is_feature_active(&neon_evm_compute_budget::id()) + if !self.feature_set.is_active(&tx_wide_compute_cap::id()) + && self.feature_set.is_active(&neon_evm_compute_budget::id()) && program_id == Some(&crate::neon_evm_program::id()) { // Bump the compute budget for neon_evm compute_budget.max_units = compute_budget.max_units.max(500_000); } - if !self.is_feature_active(&requestable_heap_size::id()) - && self.is_feature_active(&neon_evm_compute_budget::id()) + if !self.feature_set.is_active(&requestable_heap_size::id()) + && self.feature_set.is_active(&neon_evm_compute_budget::id()) && program_id == Some(&crate::neon_evm_program::id()) { // Bump the compute budget for neon_evm @@ -342,8 +322,10 @@ impl<'a> InvokeContext<'a> { program_indices: &[usize], ) -> Result<(), InstructionError> { let program_id = instruction.program_id(&message.account_keys); - let demote_program_write_locks = self.is_feature_active(&demote_program_write_locks::id()); - let do_support_realloc = self.is_feature_active(&do_support_realloc::id()); + let demote_program_write_locks = self + .feature_set + .is_active(&demote_program_write_locks::id()); + let do_support_realloc = self.feature_set.is_active(&do_support_realloc::id()); // Verify all executable accounts have zero outstanding refs for account_index in program_indices.iter() { @@ -501,7 +483,9 @@ impl<'a> InvokeContext<'a> { prev_account_sizes.push((account, account_length)); } - self.record_instruction(&instruction); + if let Some(instruction_recorder) = &self.instruction_recorder { + instruction_recorder.record_instruction(instruction); + } self.process_cross_program_instruction( &message, &program_indices, @@ -510,7 +494,7 @@ impl<'a> InvokeContext<'a> { )?; // Verify the called program has not misbehaved - let do_support_realloc = self.is_feature_active(&do_support_realloc::id()); + let do_support_realloc = self.feature_set.is_active(&do_support_realloc::id()); for (account, prev_size) in prev_account_sizes.iter() { if !do_support_realloc && *prev_size != account.borrow().data().len() && *prev_size != 0 { @@ -657,12 +641,13 @@ impl<'a> InvokeContext<'a> { // Verify the calling program hasn't misbehaved self.verify_and_update(instruction, account_indices, caller_write_privileges)?; - self.set_return_data(Vec::new())?; + self.return_data = (*self.get_caller()?, Vec::new()); self.push(message, instruction, program_indices, Some(account_indices))?; let result = self.process_instruction(&instruction.data).and_then(|_| { // Verify the called program has not misbehaved - let demote_program_write_locks = - self.is_feature_active(&demote_program_write_locks::id()); + let demote_program_write_locks = self + .feature_set + .is_active(&demote_program_write_locks::id()); let write_privileges: Vec = (0..message.account_keys.len()) .map(|i| message.is_writable(i, demote_program_write_locks)) .collect(); @@ -692,7 +677,7 @@ impl<'a> InvokeContext<'a> { ); } } - if !self.is_feature_active(&remove_native_loader::id()) { + if !self.feature_set.is_active(&remove_native_loader::id()) { let native_loader = NativeLoader::default(); // Call the program via the native loader return native_loader.process_instruction(0, instruction_data, self); @@ -733,7 +718,7 @@ impl<'a> InvokeContext<'a> { note = "To be removed together with remove_native_loader" )] pub fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> { - if !self.is_feature_active(&remove_native_loader::id()) { + if !self.feature_set.is_active(&remove_native_loader::id()) { let stack_frame = &mut self .invoke_stack .last_mut() @@ -786,23 +771,6 @@ impl<'a> InvokeContext<'a> { self.executors.borrow().get(pubkey) } - /// Set which instruction in the message is currently being recorded - pub fn set_instruction_index(&mut self, instruction_index: usize) { - self.instruction_index = instruction_index; - } - - /// Record invoked instruction - pub fn record_instruction(&self, instruction: &Instruction) { - if let Some(instruction_recorders) = &self.instruction_recorders { - instruction_recorders[self.instruction_index].record_instruction(instruction.clone()); - } - } - - /// Get the bank's active feature set - pub fn is_feature_active(&self, feature_id: &Pubkey) -> bool { - self.feature_set.is_active(feature_id) - } - /// Find an account_index and account by its key pub fn get_account(&self, pubkey: &Pubkey) -> Option<(usize, Rc>)> { for (index, (key, account)) in self.accounts.iter().enumerate().rev() { @@ -813,82 +781,27 @@ impl<'a> InvokeContext<'a> { None } - /// Update timing - pub fn update_timing( - &mut self, - serialize_us: u64, - create_vm_us: u64, - execute_us: u64, - deserialize_us: u64, - ) { - self.timings.serialize_us = self.timings.serialize_us.saturating_add(serialize_us); - self.timings.create_vm_us = self.timings.create_vm_us.saturating_add(create_vm_us); - self.timings.execute_us = self.timings.execute_us.saturating_add(execute_us); - self.timings.deserialize_us = self.timings.deserialize_us.saturating_add(deserialize_us); - } - - /// Get cached sysvars - pub fn get_sysvars(&self) -> &[(Pubkey, Vec)] { - self.sysvars - } - /// Get this invocation's compute budget pub fn get_compute_budget(&self) -> &ComputeBudget { &self.current_compute_budget } - /// Set this invocation's blockhash - pub fn set_blockhash(&mut self, hash: Hash) { - self.blockhash = hash; + /// Get the value of a sysvar by its id + pub fn get_sysvar(&self, id: &Pubkey) -> Result { + self.sysvars + .iter() + .find_map(|(key, data)| { + if id == key { + bincode::deserialize(data).ok() + } else { + None + } + }) + .ok_or_else(|| { + ic_msg!(self, "Unable to get sysvar {}", id); + InstructionError::UnsupportedSysvar + }) } - - /// Get this invocation's blockhash - pub fn get_blockhash(&self) -> &Hash { - &self.blockhash - } - - /// Set this invocation's lamports_per_signature value - pub fn set_lamports_per_signature(&mut self, lamports_per_signature: u64) { - self.lamports_per_signature = lamports_per_signature; - } - - /// Get this invocation's lamports_per_signature value - pub fn get_lamports_per_signature(&self) -> u64 { - self.lamports_per_signature - } - - /// Set the return data - pub fn set_return_data(&mut self, data: Vec) -> Result<(), InstructionError> { - self.return_data = (*self.get_caller()?, data); - Ok(()) - } - - /// Get the return data - pub fn get_return_data(&self) -> (Pubkey, &[u8]) { - (self.return_data.0, &self.return_data.1) - } -} - -// This method which has a generic parameter is outside of the InvokeContext, -// because the InvokeContext is a dyn Trait. -pub fn get_sysvar( - invoke_context: &InvokeContext, - id: &Pubkey, -) -> Result { - invoke_context - .get_sysvars() - .iter() - .find_map(|(key, data)| { - if id == key { - bincode::deserialize(data).ok() - } else { - None - } - }) - .ok_or_else(|| { - ic_msg!(invoke_context, "Unable to get sysvar {}", id); - InstructionError::UnsupportedSysvar - }) } pub struct MockInvokeContextPreparation { @@ -1300,8 +1213,9 @@ mod tests { .unwrap(); // not owned account modified by the caller (before the invoke) - let demote_program_write_locks = - invoke_context.is_feature_active(&demote_program_write_locks::id()); + let demote_program_write_locks = invoke_context + .feature_set + .is_active(&demote_program_write_locks::id()); let caller_write_privileges = message .account_keys .iter() @@ -1509,12 +1423,8 @@ mod tests { let mut feature_set = FeatureSet::all_enabled(); feature_set.deactivate(&tx_wide_compute_cap::id()); feature_set.deactivate(&requestable_heap_size::id()); - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &accounts, - &[], - &[], - Arc::new(feature_set), - ); + let mut invoke_context = InvokeContext::new_mock(&accounts, &[]); + invoke_context.feature_set = Arc::new(feature_set); invoke_context .push(&noop_message, &noop_message.instructions[0], &[0], None) diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index 0a021f627..a9f475339 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -214,7 +214,7 @@ fn get_sysvar( panic!("Exceeded compute budget"); } - match solana_program_runtime::invoke_context::get_sysvar::(invoke_context, id) { + match invoke_context.get_sysvar::(id) { Ok(sysvar_data) => unsafe { *(var_addr as *mut _ as *mut T) = sysvar_data; SUCCESS @@ -248,8 +248,9 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs { let message = Message::new(&[instruction.clone()], None); let program_id_index = message.instructions[0].program_id_index as usize; let program_id = message.account_keys[program_id_index]; - let demote_program_write_locks = - invoke_context.is_feature_active(&demote_program_write_locks::id()); + let demote_program_write_locks = invoke_context + .feature_set + .is_active(&demote_program_write_locks::id()); // TODO don't have the caller's keyed_accounts so can't validate writer or signer escalation or deescalation yet let caller_privileges = message .account_keys @@ -317,7 +318,9 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs { } } - invoke_context.record_instruction(instruction); + if let Some(instruction_recorder) = &invoke_context.instruction_recorder { + instruction_recorder.record_instruction(instruction.clone()); + } invoke_context .process_cross_program_instruction( diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index 90c0e8cb7..97b9a1f64 100644 --- a/programs/bpf/benches/bpf_loader.rs +++ b/programs/bpf/benches/bpf_loader.rs @@ -99,6 +99,10 @@ fn bench_program_alu(bencher: &mut Bencher) { let elf = load_elf("bench_alu").unwrap(); let loader_id = bpf_loader::id(); with_mock_invoke_context(loader_id, 10000001, |invoke_context| { + invoke_context + .get_compute_meter() + .borrow_mut() + .mock_set_remaining(std::i64::MAX as u64); let mut executable = Executable::::from_elf( &elf, None, @@ -109,13 +113,7 @@ fn bench_program_alu(bencher: &mut Bencher) { executable.jit_compile().unwrap(); let compute_meter = invoke_context.get_compute_meter(); let mut instruction_meter = ThisInstructionMeter { compute_meter }; - let mut vm = create_vm( - &executable, - &mut inner_iter, - invoke_context, - &[], - ) - .unwrap(); + let mut vm = create_vm(&executable, &mut inner_iter, invoke_context, &[]).unwrap(); println!("Interpreted:"); assert_eq!( @@ -205,7 +203,10 @@ fn bench_create_vm(bencher: &mut Bencher) { let loader_id = bpf_loader::id(); with_mock_invoke_context(loader_id, 10000001, |invoke_context| { const BUDGET: u64 = 200_000; - invoke_context.get_compute_meter().borrow_mut().mock_set_remaining(BUDGET); + invoke_context + .get_compute_meter() + .borrow_mut() + .mock_set_remaining(BUDGET); // Serialize account data let keyed_accounts = invoke_context.get_keyed_accounts().unwrap(); @@ -243,7 +244,10 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { let loader_id = bpf_loader::id(); with_mock_invoke_context(loader_id, 10000001, |invoke_context| { const BUDGET: u64 = 200_000; - invoke_context.get_compute_meter().borrow_mut().mock_set_remaining(BUDGET); + invoke_context + .get_compute_meter() + .borrow_mut() + .mock_set_remaining(BUDGET); // Serialize account data let keyed_accounts = invoke_context.get_keyed_accounts().unwrap(); diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 1d35f6637..09619eec6 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -223,7 +223,7 @@ fn run_program(name: &str) -> u64 { let mut instruction_count = 0; let mut tracer = None; for i in 0..2 { - invoke_context.set_return_data(Vec::new()).unwrap(); + invoke_context.return_data = (*invoke_context.get_caller().unwrap(), Vec::new()); let mut parameter_bytes = parameter_bytes.clone(); { let mut vm = create_vm( diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 173b574a6..a25abd980 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -91,9 +91,12 @@ pub fn create_executor( stack_frame_size: compute_budget.stack_frame_size, enable_instruction_tracing: log_enabled!(Trace), reject_unresolved_syscalls: reject_unresolved_syscalls - && invoke_context.is_feature_active(&reject_deployment_of_unresolved_syscalls::id()), + && invoke_context + .feature_set + .is_active(&reject_deployment_of_unresolved_syscalls::id()), verify_mul64_imm_nonzero: !invoke_context - .is_feature_active(&stop_verify_mul64_imm_nonzero::id()), // TODO: Feature gate and then remove me + .feature_set + .is_active(&stop_verify_mul64_imm_nonzero::id()), // TODO: Feature gate and then remove me ..Config::default() }; let mut executable = { @@ -158,7 +161,10 @@ pub fn create_vm<'a, 'b>( ) -> Result, EbpfError> { let compute_budget = invoke_context.get_compute_budget(); let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH); - if invoke_context.is_feature_active(&requestable_heap_size::id()) { + if invoke_context + .feature_set + .is_active(&requestable_heap_size::id()) + { let _ = invoke_context .get_compute_meter() .borrow_mut() @@ -450,8 +456,9 @@ fn process_loader_upgradeable_instruction( return Err(InstructionError::InvalidArgument); } - let predrain_buffer = - invoke_context.is_feature_active(&reduce_required_deploy_balance::id()); + let predrain_buffer = invoke_context + .feature_set + .is_active(&reduce_required_deploy_balance::id()); if predrain_buffer { // Drain the Buffer account to payer before paying for programdata account payer @@ -1014,7 +1021,7 @@ impl Executor for BpfExecutor { trace!("BPF Program Instruction Trace:\n{}", trace_string); } drop(vm); - let (_returned_from_program_id, return_data) = invoke_context.get_return_data(); + let (_returned_from_program_id, return_data) = &invoke_context.return_data; if !return_data.is_empty() { stable_log::program_return(&log_collector, &program_id, return_data); } @@ -1049,15 +1056,18 @@ impl Executor for BpfExecutor { &keyed_accounts[first_instruction_account + 1..], parameter_bytes.as_slice(), &account_lengths, - invoke_context.is_feature_active(&do_support_realloc::id()), + invoke_context + .feature_set + .is_active(&do_support_realloc::id()), )?; deserialize_time.stop(); - invoke_context.update_timing( - serialize_time.as_us(), - create_vm_time.as_us(), - execute_time.as_us(), - deserialize_time.as_us(), - ); + let timings = &mut invoke_context.timings; + timings.serialize_us = timings.serialize_us.saturating_add(serialize_time.as_us()); + timings.create_vm_us = timings.create_vm_us.saturating_add(create_vm_time.as_us()); + timings.execute_us = timings.execute_us.saturating_add(execute_time.as_us()); + timings.deserialize_us = timings + .deserialize_us + .saturating_add(deserialize_time.as_us()); stable_log::program_success(&log_collector, &program_id); Ok(()) } diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 1072a4b6d..658f265fe 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -141,12 +141,18 @@ pub fn register_syscalls( syscall_registry.register_syscall_by_name(b"sol_sha256", SyscallSha256::call)?; syscall_registry.register_syscall_by_name(b"sol_keccak256", SyscallKeccak256::call)?; - if invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id()) { + if invoke_context + .feature_set + .is_active(&secp256k1_recover_syscall_enabled::id()) + { syscall_registry .register_syscall_by_name(b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?; } - if invoke_context.is_feature_active(&blake3_syscall_enabled::id()) { + if invoke_context + .feature_set + .is_active(&blake3_syscall_enabled::id()) + { syscall_registry.register_syscall_by_name(b"sol_blake3", SyscallBlake3::call)?; } @@ -156,7 +162,10 @@ pub fn register_syscalls( b"sol_get_epoch_schedule_sysvar", SyscallGetEpochScheduleSysvar::call, )?; - if !invoke_context.is_feature_active(&disable_fees_sysvar::id()) { + if !invoke_context + .feature_set + .is_active(&disable_fees_sysvar::id()) + { syscall_registry .register_syscall_by_name(b"sol_get_fees_sysvar", SyscallGetFeesSysvar::call)?; } @@ -178,7 +187,10 @@ pub fn register_syscalls( syscall_registry.register_syscall_by_name(b"sol_alloc_free_", SyscallAllocFree::call)?; // Return data - if invoke_context.is_feature_active(&return_data_syscall_enabled::id()) { + if invoke_context + .feature_set + .is_active(&return_data_syscall_enabled::id()) + { syscall_registry .register_syscall_by_name(b"sol_set_return_data", SyscallSetReturnData::call)?; syscall_registry @@ -186,7 +198,10 @@ pub fn register_syscalls( } // Log data - if invoke_context.is_feature_active(&sol_log_data_syscall_enabled::id()) { + if invoke_context + .feature_set + .is_active(&sol_log_data_syscall_enabled::id()) + { syscall_registry.register_syscall_by_name(b"sol_log_data", SyscallLogData::call)?; } @@ -212,15 +227,21 @@ pub fn bind_syscall_context_objects<'a, 'b>( heap: AlignedMemory, orig_data_lens: &'a [usize], ) -> Result<(), EbpfError> { - let is_blake3_syscall_active = invoke_context.is_feature_active(&blake3_syscall_enabled::id()); - let is_secp256k1_recover_syscall_active = - invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id()); - let is_fee_sysvar_via_syscall_active = - !invoke_context.is_feature_active(&disable_fees_sysvar::id()); - let is_return_data_syscall_active = - invoke_context.is_feature_active(&return_data_syscall_enabled::id()); - let is_sol_log_data_syscall_active = - invoke_context.is_feature_active(&sol_log_data_syscall_enabled::id()); + let is_blake3_syscall_active = invoke_context + .feature_set + .is_active(&blake3_syscall_enabled::id()); + let is_secp256k1_recover_syscall_active = invoke_context + .feature_set + .is_active(&secp256k1_recover_syscall_enabled::id()); + let is_fee_sysvar_via_syscall_active = !invoke_context + .feature_set + .is_active(&disable_fees_sysvar::id()); + let is_return_data_syscall_active = invoke_context + .feature_set + .is_active(&return_data_syscall_enabled::id()); + let is_sol_log_data_syscall_active = invoke_context + .feature_set + .is_active(&sol_log_data_syscall_enabled::id()); let loader_id = invoke_context .get_loader() @@ -1004,18 +1025,15 @@ fn get_sysvar( var_addr: u64, loader_id: &Pubkey, memory_mapping: &MemoryMapping, - invoke_context: Rc>, + invoke_context: &mut InvokeContext, ) -> Result> { - let invoke_context = invoke_context - .try_borrow() - .map_err(|_| SyscallError::InvokeContextBorrowFailed)?; - invoke_context .get_compute_meter() .consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::() as u64)?; let var = translate_type_mut::(memory_mapping, var_addr, loader_id)?; - *var = solana_program_runtime::invoke_context::get_sysvar::(*invoke_context, id) + *var = invoke_context + .get_sysvar::(id) .map_err(SyscallError::InstructionError)?; Ok(SUCCESS) @@ -1036,9 +1054,9 @@ impl<'a, 'b> SyscallObject for SyscallGetClockSysvar<'a, 'b> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - let invoke_context = question_mark!( + let mut invoke_context = question_mark!( self.invoke_context - .try_borrow() + .try_borrow_mut() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); @@ -1053,7 +1071,7 @@ impl<'a, 'b> SyscallObject for SyscallGetClockSysvar<'a, 'b> { var_addr, &loader_id, memory_mapping, - self.invoke_context.clone(), + &mut invoke_context, ); } } @@ -1072,9 +1090,9 @@ impl<'a, 'b> SyscallObject for SyscallGetEpochScheduleSysvar<'a, 'b> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - let invoke_context = question_mark!( + let mut invoke_context = question_mark!( self.invoke_context - .try_borrow() + .try_borrow_mut() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); @@ -1089,7 +1107,7 @@ impl<'a, 'b> SyscallObject for SyscallGetEpochScheduleSysvar<'a, 'b> { var_addr, &loader_id, memory_mapping, - self.invoke_context.clone(), + &mut invoke_context, ); } } @@ -1109,9 +1127,9 @@ impl<'a, 'b> SyscallObject for SyscallGetFeesSysvar<'a, 'b> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - let invoke_context = question_mark!( + let mut invoke_context = question_mark!( self.invoke_context - .try_borrow() + .try_borrow_mut() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); @@ -1126,7 +1144,7 @@ impl<'a, 'b> SyscallObject for SyscallGetFeesSysvar<'a, 'b> { var_addr, &loader_id, memory_mapping, - self.invoke_context.clone(), + &mut invoke_context, ); } } @@ -1145,9 +1163,9 @@ impl<'a, 'b> SyscallObject for SyscallGetRentSysvar<'a, 'b> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - let invoke_context = question_mark!( + let mut invoke_context = question_mark!( self.invoke_context - .try_borrow() + .try_borrow_mut() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); @@ -1162,7 +1180,7 @@ impl<'a, 'b> SyscallObject for SyscallGetRentSysvar<'a, 'b> { var_addr, &loader_id, memory_mapping, - self.invoke_context.clone(), + &mut invoke_context, ); } } @@ -1509,12 +1527,14 @@ impl<'a, 'b> SyscallObject for SyscallSecp256k1Recover<'a, 'b> { return; } }; - let sig_parse_result = - if invoke_context.is_feature_active(&libsecp256k1_0_5_upgrade_enabled::id()) { - libsecp256k1::Signature::parse_standard_slice(signature) - } else { - libsecp256k1::Signature::parse_overflowing_slice(signature) - }; + let sig_parse_result = if invoke_context + .feature_set + .is_active(&libsecp256k1_0_5_upgrade_enabled::id()) + { + libsecp256k1::Signature::parse_standard_slice(signature) + } else { + libsecp256k1::Signature::parse_overflowing_slice(signature) + }; let signature = match sig_parse_result { Ok(sig) => sig, @@ -2157,8 +2177,9 @@ fn get_translated_accounts<'a, T, F>( where F: Fn(&T, &InvokeContext) -> Result, EbpfError>, { - let demote_program_write_locks = - invoke_context.is_feature_active(&demote_program_write_locks::id()); + let demote_program_write_locks = invoke_context + .feature_set + .is_active(&demote_program_write_locks::id()); let keyed_accounts = invoke_context .get_instruction_keyed_accounts() .map_err(SyscallError::InstructionError)?; @@ -2275,9 +2296,11 @@ fn check_authorized_program( && !(bpf_loader_upgradeable::is_upgrade_instruction(instruction_data) || bpf_loader_upgradeable::is_set_authority_instruction(instruction_data) || bpf_loader_upgradeable::is_close_instruction(instruction_data))) - || (invoke_context.is_feature_active(&prevent_calling_precompiles_as_programs::id()) + || (invoke_context + .feature_set + .is_active(&prevent_calling_precompiles_as_programs::id()) && is_precompile(program_id, |feature_id: &Pubkey| { - invoke_context.is_feature_active(feature_id) + invoke_context.feature_set.is_active(feature_id) })) { return Err(SyscallError::ProgramNotSupported(*program_id).into()); @@ -2299,7 +2322,9 @@ fn call<'a, 'b: 'a>( invoke_context .get_compute_meter() .consume(invoke_context.get_compute_budget().invoke_units)?; - let do_support_realloc = invoke_context.is_feature_active(&do_support_realloc::id()); + let do_support_realloc = invoke_context + .feature_set + .is_active(&do_support_realloc::id()); // Translate and verify caller's data let loader_id = invoke_context @@ -2335,7 +2360,9 @@ fn call<'a, 'b: 'a>( )?; // Record the instruction - invoke_context.record_instruction(&instruction); + if let Some(instruction_recorder) = &invoke_context.instruction_recorder { + instruction_recorder.record_instruction(instruction); + } // Process instruction invoke_context @@ -2453,12 +2480,13 @@ impl<'a, 'b> SyscallObject for SyscallSetReturnData<'a, 'b> { ) .to_vec() }; - question_mark!( + let program_id = question_mark!( invoke_context - .set_return_data(return_data) + .get_caller() .map_err(SyscallError::InstructionError), result ); + invoke_context.return_data = (*program_id, return_data); *result = Ok(0); } @@ -2500,7 +2528,7 @@ impl<'a, 'b> SyscallObject for SyscallGetReturnData<'a, 'b> { result ); - let (program_id, return_data) = invoke_context.get_return_data(); + let (program_id, return_data) = &invoke_context.return_data; length = length.min(return_data.len() as u64); if length != 0 { question_mark!( @@ -2522,7 +2550,7 @@ impl<'a, 'b> SyscallObject for SyscallGetReturnData<'a, 'b> { result ); - program_id_result[0] = program_id; + program_id_result[0] = *program_id; } // Return the actual length, rather the length returned @@ -2618,10 +2646,8 @@ mod tests { use solana_rbpf::{ ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config, }; - use solana_sdk::{ - bpf_loader, feature_set::FeatureSet, fee_calculator::FeeCalculator, hash::hashv, - }; - use std::{str::FromStr, sync::Arc}; + use solana_sdk::{bpf_loader, fee_calculator::FeeCalculator, hash::hashv}; + use std::str::FromStr; macro_rules! assert_access_violation { ($result:expr, $va:expr, $len:expr) => { @@ -3529,13 +3555,9 @@ mod tests { }; let mut data = vec![]; bincode::serialize_into(&mut data, &src_clock).unwrap(); + let mut invoke_context = InvokeContext::new_mock(&accounts, &[]); let sysvars = [(sysvar::clock::id(), data)]; - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &accounts, - &[], - &sysvars, - Arc::new(FeatureSet::all_enabled()), - ); + invoke_context.sysvars = &sysvars; invoke_context .push(&message, &message.instructions[0], &[0], None) .unwrap(); @@ -3578,13 +3600,9 @@ mod tests { }; let mut data = vec![]; bincode::serialize_into(&mut data, &src_epochschedule).unwrap(); + let mut invoke_context = InvokeContext::new_mock(&accounts, &[]); let sysvars = [(sysvar::epoch_schedule::id(), data)]; - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &accounts, - &[], - &sysvars, - Arc::new(FeatureSet::all_enabled()), - ); + invoke_context.sysvars = &sysvars; invoke_context .push(&message, &message.instructions[0], &[0], None) .unwrap(); @@ -3634,13 +3652,9 @@ mod tests { }; let mut data = vec![]; bincode::serialize_into(&mut data, &src_fees).unwrap(); + let mut invoke_context = InvokeContext::new_mock(&accounts, &[]); let sysvars = [(sysvar::fees::id(), data)]; - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &accounts, - &[], - &sysvars, - Arc::new(FeatureSet::all_enabled()), - ); + invoke_context.sysvars = &sysvars; invoke_context .push(&message, &message.instructions[0], &[0], None) .unwrap(); @@ -3681,13 +3695,9 @@ mod tests { }; let mut data = vec![]; bincode::serialize_into(&mut data, &src_rent).unwrap(); + let mut invoke_context = InvokeContext::new_mock(&accounts, &[]); let sysvars = [(sysvar::rent::id(), data)]; - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &accounts, - &[], - &sysvars, - Arc::new(FeatureSet::all_enabled()), - ); + invoke_context.sysvars = &sysvars; invoke_context .push(&message, &message.instructions[0], &[0], None) .unwrap(); @@ -3949,9 +3959,14 @@ mod tests { .get_compute_budget() .create_program_address_units; let address = bpf_loader_upgradeable::id(); + let max_tries = 256; // one per seed for _ in 0..1_000 { let address = Pubkey::new_unique(); + invoke_context + .get_compute_meter() + .borrow_mut() + .mock_set_remaining(cost * max_tries); let (found_address, bump_seed) = try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address) .unwrap(); @@ -3966,7 +3981,6 @@ mod tests { ); } - let max_tries = 256; // one per seed let seeds: &[&[u8]] = &[b""]; invoke_context .get_compute_meter() diff --git a/programs/config/src/config_processor.rs b/programs/config/src/config_processor.rs index 46f7a48a4..65fe7e2e5 100644 --- a/programs/config/src/config_processor.rs +++ b/programs/config/src/config_processor.rs @@ -100,7 +100,10 @@ pub fn process_instruction( } } - if invoke_context.is_feature_active(&feature_set::dedupe_config_program_signers::id()) { + if invoke_context + .feature_set + .is_active(&feature_set::dedupe_config_program_signers::id()) + { let total_new_keys = key_list.keys.len(); let unique_new_keys = key_list.keys.into_iter().collect::>(); if unique_new_keys.len() != total_new_keys { diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index d02f72502..edfea7e5f 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -1,7 +1,7 @@ use { crate::{config, stake_state::StakeAccount}, log::*, - solana_program_runtime::invoke_context::{get_sysvar, InvokeContext}, + solana_program_runtime::invoke_context::InvokeContext, solana_sdk::{ feature_set, instruction::InstructionError, @@ -48,9 +48,9 @@ pub fn process_instruction( )?)?, ), StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => { - let require_custodian_for_locked_stake_authorize = invoke_context.is_feature_active( - &feature_set::require_custodian_for_locked_stake_authorize::id(), - ); + let require_custodian_for_locked_stake_authorize = invoke_context + .feature_set + .is_active(&feature_set::require_custodian_for_locked_stake_authorize::id()); if require_custodian_for_locked_stake_authorize { let clock = from_keyed_account::(keyed_account_at_index( @@ -86,9 +86,9 @@ pub fn process_instruction( StakeInstruction::AuthorizeWithSeed(args) => { let authority_base = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?; - let require_custodian_for_locked_stake_authorize = invoke_context.is_feature_active( - &feature_set::require_custodian_for_locked_stake_authorize::id(), - ); + let require_custodian_for_locked_stake_authorize = invoke_context + .feature_set + .is_active(&feature_set::require_custodian_for_locked_stake_authorize::id()); if require_custodian_for_locked_stake_authorize { let clock = from_keyed_account::(keyed_account_at_index( @@ -124,8 +124,9 @@ pub fn process_instruction( } } StakeInstruction::DelegateStake => { - let can_reverse_deactivation = - invoke_context.is_feature_active(&feature_set::stake_program_v4::id()); + let can_reverse_deactivation = invoke_context + .feature_set + .is_active(&feature_set::stake_program_v4::id()); let vote = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?; me.delegate( @@ -154,8 +155,9 @@ pub fn process_instruction( StakeInstruction::Merge => { let source_stake = &keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?; - let can_merge_expired_lockups = - invoke_context.is_feature_active(&feature_set::stake_program_v4::id()); + let can_merge_expired_lockups = invoke_context + .feature_set + .is_active(&feature_set::stake_program_v4::id()); me.merge( invoke_context, source_stake, @@ -186,7 +188,9 @@ pub fn process_instruction( )?)?, keyed_account_at_index(keyed_accounts, first_instruction_account + 4)?, keyed_account_at_index(keyed_accounts, first_instruction_account + 5).ok(), - invoke_context.is_feature_active(&feature_set::stake_program_v4::id()), + invoke_context + .feature_set + .is_active(&feature_set::stake_program_v4::id()), ) } StakeInstruction::Deactivate => me.deactivate( @@ -197,15 +201,20 @@ pub fn process_instruction( &signers, ), StakeInstruction::SetLockup(lockup) => { - let clock = if invoke_context.is_feature_active(&feature_set::stake_program_v4::id()) { - Some(get_sysvar::(invoke_context, &sysvar::clock::id())?) + let clock = if invoke_context + .feature_set + .is_active(&feature_set::stake_program_v4::id()) + { + Some(invoke_context.get_sysvar::(&sysvar::clock::id())?) } else { None }; me.set_lockup(&lockup, &signers, clock.as_ref()) } StakeInstruction::InitializeChecked => { - if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) + if invoke_context + .feature_set + .is_active(&feature_set::vote_stake_checked_instructions::id()) { let authorized = Authorized { staker: *keyed_account_at_index(keyed_accounts, first_instruction_account + 2)? @@ -231,7 +240,9 @@ pub fn process_instruction( } } StakeInstruction::AuthorizeChecked(stake_authorize) => { - if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) + if invoke_context + .feature_set + .is_active(&feature_set::vote_stake_checked_instructions::id()) { let clock = from_keyed_account::(keyed_account_at_index( keyed_accounts, @@ -261,7 +272,9 @@ pub fn process_instruction( } } StakeInstruction::AuthorizeCheckedWithSeed(args) => { - if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) + if invoke_context + .feature_set + .is_active(&feature_set::vote_stake_checked_instructions::id()) { let authority_base = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?; @@ -293,7 +306,9 @@ pub fn process_instruction( } } StakeInstruction::SetLockupChecked(lockup_checked) => { - if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) + if invoke_context + .feature_set + .is_active(&feature_set::vote_stake_checked_instructions::id()) { let custodian = if let Ok(custodian) = keyed_account_at_index(keyed_accounts, first_instruction_account + 2) @@ -312,7 +327,7 @@ pub fn process_instruction( epoch: lockup_checked.epoch, custodian, }; - let clock = Some(get_sysvar::(invoke_context, &sysvar::clock::id())?); + let clock = Some(invoke_context.get_sysvar::(&sysvar::clock::id())?); me.set_lockup(&lockup, &signers, clock.as_ref()) } else { Err(InstructionError::InvalidInstructionData) @@ -331,7 +346,6 @@ mod tests { }; use solana_sdk::{ account::{self, AccountSharedData}, - feature_set::FeatureSet, instruction::{AccountMeta, Instruction}, pubkey::Pubkey, rent::Rent, @@ -342,7 +356,7 @@ mod tests { }, sysvar::{stake_history::StakeHistory, Sysvar}, }; - use std::{cell::RefCell, rc::Rc, str::FromStr, sync::Arc}; + use std::{cell::RefCell, rc::Rc, str::FromStr}; fn create_default_account() -> Rc> { AccountSharedData::new_ref(0, 0, &Pubkey::new_unique()) @@ -415,13 +429,9 @@ mod tests { preparation.accounts.push((id(), processor_account)); let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of()); bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap(); + let mut invoke_context = InvokeContext::new_mock(&preparation.accounts, &[]); let sysvars = [(sysvar::clock::id(), data)]; - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &preparation.accounts, - &[], - &sysvars, - Arc::new(FeatureSet::all_enabled()), - ); + invoke_context.sysvars = &sysvars; invoke_context.push( &preparation.message, &preparation.message.instructions[0], @@ -1065,13 +1075,9 @@ mod tests { preparation.accounts.push((id(), processor_account)); let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of()); bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap(); + let mut invoke_context = InvokeContext::new_mock(&preparation.accounts, &[]); let sysvars = [(sysvar::clock::id(), data)]; - let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( - &preparation.accounts, - &[], - &sysvars, - Arc::new(FeatureSet::all_enabled()), - ); + invoke_context.sysvars = &sysvars; invoke_context .push( &preparation.message, diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 9df77bf98..be02be49a 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -978,7 +978,8 @@ impl MergeKind { .zip(source.active_stake()) .map(|(stake, source)| { if invoke_context - .is_feature_active(&stake_merge_with_unmatched_credits_observed::id()) + .feature_set + .is_active(&stake_merge_with_unmatched_credits_observed::id()) { Self::active_delegations_can_merge( invoke_context, @@ -1038,7 +1039,10 @@ fn merge_delegation_stake_and_credits_observed( absorbed_lamports: u64, absorbed_credits_observed: u64, ) -> Result<(), InstructionError> { - if invoke_context.is_feature_active(&stake_merge_with_unmatched_credits_observed::id()) { + if invoke_context + .feature_set + .is_active(&stake_merge_with_unmatched_credits_observed::id()) + { stake.credits_observed = stake_weighted_credits_observed(stake, absorbed_lamports, absorbed_credits_observed) .ok_or(InstructionError::ArithmeticOverflow)?; diff --git a/programs/vote/src/vote_instruction.rs b/programs/vote/src/vote_instruction.rs index ec7d2e178..18a8c88b1 100644 --- a/programs/vote/src/vote_instruction.rs +++ b/programs/vote/src/vote_instruction.rs @@ -378,7 +378,9 @@ pub fn process_instruction( vote_state::withdraw(me, lamports, to, &signers) } VoteInstruction::AuthorizeChecked(vote_authorize) => { - if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) + if invoke_context + .feature_set + .is_active(&feature_set::vote_stake_checked_instructions::id()) { let voter_pubkey = &keyed_account_at_index(keyed_accounts, first_instruction_account + 3)? diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index e0d19f326..a6ef2f374 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -71,9 +71,7 @@ use solana_measure::measure::Measure; use solana_metrics::{inc_new_counter_debug, inc_new_counter_info}; use solana_program_runtime::{ instruction_recorder::InstructionRecorder, - invoke_context::{ - BuiltinProgram, ComputeMeter, Executor, Executors, ProcessInstructionWithContext, - }, + invoke_context::{BuiltinProgram, Executor, Executors, ProcessInstructionWithContext}, log_collector::LogCollector, timings::ExecuteDetailsTimings, }; @@ -3871,8 +3869,6 @@ impl Bank { None }; - let compute_meter = ComputeMeter::new_ref(compute_budget.max_units); - let (blockhash, lamports_per_signature) = self.last_blockhash_and_lamports_per_signature(); @@ -3888,7 +3884,6 @@ impl Bank { instruction_recorders.as_deref(), feature_set, compute_budget, - compute_meter, &mut timings.details, &*self.sysvar_cache.read().unwrap(), blockhash, diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 146a7d5e7..c483f5a68 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use solana_measure::measure::Measure; use solana_program_runtime::{ instruction_recorder::InstructionRecorder, - invoke_context::{BuiltinProgram, ComputeMeter, Executors, InvokeContext}, + invoke_context::{BuiltinProgram, Executors, InvokeContext}, log_collector::LogCollector, timings::ExecuteDetailsTimings, }; @@ -50,7 +50,6 @@ impl MessageProcessor { instruction_recorders: Option<&[InstructionRecorder]>, feature_set: Arc, compute_budget: ComputeBudget, - compute_meter: Rc>, timings: &mut ExecuteDetailsTimings, sysvars: &[(Pubkey, Vec)], blockhash: Hash, @@ -63,9 +62,7 @@ impl MessageProcessor { sysvars, log_collector, compute_budget, - compute_meter, executors, - instruction_recorders, feature_set, blockhash, lamports_per_signature, @@ -79,8 +76,10 @@ impl MessageProcessor { .enumerate() { let program_id = instruction.program_id(&message.account_keys); - if invoke_context.is_feature_active(&prevent_calling_precompiles_as_programs::id()) - && is_precompile(program_id, |id| invoke_context.is_feature_active(id)) + if invoke_context + .feature_set + .is_active(&prevent_calling_precompiles_as_programs::id()) + && is_precompile(program_id, |id| invoke_context.feature_set.is_active(id)) { // Precompiled programs don't have an instruction processor continue; @@ -99,7 +98,10 @@ impl MessageProcessor { } } - invoke_context.set_instruction_index(instruction_index); + if let Some(instruction_recorders) = instruction_recorders { + invoke_context.instruction_recorder = + Some(&instruction_recorders[instruction_index]); + } let result = invoke_context .push(message, instruction, program_indices, None) .and_then(|_| { @@ -134,7 +136,6 @@ impl MessageProcessor { mod tests { use super::*; use crate::rent_collector::RentCollector; - use solana_program_runtime::invoke_context::ComputeMeter; use solana_sdk::{ account::ReadableAccount, instruction::{AccountMeta, Instruction, InstructionError}, @@ -246,7 +247,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), @@ -276,7 +276,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), @@ -310,7 +309,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), @@ -455,7 +453,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), @@ -489,7 +486,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), @@ -520,7 +516,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), @@ -578,7 +573,6 @@ mod tests { None, Arc::new(FeatureSet::all_enabled()), ComputeBudget::new(), - ComputeMeter::new_ref(std::i64::MAX as u64), &mut ExecuteDetailsTimings::default(), &[], Hash::default(), diff --git a/runtime/src/nonce_keyed_account.rs b/runtime/src/nonce_keyed_account.rs index 397b860d1..aad7b537c 100644 --- a/runtime/src/nonce_keyed_account.rs +++ b/runtime/src/nonce_keyed_account.rs @@ -47,9 +47,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { let merge_nonce_error_into_system_error = invoke_context - .is_feature_active(&feature_set::merge_nonce_error_into_system_error::id()); + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() { + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { ic_msg!( invoke_context, "Advance nonce account: Account {} must be writeable", @@ -69,7 +74,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { ); return Err(InstructionError::MissingRequiredSignature); } - let recent_blockhash = *invoke_context.get_blockhash(); + let recent_blockhash = invoke_context.blockhash; if data.blockhash == recent_blockhash { ic_msg!( invoke_context, @@ -84,7 +89,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { let new_data = nonce::state::Data::new( data.authority, recent_blockhash, - invoke_context.get_lamports_per_signature(), + invoke_context.lamports_per_signature, ); self.set_state(&Versions::new_current(State::Initialized(new_data))) } @@ -111,9 +116,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { let merge_nonce_error_into_system_error = invoke_context - .is_feature_active(&feature_set::merge_nonce_error_into_system_error::id()); + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() { + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { ic_msg!( invoke_context, "Withdraw nonce account: Account {} must be writeable", @@ -137,7 +147,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { } State::Initialized(ref data) => { if lamports == self.lamports()? { - if data.blockhash == *invoke_context.get_blockhash() { + if data.blockhash == invoke_context.blockhash { ic_msg!( invoke_context, "Withdraw nonce account: nonce can only advance once per slot" @@ -197,9 +207,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { let merge_nonce_error_into_system_error = invoke_context - .is_feature_active(&feature_set::merge_nonce_error_into_system_error::id()); + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() { + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { ic_msg!( invoke_context, "Initialize nonce account: Account {} must be writeable", @@ -222,8 +237,8 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { } let data = nonce::state::Data::new( *nonce_authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); self.set_state(&Versions::new_current(State::Initialized(data))) } @@ -248,9 +263,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> { invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { let merge_nonce_error_into_system_error = invoke_context - .is_feature_active(&feature_set::merge_nonce_error_into_system_error::id()); + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() { + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { ic_msg!( invoke_context, "Authorize nonce account: Account {} must be writeable", @@ -325,8 +345,8 @@ mod test { fn create_invoke_context_with_blockhash<'a>(seed: usize) -> InvokeContext<'a> { let mut invoke_context = InvokeContext::new_mock(&[], &[]); let (blockhash, lamports_per_signature) = create_test_blockhash(seed); - invoke_context.set_blockhash(blockhash); - invoke_context.set_lamports_per_signature(lamports_per_signature); + invoke_context.blockhash = blockhash; + invoke_context.lamports_per_signature = lamports_per_signature; invoke_context } @@ -364,8 +384,8 @@ mod test { .convert_to_current(); let data = nonce::state::Data::new( data.authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); // First nonce instruction drives state from Uninitialized to Initialized assert_eq!(state, State::Initialized(data.clone())); @@ -378,8 +398,8 @@ mod test { .convert_to_current(); let data = nonce::state::Data::new( data.authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); // Second nonce instruction consumes and replaces stored nonce assert_eq!(state, State::Initialized(data.clone())); @@ -392,8 +412,8 @@ mod test { .convert_to_current(); let data = nonce::state::Data::new( data.authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); // Third nonce instruction for fun and profit assert_eq!(state, State::Initialized(data)); @@ -448,8 +468,8 @@ mod test { .convert_to_current(); let data = nonce::state::Data::new( authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); assert_eq!(state, State::Initialized(data)); let signers = HashSet::new(); @@ -726,8 +746,8 @@ mod test { .convert_to_current(); let data = nonce::state::Data::new( authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); assert_eq!(state, State::Initialized(data.clone())); with_test_keyed_account(42, false, |to_keyed| { @@ -749,8 +769,8 @@ mod test { .convert_to_current(); let data = nonce::state::Data::new( data.authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); assert_eq!(state, State::Initialized(data)); assert_eq!( @@ -923,8 +943,8 @@ mod test { let result = keyed_account.initialize_nonce_account(&authority, &rent, &invoke_context); let data = nonce::state::Data::new( authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); assert_eq!(result, Ok(())); let state = AccountUtilsState::::state(keyed_account) @@ -988,8 +1008,8 @@ mod test { let authority = Pubkey::default(); let data = nonce::state::Data::new( authority, - *invoke_context.get_blockhash(), - invoke_context.get_lamports_per_signature(), + invoke_context.blockhash, + invoke_context.lamports_per_signature, ); let result = nonce_account.authorize_nonce_account( &Pubkey::default(), @@ -1062,7 +1082,7 @@ mod test { .unwrap(); assert!(verify_nonce_account( &nonce_account.account.borrow(), - invoke_context.get_blockhash(), + &invoke_context.blockhash, )); }); } @@ -1093,7 +1113,7 @@ mod test { let invoke_context = create_invoke_context_with_blockhash(1); assert!(!verify_nonce_account( &nonce_account.account.borrow(), - invoke_context.get_blockhash(), + &invoke_context.blockhash, )); }); } diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index 0e5d8140d..ddb3670d2 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -124,7 +124,9 @@ fn assign( // Thus, we're starting to remove this restriction from system instruction // processor for consistency and fewer special casing by piggybacking onto // the related feature gate.. - let rent_for_sysvars = invoke_context.is_feature_active(&feature_set::rent_for_sysvars::id()); + let rent_for_sysvars = invoke_context + .feature_set + .is_active(&feature_set::rent_for_sysvars::id()); if !rent_for_sysvars && sysvar::check_id(owner) { // guard against sysvars being made ic_msg!(invoke_context, "Assign: cannot assign to sysvar, {}", owner); @@ -205,7 +207,9 @@ fn transfer( lamports: u64, invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { - if !invoke_context.is_feature_active(&feature_set::system_transfer_zero_check::id()) + if !invoke_context + .feature_set + .is_active(&feature_set::system_transfer_zero_check::id()) && lamports == 0 { return Ok(()); @@ -232,7 +236,9 @@ fn transfer_with_seed( lamports: u64, invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { - if !invoke_context.is_feature_active(&feature_set::system_transfer_zero_check::id()) + if !invoke_context + .feature_set + .is_active(&feature_set::system_transfer_zero_check::id()) && lamports == 0 { return Ok(()); @@ -944,8 +950,8 @@ mod tests { feature_set .inactive .insert(feature_set::rent_for_sysvars::id()); - let invoke_context = - InvokeContext::new_mock_with_sysvars_and_features(&[], &[], &[], Arc::new(feature_set)); + let mut invoke_context = InvokeContext::new_mock(&[], &[]); + invoke_context.feature_set = Arc::new(feature_set); // Attempt to create system account in account already owned by another program let from = Pubkey::new_unique(); let from_account = AccountSharedData::new_ref(100, 0, &system_program::id()); @@ -1107,8 +1113,8 @@ mod tests { feature_set .inactive .insert(feature_set::rent_for_sysvars::id()); - let invoke_context = - InvokeContext::new_mock_with_sysvars_and_features(&[], &[], &[], Arc::new(feature_set)); + let mut invoke_context = InvokeContext::new_mock(&[], &[]); + invoke_context.feature_set = Arc::new(feature_set); let new_owner = sysvar::id(); let from = Pubkey::new_unique(); let mut from_account = AccountSharedData::new(100, 0, &system_program::id()); @@ -1575,7 +1581,7 @@ mod tests { |first_instruction_account: usize, instruction_data: &[u8], invoke_context: &mut InvokeContext| { - invoke_context.set_blockhash(hash(&serialize(&0).unwrap())); + invoke_context.blockhash = hash(&serialize(&0).unwrap()); super::process_instruction( first_instruction_account, instruction_data, @@ -1991,7 +1997,7 @@ mod tests { |first_instruction_account: usize, instruction_data: &[u8], invoke_context: &mut InvokeContext| { - invoke_context.set_blockhash(hash(&serialize(&0).unwrap())); + invoke_context.blockhash = hash(&serialize(&0).unwrap()); super::process_instruction( first_instruction_account, instruction_data,