找回密码
立即注册
搜索
发回帖 发新帖

5053

积分

0

好友

649

主题
发表于 2 小时前 | 查看: 8| 回复: 0

前言

在上一篇 Aleo CLI 实战:从生成账户到链上部署合约,一个 Rust CLI 工具的全流程实现 中,我们用 aleo-cli 完成了从生成账户到部署合约的全流程。但细心的读者会发现:exec 命令只有一种模式——生成证明 + 广播上链。每次测试都要等 30 秒证明 + 几秒入块,调试体验很差。

Aleo 官方 JS SDK 提供了三个级别的执行 API:

JS SDK 方法 作用 网络需求
run() 本地执行,不生成 ZK 证明,不出交易 离线
run(proveExecution=true) 本地生成 ZK 证明,但不广播 仅取 state root
verifyExecution() 拿到一个链上交易,本地验证其 ZK 证明 仅拉取交易数据

而 aleo-rust-sdk v0.3.0 之前只有一条路:证明 + 广播(全链上)。这篇文章就用 aleo-cli 的新增三模式实现对 SDK 的完整覆盖。

项目地址:https://github.com/qiaopengjun5162/aleo-cli

背景

为什么需要三种模式?

  1. 调试阶段:改一行参数就等 30 秒证明 + 入块确认,开发效率极低
  2. 费用控制:每次 prove 上链都要花手续费(base fee ~0.05 credits),频繁迭代成本高
  3. 安全审计:拿到链上交易后,信任但验证(trust but verify),本地重算 ZK 证明来确认链上交易有效

架构扩展

之前 aleo-cli 的 exec 只走一条直线:

参数 → execute_local(dry-run) → prove + broadcast → 回显 tx

现在扩展为三岔路:

                    ┌→ --local   → execute_local (无证明,毫秒级返回)
参数 → exec  ────────┤
                    └→ (默认)    → prove + broadcast (原流程)
                    │
                    └→ --prove   → prove_execution (有证明,不广播,返回完整 TX JSON)

参数 → verify ──────┬→ (无 --deep) → 拉取交易基本信息
                    └→ --deep      → 拉取 + 本地重算 ZK 证明验证

底层实现

三模式都依赖 SDK 新增的三个方法:

方法 说明
AleoClient::execute_local() 直接调 ExecutionEngine::authorize_and_execute(),只用 credits.aleo 内置程序
AleoClient::prove_execution() 全管线(authorize + prove + package),但不调用 broadcast_transaction,返回 Transaction JSON 字符串
AleoClient::verify_execution() 拉取链上交易 JSON → 反序列化为 Transaction 枚举 → 根据类型走 verify_execution 或 verify_deployment

verify_execution 的核心在 SDK 的 execution.rs 中:

pub fn verify_transaction(&self, transaction: &Transaction<TestnetV0>) -> Result<String> {
    match transaction {
        Transaction::Execute(execution, _fee) => {
            // 遍历 execution 的每一个 transition,逐个验证
            for transition in execution.transitions() {
                self.process
                    .lock()
                    .verify_execution::<AleoTestnetV0>(
                        ConsensusVersion::V14,
                        transition,
                        rng,
                    )?;
            }
        }
        Transaction::Deploy(_owner, deployment, _fee) => {
            // 部署证明验证:直接调 verify_deployment
            self.process
                .lock()
                .verify_deployment::<AleoTestnetV0>(
                    ConsensusVersion::V14,
                    deployment,
                    rng,
                )?;
        }
    }
}

实操过程

环境准备

沿用上一篇的测试地址和私钥。所有操作在 Aleo Testnet 真实网络上执行。

# 构建最新版本(含三个新模式)
git clone https://github.com/qiaopengjun5162/aleo-cli.git
cd aleo-cli
cargo build --release

# 验证命令
$ ./target/release/aleo-cli --help
Usage: aleo-cli [OPTIONS] <COMMAND>

Commands:
  ...
  exec    Execute a program on chain (with --local/--prove modes)
  verify  Verify a transaction on chain (with --deep for ZK proof verification)
  ...

模式一:本地无证明运行 (exec --local)

这是调试阶段最常用的模式。它在本地执行程序(不生成 ZK 证明),直接返回执行结果。

