Solana 60 天课程

2025年02月27日更新 89 人订阅
原价: ¥ 53 限时优惠
专栏简介 开始 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) SPL Token 的运作方式 使用 Anchor 和 Web3.js 转移 SPL Token Solana 教程 - 如何实现 Token 出售 基础银行教程 Metaplex Token 元数据工作原理 使用Metaplex实施代币元数据 使用 LiteSVM 进行时间旅行测试 Solana Token-2022 标准规范 生息代币第一部分 计息代币第二部分 Solana 指令自省 Solana 中的 Ed25519 签名验证 Solana - Switchboard 预言机使用 原生Solana:程序入口与执行 原生 Solana :读取账户数据 原生 Solana :Borsh 序列化 原生 Solana:使用 invoke 和 invoke signed 进行跨程序调用 原生 Solana :创建存储账户 (一) 原生 Solana:创建存储账户 二 原生 Solana: 函数分发 原生 Solana:关键安全检查 Rust 程序到 SBF 编译 sBPF 虚拟机和指令集介绍 跟踪 sBPF 指令执行和计算成本 Solana 程序执行与输入序列化 指令处理器和运行时设置 sBPF 内存布局和寄存器约定 使用 sBPF 汇编读取 Solana 指令输入 Solana 系统调用:sBPF 汇编中的日志记录

指令处理器和运行时设置

文章详细阐述了Solana程序的指令处理器和运行时设置。它解释了entrypoint!宏如何分发指令,以及Solana程序在no_std环境下如何使用自定义堆分配器和panic处理器来管理内存和错误处理,并区分了原生Rust和Anchor程序的实现方式。

指令处理器和运行时设置

在第一部分中,我们介绍了Solana程序输入序列化格式以及程序输入如何在内存中布局。在这一部分中,我们将介绍程序如何将传入的程序输入路由到适当的处理程序,以及入口点为了实现此功能而设置的辅助代码。

指令处理器

入口点函数(由 entrypoint! 宏生成)将原始字节数组反序列化为 program_idaccountsinstruction_data,然后将它们传递给指令处理器。指令处理器读取 instruction_data 来确定哪个处理程序应该执行——这类似于Solidity合约如何根据函数选择器路由函数调用。

指令处理器必须由你的程序本身定义。入口点不提供此函数,它只定义你的指令处理器必须匹配的类型签名。此类型定义为:

Copypub type ProcessInstruction = fn(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult;

你的程序必须创建一个匹配此签名(接受这三个程序输入并返回 ProgramResult)的函数,然后将其传递给 entrypoint! 宏(我们将在下面看到这如何工作)。你如何创建此函数取决于你是使用Anchor还是编写原生Rust程序。

在原生Rust程序中,你定义一个具有此确切签名的函数并将其传递给我们之前提到的 entrypoint! 宏。此函数通过检查指令数据来处理指令路由逻辑,以确定要调用哪个函数。我们的原生Rust Solana程序系列详细介绍了如何实现这一点。

在Anchor程序中,#[program] 宏会自动为你生成指令处理器。#[program] 模块中的每个公共函数都成为一个指令处理程序,Anchor根据从函数名派生的 discriminator 生成路由逻辑。这是Anchor抽象掉样板代码并使程序开发更便捷的方式之一。

当指令处理器返回 Ok(()) 时,入口点返回 SUCCESS (0)。如果它返回一个错误,入口点将该错误转换为错误代码并返回。

以下是 entrypoint! 宏中所有部分的组合方式:

Copy#[macro_export]
macro_rules! entrypoint {
    ($process_instruction:ident) => {
        /// # 安全性
        #[no_mangle]
        pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
            let (program_id, accounts, instruction_data) = unsafe { $crate::deserialize(input) };
            match $process_instruction(program_id, &accounts, instruction_data) {
                Ok(()) => $crate::SUCCESS,
                Err(error) => error.into(),
            }
        }
        $crate::custom_heap_default!();
        $crate::custom_panic_default!();
    };
}

该宏生成的代码会反序列化输入(使用我们之前讨论的 deserialize 函数)以提取三个程序输入,将它们传递给你的 process_instruction 函数,并处理结果。

请注意最后另外两个宏调用:custom_heap_default!()custom_panic_default!()。这些宏设置了你的程序运行所需的关键基础设施,所以让我们看看它们的作用。

**自...

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

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

0 条评论

请先 登录 后评论