Refactors tuple of TransactionLoadResult into a struct. (#14773)

This commit is contained in:
Alexander Meißner 2021-01-25 10:35:08 +01:00 committed by GitHub
parent bd0433c373
commit 5700e835ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 135 deletions

View File

@ -66,16 +66,15 @@ pub type TransactionAccounts = Vec<Account>;
pub type TransactionAccountDeps = Vec<(Pubkey, Account)>; pub type TransactionAccountDeps = Vec<(Pubkey, Account)>;
pub type TransactionRent = u64; pub type TransactionRent = u64;
pub type TransactionLoaders = Vec<Vec<(Pubkey, Account)>>; pub type TransactionLoaders = Vec<Vec<(Pubkey, Account)>>;
#[derive(PartialEq, Debug, Clone)]
pub struct LoadedTransaction {
pub accounts: TransactionAccounts,
pub account_deps: TransactionAccountDeps,
pub loaders: TransactionLoaders,
pub rent: TransactionRent,
}
pub type TransactionLoadResult = ( pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>);
Result<(
TransactionAccounts,
TransactionAccountDeps,
TransactionLoaders,
TransactionRent,
)>,
Option<NonceRollbackFull>,
);
pub enum AccountAddressFilter { pub enum AccountAddressFilter {
Exclude, // exclude all addresses matching the filter Exclude, // exclude all addresses matching the filter
@ -151,7 +150,7 @@ impl Accounts {
account account
} }
fn load_tx_accounts( fn load_transaction(
&self, &self,
ancestors: &Ancestors, ancestors: &Ancestors,
tx: &Transaction, tx: &Transaction,
@ -159,7 +158,7 @@ impl Accounts {
error_counters: &mut ErrorCounters, error_counters: &mut ErrorCounters,
rent_collector: &RentCollector, rent_collector: &RentCollector,
feature_set: &FeatureSet, feature_set: &FeatureSet,
) -> Result<(TransactionAccounts, TransactionAccountDeps, TransactionRent)> { ) -> Result<LoadedTransaction> {
// Copy all the accounts // Copy all the accounts
let message = tx.message(); let message = tx.message();
if tx.signatures.is_empty() && fee != 0 { if tx.signatures.is_empty() && fee != 0 {
@ -263,7 +262,30 @@ impl Accounts {
Err(TransactionError::InsufficientFundsForFee) Err(TransactionError::InsufficientFundsForFee)
} else { } else {
accounts[payer_index].lamports -= fee; accounts[payer_index].lamports -= fee;
Ok((accounts, account_deps, tx_rent))
let message = tx.message();
let loaders = message
.instructions
.iter()
.map(|ix| {
if message.account_keys.len() <= ix.program_id_index as usize {
error_counters.account_not_found += 1;
return Err(TransactionError::AccountNotFound);
}
let program_id = message.account_keys[ix.program_id_index as usize];
self.load_executable_accounts(
ancestors,
&program_id,
error_counters,
)
})
.collect::<Result<TransactionLoaders>>()?;
Ok(LoadedTransaction {
accounts,
account_deps,
loaders,
rent: tx_rent,
})
} }
} }
} else { } else {
@ -341,28 +363,6 @@ impl Accounts {
Ok(accounts) Ok(accounts)
} }
/// For each program_id in the transaction, load its loaders.
fn load_loaders(
&self,
ancestors: &Ancestors,
tx: &Transaction,
error_counters: &mut ErrorCounters,
) -> Result<TransactionLoaders> {
let message = tx.message();
message
.instructions
.iter()
.map(|ix| {
if message.account_keys.len() <= ix.program_id_index as usize {
error_counters.account_not_found += 1;
return Err(TransactionError::AccountNotFound);
}
let program_id = message.account_keys[ix.program_id_index as usize];
self.load_executable_accounts(ancestors, &program_id, error_counters)
})
.collect()
}
pub fn load_accounts( pub fn load_accounts(
&self, &self,
ancestors: &Ancestors, ancestors: &Ancestors,
@ -396,22 +396,15 @@ impl Accounts {
return (Err(TransactionError::BlockhashNotFound), None); return (Err(TransactionError::BlockhashNotFound), None);
}; };
let load_res = self.load_tx_accounts( let loaded_transaction = match self.load_transaction(
ancestors, ancestors,
tx, tx,
fee, fee,
error_counters, error_counters,
rent_collector, rent_collector,
feature_set, feature_set,
); ) {
let (accounts, account_deps, rents) = match load_res { Ok(loaded_transaction) => loaded_transaction,
Ok((a, d, r)) => (a, d, r),
Err(e) => return (Err(e), None),
};
let load_res = self.load_loaders(ancestors, tx, error_counters);
let loaders = match load_res {
Ok(loaders) => loaders,
Err(e) => return (Err(e), None), Err(e) => return (Err(e), None),
}; };
@ -420,7 +413,7 @@ impl Accounts {
match NonceRollbackFull::from_partial( match NonceRollbackFull::from_partial(
nonce_rollback, nonce_rollback,
tx.message(), tx.message(),
&accounts, &loaded_transaction.accounts,
) { ) {
Ok(nonce_rollback) => Some(nonce_rollback), Ok(nonce_rollback) => Some(nonce_rollback),
Err(e) => return (Err(e), None), Err(e) => return (Err(e), None),
@ -429,7 +422,7 @@ impl Accounts {
None None
}; };
(Ok((accounts, account_deps, loaders, rents)), nonce_rollback) (Ok(loaded_transaction), nonce_rollback)
} }
(_, (Err(e), _nonce_rollback)) => (Err(e), None), (_, (Err(e), _nonce_rollback)) => (Err(e), None),
}) })
@ -947,13 +940,13 @@ impl Accounts {
}; };
let message = &tx.message(); let message = &tx.message();
let acc = raccs.as_mut().unwrap(); let loaded_transaction = raccs.as_mut().unwrap();
let mut fee_payer_index = None; let mut fee_payer_index = None;
for ((i, key), account) in message for ((i, key), account) in message
.account_keys .account_keys
.iter() .iter()
.enumerate() .enumerate()
.zip(acc.0.iter_mut()) .zip(loaded_transaction.accounts.iter_mut())
.filter(|((i, key), _account)| message.is_non_loader_key(key, *i)) .filter(|((i, key), _account)| message.is_non_loader_key(key, *i))
{ {
let is_nonce_account = prepare_if_nonce_account( let is_nonce_account = prepare_if_nonce_account(
@ -986,7 +979,7 @@ impl Accounts {
} }
} }
if account.rent_epoch == 0 { if account.rent_epoch == 0 {
acc.3 += rent_collector.collect_from_created_account( loaded_transaction.rent += rent_collector.collect_from_created_account(
&key, &key,
account, account,
rent_fix_enabled, rent_fix_enabled,
@ -1330,8 +1323,8 @@ mod tests {
); );
assert_eq!(loaded_accounts.len(), 1); assert_eq!(loaded_accounts.len(), 1);
let (load_res, _nonce_rollback) = &loaded_accounts[0]; let (load_res, _nonce_rollback) = &loaded_accounts[0];
let (tx_accounts, _account_deps, _loaders, _rents) = load_res.as_ref().unwrap(); let loaded_transaction = load_res.as_ref().unwrap();
assert_eq!(tx_accounts[0].lamports, min_balance); assert_eq!(loaded_transaction.accounts[0].lamports, min_balance);
// Fee leaves zero balance fails // Fee leaves zero balance fails
accounts[0].1.lamports = min_balance; accounts[0].1.lamports = min_balance;
@ -1391,19 +1384,11 @@ mod tests {
assert_eq!(error_counters.account_not_found, 0); assert_eq!(error_counters.account_not_found, 0);
assert_eq!(loaded_accounts.len(), 1); assert_eq!(loaded_accounts.len(), 1);
match &loaded_accounts[0] { match &loaded_accounts[0] {
( (Ok(loaded_transaction), _nonce_rollback) => {
Ok(( assert_eq!(loaded_transaction.accounts.len(), 3);
transaction_accounts, assert_eq!(loaded_transaction.accounts[0], accounts[0].1);
_transaction_account_deps, assert_eq!(loaded_transaction.loaders.len(), 1);
transaction_loaders, assert_eq!(loaded_transaction.loaders[0].len(), 0);
_transaction_rents,
)),
_nonce_rollback,
) => {
assert_eq!(transaction_accounts.len(), 3);
assert_eq!(transaction_accounts[0], accounts[0].1);
assert_eq!(transaction_loaders.len(), 1);
assert_eq!(transaction_loaders[0].len(), 0);
} }
(Err(e), _nonce_rollback) => Err(e).unwrap(), (Err(e), _nonce_rollback) => Err(e).unwrap(),
} }
@ -1622,21 +1607,13 @@ mod tests {
assert_eq!(error_counters.account_not_found, 0); assert_eq!(error_counters.account_not_found, 0);
assert_eq!(loaded_accounts.len(), 1); assert_eq!(loaded_accounts.len(), 1);
match &loaded_accounts[0] { match &loaded_accounts[0] {
( (Ok(loaded_transaction), _nonce_rollback) => {
Ok(( assert_eq!(loaded_transaction.accounts.len(), 3);
transaction_accounts, assert_eq!(loaded_transaction.accounts[0], accounts[0].1);
_transaction_account_deps, assert_eq!(loaded_transaction.loaders.len(), 2);
transaction_loaders, assert_eq!(loaded_transaction.loaders[0].len(), 1);
_transaction_rents, assert_eq!(loaded_transaction.loaders[1].len(), 2);
)), for loaders in loaded_transaction.loaders.iter() {
_nonce_rollback,
) => {
assert_eq!(transaction_accounts.len(), 3);
assert_eq!(transaction_accounts[0], accounts[0].1);
assert_eq!(transaction_loaders.len(), 2);
assert_eq!(transaction_loaders[0].len(), 1);
assert_eq!(transaction_loaders[1].len(), 2);
for loaders in transaction_loaders.iter() {
for (i, accounts_subset) in loaders.iter().enumerate() { for (i, accounts_subset) in loaders.iter().enumerate() {
// +1 to skip first not loader account // +1 to skip first not loader account
assert_eq!(*accounts_subset, accounts[i + 1]); assert_eq!(*accounts_subset, accounts[i + 1]);
@ -1928,12 +1905,12 @@ mod tests {
let transaction_loaders0 = vec![]; let transaction_loaders0 = vec![];
let transaction_rent0 = 0; let transaction_rent0 = 0;
let loaded0 = ( let loaded0 = (
Ok(( Ok(LoadedTransaction {
transaction_accounts0, accounts: transaction_accounts0,
vec![], account_deps: vec![],
transaction_loaders0, loaders: transaction_loaders0,
transaction_rent0, rent: transaction_rent0,
)), }),
None, None,
); );
@ -1941,12 +1918,12 @@ mod tests {
let transaction_loaders1 = vec![]; let transaction_loaders1 = vec![];
let transaction_rent1 = 0; let transaction_rent1 = 0;
let loaded1 = ( let loaded1 = (
Ok(( Ok(LoadedTransaction {
transaction_accounts1, accounts: transaction_accounts1,
vec![], account_deps: vec![],
transaction_loaders1, loaders: transaction_loaders1,
transaction_rent1, rent: transaction_rent1,
)), }),
None, None,
); );
@ -1968,7 +1945,7 @@ mod tests {
&txs, &txs,
None, None,
&loaders, &loaders,
&mut loaded, loaded.as_mut_slice(),
&rent_collector, &rent_collector,
&(Hash::default(), FeeCalculator::default()), &(Hash::default(), FeeCalculator::default()),
true, true,
@ -2317,12 +2294,12 @@ mod tests {
let transaction_loaders = vec![]; let transaction_loaders = vec![];
let transaction_rent = 0; let transaction_rent = 0;
let loaded = ( let loaded = (
Ok(( Ok(LoadedTransaction {
transaction_accounts, accounts: transaction_accounts,
vec![], account_deps: vec![],
transaction_loaders, loaders: transaction_loaders,
transaction_rent, rent: transaction_rent,
)), }),
nonce_rollback, nonce_rollback,
); );
@ -2335,7 +2312,7 @@ mod tests {
&txs, &txs,
None, None,
&loaders, &loaders,
&mut loaded, loaded.as_mut_slice(),
&rent_collector, &rent_collector,
&(next_blockhash, FeeCalculator::default()), &(next_blockhash, FeeCalculator::default()),
true, true,
@ -2428,12 +2405,12 @@ mod tests {
let transaction_loaders = vec![]; let transaction_loaders = vec![];
let transaction_rent = 0; let transaction_rent = 0;
let loaded = ( let loaded = (
Ok(( Ok(LoadedTransaction {
transaction_accounts, accounts: transaction_accounts,
vec![], account_deps: vec![],
transaction_loaders, loaders: transaction_loaders,
transaction_rent, rent: transaction_rent,
)), }),
nonce_rollback, nonce_rollback,
); );
@ -2446,7 +2423,7 @@ mod tests {
&txs, &txs,
None, None,
&loaders, &loaders,
&mut loaded, loaded.as_mut_slice(),
&rent_collector, &rent_collector,
&(next_blockhash, FeeCalculator::default()), &(next_blockhash, FeeCalculator::default()),
true, true,

View File

@ -2487,25 +2487,6 @@ impl Bank {
self.rc.accounts.accounts_db.set_shrink_paths(paths); self.rc.accounts.accounts_db.set_shrink_paths(paths);
} }
fn load_accounts(
&self,
txs: &[Transaction],
iteration_order: Option<&[usize]>,
results: Vec<TransactionCheckResult>,
error_counters: &mut ErrorCounters,
) -> Vec<TransactionLoadResult> {
self.rc.accounts.load_accounts(
&self.ancestors,
txs,
iteration_order,
results,
&self.blockhash_queue.read().unwrap(),
error_counters,
&self.rent_collector,
&self.feature_set,
)
}
fn check_age( fn check_age(
&self, &self,
txs: &[Transaction], txs: &[Transaction],
@ -2904,11 +2885,15 @@ impl Bank {
max_age, max_age,
&mut error_counters, &mut error_counters,
); );
let mut loaded_accounts = self.load_accounts( let mut loaded_accounts = self.rc.accounts.load_accounts(
&self.ancestors,
txs, txs,
batch.iteration_order(), batch.iteration_order(),
sig_results, sig_results,
&self.blockhash_queue.read().unwrap(),
&mut error_counters, &mut error_counters,
&self.rent_collector,
&self.feature_set,
); );
load_time.stop(); load_time.stop();
@ -2926,13 +2911,17 @@ impl Bank {
.zip(OrderedIterator::new(txs, batch.iteration_order())) .zip(OrderedIterator::new(txs, batch.iteration_order()))
.map(|(accs, (_, tx))| match accs { .map(|(accs, (_, tx))| match accs {
(Err(e), _nonce_rollback) => (Err(e.clone()), None), (Err(e), _nonce_rollback) => (Err(e.clone()), None),
(Ok((accounts, account_deps, loaders, _rents)), nonce_rollback) => { (Ok(loaded_transaction), nonce_rollback) => {
signature_count += u64::from(tx.message().header.num_required_signatures); signature_count += u64::from(tx.message().header.num_required_signatures);
let executors = self.get_executors(&tx.message, &loaders); let executors = self.get_executors(&tx.message, &loaded_transaction.loaders);
let (account_refcells, account_dep_refcells, loader_refcells) = let (account_refcells, account_dep_refcells, loader_refcells) =
Self::accounts_to_refcells(accounts, account_deps, loaders); Self::accounts_to_refcells(
&mut loaded_transaction.accounts,
&mut loaded_transaction.account_deps,
&mut loaded_transaction.loaders,
);
let instruction_recorders = if enable_cpi_recording { let instruction_recorders = if enable_cpi_recording {
let ix_count = tx.message.instructions.len(); let ix_count = tx.message.instructions.len();
@ -2978,8 +2967,8 @@ impl Bank {
); );
Self::refcells_to_accounts( Self::refcells_to_accounts(
accounts, &mut loaded_transaction.accounts,
loaders, &mut loaded_transaction.loaders,
account_refcells, account_refcells,
loader_refcells, loader_refcells,
); );
@ -3372,9 +3361,9 @@ impl Bank {
continue; continue;
} }
let acc = raccs.as_ref().unwrap(); let loaded_transaction = raccs.as_ref().unwrap();
collected_rent += acc.3; collected_rent += loaded_transaction.rent;
} }
self.collected_rent.fetch_add(collected_rent, Relaxed); self.collected_rent.fetch_add(collected_rent, Relaxed);
@ -4402,12 +4391,12 @@ impl Bank {
} }
let message = &tx.message(); let message = &tx.message();
let acc = raccs.as_ref().unwrap(); let loaded_transaction = raccs.as_ref().unwrap();
for (pubkey, account) in message for (pubkey, account) in message
.account_keys .account_keys
.iter() .iter()
.zip(acc.0.iter()) .zip(loaded_transaction.accounts.iter())
.filter(|(_key, account)| (Stakes::is_stake(account))) .filter(|(_key, account)| (Stakes::is_stake(account)))
{ {
if Stakes::is_stake(account) { if Stakes::is_stake(account) {