$ export ALEO_PRIVATE_KEY="APrivateKey1..."
$ aleo-cli exec credits.aleo transfer_public \
aleo1ss6e8mpfcxgvzd8urjan8c36mj5k0sllxse8y0hwvr80ufququys52qz2r \
1000u64 --local

输出:

=== Aleo Execute ===

📜 Program:    credits.aleo
🔧 Function:   transfer_public
📥 Inputs:     aleo1ss6e8mpfcxgvzd8urjan8c36mj5k0sllxse8y0hwvr80ufququys52qz2r, 1000u64

🔬 Local-only (no proof, no broadcast)...

"Response { output_ids: [...], outputs: [...] }"

✅ Execution response received

关键特性:

特性 说明
速度 毫秒级返回,不需要等证明生成(30秒)或入块确认(几秒)
离线 不需要网络连接,完全在本地执行
适用范围 仅支持 credits.aleo 系统合约(AleoClient 内置了它的程序字节码)

实现原理:--local 模式调用 SDK 的 AleoClient::execute_local(),内部走的是 ExecutionEngine::authorize_and_execute()——这条路径直接在本地的 Process 对象上执行程序,不经过 Varuna 证明生成器。

模式二:离线生成证明 (exec --prove)

有时候你需要在本地生成完整的 ZK 证明但不广播——比如你想:

  • 保存证明文件以备后用
  • 在离线环境中生成,然后通过其他通道(如邮箱、IPFS)发送
  • 只看证明的 gas 成本和 proof size,不实际发到链上
$ export ALEO_PRIVATE_KEY="APrivateKey1..."
$ aleo-cli exec credits.aleo transfer_public \
aleo1ss6e8mpfcxgvzd8urjan8c36mj5k0sllxse8y0hwvr80ufququys52qz2r \
1000u64 --prove --base-fee 50000

输出:

=== Aleo Execute ===

📜 Program:    credits.aleo
🔧 Function:   transfer_public
📥 Inputs:     aleo1ss6e8mpfcxgvzd8urjan8c36mj5k0sllxse8y0hwvr80ufququys52qz2r, 1000u64
💵 Base fee:   50000 microcredits

📡 Proving without broadcast...

🎉 Execution Transaction (not broadcast):
{
  "id": "au1wcfz3352qj430uua4p92j9t4zm57v7dy2luw28g0j5r4hl3t3yqst50q9h",
  "type": "execute",
  "execution": {
    "transitions": [...]
  },
  "fee": {
    "transition": {
      "id": "as1zg3a6h8c5j77dv74u3v4pqlfu6p3u9p49jpspfcwnxxhnk3s3q8q04z5hn",
      ...
    }
  },
  ...
}

✅ Proof generated locally — not broadcast to network

区别于默认模式:

特性 说明
生成完整的 ZK 证明 跟广播模式一样的证明流程(~30 秒 Varuna),一样的手续费授权
不广播 返回 Transaction JSON 字符串而不是 tx_id,不出块、不扣费
需要网络 虽然不上链,但还是需要拉取最新的 state root(证明生成需要链上状态)

实现原理:SDK 的 AleoClient::prove_execution() 复用了 execute_and_broadcast 的 90% 代码,核心差异只在最后一步:

pub async fn prove_execution(&self, ...) -> Result<String> {
    // ... 前 7 步跟 execute_and_broadcast 完全一致 ...

    // 第 8 步:返回 JSON 字符串,不广播
    let tx_json = serde_json::to_string_pretty(&transaction)?;
    Ok(tx_json)

    // 对比广播版的第 8 步:
    // let tx_id = self.network.broadcast_transaction(&tx_json).await?;
    // self.network.wait_for_confirmation(&tx_id).await
}

模式三:链上交易 ZK 验证 (verify / verify --deep)

有朋友在群里说:你发上去的交易我凭什么相信它是真的?Aleo 给了你答案——verify_transaction_api 方法可以本地验证任何链上交易的 ZK 证明。

verify 命令有两个模式:

浅查(默认):只拉取交易基本信息

$ aleo-cli --node "https://api.explorer.provable.com/v2/testnet" \
verify at1z9elr8m25jcvlh4kdaaxcf62t9rcx38n7tus3tqsz0tsh6cz859spmu0y2

输出:

=== Aleo Verify ===

🔍 Transaction: at1z9elr8m25jcvlh4kdaaxcf62t9rcx38n7tus3tqsz0tsh6cz859spmu0y2
📋 Type:   deploy
📋 Status: confirmed
👤 Owner:  aleo1cu0xk4tt99pgxgl

