Skip to content

Commit

Permalink
add test
Browse files Browse the repository at this point in the history
  • Loading branch information
HaoranYi committed Mar 1, 2024
1 parent 6b104a5 commit b0d8f7e
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 14 deletions.
18 changes: 9 additions & 9 deletions accounts-db/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6952,16 +6952,17 @@ impl AccountsDb {
/// those appenvec may not change between each hash calculation. Therefore,
/// we introduce the accounts hash cache to store the san result and reuse
/// them if the underlying appendvec didn't change.
pub fn calculate_accounts_lt_hash_from_index(&self, max_slot: Slot) -> AccountLTHash {
pub fn calculate_accounts_lt_hash_from_index(
&self,
ancestors: Option<&Ancestors>,
max_root: Option<Slot>,
) -> AccountLTHash {
let mut collect = Measure::start("lt_hash_collect");
let keys: Vec<_> = self
.accounts_index
.account_maps
.iter()
.flat_map(|map| {
let mut keys = map.keys();
keys
})
.flat_map(|map| map.keys())
.collect();
collect.stop();

Expand All @@ -6982,7 +6983,7 @@ impl AccountsDb {
let mut local_count = 0;
pubkeys.iter().for_each(|pubkey| {
if let AccountIndexGetResult::Found(lock, index) =
self.accounts_index.get(pubkey, None, Some(max_slot))
self.accounts_index.get(pubkey, ancestors, max_root)
{
let (slot, account_info) = &lock.slot_list()[index];
if !account_info.is_zero_lamport() {
Expand All @@ -7003,7 +7004,6 @@ impl AccountsDb {
)
.get_loaded_account()
{
let mut loaded_hash = loaded_account.loaded_hash();
let balance = loaded_account.lamports();
let lt_hash = loaded_account.compute_lt_hash(pubkey);
local_sum += balance as u128;
Expand Down Expand Up @@ -8123,12 +8123,12 @@ impl AccountsDb {
// consider what was written that changed.
let curr_ancestor = ancestors.clone();
ancestors.remove(&slot);
let old_written_accounts = old_written_accounts.read().unwrap();
let _old_written_accounts = old_written_accounts.read().unwrap();
// if we want to look it up ourselves: let (hashes, _scan_us, _accumulate) = self.get_pubkey_hash_for_slot(slot);
let old = pubkey_hash
.iter()
.map(|(k, _)| {
/// TODO: add optimization to cache lt_hash from last slot
// TODO: add optimization to cache lt_hash from last slot
//if let Some((account, hash)) = old_written_accounts.get(k) {
// Some(hash.unwrap()) // todo on demand calculate, calculate in bg
//} else {
Expand Down
5 changes: 3 additions & 2 deletions accounts-db/src/accounts_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1212,11 +1212,12 @@ impl<'a> AccountsHasher<'a> {

let _guard = self.active_stats.activate(ActiveStatItem::HashMerkleTree);
let mut hash_time = Measure::start("hash");
let mut accumulated = Hash::default();
// TODO
let mut _accumulated = Hash::default();
let mut i = 0;
while i < cumulative.total_count() {
let slice = cumulative.get_slice(i);
slice.iter().for_each(|hash| {
slice.iter().for_each(|_hash| {
// todo: accumulate here if we weren't able to do it earlier
// accumulated += hash
});
Expand Down
4 changes: 2 additions & 2 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ impl Bank {
.rc
.accounts
.accounts_db
.calculate_accounts_lt_hash_from_index(new.slot);
.calculate_accounts_lt_hash_from_index(None, Some(new.slot));
let mut w_lt_hash = new.accumulated_accounts_hash.write().unwrap();
*w_lt_hash = Some(lt_hash);
info!("finish computing lt_hash {} {}", new.slot, lt_hash);
Expand Down Expand Up @@ -6358,7 +6358,7 @@ impl Bank {
.unwrap()
.unwrap_or_default()
})
.unwrap_or_default(); // todo probably not default here
.unwrap_or_default();
self.rc.accounts.accounts_db.accumulate_accounts_lt_hash(
slot,
self.ancestors.clone(),
Expand Down
80 changes: 79 additions & 1 deletion runtime/src/bank/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10989,7 +10989,7 @@ fn test_rent_state_list_len() {
let num_accounts = tx.message().account_keys.len();
let sanitized_tx = SanitizedTransaction::try_from_legacy_transaction(tx).unwrap();
let mut error_counters = TransactionErrorMetrics::default();
let loaded_txs = load_accounts(
let loaded_txs = load_accounts::<crate::bank::Bank, AccountHash>(
&bank,
&[sanitized_tx.clone()],
&[(Ok(()), None, Some(0))],
Expand All @@ -10998,6 +10998,7 @@ fn test_rent_state_list_len() {
None,
&HashMap::new(),
&LoadedProgramsForTxBatch::default(),
&RwLock::new(HashMap::default()),
);

let compute_budget = bank.runtime_config.compute_budget.unwrap_or_else(|| {
Expand Down Expand Up @@ -13973,3 +13974,80 @@ fn test_failed_simulation_compute_units() {
let simulation = bank.simulate_transaction(&sanitized, false);
assert_eq!(expected_consumed_units, simulation.units_consumed);
}

#[test]
fn test_lt_hash_on_banks() {
let (genesis_config, _mint_keypair) = create_genesis_config(LAMPORTS_PER_SOL);

// Helper fn to compute full lattice hash from accounts db.
let compute_full_lt_hash = |bank: &Arc<Bank>| {
bank.rc
.accounts
.accounts_db
.calculate_accounts_lt_hash_from_index(Some(&bank.ancestors), None)
};

// Test genesis bank with default system accounts.
//
// Check that lattice hash is computed after `freeze`.
let bank0 = Bank::new_for_tests(&genesis_config);
let bank0 = Arc::new(bank0);
bank0.freeze();
let lt_hash0 = *bank0.accumulated_accounts_hash.read().unwrap();
assert!(!lt_hash0.is_none());

// Test bank1 with no user account update.
// In this case, it is simulating a bank with no transaction (i.e. full of
// empty ticks).
//
// 1. Check that lattice hash for bank1 is different from bank0 due to
// sysvar accounts changes.
// 2. Check that lattice hash computed in bank1 is the same as the full
// lattice hash computed from accounts db.
let bank1 = Arc::new(new_from_parent(bank0.clone()));
bank1.freeze();
let lt_hash1 = *bank1.accumulated_accounts_hash.read().unwrap();
assert_ne!(lt_hash1.unwrap(), lt_hash0.unwrap());
assert_eq!(lt_hash1.unwrap(), compute_full_lt_hash(&bank1));

// Test bank2 with simulated user account update.
//
// Check that lattice hash computed in bank2 is the same as the full lattice
// hash computed from accounts db.
let bank2 = Arc::new(new_from_parent(bank1.clone()));
let key = solana_sdk::pubkey::new_rand();
let account = AccountSharedData::new(100, 0, &system_program::id());
bank2.store_account(&key, &account);
bank2.freeze();
let lt_hash2 = *bank2.accumulated_accounts_hash.read().unwrap();
assert_eq!(lt_hash2.unwrap(), compute_full_lt_hash(&bank2));

// Test bank3 with account overwrite.
//
// bank3 store the same account as bank2 did. But it stored the same
// `account` twice, with the final account be the same as bank2. Check that
// bank3's final lattice hash should be the same as `bank2`.
let bank3 = Arc::new(new_from_parent(bank1.clone()));
let account = AccountSharedData::new(200, 0, &system_program::id());
bank3.store_account(&key, &account);
let account = AccountSharedData::new(100, 0, &system_program::id());
bank3.store_account(&key, &account);
bank3.freeze();
let lt_hash3 = *bank3.accumulated_accounts_hash.read().unwrap();
assert_eq!(lt_hash3.unwrap(), compute_full_lt_hash(&bank3));
assert_eq!(lt_hash3.unwrap(), lt_hash2.unwrap());

// Test bank4 with multiple user account update.
//
// Check that lattice hash computed in bank4 is the same as the full lattice
// hash computed from accounts db.
let bank4 = Arc::new(new_from_parent(bank1.clone()));
for i in 0..10 {
let key = solana_sdk::pubkey::new_rand();
let account = AccountSharedData::new(100 * i, 0, &system_program::id());
bank4.store_account(&key, &account);
}
bank4.freeze();
let lt_hash4 = *bank4.accumulated_accounts_hash.read().unwrap();
assert_eq!(lt_hash4.unwrap(), compute_full_lt_hash(&bank4));
}

0 comments on commit b0d8f7e

Please sign in to comment.