Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
Splits get_account() into find_index_of_account() and get_account_at_…
Browse files Browse the repository at this point in the history
…index()

in order to remove Rc from return type.
  • Loading branch information
Lichtso committed Dec 14, 2021
1 parent 6398a13 commit daea395
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 39 deletions.
42 changes: 25 additions & 17 deletions program-runtime/src/invoke_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,12 +489,12 @@ impl<'a> InvokeContext<'a> {
let mut account_indices = Vec::with_capacity(message.account_keys.len());
let mut prev_account_sizes = Vec::with_capacity(message.account_keys.len());
for account_key in message.account_keys.iter() {
let (account_index, account) = self
.get_account(account_key)
let account_index = self
.find_index_of_account(account_key)
.ok_or(InstructionError::MissingAccount)?;
let account_length = account.borrow().data().len();
let account_length = self.accounts[account_index].1.borrow().data().len();
account_indices.push(account_index);
prev_account_sizes.push((account, account_length));
prev_account_sizes.push((account_index, account_length));
}

if let Some(instruction_recorder) = &self.instruction_recorder {
Expand All @@ -510,8 +510,10 @@ impl<'a> InvokeContext<'a> {

// Verify the called program has not misbehaved
let do_support_realloc = self.feature_set.is_active(&do_support_realloc::id());
for (account, prev_size) in prev_account_sizes.iter() {
if !do_support_realloc && *prev_size != account.borrow().data().len() && *prev_size != 0
for (account_index, prev_size) in prev_account_sizes.into_iter() {
if !do_support_realloc
&& prev_size != self.accounts[account_index].1.borrow().data().len()
&& prev_size != 0
{
// Only support for `CreateAccount` at this time.
// Need a way to limit total realloc size across multiple CPI calls
Expand Down Expand Up @@ -595,26 +597,27 @@ impl<'a> InvokeContext<'a> {

// Find and validate executables / program accounts
let callee_program_id = instruction.program_id;
let (program_account_index, program_account) = callee_keyed_accounts
let program_account_index = callee_keyed_accounts
.iter()
.find(|keyed_account| &callee_program_id == keyed_account.unsigned_key())
.and_then(|_keyed_account| self.get_account(&callee_program_id))
.and_then(|_keyed_account| self.find_index_of_account(&callee_program_id))
.ok_or_else(|| {
ic_msg!(self, "Unknown program {}", callee_program_id);
InstructionError::MissingAccount
})?;
if !program_account.borrow().executable() {
let program_account = self.accounts[program_account_index].1.borrow();
if !program_account.executable() {
ic_msg!(self, "Account {} is not executable", callee_program_id);
return Err(InstructionError::AccountNotExecutable);
}
let mut program_indices = vec![];
if program_account.borrow().owner() == &bpf_loader_upgradeable::id() {
if program_account.owner() == &bpf_loader_upgradeable::id() {
if let UpgradeableLoaderState::Program {
programdata_address,
} = program_account.borrow().state()?
} = program_account.state()?
{
if let Some((programdata_account_index, _programdata_account)) =
self.get_account(&programdata_address)
if let Some(programdata_account_index) =
self.find_index_of_account(&programdata_address)
{
program_indices.push(programdata_account_index);
} else {
Expand Down Expand Up @@ -797,16 +800,21 @@ impl<'a> InvokeContext<'a> {
self.executors.borrow().get(pubkey)
}

/// Find an account_index and account by its key
pub fn get_account(&self, pubkey: &Pubkey) -> Option<(usize, Rc<RefCell<AccountSharedData>>)> {
for (index, (key, account)) in self.accounts.iter().enumerate().rev() {
/// Finds an account_index by its key
pub fn find_index_of_account(&self, pubkey: &Pubkey) -> Option<usize> {
for (index, (key, _account)) in self.accounts.iter().enumerate().rev() {
if key == pubkey {
return Some((index, account.clone()));
return Some(index);
}
}
None
}

/// Returns an account by its account_index
pub fn get_account_at_index(&self, account_index: usize) -> &RefCell<AccountSharedData> {
&self.accounts[account_index].1
}

/// Get this invocation's compute budget
pub fn get_compute_budget(&self) -> &ComputeBudget {
&self.current_compute_budget
Expand Down
24 changes: 13 additions & 11 deletions program-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
let mut account_indices = Vec::with_capacity(message.account_keys.len());
let mut accounts = Vec::with_capacity(message.account_keys.len());
for (i, account_key) in message.account_keys.iter().enumerate() {
let ((account_index, account), account_info) = invoke_context
.get_account(account_key)
let (account_index, account_info) = invoke_context
.find_index_of_account(account_key)
.zip(
account_infos
.iter()
Expand All @@ -271,7 +271,9 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
.ok_or(InstructionError::MissingAccount)
.unwrap();
{
let mut account = account.borrow_mut();
let mut account = invoke_context
.get_account_at_index(account_index)
.borrow_mut();
account.copy_into_owner_from_slice(account_info.owner.as_ref());
account.set_data_from_slice(&account_info.try_borrow_data().unwrap());
account.set_lamports(account_info.lamports());
Expand All @@ -284,10 +286,9 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
None
};
account_indices.push(account_index);
accounts.push((account, account_info));
accounts.push((account_index, account_info));
}
let (program_account_index, _program_account) =
invoke_context.get_account(&program_id).unwrap();
let program_account_index = invoke_context.find_index_of_account(&program_id).unwrap();
let program_indices = vec![program_account_index];

// Check Signers
Expand Down Expand Up @@ -329,19 +330,20 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
.map_err(|err| ProgramError::try_from(err).unwrap_or_else(|err| panic!("{}", err)))?;

// Copy writeable account modifications back into the caller's AccountInfos
for (account, account_info) in accounts.iter() {
for (account_index, account_info) in accounts.into_iter() {
if let Some(account_info) = account_info {
**account_info.try_borrow_mut_lamports().unwrap() = account.borrow().lamports();
let mut data = account_info.try_borrow_mut_data()?;
let account = invoke_context.get_account_at_index(account_index);
let account_borrow = account.borrow();
**account_info.try_borrow_mut_lamports().unwrap() = account_borrow.lamports();
let mut data = account_info.try_borrow_mut_data()?;
let new_data = account_borrow.data();
if account_info.owner != account.borrow().owner() {
if account_info.owner != account_borrow.owner() {
// TODO Figure out a better way to allow the System Program to set the account owner
#[allow(clippy::transmute_ptr_to_ptr)]
#[allow(mutable_transmutes)]
let account_info_mut =
unsafe { transmute::<&Pubkey, &mut Pubkey>(account_info.owner) };
*account_info_mut = *account.borrow().owner();
*account_info_mut = *account_borrow.owner();
}
// TODO: Figure out how to allow the System Program to resize the account data
assert!(
Expand Down
24 changes: 13 additions & 11 deletions programs/bpf_loader/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use {
vm::{EbpfVm, SyscallObject, SyscallRegistry},
},
solana_sdk::{
account::{AccountSharedData, ReadableAccount, WritableAccount},
account::{ReadableAccount, WritableAccount},
account_info::AccountInfo,
blake3, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
clock::Clock,
Expand Down Expand Up @@ -1667,10 +1667,7 @@ struct CallerAccount<'a> {
executable: bool,
rent_epoch: u64,
}
type TranslatedAccounts<'a> = (
Vec<usize>,
Vec<(Rc<RefCell<AccountSharedData>>, Option<CallerAccount<'a>>)>,
);
type TranslatedAccounts<'a> = (Vec<usize>, Vec<(usize, Option<CallerAccount<'a>>)>);

/// Implemented by language specific data structure translators
trait SyscallInvokeSigned<'a, 'b> {
Expand Down Expand Up @@ -2210,13 +2207,14 @@ where
let mut account_indices = Vec::with_capacity(message.account_keys.len());
let mut accounts = Vec::with_capacity(message.account_keys.len());
for (i, account_key) in message.account_keys.iter().enumerate() {
if let Some((account_index, account)) = invoke_context.get_account(account_key) {
if let Some(account_index) = invoke_context.find_index_of_account(account_key) {
let account = invoke_context.get_account_at_index(account_index);
if i == message.instructions[0].program_id_index as usize
|| account.borrow().executable()
{
// Use the known account
account_indices.push(account_index);
accounts.push((account, None));
accounts.push((account_index, None));
continue;
} else if let Some(caller_account_index) =
account_info_keys.iter().position(|key| *key == account_key)
Expand Down Expand Up @@ -2265,7 +2263,7 @@ where
None
};
account_indices.push(account_index);
accounts.push((account, caller_account));
accounts.push((account_index, caller_account));
continue;
}
}
Expand Down Expand Up @@ -2400,9 +2398,11 @@ fn call<'a, 'b: 'a>(
.map_err(SyscallError::InstructionError)?;

// Copy results back to caller
for (callee_account, caller_account) in accounts.iter_mut() {
for (callee_account_index, caller_account) in accounts.iter_mut() {
if let Some(caller_account) = caller_account {
let callee_account = callee_account.borrow();
let callee_account = invoke_context
.get_account_at_index(*callee_account_index)
.borrow();
*caller_account.lamports = callee_account.lamports();
*caller_account.owner = *callee_account.owner();
let new_len = callee_account.data().len();
Expand Down Expand Up @@ -2672,7 +2672,9 @@ mod tests {
solana_rbpf::{
ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config,
},
solana_sdk::{bpf_loader, fee_calculator::FeeCalculator, hash::hashv},
solana_sdk::{
account::AccountSharedData, bpf_loader, fee_calculator::FeeCalculator, hash::hashv,
},
std::str::FromStr,
};

Expand Down

0 comments on commit daea395

Please sign in to comment.