Refactor: Move `InstructionRecorder` into `TransactionContext` (#22578)

* Moves InstructionRecorder into TransactionContext.

* Adds assertions for number_of_instructions_at_transaction_level.
This commit is contained in:
Alexander Meißner 2022-01-19 22:40:09 +01:00 committed by GitHub
parent 60850d71ce
commit b448472037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 108 additions and 106 deletions

View File

@ -1991,7 +1991,7 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
let mut program_data = Vec::new(); let mut program_data = Vec::new();
file.read_to_end(&mut program_data) file.read_to_end(&mut program_data)
.map_err(|err| format!("Unable to read program file: {}", err))?; .map_err(|err| format!("Unable to read program file: {}", err))?;
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Verify the program // Verify the program

View File

@ -3,7 +3,6 @@ use {
accounts_data_meter::AccountsDataMeter, accounts_data_meter::AccountsDataMeter,
compute_budget::ComputeBudget, compute_budget::ComputeBudget,
ic_logger_msg, ic_msg, ic_logger_msg, ic_msg,
instruction_recorder::InstructionRecorder,
log_collector::LogCollector, log_collector::LogCollector,
native_loader::NativeLoader, native_loader::NativeLoader,
pre_account::PreAccount, pre_account::PreAccount,
@ -192,7 +191,6 @@ pub struct InvokeContext<'a> {
compute_meter: Rc<RefCell<ComputeMeter>>, compute_meter: Rc<RefCell<ComputeMeter>>,
accounts_data_meter: AccountsDataMeter, accounts_data_meter: AccountsDataMeter,
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
pub instruction_recorder: Option<Rc<RefCell<InstructionRecorder>>>,
pub feature_set: Arc<FeatureSet>, pub feature_set: Arc<FeatureSet>,
pub timings: ExecuteDetailsTimings, pub timings: ExecuteDetailsTimings,
pub blockhash: Hash, pub blockhash: Hash,
@ -209,7 +207,6 @@ impl<'a> InvokeContext<'a> {
log_collector: Option<Rc<RefCell<LogCollector>>>, log_collector: Option<Rc<RefCell<LogCollector>>>,
compute_budget: ComputeBudget, compute_budget: ComputeBudget,
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
instruction_recorder: Option<Rc<RefCell<InstructionRecorder>>>,
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
blockhash: Hash, blockhash: Hash,
lamports_per_signature: u64, lamports_per_signature: u64,
@ -228,7 +225,6 @@ impl<'a> InvokeContext<'a> {
compute_meter: ComputeMeter::new_ref(compute_budget.max_units), compute_meter: ComputeMeter::new_ref(compute_budget.max_units),
accounts_data_meter: AccountsDataMeter::new(current_accounts_data_len), accounts_data_meter: AccountsDataMeter::new(current_accounts_data_len),
executors, executors,
instruction_recorder,
feature_set, feature_set,
timings: ExecuteDetailsTimings::default(), timings: ExecuteDetailsTimings::default(),
blockhash, blockhash,
@ -249,7 +245,6 @@ impl<'a> InvokeContext<'a> {
Some(LogCollector::new_ref()), Some(LogCollector::new_ref()),
ComputeBudget::default(), ComputeBudget::default(),
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None,
feature_set, feature_set,
Hash::default(), Hash::default(),
0, 0,
@ -269,7 +264,6 @@ impl<'a> InvokeContext<'a> {
Some(LogCollector::new_ref()), Some(LogCollector::new_ref()),
ComputeBudget::default(), ComputeBudget::default(),
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
Hash::default(), Hash::default(),
0, 0,
@ -811,11 +805,7 @@ impl<'a> InvokeContext<'a> {
.transaction_context .transaction_context
.get_instruction_context_stack_height() .get_instruction_context_stack_height()
== 0; == 0;
if is_lowest_invocation_level { if !is_lowest_invocation_level {
if let Some(instruction_recorder) = &self.instruction_recorder {
instruction_recorder.borrow_mut().begin_next_recording();
}
} else {
// Verify the calling program hasn't misbehaved // Verify the calling program hasn't misbehaved
let mut verify_caller_time = Measure::start("verify_caller_time"); let mut verify_caller_time = Measure::start("verify_caller_time");
let verify_caller_result = self.verify_and_update(instruction_accounts, true); let verify_caller_result = self.verify_and_update(instruction_accounts, true);
@ -830,7 +820,6 @@ impl<'a> InvokeContext<'a> {
verify_caller_result?; verify_caller_result?;
// Record instruction // Record instruction
if let Some(instruction_recorder) = &self.instruction_recorder {
let compiled_instruction = CompiledInstruction { let compiled_instruction = CompiledInstruction {
program_id_index: self program_id_index: self
.transaction_context .transaction_context
@ -842,12 +831,9 @@ impl<'a> InvokeContext<'a> {
.map(|instruction_account| instruction_account.index_in_transaction as u8) .map(|instruction_account| instruction_account.index_in_transaction as u8)
.collect(), .collect(),
}; };
self.transaction_context
instruction_recorder
.borrow_mut()
.record_compiled_instruction(compiled_instruction); .record_compiled_instruction(compiled_instruction);
} }
}
let result = self let result = self
.push(instruction_accounts, program_indices, instruction_data) .push(instruction_accounts, program_indices, instruction_data)
@ -1075,6 +1061,7 @@ pub fn with_mock_invoke_context<R, F: FnMut(&mut InvokeContext) -> R>(
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
preparation.transaction_accounts, preparation.transaction_accounts,
ComputeBudget::default().max_invoke_depth.saturating_add(1), ComputeBudget::default().max_invoke_depth.saturating_add(1),
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context invoke_context
@ -1103,6 +1090,7 @@ pub fn mock_process_instruction_with_sysvars(
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
preparation.transaction_accounts, preparation.transaction_accounts,
ComputeBudget::default().max_invoke_depth.saturating_add(1), ComputeBudget::default().max_invoke_depth.saturating_add(1),
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.sysvar_cache = Cow::Borrowed(sysvar_cache); invoke_context.sysvar_cache = Cow::Borrowed(sysvar_cache);
@ -1351,7 +1339,7 @@ mod tests {
is_writable: false, is_writable: false,
}); });
} }
let mut transaction_context = TransactionContext::new(accounts, MAX_DEPTH); let mut transaction_context = TransactionContext::new(accounts, MAX_DEPTH, 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Check call depth increases and has a limit // Check call depth increases and has a limit
@ -1430,7 +1418,7 @@ mod tests {
let accounts = vec![(solana_sdk::pubkey::new_rand(), AccountSharedData::default())]; let accounts = vec![(solana_sdk::pubkey::new_rand(), AccountSharedData::default())];
let instruction_accounts = vec![]; let instruction_accounts = vec![];
let program_indices = vec![0]; let program_indices = vec![0];
let mut transaction_context = TransactionContext::new(accounts, 1); let mut transaction_context = TransactionContext::new(accounts, 1, 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context invoke_context
.push(&instruction_accounts, &program_indices, &[]) .push(&instruction_accounts, &program_indices, &[])
@ -1474,7 +1462,7 @@ mod tests {
is_writable: index_in_transaction < 2, is_writable: index_in_transaction < 2,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut transaction_context = TransactionContext::new(accounts, 2); let mut transaction_context = TransactionContext::new(accounts, 2, 8);
let mut invoke_context = let mut invoke_context =
InvokeContext::new_mock(&mut transaction_context, builtin_programs); InvokeContext::new_mock(&mut transaction_context, builtin_programs);
@ -1600,7 +1588,7 @@ mod tests {
let mut feature_set = FeatureSet::all_enabled(); let mut feature_set = FeatureSet::all_enabled();
feature_set.deactivate(&tx_wide_compute_cap::id()); feature_set.deactivate(&tx_wide_compute_cap::id());
feature_set.deactivate(&requestable_heap_size::id()); feature_set.deactivate(&requestable_heap_size::id());
let mut transaction_context = TransactionContext::new(accounts, 1); let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set); invoke_context.feature_set = Arc::new(feature_set);
@ -1652,7 +1640,7 @@ mod tests {
process_instruction: mock_process_instruction, process_instruction: mock_process_instruction,
}]; }];
let mut transaction_context = TransactionContext::new(accounts, 1); let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let mut invoke_context = let mut invoke_context =
InvokeContext::new_mock(&mut transaction_context, &builtin_programs); InvokeContext::new_mock(&mut transaction_context, &builtin_programs);

View File

@ -2,7 +2,6 @@
pub mod accounts_data_meter; pub mod accounts_data_meter;
pub mod compute_budget; pub mod compute_budget;
pub mod instruction_recorder;
pub mod invoke_context; pub mod invoke_context;
pub mod log_collector; pub mod log_collector;
pub mod native_loader; pub mod native_loader;

View File

@ -100,7 +100,7 @@ fn create_inputs() -> TransactionContext {
}, },
) )
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut transaction_context = TransactionContext::new(transaction_accounts, 1); let mut transaction_context = TransactionContext::new(transaction_accounts, 1, 1);
let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
transaction_context transaction_context
.push(&[0], &instruction_accounts, &instruction_data) .push(&[0], &instruction_accounts, &instruction_data)

View File

@ -456,7 +456,8 @@ mod tests {
instruction_accounts, instruction_accounts,
&program_indices, &program_indices,
); );
let mut transaction_context = TransactionContext::new(preparation.transaction_accounts, 1); let mut transaction_context =
TransactionContext::new(preparation.transaction_accounts, 1, 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context invoke_context
.push( .push(

View File

@ -3285,6 +3285,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();
@ -3358,6 +3359,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();
@ -3458,6 +3460,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();
@ -3496,6 +3499,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();
@ -3707,6 +3711,7 @@ mod tests {
AccountSharedData::new(0, 0, &bpf_loader_deprecated::id()), AccountSharedData::new(0, 0, &bpf_loader_deprecated::id()),
)], )],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();
@ -3864,6 +3869,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); invoke_context.sysvar_cache = Cow::Owned(sysvar_cache);
@ -4114,6 +4120,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();
@ -4226,6 +4233,7 @@ mod tests {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))], vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.push(&[], &[0], &[]).unwrap(); invoke_context.push(&[], &[0], &[]).unwrap();

View File

@ -4999,7 +4999,7 @@ mod tests {
#[test] #[test]
fn test_merge() { fn test_merge() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let stake_pubkey = solana_sdk::pubkey::new_rand(); let stake_pubkey = solana_sdk::pubkey::new_rand();
let source_stake_pubkey = solana_sdk::pubkey::new_rand(); let source_stake_pubkey = solana_sdk::pubkey::new_rand();
@ -5110,7 +5110,7 @@ mod tests {
#[test] #[test]
fn test_merge_self_fails() { fn test_merge_self_fails() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let stake_address = Pubkey::new_unique(); let stake_address = Pubkey::new_unique();
let authority_pubkey = Pubkey::new_unique(); let authority_pubkey = Pubkey::new_unique();
@ -5156,7 +5156,7 @@ mod tests {
#[test] #[test]
fn test_merge_incorrect_authorized_staker() { fn test_merge_incorrect_authorized_staker() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let stake_pubkey = solana_sdk::pubkey::new_rand(); let stake_pubkey = solana_sdk::pubkey::new_rand();
let source_stake_pubkey = solana_sdk::pubkey::new_rand(); let source_stake_pubkey = solana_sdk::pubkey::new_rand();
@ -5226,7 +5226,7 @@ mod tests {
#[test] #[test]
fn test_merge_invalid_account_data() { fn test_merge_invalid_account_data() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let stake_pubkey = solana_sdk::pubkey::new_rand(); let stake_pubkey = solana_sdk::pubkey::new_rand();
let source_stake_pubkey = solana_sdk::pubkey::new_rand(); let source_stake_pubkey = solana_sdk::pubkey::new_rand();
@ -5277,7 +5277,7 @@ mod tests {
#[test] #[test]
fn test_merge_fake_stake_source() { fn test_merge_fake_stake_source() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let stake_pubkey = solana_sdk::pubkey::new_rand(); let stake_pubkey = solana_sdk::pubkey::new_rand();
let source_stake_pubkey = solana_sdk::pubkey::new_rand(); let source_stake_pubkey = solana_sdk::pubkey::new_rand();
@ -5320,7 +5320,7 @@ mod tests {
#[test] #[test]
fn test_merge_active_stake() { fn test_merge_active_stake() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let base_lamports = 4242424242; let base_lamports = 4242424242;
let stake_address = Pubkey::new_unique(); let stake_address = Pubkey::new_unique();
@ -5943,7 +5943,7 @@ mod tests {
#[test] #[test]
fn test_things_can_merge() { fn test_things_can_merge() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let good_stake = Stake { let good_stake = Stake {
credits_observed: 4242, credits_observed: 4242,
@ -6042,7 +6042,7 @@ mod tests {
#[test] #[test]
fn test_metas_can_merge_pre_v4() { fn test_metas_can_merge_pre_v4() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Identical Metas can merge // Identical Metas can merge
assert!(MergeKind::metas_can_merge( assert!(MergeKind::metas_can_merge(
@ -6129,7 +6129,7 @@ mod tests {
#[test] #[test]
fn test_metas_can_merge_v4() { fn test_metas_can_merge_v4() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Identical Metas can merge // Identical Metas can merge
assert!(MergeKind::metas_can_merge( assert!(MergeKind::metas_can_merge(
@ -6276,7 +6276,7 @@ mod tests {
#[test] #[test]
fn test_merge_kind_get_if_mergeable() { fn test_merge_kind_get_if_mergeable() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let authority_pubkey = Pubkey::new_unique(); let authority_pubkey = Pubkey::new_unique();
let initial_lamports = 4242424242; let initial_lamports = 4242424242;
@ -6509,7 +6509,7 @@ mod tests {
#[test] #[test]
fn test_merge_kind_merge() { fn test_merge_kind_merge() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let lamports = 424242; let lamports = 424242;
let meta = Meta { let meta = Meta {
@ -6588,7 +6588,7 @@ mod tests {
#[test] #[test]
fn test_active_stake_merge() { fn test_active_stake_merge() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let delegation_a = 4_242_424_242u64; let delegation_a = 4_242_424_242u64;
let delegation_b = 6_200_000_000u64; let delegation_b = 6_200_000_000u64;

View File

@ -139,6 +139,7 @@ fn do_bench(bencher: &mut Bencher, feature: Option<Pubkey>) {
(solana_vote_program::id(), AccountSharedData::default()), (solana_vote_program::id(), AccountSharedData::default()),
], ],
1, 1,
1,
); );
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features( let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(

View File

@ -212,7 +212,7 @@ native machine code before execting it in the virtual machine.",
let program_indices = [0, 1]; let program_indices = [0, 1];
let preparation = let preparation =
prepare_mock_invoke_context(transaction_accounts, instruction_accounts, &program_indices); prepare_mock_invoke_context(transaction_accounts, instruction_accounts, &program_indices);
let mut transaction_context = TransactionContext::new(preparation.transaction_accounts, 1); let mut transaction_context = TransactionContext::new(preparation.transaction_accounts, 1, 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context invoke_context
.push( .push(

View File

@ -75,7 +75,6 @@ use {
solana_metrics::{inc_new_counter_debug, inc_new_counter_info}, solana_metrics::{inc_new_counter_debug, inc_new_counter_info},
solana_program_runtime::{ solana_program_runtime::{
compute_budget::ComputeBudget, compute_budget::ComputeBudget,
instruction_recorder::InstructionRecorder,
invoke_context::{ invoke_context::{
BuiltinProgram, Executor, Executors, ProcessInstructionWithContext, TransactionExecutor, BuiltinProgram, Executor, Executors, ProcessInstructionWithContext, TransactionExecutor,
}, },
@ -3661,19 +3660,12 @@ impl Bank {
let mut transaction_context = TransactionContext::new( let mut transaction_context = TransactionContext::new(
transaction_accounts, transaction_accounts,
compute_budget.max_invoke_depth.saturating_add(1), compute_budget.max_invoke_depth.saturating_add(1),
tx.message().instructions().len(),
); );
let pre_account_state_info = let pre_account_state_info =
self.get_transaction_account_state_info(&transaction_context, tx.message()); self.get_transaction_account_state_info(&transaction_context, tx.message());
let instruction_recorder = if enable_cpi_recording {
Some(InstructionRecorder::new_ref(
tx.message().instructions().len(),
))
} else {
None
};
let log_collector = if enable_log_recording { let log_collector = if enable_log_recording {
Some(LogCollector::new_ref()) Some(LogCollector::new_ref())
} else { } else {
@ -3691,7 +3683,6 @@ impl Bank {
self.rent_collector.rent, self.rent_collector.rent,
log_collector.clone(), log_collector.clone(),
executors.clone(), executors.clone(),
instruction_recorder.clone(),
self.feature_set.clone(), self.feature_set.clone(),
compute_budget, compute_budget,
timings, timings,
@ -3747,16 +3738,17 @@ impl Bank {
.ok() .ok()
}); });
let inner_instructions = instruction_recorder let (accounts, instruction_trace) = transaction_context.deconstruct();
.and_then(|instruction_recorder| Rc::try_unwrap(instruction_recorder).ok()) loaded_transaction.accounts = accounts;
.map(|instruction_recorder| instruction_recorder.into_inner().deconstruct());
loaded_transaction.accounts = transaction_context.deconstruct();
TransactionExecutionResult::Executed(TransactionExecutionDetails { TransactionExecutionResult::Executed(TransactionExecutionDetails {
status, status,
log_messages, log_messages,
inner_instructions, inner_instructions: if enable_cpi_recording {
Some(instruction_trace)
} else {
None
},
durable_nonce_fee, durable_nonce_fee,
}) })
} }
@ -15657,6 +15649,7 @@ pub(crate) mod tests {
sol_to_lamports(1.), sol_to_lamports(1.),
bank.last_blockhash(), bank.last_blockhash(),
); );
let number_of_instructions_at_transaction_level = tx.message().instructions.len();
let num_accounts = tx.message().account_keys.len(); let num_accounts = tx.message().account_keys.len();
let sanitized_tx = SanitizedTransaction::try_from_legacy_transaction(tx).unwrap(); let sanitized_tx = SanitizedTransaction::try_from_legacy_transaction(tx).unwrap();
let mut error_counters = ErrorCounters::default(); let mut error_counters = ErrorCounters::default();
@ -15674,6 +15667,7 @@ pub(crate) mod tests {
let transaction_context = TransactionContext::new( let transaction_context = TransactionContext::new(
loaded_txs[0].0.as_ref().unwrap().accounts.clone(), loaded_txs[0].0.as_ref().unwrap().accounts.clone(),
compute_budget.max_invoke_depth.saturating_add(1), compute_budget.max_invoke_depth.saturating_add(1),
number_of_instructions_at_transaction_level,
); );
assert_eq!( assert_eq!(

View File

@ -3,7 +3,6 @@ use {
solana_measure::measure::Measure, solana_measure::measure::Measure,
solana_program_runtime::{ solana_program_runtime::{
compute_budget::ComputeBudget, compute_budget::ComputeBudget,
instruction_recorder::InstructionRecorder,
invoke_context::{BuiltinProgram, Executors, InvokeContext}, invoke_context::{BuiltinProgram, Executors, InvokeContext},
log_collector::LogCollector, log_collector::LogCollector,
sysvar_cache::SysvarCache, sysvar_cache::SysvarCache,
@ -58,7 +57,6 @@ impl MessageProcessor {
rent: Rent, rent: Rent,
log_collector: Option<Rc<RefCell<LogCollector>>>, log_collector: Option<Rc<RefCell<LogCollector>>>,
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
instruction_recorder: Option<Rc<RefCell<InstructionRecorder>>>,
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
compute_budget: ComputeBudget, compute_budget: ComputeBudget,
timings: &mut ExecuteTimings, timings: &mut ExecuteTimings,
@ -75,7 +73,6 @@ impl MessageProcessor {
log_collector, log_collector,
compute_budget, compute_budget,
executors, executors,
instruction_recorder,
feature_set, feature_set,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
@ -242,7 +239,7 @@ mod tests {
create_loadable_account_for_test("mock_system_program"), create_loadable_account_for_test("mock_system_program"),
), ),
]; ];
let mut transaction_context = TransactionContext::new(accounts, 1); let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let program_indices = vec![vec![2]]; let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default())); let executors = Rc::new(RefCell::new(Executors::default()));
let account_metas = vec![ let account_metas = vec![
@ -267,7 +264,6 @@ mod tests {
rent_collector.rent, rent_collector.rent,
None, None,
executors.clone(), executors.clone(),
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
@ -308,7 +304,6 @@ mod tests {
rent_collector.rent, rent_collector.rent,
None, None,
executors.clone(), executors.clone(),
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
@ -341,7 +336,6 @@ mod tests {
rent_collector.rent, rent_collector.rent,
None, None,
executors, executors,
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
@ -441,7 +435,7 @@ mod tests {
create_loadable_account_for_test("mock_system_program"), create_loadable_account_for_test("mock_system_program"),
), ),
]; ];
let mut transaction_context = TransactionContext::new(accounts, 1); let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let program_indices = vec![vec![2]]; let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default())); let executors = Rc::new(RefCell::new(Executors::default()));
let account_metas = vec![ let account_metas = vec![
@ -468,7 +462,6 @@ mod tests {
rent_collector.rent, rent_collector.rent,
None, None,
executors.clone(), executors.clone(),
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
@ -502,7 +495,6 @@ mod tests {
rent_collector.rent, rent_collector.rent,
None, None,
executors.clone(), executors.clone(),
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
@ -533,7 +525,6 @@ mod tests {
rent_collector.rent, rent_collector.rent,
None, None,
executors, executors,
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
@ -586,7 +577,7 @@ mod tests {
(secp256k1_program::id(), secp256k1_account), (secp256k1_program::id(), secp256k1_account),
(mock_program_id, mock_program_account), (mock_program_id, mock_program_account),
]; ];
let mut transaction_context = TransactionContext::new(accounts, 1); let mut transaction_context = TransactionContext::new(accounts, 1, 1);
let message = SanitizedMessage::Legacy(Message::new( let message = SanitizedMessage::Legacy(Message::new(
&[ &[
@ -607,7 +598,6 @@ mod tests {
RentCollector::default().rent, RentCollector::default().rent,
None, None,
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
ComputeBudget::new(), ComputeBudget::new(),
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),

View File

@ -334,7 +334,7 @@ mod test {
where where
F: FnMut(&mut InvokeContext, &KeyedAccount), F: FnMut(&mut InvokeContext, &KeyedAccount),
{ {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let pubkey = Pubkey::new_unique(); let pubkey = Pubkey::new_unique();
let account = create_account(lamports); let account = create_account(lamports);

View File

@ -661,7 +661,7 @@ mod tests {
#[test] #[test]
fn test_address_create_with_seed_mismatch() { fn test_address_create_with_seed_mismatch() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
let seed = "dull boy"; let seed = "dull boy";
@ -676,7 +676,7 @@ mod tests {
#[test] #[test]
fn test_create_account_with_seed_missing_sig() { fn test_create_account_with_seed_missing_sig() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
@ -707,7 +707,7 @@ mod tests {
#[test] #[test]
fn test_create_with_zero_lamports() { fn test_create_with_zero_lamports() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// create account with zero lamports transferred // create account with zero lamports transferred
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
@ -742,7 +742,7 @@ mod tests {
#[test] #[test]
fn test_create_negative_lamports() { fn test_create_negative_lamports() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create account with more lamports than remaining in from_account // Attempt to create account with more lamports than remaining in from_account
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
@ -767,7 +767,7 @@ mod tests {
#[test] #[test]
fn test_request_more_than_allowed_data_length() { fn test_request_more_than_allowed_data_length() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from_account = RefCell::new(AccountSharedData::new(100, 0, &system_program::id())); let from_account = RefCell::new(AccountSharedData::new(100, 0, &system_program::id()));
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
@ -815,7 +815,7 @@ mod tests {
#[test] #[test]
fn test_create_already_in_use() { fn test_create_already_in_use() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create system account in account already owned by another program // Attempt to create system account in account already owned by another program
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
@ -884,7 +884,7 @@ mod tests {
#[test] #[test]
fn test_create_unsigned() { fn test_create_unsigned() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create an account without signing the transfer // Attempt to create an account without signing the transfer
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
@ -940,7 +940,7 @@ mod tests {
#[test] #[test]
fn test_create_sysvar_invalid_id_with_feature() { fn test_create_sysvar_invalid_id_with_feature() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create system account in account already owned by another program // Attempt to create system account in account already owned by another program
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
@ -968,7 +968,7 @@ mod tests {
#[test] #[test]
fn test_create_data_populated() { fn test_create_data_populated() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create system account in account with populated data // Attempt to create system account in account with populated data
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
@ -1002,7 +1002,7 @@ mod tests {
#[test] #[test]
fn test_create_from_account_is_nonce_fail() { fn test_create_from_account_is_nonce_fail() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let nonce = Pubkey::new_unique(); let nonce = Pubkey::new_unique();
let nonce_account = RefCell::new( let nonce_account = RefCell::new(
@ -1041,7 +1041,7 @@ mod tests {
#[test] #[test]
fn test_assign() { fn test_assign() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let new_owner = Pubkey::new(&[9; 32]); let new_owner = Pubkey::new(&[9; 32]);
let pubkey = Pubkey::new_unique(); let pubkey = Pubkey::new_unique();
@ -1084,7 +1084,7 @@ mod tests {
#[test] #[test]
fn test_assign_to_sysvar_with_feature() { fn test_assign_to_sysvar_with_feature() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let new_owner = sysvar::id(); let new_owner = sysvar::id();
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
@ -1135,7 +1135,7 @@ mod tests {
#[test] #[test]
fn test_transfer_lamports() { fn test_transfer_lamports() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
let from_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter let from_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter
@ -1174,7 +1174,7 @@ mod tests {
#[test] #[test]
fn test_transfer_with_seed() { fn test_transfer_with_seed() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let base = Pubkey::new_unique(); let base = Pubkey::new_unique();
let base_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter let base_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter
@ -1235,7 +1235,7 @@ mod tests {
#[test] #[test]
fn test_transfer_lamports_from_nonce_account_fail() { fn test_transfer_lamports_from_nonce_account_fail() {
let mut transaction_context = TransactionContext::new(Vec::new(), 1); let mut transaction_context = TransactionContext::new(Vec::new(), 1, 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from = Pubkey::new_unique(); let from = Pubkey::new_unique();
let from_account = RefCell::new( let from_account = RefCell::new(

View File

@ -2,7 +2,7 @@
use crate::{ use crate::{
account::{AccountSharedData, ReadableAccount, WritableAccount}, account::{AccountSharedData, ReadableAccount, WritableAccount},
instruction::InstructionError, instruction::{CompiledInstruction, InstructionError},
lamports::LamportsError, lamports::LamportsError,
pubkey::Pubkey, pubkey::Pubkey,
}; };
@ -31,6 +31,8 @@ pub struct TransactionContext {
accounts: Pin<Box<[RefCell<AccountSharedData>]>>, accounts: Pin<Box<[RefCell<AccountSharedData>]>>,
instruction_context_capacity: usize, instruction_context_capacity: usize,
instruction_context_stack: Vec<InstructionContext>, instruction_context_stack: Vec<InstructionContext>,
number_of_instructions_at_transaction_level: usize,
instruction_trace: Vec<Vec<CompiledInstruction>>,
return_data: (Pubkey, Vec<u8>), return_data: (Pubkey, Vec<u8>),
} }
@ -39,6 +41,7 @@ impl TransactionContext {
pub fn new( pub fn new(
transaction_accounts: Vec<TransactionAccount>, transaction_accounts: Vec<TransactionAccount>,
instruction_context_capacity: usize, instruction_context_capacity: usize,
number_of_instructions_at_transaction_level: usize,
) -> Self { ) -> Self {
let (account_keys, accounts): (Vec<Pubkey>, Vec<RefCell<AccountSharedData>>) = let (account_keys, accounts): (Vec<Pubkey>, Vec<RefCell<AccountSharedData>>) =
transaction_accounts transaction_accounts
@ -50,12 +53,15 @@ impl TransactionContext {
accounts: Pin::new(accounts.into_boxed_slice()), accounts: Pin::new(accounts.into_boxed_slice()),
instruction_context_capacity, instruction_context_capacity,
instruction_context_stack: Vec::with_capacity(instruction_context_capacity), instruction_context_stack: Vec::with_capacity(instruction_context_capacity),
number_of_instructions_at_transaction_level,
instruction_trace: Vec::with_capacity(number_of_instructions_at_transaction_level),
return_data: (Pubkey::default(), Vec::new()), return_data: (Pubkey::default(), Vec::new()),
} }
} }
/// Used by the bank in the runtime to write back the processed accounts /// Used by the bank in the runtime to write back the processed accounts and recorded instructions
pub fn deconstruct(self) -> Vec<TransactionAccount> { pub fn deconstruct(self) -> (Vec<TransactionAccount>, Vec<Vec<CompiledInstruction>>) {
(
Vec::from(Pin::into_inner(self.account_keys)) Vec::from(Pin::into_inner(self.account_keys))
.into_iter() .into_iter()
.zip( .zip(
@ -63,7 +69,9 @@ impl TransactionContext {
.into_iter() .into_iter()
.map(|account| account.into_inner()), .map(|account| account.into_inner()),
) )
.collect() .collect(),
self.instruction_trace,
)
} }
/// Used in mock_process_instruction /// Used in mock_process_instruction
@ -143,6 +151,12 @@ impl TransactionContext {
if self.instruction_context_stack.len() >= self.instruction_context_capacity { if self.instruction_context_stack.len() >= self.instruction_context_capacity {
return Err(InstructionError::CallDepth); return Err(InstructionError::CallDepth);
} }
if self.instruction_context_stack.is_empty() {
debug_assert!(
self.instruction_trace.len() < self.number_of_instructions_at_transaction_level
);
self.instruction_trace.push(Vec::new());
}
self.instruction_context_stack.push(InstructionContext { self.instruction_context_stack.push(InstructionContext {
program_accounts: program_accounts.to_vec(), program_accounts: program_accounts.to_vec(),
instruction_accounts: instruction_accounts.to_vec(), instruction_accounts: instruction_accounts.to_vec(),
@ -188,6 +202,13 @@ impl TransactionContext {
self.return_data = (program_id, data); self.return_data = (program_id, data);
Ok(()) Ok(())
} }
/// Used by the runtime when a new CPI instruction begins
pub fn record_compiled_instruction(&mut self, instruction: CompiledInstruction) {
if let Some(records) = self.instruction_trace.last_mut() {
records.push(instruction);
}
}
} }
/// Loaded instruction shared between runtime and programs. /// Loaded instruction shared between runtime and programs.