Refactor: pull out fee payer balance check (#25519)

This commit is contained in:
buffalu 2022-05-25 05:44:03 -05:00 committed by GitHub
parent b7149f7f54
commit 7b98ff1929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 63 additions and 44 deletions

View File

@ -350,51 +350,15 @@ impl Accounts {
if payer_index != 0 {
warn!("Payer index should be 0! {:?}", tx);
}
let (ref payer_address, ref mut payer_account) = accounts[payer_index];
if payer_account.lamports() == 0 {
error_counters.account_not_found += 1;
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(NonceState::size())
}
};
if payer_account.lamports() < fee + min_balance {
error_counters.insufficient_funds += 1;
return Err(TransactionError::InsufficientFundsForFee);
}
let payer_pre_rent_state =
RentState::from_account(payer_account, &rent_collector.rent);
payer_account
.checked_sub_lamports(fee)
.map_err(|_| TransactionError::InsufficientFundsForFee)?;
let payer_post_rent_state =
RentState::from_account(payer_account, &rent_collector.rent);
let rent_state_result = check_rent_state_with_account(
&payer_pre_rent_state,
&payer_post_rent_state,
payer_address,
payer_account,
feature_set.is_active(&feature_set::do_support_realloc::id()),
feature_set
.is_active(&feature_set::include_account_index_in_rent_error::ID)
.then(|| payer_index),
);
// Feature gate only wraps the actual error return so that the metrics and debug
// logging generated by `check_rent_state_with_account()` can be examined before
// feature activation
if feature_set.is_active(&feature_set::require_rent_exempt_accounts::id()) {
rent_state_result?;
}
Self::check_fee_payer_balance(
&mut accounts,
payer_index,
error_counters,
rent_collector,
feature_set,
fee,
)?;
let program_indices = message
.instructions()
@ -408,6 +372,7 @@ impl Accounts {
)
})
.collect::<Result<Vec<Vec<usize>>>>()?;
Ok(LoadedTransaction {
accounts,
program_indices,
@ -421,6 +386,60 @@ impl Accounts {
}
}
fn check_fee_payer_balance(
accounts: &mut [(Pubkey, AccountSharedData)],
payer_index: usize,
error_counters: &mut TransactionErrorMetrics,
rent_collector: &RentCollector,
feature_set: &FeatureSet,
fee: u64,
) -> Result<()> {
let (ref payer_address, ref mut payer_account) = accounts[payer_index];
if payer_account.lamports() == 0 {
error_counters.account_not_found += 1;
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(NonceState::size())
}
};
if payer_account.lamports() < fee + min_balance {
error_counters.insufficient_funds += 1;
return Err(TransactionError::InsufficientFundsForFee);
}
let payer_pre_rent_state = RentState::from_account(payer_account, &rent_collector.rent);
payer_account
.checked_sub_lamports(fee)
.map_err(|_| TransactionError::InsufficientFundsForFee)?;
let payer_post_rent_state = RentState::from_account(payer_account, &rent_collector.rent);
let rent_state_result = check_rent_state_with_account(
&payer_pre_rent_state,
&payer_post_rent_state,
payer_address,
payer_account,
feature_set.is_active(&feature_set::do_support_realloc::id()),
feature_set
.is_active(&feature_set::include_account_index_in_rent_error::ID)
.then(|| payer_index),
);
// Feature gate only wraps the actual error return so that the metrics and debug
// logging generated by `check_rent_state_with_account()` can be examined before
// feature activation
if feature_set.is_active(&feature_set::require_rent_exempt_accounts::id()) {
rent_state_result?;
}
Ok(())
}
fn load_executable_accounts(
&self,
ancestors: &Ancestors,