use solana_instruction::TRANSACTION_LEVEL_STACK_HEIGHT;
use solana_message::{
compiled_instruction::CompiledInstruction,
inner_instruction::{InnerInstruction, InnerInstructionsList},
};
use solana_transaction_context::TransactionContext;
pub(crate) fn inner_instructions_list_from_instruction_trace(
transaction_context: &TransactionContext<'_>,
) -> InnerInstructionsList {
debug_assert!(transaction_context.get_instruction_context_at_index_in_trace(0).map_or(
true,
|instruction_context| instruction_context.get_stack_height() ==
TRANSACTION_LEVEL_STACK_HEIGHT
));
let mut outer_instructions = Vec::new();
for index_in_trace in 0..transaction_context.get_instruction_trace_length() {
if let Ok(instruction_context) =
transaction_context.get_instruction_context_at_index_in_trace(index_in_trace)
{
let stack_height = instruction_context.get_stack_height();
if stack_height == TRANSACTION_LEVEL_STACK_HEIGHT {
outer_instructions.push(Vec::new());
} else if let Some(inner_instructions) = outer_instructions.last_mut() {
let stack_height = u8::try_from(stack_height).unwrap_or(u8::MAX);
let instruction = CompiledInstruction::new_from_raw_parts(
instruction_context
.get_index_of_program_account_in_transaction()
.unwrap_or_default() as u8,
instruction_context.get_instruction_data().to_vec(),
(0..instruction_context.get_number_of_instruction_accounts())
.map(|instruction_account_index| {
instruction_context
.get_index_of_instruction_account_in_transaction(
instruction_account_index,
)
.unwrap_or_default() as u8
})
.collect(),
);
inner_instructions.push(InnerInstruction { instruction, stack_height });
} else {
debug_assert!(false);
}
} else {
debug_assert!(false);
}
}
outer_instructions
}