文章

03. 多项式承诺、Merkle oracle 与 Fiat–Shamir

03. 多项式承诺、Merkle oracle 与 Fiat–Shamir

1. PCS 的抽象接口

多项式承诺方案 Polynomial Commitment Scheme 至少提供:

\[\begin{aligned} \mathsf{pp}&\leftarrow\mathsf{Setup}(1^\lambda,d),\\ C&\leftarrow\mathsf{Commit}(\mathsf{pp},f;r),\\ \pi_z&\leftarrow\mathsf{Open}(\mathsf{pp},f,r,z),\\ b&\leftarrow\mathsf{Verify}(\mathsf{pp},C,z,y,\pi_z). \end{aligned}\]

目标是让短 commitment $C$ 绑定一个次数 $\le d$ 的多项式,并用短 opening proof 证明 $f(z)=y$。

必须分别检查以下性质:

  • commitment binding:不能把同一 $C$ 打开成两个不同多项式;
  • evaluation binding:不能在同一点打开成两个不同值;
  • degree binding:被绑定对象确实不超过声明次数;
  • hiding:$C$ 是否隐藏 $f$;这不是所有 PCS 的默认性质;
  • knowledge soundness:能否从成功 prover 中提取被承诺多项式或相应 witness。

许多论文在 algebraic group model、knowledge-of-exponent 类假设或 random oracle model 下证明不同版本;“使用 KZG”四个字不足以说明完整安全结论。

sequenceDiagram
    participant P as Prover
    participant V as Verifier
    P->>V: C = Commit(f)
    V-->>P: 随机点 z
    P->>V: y = f(z), opening proof
    V->>V: 检查 C 与 z,y 一致

核心顺序是 commit → challenge → open。后续所有 polynomial IOP 都围绕它编排 transcript。

2. KZG:在秘密点 $\tau$ 上“代入”

KZG 使用阶为素数 $r$ 的双线性群

\[\mathbb G_1,\mathbb G_2,\mathbb G_T\]

与 pairing

\[e:\mathbb G_1\times\mathbb G_2\to\mathbb G_T, \qquad e(g_1^a,g_2^b)=e(g_1,g_2)^{ab}.\]

2.1 Structured Reference String

setup 采样必须销毁的非零秘密 $\tau\leftarrow\mathbb F_r^*$,发布

\[\mathsf{SRS} = \left( g_1,g_1^\tau,g_1^{\tau^2},\ldots,g_1^{\tau^d}; g_2,g_2^\tau \right).\]

给定

\[f(X)=\sum_{i=0}^{d}a_iX^i,\]

prover 无需知道 $\tau$ 就能计算

\[C_f =\prod_{i=0}^{d}(g_1^{\tau^i})^{a_i} =g_1^{f(\tau)}.\]

commitment 只有一个群元素。直觉是:SRS 允许在指数里对秘密点求值,但不允许恢复 $\tau$。

2.2 单点 opening

声称 $f(z)=y$。由因式定理,

\[q(X)=\frac{f(X)-y}{X-z}\]

是多项式。opening proof 为

\[\pi=g_1^{q(\tau)}.\]

verifier 检查

\[e\left(C_f/g_1^y,g_2\right) \stackrel{?}{=} e\left(\pi,g_2^\tau/g_2^z\right).\]

正确性来自

\[f(\tau)-y=q(\tau)(\tau-z).\]

pairing 把指数里的乘法关系搬到 $\mathbb G_T$:

\[e(g_1,g_2)^{f(\tau)-y} =e(g_1,g_2)^{q(\tau)(\tau-z)}.\]

2.3 KZG 为什么短,代价在哪里

收益代价
commitment 常数大小SRS 必须覆盖最大 degree
单点 proof 常数大小需要 pairing-friendly curve
多个多项式可随机线性批处理prover 主要成本常含大 MSM 与 FFT
链上若有 pairing 预编译则 verifier 便宜DLOG/pairing 路线不抗 Shor

2.4 universal、updatable 不等于 trustless

PLONK 常说 universal/updatable setup:

  • universal:同一 powers-of-$\tau$ 可服务所有不超过上限的电路;
  • updatable:任何参与者都可加入新随机性;只要至少一位诚实销毁其秘密,最终 toxic waste 未知;
  • circuit-specific key:可从 universal SRS 公开派生,并不需要新秘密仪式。

