ZK 语言对比:Compact vs Leo vs Noir vs Cairo(2026)

简短结论

这四种语言位于 zk 技术栈(zk stack)的不同层次:

最大的实际差异在于:

这个差异在你构建“先承诺(commit now)、后揭示(reveal later)”流程时尤其重要,因为在 Compact/Leo/Cairo 中,持久化(persistence)和状态迁移(state transitions)是一等概念;而在 Noir 中,你通常会把问题拆成:

  1. 一个证明揭示正确性的电路(circuit),以及
  2. 一个存储先前承诺值(commitment)的应用/合约层(app/contract layer)。

1) Midnight Compact

类型系统 + 关键原语

Compact 是一种合约语言(contract language),而不只是电路 DSL(domain-specific language)。官方示例使用如下语法:

export circuit owner(): Either<ZswapCoinPublicKey, ContractAddress> { ... }
export ledger owner: Either<ZswapCoinPublicKey, ContractAddress>;

这会立刻告诉你两件重要的事:

其类型系统相当紧凑,并且面向合约。从官方示例和库中可以看到:

Compact 围绕 Midnight 上的隐私保护执行(privacy-preserving execution)而设计,因此“哪些是公开状态(public state),哪些是私下证明(proved privately)的内容”比普通 EVM 语言更核心。

作为初学者,你需要关心的主要原语是:

哈希辅助函数的语法部分,是我在交付代码前会根据精确的 2026 标准库(stdlib)版本再确认的内容。

相同示例:承诺一个秘密,稍后揭示,并证明其正确性

下面是一个 Compact 风格的草图,使用了官方示例中的真实结构语法(export ledgerexport circuit、类型化存储)。我将哈希辅助函数标记为 TODO,因为其确切函数名/签名对版本较敏感。

pragma language_version >= 0.16.0;

// TODO: verify exact import path for hashing helpers in current Midnight Compact stdlib.
import CompactStandardLibrary;

export ledger commitment: Bytes<32>;
export ledger revealed: bool;

constructor(initial_commitment: Bytes<32>) {
  commitment = initial_commitment;
  revealed = false;
}

export circuit get_commitment(): Bytes<32> {
  return commitment;
}

export circuit reveal(secret: Field, nonce: Field): [] {
  // TODO: verify exact hash helper name and return type in current Compact reference.
  // Example intent: hash(secret, nonce) -> Bytes<32>
  let recomputed: Bytes<32> = persistentHash(secret, nonce);

  assert(recomputed == commitment);
  assert(revealed == false);

  revealed = true;
}

语义如下:

这正是理解 Compact 的正确心智模型:合约状态 + 具备证明感知(proof-aware)的执行,而不是“我先写一个纯电路,再在别处想办法处理状态”。

工具链成熟度、调试、测试

Compact 的成熟度,很大程度上取决于 Midnight 生态的成熟度

通常较好的方面:

与当前 Cairo 相比通常较弱的方面:

在调试方面,你应预期其工具表面(tool surface)会比主流 EVM 或 Starknet 更窄。在隐私保护语言中,调试通常是以下方法的组合:

测试质量将取决于你所使用版本中的 Midnight SDK 和本地开发工具(local dev tooling)。我预期,到 2026 这一决策时间点,关键问题不再是“我能不能写测试?”,而是“我的团队能多快诊断证明失败(proof failures)和状态迁移缺陷(state-transition bugs)?”

当下的生产部署

截至 2024 年中之前的当前公开状态(public state),Midnight 尚未处于与 Starknet 相同的生产部署(production-deployment)类别。你应将 Compact 视为一种生态特定语言(ecosystem-specific language):它有很有前景的隐私目标,但对于需要最深厚现有生产历史的团队来说,它还不是默认答案。

何时选择 Compact

在以下情况下选择 Compact:

在以下情况下不要选择它:你的真实需求是“今天把一个 zk 应用部署到最经受实战检验的在线证明型 L2 上”。那会更倾向于 Cairo/Starknet。


2) Aleo Leo

类型系统 + 关键原语

Leo 是面向 Aleo 程序(programs)的一种高级语言(high-level language)。官方语法如下:

program hello.aleo;

