本指南旨在为希望在 Solana 上为其程序实现验证构建的开发者提供参考。我们将介绍什么是验证构建、如何使用它们、需要注意的特殊事项以及确保程序链上真实性的最佳实践。
什么是验证构建?
验证构建确保您部署到 Solana 网络的可执行程序与您代码库中的源代码相匹配。通过这样做,开发者和用户可以确信链上运行的程序与公共代码库完全一致,从而促进透明性和安全性。
验证过程包括将链上程序的哈希值与从源代码本地构建的程序的哈希值进行比较。这确保了两者之间没有差异。
虽然验证构建不应被认为比未验证构建更安全,但它使开发者能够自行验证源代码与链上部署的内容相匹配。使用源代码,开发者可以验证代码在发送交易时执行的内容。
验证构建流程由 Ellipsis Labs 和 OtterSec 设计并维护。有关更多详细信息,请参阅 原始验证构建 库中的指南,以及在 Anza 工具套件中直接支持的验证构建流程(支持后)。
它是如何工作的?
验证过程是通过比较链上程序的哈希值与从源代码本地构建的程序的哈希值来完成的。您可以使用 Solana Verify CLI 和 Docker 在受控环境中构建您的程序。这确保了构建过程在不同系统之间是确定性和一致的。一旦您获得了可执行文件,您就可以将其部署到 Solana 网络。在构建过程中,会创建一个 PDA(程序派生地址)用于 verify program。这个 PDA 包含验证程序所需的所有数据。PDA 包括程序地址、Git URL、提交哈希值以及用于构建程序的参数。
通过 PDA 中的数据,任何人都可以在本地运行 verify program 命令,检查程序是否是从提供的源代码构建的。然后,任何人都可以完全无需信任地自行验证,或者运行由 OtterSec 维护的 verify API,为用户提供一个便捷的验证访问点。您已经可以在 Solana Explorer 和 SolanaFM 等平台上看到这些 API 调用 的使用。
为什么我应该使用已验证的构建?
使用已验证的构建可以带来以下好处:
-
安全性:保证链上运行的程序与源代码一致,防止恶意篡改。
-
透明性:允许其他用户和开发者通过与公共代码库进行比较来验证链上程序的可信度。
-
信任:提高用户信心,因为已验证的构建表明您的程序链上行为与您的公共代码一致。在构建可验证程序时,您可以最大限度地减少运行未经授权或恶意代码的风险。这也确保您遵循最佳实践,并为安全研究人员提供一种简单的联系方式。此外,只要程序经过验证,钱包和其他工具也可以更轻松地允许来自您的程序的交易。
-
可发现性:当您提供经过验证的程序构建版本时,所有人都可以找到您的源代码、文档、程序 SDK 或 IDL,并且如果出现问题,他们还可以通过 GitHub 轻松联系您。
如何创建经过验证的构建?
要创建经过验证的构建,您需要按照以下步骤操作:
摘要:
- 将您的代码提交到公共代码库
- 在 Docker 中构建一个经过验证的构建
- 部署经过验证的构建
- 根据公共 API 验证已部署的程序
如果您验证的程序不是在 Docker 容器中构建的,很可能会失败,因为 Solana 程序构建在不同系统之间并非确定性一致。
安装 Docker 和 Cargo
安装必要的工具,确保您已安装 Docker 和 Cargo。Docker 提供了一个受控的构建环境以确保一致性,而 Cargo 用于管理 Rust 包。
- Docker:按照 Docker 网站 上的步骤为您的平台安装 Docker。安装完成后,确保 Docker 服务正在运行,并继续按照本指南操作。
- Cargo:如果您尚未安装 Cargo,可以通过运行以下命令进行安装:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装 Solana Verify CLI
Solana Verify CLI 是用于验证构建的主要工具。Solana Verify CLI 目前由 Ellipsis Labs 维护,可以通过 Cargo 安装。
您可以通过运行以下命令安装:
cargo install solana-verify
如果您需要特定版本的 CLI,可以通过以下方式固定版本:
cargo install solana-verify --version $VERSION
如果需要,您还可以直接从特定提交中安装一个版本:
cargo install solana-verify --git https://github.com/Ellipsis-Labs/solana-verifiable-build --rev 13a1db2
准备项目
要针对仓库进行验证,仓库根目录下需要有一个 Cargo.lock
文件。如果你的仓库中只有一个程序,并且根目录下有 cargo.lock
文件,你可以直接进入下一步并构建你的程序。
如果你的程序在子文件夹中,并且你有一个 Rust
workspace,则需要在仓库根目录下创建一个 workspace Cargo.toml 文件。
你可以将此 Cargo.toml 示例作为预设:
[workspace]members = ["program/programs/*"]resolver = "2"[profile.release]overflow-checks = truelto = "fat"codegen-units = 1[profile.release.build-override]opt-level = 3incremental = falsecodegen-units = 1
请确保你的程序在 workspace/members 数组中,并且你的程序的 Cargo.toml
已正确配置 lib 名称。
重要的是
lib name,而不是 package 名称!
类似于以下内容:
[package]name = "waffle"version = "0.1.0"edition = "2021"[lib]name = "waffle"crate-type = ["cdylib", "lib"][dependencies]solana-program = "2.1.0"
在这个 repository
中,你可以看到一个包含子文件夹程序的 workspace 示例。还要注意,当程序在子文件夹中时,后续需要将该文件夹作为
--mount-path 添加到 verify-from-repo 命令中。
在这个 存储库 中,您可以找到一个 Anchor 示例。在这个 存储库 中,您可以找到一个原生 Rust 示例。
有了这个 Cargo.toml 文件后,你可以运行
cargo generate-lockfile,以创建 lock 文件并继续构建你的程序。
构建可验证程序
要可验证地构建你的 Solana 程序,请进入包含 workspace Cargo.toml
文件的目录并运行:
solana-verify build
这将把您的环境复制到一个 Docker 容器中,并以确定性的方式构建它。
请确保你实际部署的是已验证的构建版本,不要意外地用
anchor build或cargo build-sbf覆盖它,因为这些很可能不会生成相同的哈希值,从而导致验证失败。
对于包含多个程序的项目,可以使用库名称(而不是包名称)来构建特定的程序:
solana-verify build --library-name $PROGRAM_LIB_NAME
此过程可确保构建的确定性,但可能需要一些时间,尤其是在某些系统(例如 M1 MacBook)上,因为它是在 docker 容器中运行的。为了加快构建速度,建议使用运行 x86 架构的 Linux 机器。
构建完成后,可以使用以下命令检索可执行文件的哈希值:
solana-verify get-executable-hash target/deploy/$PROGRAM_LIB_NAME.so
部署可验证程序
在构建程序并检索其哈希值后,可以将其部署到 Solana 网络。建议使用多签名或治理解决方案(例如 Squads Protocol)进行安全部署,但也可以直接部署:
solana program deploy -u $NETWORK_URL target/deploy/$PROGRAM_LIB_NAME.so --program-id $PROGRAM_ID --with-compute-unit-price 50000 --max-sign-attempts 100 --use-rpc
您可以从 rpc 提供商(例如 Quicknode)请求当前适合的低优先级费用。
要验证已部署的程序与构建的可执行文件是否匹配,请运行:
solana-verify get-program-hash -u $NETWORK_URL $PROGRAM_ID
您可能在不同的 Solana 集群(例如 devnet、testnet、mainnet)上部署了不同的版本。确保使用正确的网络 URL 来验证目标 Solana 集群上的程序。远程验证仅适用于 mainnet。
与存储库进行验证
要将程序与其公共存储库进行验证,请使用:
solana-verify verify-from-repo -u $NETWORK_URL --program-id $PROGRAM_ID https://github.com/$REPO_PATH --commit-hash $COMMIT_HASH --library-name $PROGRAM_LIB_NAME --mount-path $MOUNT_PATH
当你在程序目录下运行已验证的构建时,执行
verify-from-repo时需要添加--mount-path标志。这个参数应为包含Cargo.toml的文件夹路径,该文件夹中包含你程序的库名称。
此命令将链上程序的哈希值与从指定提交哈希的源代码构建的可执行文件哈希值进行比较。
最后,命令会询问您是否希望将验证数据上传到链上。如果您选择上传,Solana Explorer 将立即显示您程序的验证数据。在通过远程构建验证之前,它将显示为未验证。了解如何在下一步中通过公共 API 验证您的程序。
如果你想将验证锁定到某个特定版本,可以在命令后追加 --commit-hash 标志。
通过公共 API 验证
最后,您还可以直接通过运行验证 API 的任何人验证程序:
solana-verify verify-from-repo --remote -um --program-id PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY https://github.com/Ellipsis-Labs/phoenix-v1
建议使用付费 RPC Url,否则你可能会遇到免费 RPC 的速率限制。因此,建议你用
--url yourRpcUrl替代-um,以获得更可靠的验证体验。
--remote 标志会向 OtterSec
API 发送构建请求,触发你的程序的远程构建。构建完成后,系统会验证你程序的链上哈希值是否与从代码库生成的构建工件哈希值一致。
默认使用 OtterSec API。
当被询问是否将验证数据上传到链上时,请确保选择“是”。API 会使用此数据验证您已上传的验证数据。
您还可以通过以下方式手动触发远程任务:
solana-verify remote submit-job --program-id <program-id> --uploader <address>
上传者是具有写入 PDA 权限的地址。在大多数情况下,这应该是程序权限。如果您的程序由多签控制,请继续阅读本指南下方的 多签验证 部分。
这将向 OtterSec API 提交一个任务,您可以通过以下方式验证任务状态:
solana-verify remote get-job-status --job-id <job-id>
一旦验证成功完成(可能需要一些时间),您将能够在以下位置看到您的程序已被验证: 单个程序的 OtterSec API、 Solana Explorer、 SolanaFM、 SolScan,以及最终在社区运营的网站 SolanaVerify.org(由 0xDeep 维护)和 OtterSec 验证程序 API,最后在 Verified Programs Dune Dashboard 上显示,为更健康的 Solana 生态系统做出贡献。
如何验证由 Squads 等多签控制的程序
为了使远程验证生效,您需要将验证数据写入由程序权限签名的 PDA。如果您的程序由多签控制,您可以导出此写入 PDA 的交易,并通过 Squads Protocol 或您选择的其他多签解决方案提交。
2. 部署程序
solana config set --url "PayedMainnetRPCAddress" // the public endpoint will be rate limited too muchsolana program deploy target/deploy/verify_squads.so
在本多签指南的其余部分,我们将使用示例程序 ID
6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD。
3. 提交并验证到存储库
完成后,我们将项目提交到 GitHub。以下是一个示例: https://github.com/solana-developers/verify-squads
可选:你可以先尝试在本地验证(此命令使用示例程序 ID
6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD):
solana-verify verify-from-repo https://github.com/solana-developers/verify-squads --program-id 6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD
确保您的参数是正确的。
4. 将程序权限转移到多签账户
如果您尚未将程序权限转移到多签账户,请执行此操作并复制多签账户的权限。在下一步中您将需要它。
5. 导出 PDA 交易
当你在本地拥有程序权限时,使用 solana-verify verify-from-repo
命令会提示你上传构建数据到链上。
由于使用多签账户时无法直接执行此操作,您需要手动导出 PDA 交易,然后通过 Squads 触发交易。
solana-verify export-pda-tx https://github.com/solana-developers/verify-squads --program-id 6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD --uploader <your program authority> --encoding base58 --compute-unit-price 0
这将返回一个 base58 交易。如果你需要用于交易分析器的 base64 编码交易,可以使用
--encoding base64。
P6vBfcPaaXb8fZoT3NBAYEcdtEj7tubA1k2gBxmFKZ3UWF5YyrmDMFTvLKALCJoUuRsPAjMckudYruCu3eeWQtuDrFbEMLxLFutnKXac974fnkMivcwUdY66VLjbxQT6ATmcy7F4hBtz1G4P1h6iBJLhb8WtrtgY3i4qq45MUEb7RjuMEfUFXKrNgPdGxkz5xvMHq3dxKRcpmEK5k2DkeW6SUQYBVe19Ga3B9GyhTX8k3CMt9JCEah13WyRnQd8GjoK6sTEvGJym6xDNvmd8yiJYSNcaYwEJsjHEUf4Yh6kAC7ki2KRvVAr3NVe1gjqK9McrwSQjtUatvydTG8Zovcr7PPUEMf3yPMgKXjZLB2QpkH63yTTYdNAnWFuv9E6b6nYRqye5XcNi436yKw5U14fXh65yK34bgYLi9328UT1huJELsJU9BRGnGUmb6GWp6c2WL5BhnzgNTSnt9TXFfEgUMzhvKzpVBxLP44hwqqBdyUhHFysCF37531PnmiESq8x1xou23xJ6FcQbc199754MkqQd7tX9CUznGzAEqHGkzn3VBoJnojsKtgYmiTYbdRsT1CU18MbYEE7WvGAvXyxxbpNzbAcc94HrnM6cqRGmwhEBroPfFghTdmzg9D
6. 通过 Squads 提交交易
前往 Squads 交易构建器并导入 base58 编码的交易。确保在模拟中,交易仅调用 osec 验证程序和计算预算程序,且没有其他内容!
7. 提交远程验证任务
当交易成功提交到 Squads 后,您可以提交远程任务:
solana-verify remote submit-job --program-id 6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD--uploader <your program authority>
就是这样!您已成功将程序验证到公共存储库,并向 OtterSec API 提交了远程任务。现在,您应该可以在 Solana Explorer 和其他地方看到它的反映。
8. 更新程序(可选)
当您更新程序时,需要导出一个新的 PDA 交易,并再次通过 Squads 提交。
更新程序的步骤:
solana-verify buildsolana program write-buffer target/deploy/verify_squads.so --with-compute-unit-price 50000 --max-sign-attempts 50
然后将该缓冲区的权限转移到多签名账户,或者直接创建一个具有多签名账户权限的缓冲区。
solana program set-buffer-authority Fu3k79g53ZozAj47uq1tXrFy4QbQYh7y745DDsxjtyLR --new-buffer-authority 3JG6ULvZVCrkKtSSskKNJGe8RNZGFe8Ruev9KUhxzK5K
9. 导出并提交新的 PDA 交易
别忘了将您的更改提交到 GitHub。再次导出 PDA 升级交易:
solana-verify export-pda-tx https://github.com/solana-developers/verify-squads --program-id 6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD --uploader 3JG6ULvZVCrkKtSSskKNJGe8RNZGFe8Ruev9KUhxzK5K
再次通过 Squads 提交交易。
您可以在这里查看一个示例交易。
然后提交另一个远程构建:
solana-verify remote submit-job --program-id 6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD --uploader 3JG6ULvZVCrkKtSSskKNJGe8RNZGFe8Ruev9KUhxzK5K
结果应类似于以下内容:
Verification request sent with request id: b63339d2-163e-49ac-b55d-3454c1c2b5b3Verification in progress... ⏳ [00:18:02] ✅ Process completed. (Done in 18minutes) Program 6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD has been verified.✅ The provided GitHub build matches the on-chain hash. On Chain Hash:96f8c3d9400258f7759408d1f6f8435b4a24d9b52f5a0340d97907e567cb8773 ExecutableHash: 96f8c3d9400258f7759408d1f6f8435b4a24d9b52f5a0340d97907e567cb8773 Repo URL:https://github.com/Woody4618/verify-squads/tree/0fb0a2e30c15c51732c0ad5e837975a6f7bbc7edCheck the verification status at:https://verify.osec.io/status/6XBGfP17P3KQAKoJb2s5M5fR4aFTXzPeuC1af2GYkvhD Joburl: https://verify.osec.io/job/b63339d2-163e-49ac-b55d-3454c1c2b5b3
恭喜您,在多签名升级后成功验证了您的程序!
从 Docker 镜像验证
您还可以通过运行以下命令,使用 Docker 镜像验证您的程序:
solana-verify verify-from-image -eexamples/hello_world/target/deploy/hello_world.so -iellipsislabs/hello_world_verifiable_build:latest -p2ZrriTQSVekoj414Ynysd48jyn4AX6ZF4TTJRqHfbJfn
该命令会加载存储在 ellipsislabs/hello_world_verifiable_build:latest
的镜像,并验证容器中可执行文件路径的哈希值是否与命令中提供的链上程序哈希一致。由于构建已经上传为镜像,无需重新完整构建可执行文件,从而节省大量时间。
创建 ellipsislabs/hello_world_verifiable_build:latest
镜像的 Dockerfile 可在 ellipsis
labs 仓库中找到:/examples/hello_world。
以下是预期的输出结果:
Verifying image: "ellipsislabs/hello_world_verifiable_build:latest", on network"https://api.mainnet.solana.com" against program ID2ZrriTQSVekoj414Ynysd48jyn4AX6ZF4TTJRqHfbJfn Executable path in container:"examples/hello_world/target/deploy/hello_world.so"Executable hash:08d91368d349c2b56c712422f6d274a1e8f1946ff2ecd1dc3efc3ebace52a760 Program hash:08d91368d349c2b56c712422f6d274a1e8f1946ff2ecd1dc3efc3ebace52a760 Executablematches on-chain program data ✅
示例已验证构建
以下是使用此 repository
源代码,验证 ID 为 FWEYpBAf9WsemQiNbAewhyESfR38GBBHLrCaU3MpEKWv
的示例程序的操作示例:
solana-verify verify-from-repo https://github.com/solana-developers/verified-program --url YOUR-RPC-URL --program-id FWEYpBAf9WsemQiNbAewhyESfR38GBBHLrCaU3MpEKWv --mount-path waffle --library-name waffle --commit-hash 5b82b86f02afbde330dff3e1847bed2d42069f4e
默认情况下,verify-from-repo
命令会获取 main 分支的最后一次提交。如果你希望在继续开发仓库时指定某个提交,可以使用
commit-hash 参数: --commit-hash 5b82b86f02afbde330dff3e1847bed2d42069f4e
最后,您还可以直接通过 OtterSec API 验证程序:
solana-verify verify-from-repo https://github.com/solana-developers/verified-program --url YOUR-RPC-URL --remote --program-id FWEYpBAf9WsemQiNbAewhyESfR38GBBHLrCaU3MpEKWv --mount-path waffle --library-name waffle --commit-hash 5b82b86f02afbde330dff3e1847bed2d42069f4e
--remote 命令会向 OtterSec
API 发送构建请求,从而触发你的程序的远程构建。构建完成后,系统会验证你程序的链上哈希是否与代码库中生成的构建工件哈希一致。
已验证的热门程序
Phoenix
solana-verify verify-from-repo -um --program-id PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY https://github.com/Ellipsis-Labs/phoenix-v1
最终输出:
Executable Program Hash from repo: 6877a5b732b3494b828a324ec846d526d962223959534dbaf4209e0da3b2d6a9On-chain Program Hash: 6877a5b732b3494b828a324ec846d526d962223959534dbaf4209e0da3b2d6a9Program hash matches ✅
Squads V3
solana-verify verify-from-repo https://github.com/Squads-Protocol/squads-mpl --commit-hash c95b7673d616c377a349ca424261872dfcf8b19d --program-id SMPLecH534NA9acpos4G6x7uf3LWbCAwZQE9e8ZekMu -um --library-name squads_mpl --bpf
请注意,我们需要指定
library-name,因为 Squads 仓库中包含多个程序。我们使用--bpf标志,是因为squads_mpl之前已通过 Anchor 验证。
最终输出:
Executable Program Hash from repo: 72da599d9ee14b2a03a23ccfa6f06d53eea4a00825ad2191929cbd78fb69205cOn-chain Program Hash: 72da599d9ee14b2a03a23ccfa6f06d53eea4a00825ad2191929cbd78fb69205cProgram hash matches ✅
Drift V2
solana-verify verify-from-repo -um --program-id dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH https://github.com/drift-labs/protocol-v2 --commit-hash 110d3ff4f8ba07c178d69f9bfc7b30194fac56d6 --library-name drift
最终输出:
Executable Program Hash from repo: e31d58edeabc3c30bf6f2aa60bfaa5e492b41ec203e9006404b463e5adee5828On-chain Program Hash: e31d58edeabc3c30bf6f2aa60bfaa5e492b41ec203e9006404b463e5adee5828Program hash matches ✅
Marginfi V2
solana-verify verify-from-repo -um --program-id MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA https://github.com/mrgnlabs/marginfi-v2 --commit-hash d33e649e415c354cc2a1e3c49131725552d69ba0 --library-name marginfi -- --features mainnet-beta
最终输出:
Executable Program Hash from repo: 890d68f48f96991016222b1fcbc2cc81b8ef2dcbf280c44fe378c523c108fad5On-chain Program Hash: 890d68f48f96991016222b1fcbc2cc81b8ef2dcbf280c44fe378c523c108fad5Program hash matches ✅
常见问题
我的验证失败了。我该怎么办?
检查这些常见问题:
- 签名者错误:通过运行
solana program show YourProgramId确认您的签名者是程序的升级权限 - 链上无 PDA:运行
solana-verify verify-from-repo -um并在提示时选择 YES。如果不上传 PDA,API 将无法检索您的验证元数据。 - PDA 数据不匹配:如果您重新部署了程序,请更新您的 PDA。您的 PDA 数据必须与已部署的程序匹配。
- 提交哈希不正确:使用您部署时的确切提交哈希创建 PDA
- 构建环境差异:在创建 PDA 时,使用 Docker 配合 solana-verify
我的本地构建哈希与链上哈希不匹配。为什么?
这通常意味着:
- 您使用了不同的 Rust/Solana 工具链版本
- 您的依赖项在两次构建之间更新了
- 您没有在 Docker 容器中构建
- 您检出了错误的提交
通过在 Docker 中使用 solana-verify build 构建您部署时的确切提交来解决此问题。
我的验证需要多长时间?
根据您的程序大小,预期时间如下:
- 简单程序:1-5 分钟
- 复杂程序:5-15 分钟
- 超大型程序:最多 30 分钟
使用作业状态端点跟踪您的进度。
我的程序是不可变的(无升级权限)。我该如何验证它?
如果您的程序没有升级权限,或者在您创建 PDA 之前已被设为不可变,我们针对这种情况设有白名单地址。请通过 contact@osec.io 联系我们,我们将帮助您验证程序。
什么是 PDA,为什么它很重要?
您的 PDA(程序派生账户)可实现无需信任的验证:
- 链上存储:将您的验证元数据(代码仓库 URL、提交哈希、构建参数)存储在由 Otter
Verify 程序(
verifycLy8mB96wd9wqq3WDXQwM4oU6r42Th37Db9fC)拥有的 PDA 中 - 加密链接:您的 PDA 由您的程序地址派生,与您的验证数据建立不可变的链接
- 去中心化信任:任何人都可以读取您的 PDA 并独立验证您的程序
为什么我必须在使用 API 之前创建 PDA?
API 仅适用于链上 PDA,因为:
- 无需信任:API 拒绝任意数据 - 它只使用您的升级权限存储在链上的数据
- 更简单:只需提供签名者 + program_id;API 从您的 PDA 获取其他所有信息
- 防篡改:您的 PDA 创建了一个任何人都可以独立验证的不可变记录
- 所有权证明:您的签名者必须是升级权限,通过加密方式证明您控制该程序
我应该多久验证一次我的程序?
在以下情况下验证您的程序:
- 每次部署或升级后
- 更新源代码仓库时
- 其他情况无需担心重新验证 - API 每 24 小时自动重新验证所有程序
升级程序时会发生什么?
升级后请按照以下步骤操作:
- API 检测到您的升级并取消程序验证。
- 使用新的验证元数据更新您的 PDA:
solana-verify verify-from-repo -um \--program-id YourProgramId... \https://github.com/your-org/your-program
- 使用您的升级权限提交新的验证请求
- API 将根据更新后的 PDA 验证您的新版本
重要提示:始终使用您的升级权限更新 PDA,并为升级后的程序提供新的提交哈希。
我可以信任验证结果吗?
是的 - 该系统旨在实现无需信任且可独立验证:
可信赖的原因:
- 链上 PDA: 您的验证元数据存储在链上,不受任何中心化机构控制
- 升级权限证明: 只有您程序的升级权限方可以创建/更新 PDA
- 独立验证: 任何人都可以通过读取您的 PDA 并在本地运行
solana-verify来进行验证 - 持续重新验证: API 每 24 小时自动重新验证所有程序
了解这些局限性:
- 验证确认源代码与部署匹配 - 并非确认您的代码是安全的
- 在与程序交互之前务必审查代码
- 已验证 ≠ 已审计或安全
- 检查 PDA 中的存储库和提交记录,以确认其来自可信来源
如何独立验证程序?
通过读取程序的链上 PDA 并在本地运行验证,您可以自行验证任何程序:
步骤 1: 读取链上 PDA
# Install solana-verify if you haven'tcargo install solana-verify# Get the PDA datasolana-verify list-program-pdas --program-id YourProgramId...
步骤 2: 本地验证
# Verify using the repository and commit & other arguments from the PDAsolana-verify verify-from-repo \--program-id YourProgramId... \https://github.com/your-org/your-program--commit-hash <commit-hash>... (other arguments from the PDA)# Confirm the hash output matches the on-chain program hash
这证明了:
- PDA 元数据是真实的(存储在链上)
- PDA 存储库中的源代码与已部署的程序匹配
- 您无需信任 API - 可以在链上自行验证一切
其他人可以在未经许可的情况下验证我的程序吗?
可以,这就是我们要求签名者必须是升级权限方的原因。我们仅在签名者是升级权限方时才认为验证有效。
创建可验证构建需要什么?
安装这些工具:
- Docker(用于确定性构建)
- Cargo(Rust 包管理器)
- Solana Verify CLI:
cargo install solana-verify - 包含您源代码的公共 Git 存储库
我可以验证私有仓库吗?
不可以 - 验证需要公开的源代码:
- 您的 PDA 存储了任何人都可以访问的公共仓库 URL
- 无需信任的验证依赖于公开的代码访问
- 用户需要阅读您的源代码以了解您的程序的功能
- 整个目的是让用户能够独立验证源代码与部署是否匹配
私有仓库会破坏验证系统的核心信任模型。
如何验证由 Squads 多签控制的程序?
对于多签控制的程序,请遵循以下步骤:
# 1. Build and deploy normallysolana-verify buildsolana program deploy <your-program.so> --program-id YourProgramId...# 2. Verify locally first - confirm the hash matchessolana-verify verify-from-repo -um \--program-id YourProgramId... \https://github.com/your-org/your-program# 3. Export the PDA creation transactionsolana-verify export-pda-tx \--program-id YourProgramId... \https://github.com/your-org/your-program# 4. Execute the PDA transaction through your Squads Multisig interface# 5. After multisig execution, trigger remote verificationsolana-verify remote submit-job \--program-id YourProgramId... \--uploader YourMultisigAddress...
关键:在导出 PDA 交易之前,务必在本地验证(步骤 2)以确认构建哈希值匹配。
结论
在 Solana 上使用已验证构建可确保您的程序在网络上的完整性和可信度,并允许开发者直接从 Solana 浏览器中找到您的 SDK。通过利用 Solana Verify CLI 和 Docker 等工具,您可以维护与源代码一致的可验证且安全的构建。始终采取必要的预防措施以使用一致的环境,并考虑使用治理解决方案来实现安全的升级和部署。
安全性 + 免责声明
虽然已验证构建是确保 Solana 程序完整性的强大工具,但在默认设置下它并非完全无需信任。Docker 镜像由 Solana 基金会构建和托管。
请注意,您是在下载的 Docker 镜像中构建项目,并且您的整个设置(包括潜在的敏感信息)都会被复制到该 Docker 镜像中进行构建。
如果您想要一个完全无需信任的设置,您可以自己构建 Docker 镜像并将其托管在自己的基础设施上。这样您就可以确保 Docker 镜像没有被篡改。您可以在已验证构建仓库中找到创建自己的 Docker 镜像的脚本,您可以 fork 它并自己运行 GitHub Actions,或验证它们是否正确。
此外,对于远程验证,您在一定程度上信任 OtterSec API 和 Solana Explorer。
如果 API 或 Solana Explorer 遭到攻击,可能会显示不正确的信息。
如果您想要完全无需信任的设置,可以自己运行
Verify API,或使用
verify-from-repo
命令在本地运行程序验证,使用保存在从程序部署权限和验证程序派生的
PDA
中的链上验证数据。
验证程序由 OtterSec 团队部署,目前尚未冻结,因此可以随时升级。
Solana 基金会、OtterSec 和 Ellipsis Labs 团队不对使用已验证构建流程可能产生的任何损失或损害负责。
Solana 程序的 Security.txt
除了已验证构建之外,您还可以为程序添加 security.txt
文件。在未来实现后,security.txt
将保存验证者公钥,以便轻松访问存储在验证 PDA 中的验证数据。包含构建和验证程序所需所有信息的 PDA 从程序地址和验证者公钥派生。默认情况下,这与构建和部署程序的公钥相同。但也可以是
security.txt 中指定的另一个公钥。
security.txt
功能允许开发者直接在其 Solana 智能合约中嵌入联系方式和安全信息。受
securitytxt.org
启发,这种方法为安全研究人员提供了一种标准化的方式来联系项目维护者,即使他们只知道合约地址。
为什么使用 security.txt?
对于许多项目,特别是较小或私有的项目,仅从合约地址识别开发者可能既困难又耗时。在程序中嵌入
security.txt
文件可以确保安全研究人员能够轻松联系到正确的人员,从而潜在地防止漏洞利用并确保及时的错误报告。
如何实现 security.txt
要将 security.txt 添加到您的 Solana 程序中,请按照以下步骤操作:
将 solana-security-txt 依赖项添加到您的 Cargo.toml 中:
[dependencies]solana-security-txt = "1.1.1"
在您的合约中使用 security_txt!
宏来定义您的安全信息。您可以包含联系方式、项目 URL,甚至安全策略。以下是一个示例:
#[cfg(not(feature = "no-entrypoint"))]use {default_env::default_env, solana_security_txt::security_txt};#[cfg(not(feature = "no-entrypoint"))]security_txt! {name: "MyProject",project_url: "https://myproject.com",contacts: "email:security@myproject.com,discord:security#1234",policy: "https://myproject.com/security-policy",// Optional Fieldspreferred_languages: "en,de",source_code: "https://github.com/solana-developers/solana-game-preset",source_revision: "5vJwnLeyjV8uNJSp1zn7VLW8GwiQbcsQbGaVSwRmkE4r",source_release: "",encryption: "",auditors: "Verifier pubkey: 5vJwnLeyjV8uNJSp1zn7VLW8GwiQbcsQbGaVSwRmkE4r",acknowledgements: "Thank you to our bug bounty hunters!"}
一旦 security.txt 信息嵌入到您的程序中,就可以通过 Solana
Explorer 等工具轻松查询,确保您的联系方式和安全详情对任何希望报告潜在问题的人都是可见的。
最佳实践
-
使用链接:对于可能更改的信息(例如联系方式),建议链接到网页而不是将其硬编码到合约中。这样可以避免频繁升级程序的需要。
-
验证:在部署之前,使用
query-security-txt工具验证格式和内容,该工具可以验证链上程序和本地二进制文件:
query-security-txt target/bpfel-unknown-unknown/release/my_contract.so
通过将安全联系信息直接嵌入到您的合约中,您可以让研究人员更容易联系到您,从而促进 Solana 生态系统内更好的安全性和沟通。
这是在 Solana Explorer 中 security.txt 的示例
security.txt 项目由 Neodyme Labs 维护
您可以在 verify.osec.io 查看验证状态并浏览已验证的程序。
Is this page helpful?