Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 1 addition & 75 deletions accounts-db/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ use {
AccountsStats, CleanAccountsStats, FlushStats, ObsoleteAccountsStats, PurgeStats,
ShrinkAncientStats, ShrinkStats, ShrinkStatsSub, StoreAccountsTiming,
},
accounts_file::{
AccountsFile, AccountsFileError, AccountsFileProvider, MatchAccountOwnerError,
StorageAccess,
},
accounts_file::{AccountsFile, AccountsFileError, AccountsFileProvider, StorageAccess},
accounts_hash::{AccountLtHash, AccountsLtHash, ZERO_LAMPORT_ACCOUNT_LT_HASH},
accounts_index::{
in_mem_accounts_index::StartupStats, AccountSecondaryIndexes, AccountsIndex,
Expand Down Expand Up @@ -831,36 +828,6 @@ impl LoadedAccountAccessor<'_> {
}
}
}

fn account_matches_owners(&self, owners: &[Pubkey]) -> Result<usize, MatchAccountOwnerError> {
match self {
LoadedAccountAccessor::Cached(cached_account) => cached_account
.as_ref()
.and_then(|cached_account| {
if cached_account.account.is_zero_lamport() {
None
} else {
owners
.iter()
.position(|entry| cached_account.account.owner() == entry)
}
})
.ok_or(MatchAccountOwnerError::NoMatch),
LoadedAccountAccessor::Stored(maybe_storage_entry) => {
// storage entry may not be present if slot was cleaned up in
// between reading the accounts index and calling this function to
// get account meta from the storage entry here
maybe_storage_entry
.as_ref()
.map(|(storage_entry, offset)| {
storage_entry
.accounts
.account_matches_owners(*offset, owners)
})
.unwrap_or(Err(MatchAccountOwnerError::UnableToLoad))
}
}
}
}

pub enum LoadedAccount<'a> {
Expand Down Expand Up @@ -4095,47 +4062,6 @@ impl AccountsDb {
self.do_load(ancestors, pubkey, None, load_hint, LoadZeroLamports::None)
}

/// Return Ok(index_of_matching_owner) if the account owner at `offset` is one of the pubkeys in `owners`.
/// Return Err(MatchAccountOwnerError::NoMatch) if the account has 0 lamports or the owner is not one of
/// the pubkeys in `owners`.
/// Return Err(MatchAccountOwnerError::UnableToLoad) if the account could not be accessed.
pub fn account_matches_owners(
&self,
ancestors: &Ancestors,
account: &Pubkey,
owners: &[Pubkey],
) -> Result<usize, MatchAccountOwnerError> {
let (slot, storage_location, _maybe_account_accessor) = self
.read_index_for_accessor_or_load_slow(ancestors, account, None, false)
.ok_or(MatchAccountOwnerError::UnableToLoad)?;

if !storage_location.is_cached() {
let result = self.read_only_accounts_cache.load(*account, slot);
if let Some(account) = result {
return if account.is_zero_lamport() {
Err(MatchAccountOwnerError::NoMatch)
} else {
owners
.iter()
.position(|entry| account.owner() == entry)
.ok_or(MatchAccountOwnerError::NoMatch)
};
}
}

let (account_accessor, _slot) = self
.retry_to_get_account_accessor(
slot,
storage_location,
ancestors,
account,
None,
LoadHint::Unspecified,
)
.ok_or(MatchAccountOwnerError::UnableToLoad)?;
account_accessor.account_matches_owners(owners)
}

/// load the account with `pubkey` into the read only accounts cache.
/// The goal is to make subsequent loads (which caller expects to occur) to find the account quickly.
pub fn load_account_into_read_cache(&self, ancestors: &Ancestors, pubkey: &Pubkey) {
Expand Down
94 changes: 0 additions & 94 deletions accounts-db/src/accounts_db/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3144,100 +3144,6 @@ fn test_load_with_read_only_accounts_cache() {
assert_eq!(slot, 2);
}

#[test]
fn test_account_matches_owners() {
let db = Arc::new(AccountsDb::new_single_for_tests());

let owners: Vec<Pubkey> = (0..2).map(|_| Pubkey::new_unique()).collect();

let account1_key = Pubkey::new_unique();
let account1 = AccountSharedData::new(321, 10, &owners[0]);

let account2_key = Pubkey::new_unique();
let account2 = AccountSharedData::new(1, 1, &owners[1]);

let account3_key = Pubkey::new_unique();
let account3 = AccountSharedData::new(1, 1, &Pubkey::new_unique());

// Account with 0 lamports
let account4_key = Pubkey::new_unique();
let account4 = AccountSharedData::new(0, 1, &owners[1]);

db.store_cached((0, &[(&account1_key, &account1)][..]));
db.store_cached((1, &[(&account2_key, &account2)][..]));
db.store_cached((2, &[(&account3_key, &account3)][..]));
db.store_cached((3, &[(&account4_key, &account4)][..]));

db.add_root(0);
db.add_root(1);
db.add_root(2);
db.add_root(3);

// Set the latest full snapshot slot to one that is *older* than the slot account4 is in.
// This is required to ensure account4 is not purged during `clean`,
// which is required to have account_matches_owners() return NoMatch.
db.set_latest_full_snapshot_slot(2);

// Flush the cache so that the account meta will be read from the storage
db.flush_accounts_cache(true, None);
db.clean_accounts_for_tests();

assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account1_key, &owners),
Ok(0)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account2_key, &owners),
Ok(1)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account3_key, &owners),
Err(MatchAccountOwnerError::NoMatch)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account4_key, &owners),
Err(MatchAccountOwnerError::NoMatch)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &Pubkey::new_unique(), &owners),
Err(MatchAccountOwnerError::UnableToLoad)
);

