Function solana_program::program::invoke_signed

source ·
pub fn invoke_signed(
    instruction: &Instruction,
    account_infos: &[AccountInfo<'_>],
    signers_seeds: &[&[&[u8]]]
) -> ProgramResult
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 AccountInfos. 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(())
}