From d54a6337591f4e4d6ca544ed22f62d6f99e9eed0 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 15 Feb 2023 09:47:10 -0800 Subject: [PATCH] Return index of matching owner for a program account --- runtime/src/accounts_db.rs | 37 +++++++++++++++++++++++++------------ runtime/src/append_vec.rs | 26 ++++++++++++++++---------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 5e3a5ef1c4e0e2..1afbc8365f0952 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -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 { 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 { 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) + }; } } @@ -14180,11 +14193,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), @@ -14214,11 +14227,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), diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index 75f6c85080b2a4..4cf45c87b4e94b 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -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 { 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());