name: midnight-core-concepts:zero-knowledge description: 当询问零知识证明、ZK SNARKs、电路编译、见证数据、证明者/验证者角色、约束条件或Midnight如何利用ZK实现隐私时使用。
Midnight中的零知识证明
零知识证明允许你在不泄露秘密的情况下证明你知晓它。在Midnight中,ZK证明用于验证交易遵循合约规则,同时不暴露私有数据。
核心概念
ZK证明证明的是:“我知道满足这些约束条件的值”,而不需要揭示这些值。
Midnight应用:证明一笔交易是有效的(输入正确、用户已授权、遵循规则),同时不暴露私有状态或用户秘密。
ZK SNARKs
Midnight使用 ZK SNARKs(零知识简洁非交互式知识论证):
| 属性 | 含义 |
|---|---|
| 零知识 | 验证者除了有效性外一无所获 |
| 简洁 | 证明大小很小,与计算复杂度无关 |
| 非交互式 | 证明者和验证者之间无需来回交互 |
| 知识论证 | 证明者必须实际知晓秘密 |
Midnight中的证明工作原理
交易结构
每笔Midnight交易包含:
- 公共记录 - 可见的状态变更
- 零知识证明 - 密码学验证
该证明表明:“我知道私有输入,当与公共数据结合时,满足合约的约束条件。”
电路心智模型
合约逻辑被编译为 电路 - 数学约束系统。
简洁代码 → 电路约束 → ZK证明
电路定义了变量之间的关系。证明显示你知道满足所有约束的变量赋值,而不揭示赋值本身。
证明生命周期
1. 设置 → 生成证明/验证密钥(每个电路)
2. 见证 → 证明者组装私有输入
3. 证明 → 根据见证 + 电路生成证明
4. 验证 → 根据公共输入检查证明(快速)
实践中的电路
证明什么
当简洁合约执行时:
- 合约逻辑编译为算术电路
- 私有值成为见证输入
- 公共值成为公共输入
- 证明展示正确的执行
电路约束
电路将计算表示为多项式约束:
// 概念性:证明 x * y = z 而不揭示 x, y
约束:a * b = c
公共输入:c = 42
见证(私有):a = 6, b = 7
从简洁代码到电路
// 这段简洁代码...
export circuit guess(guess: Field): Void {
const product = guess * other_factor;
assert product == ledger.target;
}
// ...编译成约束,证明:
// 1. guess * other_factor 等于 target
// 2. 不揭示 guess 或 other_factor 的值
实际应用
证明而不揭示
| 场景 | 证明什么 | 隐藏什么 |
|---|---|---|
| 年龄验证 | 年龄 ≥ 18 | 确切出生日期 |
| 余额检查 | 余额 ≥ 金额 | 实际余额 |
| 会员资格 | 在授权集合中 | 具体是哪个成员 |
| 投票有效性 | 合格选民,尚未投票 | 选民身份 |
在合约中
// 证明知晓因子而不揭示它们
export circuit proveFactors(
secret_a: Field, // 私有见证
secret_b: Field // 私有见证
): Void {
// 约束:因子相乘等于公共目标值
assert secret_a * secret_b == ledger.public_target;
}
关键概念
见证
证明者知晓的私有输入。从不揭示,仅用于生成证明。
公共输入
对所有人可见的值。证明根据这些值进行验证。
验证
检查证明很快(毫秒级),与原始计算复杂度无关。
可靠性
在计算上不可能在不知晓见证的情况下创建有效证明。
性能特征
| 操作 | 成本 |
|---|---|
| 电路编译 | 一次性,昂贵 |
| 证明生成 | 数秒到数分钟(取决于电路大小) |
| 证明验证 | 毫秒级 |
| 证明大小 | ~200-300 字节(恒定) |
参考资料
详细技术信息请参考:
references/snark-internals.md- 椭圆曲线、配对、可信设置references/circuit-construction.md- Compact如何编译为电路
示例
工作模式:
examples/circuit-patterns.compact- 常见证明模式