Always and fully normalize stored 0-lamport accts. (#8657)

This commit is contained in:
Michael Vines 2020-03-05 09:14:40 -07:00 committed by GitHub
parent fb2620b3a5
commit f146c92e88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 5 deletions

View File

@ -1033,22 +1033,25 @@ impl AccountsDB {
accounts: &[(&Pubkey, &Account)],
hashes: &[Hash],
) -> Vec<AccountInfo> {
let default_account = Account::default();
let with_meta: Vec<(StoredMeta, &Account)> = accounts
.iter()
.map(|(pubkey, account)| {
let write_version = self.write_version.fetch_add(1, Ordering::Relaxed) as u64;
let data_len = if account.lamports == 0 {
0
let account = if account.lamports == 0 {
&default_account
} else {
account.data.len() as u64
*account
};
let data_len = account.data.len() as u64;
let meta = StoredMeta {
write_version,
pubkey: **pubkey,
data_len,
};
(meta, *account)
(meta, account)
})
.collect();
let mut infos: Vec<AccountInfo> = Vec::with_capacity(with_meta.len());

View File

@ -341,6 +341,7 @@ mod tests {
transaction::TransactionError,
};
use std::cell::RefCell;
use std::sync::Arc;
impl From<Pubkey> for Address {
fn from(address: Pubkey) -> Self {
@ -942,6 +943,78 @@ mod tests {
.is_ok());
}
fn with_create_zero_lamport<F>(callback: F)
where
F: Fn(&Bank) -> (),
{
solana_logger::setup();
let alice_keypair = Keypair::new();
let bob_keypair = Keypair::new();
let alice_pubkey = alice_keypair.pubkey();
let bob_pubkey = bob_keypair.pubkey();
let program = Pubkey::new_rand();
let collector = Pubkey::new_rand();
let mint_lamports = 10000;
let len1 = 123;
let len2 = 456;
// create initial bank and fund the alice account
let (genesis_config, mint_keypair) = create_genesis_config(mint_lamports);
let bank = Arc::new(Bank::new(&genesis_config));
let bank_client = BankClient::new_shared(&bank);
bank_client
.transfer(mint_lamports, &mint_keypair, &alice_pubkey)
.unwrap();
// create zero-lamports account to be cleaned
let bank = Arc::new(Bank::new_from_parent(&bank, &collector, bank.slot() + 1));
let bank_client = BankClient::new_shared(&bank);
let ix = system_instruction::create_account(&alice_pubkey, &bob_pubkey, 0, len1, &program);
let message = Message::new(vec![ix]);
let r = bank_client.send_message(&[&alice_keypair, &bob_keypair], message);
assert!(r.is_ok());
// transfer some to bogus pubkey just to make previous bank (=slot) really cleanable
let bank = Arc::new(Bank::new_from_parent(&bank, &collector, bank.slot() + 1));
let bank_client = BankClient::new_shared(&bank);
bank_client
.transfer(50, &alice_keypair, &Pubkey::new_rand())
.unwrap();
// super fun time; callback chooses to .clean_accounts() or not
callback(&*bank);
// create a normal account at the same pubkey as the zero-lamports account
let bank = Arc::new(Bank::new_from_parent(&bank, &collector, bank.slot() + 1));
let bank_client = BankClient::new_shared(&bank);
let ix = system_instruction::create_account(&alice_pubkey, &bob_pubkey, 1, len2, &program);
let message = Message::new(vec![ix]);
let r = bank_client.send_message(&[&alice_keypair, &bob_keypair], message);
assert!(r.is_ok());
}
#[test]
fn test_create_zero_lamport_with_clean() {
with_create_zero_lamport(|bank| {
bank.squash();
// do clean and assert that it actually did its job
assert_eq!(3, bank.get_snapshot_storages().len());
bank.clean_accounts();
assert_eq!(2, bank.get_snapshot_storages().len());
});
}
#[test]
fn test_create_zero_lamport_without_clean() {
with_create_zero_lamport(|_| {
// just do nothing; this should behave identically with test_create_zero_lamport_with_clean
});
}
#[test]
fn test_assign_with_seed() {
let (genesis_config, mint_keypair) = create_genesis_config(100);