function main:
    input r0 as u32.public;
    add r0 r0 into r1;
    output r1 as u32.public;

而在更高层的 Leo 示例中:

transition main(a: u32, b: u32) -> u32 {
    return a + b;
}

其类型系统包括:

关键原语包括:

Leo 比 Noir 更具意见化(opinionated)。你不只是写一个电路;你是在为 Aleo 的执行模型(execution model)编程。

相同示例:承诺一个秘密,稍后揭示,并证明其正确性

一个干净的 Aleo 设计是:

  1. 承诺阶段(commit phase)将承诺值存入一个 mapping
  2. 揭示阶段(reveal phase)证明 H(secret, nonce) == commitment
  3. finalize 逻辑检查并删除/移除已存储的承诺值

由于精确的 async/finalize 细节在不同版本中发生过变化,我会在存储交互处加上 TODO 注释。

program commit_reveal.aleo;

// TODO: verify exact mapping syntax in current Leo reference.
mapping commitments: field => bool;

transition make_commitment(secret: field, nonce: field) -> field {
    let commitment: field = BHP256::hash_to_field(secret, nonce);
    return commitment;
}

// User can submit the computed commitment for storage.
// TODO: verify whether this should be `async transition ... -> Future` in current Leo/Aleo version.
async transition commit(commitment: field) -> Future {
    return finalize_commit(commitment);
}

async function finalize_commit(commitment: field) {
    commitments.set(commitment, true);
}

// Reveal proves correctness privately, then updates state publicly.
// TODO: verify exact mapping read helper and finalize syntax.
async transition reveal(secret: field, nonce: field, commitment: field) -> Future {
    let recomputed: field = BHP256::hash_to_field(secret, nonce);
    assert_eq(recomputed, commitment);
    return finalize_reveal(commitment);
}

async function finalize_reveal(commitment: field) {
    let exists: bool = commitments.get_or_use(commitment, false);
    assert_eq(exists, true);
    commitments.set(commitment, false);
}

这里在语法上真实存在的部分包括:

你需要针对具体编译器版本核对的内容包括:

但在概念上,这非常符合 Leo 的惯用风格:在 transition 中完成私有计算(private computation),然后在 finalize 中完成持久状态变更(persistent state mutation)。

工具链成熟度、调试、测试

Leo 最大的优势是纵向集成(vertical integration)。如果你是在为 Aleo 构建应用,那么语言、证明器(prover)和执行环境(execution environment)是协同设计的。

这会带来:

相较主流智能合约开发,仍然更难的点在于:

对于纯 transition 逻辑,测试通常相对直接。对于有状态程序,你需要更谨慎,因为你测试的是:

Aleo 工具链已经达到具有实际可用性的程度,但其社区与运维生态(ops ecosystem)仍小于 Starknet。

当下的生产部署

Aleo 已上线,并且拥有真实应用和开发者活动。但如果你问“这四者中,哪一个拥有最深厚、可见的生产级智能合约部署历史?”,Leo 在公开 DeFi/应用体量和运行历史上,仍然落后于 Cairo/Starknet。

何时选择 Leo

在以下情况下选择 Leo:

在以下情况下不要选择 Leo:


3) Noir (Aztec)

类型系统 + 关键原语

如果你熟悉 Rust 风格语法,那么 Noir 是这四者中最容易读懂的。官方 Noir 语法如下:

fn main(x: Field, y: pub Field) {
    assert(x == y);
}

这一行已经展示了三个核心概念:

其类型系统包括:

最重要的实际原语是:Noir 从根本上说是一种电路语言(circuit language)。这意味着它非常擅长表达如下证明约束(proof constraints):

仅靠它本身,并不会提供合约存储语义(contract storage semantics)。在 Aztec 技术栈中,Noir 需要与 Aztec 的合约/运行时模型(contract/runtime model)配合使用。

相同示例:承诺一个秘密,稍后揭示,并证明其正确性

这个模式中,纯 Noir 部分很简单:验证被揭示的秘密(secret)和随机数(nonce)确实能打开(open)一个先前已发布的承诺值(commitment)。

use dep::std::hash::poseidon;

