Skip to content

Commit

Permalink
Collect program account indices directly in load_executable_accounts().
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichtso committed Sep 6, 2021
1 parent 54e3f92 commit 49f8c9c
Showing 1 changed file with 79 additions and 72 deletions.
151 changes: 79 additions & 72 deletions runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,10 @@ impl Accounts {
feature_set.is_active(&feature_set::demote_program_write_locks::id());

for (i, key) in message.account_keys_iter().enumerate() {
let account = if message.is_non_loader_key(i) {
let account = if !message.is_non_loader_key(i) {
// Fill in an empty account for the program slots.
AccountSharedData::default()
} else {
if payer_index.is_none() {
payer_index = Some(i);
}
Expand Down Expand Up @@ -285,12 +288,11 @@ impl Accounts {
programdata_address,
}) = account.state()
{
if let Some(account) = self
if let Some((programdata_account, _)) = self
.accounts_db
.load_with_fixed_root(ancestors, &programdata_address)
.map(|(account, _)| account)
{
account_deps.push((programdata_address, account));
account_deps.push((programdata_address, programdata_account));
} else {
error_counters.account_not_found += 1;
return Err(TransactionError::ProgramAccountNotFound);
Expand All @@ -306,9 +308,6 @@ impl Accounts {

account
}
} else {
// Fill in an empty account for the program slots.
AccountSharedData::default()
};
accounts.push((*key, account));
}
Expand All @@ -327,50 +326,47 @@ impl Accounts {
let payer_account = &mut accounts[payer_index].1;
if payer_account.lamports() == 0 {
error_counters.account_not_found += 1;
Err(TransactionError::AccountNotFound)
} else {
let min_balance =
match get_system_account_kind(payer_account).ok_or_else(|| {
error_counters.invalid_account_for_fee += 1;
TransactionError::InvalidAccountForFee
})? {
SystemAccountKind::System => 0,
SystemAccountKind::Nonce => {
// Should we ever allow a fees charge to zero a nonce account's
// balance. The state MUST be set to uninitialized in that case
rent_collector.rent.minimum_balance(nonce::State::size())
}
};

if payer_account.lamports() < fee + min_balance {
error_counters.insufficient_funds += 1;
Err(TransactionError::InsufficientFundsForFee)
} else {
payer_account
.checked_sub_lamports(fee)
.map_err(|_| TransactionError::InsufficientFundsForFee)?;

let message = tx.message();
let program_indices = message
.program_instructions_iter()
.map(|(program_id, _ix)| {
self.load_executable_accounts(ancestors, program_id, error_counters)
.map(|programs| {
let base_index = accounts.len();
accounts.append(&mut programs.clone());
(base_index..base_index + programs.len())
.collect::<Vec<_>>()
})
})
.collect::<Result<Vec<Vec<usize>>>>()?;
Ok(LoadedTransaction {
accounts,
program_indices,
rent: tx_rent,
rent_debits,
})
return Err(TransactionError::AccountNotFound);
}
let min_balance = match get_system_account_kind(payer_account).ok_or_else(|| {
error_counters.invalid_account_for_fee += 1;
TransactionError::InvalidAccountForFee
})? {
SystemAccountKind::System => 0,
SystemAccountKind::Nonce => {
// Should we ever allow a fees charge to zero a nonce account's
// balance. The state MUST be set to uninitialized in that case
rent_collector.rent.minimum_balance(nonce::State::size())
}
};

if payer_account.lamports() < fee + min_balance {
error_counters.insufficient_funds += 1;
return Err(TransactionError::InsufficientFundsForFee);
}
payer_account
.checked_sub_lamports(fee)
.map_err(|_| TransactionError::InsufficientFundsForFee)?;

let message = tx.message();
let program_indices = message
.instructions()
.iter()
.map(|instruction| {
self.load_executable_accounts(
ancestors,
&mut accounts,
instruction.program_id_index as usize,
error_counters,
)
})
.collect::<Result<Vec<Vec<usize>>>>()?;
Ok(LoadedTransaction {
accounts,
program_indices,
rent: tx_rent,
rent_debits,
})
} else {
error_counters.account_not_found += 1;
Err(TransactionError::AccountNotFound)
Expand All @@ -381,35 +377,35 @@ impl Accounts {
fn load_executable_accounts(
&self,
ancestors: &Ancestors,
program_id: &Pubkey,
accounts: &mut Vec<(Pubkey, AccountSharedData)>,
mut program_account_index: usize,
error_counters: &mut ErrorCounters,
) -> Result<Vec<(Pubkey, AccountSharedData)>> {
let mut accounts = Vec::new();
) -> Result<Vec<usize>> {
let mut account_indices = Vec::new();
let mut program_id = accounts[program_account_index].0;
let mut depth = 0;
let mut program_id = *program_id;
loop {
if native_loader::check_id(&program_id) {
// At the root of the chain, ready to dispatch
break;
}

while !native_loader::check_id(&program_id) {
if depth >= 5 {
error_counters.call_chain_too_deep += 1;
return Err(TransactionError::CallChainTooDeep);
}
depth += 1;

let program = match self
program_account_index = match self
.accounts_db
.load_with_fixed_root(ancestors, &program_id)
.map(|(account, _)| account)
{
Some(program) => program,
Some((program_account, _)) => {
let account_index = accounts.len();
accounts.push((program_id, program_account));
account_index
}
None => {
error_counters.account_not_found += 1;
return Err(TransactionError::ProgramAccountNotFound);
}
};
let program = &accounts[program_account_index].1;
if !program.executable() {
error_counters.invalid_program_for_execution += 1;
return Err(TransactionError::InvalidProgramForExecution);
Expand All @@ -424,26 +420,31 @@ impl Accounts {
programdata_address,
}) = program.state()
{
if let Some(program) = self
let programdata_account_index = match self
.accounts_db
.load_with_fixed_root(ancestors, &programdata_address)
.map(|(account, _)| account)
{
accounts.insert(0, (programdata_address, program));
} else {
error_counters.account_not_found += 1;
return Err(TransactionError::ProgramAccountNotFound);
}
Some((programdata_account, _)) => {
let account_index = accounts.len();
accounts.push((programdata_address, programdata_account));
account_index
}
None => {
error_counters.account_not_found += 1;
return Err(TransactionError::ProgramAccountNotFound);
}
};
account_indices.insert(0, programdata_account_index);
} else {
error_counters.invalid_program_for_execution += 1;
return Err(TransactionError::InvalidProgramForExecution);
}
}

accounts.insert(0, (program_id, program));
account_indices.insert(0, program_account_index);
program_id = program_owner;
}
Ok(accounts)
Ok(account_indices)
}

pub fn load_accounts(
Expand Down Expand Up @@ -1707,10 +1708,16 @@ mod tests {
let mut error_counters = ErrorCounters::default();
let ancestors = vec![(0, 0)].into_iter().collect();

let keypair = Keypair::new();
let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
account.set_executable(true);
accounts.store_slow_uncached(0, &keypair.pubkey(), &account);

assert_eq!(
accounts.load_executable_accounts(
&ancestors,
&solana_sdk::pubkey::new_rand(),
&mut vec![(keypair.pubkey(), account)],
0,
&mut error_counters
),
Err(TransactionError::ProgramAccountNotFound)
Expand Down

0 comments on commit 49f8c9c

Please sign in to comment.