深度验证(--deep):拉取交易后本地重算 ZK 证明

部署交易验证:

$ aleo-cli --node "https://api.explorer.provable.com/v2/testnet" \
verify at1z9elr8m25jcvlh4kdaaxcf62t9rcx38n7tus3tqsz0tsh6cz859spmu0y2 --deep

输出:

=== Aleo Verify ===

🔍 Transaction: at1z9elr8m25jcvlh4kdaaxcf62t9rcx38n7tus3tqsz0tsh6cz859spmu0y2
📋 Type:   deploy
📋 Status: confirmed
👤 Owner:  aleo1cu0xk4tt99pgxgl

🔬 Deep verification (proof) enabled...

✅ Deployment proof VERIFIED
Program: test_cli_deploy.aleo

执行交易验证:

$ aleo-cli --node "https://api.explorer.provable.com/v2/testnet" \
verify at1n3tjm6hhehp9zsc5j2ce9cdmh030hcznzsh26qsvkkgnkhykhyrsv5aq9a --deep

输出:

=== Aleo Verify ===

🔍 Transaction: at1n3tjm6hhehp9zsc5j2ce9cdmh030hcznzsh26qsvkkgnkhykhyrsv5aq9a
📋 Type:   execute
📋 Status: confirmed

🔧 Transition #0: ?::?
Input: aleo1ss6e8mpfcxgvzd8urjan8c36mj5k0sllxse8y0hwvr80ufququys52qz2r
Input: 1000000u64

🔬 Deep verification (proof) enabled...

✅ Execution proof VERIFIED
Program: credits.aleo
Function: transfer_public
Transitions: 1

验证了什么:verify --deep 实际上做了两步:

  1. 拉取交易 → GET /v2/testnet/transaction/{id},返回完整的交易 JSON(含 execution/deployment + 证明)
  2. 本地验证 → 反序列化为 Transaction 枚举,调用 Process::verify_execution() 或 Process::verify_deployment() 重新计算证明的哈希,跟链上提交的证明对比

如果证明被篡改过(比如有人改动了交易参数),本地校验会失败:

❌ Execution proof verification FAILED
Error: 'transition proof is invalid'

这就是 Aleo "信任但验证" 的设计哲学——任何人拿到链上交易都可以本地验证其正确性,不依赖节点。

遇到的问题和解决方案

1. 自定义程序不能使用 --local

现象:执行非 credits.aleo 的程序时加 --local 报错:

Authorization failed — Program 'test_cli_deploy.aleo' does not exist

原因:AleoClient::execute_local() 只内置了 credits.aleo 系统合约。因为 execute_local 不走 set_program() 注册流程,自定义程序没有被加载到 Process 中。

解决:--local 模式下自动检测程序 ID,非 credits.aleo 时提示用户换用 --prove 或默认模式(从网络拉取程序后全流程证明)。

if program_id != "credits.aleo" {
    anyhow::bail!(
        "--local mode is only available for credits.aleo. \
Use --prove or omit the flag for custom programs."
    );
}

2. 验证部署交易时 Process 冲突

现象:verify --deep 验证部署交易时报错:

Error: Process already contains program 'test_cli_deploy.aleo' with edition '0'

原因:Process::verify_deployment() 内部会调 add_program() 注册被验证的程序。如果 Process 已经加载了同名程序(从 SDK 初始化或之前的验证残留),就会冲突。

解决:在 client.rs 的 verify_execution 方法中,部署类型使用一个新的、空的 ExecutionEngine(不加载任何用户程序),避免程序名冲突:

Transaction::Deploy(_owner, deployment, _fee) => {
    // 使用一个全新 Engine(不含用户程序),避免 program_id 冲突
    let engine = ExecutionEngine::new_empty()?;
    engine.verify_deployment_transaction(deployment, rng)
}

3. 测试网交易 JSON 结构与本地类型不对齐

现象:Transaction::from_str(json) 反序列化失败。

原因:测试网返回的交易 JSON 中包含 confirmations 字段(已入块确认数),但 snarkVM 的 Transaction 结构体在未确认阶段没有这个字段。

解决:需要先从 JSON 中提取 transaction 字段(内层对象),再传给 from_str。网络层做了字段适配。

4. Execution 的 id() 方法不存在

