Unified signature for create_program_address (#11460)
This commit is contained in:
@ -10,7 +10,7 @@ use solana_sdk::{
|
|||||||
entrypoint,
|
entrypoint,
|
||||||
entrypoint::ProgramResult,
|
entrypoint::ProgramResult,
|
||||||
info,
|
info,
|
||||||
program::{create_program_address, invoke, invoke_signed},
|
program::{invoke, invoke_signed},
|
||||||
program_error::ProgramError,
|
program_error::ProgramError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction,
|
system_instruction,
|
||||||
@ -97,7 +97,8 @@ fn process_instruction(
|
|||||||
|
|
||||||
info!("Test create_program_address");
|
info!("Test create_program_address");
|
||||||
{
|
{
|
||||||
let address = create_program_address(&[b"You pass butter", &[nonce1]], program_id)?;
|
let address =
|
||||||
|
Pubkey::create_program_address(&[b"You pass butter", &[nonce1]], program_id)?;
|
||||||
assert_eq!(&address, accounts[DERIVED_KEY1_INDEX].key);
|
assert_eq!(&address, accounts[DERIVED_KEY1_INDEX].key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,39 +2,9 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account_info::AccountInfo, entrypoint::ProgramResult, entrypoint::SUCCESS,
|
account_info::AccountInfo, entrypoint::ProgramResult, entrypoint::SUCCESS,
|
||||||
instruction::Instruction, program_error::ProgramError, pubkey::Pubkey,
|
instruction::Instruction,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create_program_address(
|
|
||||||
seeds: &[&[u8]],
|
|
||||||
program_id: &Pubkey,
|
|
||||||
) -> Result<Pubkey, ProgramError> {
|
|
||||||
let bytes = [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0,
|
|
||||||
];
|
|
||||||
let result = unsafe {
|
|
||||||
sol_create_program_address(
|
|
||||||
seeds as *const _ as *const u8,
|
|
||||||
seeds.len() as u64,
|
|
||||||
program_id as *const _ as *const u8,
|
|
||||||
&bytes as *const _ as *const u8,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
match result {
|
|
||||||
SUCCESS => Ok(Pubkey::new(&bytes)),
|
|
||||||
_ => Err(result.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
fn sol_create_program_address(
|
|
||||||
seeds_addr: *const u8,
|
|
||||||
seeds_len: u64,
|
|
||||||
program_id_addr: *const u8,
|
|
||||||
address_bytes_addr: *const u8,
|
|
||||||
) -> u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invoke a cross-program instruction
|
/// Invoke a cross-program instruction
|
||||||
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
|
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
|
||||||
invoke_signed(instruction, account_infos, &[])
|
invoke_signed(instruction, account_infos, &[])
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#[cfg(feature = "program")]
|
||||||
|
use crate::entrypoint::SUCCESS;
|
||||||
#[cfg(not(feature = "program"))]
|
#[cfg(not(feature = "program"))]
|
||||||
use crate::hash::Hasher;
|
use crate::hash::Hasher;
|
||||||
use crate::{decode_error::DecodeError, hash::hashv};
|
use crate::{decode_error::DecodeError, hash::hashv};
|
||||||
@ -25,6 +27,15 @@ impl<T> DecodeError<T> for PubkeyError {
|
|||||||
"PubkeyError"
|
"PubkeyError"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<u64> for PubkeyError {
|
||||||
|
fn from(error: u64) -> Self {
|
||||||
|
match error {
|
||||||
|
0 => PubkeyError::MaxSeedLengthExceeded,
|
||||||
|
1 => PubkeyError::InvalidSeeds,
|
||||||
|
_ => panic!("Unsupported PubkeyError"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(
|
#[derive(
|
||||||
@ -90,11 +101,14 @@ impl Pubkey {
|
|||||||
|
|
||||||
/// Create a program address, valid program address must not be on the
|
/// Create a program address, valid program address must not be on the
|
||||||
/// ed25519 curve
|
/// ed25519 curve
|
||||||
#[cfg(not(feature = "program"))]
|
|
||||||
pub fn create_program_address(
|
pub fn create_program_address(
|
||||||
seeds: &[&[u8]],
|
seeds: &[&[u8]],
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
) -> Result<Pubkey, PubkeyError> {
|
) -> Result<Pubkey, PubkeyError> {
|
||||||
|
// Perform the calculation inline, calling this from within a program is
|
||||||
|
// not supported
|
||||||
|
#[cfg(not(feature = "program"))]
|
||||||
|
{
|
||||||
let mut hasher = Hasher::default();
|
let mut hasher = Hasher::default();
|
||||||
for seed in seeds.iter() {
|
for seed in seeds.iter() {
|
||||||
if seed.len() > MAX_SEED_LEN {
|
if seed.len() > MAX_SEED_LEN {
|
||||||
@ -114,10 +128,39 @@ impl Pubkey {
|
|||||||
|
|
||||||
Ok(Pubkey::new(hash.as_ref()))
|
Ok(Pubkey::new(hash.as_ref()))
|
||||||
}
|
}
|
||||||
|
// Call via a system call to perform the calculation
|
||||||
|
#[cfg(feature = "program")]
|
||||||
|
{
|
||||||
|
extern "C" {
|
||||||
|
fn sol_create_program_address(
|
||||||
|
seeds_addr: *const u8,
|
||||||
|
seeds_len: u64,
|
||||||
|
program_id_addr: *const u8,
|
||||||
|
address_bytes_addr: *const u8,
|
||||||
|
) -> u64;
|
||||||
|
};
|
||||||
|
let bytes = [
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
];
|
||||||
|
let result = unsafe {
|
||||||
|
sol_create_program_address(
|
||||||
|
seeds as *const _ as *const u8,
|
||||||
|
seeds.len() as u64,
|
||||||
|
program_id as *const _ as *const u8,
|
||||||
|
&bytes as *const _ as *const u8,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
match result {
|
||||||
|
SUCCESS => Ok(Pubkey::new(&bytes)),
|
||||||
|
_ => Err(result.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Find a valid program address and its corresponding nonce which must be passed
|
/// Find a valid program address and its corresponding nonce which must be passed
|
||||||
/// as an additional seed when calling `create_program_address`
|
/// as an additional seed when calling `create_program_address`
|
||||||
#[cfg(not(feature = "program"))]
|
// #[cfg(not(feature = "program"))]
|
||||||
pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8) {
|
pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8) {
|
||||||
let mut nonce = [255];
|
let mut nonce = [255];
|
||||||
for _ in 0..std::u8::MAX {
|
for _ in 0..std::u8::MAX {
|
||||||
@ -143,6 +186,8 @@ impl Pubkey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO localalize this
|
||||||
|
|
||||||
impl AsRef<[u8]> for Pubkey {
|
impl AsRef<[u8]> for Pubkey {
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
&self.0[..]
|
&self.0[..]
|
||||||
|
Reference in New Issue
Block a user