Prevent new RentPaying state created by paying fees (#23358)

* Add failing test

* Check fee-payer rent-state change on load

* Add more test cases

* Review comments
This commit is contained in:
Tyera Eulberg
2022-02-26 12:10:01 -07:00
committed by GitHub
parent 569d531573
commit 36484f4f08
3 changed files with 298 additions and 12 deletions

View File

@@ -1,5 +1,6 @@
use {
crate::{
account_rent_state::{check_rent_state_with_account, RentState},
accounts_db::{
AccountShrinkThreshold, AccountsAddRootTiming, AccountsDb, AccountsDbConfig,
BankHashInfo, ErrorCounters, LoadHint, LoadedAccount, ScanStorageResult,
@@ -342,7 +343,7 @@ impl Accounts {
if payer_index != 0 {
warn!("Payer index should be 0! {:?}", tx);
}
let payer_account = &mut accounts[payer_index].1;
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);
@@ -363,10 +364,27 @@ impl Accounts {
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 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?;
}
let program_indices = message
.instructions()
.iter()