Refactoring: Unify account_deps and accounts (#17898)

* Changes ThisInvokeContext::get_account() to use accounts instead of pre_accounts.

* Adds explicit keys to accounts to make them symmetric to account_deps.

* Appends account_deps to accounts in transaction loading and removes account_deps everywhere else.
This commit is contained in:
Alexander Meißner
2021-07-05 13:49:37 +02:00
committed by GitHub
parent ffb1f3932a
commit 7462c27d07
7 changed files with 289 additions and 308 deletions

View File

@@ -97,14 +97,12 @@ pub struct Accounts {
}
// for the load instructions
pub type TransactionAccounts = Vec<AccountSharedData>;
pub type TransactionAccountDeps = Vec<(Pubkey, AccountSharedData)>;
pub type TransactionAccounts = Vec<(Pubkey, AccountSharedData)>;
pub type TransactionRent = u64;
pub type TransactionLoaders = Vec<Vec<(Pubkey, AccountSharedData)>>;
#[derive(PartialEq, Debug, Clone)]
pub struct LoadedTransaction {
pub accounts: TransactionAccounts,
pub account_deps: TransactionAccountDeps,
pub loaders: TransactionLoaders,
pub rent: TransactionRent,
pub rent_debits: RentDebits,
@@ -277,36 +275,43 @@ impl Accounts {
// Fill in an empty account for the program slots.
AccountSharedData::default()
};
accounts.push(account);
accounts.push((*key, account));
}
debug_assert_eq!(accounts.len(), message.account_keys.len());
// Appends the account_deps at the end of the accounts,
// this way they can be accessed in a uniform way.
// At places where only the accounts are needed,
// the account_deps are truncated using e.g:
// accounts.iter().take(message.account_keys.len())
accounts.append(&mut account_deps);
if let Some(payer_index) = payer_index {
if payer_index != 0 {
warn!("Payer index should be 0! {:?}", tx);
}
if accounts[payer_index].lamports() == 0 {
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(&accounts[payer_index])
.ok_or_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())
}
};
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 accounts[payer_index].lamports() < fee + min_balance {
if payer_account.lamports() < fee + min_balance {
error_counters.insufficient_funds += 1;
Err(TransactionError::InsufficientFundsForFee)
} else {
accounts[payer_index]
payer_account
.checked_sub_lamports(fee)
.map_err(|_| TransactionError::InsufficientFundsForFee)?;
@@ -329,7 +334,6 @@ impl Accounts {
.collect::<Result<TransactionLoaders>>()?;
Ok(LoadedTransaction {
accounts,
account_deps,
loaders,
rent: tx_rent,
rent_debits,
@@ -992,12 +996,9 @@ impl Accounts {
let message = &tx.message();
let loaded_transaction = raccs.as_mut().unwrap();
let mut fee_payer_index = None;
for ((i, key), account) in message
.account_keys
.iter()
.enumerate()
for (i, (key, account)) in (0..message.account_keys.len())
.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(
account,
@@ -1035,7 +1036,7 @@ impl Accounts {
.rent_debits
.push(key, rent, account.lamports());
}
accounts.push((key, &*account));
accounts.push((&*key, &*account));
}
}
}
@@ -1377,7 +1378,7 @@ mod tests {
assert_eq!(loaded_accounts.len(), 1);
let (load_res, _nonce_rollback) = &loaded_accounts[0];
let loaded_transaction = load_res.as_ref().unwrap();
assert_eq!(loaded_transaction.accounts[0].lamports(), min_balance);
assert_eq!(loaded_transaction.accounts[0].1.lamports(), min_balance);
// Fee leaves zero balance fails
accounts[0].1.set_lamports(min_balance);
@@ -1439,7 +1440,7 @@ mod tests {
match &loaded_accounts[0] {
(Ok(loaded_transaction), _nonce_rollback) => {
assert_eq!(loaded_transaction.accounts.len(), 3);
assert_eq!(loaded_transaction.accounts[0], accounts[0].1);
assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
assert_eq!(loaded_transaction.loaders.len(), 1);
assert_eq!(loaded_transaction.loaders[0].len(), 0);
}
@@ -1662,7 +1663,7 @@ mod tests {
match &loaded_accounts[0] {
(Ok(loaded_transaction), _nonce_rollback) => {
assert_eq!(loaded_transaction.accounts.len(), 3);
assert_eq!(loaded_transaction.accounts[0], accounts[0].1);
assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
assert_eq!(loaded_transaction.loaders.len(), 2);
assert_eq!(loaded_transaction.loaders[0].len(), 1);
assert_eq!(loaded_transaction.loaders[1].len(), 2);
@@ -1970,6 +1971,9 @@ mod tests {
let keypair0 = Keypair::new();
let keypair1 = Keypair::new();
let pubkey = solana_sdk::pubkey::new_rand();
let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
let rent_collector = RentCollector::default();
@@ -1982,6 +1986,10 @@ mod tests {
Hash::default(),
instructions,
);
let transaction_accounts0 = vec![
(message.account_keys[0], account0),
(message.account_keys[1], account2.clone()),
];
let tx0 = Transaction::new(&[&keypair0], message, Hash::default());
let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
@@ -1993,22 +2001,19 @@ mod tests {
Hash::default(),
instructions,
);
let transaction_accounts1 = vec![
(message.account_keys[0], account1),
(message.account_keys[1], account2),
];
let tx1 = Transaction::new(&[&keypair1], message, Hash::default());
let txs = vec![tx0, tx1];
let loaders = vec![(Ok(()), None), (Ok(()), None)];
let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
let transaction_accounts0 = vec![account0, account2.clone()];
let transaction_loaders0 = vec![];
let transaction_rent0 = 0;
let loaded0 = (
Ok(LoadedTransaction {
accounts: transaction_accounts0,
account_deps: vec![],
loaders: transaction_loaders0,
rent: transaction_rent0,
rent_debits: RentDebits::default(),
@@ -2016,13 +2021,11 @@ mod tests {
None,
);
let transaction_accounts1 = vec![account1, account2];
let transaction_loaders1 = vec![];
let transaction_rent1 = 0;
let loaded1 = (
Ok(LoadedTransaction {
accounts: transaction_accounts1,
account_deps: vec![],
loaders: transaction_loaders1,
rent: transaction_rent1,
rent_debits: RentDebits::default(),
@@ -2046,6 +2049,7 @@ mod tests {
.unwrap()
.insert_new_readonly(&pubkey);
}
let txs = &[tx0, tx1];
let collected_accounts = accounts.collect_accounts_to_store(
txs.iter(),
&loaders,
@@ -2349,16 +2353,34 @@ mod tests {
let from = keypair_from_seed(&[1; 32]).unwrap();
let from_address = from.pubkey();
let to_address = Pubkey::new_unique();
let nonce_state =
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
authority: nonce_authority.pubkey(),
blockhash: Hash::new_unique(),
fee_calculator: FeeCalculator::default(),
}));
let nonce_account_post =
AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
let from_account_post = AccountSharedData::new(4199, 0, &Pubkey::default());
let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
let instructions = vec![
system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
system_instruction::transfer(&from_address, &to_address, 42),
];
let message = Message::new(&instructions, Some(&from_address));
let blockhash = Hash::new_unique();
let transaction_accounts = vec![
(message.account_keys[0], from_account_post),
(message.account_keys[1], nonce_authority_account),
(message.account_keys[2], nonce_account_post),
(message.account_keys[3], to_account),
(message.account_keys[4], recent_blockhashes_sysvar_account),
];
let tx = Transaction::new(&[&nonce_authority, &from], message, blockhash);
let txs = vec![tx];
let nonce_state =
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
authority: nonce_authority.pubkey(),
@@ -2382,33 +2404,11 @@ mod tests {
nonce_rollback.clone(),
)];
let nonce_state =
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
authority: nonce_authority.pubkey(),
blockhash: Hash::new_unique(),
fee_calculator: FeeCalculator::default(),
}));
let nonce_account_post =
AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
let from_account_post = AccountSharedData::new(4199, 0, &Pubkey::default());
let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
let transaction_accounts = vec![
from_account_post,
nonce_authority_account,
nonce_account_post,
to_account,
recent_blockhashes_sysvar_account,
];
let transaction_loaders = vec![];
let transaction_rent = 0;
let loaded = (
Ok(LoadedTransaction {
accounts: transaction_accounts,
account_deps: vec![],
loaders: transaction_loaders,
rent: transaction_rent,
rent_debits: RentDebits::default(),
@@ -2426,6 +2426,7 @@ mod tests {
false,
AccountShrinkThreshold::default(),
);
let txs = &[tx];
let collected_accounts = accounts.collect_accounts_to_store(
txs.iter(),
&loaders,
@@ -2470,16 +2471,34 @@ mod tests {
let from = keypair_from_seed(&[1; 32]).unwrap();
let from_address = from.pubkey();
let to_address = Pubkey::new_unique();
let nonce_state =
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
authority: nonce_authority.pubkey(),
blockhash: Hash::new_unique(),
fee_calculator: FeeCalculator::default(),
}));
let nonce_account_post =
AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
let from_account_post = AccountSharedData::new(4200, 0, &Pubkey::default());
let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
let instructions = vec![
system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
system_instruction::transfer(&from_address, &to_address, 42),
];
let message = Message::new(&instructions, Some(&nonce_address));
let blockhash = Hash::new_unique();
let transaction_accounts = vec![
(message.account_keys[0], from_account_post),
(message.account_keys[1], nonce_authority_account),
(message.account_keys[2], nonce_account_post),
(message.account_keys[3], to_account),
(message.account_keys[4], recent_blockhashes_sysvar_account),
];
let tx = Transaction::new(&[&nonce_authority, &from], message, blockhash);
let txs = vec![tx];
let nonce_state =
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
authority: nonce_authority.pubkey(),
@@ -2502,33 +2521,11 @@ mod tests {
nonce_rollback.clone(),
)];
let nonce_state =
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
authority: nonce_authority.pubkey(),
blockhash: Hash::new_unique(),
fee_calculator: FeeCalculator::default(),
}));
let nonce_account_post =
AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
let from_account_post = AccountSharedData::new(4200, 0, &Pubkey::default());
let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
let transaction_accounts = vec![
from_account_post,
nonce_authority_account,
nonce_account_post,
to_account,
recent_blockhashes_sysvar_account,
];
let transaction_loaders = vec![];
let transaction_rent = 0;
let loaded = (
Ok(LoadedTransaction {
accounts: transaction_accounts,
account_deps: vec![],
loaders: transaction_loaders,
rent: transaction_rent,
rent_debits: RentDebits::default(),
@@ -2546,6 +2543,7 @@ mod tests {
false,
AccountShrinkThreshold::default(),
);
let txs = &[tx];
let collected_accounts = accounts.collect_accounts_to_store(
txs.iter(),
&loaders,