Skip to content

Commit

Permalink
Return index of matching owner for a program account (#30337)
Browse files Browse the repository at this point in the history
  • Loading branch information
pgarg66 authored Feb 15, 2023
1 parent 4909267 commit 3bea5fc
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 22 deletions.
37 changes: 25 additions & 12 deletions runtime/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -4938,22 +4942,31 @@ 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)?;

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)
};
}
}

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
26 changes: 16 additions & 10 deletions runtime/src/append_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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());
Expand Down

0 comments on commit 3bea5fc

Please sign in to comment.