stop requiring data allocation to check for rent (#543)
This commit is contained in:
parent
9ea627c16d
commit
ccb09866b5
|
@ -8608,20 +8608,25 @@ impl AccountsDb {
|
|||
}
|
||||
|
||||
/// return Some(lamports_to_top_off) if 'account' would collect rent
|
||||
fn stats_for_rent_payers<T: ReadableAccount>(
|
||||
fn stats_for_rent_payers(
|
||||
pubkey: &Pubkey,
|
||||
account: &T,
|
||||
lamports: u64,
|
||||
account_data_len: usize,
|
||||
account_rent_epoch: Epoch,
|
||||
executable: bool,
|
||||
rent_collector: &RentCollector,
|
||||
) -> Option<u64> {
|
||||
if account.lamports() == 0 {
|
||||
if lamports == 0 {
|
||||
return None;
|
||||
}
|
||||
(rent_collector.should_collect_rent(pubkey, account)
|
||||
&& !rent_collector.get_rent_due(account).is_exempt())
|
||||
(rent_collector.should_collect_rent(pubkey, executable)
|
||||
&& !rent_collector
|
||||
.get_rent_due(lamports, account_data_len, account_rent_epoch)
|
||||
.is_exempt())
|
||||
.then(|| {
|
||||
let min_balance = rent_collector.rent.minimum_balance(account.data().len());
|
||||
let min_balance = rent_collector.rent.minimum_balance(account_data_len);
|
||||
// return lamports required to top off this account to make it rent exempt
|
||||
min_balance.saturating_sub(account.lamports())
|
||||
min_balance.saturating_sub(lamports)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -8661,9 +8666,14 @@ impl AccountsDb {
|
|||
accounts_data_len += stored_account.data().len() as u64;
|
||||
}
|
||||
|
||||
if let Some(amount_to_top_off_rent_this_account) =
|
||||
Self::stats_for_rent_payers(pubkey, &stored_account, rent_collector)
|
||||
{
|
||||
if let Some(amount_to_top_off_rent_this_account) = Self::stats_for_rent_payers(
|
||||
pubkey,
|
||||
stored_account.lamports(),
|
||||
stored_account.data().len(),
|
||||
stored_account.rent_epoch(),
|
||||
stored_account.executable(),
|
||||
rent_collector,
|
||||
) {
|
||||
amount_to_top_off_rent += amount_to_top_off_rent_this_account;
|
||||
num_accounts_rent_paying += 1;
|
||||
// remember this rent-paying account pubkey
|
||||
|
@ -9090,9 +9100,14 @@ impl AccountsDb {
|
|||
);
|
||||
let loaded_account = accessor.check_and_get_loaded_account();
|
||||
accounts_data_len_from_duplicates += loaded_account.data().len();
|
||||
if let Some(lamports_to_top_off) =
|
||||
Self::stats_for_rent_payers(pubkey, &loaded_account, rent_collector)
|
||||
{
|
||||
if let Some(lamports_to_top_off) = Self::stats_for_rent_payers(
|
||||
pubkey,
|
||||
loaded_account.lamports(),
|
||||
loaded_account.data().len(),
|
||||
loaded_account.rent_epoch(),
|
||||
loaded_account.executable(),
|
||||
rent_collector,
|
||||
) {
|
||||
removed_rent_paying += 1;
|
||||
removed_top_off += lamports_to_top_off;
|
||||
}
|
||||
|
|
|
@ -5165,7 +5165,11 @@ impl Bank {
|
|||
// account itself is rent-exempted but its `rent_epoch` is not u64::MAX, we will set its
|
||||
// `rent_epoch` to u64::MAX. In such case, the behavior stays the same as before.
|
||||
if account.rent_epoch() != RENT_EXEMPT_RENT_EPOCH
|
||||
&& self.rent_collector.get_rent_due(account) == RentDue::Exempt
|
||||
&& self.rent_collector.get_rent_due(
|
||||
account.lamports(),
|
||||
account.data().len(),
|
||||
account.rent_epoch(),
|
||||
) == RentDue::Exempt
|
||||
{
|
||||
account.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH);
|
||||
}
|
||||
|
@ -7803,8 +7807,14 @@ impl TotalAccountsStats {
|
|||
self.executable_data_len += data_len;
|
||||
}
|
||||
|
||||
if !rent_collector.should_collect_rent(address, account)
|
||||
|| rent_collector.get_rent_due(account).is_exempt()
|
||||
if !rent_collector.should_collect_rent(address, account.executable())
|
||||
|| rent_collector
|
||||
.get_rent_due(
|
||||
account.lamports(),
|
||||
account.data().len(),
|
||||
account.rent_epoch(),
|
||||
)
|
||||
.is_exempt()
|
||||
{
|
||||
self.num_rent_exempt_accounts += 1;
|
||||
} else {
|
||||
|
|
|
@ -73,21 +73,22 @@ impl RentCollector {
|
|||
}
|
||||
|
||||
/// true if it is easy to determine this account should consider having rent collected from it
|
||||
pub fn should_collect_rent(&self, address: &Pubkey, account: &impl ReadableAccount) -> bool {
|
||||
!(account.executable() // executable accounts must be rent-exempt balance
|
||||
pub fn should_collect_rent(&self, address: &Pubkey, executable: bool) -> bool {
|
||||
!(executable // executable accounts must be rent-exempt balance
|
||||
|| *address == incinerator::id())
|
||||
}
|
||||
|
||||
/// given an account that 'should_collect_rent'
|
||||
/// returns (amount rent due, is_exempt_from_rent)
|
||||
pub fn get_rent_due(&self, account: &impl ReadableAccount) -> RentDue {
|
||||
if self
|
||||
.rent
|
||||
.is_exempt(account.lamports(), account.data().len())
|
||||
{
|
||||
pub fn get_rent_due(
|
||||
&self,
|
||||
lamports: u64,
|
||||
data_len: usize,
|
||||
account_rent_epoch: Epoch,
|
||||
) -> RentDue {
|
||||
if self.rent.is_exempt(lamports, data_len) {
|
||||
RentDue::Exempt
|
||||
} else {
|
||||
let account_rent_epoch = account.rent_epoch();
|
||||
let slots_elapsed: u64 = (account_rent_epoch..=self.epoch)
|
||||
.map(|epoch| {
|
||||
self.epoch_schedule
|
||||
|
@ -103,7 +104,7 @@ impl RentCollector {
|
|||
};
|
||||
|
||||
// we know this account is not exempt
|
||||
let due = self.rent.due_amount(account.data().len(), years_elapsed);
|
||||
let due = self.rent.due_amount(data_len, years_elapsed);
|
||||
RentDue::Paying(due)
|
||||
}
|
||||
}
|
||||
|
@ -158,11 +159,15 @@ impl RentCollector {
|
|||
// Maybe collect rent later, leave account alone for now.
|
||||
return RentResult::NoRentCollectionNow;
|
||||
}
|
||||
if !self.should_collect_rent(address, account) {
|
||||
if !self.should_collect_rent(address, account.executable()) {
|
||||
// easy to determine this account should not consider having rent collected from it
|
||||
return RentResult::Exempt;
|
||||
}
|
||||
match self.get_rent_due(account) {
|
||||
match self.get_rent_due(
|
||||
account.lamports(),
|
||||
account.data().len(),
|
||||
account.rent_epoch(),
|
||||
) {
|
||||
// account will not have rent collected ever
|
||||
RentDue::Exempt => RentResult::Exempt,
|
||||
// potentially rent paying account
|
||||
|
|
|
@ -250,7 +250,11 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
|
|||
// account itself is rent-exempted but its `rent_epoch` is not u64::MAX, we will set its
|
||||
// `rent_epoch` to u64::MAX. In such case, the behavior stays the same as before.
|
||||
if account.rent_epoch() != RENT_EXEMPT_RENT_EPOCH
|
||||
&& rent_collector.get_rent_due(&account) == RentDue::Exempt
|
||||
&& rent_collector.get_rent_due(
|
||||
account.lamports(),
|
||||
account.data().len(),
|
||||
account.rent_epoch(),
|
||||
) == RentDue::Exempt
|
||||
{
|
||||
account.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue