指南 · 第 3 部分,共 6 部分
验证一条记录
验证是 Label 309 中不需要征得任何人同意的那一半。只要给出一个 Cardano 交易引用,你就能自己核实一条记录——基于公开链、通过你自选的区块链浏览器。整个过程无需登录,结果也丝毫不取决于是谁发布了它。
使用 CLI
安装 cardanowall 二进制后,把它指向一笔交易:
cardanowall verify 3b9f…c1a2它会通过一个公开的 Cardano 区块链浏览器解析这笔交易,对记录做结构校验,核查所有作者身份签名,确认记录已结算,并打印出一个结论。这个结论是四种状态之一,退出码会原原本本地把它带出来,所以它能直接接入 CI:
| 退出码 | 结论 | 含义 |
|---|---|---|
0 | valid | 每一项必需的检查都通过了 |
1 | failed | 一项可归因于记录的检查失败了(完整性、结构或签名) |
2 | unverifiable | 不是记录的过错,但某项必需的检查无法运行(网络或策略) |
3 | pending | 确认数还不够——来自一条 pending 记录的结果都不是最终的 |
4 | — | CLI 输入错误(参数有误或缺少必需输入) |
failed 与 unverifiable 之间的区分是刻意为之的:一个 failed 结论总是可归因于记录本身,因此没有哪个行为不端的浏览器能制造出一个;unverifiable 则意味着验证器因记录之外的原因无法完成某项检查——一个它够不着的网关、一个被列入 deny 名单的主机,或一道拉取上限。
加上 --json 可得到机器可读的报告;把工具指向你自己的基础设施,就能让每一跳网络请求都在你的掌控之中:
cardanowall verify 3b9f…c1a2 \
--cardano-gateway https://your-koios-instance/api/v1 \
--threshold 20 \
--json如果这条记录是密封给你的,把你的密钥交给验证器,它就会解密载荷并重新计算明文哈希:
cardanowall verify 3b9f…c1a2 --secret-key-stdin优先使用 --secret-key-stdin、--secret-key-file 或 CARDANOWALL_RECIPIENT_KEY 环境变量,而不是直接用 --secret-key 标志,这样密钥就不会落入你的 shell 历史。
使用 TypeScript SDK
CLI 用的那个验证器就内置在 SDK 里。它不需要客户端、不需要基础 URL,也不需要密钥——验证不依赖网关:
import { verifyTx } from '@cardanowall/sdk-ts/verifier';
const report = await verifyTx({ txHash: '3b9f…c1a2' });
console.log(report.verdict); // 'valid' | 'pending' | 'unverifiable' | 'failed'
if (report.verdict !== 'valid') {
console.error(report.issues, report.signatures);
}verifyTx 会返回一份完整的 VerifyReport:结论和 exitCode、解析出的 block_time 与 confirmationDepth、结构校验与验证器合并的 issues 列表、逐项的 items 与 merkle 检查结果、可选的 signatures,以及它发出的每一次对外请求的 auditTrail 日志——你可以据此向自己证明,它从未联系过发布者。
要验证一条密封给你的记录,把你的私钥交给验证器。密钥环在整次运行中是全局的——你传入的每一把密钥都会被对每一个密封项逐一尝试,因此没有逐项索引:
const report = await verifyTx({
txHash: '3b9f…c1a2',
decryption: [{ recipientSecretKey: mySecretKey }],
});使用 Python SDK
cardanowall-sdk 是 TypeScript 验证器逐字节一致的孪生实现——同样的检查,同样的结论:
import asyncio
import cardanowall
report = asyncio.run(cardanowall.verify_tx(cardanowall.VerifyTxInput(tx_hash="3b9f…c1a2")))
print(report.verdict)使用 Rust SDK
cardanowall crate 也带着同一个验证器。verify_tx 是同步的——它内部持有一个阻塞式传输——并返回同样的 VerifyReport:
use cardanowall::verifier::{verify_tx, Verdict, VerifyTxInput};
let report = verify_tx(&VerifyTxInput::new("3b9f…c1a2"));
println!("{}", report.verdict.as_str()); // "valid" | "pending" | "unverifiable" | "failed"
if report.verdict != Verdict::Valid {
eprintln!("{:?}", report.issues);
eprintln!("{:?}", report.record_signatures);
}要验证一条密封给你的记录,附上你的私钥。密钥环在整次运行中是全局的——每一把密钥都会被对每一个密封项逐一尝试,因此一份凭据不携带任何项索引。输入字段都是公开的,因此可以在 VerifyTxInput::new 之上继续构建:
use cardanowall::verifier::{verify_tx, Decryption, VerifyTxInput};
let mut input = VerifyTxInput::new("3b9f…c1a2");
input.decryption = Some(vec![Decryption::Recipient {
recipient_secret_key: my_secret_key, // Vec<u8>
}]);
let report = verify_tx(&input);为什么这件事不需要信任
每一项检查都基于公开数据和你自选的区块链浏览器运行。发布这条记录的人无法左右结果——就算他们明天就消失了,你的验证照样能跑出一模一样的结果。