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:
parent
0b94d5af18
commit
6f2e556b16
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()?;
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue