跨程序调用
了解如何在 Anchor 程序中实现跨程序调用(CPI),以实现不同 Solana 程序之间的可组合性。
跨程序调用(CPI:Cross Program Invocation)指的是一个程序调用另一个程序的指令的过程,这使得 Solana 程序之间具备了可组合性。
本节将介绍在 Anchor 程序中实现 CPI 的基础知识,使用一个简单的 SOL 转账指令作为实际示例。一旦你理解了如何实现 CPI 的基础知识,你就可以将这些概念应用到任何指令中。
跨程序调用
让我们来看一个调用系统程序转账指令的 CPI 程序。以下是 Solana Playground 上的示例程序。
lib.rs
文件包含了一个 sol_transfer
指令。当调用 Anchor 程序上的 sol_transfer
指令时,程序内部会调用系统程序的转账指令。
cpi.test.ts
文件展示了如何调用 Anchor 程序的 sol_transfer
指令,并在 SolanaFM 上记录交易详情的链接。
你可以在 Playground 上构建、部署并运行此示例的测试,以查看 SolanaFM 浏览器 上的交易详情。
交易详情将显示首先调用了 Anchor 程序(指令 1),然后调用了系统程序(指令 1.1),最终完成了 SOL 转账。
示例解析
跨程序调用(CPI)允许一个程序调用另一个程序的指令。实现 CPI 的过程与创建指令的过程相同,你必须指定:
- 被调用程序的程序 ID
- 指令所需的账户
- 作为参数所需的任何指令数据
这种模式确保 CPI 具备调用目标程序指令所需的所有信息。
系统程序的转账指令需要两个账户:
from
:发送 SOL 的账户。to
:接收 SOL 的账户。
在示例程序中,SolTransfer
结构体指定了转账指令所需的账户。系统程序也被包括在内,因为 CPI 调用了系统程序。
以下选项卡展示了三种实现跨程序调用(CPI)的方法,每种方法的抽象程度不同。所有示例在功能上都是等价的。其主要目的是展示 CPI 的实现细节。
示例代码中的 sol_transfer
指令展示了使用 Anchor 框架构建 CPI 的典型方法。
此方法涉及创建一个 CpiContext
,其中包括被调用指令的程序 ID 和所需账户。然后将 CpiContext
传递给一个 Anchor 辅助函数 transfer
,以调用特定指令。
cpi_context
变量指定了转账指令所需的程序 ID(系统程序)和账户(发送者和接收者)。
然后将 cpi_context
和 amount
传递给 transfer
函数,以执行调用系统程序转账指令的 CPI。
这里是一个包含所有 3 个示例的参考程序,位于 Solana Playground。
PDA 签名者的跨程序调用
接下来,我们来看一个实现了 CPI 的程序,该程序调用了系统程序的转账指令,其中发送者是一个程序派生地址(PDA),程序必须为其签名。在该示例中,PDA 的地址是使用硬编码字符串 "pda" 和 recipient
账户的地址派生的,因此在示例中,该地址对于每个 recipient
都是唯一的。整个示例位于 Solana Playground。
PDA 签名者的跨程序调用
接下来,我们来看一个实现了 CPI 的程序,该程序调用了系统程序的转账指令,其中发送者是一个程序派生地址(PDA),程序必须为其签名。以下是 Solana Playground 上的示例程序。
lib.rs
文件包含以下程序,其中有一个 sol_transfer
指令。