Solana 60 天课程

2025年02月27日更新 66 人订阅
原价: ¥ 28 限时优惠
专栏简介 开始 Solana - 安装与故障排除 Solana 和 Rust 中的算术与基本类型 Solana Anchor 程序 IDL Solana中的Require、Revert和自定义错误 Solana程序是可升级的,并且没有构造函数 Solidity开发者的Rust基础 Rust不寻常的语法 Rust 函数式过程宏 Rust 结构体与属性式和自定义派生宏 Rust 和 Solana 中的可见性与“继承” Solana时钟及其他“区块”变量 Solana 系统变量详解 Solana 日志、“事件”与交易历史 Tx.origin、msg.sender 和 onlyOwner 在 Solana 中:识别调用者 Solana 计算单元与交易费用介绍 在 Solana 和 Anchor 中初始化账户 Solana 计数器教程:在账户中读写数据 使用 Solana web3 js 和 Anchor 读取账户数据 在Solana中创建“映射”和“嵌套映射” Solana中的存储成本、最大存储容量和账户调整 在 Solana 中读取账户余额的 Anchor 方法:address(account).balance 功能修饰符(view、pure、payable)和回退函数在 Solana 中不存在的原因 在 Solana 上实现 SOL 转账及构建支付分配器 使用不同签名者修改账户 PDA(程序派生地址)与 Solana 中的密钥对账户 理解 Solana 中的账户所有权:从PDA中转移SOL Anchor 中的 Init if needed 与重初始化攻击 Solana 中的多重调用:批量交易与交易大小限制 Solana 中的所有者与权限 在Solana中删除和关闭账户与程序 在 Anchor 中:不同类型的账户 在链上读取另一个锚点程序账户数据 在 Anchor 中的跨程序调用(CPI)

在 Anchor 中的跨程序调用(CPI)

  • RareSkills
  • 发布于 2024-12-19 10:31
  • 阅读 1604

在 Anchor 中的跨程序调用(CPI)

跨程序调用 (CPI) 是 Solana 的术语,用于描述一个程序调用另一个程序的公共函数。

我们之前已经进行过 CPI,当我们向系统程序发送一个 转账 SOL 交易。以下是相关代码片段,以作提醒:

    pub fn send_sol(ctx: Context<SendSol>, amount: u64) -> Result<()> {  
        let cpi_context = CpiContext::new(
            ctx.accounts.system_program.to_account_info(),
            system_program::Transfer {
                from: ctx.accounts.signer.to_account_info(),
                to: ctx.accounts.recipient.to_account_info(),
            }
        );

        let res = system_program::transfer(cpi_context, amount);

        if res.is_ok() {
            return Ok(());
        } else {
            return err!(Errors::TransferFailed);
        }
    }

CpiCpiContext 中字面上的意思是“跨程序调用”。

调用除系统程序外的其他程序的公共函数的工作流程并没有太大的不同——我们将在本教程中教授这一点。

本教程只关注如何调用另一个使用 Anchor 构建的 Solana 程序。如果其他程序是用纯 Rust 开发的,则以下指南将无法使用。

在我们的示例中,Alice 程序将调用 Bob 程序上的一个函数。

Bob 程序

我们从使用 Anchor 的 CLI 创建一个新项目开始:

    anchor init bob

然后在 bob/lib.rs 中复制并粘贴下面的代码。该账户有两个函数,一个用于初始化存储一个 u64 的账户,另一个函数 add_and_store 接受两个 u64 变量,将它们相加并存储在由结构体 BobData 定义的账户中。

    use anchor_lang::prelude::*;
    use std::mem::size_of;

    // 替换为你的 <PROGRAM_ID>
    declare_id!("8GYu5JYsvAYoinbFTvW4AACYB5GxGstz21FmZe3MNFn4");

    #[program]
    pub mod bob {
        use super::*;

        pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
            msg!("数据账户已初始化: {}", ctx.accounts.bob_data_account.key());

            Ok(())
        }

        pub fn add_and_store(ctx: Context<BobAddOp>, a: u64, b: u64) -> Result<()> {
            let result = a + b;

            // 修改/更新数据账户
            ctx.accounts.bob_data_account.result = result;
            Ok(())
        }
    }

    #[account]
    pub struct BobData {
        pub result: u64,
    }

    #[derive(Accounts)]
    pub struct BobAddOp<'info> {   
        #[account(mut)]
        pub bob_data_account: Account<'info, BobData>,
    }

    #[derive(Accounts)]
    pub struct Initialize<'info> {
        #[account(init, payer = signer, space = size_of::<BobData>() + 8)]
        pub bob_data_account: Account<'info, BobData>,

        #[account(mut)]
        pub signer: Signer<'info>,

        pub system_program: Program<'info, System>,
    }

本教程的目标是创建另一个程序 alice,调用 bob.add_and_store

在项目(bob)内,使用 anchor new 命令创建一个新程序:

    anchor new alice

命令行将打印出 创建了新程序

在开始编写 Alice 的程序之前,必须将下面的代码片段添加到 Alice 的 Cargo.toml 文件的 [dependencies] 部分,位置为 programs/alice/Cargo.toml

    [dependencies]
    bob = {path = "../bob", features = ["cpi"]}

Anchor 在这里做了大量的后台工作。Alice 现在可以访问 Bob 的公共函数和 Bob 的结构体的定义。你可以将这视为在 Solidity 中导入接口,以便知道如何与另一个合约进行交互

下面是 Alice 程序。 在代码顶部,Alice 程序正在导入承载 BobAddOp(用于 add_and_store)的结构体。请注意代码中的注释:


    use anchor_lang::prelude::*;
    // account struct for add_and_store
    use bob::cpi::accounts::BobAddOp;

    // Bob 的程序定义
    use bob::program::Bob;

    // Bob 存储和的账户
    use bob::BobData;

    declare_id!("6wZDNWprmb9TAZYMAPpT23kHDPABvBLT8jbWQKLHEmBy");

    #[program]
    pub mod alice {
        use super::*;

        pub fn ask_bob_to_add(ctx: Context<AliceOp>, a: u64, b: u64) -> Result<()> {
            let cpi_ctx = CpiContext::new(
                ctx.accounts.bob_program.to_account_info(),
                BobAddOp {
                    bob_data_acco...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论