它降低了信任门槛,但没有把 SRS 变成“纯透明参数”。若 $\tau$ 泄露,攻击者能构造不受正确低次多项式约束的 opening 关系。

2.5 KZG commitment 默认不隐藏

$C_f=g_1^{f(\tau)}$ 是确定性的。同一 $f$ 总给出同一 commitment;若候选空间很小,观察者可枚举。完整 ZK-SNARK 通常通过:

  • 给 witness polynomials 加不会改变约束域取值的随机 $Z_H$ 倍数;
  • 使用带独立 hiding generator 的承诺变体;
  • 在 protocol 层加入盲化项并证明 degree budget;

来获得零知识。不要把“离散对数难”误解为自动 hiding。

3. IPA:把 evaluation 变成内积

设系数向量

\[\mathbf a=(a_0,\ldots,a_{n-1})\]

和公开独立 generators $\mathbf G=(G_0,\ldots,G_{n-1})$。Pedersen 风格向量承诺可写为

\[C=\langle\mathbf a,\mathbf G\rangle+rH =\sum_i a_iG_i+rH.\]

在点 $z$ 的 evaluation 是内积

\[f(z)= \left\langle (a_0,\ldots,a_{n-1}), (1,z,\ldots,z^{n-1}) \right\rangle.\]

Inner Product Argument 递归把长度 $n$ 的向量折成两半。仅写向量折叠会漏掉关键的交叉项;为展示每轮保持的关系,考虑常见的双基 accumulator

\[\mathcal P =\langle\mathbf a,\mathbf G\rangle +\langle\mathbf b,\mathbf H\rangle +\langle\mathbf a,\mathbf b\rangle U.\]

把所有向量分成左右两半,prover 先发送

\[\begin{aligned} L={}&\langle\mathbf a_L,\mathbf G_R\rangle +\langle\mathbf b_R,\mathbf H_L\rangle +\langle\mathbf a_L,\mathbf b_R\rangle U,\\ R={}&\langle\mathbf a_R,\mathbf G_L\rangle +\langle\mathbf b_L,\mathbf H_R\rangle +\langle\mathbf a_R,\mathbf b_L\rangle U. \end{aligned}\]

transcript 在绑定 $L,R$ 后给出非零 challenge $x$,再按下面的同一 convention 折叠:

\[\begin{aligned} \mathbf a'&=x\mathbf a_L+x^{-1}\mathbf a_R,\\ \mathbf b'&=x^{-1}\mathbf b_L+x\mathbf b_R,\\ \mathbf G'&=x^{-1}\mathbf G_L+x\mathbf G_R,\\ \mathbf H'&=x\mathbf H_L+x^{-1}\mathbf H_R. \end{aligned}\]

对应的 group accumulator 必须同时更新为