现象:初始实现调用 execution.id() 获取 execution ID,编译错误。

原因:snarkVM 4.10.0 中 Execution 结构体没有直接暴露 id() 方法(可能是跨版本差异)。真正的 ID 在 Transition::transition_id() 中。

解决:改为遍历 transitions:

// 错误方式
let exec_id = execution.id();

// 正确方式
for transition in execution.transitions() {
    let tx_id = transition.transition_id();
}

效果展示

三模式全部通过真实测试网验证

模式 命令 耗时 是否上链 验证结果
本地无证明 exec --local 毫秒级 ❌ 不广播 ✅ 返回执行响应
离线证明 exec --prove ~30秒 ❌ 不广播 ✅ 完整 TX JSON(含 ZK proof ID au1...)
浅查交易 verify <tx_id> 秒级 ❌ 只拉取 ✅ 显示类型/状态/所有者
深度验证 verify <tx_id> --deep ~1秒 + 网络 ❌ 只拉取 ✅ deploy + execute 证明均验证通过

JS SDK 执行 API 完整对齐

JS SDK Rust CLI 状态
run() exec --local ✅ 已实现 + 真实测试
run(proveExecution=true) exec --prove ✅ 已实现 + 真实测试
verifyExecution() verify --deep ✅ 已实现 + 真实测试
buildExecutionTransaction() exec (默认) / deploy ✅ 此前已实现
broadcastTransaction() 集成在 exec / deploy 中 ✅ 此前已实现

项目状态

项目 详情
aleo-cli GitHub:https://github.com/qiaopengjun5162/aleo-cli
9 个命令/子命令(generate/query/balance/transfer/deploy/exec + --local/--prove/verify + --deep)
最新 commit:ec80570(feat: add verify --deep)
aleo-rust-sdk v0.3.0:https://crates.io/crates/aleo-rust-sdk
最新 commit:ae9cd70(feat: add verify_execution)
docs.rs:https://docs.rs/aleo-rust-sdk

总结

关键经验

1. 三模式对应开发三阶段:

  • 开发调试 → --local(毫秒级反馈,先确保逻辑正确)
  • 预生产 → --prove(确认 ZK 证明能生成,不浪费手续费)
  • 生产 → 默认(证明 + 广播,完整上链)
  • 审计 → verify --deep(验证已上链交易的 ZK 证明)

2. JS SDK 的 run() 在 Rust SDK 中需要三个独立方法:JS 通过一个 proveExecution 布尔开关切换,而 Rust 需要显式调用不同的管线路径(execute_local / prove_execution / execute_and_broadcast)。这是因为 Rust 的所有权模型让编译器需要在编译期确定调用路径。

3. ZK 证明验证不是玄学:verify --deep 实际做的是反序列化交易 → 提取 transitions → 调 Varuna 验证器重算。这个流程跟链上的验证节点做的完全一致,所以本地验证通过 = 链上确实接受了这笔交易。

4. Zero-knowledge, zero-trust:Aleo 的设计让任何人都可以在不信任节点的情况下验证链上交易。你不需要跑全节点,不需要信任 API 提供商,只需要一条 aleo-cli verify <tx_id> --deep 命令。

下一步

  • 发布 SDK v0.4.0(含 verify_execution API)到 crates.io
  • 将 exec --prove 的输出保存为文件(--output 参数),方便离线传输
  • 批量验证(对一组 tx_id 进行 proof check)
  • 自定义程序支持 --local:在 CLI 加载用户指定的 .aleo 文件到 Process

参考链接

  1. aleo-cli GitHub:https://github.com/qiaopengjun5162/aleo-cli
  2. aleo-rust-sdk GitHub:https://github.com/qiaopengjun5162/aleo-rust-sdk
  3. aleo-rust-sdk crates.io:https://crates.io/crates/aleo-rust-sdk
  4. Aleo Testnet Explorer:https://explorer.provable.com/testnet
  5. Aleo 开发者文档:https://developer.aleo.org
  6. JS SDK 执行 API 文档:https://docs.aleo.org/sdk/typescript/aleo-sdk/classes/AleoExecution



上一篇:卡片笔记写作法:Ryan Holiday如何靠日常研究让内容自然长出来
下一篇:量化交易核心数学模型解析:Probit、CTA、双层规划与Hull-White
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-8 05:29 , Processed in 0.091725 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表