fn main(secret: Field, nonce: Field, commitment: pub Field) {
    let recomputed = poseidon::hash_2([secret, nonce]);
    assert(recomputed == commitment);
}

Poseidon 的精确 import 路径可能因 Noir 标准库版本而变化;如有需要:

// TODO: verify exact poseidon module path for the target Noir release.

这是四者中最干净的电路。它精确表达了“必须被证明的内容”。

如果你使用的是 Aztec,那么“先承诺、后揭示”流程通常会被拆分为:

一个合约层级的 Aztec 草图在结构上大致如下,但我会在用于文档前核对精确的 2026 Aztec 合约语法:

// TODO: verify exact Aztec contract syntax, storage declarations, and hash helper names.
#[aztec]
contract CommitReveal {
    #[storage]
    struct Storage {
        // pseudostructure: map commitment => used flag
    }

    #[private]
    fn reveal(secret: Field, nonce: Field, commitment: Field) {
        let recomputed = poseidon::hash_2([secret, nonce]);
        assert(recomputed == commitment);
        // read commitment from storage / note set
        // mark consumed
    }
}

因此,正确的比较点应是:

工具链成熟度、调试、测试

Noir 的工具链是其最强卖点之一。

初学者喜欢它的原因:

难点不在 Noir 本身,而在其下层或周边:

在测试方面,Noir 非常适合电路单元测试(circuit-unit tests)。对于完整 Aztec 应用,其成熟度更多取决于 Aztec 的合约框架与 devnet 工具,而不是语言本身。

当下的生产部署

在这里,你必须区分 NoirAztec

因此,如果问题是“作为一种电路语言,Noir 是否已经过生产验证(production-proven)?”,答案是:在更广泛的 zk 工程意义上,是的。
如果问题是“今天的 Aztec 合约部署是否像 Starknet 一样成熟且经过充分实战检验(battle-tested)?”,答案是否定的。

何时选择 Noir

在以下情况下选择 Noir:

如果你的真实需求是“一个完整、成熟、有状态的链语言,并且拥有大量生产部署”,那么不要单独选择 Noir。此时通常 Cairo 更合适。


4) StarkNet Cairo

类型系统 + 关键原语

Cairo 是这里最偏生产导向(production-heavy)的选择。现代 Cairo 1 语法类似 Rust。官方合约语法如下:

#[starknet::contract]
mod Counter {
    #[storage]
    struct Storage {
        value: u128,
    }

    #[external(v0)]
    fn increment(ref self: ContractState) {
        let value = self.value.read();
        self.value.write(value + 1);
    }
}

类型系统中的关键组成包括:

对 zk 应用开发者而言,关键原语是:

Cairo 比 Leo 或 Noir 更底层,因为你离被证明的机器(machine that gets proved)更近。

相同示例:承诺一个秘密,稍后揭示,并证明其正确性

下面是一个较为真实的 Cairo 1 Starknet 合约草图:

#[starknet::contract]
mod CommitReveal {
    use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess};
    use poseidon::poseidon_hash_span;

    #[storage]
    struct Storage {
        commitments: Map<felt252, bool>,
    }

    #[external(v0)]
    fn commit(ref self: ContractState, commitment: felt252) {
        self.commitments.write(commitment, true);
    }

    #[external(v0)]
    fn reveal(ref self: ContractState, secret: felt252, nonce: felt252) {
        let mut inputs = array![];
        inputs.append(secret);
        inputs.append(nonce);

        let recomputed = poseidon_hash_span(inputs.span());

        assert(self.commitments.read(recomputed), 'UNKNOWN_COMMITMENT');
        self.commitments.write(recomputed, false);
    }

    #[view]
    fn is_committed(self: @ContractState, commitment: felt252) -> bool {
        self.commitments.read(commitment)
    }
}

其行为是:

这不是 Noir 意义上的独立 zkSNARK 电路(separate zkSNARK circuit)。在 Cairo 中,程序执行(program execution)本身就是在 Starknet/STARK 模型下被证明的对象。

工具链成熟度、调试、测试

对于面向生产的智能合约工程(production-oriented smart contract engineering)而言,Cairo/Starknet 是这里最强的选择。

优势:

弱点:

Cairo 的测试能力足以支持真实团队。与大多数 zk 系统相比,你会获得一种更标准的合约开发体验:写函数、测试存储效果、断言错误、模拟调用。

在调试方面,它也显著优于较年轻的隐私优先生态,因为已经有更多人踩过相同类型的坑。

当下的生产部署

这是四者中最明确的答案:

如果你的老板问:“这份列表中,哪种语言最有力地证明了当下的生产使用?”答案是 Cairo

何时选择 Cairo

在以下情况下选择 Cairo:

如果你的最高优先级是“用最简单、最干净的语法来表达一个独立证明(standalone proof)”,那就不要选 Cairo。对此,Noir 通常更好。


对比表

语言 最适合被理解为 核心公开语法提示 类型系统风格 状态模型 证明模型 工具链成熟度 当下的生产部署 最佳适用场景
Midnight Compact 隐私优先合约语言 export ledger, export circuit, Either<...> 合约特化、链原生隐私类型 内建合约存储 Midnight 上的可证明合约执行 新兴中 相比 Starknet 有限 Midnight 原生私有应用
Aleo Leo Aleo 程序语言 program x.aleo;, transition, field, mappings/finalize 高层、面向应用 Mappings + finalize 流程 Aleo 模型内的私有执行 中等,纵向集成强 真实存在但生态较小 需要集成式隐私的 Aleo 应用
Noir (Aztec) 首先是电路语言,其次才是 Aztec 应用语言 fn main(...), Field, pub, assert(...) 干净、表达力强、以电路为中心 纯 Noir 中不原生提供;由 Aztec/运行时提供 显式电路约束 电路层强,完整应用栈中等 Noir 是;Aztec 运行时不如 Starknet 成熟 电路编写、Aztec 私有应用
StarkNet Cairo 面向生产的智能合约/可证明执行语言 #[starknet::contract], #[storage], felt252, read()/write() 更底层、系统导向 原生合约存储 通过 STARK 证明执行轨迹 整体最强 显著最强 生产级 Starknet 应用

如何选择

使用下面这个决策树。

1. 你是否已经知道目标链?

2. 你的主要问题是“优雅地编写证明”,还是“交付一个生产合约”?

3. 你是否需要当前最强的生产部署叙事?

4. 你想要集成式私有应用平台,还是隐私优先合约链?

5. 你的团队是否会难以处理更底层的执行语义(execution semantics)?

6. 你是否需要链可移植性(chain portability)或后端灵活性?


最后的实用建议

如果我要把这些压缩成四条直接建议:

对于特定的“提交秘密、稍后揭示、证明正确性”模式:

如果你仍然不确定,可以按风险承受能力来默认选择:


下一步去哪里

读到这里很感谢。如果 “Compact / Leo / Noir / Cairo 对比” 这个话题正好契合你目前的工作,下面三条路径任选其一:

继续学习 ZK 生态

完整的 Midnight ZK Cookbook 索引 覆盖 Midnight、Aleo、Aztec、Noir、risc0 共 17 篇英文教程加 4 篇中文翻译,按生态分组列出。

接 ZK 生态 的付费活

Bounty Radar 聚合 Algora、GitHub labels、Drips Wave、Code4rena、Bountycaster 的开放 ZK bounty。Bounty Radar 主页 bounty-radar-data 或任一生态子 widget:https://battam1111.github.io/bounty-radar-data/widget.html?ecosystem=<aleo|aztec|cairo|midnight|noir|risc0>。免费版需轮询;$19/月 Hobbyist 档 会把一个 filter 实时推送到 Telegram。

给自己的 ZK 项目做体检

zk-pipeline-doctor 是 MIT 开源的免费 CLI,对任意 ZK 项目按测试、CI、文档、安全、可复现性、语言工具链六个维度打分(支持 Compact、Leo、Noir、Cairo 和 7 个 Rust zkVM)。用 zk-doctor-action 接进 GitHub Action 可获得 PR diff 评论。$15/月 Pro 档 增加 4 个跨生态深度检测器(电路复杂度、证明系统坑点、verifier soundness、多文件一致性)。


由 AI 辅助起草,作者在发布前逐行审阅。完整流程见 DISCLOSURE

Related projects