\[\mathcal P'=x^2L+\mathcal P+x^{-2}R.\]

展开可见,$x^2\langle\mathbf a_L,\mathbf b_R\rangle$ 与 $x^{-2}\langle\mathbf a_R,\mathbf b_L\rangle$ 正是折叠后内积产生的两个交叉项。具体 PCS 可能把公开的 $\mathbf b$、hiding generator 或 evaluation claim 吸收到不同基中,但不能省掉等价的 $L,R$ 与 accumulator 更新。经过 $\log_2 n$ 轮只剩一个标量关系;每轮发送常数个群元素,所以 proof 大小是 $O(\log n)$ 群元素。

flowchart TB
    N["长度 n 的内积声明"] --> H1["发送 L_1,R_1 并采样 x_1"]
    H1 --> N2["折成长度 n/2"]
    N2 --> H2["发送 L_2,R_2 并采样 x_2"]
    H2 --> ND["继续对半折叠"]
    ND --> O["长度 1 的标量检查"]

3.1 IPA 的系统含义

  • 不需要 powers-of-$\tau$ 这种结构化 trapdoor;generators 可由 domain-separated hash-to-curve 导出。
  • 它仍依赖椭圆曲线离散对数,因此不具备后量子安全。
  • proof 比 KZG 大,为对数级群元素;verifier 通常需要相应 MSM。
  • additive homomorphism 很适合 accumulation 和 Halo 风格递归。
  • 递归时要让外层 circuit 高效表达内层曲线运算,常用 curve cycle 或 endomorphism 优化。

Halo 2 与 Kimchi 常被概括为“PLONKish + IPA”,但两者具体 permutation、lookup、transcript 和递归层并不相同。

4. Merkle + FRI:承诺的是编码后的 evaluation oracle

4.1 Merkle commitment

prover 先在大域 $D$ 上计算 LDE:

\[\mathbf v=(f(x))_{x\in D}.\]

每个叶子做无歧义编码后哈希,内部节点递归

\[h_{\mathrm{parent}} =H(\mathsf{tag}_{\mathrm{node}}\|h_L\|h_R).\]

Merkle root 绑定整个 evaluation vector。打开一个位置需要该叶子与 $O(\log \lvert D\rvert)$ 个 sibling hashes。

4.2 Merkle 只绑定向量,不证明低度

任意随机向量都能建 Merkle tree。FRI 的工作是检查该向量是否接近低次 RS codeword。一个典型 hash-based PCS 组合:

  1. 对 LDE 求值并发送 Merkle root;
  2. 用 FRI / DEEP-FRI / WHIR 等证明 low-degree proximity;
  3. 用 DEEP quotient、batching 或 sumcheck 把声称的 $f(z)=y$ 连接到承诺 oracle;
  4. 对随机查询提供 Merkle authentication paths;
  5. 用 Fiat–Shamir 生成全部挑战与查询位置。

所以“FRI commitment”通常是简写。FRI 本身是 IOPP;成为非交互 PCS 还需要 commitment、evaluation reduction 与 transcript compiler。

flowchart LR
    F["f(X)"] --> L["在 D 上 LDE"]
    L --> M["Merkle root"]
    M --> B["绑定 evaluation vector"]
    L --> R["FRI / WHIR"]
    R --> D["证明接近低次编码"]
    B --> P["PCS opening"]
    D --> P
    E["evaluation reduction"] --> P

4.3 复杂度直觉

若 domain 大小为 $N$、查询数为 $s$:

  • prover 至少要处理 $O(N)$ 个编码值和哈希,若含 FFT 则常见 $O(N\log N)$ 域工作;
  • 单轮查询 authentication 数据朴素为 $O(s\log N)$ 个哈希,但可用共享路径剪枝;
  • proof 通常明显大于 KZG/IPA;
  • verifier 以哈希和小域运算为主,没有 pairing;
  • 透明且在选用合适 hash、编译器与 QROM 分析时具有 plausible post-quantum 路线。

这里没有一个对所有 STARK 都正确的固定 proof size。blowup、folding factor、查询数、leaf packing、hash digest、extension degree、grinding bits 都会改变结果。

5. 三类后端的横向比较

维度KZGIPAMerkle + FRI/WHIR
主要对象单变量 polynomialcoefficient/evaluation vector 内积编码后的 evaluation oracle
setupstructured universal SRS无结构化 toxic wastetransparent
commitment1 个群元素1 个群元素1 个 hash root
opening proof常数级$O(\log n)$ 群元素多轮值 + Merkle paths
verifier 核心pairingMSM / curve opshash + field ops
prover 核心MSM、FFTMSMFFT/encoding、hash
post-quantum可合理构造为是,但需完整模型分析
适合链上有 pairing 预编译时很强取决于曲线预编译原生验证较贵,常递归压缩
递归pairing inside circuit 较重Halo 路线友好小域/友好 hash 下可很快

“哪一个最快”没有脱离场景的答案。要同时给出:

\[(\text{circuit size},\text{field},\text{hardware}, \text{batch size},\text{proof size},\text{verifier target}).\]

6. 多项式批处理:随机组合再次出现

6.1 同一点打开多个多项式

若要证明

\[f_i(z)=y_i,\qquad i=0,\ldots,m-1,\]

先绑定所有 commitments,并把点 $z$ 与 prover 声称的全部 evaluations $y_i$ 吸收进 transcript;之后才能采样 batching challenge $v$,定义

\[F(X)=\sum_{i=0}^{m-1}v^if_i(X), \qquad Y=\sum_{i=0}^{m-1}v^iy_i.\]

只需证明 $F(z)=Y$。承诺的线性同态允许 verifier 同样组合 $C_{f_i}$。

正确依赖顺序是

\[(C_{f_0},\ldots,C_{f_{m-1}}) \longrightarrow z \longrightarrow(y_0,\ldots,y_{m-1}) \longrightarrow v \longrightarrow\pi_{\mathrm{open}}.\]

若 $y_i$ 在 $v$ 之后才确定,prover 可让多个错误声明在随机组合中相消。例如已知 $v\ne0$ 时取

\[y_0=f_0(z)+\delta, \qquad y_1=f_1(z)-\delta/v\]

便保持 $Y=F(z)$。因此“commitments 先于 $v$”仍不够,claimed evaluations 也必须先于 $v$。

这里的 random batching 只压缩一组已经定义好的 evaluation claims。对 Merkle + FRI 一类 oracle PCS,还需 DEEP quotient、folding/sumcheck 等独立的 evaluation reduction,把域外声明 $f(z)=y$ 连接到被承诺的 LDE oracle;随机线性组合本身不能替代这一步。

6.2 多点 opening

PLONK 常需在 $\zeta$ 与 $\omega\zeta$ 打开不同集合。可用:

  • 分别生成两个 opening proofs;
  • 先把同点多项式随机合并,再做 two-point aggregation;
  • 使用专门的 multi-opening 协议。

具体 proof layout 取决于 KZG、IPA 或 FRI 后端。不能把某个实现的 opening 数量当作 PLONK 算术化的固定属性。

7. Fiat–Shamir:把 verifier 的随机性放进哈希

一个 public-coin 交互协议可能是:

\[P_1 \xrightarrow{\alpha} P_2 \xrightarrow{\beta} P_3 \xrightarrow{\zeta} \text{openings}.\]

Fiat–Shamir 令

\[\begin{aligned} \alpha&=H_{\mathsf{challenge}} (\mathsf{state}_0\|P_1),\\ \beta&=H_{\mathsf{challenge}} (\mathsf{state}_1\|P_2),\\ \zeta&=H_{\mathsf{challenge}} (\mathsf{state}_2\|P_3). \end{aligned}\]

prover 与 verifier 都从完整 transcript 重算挑战,从而得到 non-interactive argument。

7.1 transcript 应吸收什么

至少包括:

  • 协议名、版本、curve/field/hash suite 的 domain separator;
  • public parameters 或 verification key 的唯一 digest;
  • statement 与全部 public inputs;
  • 每一轮此前发送的 commitments、roots、evaluations;
  • batch 长度、类型标签与 canonical encoding;
  • 若有 recursion,inner proof 与 accumulator 的明确边界。
sequenceDiagram
    participant P as Prover
    participant T as Transcript
    participant V as Verifier
    P->>T: 吸收协议版本、VK、public input
    P->>T: 吸收第一轮 commitments
    T-->>P: squeeze beta,gamma
    P->>T: 吸收 permutation / lookup commitments
    T-->>P: squeeze alpha
    P->>T: 吸收 quotient commitments
    T-->>P: squeeze zeta
    P->>T: 吸收 ζ 及各 rotation 的 claimed evaluations
    T-->>P: squeeze batching challenge v
    P->>T: 吸收 PCS 辅助 commitments / opening-proof 群元素 / FRI final object
    T-->>P: squeeze u 或 query seed(若协议需要)
    P->>T: 吸收其余 opening data / Merkle paths
    P->>V: proof bytes
    V->>T: 按相同类型与顺序重放
    T-->>V: 得到相同挑战并验证

7.2 不是“调用一次 SHA-256”那么简单

实现必须处理:

  1. canonical serialization:群元素、字段元素只有一种合法字节编码;
  2. 长度前缀与类型标签:避免 $a\mathbin{\Vert}bc$ 与 $ab\mathbin{\Vert}c$ 歧义;
  3. subgroup / on-curve check:无效群元素不能进入代数检查;
  4. rejection sampling 或无偏映射:hash-to-field 不应引入可利用偏差;
  5. domain separation:不同 challenge、协议版本、递归层不能共用含义不明的哈希状态;
  6. statement binding:漏吸收 public input 会让证明可被移植到另一个 statement;
  7. 顺序一致:prover 和 verifier 必须对完全相同的 typed transcript 操作。

群点检查也必须按具体协议区分“单位元”和“无效点”。identity/infinity 是合法曲线群元素:零多项式的 KZG commitment、常数多项式的零 opening quotient,或某些 IPA 中间结果都可能合法等于单位元。parser 应始终检查 canonical encoding、on-curve 与 subgroup;只有 specification 明确要求某个位置非单位元时才拒绝 identity,不能全局套用“非无穷点”规则。

Fiat–Shamir 的经典安全论证通常在 Random Oracle Model;后量子声称还要核对 Quantum Random Oracle Model 中的变换和具体协议证明。使用后量子 hash 并不会自动补齐 QROM 证明。

8. “承诺隐藏”与“证明零知识”是两件事

8.1 PLONKish 的典型掩码

若 $a(X)$ 在 $H$ 上编码 witness,取随机低次 $r(X)$ 并设

\[\widehat a(X)=a(X)+Z_H(X)r(X).\]

由于 $Z_H(h)=0$,

\[\widehat a(h)=a(h)\qquad\forall h\in H,\]

所以门约束不变;但随机点 $\zeta\notin H$ 的值被掩盖。代价是 degree 增长,必须预留 PCS bound 和 quotient budget。

8.2 STARK 的典型问题

Merkle root 对整条 LDE 做确定性承诺,query phase 还会公开少量叶子。如果这些值是 witness 的直接编码,协议可能泄露统计信息。ZK-STARK 需要专门的 randomized encoding、masking polynomial、随机 padding/trace 或 ZK code 技术,并证明查询分布可模拟。

“verifier 只看几个点”不等于零知识;泄露一个精心选择的线性组合也可能泄露 secret。

9. 一次完整的安全归约应长什么样

最终接受概率通常由多项错误项组成:

\[\epsilon_{\mathrm{total}} \le \epsilon_{\mathrm{arith}} +\epsilon_{\mathrm{degree}} +\epsilon_{\mathrm{query}} +\epsilon_{\mathrm{commit}} +\epsilon_{\mathrm{FS}} +\epsilon_{\mathrm{hash}}.\]

它们大致对应:

  • 随机合并时错误约束恰好抵消;
  • 错误 quotient 通过随机点;
  • 远离低度码的 word 躲过 proximity queries;
  • PCS binding / knowledge assumption 被攻破;
  • Fiat–Shamir compiler 的模型误差;
  • Merkle collision 或 transcript collision。

不能把“查询 30 次所以是 120 bit”或“字段是 128 bit 所以 soundness 是 128 bit”作为完整计算。各事件可能相关,尤其多轮 FRI 的 soundness 需要 round-by-round / correlated agreement 分析。

10. 边界与审计清单

  1. SRS 的最大 degree 是否覆盖所有 quotient chunks 和 blinding 后 degree?
  2. verification key、public input、协议版本是否都进入 transcript?
  3. 每个随机挑战是否在它要随机化的对象被承诺之后生成?
  4. batching challenge 是否与被批对象 domain-separated?
  5. 群点是否做 canonical、on-curve、subgroup 检查,并按每个 proof 字段的协议规则决定 identity/infinity 是允许还是拒绝?
  6. Merkle leaf 是否含列号、行号、宽度或无歧义结构编码?
  7. query index 生成是否无偏,重复 query 如何计入 soundness?
  8. proof parser 是否拒绝 trailing bytes、重复字段和非规范字段元素?
  9. 所谓 ZK 是否有 masking 构造与模拟论证,而不是只依赖 commitment?
  10. 后量子结论是否覆盖 Fiat–Shamir、hash、commitment 与知识可靠性的完整组合?

11. 自测

  1. 从 $f(X)-f(z)=(X-z)q(X)$ 推导 KZG pairing 等式。
  2. 解释为什么知道 $\tau$ 会破坏 KZG 的安全直觉。
  3. 为什么 Merkle root 无法单独证明 evaluation vector 来自低次多项式?
  4. 对三个 commitments $C_f,C_g,C_h$ 写出同点随机批处理公式。
  5. 举例说明 transcript 漏吸收 public input 会造成什么重放问题。
  6. 为什么 IPA 没有 structured toxic waste,却仍不是后量子方案?

参考


上一篇:有限域、多项式与编码基础 · 下一篇:PLONK 算术化基础 · 返回:总目录

本文由作者按照 CC BY 4.0 进行授权