保护 Solana 生态系统 (1) — 你好 Solana

BlockSec 的 DApp 生态安全使命:了解 BlockSec 如何专注于 Solana 智能合约安全,致力于提升 DApp 生态系统的安全性。

保护 Solana 生态系统 (1) — 你好 Solana

1. 引言

Solana 是一个高性能、无需许可的 Layer 1 区块链系统,支持使用多种语言(例如 Rust、C++ 和 C)开发程序(智能合约)。借助 Tower BFT(拜占庭容错),它每秒可以处理数千笔交易。Solana 的核心创新之一是历史证明(PoH),这是一个在网络中可全局访问、无需许可的时间源,它在共识之前运行。我们将在未来更详细地讨论 PoH。

2. 我们的使命

BlockSec 是一家区块链安全公司,以“保护 DApp 生态系统”为使命。因此,我们不仅提供合约审计服务,还为整个社区提供有关如何编写安全智能合约的建议。考虑到 Solana 的流行度、高性能和出色的设计,本系列将重点关注 Solana 上 Rust 智能合约的安全性。

3. Hello Solana

在从安全角度讨论 Solana 智能合约之前,我们首先需要了解如何编写、编译和部署 Solana 智能合约。这里我们以 Hello World 为例进行说明。

3.1 代码审查

在 Solana 中,智能合约称为程序。 Hello World 程序旨在维护一个计数器,该计数器记录客户端调用目标账户(由程序拥有)的次数,并将此数字作为输出打印。

现在让我们逐步分析整个合约。

第 1 行到第 9 行使用 use 关键字显式引入了许多库。

第 12 行,[derive(BorshSerialize, BorshDeserialize, Debug)] 用于序列化和反序列化传递给结构体 GreetingAccount 的参数,该结构体从第 13 行到第 16 行定义。该结构体包含一个名为 counteru32 公有成员。之后,如注释所示,第 19 行导出了程序的入口点,即 process_instruction 函数。

process_instruction 函数接受三个参数(即 program_idaccounts_instruction_data)。请注意,program_id 是已部署程序的公钥(即地址),而 accounts 包含要问候的账户。_instruction_data 为空且未使用。

要了解有关 Solana 中程序和账户的更多信息,请参阅 Solana 文档

第 27 行,打印一条问候消息。从第 30 行到第 33 行,将遍历账户,并提取要问候的特定账户。之后,将检查账户的所有者,应将其与 program_id 进行比较,以确保程序可以写入该账户。最后,使用 try_from_slice 提取 greeting_account,并将计数器加 1。

3.2 编译程序

要编译程序,我们需要使用以下命令安装 Solana CLI

sh -c "$(curl -sSfL https://release.solana.com/v1.9.9/install)"

要确认 Solana CLI 已成功安装,我们可以使用以下命令检查其版本。

solana --version

请注意,RustNodeJS 也必需。

要编译程序,我们可以使用以下命令。

cargo build-bpf --manifest-path=./src/program-rust/Cargo.toml --bpf-out-dir=dist/program

编译后的程序将生成在 --bpf-out-dir 中指定的目录下的 helloworld.so 文件。

3.3 部署合约

要在 Solana 上部署编译后的程序,我们需要先选择一个集群。在 Solana 中,有四个不同的集群:主网、测试网、开发网和本地网。在本帖中,我们仅为演示在开发网上部署编译后的程序。

我们使用以下命令指定集群。

solana config set --url https://api.devnet.solana.com

之后,我们需要生成用于部署的钱包。 solana-keygen new --force 有助于生成钱包。有关更多信息,请查看 Solana 文档

由于新创建的账户没有余额来支付交易费用,因此我们使用以下命令空投 1 SOL。

solana airdrop 1 <YourPublicKey> --url https://api.devnet.solana.com

现在,我们已准备好部署合约。

solana program deploy dist/program/helloworld.so

用户可以在 Devnet Explorer 中查看程序和交易。在此演示中,您可以通过 此链接 找到已部署的程序。

3.4 发送交易

建议编写脚本,即所谓的客户端,来发送 Solana 交易。幸运的是,Solana 提供了 示例代码。要运行客户端,我们首先需要安装客户端依赖项。

npm install

安装完成后,我们使用以下命令运行 main.ts 文件中的 main 函数。

npm run start

main 函数中,客户端首先使用 establishConnection() 函数建立与指定集群(即开发网)的连接,使用 establishPayer 函数检查支付交易费用的付款人,并使用 checkProgram 函数验证程序和要问候的账户是否存在。请注意,如果所需账户不存在,它将被创建,发送一个交易。在我们的演示中,该账户已在此 交易 中创建。

当一切就绪后,将调用 sayHello 函数向目标账户发送问候。交易包含一个指令。此指令接收包含一个账户的 keys。该账户的公钥(即 greetedPubkey)是要问候的目标账户。请注意,此账户用于存储,而不是签名者。在这种情况下,isSigner 属性为 false,而 isWritabletrueprogramIdgreetedPubkey 的所有者,也是已部署合约的地址。请注意,data 为空,并且在此交易中不会使用。在第 208 行,调用 sendAndConfirmTransaction 函数,交易将被发送到集群。

您可以在 这里 查看详细交易。

4. 结论

在本文中,我们简要介绍了 Solana 的背景,并回顾了示例项目(即 Hello World)。我们学习了如何在 Solana 上部署程序,以及如何使用客户端与链上程序进行交互。请继续关注我们的博客,我们将持续发布本系列的更多文章。

阅读本系列的另一篇文章:

Sign up for the latest updates