程序升级
软件总是需要修补的
在以太坊的早期,智能合约一旦部署就无法修改。如果发现了 Bug,或者想要添加新功能,开发者必须部署一个全新的合约,然后通知所有用户迁移资金和数据到新地址。这不仅麻烦,而且风险极高。
Solana 吸取了教训,从 BPF Loader Upgradeable (v3) 开始,将“可升级性”作为默认选项。
1. 可升级架构:外壳与内核
Solana 的可升级程序由两个账户组成,实现了接口与实现的分离:
-
Program Account (程序账户)
- 角色:外壳 / 代理 / 入口。
- 地址:这就是众所周知的 Program ID (如
Tokenkeg...)。 - 内容:它不存代码!它只存储一个指针,指向实际存放代码的地方。
- 特点:地址永远不变。用户和前端永远只跟这个地址交互。
-
ProgramData Account (数据账户)
- 角色:内核 / 实现。
- 内容:存储实际编译好的
.so字节码 (ELF)。 - 权限:记录了 Upgrade Authority (升级管理员)。只有拥有这个私钥的人才能修改这里的字节码。
当用户调用程序时,运行时加载器会先找到 Program Account,顺藤摸瓜找到 ProgramData Account,加载里面的字节码并执行。
2. 升级流程
升级过程对用户是完全透明的,因为 Program ID 没有变。
- 编译新代码:修复 Bug,编译出新的
.so文件。 - 写入 Buffer:将新代码上传到一个临时的 Buffer 账户(和初次部署一样)。
- 执行升级:管理员发送
Upgrade指令。- Loader 会将 Buffer 中的新字节码替换掉 ProgramData Account 中的旧字节码。
- Buffer 账户随之关闭,租金退还。
python# 使用代码进行升级 import pathlib import pxsol ada = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(0x01)) program_pubkey = pxsol.core.PubKey.base58_decode('DVapU9kv...K5E') # 读取新版本的字节码 new_code = pathlib.Path('target/deploy/solana_storage_v2.so').read_bytes() # 发起升级交易 ada.program_update(program_pubkey, new_code) print("✅ 程序已升级到 v2")
3. 放弃权限:通往去中心化
可升级是一把双刃剑。虽然方便了修复 Bug,但也意味着开发者可以随时“作恶”(比如修改代码卷走资金)。
在 DeFi 项目成熟后,为了赢得社区信任,开发者通常会放弃升级权限,使程序变得不可变 (Immutable)。
操作很简单:将 Upgrade Authority 设置为 None (null)。
一旦执行,没人(包括开发者自己)能再修改代码。程序将永远按照既定逻辑运行,直到 Solana 链停止运转。
bash# 命令行放弃权限 solana program set-upgrade-authority <PROGRAM_ID> --final