From 03b596586c759b1e0d7afdf461b8938f5c33a59a Mon Sep 17 00:00:00 2001 From: HaoranYi Date: Tue, 16 Apr 2024 16:04:52 -0500 Subject: [PATCH] Write default hash to account storage (#469) * write default hash to apendvec * fix get_pubkey_hash_for_slot * fix tests * fix rebase error --------- Co-authored-by: HaoranYi --- accounts-db/src/accounts_db.rs | 8 +++++--- accounts-db/src/append_vec.rs | 7 ++++--- runtime/tests/accounts.rs | 28 ++++++++++++++++++++++++---- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index b71603b4d8..b7a674746a 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -10215,14 +10215,16 @@ pub mod tests { ); #[test] - #[should_panic(expected = "MismatchedAccountsHash")] fn test_accountsdb_scan_snapshot_stores_check_hash() { solana_logger::setup(); let accounts_db = AccountsDb::new_single_for_tests(); let (storages, _raw_expected) = sample_storages_and_accounts(&accounts_db); let max_slot = storages.iter().map(|storage| storage.slot()).max().unwrap(); - let hash = + // bogus_hash is ignored during appendvec store. When we verify hashes + // later during scan, the test will recompute the "correct" hash and + // should not mismatch. + let bogus_hash = AccountHash(Hash::from_str("7JcmM6TFZMkcDkZe6RKVkGaWwN5dXciGC4fa3RxvqQc9").unwrap()); // replace the sample storages, storing bogus hash values so that we trigger the hash mismatch @@ -10242,7 +10244,7 @@ pub mod tests { .collect::>(); let slice = &accounts[..]; let account_data = (slot, slice); - let hashes = (0..account_data.len()).map(|_| &hash).collect(); + let hashes = (0..account_data.len()).map(|_| &bogus_hash).collect(); let storable_accounts = StorableAccountsWithHashes::new_with_hashes(&account_data, hashes); copied_storage diff --git a/accounts-db/src/append_vec.rs b/accounts-db/src/append_vec.rs index c7feb0eaee..b963dee3df 100644 --- a/accounts-db/src/append_vec.rs +++ b/accounts-db/src/append_vec.rs @@ -20,6 +20,7 @@ use { solana_sdk::{ account::{AccountSharedData, ReadableAccount, WritableAccount}, clock::Slot, + hash::Hash, pubkey::Pubkey, stake_history::Epoch, }, @@ -752,8 +753,8 @@ impl AppendVec { skip: usize, ) -> Option> { let _lock = self.append_lock.lock().unwrap(); + let default_hash: Hash = Hash::default(); // [0_u8; 32]; let mut offset = self.len(); - let len = accounts.accounts.len(); // Here we have `len - skip` number of accounts. The +1 extra capacity // is for storing the aligned offset of the last entry to that is used @@ -765,7 +766,7 @@ impl AppendVec { if stop { break; } - accounts.get(i, |account, hash| { + accounts.get(i, |account, _hash| { let account_meta = AccountMeta { lamports: account.lamports(), owner: *account.owner(), @@ -782,7 +783,7 @@ impl AppendVec { let account_meta_ptr = &account_meta as *const AccountMeta; let data_len = stored_meta.data_len as usize; let data_ptr = account.data().as_ptr(); - let hash_ptr = bytemuck::bytes_of(hash).as_ptr(); + let hash_ptr = bytemuck::bytes_of(&default_hash).as_ptr(); let ptrs = [ (meta_ptr as *const u8, mem::size_of::()), (account_meta_ptr as *const u8, mem::size_of::()), diff --git a/runtime/tests/accounts.rs b/runtime/tests/accounts.rs index 549839be5f..bcb6f7746a 100644 --- a/runtime/tests/accounts.rs +++ b/runtime/tests/accounts.rs @@ -4,11 +4,13 @@ use { rayon::prelude::*, solana_accounts_db::{ accounts_db::{AccountsDb, LoadHint}, + accounts_hash::AccountHash, ancestors::Ancestors, }, solana_sdk::{ account::{AccountSharedData, ReadableAccount, WritableAccount}, clock::Slot, + hash::Hash, pubkey::Pubkey, sysvar::epoch_schedule::EpochSchedule, }, @@ -128,11 +130,29 @@ fn test_bad_bank_hash() { db.store_cached((some_slot, &account_refs[..]), None); for pass in 0..2 { for (key, account) in &account_refs { - assert_eq!( - db.load_account_hash(&ancestors, key, Some(some_slot), LoadHint::Unspecified) + if pass == 1 { + assert_eq!( + db.load_account_hash( + &ancestors, + key, + Some(some_slot), + LoadHint::Unspecified + ) .unwrap(), - AccountsDb::hash_account(*account, key) - ); + AccountHash(Hash::default()) + ); + } else { + assert_eq!( + db.load_account_hash( + &ancestors, + key, + Some(some_slot), + LoadHint::Unspecified + ) + .unwrap(), + AccountsDb::hash_account(*account, key) + ); + } } if pass == 0 { // flush the write cache so we're reading from append vecs on the next iteration