|
1 | 1 | //! Public key type and functions. |
2 | 2 |
|
| 3 | +use core::ptr::read_unaligned; |
| 4 | + |
3 | 5 | use crate::program_error::ProgramError; |
4 | 6 |
|
5 | 7 | /// Number of bytes in a pubkey. |
@@ -33,6 +35,24 @@ pub fn log(pubkey: &Pubkey) { |
33 | 35 | core::hint::black_box(pubkey); |
34 | 36 | } |
35 | 37 |
|
| 38 | +/// Compare two `Pubkey`s for equality. |
| 39 | +/// |
| 40 | +/// The implementation of this function is currently more efficient |
| 41 | +/// than `p1 == p2` since it compares 8 bytes at a time instead of |
| 42 | +/// byte-by-byte. |
| 43 | +#[inline(always)] |
| 44 | +pub const fn pubkey_eq(p1: &Pubkey, p2: &Pubkey) -> bool { |
| 45 | + let p1_ptr = p1.as_ptr() as *const u64; |
| 46 | + let p2_ptr = p2.as_ptr() as *const u64; |
| 47 | + |
| 48 | + unsafe { |
| 49 | + read_unaligned(p1_ptr) == read_unaligned(p2_ptr) |
| 50 | + && read_unaligned(p1_ptr.add(1)) == read_unaligned(p2_ptr.add(1)) |
| 51 | + && read_unaligned(p1_ptr.add(2)) == read_unaligned(p2_ptr.add(2)) |
| 52 | + && read_unaligned(p1_ptr.add(3)) == read_unaligned(p2_ptr.add(3)) |
| 53 | + } |
| 54 | +} |
| 55 | + |
36 | 56 | /// Find a valid [program derived address][pda] and its corresponding bump seed. |
37 | 57 | /// |
38 | 58 | /// [pda]: https://solana.com/docs/core/cpi#program-derived-addresses |
@@ -277,3 +297,25 @@ pub fn create_with_seed( |
277 | 297 | panic!("create_with_seed is only available on target `solana`") |
278 | 298 | } |
279 | 299 | } |
| 300 | + |
| 301 | +#[cfg(test)] |
| 302 | +mod tests { |
| 303 | + use crate::pubkey::{pubkey_eq, Pubkey, PUBKEY_BYTES}; |
| 304 | + |
| 305 | + #[test] |
| 306 | + fn test_pubkey_eq_matches_default_eq() { |
| 307 | + for i in 0..u8::MAX { |
| 308 | + let p1: Pubkey = [i; PUBKEY_BYTES]; |
| 309 | + let p2: Pubkey = [i; PUBKEY_BYTES]; |
| 310 | + |
| 311 | + assert_eq!(pubkey_eq(&p1, &p2), p1 == p2); |
| 312 | + } |
| 313 | + |
| 314 | + for i in 0..u8::MAX { |
| 315 | + let p1: Pubkey = [i; PUBKEY_BYTES]; |
| 316 | + let p2: Pubkey = [u8::MAX - i; PUBKEY_BYTES]; |
| 317 | + |
| 318 | + assert_eq!(!pubkey_eq(&p1, &p2), p1 != p2); |
| 319 | + } |
| 320 | + } |
| 321 | +} |
0 commit comments