Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test permutations of set_exempt_rent_epoch_max #29461

Merged
merged 1 commit into from
Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 138 additions & 132 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7983,7 +7983,6 @@ pub(crate) mod tests {
genesis_sysvar_and_builtin_program_lamports, GenesisConfigInfo,
ValidatorVoteKeypairs,
},
rent_collector::TEST_SET_EXEMPT_RENT_EPOCH_MAX,
rent_paying_accounts_by_partition::RentPayingAccountsByPartition,
status_cache::MAX_CACHE_ENTRIES,
},
Expand Down Expand Up @@ -8401,113 +8400,116 @@ pub(crate) mod tests {
/// one thing being tested here is that a failed tx (due to rent collection using up all lamports) followed by rent collection
/// results in the same state as if just rent collection ran (and emptied the accounts that have too few lamports)
fn test_credit_debit_rent_no_side_effect_on_hash() {
solana_logger::setup();
for set_exempt_rent_epoch_max in [false, true] {
solana_logger::setup();

let (mut genesis_config, _mint_keypair) = create_genesis_config(10);
let (mut genesis_config, _mint_keypair) = create_genesis_config(10);

genesis_config.rent = rent_with_exemption_threshold(21.0);
genesis_config.rent = rent_with_exemption_threshold(21.0);

let slot = years_as_slots(
2.0,
&genesis_config.poh_config.target_tick_duration,
genesis_config.ticks_per_slot,
) as u64;
let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
let bank = Bank::new_from_parent(&root_bank, &Pubkey::default(), slot);
let slot = years_as_slots(
2.0,
&genesis_config.poh_config.target_tick_duration,
genesis_config.ticks_per_slot,
) as u64;
let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
let bank = Bank::new_from_parent(&root_bank, &Pubkey::default(), slot);

let root_bank_2 = Arc::new(Bank::new_for_tests(&genesis_config));
let bank_with_success_txs = Bank::new_from_parent(&root_bank_2, &Pubkey::default(), slot);
let root_bank_2 = Arc::new(Bank::new_for_tests(&genesis_config));
let bank_with_success_txs =
Bank::new_from_parent(&root_bank_2, &Pubkey::default(), slot);

assert_eq!(bank.last_blockhash(), genesis_config.hash());
assert_eq!(bank.last_blockhash(), genesis_config.hash());

let plenty_of_lamports = 264;
let too_few_lamports = 10;
// Initialize credit-debit and credit only accounts
let accounts = [
AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
// Transaction between these two accounts will fail
AccountSharedData::new(too_few_lamports, 0, &Pubkey::default()),
AccountSharedData::new(too_few_lamports, 1, &Pubkey::default()),
];
let plenty_of_lamports = 264;
let too_few_lamports = 10;
// Initialize credit-debit and credit only accounts
let accounts = [
AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
// Transaction between these two accounts will fail
AccountSharedData::new(too_few_lamports, 0, &Pubkey::default()),
AccountSharedData::new(too_few_lamports, 1, &Pubkey::default()),
];

let keypairs = accounts.iter().map(|_| Keypair::new()).collect::<Vec<_>>();
{
// make sure rent and epoch change are such that we collect all lamports in accounts 4 & 5
let mut account_copy = accounts[4].clone();
let expected_rent = bank.rent_collector().collect_from_existing_account(
&keypairs[4].pubkey(),
&mut account_copy,
None,
TEST_SET_EXEMPT_RENT_EPOCH_MAX,
);
assert_eq!(expected_rent.rent_amount, too_few_lamports);
assert_eq!(account_copy.lamports(), 0);
}
let keypairs = accounts.iter().map(|_| Keypair::new()).collect::<Vec<_>>();
{
// make sure rent and epoch change are such that we collect all lamports in accounts 4 & 5
let mut account_copy = accounts[4].clone();
let expected_rent = bank.rent_collector().collect_from_existing_account(
&keypairs[4].pubkey(),
&mut account_copy,
None,
set_exempt_rent_epoch_max,
);
assert_eq!(expected_rent.rent_amount, too_few_lamports);
assert_eq!(account_copy.lamports(), 0);
}

for i in 0..accounts.len() {
let account = &accounts[i];
bank.store_account(&keypairs[i].pubkey(), account);
bank_with_success_txs.store_account(&keypairs[i].pubkey(), account);
}
for i in 0..accounts.len() {
let account = &accounts[i];
bank.store_account(&keypairs[i].pubkey(), account);
bank_with_success_txs.store_account(&keypairs[i].pubkey(), account);
}

// Make builtin instruction loader rent exempt
let system_program_id = system_program::id();
let mut system_program_account = bank.get_account(&system_program_id).unwrap();
system_program_account.set_lamports(
bank.get_minimum_balance_for_rent_exemption(system_program_account.data().len()),
);
bank.store_account(&system_program_id, &system_program_account);
bank_with_success_txs.store_account(&system_program_id, &system_program_account);
// Make builtin instruction loader rent exempt
let system_program_id = system_program::id();
let mut system_program_account = bank.get_account(&system_program_id).unwrap();
system_program_account.set_lamports(
bank.get_minimum_balance_for_rent_exemption(system_program_account.data().len()),
);
bank.store_account(&system_program_id, &system_program_account);
bank_with_success_txs.store_account(&system_program_id, &system_program_account);

let t1 = system_transaction::transfer(
&keypairs[0],
&keypairs[1].pubkey(),
1,
genesis_config.hash(),
);
let t2 = system_transaction::transfer(
&keypairs[2],
&keypairs[3].pubkey(),
1,
genesis_config.hash(),
);
// the idea is this transaction will result in both accounts being drained of all lamports due to rent collection
let t3 = system_transaction::transfer(
&keypairs[4],
&keypairs[5].pubkey(),
1,
genesis_config.hash(),
);
let t1 = system_transaction::transfer(
&keypairs[0],
&keypairs[1].pubkey(),
1,
genesis_config.hash(),
);
let t2 = system_transaction::transfer(
&keypairs[2],
&keypairs[3].pubkey(),
1,
genesis_config.hash(),
);
// the idea is this transaction will result in both accounts being drained of all lamports due to rent collection
let t3 = system_transaction::transfer(
&keypairs[4],
&keypairs[5].pubkey(),
1,
genesis_config.hash(),
);

let txs = vec![t1.clone(), t2.clone(), t3];
let res = bank.process_transactions(txs.iter());
let txs = vec![t1.clone(), t2.clone(), t3];
let res = bank.process_transactions(txs.iter());

assert_eq!(res.len(), 3);
assert_eq!(res[0], Ok(()));
assert_eq!(res[1], Ok(()));
assert_eq!(res[2], Err(TransactionError::AccountNotFound));
assert_eq!(res.len(), 3);
assert_eq!(res[0], Ok(()));
assert_eq!(res[1], Ok(()));
assert_eq!(res[2], Err(TransactionError::AccountNotFound));

bank.freeze();
bank.freeze();

let rwlockguard_bank_hash = bank.hash.read().unwrap();
let bank_hash = rwlockguard_bank_hash.as_ref();
let rwlockguard_bank_hash = bank.hash.read().unwrap();
let bank_hash = rwlockguard_bank_hash.as_ref();

let txs = vec![t2, t1];
let res = bank_with_success_txs.process_transactions(txs.iter());
let txs = vec![t2, t1];
let res = bank_with_success_txs.process_transactions(txs.iter());

assert_eq!(res.len(), 2);
assert_eq!(res[0], Ok(()));
assert_eq!(res[1], Ok(()));
assert_eq!(res.len(), 2);
assert_eq!(res[0], Ok(()));
assert_eq!(res[1], Ok(()));

bank_with_success_txs.freeze();
bank_with_success_txs.freeze();

let rwlockguard_bank_with_success_txs_hash = bank_with_success_txs.hash.read().unwrap();
let bank_with_success_txs_hash = rwlockguard_bank_with_success_txs_hash.as_ref();
let rwlockguard_bank_with_success_txs_hash = bank_with_success_txs.hash.read().unwrap();
let bank_with_success_txs_hash = rwlockguard_bank_with_success_txs_hash.as_ref();

assert_eq!(bank_with_success_txs_hash, bank_hash);
assert_eq!(bank_with_success_txs_hash, bank_hash);
}
}

fn store_accounts_for_rent_test(
Expand Down Expand Up @@ -20012,55 +20014,59 @@ pub(crate) mod tests {
/// Ensure that accounts data size is updated correctly by rent collection
#[test]
fn test_accounts_data_size_and_rent_collection() {
let GenesisConfigInfo {
mut genesis_config, ..
} = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SOL);
genesis_config.rent = Rent::default();
activate_all_features(&mut genesis_config);
let bank = Arc::new(Bank::new_for_tests(&genesis_config));
let bank = Arc::new(Bank::new_from_parent(
&bank,
&Pubkey::default(),
bank.slot() + bank.slot_count_per_normal_epoch(),
));
for set_exempt_rent_epoch_max in [false, true] {
let GenesisConfigInfo {
mut genesis_config, ..
} = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SOL);
genesis_config.rent = Rent::default();
activate_all_features(&mut genesis_config);
let bank = Arc::new(Bank::new_for_tests(&genesis_config));
let bank = Arc::new(Bank::new_from_parent(
&bank,
&Pubkey::default(),
bank.slot() + bank.slot_count_per_normal_epoch(),
));

// make another bank so that any reclaimed accounts from the previous bank do not impact
// this test
let bank = Arc::new(Bank::new_from_parent(
&bank,
&Pubkey::default(),
bank.slot() + bank.slot_count_per_normal_epoch(),
));
// make another bank so that any reclaimed accounts from the previous bank do not impact
// this test
let bank = Arc::new(Bank::new_from_parent(
&bank,
&Pubkey::default(),
bank.slot() + bank.slot_count_per_normal_epoch(),
));

// Store an account into the bank that is rent-paying and has data
let data_size = 123;
let mut account = AccountSharedData::new(1, data_size, &Pubkey::default());
let keypair = Keypair::new();
bank.store_account(&keypair.pubkey(), &account);
// Store an account into the bank that is rent-paying and has data
let data_size = 123;
let mut account = AccountSharedData::new(1, data_size, &Pubkey::default());
let keypair = Keypair::new();
bank.store_account(&keypair.pubkey(), &account);

// Ensure if we collect rent from the account that it will be reclaimed
{
let info = bank.rent_collector.collect_from_existing_account(
&keypair.pubkey(),
&mut account,
None,
TEST_SET_EXEMPT_RENT_EPOCH_MAX,
);
assert_eq!(info.account_data_len_reclaimed, data_size as u64);
}
// Ensure if we collect rent from the account that it will be reclaimed
{
let info = bank.rent_collector.collect_from_existing_account(
&keypair.pubkey(),
&mut account,
None,
set_exempt_rent_epoch_max,
);
assert_eq!(info.account_data_len_reclaimed, data_size as u64);
}

// Collect rent for real
let accounts_data_size_delta_before_collecting_rent = bank.load_accounts_data_size_delta();
bank.collect_rent_eagerly();
let accounts_data_size_delta_after_collecting_rent = bank.load_accounts_data_size_delta();
// Collect rent for real
let accounts_data_size_delta_before_collecting_rent =
bank.load_accounts_data_size_delta();
bank.collect_rent_eagerly();
let accounts_data_size_delta_after_collecting_rent =
bank.load_accounts_data_size_delta();

let accounts_data_size_delta_delta = accounts_data_size_delta_after_collecting_rent
- accounts_data_size_delta_before_collecting_rent;
assert!(accounts_data_size_delta_delta < 0);
let reclaimed_data_size = accounts_data_size_delta_delta.saturating_neg() as usize;
let accounts_data_size_delta_delta = accounts_data_size_delta_after_collecting_rent
- accounts_data_size_delta_before_collecting_rent;
assert!(accounts_data_size_delta_delta < 0);
let reclaimed_data_size = accounts_data_size_delta_delta.saturating_neg() as usize;

// Ensure the account is reclaimed by rent collection
assert_eq!(reclaimed_data_size, data_size,);
// Ensure the account is reclaimed by rent collection
assert_eq!(reclaimed_data_size, data_size,);
}
}

#[test]
Expand Down
Loading