Always and fully normalize stored 0-lamport accts. (#8657)
This commit is contained in:
parent
fb2620b3a5
commit
f146c92e88
|
@ -1033,22 +1033,25 @@ impl AccountsDB {
|
||||||
accounts: &[(&Pubkey, &Account)],
|
accounts: &[(&Pubkey, &Account)],
|
||||||
hashes: &[Hash],
|
hashes: &[Hash],
|
||||||
) -> Vec<AccountInfo> {
|
) -> Vec<AccountInfo> {
|
||||||
|
let default_account = Account::default();
|
||||||
|
|
||||||
let with_meta: Vec<(StoredMeta, &Account)> = accounts
|
let with_meta: Vec<(StoredMeta, &Account)> = accounts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(pubkey, account)| {
|
.map(|(pubkey, account)| {
|
||||||
let write_version = self.write_version.fetch_add(1, Ordering::Relaxed) as u64;
|
let write_version = self.write_version.fetch_add(1, Ordering::Relaxed) as u64;
|
||||||
let data_len = if account.lamports == 0 {
|
let account = if account.lamports == 0 {
|
||||||
0
|
&default_account
|
||||||
} else {
|
} else {
|
||||||
account.data.len() as u64
|
*account
|
||||||
};
|
};
|
||||||
|
let data_len = account.data.len() as u64;
|
||||||
|
|
||||||
let meta = StoredMeta {
|
let meta = StoredMeta {
|
||||||
write_version,
|
write_version,
|
||||||
pubkey: **pubkey,
|
pubkey: **pubkey,
|
||||||
data_len,
|
data_len,
|
||||||
};
|
};
|
||||||
|
(meta, account)
|
||||||
(meta, *account)
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let mut infos: Vec<AccountInfo> = Vec::with_capacity(with_meta.len());
|
let mut infos: Vec<AccountInfo> = Vec::with_capacity(with_meta.len());
|
||||||
|
|
|
@ -341,6 +341,7 @@ mod tests {
|
||||||
transaction::TransactionError,
|
transaction::TransactionError,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
impl From<Pubkey> for Address {
|
impl From<Pubkey> for Address {
|
||||||
fn from(address: Pubkey) -> Self {
|
fn from(address: Pubkey) -> Self {
|
||||||
|
@ -942,6 +943,78 @@ mod tests {
|
||||||
.is_ok());
|
.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]
|
#[test]
|
||||||
fn test_assign_with_seed() {
|
fn test_assign_with_seed() {
|
||||||
let (genesis_config, mint_keypair) = create_genesis_config(100);
|
let (genesis_config, mint_keypair) = create_genesis_config(100);
|
||||||
|
|
Loading…
Reference in New Issue