Removes {get,set}_bank_hash_info_from_snapshot() (#30087)

This commit is contained in:
Brooks 2023-02-02 16:50:44 -05:00 committed by GitHub
parent 1570400612
commit 3249e4a123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 200 additions and 98 deletions

View File

@ -2379,15 +2379,15 @@ mod tests {
}
#[test]
fn test_accounts_empty_bank_hash() {
fn test_accounts_empty_bank_hash_stats() {
let accounts = Accounts::new_with_config_for_tests(
Vec::new(),
&ClusterType::Development,
AccountSecondaryIndexes::default(),
AccountShrinkThreshold::default(),
);
assert!(accounts.accounts_db.get_bank_hash_info(0).is_some());
assert!(accounts.accounts_db.get_bank_hash_info(1).is_none());
assert!(accounts.accounts_db.get_bank_hash_stats(0).is_some());
assert!(accounts.accounts_db.get_bank_hash_stats(1).is_none());
}
#[test]

View File

@ -7244,6 +7244,14 @@ impl AccountsDb {
.insert(slot, accounts_hash)
}
pub fn set_accounts_hash_from_snapshot(
&self,
slot: Slot,
accounts_hash: AccountsHash,
) -> Option<AccountsHash> {
self.set_accounts_hash(slot, accounts_hash)
}
/// Get the accounts hash for `slot` in the `accounts_hashes` map
pub fn get_accounts_hash(&self, slot: Slot) -> Option<AccountsHash> {
self.accounts_hashes.lock().unwrap().get(&slot).cloned()
@ -7647,6 +7655,14 @@ impl AccountsDb {
.insert(slot, accounts_delta_hash)
}
pub fn set_accounts_delta_hash_from_snapshot(
&self,
slot: Slot,
accounts_delta_hash: AccountsDeltaHash,
) -> Option<AccountsDeltaHash> {
self.set_accounts_delta_hash(slot, accounts_delta_hash)
}
/// Get the accounts delta hash for `slot` in the `accounts_delta_hashes` map
pub fn get_accounts_delta_hash(&self, slot: Slot) -> Option<AccountsDeltaHash> {
self.accounts_delta_hashes
@ -7656,18 +7672,23 @@ impl AccountsDb {
.cloned()
}
/// Set the bank hash stats for `slot` in the `bank_hash_stats` map
/// When reconstructing AccountsDb from a snapshot, insert the `bank_hash_stats` into the
/// internal bank hash stats map.
///
/// returns the previous bank hash stats for `slot`
fn set_bank_hash_stats(
/// This fn is only called when loading from a snapshot, which means AccountsDb is new and its
/// bank hash stats map is unpopulated. Except for slot 0.
///
/// Slot 0 is a special case. When a new AccountsDb is created--like when loading from a
/// snapshot--the bank hash stats map is populated with a default entry at slot 0. Remove the
/// default entry at slot 0, and then insert the new value at `slot`.
pub fn update_bank_hash_stats_from_snapshot(
&self,
slot: Slot,
bank_hash_stats: BankHashStats,
stats: BankHashStats,
) -> Option<BankHashStats> {
self.bank_hash_stats
.lock()
.unwrap()
.insert(slot, bank_hash_stats)
let mut bank_hash_stats = self.bank_hash_stats.lock().unwrap();
bank_hash_stats.remove(&0);
bank_hash_stats.insert(slot, stats)
}
/// Get the bank hash stats for `slot` in the `bank_hash_stats` map
@ -7675,60 +7696,6 @@ impl AccountsDb {
self.bank_hash_stats.lock().unwrap().get(&slot).cloned()
}
/// Set the "bank hash info" for `slot`
///
/// Internally this sets the accounts delta hash, the accounts hash, and the bank hash stats
/// from `bank_hash_info` for `slot` in their respective maps.
///
/// returns the previous accounts delta hash, accounts hash, and bank hash stats for `slot`
fn set_bank_hash_info(
&self,
slot: Slot,
bank_hash_info: BankHashInfo,
) -> (
Option<AccountsDeltaHash>,
Option<AccountsHash>,
Option<BankHashStats>,
) {
let BankHashInfo {
accounts_delta_hash,
accounts_hash,
stats,
} = bank_hash_info;
let old_accounts_delta_hash = self.set_accounts_delta_hash(slot, accounts_delta_hash);
let old_accounts_hash = self.set_accounts_hash(slot, accounts_hash);
let old_stats = self.set_bank_hash_stats(slot, stats);
(old_accounts_delta_hash, old_accounts_hash, old_stats)
}
/// When reconstructing AccountsDb from a snapshot, insert the `bank_hash_info` into the
/// internal bank hash info maps.
///
/// This fn is only called when loading from a snapshot, which means AccountsDb is new and its
/// bank hash info maps are unpopulated. Therefore, a bank hash info must not already exist at
/// `slot` [^1].
///
/// [^1] Slot 0 is a special case, however. When a new AccountsDb is created--like when
/// loading from a snapshot--the bank hash stats map is populated with a default entry at slot 0.
/// It is valid to have a snapshot at slot 0, so it must be handled accordingly.
pub fn set_bank_hash_info_from_snapshot(&self, slot: Slot, bank_hash_info: BankHashInfo) {
let (old_accounts_delta_hash, old_accounts_hash, old_stats) =
self.set_bank_hash_info(slot, bank_hash_info);
assert!(
old_accounts_delta_hash.is_none(),
"There should not already be an AccountsDeltaHash at slot {slot}: {old_accounts_delta_hash:?}",
);
assert!(
old_accounts_hash.is_none(),
"There should not already be an AccountsHash at slot {slot}: {old_accounts_hash:?}",
);
assert!(
old_stats.is_none() || (slot == 0 && old_stats == Some(BankHashStats::default())),
"There should not already be a BankHashStats at slot {slot}: {old_stats:?}",
);
}
/// Remove "bank hash info" for `slot`
///
/// This fn removes the accounts delta hash, accounts hash, and bank hash stats for `slot` from
@ -7753,33 +7720,6 @@ impl AccountsDb {
}
}
/// Get the "bank hash info" for `slot`
///
/// Internally this gets the accounts delta hash, the accounts hash, and the bank hash stats
/// for `slot` from their respective maps.
///
/// Only called by tests or serde_snapshot when serializing accounts db fields
pub fn get_bank_hash_info(&self, slot: Slot) -> Option<BankHashInfo> {
let Some(stats) = self.get_bank_hash_stats(slot) else {
return None;
};
// If there is a bank hash stats at this slot, then we'll return a `Some` regardless. Use
// default values for accounts hash and accounts delta hash if not found.
let accounts_hash = self
.get_accounts_hash(slot)
.unwrap_or_else(|| AccountsHash(Hash::default()));
let accounts_delta_hash = self
.get_accounts_delta_hash(slot)
.unwrap_or_else(|| AccountsDeltaHash(Hash::default()));
Some(BankHashInfo {
accounts_hash,
accounts_delta_hash,
stats,
})
}
fn update_index<'a, T: ReadableAccount + Sync>(
&self,
infos: Vec<AccountInfo>,
@ -9507,6 +9447,71 @@ pub mod tests {
pub fn set_accounts_hash_for_tests(&self, slot: Slot, accounts_hash: AccountsHash) {
self.set_accounts_hash(slot, accounts_hash);
}
/// Set the bank hash stats for `slot` in the `bank_hash_stats` map
///
/// returns the previous bank hash stats for `slot`
fn set_bank_hash_stats(
&self,
slot: Slot,
bank_hash_stats: BankHashStats,
) -> Option<BankHashStats> {
self.bank_hash_stats
.lock()
.unwrap()
.insert(slot, bank_hash_stats)
}
/// Set the "bank hash info" for `slot`
///
/// Internally this sets the accounts delta hash, the accounts hash, and the bank hash stats
/// from `bank_hash_info` for `slot` in their respective maps.
///
/// returns the previous accounts delta hash, accounts hash, and bank hash stats for `slot`
fn set_bank_hash_info(
&self,
slot: Slot,
bank_hash_info: BankHashInfo,
) -> (
Option<AccountsDeltaHash>,
Option<AccountsHash>,
Option<BankHashStats>,
) {
let BankHashInfo {
accounts_delta_hash,
accounts_hash,
stats,
} = bank_hash_info;
let old_accounts_delta_hash = self.set_accounts_delta_hash(slot, accounts_delta_hash);
let old_accounts_hash = self.set_accounts_hash(slot, accounts_hash);
let old_stats = self.set_bank_hash_stats(slot, stats);
(old_accounts_delta_hash, old_accounts_hash, old_stats)
}
/// Get the "bank hash info" for `slot`
///
/// Internally this gets the accounts delta hash, the accounts hash, and the bank hash stats
/// for `slot` from their respective maps.
fn get_bank_hash_info(&self, slot: Slot) -> Option<BankHashInfo> {
let Some(stats) = self.get_bank_hash_stats(slot) else {
return None;
};
// If there is a bank hash stats at this slot, then we'll return a `Some` regardless. Use
// default values for accounts hash and accounts delta hash if not found.
let accounts_hash = self
.get_accounts_hash(slot)
.unwrap_or_else(|| AccountsHash(Hash::default()));
let accounts_delta_hash = self
.get_accounts_delta_hash(slot)
.unwrap_or_else(|| AccountsDeltaHash(Hash::default()));
Some(BankHashInfo {
accounts_hash,
accounts_delta_hash,
stats,
})
}
}
/// This impl exists until this feature is activated:
@ -10886,6 +10891,9 @@ pub mod tests {
db.store_for_tests(new_root, &[(&key2, &account0)]);
db.add_root_and_flush_write_cache(new_root);
db.calculate_accounts_delta_hash(new_root);
db.update_accounts_hash_for_tests(new_root, &linear_ancestors(new_root), false, false);
// Simulate reconstruction from snapshot
let db = reconstruct_accounts_db_via_serialization(&db, new_root);
@ -12006,6 +12014,14 @@ pub mod tests {
accounts.clean_accounts_for_tests();
accounts.print_accounts_stats("accounts_post_purge");
accounts.calculate_accounts_delta_hash(current_slot);
accounts.update_accounts_hash_for_tests(
current_slot,
&linear_ancestors(current_slot),
false,
false,
);
let accounts = reconstruct_accounts_db_via_serialization(&accounts, current_slot);
accounts.print_accounts_stats("reconstructed");
@ -12056,6 +12072,7 @@ pub mod tests {
accounts.add_root_and_flush_write_cache(current_slot);
accounts.print_accounts_stats("pre_f");
accounts.calculate_accounts_delta_hash(current_slot);
accounts.update_accounts_hash_for_tests(4, &Ancestors::default(), false, false);
let accounts = f(accounts, current_slot);
@ -12854,6 +12871,13 @@ pub mod tests {
accounts.add_root_and_flush_write_cache(current_slot);
accounts.print_count_and_status("before reconstruct");
accounts.calculate_accounts_delta_hash(current_slot);
accounts.update_accounts_hash_for_tests(
current_slot,
&linear_ancestors(current_slot),
false,
false,
);
let accounts = reconstruct_accounts_db_via_serialization(&accounts, current_slot);
accounts.print_count_and_status("before purge zero");
accounts.clean_accounts_for_tests();
@ -13087,6 +13111,12 @@ pub mod tests {
// So, prevent that from happening by introducing refcount
((current_slot - 1)..=current_slot).for_each(|slot| accounts.flush_root_write_cache(slot));
accounts.clean_accounts_for_tests();
accounts.update_accounts_hash_for_tests(
current_slot,
&linear_ancestors(current_slot),
false,
false,
);
let accounts = reconstruct_accounts_db_via_serialization(&accounts, current_slot);
accounts.clean_accounts_for_tests();

View File

@ -718,7 +718,26 @@ where
);
// Process deserialized data, set necessary fields in self
accounts_db.set_bank_hash_info_from_snapshot(snapshot_slot, snapshot_bank_hash_info);
let old_accounts_delta_hash = accounts_db.set_accounts_delta_hash_from_snapshot(
snapshot_slot,
snapshot_bank_hash_info.accounts_delta_hash,
);
assert!(
old_accounts_delta_hash.is_none(),
"There should not already be an AccountsDeltaHash at slot {snapshot_slot}: {old_accounts_delta_hash:?}",
);
let old_accounts_hash = accounts_db
.set_accounts_hash_from_snapshot(snapshot_slot, snapshot_bank_hash_info.accounts_hash);
assert!(
old_accounts_hash.is_none(),
"There should not already be an AccountsHash at slot {snapshot_slot}: {old_accounts_hash:?}",
);
let old_stats = accounts_db
.update_bank_hash_stats_from_snapshot(snapshot_slot, snapshot_bank_hash_info.stats);
assert!(
old_stats.is_none(),
"There should not already be a BankHashStats at slot {snapshot_slot}: {old_stats:?}",
);
accounts_db.storage.initialize(storage);
accounts_db
.next_id

View File

@ -5,6 +5,7 @@ use {
*,
},
crate::{
accounts_db::BankHashInfo,
accounts_hash::AccountsHash,
ancestors::AncestorsForSerialization,
stakes::{serde_stakes_enum_compat, StakesEnum},
@ -270,10 +271,27 @@ impl<'a> TypeContext<'a> for Context {
)
}));
let slot = serializable_db.slot;
let bank_hash_info = serializable_db
let accounts_delta_hash = serializable_db
.accounts_db
.get_bank_hash_info(serializable_db.slot)
.unwrap_or_else(|| panic!("No bank_hashes entry for slot {}", serializable_db.slot));
.get_accounts_delta_hash(slot)
.unwrap_or_else(|| panic!("Missing accounts delta hash entry for slot {slot}"));
// NOTE: The accounts hash is calculated in AHV, which is *after* a bank snapshot is taken
// (and serialized here). Thus it is expected that an accounts hash is *not* found for
// this slot, and a placeholder value will be used instead. The real accounts hash will be
// set by `reserialize_bank_with_new_accounts_hash` from AHV.
let accounts_hash = serializable_db
.accounts_db
.get_accounts_hash(slot)
.unwrap_or_default();
let stats = serializable_db
.accounts_db
.get_bank_hash_stats(slot)
.unwrap_or_else(|| panic!("Missing bank hash stats entry for slot {slot}"));
let bank_hash_info = BankHashInfo {
accounts_delta_hash,
accounts_hash,
stats,
};
let historical_roots = serializable_db
.accounts_db

View File

@ -8,7 +8,7 @@ use {
accounts_db::{
get_temp_accounts_paths, test_utils::create_test_accounts, AccountShrinkThreshold,
},
accounts_hash::AccountsHash,
accounts_hash::{AccountsDeltaHash, AccountsHash},
append_vec::AppendVec,
bank::{Bank, BankTestConfig},
epoch_accounts_hash,
@ -25,6 +25,7 @@ use {
clock::Slot,
feature_set::{self, disable_fee_calculator},
genesis_config::{create_genesis_config, ClusterType},
hash::Hash,
pubkey::Pubkey,
signature::{Keypair, Signer},
},
@ -181,6 +182,11 @@ fn test_accounts_serialize_style(serde_style: SerdeStyle) {
create_test_accounts(&accounts, &mut pubkeys, 100, slot);
check_accounts(&accounts, &pubkeys, 100);
accounts.add_root(slot);
let accounts_delta_hash = accounts.accounts_db.calculate_accounts_delta_hash(slot);
let accounts_hash = AccountsHash(Hash::new_unique());
accounts
.accounts_db
.set_accounts_hash_from_snapshot(slot, accounts_hash);
let mut writer = Cursor::new(vec![]);
accountsdb_to_stream(
@ -211,9 +217,10 @@ fn test_accounts_serialize_style(serde_style: SerdeStyle) {
.unwrap(),
);
check_accounts(&daccounts, &pubkeys, 100);
let accounts_delta_hash = accounts.accounts_db.calculate_accounts_delta_hash(slot);
let daccounts_delta_hash = daccounts.accounts_db.calculate_accounts_delta_hash(slot);
assert_eq!(accounts_delta_hash, daccounts_delta_hash);
let daccounts_hash = daccounts.accounts_db.get_accounts_hash(slot);
assert_eq!(Some(accounts_hash), daccounts_hash);
}
fn test_bank_serialize_style(
@ -510,6 +517,15 @@ fn test_extra_fields_eof() {
let mut bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
add_root_and_flush_write_cache(&bank0);
bank.rc
.accounts
.accounts_db
.set_accounts_delta_hash_from_snapshot(bank.slot(), AccountsDeltaHash(Hash::new_unique()));
bank.rc
.accounts
.accounts_db
.set_accounts_hash_from_snapshot(bank.slot(), AccountsHash(Hash::new_unique()));
// Set extra fields
bank.fee_rate_governor.lamports_per_signature = 7000;
@ -637,6 +653,14 @@ fn test_blank_extra_fields() {
bank0.squash();
let mut bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
add_root_and_flush_write_cache(&bank0);
bank.rc
.accounts
.accounts_db
.set_accounts_delta_hash_from_snapshot(bank.slot(), AccountsDeltaHash(Hash::new_unique()));
bank.rc
.accounts
.accounts_db
.set_accounts_hash_from_snapshot(bank.slot(), AccountsHash(Hash::new_unique()));
// Set extra fields
bank.fee_rate_governor.lamports_per_signature = 7000;
@ -705,6 +729,17 @@ mod test_bank_serialize {
where
S: serde::Serializer,
{
bank.rc
.accounts
.accounts_db
.set_accounts_delta_hash_from_snapshot(
bank.slot(),
AccountsDeltaHash(Hash::new_unique()),
);
bank.rc
.accounts
.accounts_db
.set_accounts_hash_from_snapshot(bank.slot(), AccountsHash(Hash::new_unique()));
let snapshot_storages = bank
.rc
.accounts