// Flush the cache and load account1 (so that it's in the cache)
db.flush_accounts_cache(true, None);
db.clean_accounts_for_tests();
let _ = db
.do_load(
&Ancestors::default(),
&account1_key,
Some(0),
LoadHint::Unspecified,
LoadZeroLamports::SomeWithZeroLamportAccountForTests,
)
.unwrap();

assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account1_key, &owners),
Ok(0)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account2_key, &owners),
Ok(1)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account3_key, &owners),
Err(MatchAccountOwnerError::NoMatch)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account4_key, &owners),
Err(MatchAccountOwnerError::NoMatch)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &Pubkey::new_unique(), &owners),
Err(MatchAccountOwnerError::UnableToLoad)
);
}

/// a test that will accept either answer
const LOAD_ZERO_LAMPORTS_ANY_TESTS: LoadZeroLamports = LoadZeroLamports::None;

Expand Down
30 changes: 0 additions & 30 deletions accounts-db/src/accounts_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,6 @@ pub enum AccountsFileError {
TieredStorageError(#[from] TieredStorageError),
}

#[derive(Error, Debug, PartialEq, Eq)]
pub enum MatchAccountOwnerError {
#[error("The account owner does not match with the provided list")]
NoMatch,
#[error("Unable to load the account")]
UnableToLoad,
}

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum StorageAccess {
/// storages should be accessed by Mmap
Expand Down Expand Up @@ -263,28 +255,6 @@ impl AccountsFile {
}
}

pub fn account_matches_owners(
&self,
offset: usize,
owners: &[Pubkey],
) -> std::result::Result<usize, MatchAccountOwnerError> {
match self {
Self::AppendVec(av) => av.account_matches_owners(offset, owners),
// Note: The conversion here is needed as the AccountsDB currently
// assumes all offsets are multiple of 8 while TieredStorage uses
// IndexOffset that is equivalent to AccountInfo::reduced_offset.
Self::TieredStorage(ts) => {
let Some(reader) = ts.reader() else {
return Err(MatchAccountOwnerError::UnableToLoad);
};
reader.account_matches_owners(
IndexOffset(AccountInfo::get_reduced_offset(offset)),
owners,
)
}
}
}

/// Return the path of the underlying account file.
pub fn path(&self) -> &Path {
match self {
Expand Down
65 changes: 1 addition & 64 deletions accounts-db/src/append_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use {
account_info::Offset,
account_storage::stored_account_info::{StoredAccountInfo, StoredAccountInfoWithoutData},
accounts_file::{
AccountsFileError, InternalsForArchive, MatchAccountOwnerError, Result, StorageAccess,
StoredAccountsInfo,
AccountsFileError, InternalsForArchive, Result, StorageAccess, StoredAccountsInfo,
},
buffered_reader::{
BufReaderWithOverflow, BufferedReader, FileBufRead as _, RequiredLenBufFileRead,
Expand Down Expand Up @@ -893,28 +892,6 @@ impl AppendVec {
}
}

/// Return Ok(index_of_matching_owner) if the account owner at `offset` is one of the pubkeys in `owners`.
/// Return Err(MatchAccountOwnerError::NoMatch) if the account has 0 lamports or the owner is not one of
/// the pubkeys in `owners`.
/// Return Err(MatchAccountOwnerError::UnableToLoad) if the `offset` value causes a data overrun.
pub fn account_matches_owners(
&self,
offset: usize,
owners: &[Pubkey],
) -> std::result::Result<usize, MatchAccountOwnerError> {
self.get_stored_account_no_data_callback(offset, |stored_account_meta| {
if stored_account_meta.lamports() == 0 {
Err(MatchAccountOwnerError::NoMatch)
} else {
owners
.iter()
.position(|entry| stored_account_meta.owner() == entry)
.ok_or(MatchAccountOwnerError::NoMatch)
}
})
.unwrap_or(Err(MatchAccountOwnerError::UnableToLoad))
}

#[cfg(test)]
pub fn get_account_test(
&self,
Expand Down Expand Up @@ -1591,46 +1568,6 @@ pub mod tests {
assert_eq!(av.get_account_test(index1).unwrap(), account1);
}

#[test]
fn test_account_matches_owners() {
let path = get_append_vec_path("test_append_data");
let av = AppendVec::new(&path.path, true, 1024 * 1024);
let owners: Vec<Pubkey> = (0..2).map(|_| Pubkey::new_unique()).collect();

let mut account = create_test_account(5);
account.1.set_owner(owners[0]);
let index = av.append_account_test(&account).unwrap();
assert_eq!(av.account_matches_owners(index, &owners), Ok(0));

let mut account1 = create_test_account(6);
account1.1.set_owner(owners[1]);
let index1 = av.append_account_test(&account1).unwrap();
assert_eq!(av.account_matches_owners(index1, &owners), Ok(1));
assert_eq!(av.account_matches_owners(index, &owners), Ok(0));

let mut account2 = create_test_account(6);
account2.1.set_owner(Pubkey::new_unique());
let index2 = av.append_account_test(&account2).unwrap();
assert_eq!(
av.account_matches_owners(index2, &owners),
Err(MatchAccountOwnerError::NoMatch)
);

// tests for overflow
assert_eq!(
av.account_matches_owners(usize::MAX - mem::size_of::<StoredMeta>(), &owners),
Err(MatchAccountOwnerError::UnableToLoad)
);

assert_eq!(
av.account_matches_owners(
usize::MAX - mem::size_of::<StoredMeta>() - mem::size_of::<AccountMeta>() + 1,
&owners
),
Err(MatchAccountOwnerError::UnableToLoad)
);
}

impl AppendVec {
/// return how many accounts in the storage
fn accounts_count(&self) -> usize {
Expand Down
Loading
Loading