Return index of matching owner for a program account (#30337)

This commit is contained in:
Pankaj Garg 2023-02-15 11:41:29 -08:00 committed by GitHub
parent 4909267c88
commit 3bea5fc326
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 22 deletions

View File

@ -821,14 +821,18 @@ impl<'a> LoadedAccountAccessor<'a> {
}
}
fn account_matches_owners(&self, owners: &[&Pubkey]) -> Result<(), MatchAccountOwnerError> {
fn account_matches_owners(&self, owners: &[&Pubkey]) -> Result<usize, MatchAccountOwnerError> {
match self {
LoadedAccountAccessor::Cached(cached_account) => cached_account
.as_ref()
.and_then(|cached_account| {
(!cached_account.account.is_zero_lamport()
&& owners.contains(&cached_account.account.owner()))
.then_some(())
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) => {
@ -4938,12 +4942,16 @@ 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<(), MatchAccountOwnerError> {
) -> Result<usize, MatchAccountOwnerError> {
let (slot, storage_location, _maybe_account_accesor) = self
.read_index_for_accessor_or_load_slow(ancestors, account, None, false)
.ok_or(MatchAccountOwnerError::UnableToLoad)?;
@ -4951,9 +4959,14 @@ impl AccountsDb {
if !storage_location.is_cached() {
let result = self.read_only_accounts_cache.load(*account, slot);
if let Some(account) = result {
return (!account.is_zero_lamport() && owners.contains(&account.owner()))
.then_some(())
.ok_or(MatchAccountOwnerError::NoMatch);
return if account.is_zero_lamport() {
Err(MatchAccountOwnerError::NoMatch)
} else {
owners
.iter()
.position(|entry| &account.owner() == entry)
.ok_or(MatchAccountOwnerError::NoMatch)
};
}
}
@ -14184,11 +14197,11 @@ pub mod tests {
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account1_key, &owners_refs),
Ok(())
Ok(0)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account2_key, &owners_refs),
Ok(())
Ok(1)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account3_key, &owners_refs),
@ -14218,11 +14231,11 @@ pub mod tests {
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account1_key, &owners_refs),
Ok(())
Ok(0)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account2_key, &owners_refs),
Ok(())
Ok(1)
);
assert_eq!(
db.account_matches_owners(&Ancestors::default(), &account3_key, &owners_refs),

View File

@ -612,20 +612,26 @@ impl AppendVec {
Some(account_meta)
}
/// Return Some(true) if the account owner at `offset` is one of the pubkeys in `owners`.
/// Return Some(false) if the account owner is not one of the pubkeys in `owners`.
/// It returns None if the `offset` value causes a data overrun.
/// 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],
) -> Result<(), MatchAccountOwnerError> {
) -> Result<usize, MatchAccountOwnerError> {
let account_meta = self
.get_account_meta(offset)
.ok_or(MatchAccountOwnerError::UnableToLoad)?;
(account_meta.lamports != 0 && owners.contains(&&account_meta.owner))
.then_some(())
.ok_or(MatchAccountOwnerError::NoMatch)
if account_meta.lamports == 0 {
Err(MatchAccountOwnerError::NoMatch)
} else {
owners
.iter()
.position(|entry| &&account_meta.owner == entry)
.ok_or(MatchAccountOwnerError::NoMatch)
}
}
#[cfg(test)]
@ -1091,13 +1097,13 @@ pub mod tests {
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_refs), Ok(()));
assert_eq!(av.account_matches_owners(index, &owners_refs), 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_refs), Ok(()));
assert_eq!(av.account_matches_owners(index, &owners_refs), Ok(()));
assert_eq!(av.account_matches_owners(index1, &owners_refs), Ok(1));
assert_eq!(av.account_matches_owners(index, &owners_refs), Ok(0));
let mut account2 = create_test_account(6);
account2.1.set_owner(Pubkey::new_unique());