Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 6 additions & 2 deletions sdk/pinocchio/src/account_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ use core::{
#[cfg(target_os = "solana")]
use crate::syscalls::sol_memset_;

use crate::{program_error::ProgramError, pubkey::Pubkey, ProgramResult};
use crate::{
program_error::ProgramError,
pubkey::{pubkey_eq, Pubkey},
ProgramResult,
};

/// Maximum number of bytes a program may add to an account during a
/// single top-level instruction.
Expand Down Expand Up @@ -186,7 +190,7 @@ impl AccountInfo {
/// Checks if the account is owned by the given program.
#[inline(always)]
pub fn is_owned_by(&self, program: &Pubkey) -> bool {
self.owner() == program
pubkey_eq(self.owner(), program)
}

/// Changes the owner of the account.
Expand Down
4 changes: 2 additions & 2 deletions sdk/pinocchio/src/cpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
account_info::{AccountInfo, BorrowState},
instruction::{Account, Instruction, Signer},
program_error::ProgramError,
pubkey::Pubkey,
pubkey::{pubkey_eq, Pubkey},
ProgramResult,
};

Expand Down Expand Up @@ -299,7 +299,7 @@ unsafe fn inner_invoke_signed_with_bounds<const MAX_ACCOUNTS: usize>(
// In order to check whether the borrow state is compatible
// with the invocation, we need to check that we have the
// correct account info and meta pair.
if account_info.key() != account_meta.pubkey {
if !pubkey_eq(account_info.key(), account_meta.pubkey) {
return Err(ProgramError::InvalidArgument);
}

Expand Down
20 changes: 20 additions & 0 deletions sdk/pinocchio/src/pubkey.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Public key type and functions.

use core::ptr::read_unaligned;

use crate::program_error::ProgramError;

/// Number of bytes in a pubkey.
Expand Down Expand Up @@ -33,6 +35,24 @@ pub fn log(pubkey: &Pubkey) {
core::hint::black_box(pubkey);
}

/// Compare two `Pubkey`s for equality.
///
/// The implementation of this function is currectly more efficient
/// than `p1 == p2` since it compares 8 bytes at a time instead of
/// byte-by-byte.
#[inline(always)]
pub const fn pubkey_eq(p1: &Pubkey, p2: &Pubkey) -> bool {
let p1_ptr = p1.as_ptr() as *const u64;
let p2_ptr = p2.as_ptr() as *const u64;

unsafe {
read_unaligned(p1_ptr) == read_unaligned(p2_ptr)
&& read_unaligned(p1_ptr.add(1)) == read_unaligned(p2_ptr.add(1))
&& read_unaligned(p1_ptr.add(2)) == read_unaligned(p2_ptr.add(2))
&& read_unaligned(p1_ptr.add(3)) == read_unaligned(p2_ptr.add(3))
}
}

/// Find a valid [program derived address][pda] and its corresponding bump seed.
///
/// [pda]: https://solana.com/docs/core/cpi#program-derived-addresses
Expand Down
5 changes: 3 additions & 2 deletions sdk/pinocchio/src/sysvars/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
use super::Sysvar;
use crate::{
account_info::{AccountInfo, Ref},
hint::unlikely,
impl_sysvar_get,
program_error::ProgramError,
pubkey::Pubkey,
pubkey::{pubkey_eq, Pubkey},
};

/// The ID of the clock sysvar.
Expand Down Expand Up @@ -86,7 +87,7 @@ impl Clock {
/// This method performs a check on the account info key.
#[inline]
pub fn from_account_info(account_info: &AccountInfo) -> Result<Ref<Clock>, ProgramError> {
if account_info.key() != &CLOCK_ID {
if unlikely(!pubkey_eq(account_info.key(), &CLOCK_ID)) {
return Err(ProgramError::InvalidArgument);
}
Ok(Ref::map(account_info.try_borrow_data()?, |data| unsafe {
Expand Down
5 changes: 3 additions & 2 deletions sdk/pinocchio/src/sysvars/rent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
use super::Sysvar;
use crate::{
account_info::{AccountInfo, Ref},
hint::unlikely,
impl_sysvar_get,
program_error::ProgramError,
pubkey::Pubkey,
pubkey::{pubkey_eq, Pubkey},
};

/// The ID of the rent sysvar.
Expand Down Expand Up @@ -94,7 +95,7 @@ impl Rent {
pub unsafe fn from_account_info_unchecked(
account_info: &AccountInfo,
) -> Result<&Self, ProgramError> {
if account_info.key() != &RENT_ID {
if unlikely(!pubkey_eq(account_info.key(), &RENT_ID)) {
return Err(ProgramError::InvalidArgument);
}
Ok(Self::from_bytes_unchecked(
Expand Down
5 changes: 3 additions & 2 deletions sdk/pinocchio/src/sysvars/slot_hashes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ mod test_utils;

use crate::{
account_info::{AccountInfo, Ref},
hint::unlikely,
program_error::ProgramError,
pubkey::Pubkey,
pubkey::{pubkey_eq, Pubkey},
sysvars::clock::Slot,
};
use core::{mem, ops::Deref, slice::from_raw_parts};
Expand Down Expand Up @@ -277,7 +278,7 @@ impl<'a> SlotHashes<Ref<'a, [u8]>> {
/// - `ProgramError::AccountBorrowFailed` if the account data is already mutably borrowed
#[inline(always)]
pub fn from_account_info(account_info: &'a AccountInfo) -> Result<Self, ProgramError> {
if account_info.key() != &SLOTHASHES_ID {
if unlikely(!pubkey_eq(account_info.key(), &SLOTHASHES_ID)) {
return Err(ProgramError::InvalidArgument);
}

Expand Down
4 changes: 2 additions & 2 deletions sdk/pubkey/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#[doc(hidden)]
// Re-export dependencies used in macros.
pub mod reexport {
pub use pinocchio::pubkey::Pubkey;
pub use pinocchio::pubkey::{pubkey_eq, Pubkey};
}

use core::mem::MaybeUninit;
Expand Down Expand Up @@ -176,7 +176,7 @@ macro_rules! declare_id {
#[doc = "Returns `true` if given pubkey is the program ID."]
#[inline]
pub fn check_id(id: &$crate::reexport::Pubkey) -> bool {
id == &ID
$crate::reexport::pubkey_eq(id, &ID)
}

#[doc = "Returns the program ID."]
Expand Down
Loading