零知识证明(Zero-Knowledge Proof, ZKP)被称为密码学的"圣杯"。它允许一个人证明"我知道某个秘密"或"某个陈述为真",却丝毫不泄露那个秘密本身。在区块链领域,ZKP 是隐私币的灵魂——Monero 的环机密交易和 Zcash 的屏蔽交易都完全依赖于它。
10.3.1 ZKP 的三条铁律
一个真正的零知识证明系统必须同时满足三条形式化性质:
1. 完备性(Completeness)
如果陈述为真且证明者知道证据,验证者总是接受:
2. 可靠性(Soundness)
如果陈述为假,任何作弊的证明者都无法让验证者接受(除可忽略概率外):
3. 零知识性(Zero-Knowledge)
验证者从交互中获得的信息,完全可以由一个模拟器独立生成——也就是说,验证者"什么也没学到":
graph LR
P[证明者 P<br/>知道秘密 w] --> |"证明: x ∈ L"| V[验证者 V]
V --> |"只接受/拒绝"| R[结果]
S[模拟器 S<br/>不需要 w] --> |"可复现 View_V"| V2[验证者 V]
P -.->|"w 对 V 隐藏"| R
style S fill:#c8e6c9
style V fill:#bbdefb
style V2 fill:#bbdefb
10.3.2 zk-SNARK 深度原理
从 "电路可满足性" 到 "零知识证明"
zk-SNARK 的核心是将任意计算转化为算术电路(Arithmetic Circuit),然后证明"我知道满足这个电路的输入(证据)"。
对于一个包含 个门的电路,zk-SNARK 使用以下密码学构造:
其中 是多项式,只有当电路逻辑被正确满足时,中间多项式的等式才成立。证明者要证明的是:
核心密码学:双线性配对(Bilinear Pairing)
zk-SNARK 依赖于椭圆曲线上的双线性配对 :
这允许验证者通过检查配对等式来验证多项式约束,而不需要看到证据。
可信设置仪式(CRS 生成)
zk-SNARK 的公共参考字符串(CRS)包含可信设置中生成的公开参数:
其中 是"有毒废料"。如果设置参与者保留 ,就可以伪造证明。
MPC 多方计算仪式(Powers of Tau)确保只要至少一方诚实地删除了自己的秘密贡献,系统就是安全的。以太坊的 KZG 承诺(Dencun 升级中包含的 4844 提案)就采用了这种仪式。
zk-SNARK 的证明验证成本
对于 1 万次门电路,zk-SNARK 的技术参数是惊人的:
| 指标 | 值 | 对比(非 ZK 验证) |
|---|---|---|
| 证明大小 | 约 200-300 字节 | N/A |
| 验证时间 | 约 2-3 毫秒 | (几毫秒到秒级) |
| 证明生成时间 | 几秒到几分钟 | N/A |
证明大小与验证时间的常数级增长,是 zk-SNARK 名称中 "S"(Succinct 简洁) 的来源。
抗量子短板
zk-SNARK 的安全基础是:
- 椭圆曲线离散对数
- 双线性配对的 Diffie-Hellman 假设
这两者都在量子计算下存在多项式时间破解——zk-SNARK 不具有抗量子安全性。
/**
* zk-SNARK 核心参数验证模拟
* 模拟配对检查与 CRS 验证的逻辑框架
*/
interface CRS {
g1Powers: bigint[]; // [G, τG, τ²G, ...]
g2Powers: bigint[]; // [H, τH, τ²H, ...]
}
interface SNARKProof {
pi_a: bigint; // [A]_1 in G1
pi_b: bigint; // [B]_2 in G2
pi_c: bigint; // [C]_1 in G1
proofSize: number; // 字节数
}
function pairingCheck(
a: bigint, // element in G1
b: bigint, // element in G2
target: bigint // expected in GT
): boolean {
// 简化:真实为 e(a, b) = e(G, H)^{ab}
// 这里用模运算模拟配对等式
const P_curve = 2n**256n - 2n**32n - 977n;
// e(a,b) * e(G, H)^{-target} 应该 == 1
const pairAB = (a * b) % P_curve;
return pairAB === target;
}
/**
* 模拟 zk-SNARK 的三方程验证
* 真实验证: e(A1, B2) = e(α1, H2) * e(C1, H2) * e(δ1, Z2)
* 这里简化为核心代数约束验证
*/
function verifySNARK(
proof: SNARKProof,
publicInput: bigint,
crs: CRS,
alpha: bigint, // 设置参数 α
beta: bigint, // 设置参数 β
delta: bigint, // 设置参数 δ
): { verified: boolean; pairingChecks: number } {
// 简化验证方程(核心逻辑示意)
const check1 = pairingCheck(
(proof.pi_a + publicInput * alpha) % crs.g1Powers[0],
proof.pi_b,
(proof.pi_c + publicInput * delta) % crs.g1Powers[0]
);
const check2 = pairingCheck(
proof.pi_a,
crs.g2Powers[1], // β 对应的 G2 元素
crs.g2Powers[0] // 目标
);
return {
verified: check1 && check2,
pairingChecks: 2,
};
}
// --- 演示 ---
const sampleCRS: CRS = {
g1Powers: [1n, 3n, 9n, 27n], // [G, 3G, 9G, 27G] 模拟
g2Powers: [1n, 5n, 25n, 125n], // [H, 5H, 25H, 125H]
};
const proof: SNARKProof = {
pi_a: 7n,
pi_b: 11n,
pi_c: 13n,
proofSize: 192, // 192 字节 = 典型的 BN254 SNARK 证明大小
};
const result = verifySNARK(proof, 42n, sampleCRS, 2n, 3n, 5n);
console.log(`验证结果: ${result.verified}`);
console.log(`证明大小: ${proof.proofSize} 字节 (与 ~200B 目标一致)`);
// 配对检查次数: 2 (实际系统需 2-3 次)
// 验证复杂度: O(1) - 与电路大小无关!10.3.3 zk-STARK:抗量子替代方案
zk-STARK(Scalable Transparent ARgument of Knowledge)放弃了双线性配对,改用一个全新的范式——基于纠错码和 Merkle 树。
核心差异
| 维度 | zk-SNARK | zk-STARK |
|---|---|---|
| 安全假设 | 椭圆曲线配对 + CRS | 哈希函数(抗碰撞) |
| 可信设置 | 需要 Powers of Tau | 无需 |
| 证明大小 | ~200 字节 | ~50-200 KB |
| 验证时间 | 毫秒 | |
| 量子安全 | 否 | 是 |
| 递归聚合 | 需要特殊构造 | 原生支持 |
FRI 协议:STARK 的核心
zk-STARK 使用 FRI(Fast Reed-Solomon Interactive Oracle Proof) 协议来证明一个多项式"接近"低次(也就是"我的计算遵守了正确的多项式约束")。
核心思想:如果一个多项式 的次数远小于其求值域,那么随机采样可以高概率检测出作弊。
给定声明"多项式 的次数 ",验证者:
- 要求证明者承诺 在域 上的所有求值(通过 Merkle 树根)
- 随机挑战点
- 证明者提供 的 Merkle 证明
- 验证者检查一致性
- 将问题"折叠"为更小的子问题,迭代 轮
最终验证只需要 次查询,但每次查询需要整个求值域的 Merkle 证明(约多项式 次求值)。
STARK 证明尺寸公式
其中 是约束次数, 是有限域大小。
这意味着证明大小随约束的平方对数增长,而非 zk-SNARK 的常数级。对于大型程序,这个差距会相当明显。
递归聚合的魔力
STARK 原生支持递归证明——用 STARK 来验证另一个 STARK。这意味着:
我们可以将 1000 笔交易的 1000 个 STARK 证明,聚合成一个 STARK 证明。
StarkNet 正是利用这一特性,将大量 Layer 2 交易的验证压缩为恒定大小的证明提交到以太坊主网。
flowchart TB
subgraph Batch1["交易批次 1"]
T1[TX_1] --> P1["STARK 证明 p1"]
T2[TX_2] --> P1
T3[TX_3] --> P1
end
subgraph Batch2["交易批次 2"]
T4[TX_4] --> P2["STARK 证明 p2"]
T5[TX_5] --> P2
T6[TX_6] --> P2
end
P1 --> M1
P2 --> M1["聚合 STARK<br/>递归证明"]
M1 -.->|"提交到 L1"| L1[以太坊主网<br/>验证 ~2^20 约束]
style M1 fill:#c8e6c9
style L1 fill:#bbdefb
10.3.4 L2 中 zk-SNARK 与 zk-STARK 的工程对比
选择矩阵
| 应用场景 | 推荐方案 | 理由 |
|---|---|---|
| 高频小额支付(zk-Rollup) | zk-STARK (StarkEx) | 原生递归、透明设置 |
| 隐私交易(Zcash T-to-Z) | zk-SNARK (Orchard/Halo2) | 小证明、快验证 |
| 跨链桥证明 | zk-SNARK(轻量) | 证明必须上链,字节数敏感 |
| 抗量子未来需求 | zk-STARK | 抗 Shor 攻击 |
当前生态版图
graph LR
subgraph ZK-EVM
P1[Polygon zkEVM<br/>zk-SNARK based]
P2[Scroll<br/>zk-SNARK based]
P3[StarkNet<br/>zk-STARK based]
end
subgraph 隐私币
M[Monero<br/>Bulletproofs]
Z[Zcash<br/>Orchard: Halo2]
A[Aztec<br/>Halo2]
end
subgraph 中间层
I1[zkPass<br/>zk-SNARK]
I2[HyperOracle<br/>zk-STARK]
end
P1 --> I1
P3 --> I2
Z --> M
10.3.5 知识地图
mindmap
root((零知识证明))
三大性质
完备性 P(接受|真) = 1
可靠性 P(接受|假) ≤ negl
零知识 模拟器等价
zk-SNARK
优点: 常数证明大小 ~200B
缺点: 需要可信设置(CRS)
不抗量子
双线性配对 e(aP,bQ)=e(P,Q)^{ab}
QAP: A(x)·B(x)=C(x)
zk-STARK
优点: 无需可信设置
抗量子
原生递归聚合
缺点: 证明较大 ~50-200KB
FRI 协议
递归证明
用 ZK 验证 ZK
批量压缩
应用场景
隐私币
Rollup L2
可验证计算
跨链桥
> ← 上一节:10.2 混币与环签名 | 前往 → 10.4 隐私币对比(Monero vs Zcash) |*
评论
0评论加载中…