Cross Program Invocations
CPI 跨程序调用类似 evm trace 中的 inner call,它使得program能像普通账户一样与其他program交互(尽管可以分析当前的 ix index来判断当前调用是否是 CPI )。
solana-program 中实现了两个 CPI 方法:invoke & invoke_signed
签名
CPI 中的 account 签名是可以传递的,也就是说,在 CPI 调用过程中,每一个输入的 account 的 is_signer flag 都可以被传递到下一个 program。这使得类似 evm中的 approve 过程十分灵活和方便。
solana_program::program::invoke
原型:
fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult
与普通的 tx 基本相同,account_infos 中需要包含所有需要签名的账户,由于 program 无法添加新的、ed25519 曲线上的 account 签名,因此此处需要的签名 account必须已经全部传入当前的 ix 。
solana_program::program::invoke_signed
原型:
fn invoke_signed(
instruction: &Instruction,
account_infos: &[AccountInfo],
signers_seeds: &[&[&[u8]]],
) -> ProgramResult
只有一个区别,就是多了 signers_seeds 这个参数。传入的 seeds 和 caller program id (pubkey) 生成一个唯一的、固定的 account pubkey,并且这个 pubkey 将被 callee ix 视为 signer 。这就使得 program 可以生成无私钥、Autonomous 的签名 来实现跨程序的 authority。
这种由 program 派生而来的特殊的 account 叫做 PDA 👉 Program Derived Addresses
Account data reload
CPI 调用中可以对 account data进行修改(参考上一节 Account 的数据结构),因此在 CPI 调用后需要手动 reload data:
&account_info.data.borrow()