短的代价
前面十三章我一直在说验证者有多轻松。这一章把账单翻过来。本机实测:证明一段 8192 步的计算,比直接把它跑一遍慢 164 倍;而验证那份证明比直接跑快 2.3 倍,且工作量只随长度按对数增长。而且我这台还是个只干了一半活的玩具——工业实现的证明开销在 10⁴ 到 10⁶ 倍量级。
三个数,一起看
把卷 III 那台机器实装成代码,跑第 3 章那条 MiMC 记录,测三件事:直接执行、生成证明、验证证明。
| 计算长度 n | 直接执行 | 生成证明 | 验证 | 证明大小 |
|---|---|---|---|---|
| 1024 | 0.143 ms | 30.0 ms | 0.478 ms | 13.9 KB |
| 2048 | 0.298 ms | 31.4 ms | 0.398 ms | 14.9 KB |
| 4096 | 0.546 ms | 65.7 ms | 0.453 ms | 16.0 KB |
| 8192 | 1.092 ms | 178.9 ms | 0.479 ms | 17.1 KB |
三列各有各的脾气,值得逐列看:
★ n=8192:证明比执行慢 164× ★ n=8192:验证比执行快 2.3× ★ 验证做的全部工作 544 次 SHA-256 证明大小(与 n 几乎无关) 13.9 → 17.1 KB 验证工作量随 n 怎么长 对数:树高 13 / 14 / 15 / 16 执行与验证打平的 n(本机) 3591
| 这一列 | 随 n 怎么长 | 说明 |
|---|---|---|
| 直接执行 | 线性 | n 翻倍,时间翻倍。天经地义 |
| 生成证明 | n log n | 要做一次插值、一次 64 倍的求值、一整棵 Merkle 树。它比执行本身还长得快 |
| 验证 | log n | 34 条路径 × 树高。n 从 1024 涨到 8192,验证时间几乎没动 |
| 证明大小 | log n | 同上。这就是「简洁」 |
把执行推到玩具证不了的规模
n = 8192 的时候,验证只比执行快 2.3 倍——听起来不值一提。但那是因为 8192 步的计算本来就只要一毫秒。把执行推大:
光是执行 1e+5 步(不证明) 12 ms 光是执行 1e+6 步(不证明) 95 ms 光是执行 1e+7 步(不证明) 865 ms 而验证那一头呢? n = 8192 树高 16,544 次哈希,0.479 ms n = 10 亿 树高 33,1122 次哈希,约 1 ms
执行那一列在按线性往上冲,验证那一列几乎是平的。这才是这台机器的意义:它不在小规模上赢,它在大规模上赢,而且赢的幅度随规模无限增长。本机的打平点是 n ≈ 3591 步——超过这个长度,验证一份证明就比亲自跑一遍便宜。
把三方的账放在一起:
| 角色 | 没有证明系统 | 有证明系统 | 变化 |
|---|---|---|---|
| 做事的那个人 | 1 份力气 | 1 + 164 份力气 | ×165 |
| 每一个验证者 | 1 份力气 | 0.44 份力气 | ×0.44 |
| N 个验证者时的总账 | 1 + N | 165 + 0.44N | N > 366 时开始划算 |
所以这门技术的适用范围,是由「有多少人要验证同一件事」决定的。N 很小的时候,它纯属浪费;N 很大的时候,它的收益随 N 线性增长。
这就解释了一个常被问的问题:为什么零知识证明先在区块链落地,而不是在别的地方?因为区块链是人类造出来的、N 最大的那个场景——几万个节点在验证同一件事。第 18 章会把这笔账算完。
诚实地说说我这台玩具
上面那个 164 倍是低估,必须说清楚。我这台只做了完整流程的一部分:
| 真实系统要做而我没做的 | 大约会让证明者贵多少 |
|---|---|
| FRI 低度测试(第 11 章那个洞) | 再来 log n 轮折叠,每轮一棵 Merkle 树 |
| 约束多项式的组合与商(第 12 章那个 H(x)) | 几次额外的大规模求值 |
| 真实的域和真实的安全参数 | 64 位或 256 位的域,而不是我这个 16 位的玩具 |
| 零知识所需的掺随机 | 额外的约束和承诺 |
公开基准里,工业级 zkVM 生成证明的成本大约是原生执行的 10⁴ 到 10⁶ 倍(取决于工作负载和硬件)。也就是说:一个在你笔记本上跑 1 秒的程序,证明它可能要几个小时的 CPU 时间——或者几十秒的 GPU 集群时间。第 21 章会给出 2026 年的具体数字。
证明大小:另一条完全不同的曲线
「证明多大」和「证明多久」是两件事,经常被混在一起:
| 方案 | 证明大小 | 随计算长度 | 验证成本 |
|---|---|---|---|
| 我这台玩具(Merkle + 抽查) | 17.1 KB | log n | 544 次哈希 |
| 典型 STARK | 45 – 200 KB | log² n | 几十万次哈希 |
| Groth16 | 128 字节 | 完全无关 | 3 次配对 |
| PlonK | 约 400 – 500 字节 | 完全无关 | 常数次配对 |
Groth16 那 128 字节是这门技术最惊人的一个数字:无论你证的是 100 步还是 10 亿步的计算,证明永远是 128 字节,三个椭圆曲线上的点。验证是三次配对运算,几毫秒。
为什么工业界不全用它?因为它要一场仪式(第 15 章),而且换一个电路就要重办一次。这就是第 16 章那张选型表。
这一章的数字是本机计时,换台机器就变,但三条曲线的形状不会变。你可以在自己机器上把形状跑出来:
import hashlib, time
P, G = 65537, 3
sha = lambda b: hashlib.sha256(b).digest()
# ntt()、lde() 见第 11 章;build()、open_at() 见第 13 章
def bench(n, blowup=8):
C = [(i * 7919 + 31337) % P for i in range(n)]
t = time.perf_counter() # ① 直接执行
x, trace = 12345, []
for i in range(n):
trace.append(x); x = pow(x + C[i], 3, P)
t_exec = time.perf_counter() - t
t = time.perf_counter() # ② 生成证明
ext = lde(trace, n * blowup)
layers = build(ext)
t_prove = time.perf_counter() - t
t = time.perf_counter() # ③ 验证 34 次抽查
root, depth = layers[-1][0], len(layers) - 1
for q in range(34):
i = (q * 7919) % (n * blowup)
assert verify(root, i, ext[i], open_at(layers, i))
t_verify = time.perf_counter() - t
print('n=%5d 执行 %7.3f ms 证明 %8.1f ms 验证 %6.3f ms '
'证明 %.1f KB 慢 %.0f×' %
(n, t_exec*1000, t_prove*1000, t_verify*1000,
34*(depth*32+2)/1024, t_prove/t_exec))
for n in (1024, 2048, 4096, 8192):
bench(n)
你会看到三件事,而且在任何机器上都成立:(1) 执行那一列严格随 n 翻倍;(2) 证明那一列涨得比线性还快;(3) 验证那一列几乎不动,证明大小每次只多 1 KB 左右。
再做一个实验:把 blowup 从 8 改成 64,看证明时间涨 8 倍、而抽查次数可以从 34 降到 17(第 11 章那张表)——证明大小反而变小。这就是那个旋钮的两端。
python3 bench.py
在线跑:python.org/shell(n 调到 1024 以内)。想看工业级基准,找 ecosystem benchmarks 类的公开榜单,注意看它们用的是 CPU 还是 GPU 集群——差别在两个数量级。
- 以太坊为一个区块生成证明。2025 年这件事要约 16 分钟,2026 年压到了约 16 秒,成本降了 45 倍(以太坊基金会公布的数字)。而验证那份证明只要几毫秒。整整一年的工程投入,全花在了本章这一列上——证明者那一列。
- 硬件正在被专门造出来干这件事。这个领域已经有专用 ASIC/FPGA 加速器在做 NTT 和多标量乘法(证明者时间的大头)。以太坊 2026 年路线图里甚至写了硬性指标:本地证明设备成本 ≤ 10 万美元、功耗 ≤ 10 kW。「证明者成本」已经变成了一个有采购单和电费账单的工程问题。
- 把它当成一次「压缩」来理解。你压一个视频要几分钟,播放要几毫秒——没人觉得这不划算,因为压一次、播一万次。零知识证明是同一个经济结构,只是倍数更极端:压缩比是「一亿步 → 几十 KB」,而压缩耗时是播放的一百万倍。
- 反面:不要给「只有一个验证者」的场景上这套东西。你和一个服务端一对一交互,让它验一份证明,总账是 165 份力气对 2 份——纯亏。这个场景该用的是普通的审计日志或签名。这本书里最容易犯的工程错误,就是把它用在 N 很小的地方。
「zk-rollup 说自己能扩容一百倍,那零知识证明肯定是让计算变快了。」
正好相反:它让计算变慢了几千甚至上百万倍。那一百倍的扩容,来自完全不同的地方——它消掉的是「几万个节点各算一遍」的重复,不是单次计算的成本。
把账摊开就清楚了。原来的总成本是「1 次执行 × 几万个节点」;现在是「1 次执行 + 1 次证明(贵一万倍) + 几万次验证(每次几毫秒)」。贵的那一次被摊到了所有节点头上,于是人均反而便宜了。这是一次典型的「集中付出、分散受益」。
这个误解还有一个更常见的变体:「zk 让隐私变便宜了」。也不对。零知识那条性质在这套机制里几乎是白送的(第 13 章),但整台机器本身极其昂贵。判据是:任何时候看到「zk 让 X 变快了」,先问「快的是谁那一头」——这本书里唯一变快的永远是验证者,而且是以证明者慢几个数量级为代价的。
这一章的一句话
「简洁」是一次成本转移而不是一次节约:证明者要多付三位数以上的力气,换来每个验证者只付零点几;因此这门技术的价值完全由「有多少人在重复验证同一件事」决定。
下一章讲那 128 字节要付的另一笔账,而它不是算力,是信任。Groth16 那种极短的证明,需要一场仪式来生成参数,仪式过程中会产生一个 32 字节的数——谁留着它,谁就能伪造任何证明,而且没有人能发现。这个数有个绰号叫「毒废料」。2016 年 Zcash 为了销毁它,六个人分散在世界各地,用与网络物理隔离的电脑、拆开的笔记本、事后被砸毁的硬件,办了一场后来被写成纪录片的仪式。