- Prover 根据要证明的计算/程序,构造一个公开的约束系统
- 约束通常是等式约束,形式为:
- 所有约束结构对 verifier 是公开已知的
-
Prover 计算一组 witness(私有数据 + 中间变量)
-
将 witness 代入所有约束:
- 如果 所有约束都等于 0:说明这组 witness 是合法解
- 如果 存在任一约束不等于 0: 👉 proof 无法生成,流程直接终止
这一步是整个 ZKP 中计算量最大的一步 本质上等价于“真正执行了一次被证明的计算,并记录所有中间结果”
目标:不暴露 witness,让 verifier 相信:存在一组 witness 使所有约束成立
- 每一条约束都有一个固定编号:
- Prover 用 witness 计算每条约束的残差:
- 按照公开规则(verifier 也知道)构造一个多项式:
- 规则是:
也就是说:
- 第
$i$ 条约束的残差 - 被当作多项式在
$X=i$ 处的取值
- 因为所有约束都成立:
- 所以:
到这里,prover 得到了一个确定的多项式
$E(X)$
- 它完全由 witness 决定
- verifier 看不到
- prover 也不能随意更改其含义
- verifier 会提供一个随机数
$r$ - 用于将多条/多类约束进行随机线性组合
- 目的:防止 prover 只满足部分约束(对冲作弊)
【注】在你当前流程里,这一步已经逻辑上包含在多项式构造中
- Prover 对构造出的多项式
$E(X)$ 进行承诺:
承诺具有两大性质:
- 绑定性(Binding)
- 一旦提交,prover 不能再更换多项式
- 隐藏性(Hiding)
- verifier 无法从承诺中推导出多项式内容或 witness
此时:
- verifier 能看到承诺
- verifier 不知道多项式长什么样
- prover 已经“被锁死”
- verifier 已收到:
- 多项式承诺
$C_E$
- 多项式承诺
- verifier 不知道:
- witness
- 多项式
$E(X)$ - 约束是否真的都为 0
- 但 verifier 确信 prover 不能再修改多项式
- verifier 不可能检查:
- 只能进行概率抽查
- verifier 从一个很大的有限域中选取随机数:
- 将
$z$ 发送给 prover (交互式 / 非交互式版本在实现上不同)
verifier 期望: 如果 prover 没有作弊,则应有
$E(z)=0$
- Prover 计算:
- Prover 不能只给出数值
$v_E$ - 还必须证明:
“这个
$v_E$ 确实来自我之前承诺的那个多项式” - 生成一个 打开证明,内容为:
我承诺过多项式
$E(X)$ , 并且它在点$z$ 处的值等于$v_E$
- 数值:
- 打开证明:
- verifier 使用:
- 承诺
$C_E$ - 随机点
$z$ - 数值
$v_E$ - 打开证明
$\pi_{\text{open}}$
- 承诺
- 检查:
$v_E$ 是否确实是承诺多项式在$z$ 处的值
若失败 → 直接拒绝
-
verifier 只检查数值
-
最简形式:
- 若协议使用整除形式(常见):
不成立 → 拒绝
- 若所有检查通过 → Accept
- 否则 → Reject
到此为止,整个 ZKP 流程结束 verifier 被数学上“强制相信”: 存在一组 witness,使所有约束成立
ZKP 的本质不是证明“我算了什么”, 而是证明: “我不可能在不知道 witness 的情况下,通过这些随机抽查。”