diff --git a/accounts-db/src/account_storage/meta.rs b/accounts-db/src/account_storage/meta.rs index d01f7b55fbfb73..4f6a40a92d6d86 100644 --- a/accounts-db/src/account_storage/meta.rs +++ b/accounts-db/src/account_storage/meta.rs @@ -1,5 +1,6 @@ use { crate::{ + accounts_hash::AccountHash, append_vec::AppendVecStoredAccountMeta, storable_accounts::StorableAccounts, tiered_storage::{hot::HotAccountMeta, readable::TieredReadableAccount}, @@ -17,7 +18,7 @@ pub struct StoredAccountInfo { } lazy_static! { - static ref DEFAULT_ACCOUNT_HASH: Hash = Hash::default(); + static ref DEFAULT_ACCOUNT_HASH: AccountHash = AccountHash(Hash::default()); } /// Goal is to eliminate copies and data reshaping given various code paths that store accounts. @@ -30,7 +31,7 @@ pub struct StorableAccountsWithHashesAndWriteVersions< 'b, T: ReadableAccount + Sync + 'b, U: StorableAccounts<'a, T>, - V: Borrow, + V: Borrow, > { /// accounts to store /// always has pubkey and account @@ -41,8 +42,13 @@ pub struct StorableAccountsWithHashesAndWriteVersions< _phantom: PhantomData<&'a T>, } -impl<'a: 'b, 'b, T: ReadableAccount + Sync + 'b, U: StorableAccounts<'a, T>, V: Borrow> - StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V> +impl< + 'a: 'b, + 'b, + T: ReadableAccount + Sync + 'b, + U: StorableAccounts<'a, T>, + V: Borrow, + > StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V> { /// used when accounts contains hash and write version already pub fn new(accounts: &'b U) -> Self { @@ -71,12 +77,12 @@ impl<'a: 'b, 'b, T: ReadableAccount + Sync + 'b, U: StorableAccounts<'a, T>, V: } /// get all account fields at 'index' - pub fn get(&self, index: usize) -> (Option<&T>, &Pubkey, &Hash, StoredMetaWriteVersion) { + pub fn get(&self, index: usize) -> (Option<&T>, &Pubkey, &AccountHash, StoredMetaWriteVersion) { let account = self.accounts.account_default_if_zero_lamport(index); let pubkey = self.accounts.pubkey(index); let (hash, write_version) = if self.accounts.has_hash_and_write_version() { ( - &self.accounts.hash(index).0, + self.accounts.hash(index), self.accounts.write_version(index), ) } else { @@ -119,11 +125,12 @@ impl<'storage> StoredAccountMeta<'storage> { } } - pub fn hash(&self) -> &'storage Hash { - match self { + pub fn hash(&self) -> &'storage AccountHash { + let hash = match self { Self::AppendVec(av) => av.hash(), - Self::Hot(hot) => hot.hash().unwrap_or(&DEFAULT_ACCOUNT_HASH), - } + Self::Hot(hot) => hot.hash().unwrap_or(&DEFAULT_ACCOUNT_HASH.0), + }; + bytemuck::cast_ref(hash) } pub fn stored_size(&self) -> usize { diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index 6ccd88349d533d..ea08df0e245735 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -384,7 +384,7 @@ impl CurrentAncientAppendVec { INCLUDE_SLOT_IN_HASH_IRRELEVANT_APPEND_VEC_OPERATION, accounts_to_store.slot, ), - None::>, + None::>, self.append_vec(), None, StoreReclaims::Ignore, @@ -896,7 +896,7 @@ pub enum LoadedAccount<'a> { impl<'a> LoadedAccount<'a> { pub fn loaded_hash(&self) -> AccountHash { match self { - LoadedAccount::Stored(stored_account_meta) => AccountHash(*stored_account_meta.hash()), + LoadedAccount::Stored(stored_account_meta) => *stored_account_meta.hash(), LoadedAccount::Cached(cached_account) => cached_account.hash(), } } @@ -4126,7 +4126,7 @@ impl AccountsDb { &shrink_collect.alive_accounts.alive_accounts()[..], INCLUDE_SLOT_IN_HASH_IRRELEVANT_APPEND_VEC_OPERATION, ), - None::>, + None::>, shrink_in_progress.new_storage(), None, StoreReclaims::Ignore, @@ -6245,7 +6245,7 @@ impl AccountsDb { 'b, T: ReadableAccount + Sync, U: StorableAccounts<'a, T>, - V: Borrow, + V: Borrow, >( &self, slot: Slot, @@ -6612,7 +6612,7 @@ impl AccountsDb { let pubkeys = self.get_filler_account_pubkeys(filler_accounts as usize); pubkeys.iter().for_each(|key| { accounts.push((key, &account)); - hashes.push(hash); + hashes.push(AccountHash(hash)); }); self.store_accounts_frozen( (slot, &accounts[..], include_slot_in_hash), @@ -6684,7 +6684,9 @@ impl AccountsDb { INCLUDE_SLOT_IN_HASH_IRRELEVANT_APPEND_VEC_OPERATION, ); let storable = - StorableAccountsWithHashesAndWriteVersions::<'_, '_, _, _, &Hash>::new(&to_store); + StorableAccountsWithHashesAndWriteVersions::<'_, '_, _, _, &AccountHash>::new( + &to_store, + ); storage.accounts.append_accounts(&storable, 0); Arc::new(storage) @@ -6796,7 +6798,7 @@ impl AccountsDb { >( &self, accounts: &'c impl StorableAccounts<'b, T>, - hashes: Option>>, + hashes: Option>>, mut write_version_producer: P, store_to: &StoreTo, transactions: Option<&[Option<&'a SanitizedTransaction>]>, @@ -6836,7 +6838,7 @@ impl AccountsDb { self.write_accounts_to_storage( slot, storage, - &StorableAccountsWithHashesAndWriteVersions::<'_, '_, _, _, &Hash>::new( + &StorableAccountsWithHashesAndWriteVersions::<'_, '_, _, _, &AccountHash>::new( accounts, ), ) @@ -8544,7 +8546,7 @@ impl AccountsDb { // we use default hashes for now since the same account may be stored to the cache multiple times self.store_accounts_unfrozen( accounts, - None::>, + None::>, store_to, transactions, reclaim, @@ -8698,7 +8700,7 @@ impl AccountsDb { fn store_accounts_unfrozen<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>( &self, accounts: impl StorableAccounts<'a, T>, - hashes: Option>>, + hashes: Option>>, store_to: &StoreTo, transactions: Option<&'a [Option<&'a SanitizedTransaction>]>, reclaim: StoreReclaims, @@ -8727,7 +8729,7 @@ impl AccountsDb { pub fn store_accounts_frozen<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>( &self, accounts: impl StorableAccounts<'a, T>, - hashes: Option>>, + hashes: Option>>, storage: &Arc, write_version_producer: Option>>, reclaim: StoreReclaims, @@ -8751,7 +8753,7 @@ impl AccountsDb { fn store_accounts_custom<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>( &self, accounts: impl StorableAccounts<'a, T>, - hashes: Option>>, + hashes: Option>>, write_version_producer: Option>>, store_to: &StoreTo, reset_accounts: bool, @@ -9085,6 +9087,7 @@ impl AccountsDb { } /// return 'AccountSharedData' and a hash for a filler account + /// bprumo TODO: return AccountHash instead? fn get_filler_account(&self, rent: &Rent) -> (AccountSharedData, Hash) { let string = "FiLLERACCoUNTooooooooooooooooooooooooooooooo"; let hash = Hash::from_str(string).unwrap(); @@ -10114,7 +10117,10 @@ pub mod tests { let expected_accounts_data_len = data.last().unwrap().1.data().len(); let expected_alive_bytes = aligned_stored_size(expected_accounts_data_len); let storable = (slot0, &data[..], INCLUDE_SLOT_IN_HASH_TESTS); - let hashes = data.iter().map(|_| Hash::default()).collect::>(); + let hashes = data + .iter() + .map(|_| AccountHash(Hash::default())) + .collect::>(); let write_versions = data.iter().map(|_| 0).collect::>(); let append = StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions( @@ -10608,7 +10614,7 @@ pub mod tests { accounts_db.storage.remove(&storage.slot(), false); }); - let hash = Hash::default(); + let hash = AccountHash(Hash::default()); // replace the sample storages, storing default hash values so that we rehash during scan let storages = storages @@ -10655,7 +10661,8 @@ pub mod tests { sample_storages_and_accounts(&accounts_db, INCLUDE_SLOT_IN_HASH_TESTS); let max_slot = storages.iter().map(|storage| storage.slot()).max().unwrap(); - let hash = Hash::from_str("7JcmM6TFZMkcDkZe6RKVkGaWwN5dXciGC4fa3RxvqQc9").unwrap(); + let hash = + AccountHash(Hash::from_str("7JcmM6TFZMkcDkZe6RKVkGaWwN5dXciGC4fa3RxvqQc9").unwrap()); // replace the sample storages, storing bogus hash values so that we trigger the hash mismatch let storages = storages @@ -11158,7 +11165,7 @@ pub mod tests { let accounts = [(pubkey, account)]; let slice = &accounts[..]; let account_data = (slot, slice); - let hash = Hash::default(); + let hash = AccountHash(Hash::default()); let storable_accounts = StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions( &account_data, @@ -12758,7 +12765,7 @@ pub mod tests { // put wrong hash value in store so we get a mismatch db.store_accounts_unfrozen( (some_slot, &[(&key, &account)][..]), - Some(vec![&Hash::default()]), + Some(vec![&AccountHash(Hash::default())]), &StoreTo::Storage(&db.find_storage_candidate(some_slot, 1)), None, StoreReclaims::Default, @@ -12992,7 +12999,7 @@ pub mod tests { db.update_accounts_hash_for_tests(some_slot, &ancestors, false, false); // provide bogus account hashes - let some_hash = Hash::new(&[0xca; HASH_BYTES]); + let some_hash = AccountHash(Hash::new(&[0xca; HASH_BYTES])); db.store_accounts_unfrozen( (some_slot, accounts), Some(vec![&some_hash]), @@ -15830,7 +15837,7 @@ pub mod tests { accounts.accounts_index.set_startup(Startup::Startup); let storage = accounts.create_and_insert_store(slot0, 4_000, "flush_slot_cache"); - let hashes = vec![Hash::default(); 1]; + let hashes = vec![AccountHash(Hash::default()); 1]; let write_version = vec![0; 1]; storage.accounts.append_accounts( &StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions( @@ -15895,7 +15902,7 @@ pub mod tests { let account_big = AccountSharedData::new(1, 1000, AccountSharedData::default().owner()); let slot0 = 0; let storage = accounts.create_and_insert_store(slot0, 4_000, "flush_slot_cache"); - let hashes = vec![Hash::default(); 2]; + let hashes = vec![AccountHash(Hash::default()); 2]; let write_version = vec![0; 2]; storage.accounts.append_accounts( &StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions( diff --git a/accounts-db/src/accounts_file.rs b/accounts-db/src/accounts_file.rs index dedec30af24e88..77f1717a9ca259 100644 --- a/accounts-db/src/accounts_file.rs +++ b/accounts-db/src/accounts_file.rs @@ -3,11 +3,12 @@ use { account_storage::meta::{ StorableAccountsWithHashesAndWriteVersions, StoredAccountInfo, StoredAccountMeta, }, + accounts_hash::AccountHash, append_vec::{AppendVec, AppendVecError, MatchAccountOwnerError}, storable_accounts::StorableAccounts, tiered_storage::error::TieredStorageError, }, - solana_sdk::{account::ReadableAccount, clock::Slot, hash::Hash, pubkey::Pubkey}, + solana_sdk::{account::ReadableAccount, clock::Slot, pubkey::Pubkey}, std::{ borrow::Borrow, mem, @@ -154,7 +155,7 @@ impl AccountsFile { 'b, T: ReadableAccount + Sync, U: StorableAccounts<'a, T>, - V: Borrow, + V: Borrow, >( &self, accounts: &StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V>, diff --git a/accounts-db/src/accounts_hash.rs b/accounts-db/src/accounts_hash.rs index c6a1458a4bb263..315c73289645a1 100644 --- a/accounts-db/src/accounts_hash.rs +++ b/accounts-db/src/accounts_hash.rs @@ -1248,12 +1248,6 @@ pub struct AccountHash(pub Hash); // This also ensures there are no padding bytes, which is requried to safely implement Pod const _: () = assert!(std::mem::size_of::() == std::mem::size_of::()); -impl Borrow for AccountHash { - fn borrow(&self) -> &Hash { - &self.0 - } -} - /// Hash of accounts #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum AccountsHashKind { diff --git a/accounts-db/src/ancient_append_vecs.rs b/accounts-db/src/ancient_append_vecs.rs index 770eb0be73a741..9c7d2e5c089bad 100644 --- a/accounts-db/src/ancient_append_vecs.rs +++ b/accounts-db/src/ancient_append_vecs.rs @@ -12,6 +12,7 @@ use { INCLUDE_SLOT_IN_HASH_IRRELEVANT_APPEND_VEC_OPERATION, }, accounts_file::AccountsFile, + accounts_hash::AccountHash, accounts_index::{AccountsIndexScanResult, ZeroLamport}, active_stats::ActiveStatItem, append_vec::aligned_stored_size, @@ -20,9 +21,7 @@ use { rand::{thread_rng, Rng}, rayon::prelude::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}, solana_measure::measure_us, - solana_sdk::{ - account::ReadableAccount, clock::Slot, hash::Hash, pubkey::Pubkey, saturating_add_assign, - }, + solana_sdk::{account::ReadableAccount, clock::Slot, pubkey::Pubkey, saturating_add_assign}, std::{ collections::HashMap, num::NonZeroU64, @@ -375,7 +374,7 @@ impl AccountsDb { measure_us!(self.get_store_for_shrink(target_slot, bytes)); let (store_accounts_timing, rewrite_elapsed_us) = measure_us!(self.store_accounts_frozen( accounts_to_write, - None::>, + None::>, shrink_in_progress.new_storage(), None, StoreReclaims::Ignore, diff --git a/accounts-db/src/append_vec.rs b/accounts-db/src/append_vec.rs index fce45672f2a9bd..2cd8612828c254 100644 --- a/accounts-db/src/append_vec.rs +++ b/accounts-db/src/append_vec.rs @@ -11,6 +11,7 @@ use { StoredAccountMeta, StoredMeta, StoredMetaWriteVersion, }, accounts_file::{AccountsFileError, Result, ALIGN_BOUNDARY_OFFSET}, + accounts_hash::AccountHash, storable_accounts::StorableAccounts, u64_align, }, @@ -575,7 +576,7 @@ impl AppendVec { 'b, T: ReadableAccount + Sync, U: StorableAccounts<'a, T>, - V: Borrow, + V: Borrow, >( &self, accounts: &StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V>, @@ -611,7 +612,7 @@ impl AppendVec { .map(|account| account.data()) .unwrap_or_default() .as_ptr(); - let hash_ptr = hash.as_ref().as_ptr(); + let hash_ptr = hash.0.as_ref().as_ptr(); let ptrs = [ (meta_ptr as *const u8, mem::size_of::()), (account_meta_ptr as *const u8, mem::size_of::()), @@ -669,7 +670,7 @@ pub mod tests { let accounts = [(&data.0.pubkey, &data.1)]; let slice = &accounts[..]; let account_data = (slot_ignored, slice); - let hash = Hash::default(); + let hash = AccountHash(Hash::default()); let storable_accounts = StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions( &account_data, @@ -740,7 +741,7 @@ pub mod tests { // for (Slot, &'a [(&'a Pubkey, &'a T)], IncludeSlotInHash) let slot = 0 as Slot; let pubkey = Pubkey::default(); - StorableAccountsWithHashesAndWriteVersions::<'_, '_, _, _, &Hash>::new(&( + StorableAccountsWithHashesAndWriteVersions::<'_, '_, _, _, &AccountHash>::new(&( slot, &[(&pubkey, &account)][..], INCLUDE_SLOT_IN_HASH_TESTS, @@ -755,7 +756,7 @@ pub mod tests { // mismatch between lens of accounts, hashes, write_versions let mut hashes = Vec::default(); if correct_hashes { - hashes.push(Hash::default()); + hashes.push(AccountHash(Hash::default())); } let mut write_versions = Vec::default(); if correct_write_versions { @@ -798,7 +799,7 @@ pub mod tests { let account = AccountSharedData::default(); let slot = 0 as Slot; let pubkeys = [Pubkey::default()]; - let hashes = Vec::::default(); + let hashes = Vec::::default(); let write_versions = Vec::default(); let mut accounts = vec![(&pubkeys[0], &account)]; accounts.clear(); @@ -819,7 +820,10 @@ pub mod tests { let account = AccountSharedData::default(); let slot = 0 as Slot; let pubkeys = [Pubkey::from([5; 32]), Pubkey::from([6; 32])]; - let hashes = vec![Hash::new(&[3; 32]), Hash::new(&[4; 32])]; + let hashes = vec![ + AccountHash(Hash::new(&[3; 32])), + AccountHash(Hash::new(&[4; 32])), + ]; let write_versions = vec![42, 43]; let accounts = [(&pubkeys[0], &account), (&pubkeys[1], &account)]; let accounts2 = (slot, &accounts[..], INCLUDE_SLOT_IN_HASH_TESTS); @@ -850,7 +854,7 @@ pub mod tests { // for (Slot, &'a [(&'a Pubkey, &'a T)], IncludeSlotInHash) let slot = 0 as Slot; let pubkey = Pubkey::default(); - let hashes = vec![Hash::default()]; + let hashes = vec![AccountHash(Hash::default())]; let write_versions = vec![0]; let accounts = [(&pubkey, &account)]; let accounts2 = (slot, &accounts[..], INCLUDE_SLOT_IN_HASH_TESTS); diff --git a/accounts-db/src/storable_accounts.rs b/accounts-db/src/storable_accounts.rs index 8da6885dce6947..c52b1910addf95 100644 --- a/accounts-db/src/storable_accounts.rs +++ b/accounts-db/src/storable_accounts.rs @@ -606,7 +606,7 @@ pub mod tests { let index = index as usize; assert_eq!(storable.account(index), &raw2[index]); assert_eq!(storable.pubkey(index), raw2[index].pubkey()); - assert_eq!(&storable.hash(index).0, raw2[index].hash()); + assert_eq!(storable.hash(index), raw2[index].hash()); assert_eq!(storable.slot(index), expected_slots[index]); assert_eq!(storable.write_version(index), raw2[index].write_version()); }) diff --git a/accounts-db/src/tiered_storage.rs b/accounts-db/src/tiered_storage.rs index 43d34f1561cca4..6a9f0193fd0fee 100644 --- a/accounts-db/src/tiered_storage.rs +++ b/accounts-db/src/tiered_storage.rs @@ -14,13 +14,14 @@ pub mod writer; use { crate::{ account_storage::meta::{StorableAccountsWithHashesAndWriteVersions, StoredAccountInfo}, + accounts_hash::AccountHash, storable_accounts::StorableAccounts, }, error::TieredStorageError, footer::{AccountBlockFormat, AccountMetaFormat, OwnersBlockFormat}, index::AccountIndexFormat, readable::TieredStorageReader, - solana_sdk::{account::ReadableAccount, hash::Hash}, + solana_sdk::account::ReadableAccount, std::{ borrow::Borrow, fs::OpenOptions, @@ -96,7 +97,7 @@ impl TieredStorage { 'b, T: ReadableAccount + Sync, U: StorableAccounts<'a, T>, - V: Borrow, + V: Borrow, >( &self, accounts: &StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V>, @@ -157,6 +158,7 @@ mod tests { solana_sdk::{ account::{Account, AccountSharedData}, clock::Slot, + hash::Hash, pubkey::Pubkey, system_instruction::MAX_PERMITTED_DATA_LENGTH, }, @@ -182,7 +184,7 @@ mod tests { let storable_accounts = StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions( &account_data, - Vec::<&Hash>::new(), + Vec::::new(), Vec::::new(), ); @@ -341,7 +343,7 @@ mod tests { // Slot information is not used here let account_data = (Slot::MAX, &account_refs[..]); - let hashes: Vec<_> = std::iter::repeat_with(Hash::new_unique) + let hashes: Vec<_> = std::iter::repeat_with(|| AccountHash(Hash::new_unique())) .take(account_data_sizes.len()) .collect(); let write_versions: Vec<_> = accounts diff --git a/accounts-db/src/tiered_storage/writer.rs b/accounts-db/src/tiered_storage/writer.rs index 839ddca9a94d98..dece0e42732f49 100644 --- a/accounts-db/src/tiered_storage/writer.rs +++ b/accounts-db/src/tiered_storage/writer.rs @@ -3,13 +3,14 @@ use { crate::{ account_storage::meta::{StorableAccountsWithHashesAndWriteVersions, StoredAccountInfo}, + accounts_hash::AccountHash, storable_accounts::StorableAccounts, tiered_storage::{ error::TieredStorageError, file::TieredStorageFile, footer::TieredStorageFooter, TieredStorageFormat, TieredStorageResult, }, }, - solana_sdk::{account::ReadableAccount, hash::Hash}, + solana_sdk::account::ReadableAccount, std::{borrow::Borrow, path::Path}, }; @@ -35,7 +36,7 @@ impl<'format> TieredStorageWriter<'format> { 'b, T: ReadableAccount + Sync, U: StorableAccounts<'a, T>, - V: Borrow, + V: Borrow, >( &self, accounts: &StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V>, diff --git a/runtime/store-tool/src/main.rs b/runtime/store-tool/src/main.rs index 98140ed59ba0ea..cb5838af4f21ad 100644 --- a/runtime/store-tool/src/main.rs +++ b/runtime/store-tool/src/main.rs @@ -1,7 +1,9 @@ use { clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg}, log::*, - solana_accounts_db::{account_storage::meta::StoredAccountMeta, append_vec::AppendVec}, + solana_accounts_db::{ + account_storage::meta::StoredAccountMeta, accounts_hash::AccountHash, append_vec::AppendVec, + }, solana_sdk::{ account::{AccountSharedData, ReadableAccount}, hash::Hash, @@ -65,7 +67,7 @@ fn main() { } fn is_account_zeroed(account: &StoredAccountMeta) -> bool { - account.hash() == &Hash::default() + account.hash() == &AccountHash(Hash::default()) && account.data_len() == 0 && account.write_version() == 0 && account.pubkey() == &Pubkey::default()