Cleanup: `TransactionContext` (#27595)

* Lets instruction_accounts_lamport_sum() have the &InstructionContext as parameter directly.

* Updates docu comments.

* Uses accessors methods instead of accessing private properties of other structs.

* Adds #![deny(clippy::indexing_slicing)].

* Has get_signers() return a Result instead of using unwrap().

* Removes InvokeContext::get_key_of_account_at_index().
This commit is contained in:
Alexander Meißner 2022-09-05 16:29:02 +02:00 committed by GitHub
parent 0b94d5af18
commit 6f2e556b16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 60 deletions

View File

@ -895,15 +895,6 @@ impl<'a> InvokeContext<'a> {
&self.sysvar_cache &self.sysvar_cache
} }
// Get pubkey of account at index
pub fn get_key_of_account_at_index(
&self,
index_in_transaction: usize,
) -> Result<&Pubkey, InstructionError> {
self.transaction_context
.get_key_of_account_at_index(index_in_transaction)
}
// Set this instruction syscall context // Set this instruction syscall context
pub fn set_syscall_context( pub fn set_syscall_context(
&mut self, &mut self,

View File

@ -1812,7 +1812,9 @@ declare_syscall!(
let account_metas = question_mark!( let account_metas = question_mark!(
(0..instruction_context.get_number_of_instruction_accounts()) (0..instruction_context.get_number_of_instruction_accounts())
.map(|instruction_account_index| Ok(AccountMeta { .map(|instruction_account_index| Ok(AccountMeta {
pubkey: *invoke_context.get_key_of_account_at_index( pubkey: *invoke_context
.transaction_context
.get_key_of_account_at_index(
instruction_context instruction_context
.get_index_of_instruction_account_in_transaction( .get_index_of_instruction_account_in_transaction(
instruction_account_index instruction_account_index

View File

@ -69,7 +69,7 @@ pub fn process_instruction(
Ok(me) Ok(me)
}; };
let signers = instruction_context.get_signers(transaction_context); let signers = instruction_context.get_signers(transaction_context)?;
match limited_deserialize(data) { match limited_deserialize(data) {
Ok(StakeInstruction::Initialize(authorized, lockup)) => { Ok(StakeInstruction::Initialize(authorized, lockup)) => {
let mut me = get_stake_account()?; let mut me = get_stake_account()?;

View File

@ -70,7 +70,7 @@ pub fn process_instruction(
return Err(InstructionError::InvalidAccountOwner); return Err(InstructionError::InvalidAccountOwner);
} }
let signers = instruction_context.get_signers(transaction_context); let signers = instruction_context.get_signers(transaction_context)?;
match limited_deserialize(data)? { match limited_deserialize(data)? {
VoteInstruction::InitializeAccount(vote_init) => { VoteInstruction::InitializeAccount(vote_init) => {
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?; let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?;

View File

@ -324,7 +324,7 @@ pub fn process_instruction(
trace!("process_instruction: {:?}", instruction); trace!("process_instruction: {:?}", instruction);
let signers = instruction_context.get_signers(transaction_context); let signers = instruction_context.get_signers(transaction_context)?;
match instruction { match instruction {
SystemInstruction::CreateAccount { SystemInstruction::CreateAccount {
lamports, lamports,

View File

@ -1,4 +1,5 @@
//! Data shared between program runtime and built-in programs as well as SBF programs //! Data shared between program runtime and built-in programs as well as SBF programs
#![deny(clippy::indexing_slicing)]
#[cfg(target_os = "solana")] #[cfg(target_os = "solana")]
use crate::instruction::AccountPropertyUpdate; use crate::instruction::AccountPropertyUpdate;
@ -23,8 +24,6 @@ use {
}, },
}; };
pub type TransactionAccount = (Pubkey, AccountSharedData);
/// For addressing (nested) properties of the TransactionContext /// For addressing (nested) properties of the TransactionContext
#[repr(u16)] #[repr(u16)]
pub enum TransactionContextAttribute { pub enum TransactionContextAttribute {
@ -99,6 +98,9 @@ pub struct InstructionAccount {
pub is_writable: bool, pub is_writable: bool,
} }
/// An account key and the matching account
pub type TransactionAccount = (Pubkey, AccountSharedData);
/// Loaded transaction shared between runtime and programs. /// Loaded transaction shared between runtime and programs.
/// ///
/// This context is valid for the entire duration of a transaction being processed. /// This context is valid for the entire duration of a transaction being processed.
@ -273,19 +275,16 @@ impl TransactionContext {
.instruction_trace .instruction_trace
.last() .last()
.ok_or(InstructionError::CallDepth)?; .ok_or(InstructionError::CallDepth)?;
let callee_instruction_accounts_lamport_sum = self.instruction_accounts_lamport_sum( let callee_instruction_accounts_lamport_sum =
caller_instruction_context.instruction_accounts.iter(), self.instruction_accounts_lamport_sum(caller_instruction_context)?;
)?;
if !self.instruction_stack.is_empty() if !self.instruction_stack.is_empty()
&& self.is_early_verification_of_account_modifications_enabled() && self.is_early_verification_of_account_modifications_enabled()
{ {
let caller_instruction_context = self.get_current_instruction_context()?; let caller_instruction_context = self.get_current_instruction_context()?;
let original_caller_instruction_accounts_lamport_sum = let original_caller_instruction_accounts_lamport_sum =
caller_instruction_context.instruction_accounts_lamport_sum; caller_instruction_context.instruction_accounts_lamport_sum;
let current_caller_instruction_accounts_lamport_sum = self let current_caller_instruction_accounts_lamport_sum =
.instruction_accounts_lamport_sum( self.instruction_accounts_lamport_sum(caller_instruction_context)?;
caller_instruction_context.instruction_accounts.iter(),
)?;
if original_caller_instruction_accounts_lamport_sum if original_caller_instruction_accounts_lamport_sum
!= current_caller_instruction_accounts_lamport_sum != current_caller_instruction_accounts_lamport_sum
{ {
@ -298,7 +297,7 @@ impl TransactionContext {
instruction_context.instruction_accounts_lamport_sum = instruction_context.instruction_accounts_lamport_sum =
callee_instruction_accounts_lamport_sum; callee_instruction_accounts_lamport_sum;
} }
let index_in_trace = self.instruction_trace.len().saturating_sub(1); let index_in_trace = self.get_instruction_trace_length();
self.instruction_trace.push(InstructionContext::default()); self.instruction_trace.push(InstructionContext::default());
if nesting_level >= self.instruction_context_capacity { if nesting_level >= self.instruction_context_capacity {
return Err(InstructionError::CallDepth); return Err(InstructionError::CallDepth);
@ -324,9 +323,7 @@ impl TransactionContext {
.try_borrow_mut() .try_borrow_mut()
.map_err(|_| InstructionError::AccountBorrowOutstanding)?; .map_err(|_| InstructionError::AccountBorrowOutstanding)?;
} }
self.instruction_accounts_lamport_sum( self.instruction_accounts_lamport_sum(instruction_context)
instruction_context.instruction_accounts.iter(),
)
.map(|instruction_accounts_lamport_sum| { .map(|instruction_accounts_lamport_sum| {
instruction_context.instruction_accounts_lamport_sum instruction_context.instruction_accounts_lamport_sum
!= instruction_accounts_lamport_sum != instruction_accounts_lamport_sum
@ -361,23 +358,26 @@ impl TransactionContext {
/// Calculates the sum of all lamports within an instruction /// Calculates the sum of all lamports within an instruction
#[cfg(not(target_os = "solana"))] #[cfg(not(target_os = "solana"))]
fn instruction_accounts_lamport_sum<'a, I>( fn instruction_accounts_lamport_sum(
&'a self, &self,
instruction_accounts: I, instruction_context: &InstructionContext,
) -> Result<u128, InstructionError> ) -> Result<u128, InstructionError> {
where
I: Iterator<Item = &'a InstructionAccount>,
{
if !self.is_early_verification_of_account_modifications_enabled() { if !self.is_early_verification_of_account_modifications_enabled() {
return Ok(0); return Ok(0);
} }
let mut instruction_accounts_lamport_sum: u128 = 0; let mut instruction_accounts_lamport_sum: u128 = 0;
for (instruction_account_index, instruction_account) in instruction_accounts.enumerate() { for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts()
if instruction_account_index != instruction_account.index_in_callee { {
if instruction_context
.is_instruction_account_duplicate(instruction_account_index)?
.is_some()
{
continue; // Skip duplicate account continue; // Skip duplicate account
} }
let index_in_transaction = instruction_context
.get_index_of_instruction_account_in_transaction(instruction_account_index)?;
instruction_accounts_lamport_sum = (self instruction_accounts_lamport_sum = (self
.get_account_at_index(instruction_account.index_in_transaction)? .get_account_at_index(index_in_transaction)?
.try_borrow() .try_borrow()
.map_err(|_| InstructionError::AccountBorrowOutstanding)? .map_err(|_| InstructionError::AccountBorrowOutstanding)?
.lamports() as u128) .lamports() as u128)
@ -483,7 +483,7 @@ impl InstructionContext {
self.program_accounts self.program_accounts
.iter() .iter()
.position(|index_in_transaction| { .position(|index_in_transaction| {
&transaction_context.account_keys[*index_in_transaction] == pubkey transaction_context.account_keys.get(*index_in_transaction) == Some(pubkey)
}) })
} }
@ -496,8 +496,10 @@ impl InstructionContext {
self.instruction_accounts self.instruction_accounts
.iter() .iter()
.position(|instruction_account| { .position(|instruction_account| {
&transaction_context.account_keys[instruction_account.index_in_transaction] transaction_context
== pubkey .account_keys
.get(instruction_account.index_in_transaction)
== Some(pubkey)
}) })
} }
@ -548,7 +550,7 @@ impl InstructionContext {
transaction_context: &'b TransactionContext, transaction_context: &'b TransactionContext,
) -> Result<&'b Pubkey, InstructionError> { ) -> Result<&'b Pubkey, InstructionError> {
self.get_index_of_program_account_in_transaction( self.get_index_of_program_account_in_transaction(
self.program_accounts.len().saturating_sub(1), self.get_number_of_program_accounts().saturating_sub(1),
) )
.and_then(|index_in_transaction| { .and_then(|index_in_transaction| {
transaction_context.get_key_of_account_at_index(index_in_transaction) transaction_context.get_key_of_account_at_index(index_in_transaction)
@ -583,7 +585,7 @@ impl InstructionContext {
) -> Result<BorrowedAccount<'a>, InstructionError> { ) -> Result<BorrowedAccount<'a>, InstructionError> {
let result = self.try_borrow_program_account( let result = self.try_borrow_program_account(
transaction_context, transaction_context,
self.program_accounts.len().saturating_sub(1), self.get_number_of_program_accounts().saturating_sub(1),
); );
debug_assert!(result.is_ok()); debug_assert!(result.is_ok());
result result
@ -615,8 +617,7 @@ impl InstructionContext {
self.try_borrow_account( self.try_borrow_account(
transaction_context, transaction_context,
index_in_transaction, index_in_transaction,
self.program_accounts self.get_number_of_program_accounts()
.len()
.saturating_add(instruction_account_index), .saturating_add(instruction_account_index),
) )
} }
@ -646,16 +647,20 @@ impl InstructionContext {
} }
/// Calculates the set of all keys of signer instruction 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<Pubkey> { pub fn get_signers(
&self,
transaction_context: &TransactionContext,
) -> Result<HashSet<Pubkey>, InstructionError> {
let mut result = HashSet::new(); let mut result = HashSet::new();
for instruction_account in self.instruction_accounts.iter() { for instruction_account in self.instruction_accounts.iter() {
if instruction_account.is_signer { if instruction_account.is_signer {
result.insert( result.insert(
transaction_context.account_keys[instruction_account.index_in_transaction], *transaction_context
.get_key_of_account_at_index(instruction_account.index_in_transaction)?,
); );
} }
} }
result Ok(result)
} }
} }
@ -677,7 +682,9 @@ impl<'a> BorrowedAccount<'a> {
/// Returns the public key of this account (transaction wide) /// Returns the public key of this account (transaction wide)
pub fn get_key(&self) -> &Pubkey { pub fn get_key(&self) -> &Pubkey {
&self.transaction_context.account_keys[self.index_in_transaction] self.transaction_context
.get_key_of_account_at_index(self.index_in_transaction)
.unwrap()
} }
/// Returns the owner of this account (transaction wide) /// Returns the owner of this account (transaction wide)
@ -933,26 +940,26 @@ impl<'a> BorrowedAccount<'a> {
/// Returns whether this account is a signer (instruction wide) /// Returns whether this account is a signer (instruction wide)
pub fn is_signer(&self) -> bool { pub fn is_signer(&self) -> bool {
if self.index_in_instruction < self.instruction_context.program_accounts.len() { if self.index_in_instruction < self.instruction_context.get_number_of_program_accounts() {
return false; return false;
} }
self.instruction_context self.instruction_context
.is_instruction_account_signer( .is_instruction_account_signer(
self.index_in_instruction self.index_in_instruction
.saturating_sub(self.instruction_context.program_accounts.len()), .saturating_sub(self.instruction_context.get_number_of_program_accounts()),
) )
.unwrap_or_default() .unwrap_or_default()
} }
/// Returns whether this account is writable (instruction wide) /// Returns whether this account is writable (instruction wide)
pub fn is_writable(&self) -> bool { pub fn is_writable(&self) -> bool {
if self.index_in_instruction < self.instruction_context.program_accounts.len() { if self.index_in_instruction < self.instruction_context.get_number_of_program_accounts() {
return false; return false;
} }
self.instruction_context self.instruction_context
.is_instruction_account_writable( .is_instruction_account_writable(
self.index_in_instruction self.index_in_instruction
.saturating_sub(self.instruction_context.program_accounts.len()), .saturating_sub(self.instruction_context.get_number_of_program_accounts()),
) )
.unwrap_or_default() .unwrap_or_default()
} }