|
|
@@ -17,7 +17,7 @@ pub const MAX_SEEDS: usize = 16;
|
|
|
pub type Pubkey = [u8; PUBKEY_BYTES];
|
|
|
|
|
|
/// Log a `Pubkey` from a program
|
|
|
-#[inline]
|
|
|
+#[inline(always)]
|
|
|
pub fn log(pubkey: &Pubkey) {
|
|
|
#[cfg(target_os = "solana")]
|
|
|
unsafe {
|
|
|
@@ -116,6 +116,7 @@ pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8
|
|
|
/// See the documentation for [`find_program_address`] for a full description.
|
|
|
///
|
|
|
/// [`find_program_address`]: #find_program_address
|
|
|
+#[inline]
|
|
|
pub fn try_find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> Option<(Pubkey, u8)> {
|
|
|
#[cfg(target_os = "solana")]
|
|
|
{
|
|
|
@@ -158,22 +159,21 @@ pub fn try_find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> Option<
|
|
|
/// See the documentation for [`find_program_address`] for a full description
|
|
|
/// of program derived addresses and bump seeds.
|
|
|
///
|
|
|
+/// Note that this function does *not* validate whether the given `seeds` are within
|
|
|
+/// the valid length or not. It will return an error in case of invalid seeds length,
|
|
|
+/// incurring the cost of the syscall.
|
|
|
+///
|
|
|
/// [`find_program_address`]: #find_program_address
|
|
|
+#[inline]
|
|
|
pub fn create_program_address(
|
|
|
seeds: &[&[u8]],
|
|
|
program_id: &Pubkey,
|
|
|
) -> Result<Pubkey, ProgramError> {
|
|
|
- if seeds.len() > MAX_SEEDS {
|
|
|
- return Err(ProgramError::MaxSeedLengthExceeded);
|
|
|
- }
|
|
|
- if seeds.iter().any(|seed| seed.len() > MAX_SEED_LEN) {
|
|
|
- return Err(ProgramError::MaxSeedLengthExceeded);
|
|
|
- }
|
|
|
-
|
|
|
// Call via a system call to perform the calculation
|
|
|
#[cfg(target_os = "solana")]
|
|
|
{
|
|
|
let mut bytes = [0; 32];
|
|
|
+
|
|
|
let result = unsafe {
|
|
|
crate::syscalls::sol_create_program_address(
|
|
|
seeds as *const _ as *const u8,
|
|
|
@@ -182,6 +182,7 @@ pub fn create_program_address(
|
|
|
&mut bytes as *mut _ as *mut u8,
|
|
|
)
|
|
|
};
|
|
|
+
|
|
|
match result {
|
|
|
crate::SUCCESS => Ok(bytes),
|
|
|
_ => Err(result.into()),
|
|
|
@@ -194,3 +195,37 @@ pub fn create_program_address(
|
|
|
panic!("create_program_address is only available on target `solana`")
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/// Create a valid [program derived address][pda] without searching for a bump seed.
|
|
|
+///
|
|
|
+/// [pda]: https://solana.com/docs/core/cpi#program-derived-addresses
|
|
|
+///
|
|
|
+/// Because this function does not create a bump seed, it may unpredictably
|
|
|
+/// return an error for any given set of seeds and is not generally suitable
|
|
|
+/// for creating program derived addresses.
|
|
|
+///
|
|
|
+/// However, it can be used for efficiently verifying that a set of seeds plus
|
|
|
+/// bump seed generated by [`find_program_address`] derives a particular
|
|
|
+/// address as expected. See the example for details.
|
|
|
+///
|
|
|
+/// See the documentation for [`find_program_address`] for a full description
|
|
|
+/// of program derived addresses and bump seeds.
|
|
|
+///
|
|
|
+/// Note that this function validates whether the given `seeds` are within the valid
|
|
|
+/// length or not, returning an error without incurring the cost of the syscall.
|
|
|
+///
|
|
|
+/// [`find_program_address`]: #find_program_address
|
|
|
+#[inline(always)]
|
|
|
+pub fn checked_create_program_address(
|
|
|
+ seeds: &[&[u8]],
|
|
|
+ program_id: &Pubkey,
|
|
|
+) -> Result<Pubkey, ProgramError> {
|
|
|
+ if seeds.len() > MAX_SEEDS {
|
|
|
+ return Err(ProgramError::MaxSeedLengthExceeded);
|
|
|
+ }
|
|
|
+ if seeds.iter().any(|seed| seed.len() > MAX_SEED_LEN) {
|
|
|
+ return Err(ProgramError::MaxSeedLengthExceeded);
|
|
|
+ }
|
|
|
+
|
|
|
+ create_program_address(seeds, program_id)
|
|
|
+}
|