change RentResult enum values (#29139)
* test_shrink_candidate_slots uses write cache (#29145) * add tests for collect_from_existing_account
This commit is contained in:
parent
06a806bb9d
commit
3d268be800
|
@ -35,12 +35,14 @@ impl Default for RentCollector {
|
||||||
/// when rent is collected for this account, this is the action to apply to the account
|
/// when rent is collected for this account, this is the action to apply to the account
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum RentResult {
|
enum RentResult {
|
||||||
/// maybe collect rent later, leave account alone
|
/// this account will never have rent collected from it
|
||||||
LeaveAloneNoRent,
|
Exempt,
|
||||||
|
/// maybe we collect rent later, but not now
|
||||||
|
NoRentCollectionNow,
|
||||||
/// collect rent
|
/// collect rent
|
||||||
CollectRent {
|
CollectRent {
|
||||||
new_rent_epoch: Epoch,
|
new_rent_epoch: Epoch,
|
||||||
rent_due: u64, // lamports
|
rent_due: u64, // lamports, could be 0
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +129,7 @@ impl RentCollector {
|
||||||
filler_account_suffix: Option<&Pubkey>,
|
filler_account_suffix: Option<&Pubkey>,
|
||||||
) -> CollectedInfo {
|
) -> CollectedInfo {
|
||||||
match self.calculate_rent_result(address, account, filler_account_suffix) {
|
match self.calculate_rent_result(address, account, filler_account_suffix) {
|
||||||
RentResult::LeaveAloneNoRent => CollectedInfo::default(),
|
RentResult::Exempt | RentResult::NoRentCollectionNow => CollectedInfo::default(),
|
||||||
RentResult::CollectRent {
|
RentResult::CollectRent {
|
||||||
new_rent_epoch,
|
new_rent_epoch,
|
||||||
rent_due,
|
rent_due,
|
||||||
|
@ -159,15 +161,26 @@ impl RentCollector {
|
||||||
account: &impl ReadableAccount,
|
account: &impl ReadableAccount,
|
||||||
filler_account_suffix: Option<&Pubkey>,
|
filler_account_suffix: Option<&Pubkey>,
|
||||||
) -> RentResult {
|
) -> RentResult {
|
||||||
if self.can_skip_rent_collection(address, account, filler_account_suffix) {
|
if account.rent_epoch() > self.epoch {
|
||||||
return RentResult::LeaveAloneNoRent;
|
// potentially rent paying account
|
||||||
|
// Maybe collect rent later, leave account alone for now.
|
||||||
|
return RentResult::NoRentCollectionNow;
|
||||||
|
}
|
||||||
|
if !self.should_collect_rent(address, account)
|
||||||
|
|| crate::accounts_db::AccountsDb::is_filler_account_helper(
|
||||||
|
address,
|
||||||
|
filler_account_suffix,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// 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) {
|
||||||
// Rent isn't collected for the next epoch.
|
// account will not have rent collected ever
|
||||||
// Make sure to check exempt status again later in current epoch.
|
RentDue::Exempt => RentResult::Exempt,
|
||||||
RentDue::Exempt => RentResult::LeaveAloneNoRent,
|
// potentially rent paying account
|
||||||
// Maybe collect rent later, leave account alone.
|
// Maybe collect rent later, leave account alone for now.
|
||||||
RentDue::Paying(0) => RentResult::LeaveAloneNoRent,
|
RentDue::Paying(0) => RentResult::NoRentCollectionNow,
|
||||||
// Rent is collected for next epoch.
|
// Rent is collected for next epoch.
|
||||||
RentDue::Paying(rent_due) => RentResult::CollectRent {
|
RentDue::Paying(rent_due) => RentResult::CollectRent {
|
||||||
new_rent_epoch: self.epoch + 1,
|
new_rent_epoch: self.epoch + 1,
|
||||||
|
@ -175,21 +188,6 @@ impl RentCollector {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs easy checks to see if rent collection can be skipped
|
|
||||||
fn can_skip_rent_collection(
|
|
||||||
&self,
|
|
||||||
address: &Pubkey,
|
|
||||||
account: &impl ReadableAccount,
|
|
||||||
filler_account_suffix: Option<&Pubkey>,
|
|
||||||
) -> bool {
|
|
||||||
!self.should_collect_rent(address, account)
|
|
||||||
|| account.rent_epoch() > self.epoch
|
|
||||||
|| crate::accounts_db::AccountsDb::is_filler_account_helper(
|
|
||||||
address,
|
|
||||||
filler_account_suffix,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information computed during rent collection
|
/// Information computed during rent collection
|
||||||
|
@ -244,6 +242,164 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_calculate_rent_result() {
|
||||||
|
let mut rent_collector = RentCollector::default();
|
||||||
|
|
||||||
|
let mut account = AccountSharedData::default();
|
||||||
|
assert!(matches!(
|
||||||
|
rent_collector.calculate_rent_result(&Pubkey::default(), &account, None),
|
||||||
|
RentResult::NoRentCollectionNow,
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut account_clone,
|
||||||
|
None
|
||||||
|
),
|
||||||
|
CollectedInfo::default()
|
||||||
|
);
|
||||||
|
assert_eq!(account_clone, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
account.set_executable(true);
|
||||||
|
assert!(matches!(
|
||||||
|
rent_collector.calculate_rent_result(&Pubkey::default(), &account, None),
|
||||||
|
RentResult::Exempt
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut account_clone,
|
||||||
|
None
|
||||||
|
),
|
||||||
|
CollectedInfo::default()
|
||||||
|
);
|
||||||
|
assert_eq!(account_clone, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
account.set_executable(false);
|
||||||
|
assert!(matches!(
|
||||||
|
rent_collector.calculate_rent_result(&incinerator::id(), &account, None),
|
||||||
|
RentResult::Exempt
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&incinerator::id(),
|
||||||
|
&mut account_clone,
|
||||||
|
None
|
||||||
|
),
|
||||||
|
CollectedInfo::default()
|
||||||
|
);
|
||||||
|
assert_eq!(account_clone, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try a few combinations of rent collector rent epoch and collecting rent with and without filler accounts specified (but we aren't a filler)
|
||||||
|
let filler_account = solana_sdk::pubkey::new_rand();
|
||||||
|
|
||||||
|
for filler_accounts in [None, Some(&filler_account)] {
|
||||||
|
for (rent_epoch, rent_due_expected) in [(2, 2), (3, 5)] {
|
||||||
|
rent_collector.epoch = rent_epoch;
|
||||||
|
account.set_lamports(10);
|
||||||
|
account.set_rent_epoch(1);
|
||||||
|
let new_rent_epoch_expected = rent_collector.epoch + 1;
|
||||||
|
assert!(
|
||||||
|
matches!(
|
||||||
|
rent_collector.calculate_rent_result(&Pubkey::default(), &account, filler_accounts),
|
||||||
|
RentResult::CollectRent{ new_rent_epoch, rent_due} if new_rent_epoch == new_rent_epoch_expected && rent_due == rent_due_expected,
|
||||||
|
),
|
||||||
|
"{:?}",
|
||||||
|
rent_collector.calculate_rent_result(&Pubkey::default(), &account, None)
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut account_clone,
|
||||||
|
filler_accounts
|
||||||
|
),
|
||||||
|
CollectedInfo {
|
||||||
|
rent_amount: rent_due_expected,
|
||||||
|
account_data_len_reclaimed: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let mut account_expected = account.clone();
|
||||||
|
account_expected.set_lamports(account.lamports() - rent_due_expected);
|
||||||
|
account_expected.set_rent_epoch(new_rent_epoch_expected);
|
||||||
|
assert_eq!(account_clone, account_expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enough lamports to make us exempt
|
||||||
|
account.set_lamports(1_000_000);
|
||||||
|
assert!(matches!(
|
||||||
|
rent_collector.calculate_rent_result(&Pubkey::default(), &account, None),
|
||||||
|
RentResult::Exempt,
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut account_clone,
|
||||||
|
None
|
||||||
|
),
|
||||||
|
CollectedInfo::default()
|
||||||
|
);
|
||||||
|
assert_eq!(account_clone, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// enough lamports to make us exempt
|
||||||
|
// but, our rent_epoch is set in the future, so we can't know if we are exempt yet or not.
|
||||||
|
// We don't calculate rent amount vs data if the rent_epoch is already in the future.
|
||||||
|
account.set_rent_epoch(1_000_000);
|
||||||
|
assert!(matches!(
|
||||||
|
rent_collector.calculate_rent_result(&Pubkey::default(), &account, None),
|
||||||
|
RentResult::NoRentCollectionNow,
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut account_clone,
|
||||||
|
None
|
||||||
|
),
|
||||||
|
CollectedInfo::default()
|
||||||
|
);
|
||||||
|
assert_eq!(account_clone, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filler accounts are exempt
|
||||||
|
account.set_rent_epoch(1);
|
||||||
|
account.set_lamports(10);
|
||||||
|
assert!(matches!(
|
||||||
|
rent_collector.calculate_rent_result(&filler_account, &account, Some(&filler_account)),
|
||||||
|
RentResult::Exempt,
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let mut account_clone = account.clone();
|
||||||
|
assert_eq!(
|
||||||
|
rent_collector.collect_from_existing_account(
|
||||||
|
&filler_account,
|
||||||
|
&mut account_clone,
|
||||||
|
Some(&filler_account)
|
||||||
|
),
|
||||||
|
CollectedInfo::default()
|
||||||
|
);
|
||||||
|
assert_eq!(account_clone, account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collect_from_account_created_and_existing() {
|
fn test_collect_from_account_created_and_existing() {
|
||||||
let old_lamports = 1000;
|
let old_lamports = 1000;
|
||||||
|
|
Loading…
Reference in New Issue