Add get_processed_sibling_instruction syscall (#22859) (#22956)

This commit is contained in:
Jack May
2022-02-08 09:21:11 -08:00
committed by GitHub
parent 5c69af607d
commit d05b5b0902
19 changed files with 864 additions and 66 deletions

View File

@ -53,7 +53,7 @@ use {
cost_tracker::CostTracker,
epoch_stakes::{EpochStakes, NodeVoteAccounts},
inline_spl_associated_token_account, inline_spl_token,
message_processor::MessageProcessor,
message_processor::{InstructionTrace, MessageProcessor},
rent_collector::{CollectedInfo, RentCollector},
stake_weighted_timestamp::{
calculate_stake_weighted_timestamp, MaxAllowableDrift, MAX_ALLOWABLE_DRIFT_PERCENTAGE,
@ -79,7 +79,6 @@ use {
solana_metrics::{inc_new_counter_debug, inc_new_counter_info},
solana_program_runtime::{
compute_budget::ComputeBudget,
instruction_recorder::InstructionRecorder,
invoke_context::{
BuiltinProgram, Executor, Executors, ProcessInstructionWithContext,
TransactionAccountRefCells, TransactionExecutor,
@ -696,6 +695,17 @@ pub type InnerInstructions = Vec<CompiledInstruction>;
/// A list of instructions that were invoked during each instruction of a transaction
pub type InnerInstructionsList = Vec<InnerInstructions>;
/// Convert from an InstructionTrace to InnerInstructionsList
pub fn inner_instructions_list_from_instruction_trace(
instruction_trace: &InstructionTrace,
message: &SanitizedMessage,
) -> Option<InnerInstructionsList> {
instruction_trace
.iter()
.map(|r| r.compile_instructions(message))
.collect()
}
/// A list of log messages emitted during a transaction
pub type TransactionLogMessages = Vec<String>;
@ -3880,15 +3890,7 @@ impl Bank {
let pre_account_state_info =
self.get_transaction_account_state_info(&account_refcells, tx.message());
let instruction_recorders = if enable_cpi_recording {
let ix_count = tx.message().instructions().len();
let mut recorders = Vec::with_capacity(ix_count);
recorders.resize_with(ix_count, InstructionRecorder::default);
Some(recorders)
} else {
None
};
let mut instruction_trace = Vec::with_capacity(tx.message().instructions().len());
let log_collector = if enable_log_recording {
Some(LogCollector::new_ref())
} else {
@ -3906,7 +3908,7 @@ impl Bank {
self.rent_collector.rent,
log_collector.clone(),
executors.clone(),
instruction_recorders.as_deref(),
&mut instruction_trace,
self.feature_set.clone(),
compute_budget,
timings,
@ -3962,13 +3964,11 @@ impl Bank {
.ok()
});
let inner_instructions: Option<InnerInstructionsList> =
instruction_recorders.and_then(|instruction_recorders| {
instruction_recorders
.into_iter()
.map(|r| r.compile_instructions(tx.message()))
.collect()
});
let inner_instructions = if enable_cpi_recording {
inner_instructions_list_from_instruction_trace(&instruction_trace, tx.message())
} else {
None
};
if let Err(e) =
Self::refcells_to_accounts(&mut loaded_transaction.accounts, account_refcells)
@ -6677,7 +6677,9 @@ pub(crate) mod tests {
status_cache::MAX_CACHE_ENTRIES,
},
crossbeam_channel::{bounded, unbounded},
solana_program_runtime::invoke_context::InvokeContext,
solana_program_runtime::{
instruction_recorder::InstructionRecorder, invoke_context::InvokeContext,
},
solana_sdk::{
account::Account,
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
@ -16172,4 +16174,56 @@ pub(crate) mod tests {
}
}
}
#[test]
fn test_inner_instructions_list_from_instruction_trace() {
let instruction1 = Instruction::new_with_bytes(Pubkey::default(), &[1], Vec::new());
let instruction2 = Instruction::new_with_bytes(Pubkey::default(), &[2], Vec::new());
let instruction3 = Instruction::new_with_bytes(Pubkey::default(), &[3], Vec::new());
let instruction4 = Instruction::new_with_bytes(Pubkey::default(), &[4], Vec::new());
let instruction5 = Instruction::new_with_bytes(Pubkey::default(), &[5], Vec::new());
let instruction6 = Instruction::new_with_bytes(Pubkey::default(), &[6], Vec::new());
let instruction_trace = vec![
InstructionRecorder::default(),
InstructionRecorder::default(),
InstructionRecorder::default(),
];
instruction_trace[0].record_instruction(1, instruction1.clone());
instruction_trace[0].record_instruction(2, instruction2.clone());
instruction_trace[2].record_instruction(1, instruction3.clone());
instruction_trace[2].record_instruction(2, instruction4.clone());
instruction_trace[2].record_instruction(3, instruction5.clone());
instruction_trace[2].record_instruction(2, instruction6.clone());
let message = Message::new(
&[
instruction1,
instruction2,
instruction3,
instruction4,
instruction5,
instruction6,
],
None,
);
let inner_instructions = inner_instructions_list_from_instruction_trace(
&instruction_trace,
&SanitizedMessage::Legacy(message),
);
assert_eq!(
inner_instructions,
Some(vec![
vec![CompiledInstruction::new_from_raw_parts(0, vec![2], vec![])],
vec![],
vec![
CompiledInstruction::new_from_raw_parts(0, vec![4], vec![]),
CompiledInstruction::new_from_raw_parts(0, vec![5], vec![]),
CompiledInstruction::new_from_raw_parts(0, vec![6], vec![])
]
])
);
}
}

View File

@ -20,7 +20,7 @@ fn process_instruction_with_program_logging(
) -> Result<(), InstructionError> {
let logger = invoke_context.get_log_collector();
let program_id = invoke_context.get_caller()?;
stable_log::program_invoke(&logger, program_id, invoke_context.invoke_depth());
stable_log::program_invoke(&logger, program_id, invoke_context.get_stack_height());
let result = process_instruction(first_instruction_account, instruction_data, invoke_context);

View File

@ -38,6 +38,9 @@ impl ::solana_frozen_abi::abi_example::AbiExample for MessageProcessor {
}
}
/// Trace of all instructions attempted
pub type InstructionTrace = Vec<InstructionRecorder>;
/// Resultant information gathered from calling process_message()
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct ProcessedMessageInfo {
@ -60,7 +63,7 @@ impl MessageProcessor {
rent: Rent,
log_collector: Option<Rc<RefCell<LogCollector>>>,
executors: Rc<RefCell<Executors>>,
instruction_recorders: Option<&[InstructionRecorder]>,
instruction_trace: &mut InstructionTrace,
feature_set: Arc<FeatureSet>,
compute_budget: ComputeBudget,
timings: &mut ExecuteTimings,
@ -89,6 +92,12 @@ impl MessageProcessor {
.zip(program_indices.iter())
.enumerate()
{
invoke_context.record_top_level_instruction(
instruction.decompile(message).map_err(|err| {
TransactionError::InstructionError(instruction_index as u8, err)
})?,
);
if invoke_context
.feature_set
.is_active(&prevent_calling_precompiles_as_programs::id())
@ -111,10 +120,6 @@ impl MessageProcessor {
}
}
if let Some(instruction_recorders) = instruction_recorders {
invoke_context.instruction_recorder =
Some(&instruction_recorders[instruction_index]);
}
let mut time = Measure::start("execute_instruction");
let ProcessInstructionResult {
compute_units_consumed,
@ -139,9 +144,13 @@ impl MessageProcessor {
timings.execute_accessories.process_instructions.total_us,
time.as_us()
);
result
.map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?;
result.map_err(|err| {
instruction_trace.append(invoke_context.get_instruction_trace_mut());
TransactionError::InstructionError(instruction_index as u8, err)
})?;
}
instruction_trace.append(invoke_context.get_instruction_trace_mut());
Ok(ProcessedMessageInfo {
accounts_data_len: invoke_context.get_accounts_data_meter().current(),
})
@ -263,7 +272,7 @@ mod tests {
rent_collector.rent,
None,
executors.clone(),
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),
@ -293,7 +302,7 @@ mod tests {
rent_collector.rent,
None,
executors.clone(),
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),
@ -327,7 +336,7 @@ mod tests {
rent_collector.rent,
None,
executors,
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),
@ -473,7 +482,7 @@ mod tests {
rent_collector.rent,
None,
executors.clone(),
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),
@ -507,7 +516,7 @@ mod tests {
rent_collector.rent,
None,
executors.clone(),
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),
@ -538,7 +547,7 @@ mod tests {
rent_collector.rent,
None,
executors,
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),
@ -596,7 +605,7 @@ mod tests {
RentCollector::default().rent,
None,
Rc::new(RefCell::new(Executors::default())),
None,
&mut Vec::new(),
Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(),
&mut ExecuteTimings::default(),