返回博客

保护 Solana 生态系统 (3) — 程序升级

2022年3月27日
阅读约 5 分钟

0. 回顾

1. 概述

在上一篇 博客 中,我们介绍了如何通过 invokeinvoke_signed 函数实现跨程序调用。在本文中,我们将介绍另一个基本主题——程序升级。

2. 部署可升级程序

默认情况下,所有已部署的程序都使用 Solana 的 BPFLoaderUpgradeable 加载器进行部署,这意味着它们可以被升级。除此之外,Solana 还提供了 --final 选项来确保部署的程序是不可变的。在这种情况下,将使用 BPFLoader2 加载器来部署程序。一旦部署,程序将无法被升级。

BPFLoaderUpgradeable 加载器程序管理三种类型的账户:程序账户程序数据账户缓冲区账户。在部署过程中,首先会创建一个缓冲区账户。然后,Solana CLI 会加载目标程序的字节码并将其写入缓冲区账户。最终,存储在缓冲区账户中的字节码将被复制到程序数据账户中。

因此,可升级 BPF 加载器在部署过程中使用缓冲区账户来临时存储字节码,程序数据账户存储程序的实际数据,而程序账户则充当指向相应程序数据账户的代理。

接下来,我们将通过几个示例来演示如何升级你的程序。本文使用的所有代码都可以在 这里 找到。

2.1 代码审查(Rectangle_Area)

在此示例合约中,我们定义了一个名为 Rectangle 的结构体,该结构体包含三个属性:widthheightarea(从第 13 行到第 17 行)。我们还为 Rectangle 定义了一个 area() 函数。area() 函数用于计算矩形的面积,使用 widthheight

process_instruction() 函数中,我们首先使用 unpack_u32() 函数从指令数据中提取矩形的 widthheight(第 45-46 行)。在第 51 行,提取用于存储矩形数据的账户。在第 59 行,try_from_slice_unchecked() 函数使用 Rectangle 结构体类型对账户数据进行反序列化。接下来,我们将数据分配给结构体的相应字段并计算面积值(第 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)。

最后,我们计算周长值并将其分配回 update_account,然后将其序列化到 account_data 中。

升级交易可在下方找到。

https://explorer.solana.com/tx/5J3oKxZXtCi755gD7pMnVh48AFvmeVzRLPgJiyNn8JFeCKx1xpAfJtsi34zjyYKJmnMk8LtC3bcwfFSP7H2gtj5o?cluster=testnet

升级后,我们可以使用 solana account <DataAccount> 命令检查存储在账户中的数据。您会发现属性存储在前 32 个字节中。整个升级过程完成。

5. 结论

在本文中,我们介绍了如何在 Solana 中升级程序。我们使用不同的示例来说明详细过程。敬请期待更多关于 Solana 的文章。

阅读本系列其他文章:


关于 BlockSec

BlockSec 是一家开创性的区块链安全公司,成立于 2021 年,由一群世界顶尖的安全专家创立。公司致力于提升新兴 Web3 世界的安全性和可用性,以促进其大规模采用。为此,BlockSec 提供智能合约和 EVM 链 安全审计 服务、用于安全开发和主动阻止威胁的 Phalcon 平台、用于资金追踪和调查的 MetaSleuth 平台,以及供 Web3 构建者在加密世界中高效冲浪的 MetaSuites 扩展。

截至目前,公司已为 MetaMask、Uniswap Foundation、Compound、Forta 和 PancakeSwap 等 300 多家知名客户提供服务,并通过 Matrix Partners、Vitalbridge Capital 和 Fenbushi Capital 等知名投资者的两轮融资,获得了数千万美元的资金。

官方网站:https://blocksec.com/

官方 Twitter 账号:https://twitter.com/BlockSecTeam

订阅最新动态
Web3攻击面:渗透测试概览

Web3攻击面:渗透测试概览

加密机构承载所有传统攻击面,并叠加资金处理链。本文提供系统的实用抽象:应用、授权与签名、区块链交互、基础设施四组件模型,说明各自职责、代表实现及继承的攻击面,并将web3特有覆盖细分为五大攻击面:生产与自动化运维、签名意图、审批与提现链、资金逻辑及链上交易与已部署合约。

损失约2300万美元:Cosmos EVM与Moonwell遭利用攻击 | BlockSec Weekly
Security Insights

损失约2300万美元:Cosmos EVM与Moonwell遭利用攻击 | BlockSec Weekly

在报告期(2026/08/22-2026/08/30)内,我们统计5起区块链安全事件,损失约2270万美元;Tectonic被盗约7400万-1.195亿美元,因Cronos回滚至攻击前状态而多数被抹除。重点是六链Cosmos EVM漏洞系列(实现约570万美元),经TAC Chain溯源,共享余额同步漏洞串联下溢与上溢耗尽质押池。报告还分析了Moonwell的抵押品核算与预言机价格操纵组合攻击、Tectonic的预言机价格与凭证代币汇率操纵低流动性抵押品、Ajna清算业务逻辑缺陷,以及Solana上的Rain Card Contract Exploit Series(Ed25519签名验证绕过,涉及Avici、Tria等)。

什么是区块链渗透测试?定义与边界
Security Services

什么是区块链渗透测试?定义与边界

区块链渗透测试尚无公认定义,常与审计、扫描、赏金测试混淆。本文提出工作定义:在约定范围与规则下,对运行系统进行对抗性实测,验证可利用路径与控制链;并指出web3新增的资金处理威胁模型,其关键组合缺口在链下到链上的交接。随后梳理该链条的五项可测能力,并将相关目标分流至代码审计、钱包安全审计、web3安全测试、扫描与赏金测试。