部署程序
构建程序
在部署之前,必须先将 Rust 代码编译为 Solana 可执行的 BPF 字节码。
bashanchor build
这会在 target/deploy/ 目录生成两个关键文件:
<program-name>.so:编译后的程序字节码(共享对象文件)。<program-name>-keypair.json:程序的密钥对。如果你是第一次构建,Anchor 会自动生成它。这个密钥对的公钥就是你的 Program ID。
获取程序地址
在部署前,务必检查代码中声明的 ID 与生成的密钥对是否匹配。
bashsolana address -k target/deploy/solana_university_counter-keypair.json
确保 lib.rs 中的 declare_id!() 宏填写的地址与上述命令输出的地址一致。如果不一致,部署后的程序将无法验证通过。
配置部署目标
编辑项目根目录下的 Anchor.toml 文件,配置网络和钱包:
toml[provider] cluster = "devnet" # 目标集群:localnet, devnet, mainnet wallet = "~/.config/solana/id.json" # 部署者钱包路径 [programs.devnet] solana_university_counter = "So1Univ..." # 你的程序 ID [programs.mainnet] solana_university_counter = "So1Univ..."
部署到 Devnet
部署需要消耗 SOL 作为存储租金。对于简单的程序,通常需要 2-5 SOL。
bash# 1. 切换到 devnet solana config set --url devnet # 2. 获取测试 SOL (可能需要多次领取) solana airdrop 2 # 3. 执行部署 anchor deploy
处理部署失败
Solana 程序的部署不是一笔交易完成的,而是分片上传到一个临时的 Buffer 账户,最后一步才是写入程序账户。如果网络中断,Buffer 账户会残留,占用你的 SOL。
Anchor 在部署失败时会提示你 Buffer 的地址。你可以选择恢复或关闭它:
bash# 选项 A: 继续部署 (断点续传) # 需要用到中间生成的缓冲密钥对 solana program deploy ./target/deploy/my_program.so --program-id ./target/deploy/my_program-keypair.json --buffer ./recovered-keypair.json # 选项 B: 放弃部署,回收租金 solana program close <BUFFER_ADDRESS>
网络拥堵时的部署技巧
在主网拥堵时,普通的部署交易可能会被丢弃。可以使用 solana-cli 的高级参数:
bashsolana program deploy ./target/deploy/my_program.so --program-id ./target/deploy/my_program-keypair.json --with-compute-unit-price 10000 # 支付优先费 (MicroLamports) --use-rpc # 使用 RPC 而非 TPU 发送 (更稳定但更慢) --max-sign-attempts 100 # 增加重试次数
升级程序
Solana 程序默认是可升级的。如果你修复了 bug 或添加了功能,可以保留原地址升级代码:
bash# 1. 检查新版本大小 # 如果新编译的 .so 文件比原来的大,必须先扩展程序账户空间 solana program extend <PROGRAM_ID> <ADDITIONAL_BYTES> # 2. 执行升级 anchor upgrade target/deploy/my_program.so --program-id <PROGRAM_ID>
使程序不可变 (Immutable)
当项目成熟,为了赢得社区信任,你可能需要放弃升级权限,使代码永久不可更改。
bashsolana program set-upgrade-authority <PROGRAM_ID> --final
⚠️ 警告:此操作不可逆!一旦执行,即使发现严重 Bug 也无法修复,只能部署新合约并迁移数据。
上传 IDL
IDL (Interface Definition Language) 描述了你的程序接口。将其上传到链上,可以让区块浏览器(如 Solana Explorer)自动解析你的指令数据,也方便前端通过 Program.at() 动态加载。
bash# 初始化 IDL 账户 (第一次) anchor idl init --filepath target/idl/my_program.json <PROGRAM_ID> # 更新 IDL (当接口变更时) anchor idl upgrade --filepath target/idl/my_program.json <PROGRAM_ID>
IDL 存储在一个独立的账户中,地址由 Program ID 派生,且同样需要支付租金。
可验证构建 (Verifiable Build)
为了证明链上运行的二进制代码确实是由开源的 Rust 代码编译而来,Anchor 提供了 Docker 构建方案:
bash# 使用官方 Docker 镜像进行构建,确保环境一致性 anchor build --verifiable # 验证已部署的程序 (比对链上数据与本地构建结果的哈希) anchor verify -p my_program <PROGRAM_ID>