From bf9ca9827e0ce1fb6a156fe0b122b6e018d950f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Thu, 16 Jun 2022 18:46:17 +0200 Subject: [PATCH] Refactor: instruction account index (#25825) * Adds methods based on instruction_account_index to InstructionContext. Removes methods which are based on index_in_instruction. * Adjusts program-runtime. * Adjusts runtime. * Adjusts bpf loader. * Adjusts built-in programs. * Adjusts program-test and bpf tests. --- program-runtime/src/invoke_context.rs | 70 +++--- program-runtime/src/sysvar_cache.rs | 27 ++- program-test/src/lib.rs | 29 ++- .../address-lookup-table/src/processor.rs | 47 +--- programs/bpf/tests/programs.rs | 2 +- programs/bpf_loader/benches/serialization.rs | 8 +- programs/bpf_loader/src/lib.rs | 175 +++++++++------ programs/bpf_loader/src/serialization.rs | 85 ++++--- programs/bpf_loader/src/syscalls.rs | 38 ++-- programs/config/src/config_processor.rs | 8 +- programs/stake/src/stake_instruction.rs | 104 ++++----- programs/stake/src/stake_state.rs | 97 ++++---- programs/vote/benches/process_vote.rs | 8 +- programs/vote/src/vote_processor.rs | 28 +-- programs/vote/src/vote_state/mod.rs | 8 +- runtime/src/bank.rs | 23 +- runtime/src/message_processor.rs | 6 +- runtime/src/nonce_keyed_account.rs | 55 ++--- runtime/src/system_instruction_processor.rs | 78 ++++--- sdk/src/transaction_context.rs | 211 +++++++++--------- 20 files changed, 559 insertions(+), 548 deletions(-) diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 44fc0f34a7..759d535ac3 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -368,10 +368,10 @@ impl<'a> InvokeContext<'a> { self.pre_accounts = Vec::with_capacity(instruction_accounts.len()); - for (index_in_instruction, instruction_account) in + for (instruction_account_index, instruction_account) in instruction_accounts.iter().enumerate() { - if index_in_instruction != instruction_account.index_in_callee { + if instruction_account_index != instruction_account.index_in_callee { continue; // Skip duplicate account } if instruction_account.index_in_transaction @@ -398,7 +398,8 @@ impl<'a> InvokeContext<'a> { self.transaction_context .get_instruction_context_at(level) .and_then(|instruction_context| { - instruction_context.try_borrow_program_account(self.transaction_context) + instruction_context + .try_borrow_last_program_account(self.transaction_context) }) .map(|program_account| program_account.get_key() == program_id) .unwrap_or(false) @@ -407,7 +408,7 @@ impl<'a> InvokeContext<'a> { .transaction_context .get_current_instruction_context() .and_then(|instruction_context| { - instruction_context.try_borrow_program_account(self.transaction_context) + instruction_context.try_borrow_last_program_account(self.transaction_context) }) .map(|program_account| program_account.get_key() == program_id) .unwrap_or(false); @@ -490,7 +491,7 @@ impl<'a> InvokeContext<'a> { .get_current_instruction_context() .map_err(|_| InstructionError::CallDepth)?; let program_id = instruction_context - .get_program_key(self.transaction_context) + .get_last_program_key(self.transaction_context) .map_err(|_| InstructionError::CallDepth)?; // Verify all executable accounts have zero outstanding refs @@ -504,8 +505,10 @@ impl<'a> InvokeContext<'a> { // Verify the per-account instruction results let (mut pre_sum, mut post_sum) = (0_u128, 0_u128); let mut pre_account_index = 0; - for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() { - if index_in_instruction != instruction_account.index_in_callee { + for (instruction_account_index, instruction_account) in + instruction_accounts.iter().enumerate() + { + if instruction_account_index != instruction_account.index_in_callee { continue; // Skip duplicate account } { @@ -581,13 +584,15 @@ impl<'a> InvokeContext<'a> { let transaction_context = &self.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let program_id = instruction_context - .get_program_key(transaction_context) + .get_last_program_key(transaction_context) .map_err(|_| InstructionError::CallDepth)?; // Verify the per-account instruction results let (mut pre_sum, mut post_sum) = (0_u128, 0_u128); - for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() { - if index_in_instruction != instruction_account.index_in_callee { + for (instruction_account_index, instruction_account) in + instruction_accounts.iter().enumerate() + { + if instruction_account_index != instruction_account.index_in_callee { continue; // Skip duplicate account } if instruction_account.index_in_transaction @@ -599,11 +604,7 @@ impl<'a> InvokeContext<'a> { .get_account_at_index(instruction_account.index_in_transaction)?; let is_writable = if before_instruction_context_push { instruction_context - .try_borrow_instruction_account( - self.transaction_context, - instruction_account.index_in_caller, - )? - .is_writable() + .is_instruction_account_writable(instruction_account.index_in_caller)? } else { instruction_account.is_writable }; @@ -713,7 +714,7 @@ impl<'a> InvokeContext<'a> { let instruction_context = self.transaction_context.get_current_instruction_context()?; let mut deduplicated_instruction_accounts: Vec = Vec::new(); let mut duplicate_indicies = Vec::with_capacity(instruction.accounts.len()); - for (index_in_instruction, account_meta) in instruction.accounts.iter().enumerate() { + for (instruction_account_index, account_meta) in instruction.accounts.iter().enumerate() { let index_in_transaction = self .transaction_context .find_index_of_account(&account_meta.pubkey) @@ -740,10 +741,10 @@ impl<'a> InvokeContext<'a> { instruction_account.is_writable |= account_meta.is_writable; } else { let index_in_caller = instruction_context - .find_index_of_account(self.transaction_context, &account_meta.pubkey) - .map(|index| { - index.saturating_sub(instruction_context.get_number_of_program_accounts()) - }) + .find_index_of_instruction_account( + self.transaction_context, + &account_meta.pubkey, + ) .ok_or_else(|| { ic_msg!( self, @@ -756,7 +757,7 @@ impl<'a> InvokeContext<'a> { deduplicated_instruction_accounts.push(InstructionAccount { index_in_transaction, index_in_caller, - index_in_callee: index_in_instruction, + index_in_callee: instruction_account_index, is_signer: account_meta.is_signer, is_writable: account_meta.is_writable, }); @@ -804,13 +805,13 @@ impl<'a> InvokeContext<'a> { // Find and validate executables / program accounts let callee_program_id = instruction.program_id; let program_account_index = instruction_context - .find_index_of_account(self.transaction_context, &callee_program_id) + .find_index_of_instruction_account(self.transaction_context, &callee_program_id) .ok_or_else(|| { ic_msg!(self, "Unknown program {}", callee_program_id); InstructionError::MissingAccount })?; let borrowed_program_account = instruction_context - .try_borrow_account(self.transaction_context, program_account_index)?; + .try_borrow_instruction_account(self.transaction_context, program_account_index)?; if !borrowed_program_account.is_executable() { ic_msg!(self, "Account {} is not executable", callee_program_id); return Err(InstructionError::AccountNotExecutable); @@ -952,7 +953,7 @@ impl<'a> InvokeContext<'a> { let (first_instruction_account, builtin_id) = { let borrowed_root_account = instruction_context - .try_borrow_account(self.transaction_context, 0) + .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) { @@ -964,7 +965,8 @@ impl<'a> InvokeContext<'a> { for entry in self.builtin_programs { if entry.program_id == builtin_id { - let program_id = instruction_context.get_program_id(self.transaction_context); + let program_id = + *instruction_context.get_last_program_key(self.transaction_context)?; if builtin_id == program_id { let logger = self.get_log_collector(); stable_log::program_invoke(&logger, &program_id, self.get_stack_height()); @@ -1123,19 +1125,19 @@ pub fn prepare_mock_invoke_context( ) -> MockInvokeContextPreparation { let mut instruction_accounts: Vec = Vec::with_capacity(instruction_account_metas.len()); - for (index_in_instruction, account_meta) in instruction_account_metas.iter().enumerate() { + for (instruction_account_index, account_meta) in instruction_account_metas.iter().enumerate() { let index_in_transaction = transaction_accounts .iter() .position(|(key, _account)| *key == account_meta.pubkey) .unwrap_or(transaction_accounts.len()); let index_in_callee = instruction_accounts - .get(0..index_in_instruction) + .get(0..instruction_account_index) .unwrap() .iter() .position(|instruction_account| { instruction_account.index_in_transaction == index_in_transaction }) - .unwrap_or(index_in_instruction); + .unwrap_or(instruction_account_index); instruction_accounts.push(InstructionAccount { index_in_transaction, index_in_caller: index_in_transaction, @@ -1295,7 +1297,7 @@ mod tests { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; assert_eq!( program_id, instruction_context @@ -1528,12 +1530,12 @@ mod tests { AccountMeta::new_readonly(accounts.get(2).unwrap().0, false), ]; let instruction_accounts = (0..4) - .map(|index_in_instruction| InstructionAccount { - index_in_transaction: index_in_instruction, - index_in_caller: index_in_instruction, - index_in_callee: index_in_instruction, + .map(|instruction_account_index| InstructionAccount { + index_in_transaction: instruction_account_index, + index_in_caller: instruction_account_index, + index_in_callee: instruction_account_index, is_signer: false, - is_writable: index_in_instruction < 2, + is_writable: instruction_account_index < 2, }) .collect::>(); let mut transaction_context = TransactionContext::new(accounts, 2, 8); diff --git a/program-runtime/src/sysvar_cache.rs b/program-runtime/src/sysvar_cache.rs index 9469b94ab2..79ea90dc70 100644 --- a/program-runtime/src/sysvar_cache.rs +++ b/program-runtime/src/sysvar_cache.rs @@ -186,10 +186,9 @@ pub mod get_sysvar_with_account_check { instruction_context: &InstructionContext, instruction_account_index: usize, ) -> Result<(), InstructionError> { - if !S::check_id( - instruction_context - .get_instruction_account_key(transaction_context, instruction_account_index)?, - ) { + let index_in_transaction = instruction_context + .get_index_of_instruction_account_in_transaction(instruction_account_index)?; + if !S::check_id(transaction_context.get_key_of_account_at_index(index_in_transaction)?) { return Err(InstructionError::InvalidArgument); } Ok(()) @@ -198,12 +197,12 @@ pub mod get_sysvar_with_account_check { pub fn clock( invoke_context: &InvokeContext, instruction_context: &InstructionContext, - index_in_instruction: usize, + instruction_account_index: usize, ) -> Result, InstructionError> { check_sysvar_account::( invoke_context.transaction_context, instruction_context, - index_in_instruction, + instruction_account_index, )?; invoke_context.get_sysvar_cache().get_clock() } @@ -211,12 +210,12 @@ pub mod get_sysvar_with_account_check { pub fn rent( invoke_context: &InvokeContext, instruction_context: &InstructionContext, - index_in_instruction: usize, + instruction_account_index: usize, ) -> Result, InstructionError> { check_sysvar_account::( invoke_context.transaction_context, instruction_context, - index_in_instruction, + instruction_account_index, )?; invoke_context.get_sysvar_cache().get_rent() } @@ -224,12 +223,12 @@ pub mod get_sysvar_with_account_check { pub fn slot_hashes( invoke_context: &InvokeContext, instruction_context: &InstructionContext, - index_in_instruction: usize, + instruction_account_index: usize, ) -> Result, InstructionError> { check_sysvar_account::( invoke_context.transaction_context, instruction_context, - index_in_instruction, + instruction_account_index, )?; invoke_context.get_sysvar_cache().get_slot_hashes() } @@ -238,12 +237,12 @@ pub mod get_sysvar_with_account_check { pub fn recent_blockhashes( invoke_context: &InvokeContext, instruction_context: &InstructionContext, - index_in_instruction: usize, + instruction_account_index: usize, ) -> Result, InstructionError> { check_sysvar_account::( invoke_context.transaction_context, instruction_context, - index_in_instruction, + instruction_account_index, )?; invoke_context.get_sysvar_cache().get_recent_blockhashes() } @@ -251,12 +250,12 @@ pub mod get_sysvar_with_account_check { pub fn stake_history( invoke_context: &InvokeContext, instruction_context: &InstructionContext, - index_in_instruction: usize, + instruction_account_index: usize, ) -> Result, InstructionError> { check_sysvar_account::( invoke_context.transaction_context, instruction_context, - index_in_instruction, + instruction_account_index, )?; invoke_context.get_sysvar_cache().get_stake_history() } diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index 24a7df5937..6b9ce41ec9 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -101,11 +101,10 @@ pub fn builtin_process_instruction( let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - let indices_in_instruction = instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts(); + let instruction_account_indices = 0..instruction_context.get_number_of_instruction_accounts(); let log_collector = invoke_context.get_log_collector(); - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; stable_log::program_invoke( &log_collector, program_id, @@ -113,14 +112,14 @@ pub fn builtin_process_instruction( ); // Copy indices_in_instruction into a HashSet to ensure there are no duplicates - let deduplicated_indices: HashSet = indices_in_instruction.clone().collect(); + let deduplicated_indices: HashSet = instruction_account_indices.clone().collect(); // Create copies of the accounts let mut account_copies = deduplicated_indices .iter() - .map(|index_in_instruction| { + .map(|instruction_account_index| { let borrowed_account = instruction_context - .try_borrow_account(transaction_context, *index_in_instruction)?; + .try_borrow_instruction_account(transaction_context, *instruction_account_index)?; Ok(( *borrowed_account.get_key(), *borrowed_account.get_owner(), @@ -144,15 +143,15 @@ pub fn builtin_process_instruction( .collect(); // Create AccountInfos - let account_infos = indices_in_instruction - .map(|index_in_instruction| { + let account_infos = instruction_account_indices + .map(|instruction_account_index| { let account_copy_index = deduplicated_indices .iter() - .position(|index| *index == index_in_instruction) + .position(|index| *index == instruction_account_index) .unwrap(); let (key, owner, lamports, data) = &account_refs[account_copy_index]; let borrowed_account = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)?; + .try_borrow_instruction_account(transaction_context, instruction_account_index)?; Ok(AccountInfo { key, is_signer: borrowed_account.is_signer(), @@ -175,12 +174,12 @@ pub fn builtin_process_instruction( stable_log::program_success(&log_collector, program_id); // Commit AccountInfo changes back into KeyedAccounts - for (index_in_instruction, (_key, _owner, lamports, data)) in deduplicated_indices + for (instruction_account_index, (_key, _owner, lamports, data)) in deduplicated_indices .into_iter() .zip(account_copies.into_iter()) { - let mut borrowed_account = - instruction_context.try_borrow_account(transaction_context, index_in_instruction)?; + let mut borrowed_account = instruction_context + .try_borrow_instruction_account(transaction_context, instruction_account_index)?; if borrowed_account.is_writable() { borrowed_account.set_lamports(lamports)?; borrowed_account.set_data(&data)?; @@ -253,7 +252,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs { .get_current_instruction_context() .unwrap(); let caller = instruction_context - .get_program_key(transaction_context) + .get_last_program_key(transaction_context) .unwrap(); stable_log::program_invoke( @@ -379,7 +378,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs { .get_current_instruction_context() .unwrap(); let caller = *instruction_context - .get_program_key(transaction_context) + .get_last_program_key(transaction_context) .unwrap(); transaction_context .set_return_data(caller, data.to_vec()) diff --git a/programs/address-lookup-table/src/processor.rs b/programs/address-lookup-table/src/processor.rs index d5eb33c97f..39d36b988c 100644 --- a/programs/address-lookup-table/src/processor.rs +++ b/programs/address-lookup-table/src/processor.rs @@ -18,7 +18,7 @@ use { }; pub fn process_instruction( - first_instruction_account: usize, + _first_instruction_account: usize, invoke_context: &mut InvokeContext, ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; @@ -28,24 +28,15 @@ pub fn process_instruction( ProgramInstruction::CreateLookupTable { recent_slot, bump_seed, - } => Processor::create_lookup_table( - invoke_context, - first_instruction_account, - recent_slot, - bump_seed, - ), - ProgramInstruction::FreezeLookupTable => { - Processor::freeze_lookup_table(invoke_context, first_instruction_account) - } + } => Processor::create_lookup_table(invoke_context, recent_slot, bump_seed), + ProgramInstruction::FreezeLookupTable => Processor::freeze_lookup_table(invoke_context), ProgramInstruction::ExtendLookupTable { new_addresses } => { - Processor::extend_lookup_table(invoke_context, first_instruction_account, new_addresses) + Processor::extend_lookup_table(invoke_context, new_addresses) } ProgramInstruction::DeactivateLookupTable => { - Processor::deactivate_lookup_table(invoke_context, first_instruction_account) - } - ProgramInstruction::CloseLookupTable => { - Processor::close_lookup_table(invoke_context, first_instruction_account) + Processor::deactivate_lookup_table(invoke_context) } + ProgramInstruction::CloseLookupTable => Processor::close_lookup_table(invoke_context), } } @@ -57,7 +48,6 @@ pub struct Processor; impl Processor { fn create_lookup_table( invoke_context: &mut InvokeContext, - _first_instruction_account: usize, untrusted_recent_slot: Slot, bump_seed: u8, ) -> Result<(), InstructionError> { @@ -161,10 +151,7 @@ impl Processor { Ok(()) } - fn freeze_lookup_table( - invoke_context: &mut InvokeContext, - _first_instruction_account: usize, - ) -> Result<(), InstructionError> { + fn freeze_lookup_table(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; @@ -217,7 +204,6 @@ impl Processor { fn extend_lookup_table( invoke_context: &mut InvokeContext, - _first_instruction_account: usize, new_addresses: Vec, ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; @@ -335,10 +321,7 @@ impl Processor { Ok(()) } - fn deactivate_lookup_table( - invoke_context: &mut InvokeContext, - _first_instruction_account: usize, - ) -> Result<(), InstructionError> { + fn deactivate_lookup_table(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; @@ -387,10 +370,7 @@ impl Processor { Ok(()) } - fn close_lookup_table( - invoke_context: &mut InvokeContext, - _first_instruction_account: usize, - ) -> Result<(), InstructionError> { + fn close_lookup_table(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; @@ -411,13 +391,8 @@ impl Processor { drop(authority_account); instruction_context.check_number_of_instruction_accounts(3)?; - if instruction_context - .get_index_in_transaction(instruction_context.get_number_of_program_accounts())? - == instruction_context.get_index_in_transaction( - instruction_context - .get_number_of_program_accounts() - .saturating_add(2), - )? + if instruction_context.get_index_of_instruction_account_in_transaction(0)? + == instruction_context.get_index_of_instruction_account_in_transaction(2)? { ic_msg!( invoke_context, diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 20327763c3..289aacf827 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -246,7 +246,7 @@ fn run_program(name: &str) -> u64 { .get_current_instruction_context() .unwrap(); let caller = *instruction_context - .get_program_key(transaction_context) + .get_last_program_key(transaction_context) .unwrap(); transaction_context .set_return_data(caller, Vec::new()) diff --git a/programs/bpf_loader/benches/serialization.rs b/programs/bpf_loader/benches/serialization.rs index dbc62c09d7..2be8073bf0 100644 --- a/programs/bpf_loader/benches/serialization.rs +++ b/programs/bpf_loader/benches/serialization.rs @@ -92,12 +92,12 @@ fn create_inputs() -> TransactionContext { .into_iter() .enumerate() .map( - |(index_in_instruction, index_in_transaction)| InstructionAccount { - index_in_caller: index_in_instruction, + |(instruction_account_index, index_in_transaction)| InstructionAccount { + index_in_caller: instruction_account_index, index_in_transaction, - index_in_callee: index_in_instruction, + index_in_callee: instruction_account_index, is_signer: false, - is_writable: index_in_instruction >= 4, + is_writable: instruction_account_index >= 4, }, ) .collect::>(); diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index dc26f55498..f5d515f22d 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -54,7 +54,7 @@ use { pubkey::Pubkey, saturating_add_assign, system_instruction::{self, MAX_PERMITTED_DATA_LENGTH}, - transaction_context::{InstructionContext, TransactionContext}, + transaction_context::{BorrowedAccount, InstructionContext, TransactionContext}, }, std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc}, thiserror::Error, @@ -103,6 +103,40 @@ mod executor_metrics { } } +// The BPF loader is special in that it is the only place in the runtime and its built-in programs, +// where data comes not only from instruction account but also program accounts. +// Thus, these two helper methods have to distinguish the mixed sources via index_in_instruction. + +fn get_index_in_transaction( + instruction_context: &InstructionContext, + index_in_instruction: usize, +) -> Result { + if index_in_instruction < instruction_context.get_number_of_program_accounts() { + instruction_context.get_index_of_program_account_in_transaction(index_in_instruction) + } else { + instruction_context.get_index_of_instruction_account_in_transaction( + index_in_instruction + .saturating_sub(instruction_context.get_number_of_program_accounts()), + ) + } +} + +fn try_borrow_account<'a>( + transaction_context: &'a TransactionContext, + instruction_context: &'a InstructionContext, + index_in_instruction: usize, +) -> Result, InstructionError> { + if index_in_instruction < instruction_context.get_number_of_program_accounts() { + instruction_context.try_borrow_program_account(transaction_context, index_in_instruction) + } else { + instruction_context.try_borrow_instruction_account( + transaction_context, + index_in_instruction + .saturating_sub(instruction_context.get_number_of_program_accounts()), + ) + } +} + pub fn create_executor( programdata_account_index: usize, programdata_offset: usize, @@ -160,8 +194,11 @@ pub fn create_executor( let executable = { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let programdata = instruction_context - .try_borrow_account(transaction_context, programdata_account_index)?; + let programdata = try_borrow_account( + transaction_context, + instruction_context, + programdata_account_index, + )?; create_executor_metrics.program_id = programdata.get_key().to_string(); let mut load_elf_time = Measure::start("load_elf_time"); let executable = Executable::::from_elf( @@ -222,8 +259,11 @@ fn write_program_data( ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let mut program = - instruction_context.try_borrow_account(transaction_context, program_account_index)?; + let mut program = try_borrow_account( + transaction_context, + instruction_context, + program_account_index, + )?; let data = program.get_data_mut()?; let write_offset = program_data_offset.saturating_add(bytes.len()); if data.len() < write_offset { @@ -296,15 +336,17 @@ fn process_instruction_common( let log_collector = invoke_context.get_log_collector(); let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; let first_account_key = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + get_index_in_transaction(instruction_context, first_instruction_account)?, )?; - let second_account_key = instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(1)) - .and_then(|index_in_transaction| { - transaction_context.get_key_of_account_at_index(index_in_transaction) - }); + let second_account_key = get_index_in_transaction( + instruction_context, + first_instruction_account.saturating_add(1), + ) + .and_then(|index_in_transaction| { + transaction_context.get_key_of_account_at_index(index_in_transaction) + }); let program_account_index = if first_account_key == program_id { first_instruction_account @@ -314,18 +356,23 @@ fn process_instruction_common( { first_instruction_account.saturating_add(1) } else { - if instruction_context - .try_borrow_account(transaction_context, first_instruction_account)? - .is_executable() - { + let first_account = try_borrow_account( + transaction_context, + instruction_context, + first_instruction_account, + )?; + if first_account.is_executable() { ic_logger_msg!(log_collector, "BPF loader is executable"); return Err(InstructionError::IncorrectProgramId); } first_instruction_account }; - let program = - instruction_context.try_borrow_account(transaction_context, program_account_index)?; + let program = try_borrow_account( + transaction_context, + instruction_context, + program_account_index, + )?; if program.is_executable() { // First instruction account can only be zero if called from CPI, which // means stack height better be greater than one @@ -356,7 +403,7 @@ fn process_instruction_common( } if !matches!( instruction_context - .try_borrow_account(transaction_context, first_instruction_account)? + .try_borrow_program_account(transaction_context, first_instruction_account)? .get_state()?, UpgradeableLoaderState::ProgramData { slot: _, @@ -391,7 +438,7 @@ fn process_instruction_common( )?; let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; invoke_context.add_executor(program_id, executor.clone()); executor } @@ -438,7 +485,7 @@ fn process_loader_upgradeable_instruction( let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; match limited_deserialize(instruction_data)? { UpgradeableLoaderInstruction::InitializeBuffer => { @@ -451,12 +498,9 @@ fn process_loader_upgradeable_instruction( return Err(InstructionError::AccountAlreadyInitialized); } - let authority_key = Some( - *transaction_context.get_key_of_account_at_index( - instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(1))?, - )?, - ); + let authority_key = Some(*transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction(1)?, + )?); buffer.set_state(&UpgradeableLoaderState::Buffer { authority_address: authority_key, @@ -472,17 +516,14 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Buffer is immutable"); return Err(InstructionError::Immutable); // TODO better error code } - let authority_key = - Some(*transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction( - first_instruction_account.saturating_add(1), - )?, - )?); + let authority_key = Some(*transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction(1)?, + )?); if authority_address != authority_key { ic_logger_msg!(log_collector, "Incorrect buffer authority provided"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context.is_signer(first_instruction_account.saturating_add(1))? { + if !instruction_context.is_instruction_account_signer(1)? { ic_logger_msg!(log_collector, "Buffer authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -501,22 +542,18 @@ fn process_loader_upgradeable_instruction( UpgradeableLoaderInstruction::DeployWithMaxDataLen { max_data_len } => { instruction_context.check_number_of_instruction_accounts(4)?; let payer_key = *transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + instruction_context.get_index_of_instruction_account_in_transaction(0)?, )?; let programdata_key = *transaction_context.get_key_of_account_at_index( - instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(1))?, + instruction_context.get_index_of_instruction_account_in_transaction(1)?, )?; let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 4)?; let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 5)?; instruction_context.check_number_of_instruction_accounts(8)?; - let authority_key = Some( - *transaction_context.get_key_of_account_at_index( - instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(7))?, - )?, - ); + let authority_key = Some(*transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction(7)?, + )?); // Verify Program account @@ -546,7 +583,7 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context.is_signer(first_instruction_account.saturating_add(7))? { + if !instruction_context.is_instruction_account_signer(7)? { ic_logger_msg!(log_collector, "Upgrade authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -617,7 +654,8 @@ fn process_loader_upgradeable_instruction( let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let caller_program_id = instruction_context.get_program_key(transaction_context)?; + let caller_program_id = + instruction_context.get_last_program_key(transaction_context)?; let signers = [&[new_program_id.as_ref(), &[bump_seed]]] .iter() .map(|seeds| Pubkey::create_program_address(*seeds, caller_program_id)) @@ -689,18 +727,15 @@ fn process_loader_upgradeable_instruction( UpgradeableLoaderInstruction::Upgrade => { instruction_context.check_number_of_instruction_accounts(3)?; let programdata_key = *transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + instruction_context.get_index_of_instruction_account_in_transaction(0)?, )?; let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 4)?; let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 5)?; instruction_context.check_number_of_instruction_accounts(7)?; - let authority_key = Some( - *transaction_context.get_key_of_account_at_index( - instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(6))?, - )?, - ); + let authority_key = Some(*transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction(6)?, + )?); // Verify Program account @@ -742,7 +777,7 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context.is_signer(first_instruction_account.saturating_add(6))? { + if !instruction_context.is_instruction_account_signer(6)? { ic_logger_msg!(log_collector, "Upgrade authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -796,7 +831,7 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Incorrect upgrade authority provided"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context.is_signer(first_instruction_account.saturating_add(6))? { + if !instruction_context.is_instruction_account_signer(6)? { ic_logger_msg!(log_collector, "Upgrade authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -878,11 +913,10 @@ fn process_loader_upgradeable_instruction( let mut account = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let present_authority_key = transaction_context.get_key_of_account_at_index( - instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(1))?, + instruction_context.get_index_of_instruction_account_in_transaction(1)?, )?; let new_authority = instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(2)) + .get_index_of_instruction_account_in_transaction(2) .and_then(|index_in_transaction| { transaction_context.get_key_of_account_at_index(index_in_transaction) }) @@ -902,9 +936,7 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Incorrect buffer authority provided"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context - .is_signer(first_instruction_account.saturating_add(1))? - { + if !instruction_context.is_instruction_account_signer(1)? { ic_logger_msg!(log_collector, "Buffer authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -924,9 +956,7 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Incorrect upgrade authority provided"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context - .is_signer(first_instruction_account.saturating_add(1))? - { + if !instruction_context.is_instruction_account_signer(1)? { ic_logger_msg!(log_collector, "Upgrade authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -945,9 +975,8 @@ fn process_loader_upgradeable_instruction( } UpgradeableLoaderInstruction::Close => { instruction_context.check_number_of_instruction_accounts(2)?; - if instruction_context.get_index_in_transaction(first_instruction_account)? - == instruction_context - .get_index_in_transaction(first_instruction_account.saturating_add(1))? + if instruction_context.get_index_of_instruction_account_in_transaction(0)? + == instruction_context.get_index_of_instruction_account_in_transaction(1)? { ic_logger_msg!( log_collector, @@ -1050,16 +1079,14 @@ fn common_close_account( return Err(InstructionError::Immutable); } if *authority_address - != Some(*instruction_context.get_instruction_account_key(transaction_context, 2)?) + != Some(*transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction(2)?, + )?) { ic_logger_msg!(log_collector, "Incorrect authority provided"); return Err(InstructionError::IncorrectAuthority); } - if !instruction_context.is_signer( - instruction_context - .get_number_of_program_accounts() - .saturating_add(2), - )? { + if !instruction_context.is_instruction_account_signer(2)? { ic_logger_msg!(log_collector, "Authority did not sign"); return Err(InstructionError::MissingRequiredSignature); } @@ -1082,7 +1109,7 @@ fn process_loader_instruction( let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; let program = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; if program.get_owner() != program_id { ic_msg!( @@ -1178,7 +1205,7 @@ impl Executor for BpfExecutor { let stack_height = invoke_context.get_stack_height(); let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let program_id = *instruction_context.get_program_key(transaction_context)?; + let program_id = *instruction_context.get_last_program_key(transaction_context)?; let mut serialize_time = Measure::start("serialize"); let (mut parameter_bytes, account_lengths) = diff --git a/programs/bpf_loader/src/serialization.rs b/programs/bpf_loader/src/serialization.rs index c53b96dd58..6bf9a915d5 100644 --- a/programs/bpf_loader/src/serialization.rs +++ b/programs/bpf_loader/src/serialization.rs @@ -19,7 +19,7 @@ pub fn serialize_parameters( instruction_context: &InstructionContext, ) -> Result<(AlignedMemory, Vec), InstructionError> { let is_loader_deprecated = *instruction_context - .try_borrow_program_account(transaction_context)? + .try_borrow_last_program_account(transaction_context)? .get_owner() == bpf_loader_deprecated::id(); if is_loader_deprecated { @@ -28,11 +28,10 @@ pub fn serialize_parameters( serialize_parameters_aligned(transaction_context, instruction_context) } .and_then(|buffer| { - let account_lengths = (instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts()) - .map(|index_in_instruction| { + let account_lengths = (0..instruction_context.get_number_of_instruction_accounts()) + .map(|instruction_account_index| { Ok(instruction_context - .try_borrow_account(transaction_context, index_in_instruction)? + .try_borrow_instruction_account(transaction_context, instruction_account_index)? .get_data() .len()) }) @@ -48,7 +47,7 @@ pub fn deserialize_parameters( account_lengths: &[usize], ) -> Result<(), InstructionError> { let is_loader_deprecated = *instruction_context - .try_borrow_program_account(transaction_context)? + .try_borrow_last_program_account(transaction_context)? .get_owner() == bpf_loader_deprecated::id(); if is_loader_deprecated { @@ -74,14 +73,13 @@ pub fn serialize_parameters_unaligned( ) -> Result { // Calculate size in order to alloc once let mut size = size_of::(); - for index_in_instruction in instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts() - { - let duplicate = instruction_context.is_duplicate(index_in_instruction)?; + for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() { + let duplicate = + instruction_context.is_instruction_account_duplicate(instruction_account_index)?; size += 1; // dup if duplicate.is_none() { let data_len = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)? + .try_borrow_instruction_account(transaction_context, instruction_account_index)? .get_data() .len(); size += size_of::() // is_signer @@ -102,16 +100,15 @@ pub fn serialize_parameters_unaligned( v.write_u64::(instruction_context.get_number_of_instruction_accounts() as u64) .map_err(|_| InstructionError::InvalidArgument)?; - for index_in_instruction in instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts() - { - let duplicate = instruction_context.is_duplicate(index_in_instruction)?; + for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() { + let duplicate = + instruction_context.is_instruction_account_duplicate(instruction_account_index)?; if let Some(position) = duplicate { v.write_u8(position as u8) .map_err(|_| InstructionError::InvalidArgument)?; } else { let borrowed_account = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)?; + .try_borrow_instruction_account(transaction_context, instruction_account_index)?; v.write_u8(std::u8::MAX) .map_err(|_| InstructionError::InvalidArgument)?; v.write_u8(borrowed_account.is_signer() as u8) @@ -140,7 +137,7 @@ pub fn serialize_parameters_unaligned( .map_err(|_| InstructionError::InvalidArgument)?; v.write_all( instruction_context - .try_borrow_program_account(transaction_context)? + .try_borrow_last_program_account(transaction_context)? .get_key() .as_ref(), ) @@ -155,15 +152,15 @@ pub fn deserialize_parameters_unaligned( account_lengths: &[usize], ) -> Result<(), InstructionError> { let mut start = size_of::(); // number of accounts - for (index_in_instruction, pre_len) in (instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts()) - .zip(account_lengths.iter()) + for (instruction_account_index, pre_len) in + (0..instruction_context.get_number_of_instruction_accounts()).zip(account_lengths.iter()) { - let duplicate = instruction_context.is_duplicate(index_in_instruction)?; + let duplicate = + instruction_context.is_instruction_account_duplicate(instruction_account_index)?; start += 1; // is_dup if duplicate.is_none() { let mut borrowed_account = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)?; + .try_borrow_instruction_account(transaction_context, instruction_account_index)?; start += size_of::(); // is_signer start += size_of::(); // is_writable start += size_of::(); // key @@ -194,16 +191,15 @@ pub fn serialize_parameters_aligned( ) -> Result { // Calculate size in order to alloc once let mut size = size_of::(); - for index_in_instruction in instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts() - { - let duplicate = instruction_context.is_duplicate(index_in_instruction)?; + for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() { + let duplicate = + instruction_context.is_instruction_account_duplicate(instruction_account_index)?; size += 1; // dup if duplicate.is_some() { size += 7; // padding to 64-bit aligned } else { let data_len = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)? + .try_borrow_instruction_account(transaction_context, instruction_account_index)? .get_data() .len(); size += size_of::() // is_signer @@ -228,10 +224,9 @@ pub fn serialize_parameters_aligned( // Serialize into the buffer v.write_u64::(instruction_context.get_number_of_instruction_accounts() as u64) .map_err(|_| InstructionError::InvalidArgument)?; - for index_in_instruction in instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts() - { - let duplicate = instruction_context.is_duplicate(index_in_instruction)?; + for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() { + let duplicate = + instruction_context.is_instruction_account_duplicate(instruction_account_index)?; if let Some(position) = duplicate { v.write_u8(position as u8) .map_err(|_| InstructionError::InvalidArgument)?; @@ -239,7 +234,7 @@ pub fn serialize_parameters_aligned( .map_err(|_| InstructionError::InvalidArgument)?; // 7 bytes of padding to make 64-bit aligned } else { let borrowed_account = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)?; + .try_borrow_instruction_account(transaction_context, instruction_account_index)?; v.write_u8(std::u8::MAX) .map_err(|_| InstructionError::InvalidArgument)?; v.write_u8(borrowed_account.is_signer() as u8) @@ -276,7 +271,7 @@ pub fn serialize_parameters_aligned( .map_err(|_| InstructionError::InvalidArgument)?; v.write_all( instruction_context - .try_borrow_program_account(transaction_context)? + .try_borrow_last_program_account(transaction_context)? .get_key() .as_ref(), ) @@ -291,17 +286,17 @@ pub fn deserialize_parameters_aligned( account_lengths: &[usize], ) -> Result<(), InstructionError> { let mut start = size_of::(); // number of accounts - for (index_in_instruction, pre_len) in (instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts()) - .zip(account_lengths.iter()) + for (instruction_account_index, pre_len) in + (0..instruction_context.get_number_of_instruction_accounts()).zip(account_lengths.iter()) { - let duplicate = instruction_context.is_duplicate(index_in_instruction)?; + let duplicate = + instruction_context.is_instruction_account_duplicate(instruction_account_index)?; start += size_of::(); // position if duplicate.is_some() { start += 7; // padding to 64-bit aligned } else { let mut borrowed_account = instruction_context - .try_borrow_account(transaction_context, index_in_instruction)?; + .try_borrow_instruction_account(transaction_context, instruction_account_index)?; start += size_of::() // is_signer + size_of::() // is_writable + size_of::() // executable @@ -442,11 +437,13 @@ mod tests { let instruction_accounts = [1, 1, 2, 3, 4, 4, 5, 6] .into_iter() .enumerate() - .map(|(index_in_instruction, index_in_transaction)| AccountMeta { - pubkey: transaction_accounts.get(index_in_transaction).unwrap().0, - is_signer: false, - is_writable: index_in_instruction >= 4, - }) + .map( + |(instruction_account_index, index_in_transaction)| AccountMeta { + pubkey: transaction_accounts.get(index_in_transaction).unwrap().0, + is_signer: false, + is_writable: instruction_account_index >= 4, + }, + ) .collect(); let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; let program_indices = [0]; @@ -552,7 +549,7 @@ mod tests { .transaction_context .get_current_instruction_context() .unwrap() - .try_borrow_account(invoke_context.transaction_context, 0) + .try_borrow_program_account(invoke_context.transaction_context, 0) .unwrap() .set_owner(bpf_loader_deprecated::id().as_ref()); diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index a0c1d48bb6..06536c36df 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -369,7 +369,8 @@ pub fn bind_syscall_context_objects<'a, 'b>( .transaction_context .get_current_instruction_context() .and_then(|instruction_context| { - instruction_context.try_borrow_program_account(invoke_context.transaction_context) + instruction_context + .try_borrow_last_program_account(invoke_context.transaction_context) }) .map(|program_account| *program_account.get_owner()) .map_err(SyscallError::InstructionError)?; @@ -2946,8 +2947,9 @@ where ))?; accounts.push((*program_account_index, None)); - for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() { - if index_in_instruction != instruction_account.index_in_callee { + for (instruction_account_index, instruction_account) in instruction_accounts.iter().enumerate() + { + if instruction_account_index != instruction_account.index_in_callee { continue; // Skip duplicate account } let mut callee_account = instruction_context @@ -3121,7 +3123,7 @@ fn call<'a, 'b: 'a>( .get_current_instruction_context() .map_err(SyscallError::InstructionError)?; let caller_program_id = instruction_context - .get_program_key(transaction_context) + .get_last_program_key(transaction_context) .map_err(SyscallError::InstructionError)?; let signers = syscall.translate_signers( caller_program_id, @@ -3288,9 +3290,8 @@ declare_syscall!( let program_id = *question_mark!( transaction_context .get_current_instruction_context() - .and_then( - |instruction_context| instruction_context.get_program_key(transaction_context) - ) + .and_then(|instruction_context| instruction_context + .get_last_program_key(transaction_context)) .map_err(SyscallError::InstructionError), result ); @@ -3570,19 +3571,26 @@ declare_syscall!( result ); - *program_id = - instruction_context.get_program_id(invoke_context.transaction_context); + *program_id = *question_mark!( + instruction_context + .get_last_program_key(invoke_context.transaction_context) + .map_err(SyscallError::InstructionError), + result + ); data.clone_from_slice(instruction_context.get_instruction_data()); let account_metas = question_mark!( - (instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts()) - .map(|index_in_instruction| Ok(AccountMeta { + (0..instruction_context.get_number_of_instruction_accounts()) + .map(|instruction_account_index| Ok(AccountMeta { pubkey: *invoke_context.get_key_of_account_at_index( instruction_context - .get_index_in_transaction(index_in_instruction)? + .get_index_of_instruction_account_in_transaction( + instruction_account_index + )? )?, - is_signer: instruction_context.is_signer(index_in_instruction)?, - is_writable: instruction_context.is_writable(index_in_instruction)?, + is_signer: instruction_context + .is_instruction_account_signer(instruction_account_index)?, + is_writable: instruction_context + .is_instruction_account_writable(instruction_account_index)?, })) .collect::, InstructionError>>() .map_err(SyscallError::InstructionError), diff --git a/programs/config/src/config_processor.rs b/programs/config/src/config_processor.rs index 6387acc7c4..1acdeab938 100644 --- a/programs/config/src/config_processor.rs +++ b/programs/config/src/config_processor.rs @@ -20,11 +20,9 @@ pub fn process_instruction( let data = instruction_context.get_instruction_data(); let key_list: ConfigKeys = limited_deserialize(data)?; - let config_account_key = - transaction_context - .get_key_of_account_at_index(instruction_context.get_index_in_transaction( - instruction_context.get_number_of_program_accounts(), - )?)?; + let config_account_key = transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction(0)?, + )?; let config_account = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let is_config_account_signer = config_account.is_signer(); diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 684c19358d..ab1cb34efa 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -28,17 +28,23 @@ use { fn get_optional_pubkey<'a>( transaction_context: &'a TransactionContext, instruction_context: &'a InstructionContext, - index_in_instruction: usize, + instruction_account_index: usize, should_be_signer: bool, ) -> Result, InstructionError> { Ok( - if instruction_context.get_number_of_accounts() > index_in_instruction { - if should_be_signer && !instruction_context.is_signer(index_in_instruction)? { + if instruction_account_index < instruction_context.get_number_of_instruction_accounts() { + if should_be_signer + && !instruction_context.is_instruction_account_signer(instruction_account_index)? + { return Err(InstructionError::MissingRequiredSignature); } - Some(transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(index_in_instruction)?, - )?) + Some( + transaction_context.get_key_of_account_at_index( + instruction_context.get_index_of_instruction_account_in_transaction( + instruction_account_index, + )?, + )?, + ) } else { None }, @@ -46,7 +52,7 @@ fn get_optional_pubkey<'a>( } pub fn process_instruction( - first_instruction_account: usize, + _first_instruction_account: usize, invoke_context: &mut InvokeContext, ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; @@ -86,12 +92,8 @@ pub fn process_instruction( let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?; instruction_context.check_number_of_instruction_accounts(3)?; - let custodian_pubkey = get_optional_pubkey( - transaction_context, - instruction_context, - first_instruction_account + 3, - false, - )?; + let custodian_pubkey = + get_optional_pubkey(transaction_context, instruction_context, 3, false)?; authorize( &mut me, @@ -123,18 +125,14 @@ pub fn process_instruction( if require_custodian_for_locked_stake_authorize { let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 2)?; - let custodian_pubkey = get_optional_pubkey( - transaction_context, - instruction_context, - first_instruction_account + 3, - false, - )?; + let custodian_pubkey = + get_optional_pubkey(transaction_context, instruction_context, 3, false)?; authorize_with_seed( transaction_context, instruction_context, &mut me, - first_instruction_account + 1, + 1, &args.authority_seed, &args.authority_owner, &args.new_authorized_pubkey, @@ -148,7 +146,7 @@ pub fn process_instruction( transaction_context, instruction_context, &mut me, - first_instruction_account + 1, + 1, &args.authority_seed, &args.authority_owner, &args.new_authorized_pubkey, @@ -181,8 +179,8 @@ pub fn process_instruction( delegate( transaction_context, instruction_context, - first_instruction_account, - first_instruction_account + 1, + 0, + 1, &clock, &stake_history, &config, @@ -198,9 +196,9 @@ pub fn process_instruction( invoke_context, transaction_context, instruction_context, - first_instruction_account, + 0, lamports, - first_instruction_account + 1, + 1, &signers, ) } @@ -219,8 +217,8 @@ pub fn process_instruction( invoke_context, transaction_context, instruction_context, - first_instruction_account, - first_instruction_account + 1, + 0, + 1, &clock, &stake_history, &signers, @@ -241,14 +239,14 @@ pub fn process_instruction( withdraw( transaction_context, instruction_context, - first_instruction_account, + 0, lamports, - first_instruction_account + 1, + 1, &clock, &stake_history, - first_instruction_account + 4, + 4, if instruction_context.get_number_of_instruction_accounts() >= 6 { - Some(first_instruction_account + 5) + Some(5) } else { None }, @@ -274,12 +272,12 @@ pub fn process_instruction( { instruction_context.check_number_of_instruction_accounts(4)?; let staker_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 2)?, + instruction_context.get_index_of_instruction_account_in_transaction(2)?, )?; let withdrawer_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 3)?, + instruction_context.get_index_of_instruction_account_in_transaction(3)?, )?; - if !instruction_context.is_signer(first_instruction_account + 3)? { + if !instruction_context.is_instruction_account_signer(3)? { return Err(InstructionError::MissingRequiredSignature); } @@ -311,17 +309,13 @@ pub fn process_instruction( get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?; instruction_context.check_number_of_instruction_accounts(4)?; let authorized_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 3)?, + instruction_context.get_index_of_instruction_account_in_transaction(3)?, )?; - if !instruction_context.is_signer(first_instruction_account + 3)? { + if !instruction_context.is_instruction_account_signer(3)? { return Err(InstructionError::MissingRequiredSignature); } - let custodian_pubkey = get_optional_pubkey( - transaction_context, - instruction_context, - first_instruction_account + 4, - false, - )?; + let custodian_pubkey = + get_optional_pubkey(transaction_context, instruction_context, 4, false)?; authorize( &mut me, @@ -347,23 +341,19 @@ pub fn process_instruction( get_sysvar_with_account_check::clock(invoke_context, instruction_context, 2)?; instruction_context.check_number_of_instruction_accounts(4)?; let authorized_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 3)?, + instruction_context.get_index_of_instruction_account_in_transaction(3)?, )?; - if !instruction_context.is_signer(first_instruction_account + 3)? { + if !instruction_context.is_instruction_account_signer(3)? { return Err(InstructionError::MissingRequiredSignature); } - let custodian_pubkey = get_optional_pubkey( - transaction_context, - instruction_context, - first_instruction_account + 4, - false, - )?; + let custodian_pubkey = + get_optional_pubkey(transaction_context, instruction_context, 4, false)?; authorize_with_seed( transaction_context, instruction_context, &mut me, - first_instruction_account + 1, + 1, &args.authority_seed, &args.authority_owner, authorized_pubkey, @@ -382,12 +372,8 @@ pub fn process_instruction( .feature_set .is_active(&feature_set::vote_stake_checked_instructions::id()) { - let custodian_pubkey = get_optional_pubkey( - transaction_context, - instruction_context, - first_instruction_account + 2, - true, - )?; + let custodian_pubkey = + get_optional_pubkey(transaction_context, instruction_context, 2, true)?; let lockup = LockupArgs { unix_timestamp: lockup_checked.unix_timestamp, @@ -430,8 +416,8 @@ pub fn process_instruction( transaction_context, instruction_context, &mut me, - first_instruction_account + 1, - first_instruction_account + 2, + 1, + 2, clock.epoch, ) } else { diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 8bf1eaccf6..539dc83152 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -534,9 +534,10 @@ pub fn authorize_with_seed( custodian: Option<&Pubkey>, ) -> Result<(), InstructionError> { let mut signers = HashSet::default(); - if instruction_context.is_signer(authority_base_index)? { + if instruction_context.is_instruction_account_signer(authority_base_index)? { let base_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(authority_base_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(authority_base_index)?, )?; signers.insert(Pubkey::create_with_seed( base_pubkey, @@ -566,8 +567,8 @@ pub fn delegate( signers: &HashSet, feature_set: &FeatureSet, ) -> Result<(), InstructionError> { - let vote_account = - instruction_context.try_borrow_account(transaction_context, vote_account_index)?; + let vote_account = instruction_context + .try_borrow_instruction_account(transaction_context, vote_account_index)?; if *vote_account.get_owner() != solana_vote_program::id() { return Err(InstructionError::IncorrectProgramId); } @@ -575,8 +576,8 @@ pub fn delegate( let vote_state = vote_account.get_state::(); drop(vote_account); - let mut stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let mut stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; match stake_account.get_state()? { StakeState::Initialized(meta) => { meta.authorized.check(signers, StakeAuthorize::Staker)?; @@ -653,7 +654,8 @@ pub fn split( split_index: usize, signers: &HashSet, ) -> Result<(), InstructionError> { - let split = instruction_context.try_borrow_account(transaction_context, split_index)?; + let split = + instruction_context.try_borrow_instruction_account(transaction_context, split_index)?; if *split.get_owner() != id() { return Err(InstructionError::IncorrectProgramId); } @@ -665,8 +667,8 @@ pub fn split( } let split_lamport_balance = split.get_lamports(); drop(split); - let stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; if lamports > stake_account.get_lamports() { return Err(InstructionError::InsufficientFunds); } @@ -724,12 +726,12 @@ pub fn split( let mut split_meta = meta; split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve; - let mut stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let mut stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; stake_account.set_state(&StakeState::Stake(meta, stake))?; drop(stake_account); - let mut split = - instruction_context.try_borrow_account(transaction_context, split_index)?; + let mut split = instruction_context + .try_borrow_instruction_account(transaction_context, split_index)?; split.set_state(&StakeState::Stake(split_meta, split_stake))?; } StakeState::Initialized(meta) => { @@ -755,13 +757,14 @@ pub fn split( )?; let mut split_meta = meta; split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve; - let mut split = - instruction_context.try_borrow_account(transaction_context, split_index)?; + let mut split = instruction_context + .try_borrow_instruction_account(transaction_context, split_index)?; split.set_state(&StakeState::Initialized(split_meta))?; } StakeState::Uninitialized => { let stake_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(stake_account_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(stake_account_index)?, )?; if !signers.contains(stake_pubkey) { return Err(InstructionError::MissingRequiredSignature); @@ -771,18 +774,19 @@ pub fn split( } // Deinitialize state upon zero balance - let mut stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let mut stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; if lamports == stake_account.get_lamports() { stake_account.set_state(&StakeState::Uninitialized)?; } drop(stake_account); - let mut split = instruction_context.try_borrow_account(transaction_context, split_index)?; + let mut split = + instruction_context.try_borrow_instruction_account(transaction_context, split_index)?; split.checked_add_lamports(lamports)?; drop(split); - let mut stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let mut stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; stake_account.checked_sub_lamports(lamports)?; Ok(()) } @@ -797,20 +801,21 @@ pub fn merge( stake_history: &StakeHistory, signers: &HashSet, ) -> Result<(), InstructionError> { - let mut source_account = - instruction_context.try_borrow_account(transaction_context, source_account_index)?; + let mut source_account = instruction_context + .try_borrow_instruction_account(transaction_context, source_account_index)?; // Ensure source isn't spoofed if *source_account.get_owner() != id() { return Err(InstructionError::IncorrectProgramId); } // Close the stake_account-reference loophole - if instruction_context.get_index_in_transaction(stake_account_index)? - == instruction_context.get_index_in_transaction(source_account_index)? + if instruction_context.get_index_of_instruction_account_in_transaction(stake_account_index)? + == instruction_context + .get_index_of_instruction_account_in_transaction(source_account_index)? { return Err(InstructionError::InvalidArgument); } - let mut stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let mut stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; ic_msg!(invoke_context, "Checking if destination stake is mergeable"); let stake_merge_kind = MergeKind::get_if_mergeable( @@ -865,16 +870,17 @@ pub fn withdraw( feature_set: &FeatureSet, ) -> Result<(), InstructionError> { let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(withdraw_authority_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(withdraw_authority_index)?, )?; - if !instruction_context.is_signer(withdraw_authority_index)? { + if !instruction_context.is_instruction_account_signer(withdraw_authority_index)? { return Err(InstructionError::MissingRequiredSignature); } let mut signers = HashSet::new(); signers.insert(*withdraw_authority_pubkey); - let mut stake_account = - instruction_context.try_borrow_account(transaction_context, stake_account_index)?; + let mut stake_account = instruction_context + .try_borrow_instruction_account(transaction_context, stake_account_index)?; let (lockup, reserve, is_staked) = match stake_account.get_state()? { StakeState::Stake(meta, stake) => { meta.authorized @@ -919,10 +925,13 @@ pub fn withdraw( // verify that lockup has expired or that the withdrawal is signed by // the custodian, both epoch and unix_timestamp must have passed let custodian_pubkey = if let Some(custodian_index) = custodian_index { - if instruction_context.is_signer(custodian_index)? { - Some(transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(custodian_index)?, - )?) + if instruction_context.is_instruction_account_signer(custodian_index)? { + Some( + transaction_context.get_key_of_account_at_index( + instruction_context + .get_index_of_instruction_account_in_transaction(custodian_index)?, + )?, + ) } else { None } @@ -955,7 +964,8 @@ pub fn withdraw( stake_account.checked_sub_lamports(lamports)?; drop(stake_account); - let mut to = instruction_context.try_borrow_account(transaction_context, to_index)?; + let mut to = + instruction_context.try_borrow_instruction_account(transaction_context, to_index)?; to.checked_add_lamports(lamports)?; Ok(()) } @@ -969,10 +979,11 @@ pub(crate) fn deactivate_delinquent( current_epoch: Epoch, ) -> Result<(), InstructionError> { let delinquent_vote_account_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(delinquent_vote_account_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(delinquent_vote_account_index)?, )?; let delinquent_vote_account = instruction_context - .try_borrow_account(transaction_context, delinquent_vote_account_index)?; + .try_borrow_instruction_account(transaction_context, delinquent_vote_account_index)?; if *delinquent_vote_account.get_owner() != solana_vote_program::id() { return Err(InstructionError::IncorrectProgramId); } @@ -981,7 +992,7 @@ pub(crate) fn deactivate_delinquent( .convert_to_current(); let reference_vote_account = instruction_context - .try_borrow_account(transaction_context, reference_vote_account_index)?; + .try_borrow_instruction_account(transaction_context, reference_vote_account_index)?; if *reference_vote_account.get_owner() != solana_vote_program::id() { return Err(InstructionError::IncorrectProgramId); } @@ -1062,13 +1073,13 @@ fn validate_split_amount( source_stake: Option<&Stake>, additional_required_lamports: u64, ) -> Result { - let source_account = - instruction_context.try_borrow_account(transaction_context, source_account_index)?; + let source_account = instruction_context + .try_borrow_instruction_account(transaction_context, source_account_index)?; let source_lamports = source_account.get_lamports(); let source_data_len = source_account.get_data().len(); drop(source_account); - let destination_account = - instruction_context.try_borrow_account(transaction_context, destination_account_index)?; + let destination_account = instruction_context + .try_borrow_instruction_account(transaction_context, destination_account_index)?; let destination_lamports = destination_account.get_lamports(); let destination_data_len = destination_account.get_data().len(); drop(destination_account); diff --git a/programs/vote/benches/process_vote.rs b/programs/vote/benches/process_vote.rs index 9c25216a63..f939c6c26f 100644 --- a/programs/vote/benches/process_vote.rs +++ b/programs/vote/benches/process_vote.rs @@ -81,10 +81,10 @@ fn create_accounts() -> ( (authority_pubkey, AccountSharedData::default()), ]; let mut instruction_accounts = (0..4) - .map(|index_in_instruction| InstructionAccount { - index_in_transaction: 1usize.saturating_add(index_in_instruction), - index_in_caller: index_in_instruction, - index_in_callee: index_in_instruction, + .map(|index_in_callee| InstructionAccount { + index_in_transaction: 1usize.saturating_add(index_in_callee), + index_in_caller: index_in_callee, + index_in_callee, is_signer: false, is_writable: false, }) diff --git a/programs/vote/src/vote_processor.rs b/programs/vote/src/vote_processor.rs index 437587d119..e5787027a6 100644 --- a/programs/vote/src/vote_processor.rs +++ b/programs/vote/src/vote_processor.rs @@ -24,7 +24,6 @@ fn process_authorize_with_seed_instruction( invoke_context: &InvokeContext, instruction_context: &InstructionContext, transaction_context: &TransactionContext, - first_instruction_account: usize, vote_account: &mut BorrowedAccount, new_authority: &Pubkey, authorization_type: VoteAuthorize, @@ -39,10 +38,9 @@ fn process_authorize_with_seed_instruction( } let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?; let mut expected_authority_keys: HashSet = HashSet::default(); - let authority_base_key_index = first_instruction_account + 2; - if instruction_context.is_signer(authority_base_key_index)? { + if instruction_context.is_instruction_account_signer(2)? { let base_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(authority_base_key_index)?, + instruction_context.get_index_of_instruction_account_in_transaction(2)?, )?; expected_authority_keys.insert(Pubkey::create_with_seed( base_pubkey, @@ -61,7 +59,7 @@ fn process_authorize_with_seed_instruction( } pub fn process_instruction( - first_instruction_account: usize, + _first_instruction_account: usize, invoke_context: &mut InvokeContext, ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; @@ -70,8 +68,7 @@ pub fn process_instruction( trace!("process_instruction: {:?}", data); - let mut me = - instruction_context.try_borrow_account(transaction_context, first_instruction_account)?; + let mut me = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; if *me.get_owner() != id() { return Err(InstructionError::InvalidAccountOwner); } @@ -105,7 +102,6 @@ pub fn process_instruction( invoke_context, instruction_context, transaction_context, - first_instruction_account, &mut me, &args.new_authority, args.authorization_type, @@ -115,18 +111,16 @@ pub fn process_instruction( } VoteInstruction::AuthorizeCheckedWithSeed(args) => { instruction_context.check_number_of_instruction_accounts(4)?; - let new_authority_index = first_instruction_account + 3; let new_authority = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(new_authority_index)?, + instruction_context.get_index_of_instruction_account_in_transaction(3)?, )?; - if !instruction_context.is_signer(new_authority_index)? { + if !instruction_context.is_instruction_account_signer(3)? { return Err(InstructionError::MissingRequiredSignature); } process_authorize_with_seed_instruction( invoke_context, instruction_context, transaction_context, - first_instruction_account, &mut me, new_authority, args.authorization_type, @@ -137,7 +131,7 @@ pub fn process_instruction( VoteInstruction::UpdateValidatorIdentity => { instruction_context.check_number_of_instruction_accounts(2)?; let node_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 1)?, + instruction_context.get_index_of_instruction_account_in_transaction(1)?, )?; vote_state::update_validator_identity(&mut me, node_pubkey, &signers) } @@ -203,9 +197,9 @@ pub fn process_instruction( vote_state::withdraw( transaction_context, instruction_context, - first_instruction_account, + 0, lamports, - first_instruction_account + 1, + 1, &signers, rent_sysvar.as_deref(), clock_if_feature_active.as_deref(), @@ -218,9 +212,9 @@ pub fn process_instruction( { instruction_context.check_number_of_instruction_accounts(4)?; let voter_pubkey = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 3)?, + instruction_context.get_index_of_instruction_account_in_transaction(3)?, )?; - if !instruction_context.is_signer(first_instruction_account + 3)? { + if !instruction_context.is_instruction_account_signer(3)? { return Err(InstructionError::MissingRequiredSignature); } let clock = diff --git a/programs/vote/src/vote_state/mod.rs b/programs/vote/src/vote_state/mod.rs index 7907435180..4da8e4841f 100644 --- a/programs/vote/src/vote_state/mod.rs +++ b/programs/vote/src/vote_state/mod.rs @@ -1309,8 +1309,8 @@ pub fn withdraw( rent_sysvar: Option<&Rent>, clock: Option<&Clock>, ) -> Result<(), InstructionError> { - let mut vote_account = - instruction_context.try_borrow_account(transaction_context, vote_account_index)?; + let mut vote_account = instruction_context + .try_borrow_instruction_account(transaction_context, vote_account_index)?; let vote_state: VoteState = vote_account .get_state::()? .convert_to_current(); @@ -1351,8 +1351,8 @@ pub fn withdraw( vote_account.checked_sub_lamports(lamports)?; drop(vote_account); - let mut to_account = - instruction_context.try_borrow_account(transaction_context, to_account_index)?; + let mut to_account = instruction_context + .try_borrow_instruction_account(transaction_context, to_account_index)?; to_account.checked_add_lamports(lamports)?; Ok(()) } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index ebbedcb865..79e448395d 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -770,13 +770,20 @@ pub fn inner_instructions_list_from_instruction_trace( .skip(1) .map(|instruction_context| { CompiledInstruction::new_from_raw_parts( - instruction_context.get_program_id_index() as u8, - instruction_context.get_instruction_data().to_vec(), - (instruction_context.get_number_of_program_accounts() - ..instruction_context.get_number_of_accounts()) - .map(|index_in_instruction| { + instruction_context + .get_index_of_program_account_in_transaction( instruction_context - .get_index_in_transaction(index_in_instruction) + .get_number_of_program_accounts() + .saturating_sub(1), + ) + .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(), @@ -12207,7 +12214,7 @@ pub(crate) mod tests { ) -> std::result::Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; - let program_id = instruction_context.get_program_key(transaction_context)?; + let program_id = instruction_context.get_last_program_key(transaction_context)?; if mock_vote_program_id() != *program_id { return Err(InstructionError::IncorrectProgramId); } @@ -14108,7 +14115,7 @@ pub(crate) mod tests { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let _ = instruction_context - .try_borrow_account(transaction_context, 1)? + .try_borrow_program_account(transaction_context, 1)? .checked_add_lamports(1); Ok(()) } diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 5fc179936f..d3e760de28 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -120,16 +120,16 @@ impl MessageProcessor { } let mut instruction_accounts = Vec::with_capacity(instruction.accounts.len()); - for (index_in_instruction, index_in_transaction) in + for (instruction_account_index, index_in_transaction) in instruction.accounts.iter().enumerate() { let index_in_callee = instruction .accounts - .get(0..index_in_instruction) + .get(0..instruction_account_index) .ok_or(TransactionError::InvalidAccountIndex)? .iter() .position(|account_index| account_index == index_in_transaction) - .unwrap_or(index_in_instruction); + .unwrap_or(instruction_account_index); let index_in_transaction = *index_in_transaction as usize; instruction_accounts.push(InstructionAccount { index_in_transaction, diff --git a/runtime/src/nonce_keyed_account.rs b/runtime/src/nonce_keyed_account.rs index 9a62ae4e2a..e7ab6965bf 100644 --- a/runtime/src/nonce_keyed_account.rs +++ b/runtime/src/nonce_keyed_account.rs @@ -104,8 +104,8 @@ pub fn withdraw_nonce_account( transaction_context: &TransactionContext, instruction_context: &InstructionContext, ) -> Result<(), InstructionError> { - let mut from = - instruction_context.try_borrow_account(transaction_context, from_account_index)?; + let mut from = instruction_context + .try_borrow_instruction_account(transaction_context, from_account_index)?; let merge_nonce_error_into_system_error = invoke_context .feature_set .is_active(&feature_set::merge_nonce_error_into_system_error::id()); @@ -180,7 +180,8 @@ pub fn withdraw_nonce_account( from.checked_sub_lamports(lamports) .map_err(|_| InstructionError::ArithmeticOverflow)?; drop(from); - let mut to = instruction_context.try_borrow_account(transaction_context, to_account_index)?; + let mut to = instruction_context + .try_borrow_instruction_account(transaction_context, to_account_index)?; to.checked_add_lamports(lamports) .map_err(|_| InstructionError::ArithmeticOverflow)?; @@ -450,9 +451,9 @@ mod test { drop(nonce_account); drop(to_account); withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -621,9 +622,9 @@ mod test { drop(nonce_account); drop(to_account); withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -666,9 +667,9 @@ mod test { drop(nonce_account); drop(to_account); let result = withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -698,9 +699,9 @@ mod test { let withdraw_lamports = nonce_account.get_lamports() + 1; drop(nonce_account); let result = withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -734,9 +735,9 @@ mod test { drop(nonce_account); drop(to_account); withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -760,9 +761,9 @@ mod test { drop(nonce_account); drop(to_account); withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -815,9 +816,9 @@ mod test { drop(nonce_account); drop(to_account); withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -847,9 +848,9 @@ mod test { drop(nonce_account); drop(to_account); withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -893,9 +894,9 @@ mod test { drop(nonce_account); drop(to_account); let result = withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -926,9 +927,9 @@ mod test { let withdraw_lamports = nonce_account.get_lamports() + 1; drop(nonce_account); let result = withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -959,9 +960,9 @@ mod test { let withdraw_lamports = 42 + 1; drop(nonce_account); let result = withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, @@ -992,9 +993,9 @@ mod test { let withdraw_lamports = u64::MAX - 54; drop(nonce_account); let result = withdraw_nonce_account( - 1 + NONCE_ACCOUNT_INDEX, + NONCE_ACCOUNT_INDEX, withdraw_lamports, - 1 + WITHDRAW_TO_ACCOUNT_INDEX, + WITHDRAW_TO_ACCOUNT_INDEX, &rent, &signers, &invoke_context, diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index 226fda10ef..8e4f753145 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -158,8 +158,8 @@ fn create_account( ) -> Result<(), InstructionError> { // if it looks like the `to` account is already in use, bail { - let mut to = - instruction_context.try_borrow_account(transaction_context, to_account_index)?; + let mut to = instruction_context + .try_borrow_instruction_account(transaction_context, to_account_index)?; if to.get_lamports() > 0 { ic_msg!( invoke_context, @@ -189,8 +189,8 @@ fn transfer_verified( transaction_context: &TransactionContext, instruction_context: &InstructionContext, ) -> Result<(), InstructionError> { - let mut from = - instruction_context.try_borrow_account(transaction_context, from_account_index)?; + let mut from = instruction_context + .try_borrow_instruction_account(transaction_context, from_account_index)?; if !from.get_data().is_empty() { ic_msg!(invoke_context, "Transfer: `from` must not carry data"); return Err(InstructionError::InvalidArgument); @@ -207,7 +207,8 @@ fn transfer_verified( from.checked_sub_lamports(lamports)?; drop(from); - let mut to = instruction_context.try_borrow_account(transaction_context, to_account_index)?; + let mut to = instruction_context + .try_borrow_instruction_account(transaction_context, to_account_index)?; to.checked_add_lamports(lamports)?; Ok(()) } @@ -228,12 +229,13 @@ fn transfer( return Ok(()); } - if !instruction_context.is_signer(from_account_index)? { + if !instruction_context.is_instruction_account_signer(from_account_index)? { ic_msg!( invoke_context, "Transfer: `from` account {} must sign", transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(from_account_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(from_account_index)?, )?, ); return Err(InstructionError::MissingRequiredSignature); @@ -268,26 +270,28 @@ fn transfer_with_seed( return Ok(()); } - if !instruction_context.is_signer(from_base_account_index)? { + if !instruction_context.is_instruction_account_signer(from_base_account_index)? { ic_msg!( invoke_context, "Transfer: 'from' account {:?} must sign", transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(from_base_account_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(from_base_account_index)?, )?, ); return Err(InstructionError::MissingRequiredSignature); } let address_from_seed = Pubkey::create_with_seed( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(from_base_account_index)?, + instruction_context + .get_index_of_instruction_account_in_transaction(from_base_account_index)?, )?, from_seed, from_owner, )?; let from_key = transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(from_account_index)?, + instruction_context.get_index_of_instruction_account_in_transaction(from_account_index)?, )?; if *from_key != address_from_seed { ic_msg!( @@ -310,7 +314,7 @@ fn transfer_with_seed( } pub fn process_instruction( - first_instruction_account: usize, + _first_instruction_account: usize, invoke_context: &mut InvokeContext, ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; @@ -330,14 +334,14 @@ pub fn process_instruction( instruction_context.check_number_of_instruction_accounts(2)?; let to_address = Address::create( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 1)?, + instruction_context.get_index_of_instruction_account_in_transaction(1)?, )?, None, invoke_context, )?; create_account( - first_instruction_account, - first_instruction_account + 1, + 0, + 1, &to_address, lamports, space, @@ -358,14 +362,14 @@ pub fn process_instruction( instruction_context.check_number_of_instruction_accounts(2)?; let to_address = Address::create( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account + 1)?, + instruction_context.get_index_of_instruction_account_in_transaction(1)?, )?, Some((&base, &seed, &owner)), invoke_context, )?; create_account( - first_instruction_account, - first_instruction_account + 1, + 0, + 1, &to_address, lamports, space, @@ -378,11 +382,11 @@ pub fn process_instruction( } SystemInstruction::Assign { owner } => { instruction_context.check_number_of_instruction_accounts(1)?; - let mut account = instruction_context - .try_borrow_account(transaction_context, first_instruction_account)?; + let mut account = + instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let address = Address::create( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + instruction_context.get_index_of_instruction_account_in_transaction(0)?, )?, None, invoke_context, @@ -392,8 +396,8 @@ pub fn process_instruction( SystemInstruction::Transfer { lamports } => { instruction_context.check_number_of_instruction_accounts(2)?; transfer( - first_instruction_account, - first_instruction_account + 1, + 0, + 1, lamports, invoke_context, transaction_context, @@ -407,11 +411,11 @@ pub fn process_instruction( } => { instruction_context.check_number_of_instruction_accounts(3)?; transfer_with_seed( - first_instruction_account, - first_instruction_account + 1, + 0, + 1, &from_seed, &from_owner, - first_instruction_account + 2, + 2, lamports, invoke_context, transaction_context, @@ -447,9 +451,9 @@ pub fn process_instruction( )?; let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 3)?; withdraw_nonce_account( - first_instruction_account, + 0, lamports, - first_instruction_account + 1, + 1, &rent, &signers, invoke_context, @@ -507,11 +511,11 @@ pub fn process_instruction( } SystemInstruction::Allocate { space } => { instruction_context.check_number_of_instruction_accounts(1)?; - let mut account = instruction_context - .try_borrow_account(transaction_context, first_instruction_account)?; + let mut account = + instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let address = Address::create( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + instruction_context.get_index_of_instruction_account_in_transaction(0)?, )?, None, invoke_context, @@ -525,11 +529,11 @@ pub fn process_instruction( owner, } => { instruction_context.check_number_of_instruction_accounts(1)?; - let mut account = instruction_context - .try_borrow_account(transaction_context, first_instruction_account)?; + let mut account = + instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let address = Address::create( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + instruction_context.get_index_of_instruction_account_in_transaction(0)?, )?, Some((&base, &seed, &owner)), invoke_context, @@ -545,11 +549,11 @@ pub fn process_instruction( } SystemInstruction::AssignWithSeed { base, seed, owner } => { instruction_context.check_number_of_instruction_accounts(1)?; - let mut account = instruction_context - .try_borrow_account(transaction_context, first_instruction_account)?; + let mut account = + instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let address = Address::create( transaction_context.get_key_of_account_at_index( - instruction_context.get_index_in_transaction(first_instruction_account)?, + instruction_context.get_index_of_instruction_account_in_transaction(0)?, )?, Some((&base, &seed, &owner)), invoke_context, diff --git a/sdk/src/transaction_context.rs b/sdk/src/transaction_context.rs index d238cf5f2d..0abfa29529 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/src/transaction_context.rs @@ -301,16 +301,6 @@ impl InstructionContext { self.program_accounts.len() } - /// Get the index of the instruction's program id - pub fn get_program_id_index(&self) -> usize { - self.program_accounts.last().cloned().unwrap_or_default() - } - - /// Get the instruction's program id - pub fn get_program_id(&self, transaction_context: &TransactionContext) -> Pubkey { - transaction_context.account_keys[self.program_accounts.last().cloned().unwrap_or_default()] - } - /// Number of accounts in this Instruction (without program accounts) pub fn get_number_of_instruction_accounts(&self) -> usize { self.instruction_accounts.len() @@ -328,13 +318,6 @@ impl InstructionContext { } } - /// Number of accounts in this Instruction - pub fn get_number_of_accounts(&self) -> usize { - self.program_accounts - .len() - .saturating_add(self.instruction_accounts.len()) - } - /// Data parameter for the programs `process_instruction` handler pub fn get_instruction_data(&self) -> &[u8] { &self.instruction_data @@ -353,8 +336,8 @@ impl InstructionContext { }) } - /// Searches for an account by its key - pub fn find_index_of_account( + /// Searches for an instruction account by its key + pub fn find_index_of_instruction_account( &self, transaction_context: &TransactionContext, pubkey: &Pubkey, @@ -365,82 +348,75 @@ impl InstructionContext { &transaction_context.account_keys[instruction_account.index_in_transaction] == pubkey }) - .map(|index| index.saturating_add(self.program_accounts.len())) } - /// Translates the given instruction wide index into a transaction wide index - pub fn get_index_in_transaction( + /// Translates the given instruction wide program_account_index into a transaction wide index + pub fn get_index_of_program_account_in_transaction( &self, - index_in_instruction: usize, + program_account_index: usize, ) -> Result { - if index_in_instruction < self.program_accounts.len() { - Ok(self.program_accounts[index_in_instruction]) - } else if index_in_instruction < self.get_number_of_accounts() { - Ok(self.instruction_accounts - [index_in_instruction.saturating_sub(self.program_accounts.len())] - .index_in_transaction) - } else { - Err(InstructionError::NotEnoughAccountKeys) - } + Ok(*self + .program_accounts + .get(program_account_index) + .ok_or(InstructionError::NotEnoughAccountKeys)?) } - /// Returns `Some(index_in_instruction)` if this is a duplicate - /// and `None` if it is the first account with this key - pub fn is_duplicate( + /// Translates the given instruction wide instruction_account_index into a transaction wide index + pub fn get_index_of_instruction_account_in_transaction( &self, - index_in_instruction: usize, + instruction_account_index: usize, + ) -> Result { + Ok(self + .instruction_accounts + .get(instruction_account_index) + .ok_or(InstructionError::NotEnoughAccountKeys)? + .index_in_transaction) + } + + /// Returns `Some(instruction_account_index)` if this is a duplicate + /// and `None` if it is the first account with this key + pub fn is_instruction_account_duplicate( + &self, + instruction_account_index: usize, ) -> Result, InstructionError> { - if index_in_instruction < self.program_accounts.len() - || index_in_instruction >= self.get_number_of_accounts() - { - Err(InstructionError::NotEnoughAccountKeys) + let index_in_callee = self + .instruction_accounts + .get(instruction_account_index) + .ok_or(InstructionError::NotEnoughAccountKeys)? + .index_in_callee; + Ok(if index_in_callee == instruction_account_index { + None } else { - let index_in_instruction = - index_in_instruction.saturating_sub(self.program_accounts.len()); - let index_in_callee = self.instruction_accounts[index_in_instruction].index_in_callee; - Ok(if index_in_callee == index_in_instruction { - None - } else { - Some(index_in_callee) - }) - } + Some(index_in_callee) + }) } /// Gets the key of the last program account of this Instruction - pub fn get_program_key<'a, 'b: 'a>( + pub fn get_last_program_key<'a, 'b: 'a>( &'a self, transaction_context: &'b TransactionContext, ) -> Result<&'b Pubkey, InstructionError> { - let index_in_transaction = - self.get_index_in_transaction(self.program_accounts.len().saturating_sub(1))?; - transaction_context.get_key_of_account_at_index(index_in_transaction) + let result = self + .get_index_of_program_account_in_transaction( + self.program_accounts.len().saturating_sub(1), + ) + .and_then(|index_in_transaction| { + transaction_context.get_key_of_account_at_index(index_in_transaction) + }); + debug_assert!(result.is_ok()); + result } - /// Gets the key of an instruction account (skipping program accounts) - pub fn get_instruction_account_key<'a, 'b: 'a>( - &'a self, - transaction_context: &'b TransactionContext, - instruction_account_index: usize, - ) -> Result<&'b Pubkey, InstructionError> { - let index_in_transaction = self.get_index_in_transaction( - self.program_accounts - .len() - .saturating_add(instruction_account_index), - )?; - transaction_context.get_key_of_account_at_index(index_in_transaction) - } - - /// Tries to borrow an account from this Instruction - pub fn try_borrow_account<'a, 'b: 'a>( + fn try_borrow_account<'a, 'b: 'a>( &'a self, transaction_context: &'b TransactionContext, + index_in_transaction: usize, index_in_instruction: usize, ) -> Result, InstructionError> { - let index_in_transaction = self.get_index_in_transaction(index_in_instruction)?; - if index_in_transaction >= transaction_context.accounts.len() { - return Err(InstructionError::MissingAccount); - } - let account = transaction_context.accounts[index_in_transaction] + let account = transaction_context + .accounts + .get(index_in_transaction) + .ok_or(InstructionError::MissingAccount)? .try_borrow_mut() .map_err(|_| InstructionError::AccountBorrowFailed)?; Ok(BorrowedAccount { @@ -453,13 +429,30 @@ impl InstructionContext { } /// Gets the last program account of this Instruction - pub fn try_borrow_program_account<'a, 'b: 'a>( + pub fn try_borrow_last_program_account<'a, 'b: 'a>( &'a self, transaction_context: &'b TransactionContext, ) -> Result, InstructionError> { - self.try_borrow_account( + let result = self.try_borrow_program_account( transaction_context, self.program_accounts.len().saturating_sub(1), + ); + debug_assert!(result.is_ok()); + result + } + + /// Tries to borrow a program account from this Instruction + pub fn try_borrow_program_account<'a, 'b: 'a>( + &'a self, + transaction_context: &'b TransactionContext, + program_account_index: usize, + ) -> Result, InstructionError> { + let index_in_transaction = + self.get_index_of_program_account_in_transaction(program_account_index)?; + self.try_borrow_account( + transaction_context, + index_in_transaction, + program_account_index, ) } @@ -469,39 +462,42 @@ impl InstructionContext { transaction_context: &'b TransactionContext, instruction_account_index: usize, ) -> Result, InstructionError> { + let index_in_transaction = + self.get_index_of_instruction_account_in_transaction(instruction_account_index)?; self.try_borrow_account( transaction_context, + index_in_transaction, self.program_accounts .len() .saturating_add(instruction_account_index), ) } - /// Returns whether an account is a signer - pub fn is_signer(&self, index_in_instruction: usize) -> Result { - Ok(if index_in_instruction < self.program_accounts.len() { - false - } else { - self.instruction_accounts - .get(index_in_instruction.saturating_sub(self.program_accounts.len())) - .ok_or(InstructionError::MissingAccount)? - .is_signer - }) + /// Returns whether an instruction account is a signer + pub fn is_instruction_account_signer( + &self, + instruction_account_index: usize, + ) -> Result { + Ok(self + .instruction_accounts + .get(instruction_account_index) + .ok_or(InstructionError::MissingAccount)? + .is_signer) } - /// Returns whether an account is writable - pub fn is_writable(&self, index_in_instruction: usize) -> Result { - Ok(if index_in_instruction < self.program_accounts.len() { - false - } else { - self.instruction_accounts - .get(index_in_instruction.saturating_sub(self.program_accounts.len())) - .ok_or(InstructionError::MissingAccount)? - .is_writable - }) + /// Returns whether an instruction account is writable + pub fn is_instruction_account_writable( + &self, + instruction_account_index: usize, + ) -> Result { + Ok(self + .instruction_accounts + .get(instruction_account_index) + .ok_or(InstructionError::MissingAccount)? + .is_writable) } - /// Calculates the set of all keys of signer accounts in this Instruction + /// Calculates the set of all keys of signer instruction accounts in this Instruction pub fn get_signers(&self, transaction_context: &TransactionContext) -> HashSet { let mut result = HashSet::new(); for instruction_account in self.instruction_accounts.iter() { @@ -531,11 +527,6 @@ impl<'a> BorrowedAccount<'a> { self.index_in_transaction } - /// Returns the index of this account (instruction wide) - pub fn get_index_in_instruction(&self) -> usize { - self.index_in_instruction - } - /// Returns the public key of this account (transaction wide) pub fn get_key(&self) -> &Pubkey { &self.transaction_context.account_keys[self.index_in_transaction] @@ -646,15 +637,27 @@ impl<'a> BorrowedAccount<'a> { /// Returns whether this account is a signer (instruction wide) pub fn is_signer(&self) -> bool { + if self.index_in_instruction < self.instruction_context.program_accounts.len() { + return false; + } self.instruction_context - .is_signer(self.index_in_instruction) + .is_instruction_account_signer( + self.index_in_instruction + .saturating_sub(self.instruction_context.program_accounts.len()), + ) .unwrap_or_default() } /// Returns whether this account is writable (instruction wide) pub fn is_writable(&self) -> bool { + if self.index_in_instruction < self.instruction_context.program_accounts.len() { + return false; + } self.instruction_context - .is_writable(self.index_in_instruction) + .is_instruction_account_writable( + self.index_in_instruction + .saturating_sub(self.instruction_context.program_accounts.len()), + ) .unwrap_or_default() } }