0. 回顾
1. 概述
在上一篇 博客 中,我们介绍了如何通过 invoke 和 invoke_signed 函数实现跨程序调用。在本文中,我们将介绍另一个基础主题——程序升级。
2. 部署可升级程序
默认情况下,Solana 上部署的所有程序都使用 BPFLoaderUpgradeable 加载器进行部署,这意味着它们可以被升级。除此之外,Solana 还提供了 --final 选项来确保部署的程序是不可变的。在这种情况下,将使用 BPFLoader2 加载器来部署程序。部署后,程序将无法升级。
BPFLoaderUpgradeable 加载器程序管理三种类型的账户:程序账户、程序数据账户 和 缓冲区账户。在部署过程中,首先会创建一个缓冲区账户。然后,Solana CLI 会加载目标程序的字节码并将其写入缓冲区账户。最后,存储在缓冲区账户中的字节码将被复制到程序数据账户。
因此,可升级 BPF 加载器在部署过程中使用缓冲区账户临时存储字节码,程序数据账户存储程序的实际数据,而程序账户充当指向相应程序数据账户的代理。
接下来,我们将通过几个示例来演示如何升级你的程序。本文中使用的所有代码都可以在 这里 找到。
2.1 代码审查 (Rectangle_Area)

在这个示例合约中,我们在第 13 至 17 行定义了一个名为 Rectangle 的结构体,其中包含三个属性:width、height 和 area。我们还为 Rectangle 定义了一个 area() 函数。area() 函数用于使用 width 和 height 计算矩形的面积。

在 process_instruction() 函数中,我们首先使用 unpack_u32() 函数从指令数据中提取矩形的 width 和 height(第 45-46 行)。在第 51 行,我们提取用于存储矩形数据的账户。在第 59 行,try_from_slice_unchecked() 函数使用 Rectangle 结构体类型反序列化账户数据。接下来,我们将数据分配给结构体的相应字段并计算 area 的值(第 61-63 行)。最后一步是序列化数据,并将其写回数据账户。
已部署的程序可以在以下链接中找到。
https://explorer.solana.com/address/84mMqHRTQT6b2vfsD7XRxVKA3XMd7xoEXFdF6pLNw8y?cluster=testnet
2.2 发送交易

在客户端,我们首先发送一笔交易来创建一个用于存储数据的账户。我们将空间大小设置为 1024 字节,以确保其足够。

然后,我们发送另一笔交易来计算矩形的面积并将其存储到数据账户中。
交易可以在以下链接中找到。
https://explorer.solana.com/tx/4PybjXGRpuPKpak7FAz4BKMbcQCWmway69zAxtTnpFRuTTg7onyxW7agSe6ETx44iAGexbgnBUa8WdzdTTQSawJ3?cluster=testnet
3. 升级
现在,我们想在程序中添加一个新功能,即计算矩形的周长。

编译更新后的项目后,我们使用以下命令在链上升级已部署的程序。
solana program deploy /path/to/program.so --program-id <PROGRAM_ID>
该合约可以直接升级,您可以在下方查看相关交易。
https://explorer.solana.com/tx/4Dm9v4zMiijKjQBhatx1D9xbV9PvMLdaonUWLaC2VwzkFvzdgorzbX5vsy4VQ7VxSUmqadftjiDzbyUmXgQchYmk?cluster=testnet
我们进一步向程序发送了一笔交易,以验证升级是否成功。结果显示该功能运行良好。
相关交易可以在下方找到。
https://explorer.solana.com/tx/21c2G7kPVktAtdUFkH3QwGVi7orajRmy5PJo1UxX1mmAMU68eUkNuLzWYJRBaTzwGi5DxeocYjHfpWiU4hcSFtpQ?cluster=testnet
4. 再次升级

这次我们想将计算出的周长存储到数据账户中。在这种情况下,我们在 Rectangle 结构体中添加了一个名为 perimeter 的新属性(第 18 行)。

由于数据账户的结构与之前不同,我们需要先从数据账户中读取数据。我们使用原始结构体(即 OldRectangle)反序列化存储的数据。之后,我们将相关属性分配给新结构体(即 CurrentRectangle)并初始化新属性(即 perimeter)。

最后,我们计算 perimeter 的值并将其分配回 update_account,然后将其序列化到 account_data 中。
升级交易可以在下方找到。
https://explorer.solana.com/tx/5J3oKxZXtCi755gD7pMnVh48AFvmeVzRLPgJiyNn8JFeCKx1xpAfJtsi34zjyYKJmnMk8LtC3bcwfFSP7H2gtj5o?cluster=testnet
升级后,我们可以使用 solana account <DataAccount> 命令查看存储在账户中的数据。您会发现属性存储在前 32 个字节中。整个升级过程完成。

5. 结论
在本文中,我们介绍了程序如何在 Solana 中进行升级。我们使用不同的示例来说明详细过程。敬请期待更多关于 Solana 的文章。
阅读本系列的更多文章:
- 保护 Solana 生态系统 (1) — 欢迎来到 Solana
- 保护 Solana 生态系统 (2) — 程序间的调用
- 保护 Solana 生态系统 (4) — 账户验证
- 保护 Solana 生态系统 (5) — 多重签名
- 保护 Solana 生态系统 (6) — 多重签名2
- 保护 Solana 生态系统 (7) — 类型混淆
关于 BlockSec
BlockSec 是一家开创性的区块链安全公司,由一群全球知名的安全专家于 2021 年创立。公司致力于为新兴的 Web3 世界增强安全性和可用性,以促进其大规模采用。为此,BlockSec 提供智能合约和 EVM 链 安全审计 服务,用于主动开发和阻止威胁的 Phalcon 平台,用于资金追踪和调查的 MetaSleuth 平台,以及供 Web3 构建者在加密世界中高效冲浪的 MetaSuites 扩展。
迄今为止,公司已为 MetaMask、Uniswap Foundation、Compound、Forta 和 PancakeSwap 等 300 多家尊贵客户提供服务,并在两轮融资中从 Matrix Partners、Vitalbridge Capital 和 Fenbushi Capital 等知名投资者那里获得了数千万美元的投资。
官方 Twitter 账号:https://twitter.com/BlockSecTeam



