Skip to content

Commit

Permalink
preserves rent_epoch for rent exempt accounts (backport #26479) (#26518)
Browse files Browse the repository at this point in the history
* names fields in RentResullt::CollectRent enum variant (#26449)

Avoiding ambiguous raw tuple:
    CollectRent((Epoch, u64))

Using named fields instead:
    CollectRent {
        new_rent_epoch: Epoch,
        rent_due: u64,
    },

(cherry picked from commit d7201a8)

# Conflicts:
#	runtime/src/bank.rs
#	runtime/src/expected_rent_collection.rs
#	runtime/src/rent_collector.rs

* removes mergify merge conflicts

* preserves rent_epoch for rent exempt accounts (#26479)

#22292
prevents rent paying account creation going forward. As a result
rent_epoch field for rent exempt accounts is redundant, and advancing
this field will incur expensive account rewrites and cause discrepancy
between accounts-db and cached vote/stake accounts.

This commit adds a feature which upon activation preserves rent_epoch
field for rent exempt accounts so that the field is frozen and is no
longer advanced.

(cherry picked from commit c99d9f0)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
  • Loading branch information
mergify[bot] and behzadnouri committed Jul 10, 2022
1 parent 4be121e commit 90ee0ba
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 81 deletions.
27 changes: 20 additions & 7 deletions runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ impl Accounts {
let mut accounts = Vec::with_capacity(account_keys.len());
let mut account_deps = Vec::with_capacity(account_keys.len());
let mut rent_debits = RentDebits::default();
let preserve_rent_epoch_for_rent_exempt_accounts = feature_set
.is_active(&feature_set::preserve_rent_epoch_for_rent_exempt_accounts::id());
for (i, key) in account_keys.iter().enumerate() {
let account = if !message.is_non_loader_key(i) {
// Fill in an empty account for the program slots.
Expand Down Expand Up @@ -286,6 +288,7 @@ impl Accounts {
key,
&mut account,
self.accounts_db.filler_account_suffix.as_ref(),
preserve_rent_epoch_for_rent_exempt_accounts,
)
.rent_amount;
(account, rent_due)
Expand Down Expand Up @@ -1161,16 +1164,17 @@ impl Accounts {
/// Store the accounts into the DB
// allow(clippy) needed for various gating flags
#[allow(clippy::too_many_arguments)]
pub fn store_cached<'a>(
pub(crate) fn store_cached(
&self,
slot: Slot,
txs: &'a [SanitizedTransaction],
res: &'a [TransactionExecutionResult],
loaded: &'a mut [TransactionLoadResult],
txs: &[SanitizedTransaction],
res: &[TransactionExecutionResult],
loaded: &mut [TransactionLoadResult],
rent_collector: &RentCollector,
durable_nonce: &(DurableNonce, /*separate_domains:*/ bool),
lamports_per_signature: u64,
leave_nonce_on_success: bool,
preserve_rent_epoch_for_rent_exempt_accounts: bool,
) {
let accounts_to_store = self.collect_accounts_to_store(
txs,
Expand All @@ -1180,6 +1184,7 @@ impl Accounts {
durable_nonce,
lamports_per_signature,
leave_nonce_on_success,
preserve_rent_epoch_for_rent_exempt_accounts,
);
self.accounts_db.store_cached(slot, &accounts_to_store);
}
Expand All @@ -1206,6 +1211,7 @@ impl Accounts {
durable_nonce: &(DurableNonce, /*separate_domains:*/ bool),
lamports_per_signature: u64,
leave_nonce_on_success: bool,
preserve_rent_epoch_for_rent_exempt_accounts: bool,
) -> Vec<(&'a Pubkey, &'a AccountSharedData)> {
let mut accounts = Vec::with_capacity(load_results.len());
for (i, ((tx_load_result, nonce), tx)) in load_results.iter_mut().zip(txs).enumerate() {
Expand Down Expand Up @@ -1264,7 +1270,11 @@ impl Accounts {
if execution_status.is_ok() || is_nonce_account || is_fee_payer {
if account.rent_epoch() == INITIAL_RENT_EPOCH {
let rent = rent_collector
.collect_from_created_account(address, account)
.collect_from_created_account(
address,
account,
preserve_rent_epoch_for_rent_exempt_accounts,
)
.rent_amount;
loaded_transaction.rent += rent;
loaded_transaction.rent_debits.insert(
Expand Down Expand Up @@ -1680,9 +1690,9 @@ mod tests {
feature_set.deactivate(&tx_wide_compute_cap::id());
let rent_collector = RentCollector::new(
0,
&EpochSchedule::default(),
EpochSchedule::default(),
500_000.0,
&Rent {
Rent {
lamports_per_byte_year: 42,
..Rent::default()
},
Expand Down Expand Up @@ -3002,6 +3012,7 @@ mod tests {
&(DurableNonce::default(), /*separate_domains:*/ true),
0,
true, // leave_nonce_on_success
true, // preserve_rent_epoch_for_rent_exempt_accounts
);
assert_eq!(collected_accounts.len(), 2);
assert!(collected_accounts
Expand Down Expand Up @@ -3501,6 +3512,7 @@ mod tests {
&(durable_nonce, /*separate_domains:*/ true),
0,
true, // leave_nonce_on_success
true, // preserve_rent_epoch_for_rent_exempt_accounts
);
assert_eq!(collected_accounts.len(), 2);
assert_eq!(
Expand Down Expand Up @@ -3629,6 +3641,7 @@ mod tests {
&(durable_nonce, /*separate_domains:*/ true),
0,
true, // leave_nonce_on_success
true, // preserve_rent_epoch_for_rent_exempt_accounts
);
assert_eq!(collected_accounts.len(), 1);
let collected_nonce_account = collected_accounts
Expand Down
7 changes: 4 additions & 3 deletions runtime/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5260,7 +5260,8 @@ impl AccountsDb {
)
}

pub fn update_accounts_hash_test(&self, slot: Slot, ancestors: &Ancestors) -> (Hash, u64) {
#[cfg(test)]
fn update_accounts_hash_test(&self, slot: Slot, ancestors: &Ancestors) -> (Hash, u64) {
self.update_accounts_hash_with_index_option(
true, true, slot, ancestors, None, false, None, false,
)
Expand Down Expand Up @@ -6972,9 +6973,9 @@ impl AccountsDb {
let schedule = genesis_config.epoch_schedule;
let rent_collector = RentCollector::new(
schedule.get_epoch(max_slot),
&schedule,
schedule,
genesis_config.slots_per_year(),
&genesis_config.rent,
genesis_config.rent,
);
let accounts_data_len = AtomicU64::new(0);

Expand Down
19 changes: 16 additions & 3 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3224,9 +3224,9 @@ impl Bank {

self.rent_collector = RentCollector::new(
self.epoch,
&self.epoch_schedule,
*self.epoch_schedule(),
self.slots_per_year,
&genesis_config.rent,
genesis_config.rent,
);

// Add additional builtin programs specified in the genesis config
Expand Down Expand Up @@ -4613,6 +4613,7 @@ impl Bank {
&durable_nonce,
lamports_per_signature,
self.leave_nonce_on_success(),
self.preserve_rent_epoch_for_rent_exempt_accounts(),
);
let rent_debits = self.collect_rent(&execution_results, loaded_txs);

Expand Down Expand Up @@ -4922,11 +4923,14 @@ impl Bank {
// parallelize?
let mut rent_debits = RentDebits::default();
let mut total_collected = CollectedInfo::default();
let preserve_rent_epoch_for_rent_exempt_accounts =
self.preserve_rent_epoch_for_rent_exempt_accounts();
for (pubkey, mut account) in accounts {
let collected = self.rent_collector.collect_from_existing_account(
&pubkey,
&mut account,
self.rc.accounts.accounts_db.filler_account_suffix.as_ref(),
preserve_rent_epoch_for_rent_exempt_accounts,
);
total_collected += collected;
// Store all of them unconditionally to purge old AppendVec,
Expand Down Expand Up @@ -6588,6 +6592,11 @@ impl Bank {
.is_active(&feature_set::send_to_tpu_vote_port::id())
}

fn preserve_rent_epoch_for_rent_exempt_accounts(&self) -> bool {
self.feature_set
.is_active(&feature_set::preserve_rent_epoch_for_rent_exempt_accounts::id())
}

pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
self.cost_tracker.read()
}
Expand Down Expand Up @@ -7428,6 +7437,7 @@ pub(crate) mod tests {
&keypairs[4].pubkey(),
&mut account_copy,
None,
true, // preserve_rent_epoch_for_rent_exempt_accounts
);
assert_eq!(expected_rent.rent_amount, too_few_lamports);
assert_eq!(account_copy.lamports(), 0);
Expand Down Expand Up @@ -8966,9 +8976,11 @@ pub(crate) mod tests {
bank.get_account(&rent_exempt_pubkey).unwrap().lamports(),
large_lamports
);
// Once preserve_rent_epoch_for_rent_exempt_accounts is activated,
// rent_epoch of rent-exempt accounts will no longer advance.
assert_eq!(
bank.get_account(&rent_exempt_pubkey).unwrap().rent_epoch(),
current_epoch
0
);
assert_eq!(
bank.slots_by_pubkey(&rent_due_pubkey, &ancestors),
Expand Down Expand Up @@ -18150,6 +18162,7 @@ pub(crate) mod tests {
&keypair.pubkey(),
&mut account,
None,
true, // preserve_rent_epoch_for_rent_exempt_accounts
);
assert_eq!(info.account_data_len_reclaimed, data_size as u64);
}
Expand Down
Loading

0 comments on commit 90ee0ba

Please sign in to comment.