diff --git a/Cargo.lock b/Cargo.lock index 5103a890..24f22428 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1817,6 +1817,7 @@ dependencies = [ "solana-epoch-schedule", "solana-hash", "solana-instruction", + "solana-instructions-sysvar", "solana-loader-v3-interface 3.0.0", "solana-loader-v4-interface", "solana-log-collector", diff --git a/Cargo.toml b/Cargo.toml index 67574c61..d9fe7539 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,6 +63,7 @@ solana-epoch-rewards = "2.2" solana-epoch-schedule = "2.2" solana-hash = "2.2" solana-instruction = "2.2" +solana-instructions-sysvar = "2.2" solana-keccak-hasher = "2.2" solana-loader-v3-interface = "3.0" solana-loader-v4-interface = "2.2" diff --git a/harness/Cargo.toml b/harness/Cargo.toml index 6bbdc70c..7de3d3cd 100644 --- a/harness/Cargo.toml +++ b/harness/Cargo.toml @@ -48,6 +48,7 @@ solana-epoch-rewards = { workspace = true } solana-epoch-schedule = { workspace = true } solana-hash = { workspace = true } solana-instruction = { workspace = true } +solana-instructions-sysvar = { workspace = true } solana-loader-v3-interface = { workspace = true, features = ["serde"] } solana-loader-v4-interface = { workspace = true } solana-log-collector = { workspace = true } diff --git a/harness/src/instructions_sysvar.rs b/harness/src/instructions_sysvar.rs new file mode 100644 index 00000000..4309d7ff --- /dev/null +++ b/harness/src/instructions_sysvar.rs @@ -0,0 +1,40 @@ +use { + crate::Mollusk, + solana_account::Account, + solana_instruction::{BorrowedAccountMeta, BorrowedInstruction, Instruction}, + solana_instructions_sysvar::construct_instructions_data, + solana_pubkey::Pubkey, +}; + +pub fn keyed_account(mollusk: &Mollusk, instructions: &[Instruction]) -> (Pubkey, Account) { + let data = construct_instructions_data( + instructions + .iter() + .map(|instruction| BorrowedInstruction { + program_id: &instruction.program_id, + accounts: instruction + .accounts + .iter() + .map(|meta| BorrowedAccountMeta { + pubkey: &meta.pubkey, + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect(), + data: &instruction.data, + }) + .collect::>() + .as_slice(), + ); + + ( + solana_instructions_sysvar::ID, + Account { + lamports: mollusk.sysvars.rent.minimum_balance(data.len()), + data, + owner: solana_sysvar_id::ID, + executable: false, + rent_epoch: Default::default(), + }, + ) +} diff --git a/harness/src/lib.rs b/harness/src/lib.rs index ebb7d38c..2d359ddc 100644 --- a/harness/src/lib.rs +++ b/harness/src/lib.rs @@ -445,6 +445,7 @@ pub mod epoch_stake; pub mod file; #[cfg(any(feature = "fuzz", feature = "fuzz-fd"))] pub mod fuzz; +pub mod instructions_sysvar; pub mod program; pub mod sysvar; @@ -666,6 +667,15 @@ impl Mollusk { &self, instruction: &Instruction, accounts: &[(Pubkey, Account)], + ) -> InstructionResult { + self.process_instruction_with_instruction_index(instruction, accounts, 0) + } + + pub fn process_instruction_with_instruction_index( + &self, + instruction: &Instruction, + accounts: &[(Pubkey, Account)], + instruction_index: usize, ) -> InstructionResult { let mut compute_units_consumed = 0; let mut timings = ExecuteTimings::default(); @@ -692,6 +702,7 @@ impl Mollusk { self.compute_budget.max_instruction_stack_depth, self.compute_budget.max_instruction_trace_length, ); + transaction_context.set_top_level_instruction_index(instruction_index); let invoke_result = { let mut program_cache = self.program_cache.cache(); @@ -803,8 +814,12 @@ impl Mollusk { ..Default::default() }; - for instruction in instructions { - let this_result = self.process_instruction(instruction, &result.resulting_accounts); + for (index, instruction) in instructions.iter().enumerate() { + let this_result = self.process_instruction_with_instruction_index( + instruction, + &result.resulting_accounts, + index, + ); result.absorb(this_result);