Function solana_sdk::program::invoke_signed
source · pub fn invoke_signed(
instruction: &Instruction,
account_infos: &[AccountInfo<'_>],
signers_seeds: &[&[&[u8]]]
) -> Result<(), ProgramError>
Expand description
Invoke a cross-program instruction with program signatures.
This function is like invoke
with the additional ability to virtually
sign an invocation on behalf of one or more program derived addresses (PDAs)
controlled by the calling program, allowing the callee to mutate them, or
otherwise confirm that a PDA program key has authorized the actions of the
callee.
There is no cryptographic signing involved — PDA signing is a runtime construct that allows the calling program to control accounts as if it could cryptographically sign for them; and the callee to treat the account as if it was cryptographically signed.
The signer_seeds
parameter is a slice of u8
slices where the inner
slices represent the seeds plus the bump seed used to derive (with
Pubkey::find_program_address
) one of the PDAs within the account_infos
slice of AccountInfo
s. During invocation, the runtime will re-derive the
PDA from the seeds and the calling program’s ID, and if it matches one of
the accounts in account_info
, will consider that account “signed”.
See the documentation for Pubkey::find_program_address
for more
about program derived addresses.
Examples
A simple example of creating an account for a PDA:
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
entrypoint::ProgramResult,
program::invoke_signed,
pubkey::Pubkey,
system_instruction,
system_program,
};
entrypoint!(process_instruction);
fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let payer = next_account_info(account_info_iter)?;
let vault_pda = next_account_info(account_info_iter)?;
let system_program = next_account_info(account_info_iter)?;
assert!(payer.is_writable);
assert!(payer.is_signer);
assert!(vault_pda.is_writable);
assert_eq!(vault_pda.owner, &system_program::ID);
assert!(system_program::check_id(system_program.key));
let vault_bump_seed = instruction_data[0];
let vault_seeds = &[b"vault", payer.key.as_ref(), &[vault_bump_seed]];
let expected_vault_pda = Pubkey::create_program_address(vault_seeds, program_id)?;
assert_eq!(vault_pda.key, &expected_vault_pda);
let lamports = 10000000;
let vault_size = 16;
invoke_signed(
&system_instruction::create_account(
&payer.key,
&vault_pda.key,
lamports,
vault_size,
&program_id,
),
&[
payer.clone(),
vault_pda.clone(),
],
&[
&[
b"vault",
payer.key.as_ref(),
&[vault_bump_seed],
],
]
)?;
Ok(())
}