diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 75a437988b..67e669ad94 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -843,14 +843,6 @@ impl<'a> InvokeContext<'a> { timings: &mut ExecuteTimings, ) -> Result<(), InstructionError> { *compute_units_consumed = 0; - let program_id = program_indices - .last() - .map(|index| { - self.transaction_context - .get_key_of_account_at_index(*index) - .map(|pubkey| *pubkey) - }) - .unwrap_or_else(|| Ok(native_loader::id()))?; let nesting_level = self .transaction_context @@ -884,37 +876,17 @@ impl<'a> InvokeContext<'a> { } } - let result = self - .push(instruction_accounts, program_indices, instruction_data) + self.push(instruction_accounts, program_indices, instruction_data)?; + self.process_executable_chain(compute_units_consumed, timings) .and_then(|_| { - let mut process_executable_chain_time = - Measure::start("process_executable_chain_time"); - self.transaction_context - .set_return_data(program_id, Vec::new())?; - let pre_remaining_units = self.compute_meter.borrow().get_remaining(); - let execution_result = self.process_executable_chain(); - let post_remaining_units = self.compute_meter.borrow().get_remaining(); - *compute_units_consumed = pre_remaining_units.saturating_sub(post_remaining_units); - process_executable_chain_time.stop(); - // Verify the called program has not misbehaved let mut verify_callee_time = Measure::start("verify_callee_time"); - let result = execution_result.and_then(|_| { - if is_top_level_instruction { - self.verify(instruction_accounts, program_indices) - } else { - self.verify_and_update(instruction_accounts, false) - } - }); + let result = if is_top_level_instruction { + self.verify(instruction_accounts, program_indices) + } else { + self.verify_and_update(instruction_accounts, false) + }; verify_callee_time.stop(); - - saturating_add_assign!( - timings - .execute_accessories - .process_instructions - .process_executable_chain_us, - process_executable_chain_time.as_us() - ); saturating_add_assign!( timings .execute_accessories @@ -922,25 +894,28 @@ impl<'a> InvokeContext<'a> { .verify_callee_us, verify_callee_time.as_us() ); - result - }); - - // Pop the invoke_stack to restore previous state - let _ = self.pop(); - result + }) + // MUST pop if and only if `push` succeeded, independent of `result`. + // Thus, the `.and()` instead of an `.and_then()`. + .and(self.pop()) } /// Calls the instruction's program entrypoint method - fn process_executable_chain(&mut self) -> Result<(), InstructionError> { + fn process_executable_chain( + &mut self, + compute_units_consumed: &mut u64, + timings: &mut ExecuteTimings, + ) -> Result<(), InstructionError> { let instruction_context = self.transaction_context.get_current_instruction_context()?; + let mut process_executable_chain_time = Measure::start("process_executable_chain_time"); let (first_instruction_account, builtin_id) = { let borrowed_root_account = instruction_context .try_borrow_program_account(self.transaction_context, 0) .map_err(|_| InstructionError::UnsupportedProgramId)?; let owner_id = borrowed_root_account.get_owner(); - if solana_sdk::native_loader::check_id(owner_id) { + if native_loader::check_id(owner_id) { (1, *borrowed_root_account.get_key()) } else { (0, *owner_id) @@ -951,20 +926,36 @@ impl<'a> InvokeContext<'a> { if entry.program_id == builtin_id { let program_id = *instruction_context.get_last_program_key(self.transaction_context)?; - if builtin_id == program_id { + self.transaction_context + .set_return_data(program_id, Vec::new())?; + + let pre_remaining_units = self.compute_meter.borrow().get_remaining(); + let result = if builtin_id == program_id { let logger = self.get_log_collector(); stable_log::program_invoke(&logger, &program_id, self.get_stack_height()); - return (entry.process_instruction)(first_instruction_account, self) + (entry.process_instruction)(first_instruction_account, self) .map(|()| { stable_log::program_success(&logger, &program_id); }) .map_err(|err| { stable_log::program_failure(&logger, &program_id, &err); err - }); + }) } else { - return (entry.process_instruction)(first_instruction_account, self); - } + (entry.process_instruction)(first_instruction_account, self) + }; + let post_remaining_units = self.compute_meter.borrow().get_remaining(); + *compute_units_consumed = pre_remaining_units.saturating_sub(post_remaining_units); + + process_executable_chain_time.stop(); + saturating_add_assign!( + timings + .execute_accessories + .process_instructions + .process_executable_chain_us, + process_executable_chain_time.as_us() + ); + return result; } } @@ -1145,7 +1136,7 @@ pub fn with_mock_invoke_context R>( let transaction_accounts = vec![ ( loader_id, - AccountSharedData::new(0, 0, &solana_sdk::native_loader::id()), + AccountSharedData::new(0, 0, &native_loader::id()), ), ( Pubkey::new_unique(), @@ -1189,7 +1180,7 @@ pub fn mock_process_instruction( program_indices.insert(0, transaction_accounts.len()); let mut preparation = prepare_mock_invoke_context(transaction_accounts, instruction_accounts, &program_indices); - let processor_account = AccountSharedData::new(0, 0, &solana_sdk::native_loader::id()); + let processor_account = AccountSharedData::new(0, 0, &native_loader::id()); preparation .transaction_accounts .push((*loader_id, processor_account));