文章

12. Plonky3 模块化架构:从 Field、MMCS、PCS 到 AIR

12. Plonky3 模块化架构:从 Field、MMCS、PCS 到 AIR

版本口径:本篇以 2026-07-29 官方主分支快照 66e290615de1858f2f2f6a804158064c406cda1c 为准。Plonky3 API 演进很快,历史教程中的 crate/type 名可能已经变化。

1. “Plonky3”不是一份固定协议

官方 README 的定位是:

a toolkit which provides a set of primitives … for implementing polynomial IOPs

当前主要服务 STARK-based zkVM,但原则上也可用于 PLONK 或其他 PIOP。

所以不能只说:

\[\text{“这个系统使用 Plonky3”}.\]

至少应说明:

\[\boxed{ ( \text{AIR/PIOP}, \text{field}, \text{extension}, \text{domain/DFT}, \text{PCS}, \text{MMCS/hash}, \text{challenger}, \text{ZK mode}, \text{parameters} ). }\]

同样的 AIR 可搭配不同:

  • BabyBear + two-adic FRI + Poseidon2;
  • KoalaBear + two-adic FRI + Keccak;
  • Mersenne31 + Circle PCS;
  • 其他自定义 PCS/challenger。

它们都可以使用 Plonky3 crates,但不是相同 proof system,也不保证 proof bytes 兼容。

1.1 名字里有 Plonky,不代表当前实现以 PLONK 为主

当前 README 的 status list 中:

  • univariate STARK:已实现;
  • multivariate STARK:已实现/由当前模块演进承载;
  • PLONK:仍未勾选。

因此把 Plonky3 简称为“PLONK3 算法”会误导。当前主线更准确地称为:

\[\text{modular STARK / PIOP toolkit}.\]

2. 整体类型依赖图

flowchart TB
    F["Field traits<br/>base / extension / packed"] --> D["PolynomialSpace / Domain"]
    F --> M["Matrix"]
    D --> FFT["DFT / CFFT / interpolation"]
    M --> MMCS["MMCS<br/>mixed matrix commitment"]
    FFT --> PCS["PCS"]
    MMCS --> PCS
    H["Hash / permutation"] --> MMCS
    H --> CH["Challenger<br/>Fiat-Shamir"]
    F --> CH
    AIR["AIR + AirBuilder"] --> STARK["Uni-STARK / Batch-STARK"]
    PCS --> STARK
    CH --> STARK
    STARK --> PROOF["具体 proof format"]

关键设计思想是依赖倒置:

  • Uni-STARK 不直接写死 Merkle tree;
  • AIR 不直接写死 BabyBear;
  • PCS 不直接写死 Poseidon2;
  • challenger 不直接写死 proof protocol;
  • SIMD packing 不改变 AIR 公式。

3. Field 层:不仅是一个 Field trait

3.1 trait 层级

当前 p3-field 的核心层次包括:

  • PrimeCharacteristicRing:特征为素数的环运算;
  • Algebra:某个基础环上的代数;
  • Field:逆元、除法等域接口;
  • PrimeField / PrimeField32 / PrimeField64
  • TwoAdicField:二次幂根单位;
  • ExtensionField / BasedVectorSpace
  • PackedField / PackedValue:SIMD packed arithmetic。

这使同一 AIR expression 可以在三种语义下运行:

  1. 单个标量域元素;
  2. 一组 SIMD lanes;
  3. symbolic polynomial expression。

3.2 当前主要基础域

模数乘法群 two-adicity主要用途
Goldilocks$2^{64}-2^{32}+1$3264-bit two-adic FFT、Plonky2 兼容方向
BabyBear$15\cdot2^{27}+1=\texttt{0x78000001}$2731-bit SIMD-friendly two-adic STARK
KoalaBear$127\cdot2^{24}+1=\texttt{0x7f000001}$2431-bit SIMD-friendly two-adic STARK
Mersenne31$2^{31}-1$1Circle domain;利用 $p+1=2^{31}$ 的圆群

Mersenne31 的特殊点是:

\[v_2(p-1)=1,\]

所以基础域乘法群没有大 two-adic subgroup;但单位圆群阶与 $p+1$ 有关:

\[p+1=2^{31},\]

适合 Circle FFT/PCS。

3.3 扩域负责 challenge soundness

31-bit 基础域常搭配 degree-4 左右的 binomial extension:

\[\mathbb E = \mathbb F[X]/(X^4-w),\]

使 challenge space 接近:

\[|\mathbb E| \approx 2^{124}.\]

具体 degree/nonresidue 由 field config 决定。不能只凭“BabyBear”推断 extension degree。

3.4 packed field 不改变数学 statement

若 SIMD width 为 $s$,packed value

\[\widehat a =(a_0,\ldots,a_{s-1})\]

按 lane 做:

\[\widehat a+\widehat b =(a_0+b_0,\ldots,a_{s-1}+b_{s-1}).\]

AIR prover 可一次计算 $s$ 个 quotient-domain points。verifier 仍使用 scalar extension field,所以 SIMD 是实现优化,不改变 proof relation。

4. Domain 不再等同于“乘法子群”

PolynomialSpace 抽象一类:

  • 可定义 degree/basis 的 polynomial space;
  • 可选择 natural evaluation domain;
  • 可计算 vanishing polynomial;
  • 可得到 next point;
  • 可 split domain/evaluations;
  • 可评估 first/last/transition selectors

的对象。

4.1 two-adic multiplicative coset

普通 Uni-STARK 可取:

\[H=g\langle\omega\rangle, \qquad |H|=N=2^n.\]

next-row map 是:

\[x\longmapsto \omega x.\]

消失多项式:

\[Z_H(X)=X^N-g^N.\]

4.2 Circle domain

Circle STARK 不用普通 $X^N-g^N$ 基,而在圆群及其 polynomial basis 上定义:

  • standard position cosets;
  • circle FFT;
  • circle vanishing functions;
  • circle-specific DEEP quotient 与 fold。

Uni-STARK 通过 Pcs::DomainPolynomialSpace 使用这些能力,而不是在协议层写死 $\omega X$。

4.3 next_point 是 AIR 的关键要求

AIR transition 读取:

\[\mathbf t(r+1).\]

在 OOD verifier 中对应:

\[\mathbf t(\zeta_{\mathrm{next}}),\]

所以 natural domain 必须给出:

\[\zeta_{\mathrm{next}} = \operatorname{nextPoint}_H(\zeta).\]

对于乘法 coset 是 $\omega\zeta$;对 Circle domain 则由圆群步进定义。

5. Matrix 层:trace 是列多项式的 evaluation matrix

trace 写为:

\[T\in\mathbb F^{N\times w}.\]
  • 行 $r$:第 $r$ 个 machine step;
  • 列 $j$:一个 polynomial $t_j(X)$ 在 trace domain 上的 evaluations。

p3-matrix 抽象:

  • row-major dense matrix;
  • matrix views;
  • stacked/vertical pairs;
  • packed-row access;
  • transpose/strided layouts。

AIR 看到的是 current/next row window;PCS 看到的是“每一列是一条 polynomial evaluation vector”;MMCS 看到的是 LDE 后的 rows。

flowchart LR
    R["执行行语义<br/>state_r -> state_{r+1}"] --> T["N × w trace matrix"]
    T --> C["每列插值为 t_j(X)"]
    C --> L["在更大 domain 上做 LDE"]
    L --> H["逐行 hash / MMCS commitment"]

6. MMCS:把不同高度的矩阵放进同一承诺

Mmcs 是 Mixed Matrix Commitment Scheme。

它接收:

\[M_0,\ldots,M_{k-1}\]

且允许:

\[h_i=\operatorname{height}(M_i)\]

不同。

6.1 global index 语义

设最大高度

\[h_{\max}=2^m,\]

某矩阵高度

\[h_i=2^{m_i}.\]

global query index $q$ 映射为:

\[q_i = q\gg(m-m_i).\]

这非常适合 FRI:不同轮 codewords 高度逐轮下降,但可共用一套 query randomness。

6.2 commitment 与 prover data 分离

commit 返回:

\[(C,\mathsf{ProverData}).\]
  • $C$ 发给 verifier;
  • prover data 保存完整 matrices/Merkle tree,供之后 opening;
  • verifier 只需 commitment、dimensions、index、opened row、proof。

6.3 multi-opening

当前 trait 还区分:

  • 单个 Proof
  • 多 index 的 MultiProof

多个 Merkle paths 共享 ancestors,multi-proof 只发送一次共享 digest,可降低 proof size。

6.4 width 是 verifier-known security data

当前 trait 文档明确要求:

opened row length 必须等于 verifier-known width。

因为把多 rows 平铺进 hash 时,单个 digest 不会自动绑定矩阵边界。width 不能直接信任 proof。

7. PCS:承诺的是 polynomial evaluations

Pcs<Challenge, Challenger> 的关键 associated types:

  • Domain
  • Commitment
  • ProverData
  • EvaluationsOnDomain
  • Proof
  • Error
  • 常量 ZK

7.1 commit

输入:

\[\bigl(D_i,\ T_i|_{D_i}\bigr)_i.\]

输出:

\[(C,\mathsf{ProverData}).\]

7.2 open

对每个 committed matrix 指定若干点:

\[z_{i,0},\ldots,z_{i,s_i-1}.\]

返回:

  • 每列在这些点的 evaluations;
  • 一份聚合 opening proof。

7.3 verify

verifier 输入:

\[\bigl( C_i, D_{i,j}, (z_{i,j,k},\mathbf v_{i,j,k})_k \bigr)_{i,j}\]

和 opening proof,检查所有声称点值。

7.4 quotient chunks

commit_quotient 可把高 degree quotient evaluation matrix 拆成多个低度 subdomain chunks,再统一承诺。

7.5 ZK 是 backend property

Pcs::ZK 是编译期常量:

\[\texttt{true} \quad\text{或}\quad \texttt{false}.\]

Uni-STARK 根据它决定:

  • 是否扩展 trace;
  • 是否产生 randomization commitment;
  • proof shape 中是否应有 random openings。

8. 当前 PCS 后端不是只有 FRI

8.1 TwoAdicFriPcs

对 two-adic multiplicative cosets:

  • DFT/LDE;
  • MMCS commitment;
  • DEEP opening reduction;
  • configurable-arity FRI。

8.2 HidingFriPcs

在 FRI PCS 上增加:

  • trace randomization;
  • hiding MMCS;
  • random polynomial/opening terms;
  • ZK proof layout。

8.3 CirclePcs

在 circle domains 上实现:

  • Circle FFT;
  • circle DEEP quotient;
  • circle-specific FRI fold;
  • Mersenne31 支持。

8.4 WHIR

p3-whir 面向 multilinear polynomial commitments,并实现 MultilinearPcs 侧的接口。它使用:

  • constrained Reed–Solomon proximity;
  • sumcheck;
  • rate-improving/code-switching 思路;
  • 当前另有 hiding/ZK modules。

它不是把 TwoAdicFriPcs 的 type alias 换个名字;polynomial representation 与 verifier flow 都不同。

9. Challenger:Fiat–Shamir 是一个独立模块

p3-challenger 提供:

  • CanObserve
  • CanSample
  • CanSampleBits
  • FieldChallenger
  • GrindingChallenger

实现包括:

  • DuplexChallenger:基于 permutation 的 sponge;
  • HashChallenger:基于通用 hash;
  • SerializingChallenger32/64:field-to-byte/word bridge;
  • MultiField32Challenger:跨字段 challenger。

9.1 transcript 的核心不变量

prover 和 verifier 必须满足:

\[\operatorname{TranscriptState}^{P}_i = \operatorname{TranscriptState}^{V}_i\]

对每一步 $i$ 成立。

所有会影响 challenge 的数据,必须在采样前 observe:

\[c_i = \mathsf{Sample}\bigl( \mathsf{Observe}(s_{i-1},m_i) \bigr).\]

9.2 field serialization 是协议的一部分

若 hash 接收 bytes 而 AIR values 是 field elements,必须固定:

  • canonical encoding;
  • endianness;
  • length framing;
  • extension basis order;
  • rejection/reduction rule。

SerializingChallenger 是密码协议组件,不只是工程适配器。

10. AIR:一份约束,多种执行语义

10.1 BaseAir 描述静态接口

当前 BaseAir<F> 可声明:

  • width():main trace columns;
  • preprocessed_trace() / preprocessed_width()
  • periodic_columns()
  • num_public_values()
  • main_next_row_columns()
  • preprocessed_next_row_columns()
  • 可选 num_constraints() hint;
  • 可选 max_constraint_degree() hint。

10.2 Air<AB> 只写 eval

AIR 核心是:

1
2
3
trait Air<AB: AirBuilder>: BaseAir<AB::F> {
    fn eval(&self, builder: &mut AB);
}

AirBuilder 提供:

  • current/next row window;
  • first/last/transition selectors;
  • public values;
  • preprocessed/periodic values;
  • assert_zeroassert_eqassert_bool
  • filtered builder:when_first_rowwhen_transition 等。

10.3 三种 builder

同一个 eval 至少可在三种环境运行。

Symbolic builder

变量是 symbolic expressions,用于推导:

  • constraint count;
  • maximum degree;
  • 哪些 columns/rotations 被访问;
  • quotient chunks 数。

Prover folder

变量是 packed field evaluations,在 quotient domain 上并行计算:

\[Q(x) = \frac{ \sum_i\alpha^i C_i(x) }{ Z_H(x) }.\]

Verifier folder

变量是 $\zeta$ 上的 extension-field openings,用 Horner accumulator 重算:

\[C_\alpha(\zeta).\]
flowchart TB
    E["同一 Air::eval 源码"] --> S["SymbolicAirBuilder<br/>推导 degree 与 layout"]
    E --> P["ProverConstraintFolder<br/>批量算 quotient evaluations"]
    E --> V["VerifierConstraintFolder<br/>重算 OOD identity"]
    S --> Q["quotient chunks shape"]
    P --> PR["proof"]
    V --> VR["verification"]

这比 Plonky2.5 的双份手写 AIR 更稳健:约束顺序和公式由同一 eval 源码产生。

11. Fibonacci AIR 的完整关系

设每行两列:

\[(l_r,r_r).\]

公开值:

\[(a,b,x).\]

约束:

11.1 首行

\[s_{\mathrm{first}}(r) \bigl(l_r-a\bigr)=0,\] \[s_{\mathrm{first}}(r) \bigl(r_r-b\bigr)=0.\]

11.2 transition

\[s_{\mathrm{trans}}(r) \bigl(l_{r+1}-r_r\bigr)=0,\] \[s_{\mathrm{trans}}(r) \bigl(r_{r+1}-l_r-r_r\bigr)=0.\]

11.3 末行

\[s_{\mathrm{last}}(r) \bigl(r_r-x\bigr)=0.\]

trace:

\[\begin{array}{c|cc} r&l_r&r_r\\\hline 0&a&b\\ 1&b&a+b\\ 2&a+b&a+2b\\ \vdots&\vdots&\vdots \end{array}\]

BaseAir::num_public_values()=3 让 verifier 精确检查公开值长度。若 proof/application 给出两个或四个 values,应在进入 PCS 前就拒绝。

12. Uni-STARK 完整协议

以下令:

  • base field 为 $\mathbb F$;
  • challenge extension 为 $\mathbb E$;
  • trace 高度为 $N=2^n$;
  • trace width 为 $w$;
  • PCS natural trace domain 为 $H$。

12.1 推导 layout 与 constraint degree

prover 先构造 AirLayout

\[\mathcal L = ( w_{\mathrm{main}}, w_{\mathrm{pre}}, n_{\mathrm{PI}}, n_{\mathrm{periodic}}, \ldots ).\]

symbolic evaluation 得到约束最大 degree factor $d$,进而确定 quotient chunks。

12.2 trace domain

非 ZK 时:

\[|H|=N.\]

ZK backend 时,当前 Uni-STARK 把 committed trace domain 扩为:

\[|H_{\mathrm{ext}}|=2N.\]

源码中的:

\[\texttt{log\_ext\_degree} = \log_2N+\texttt{is\_zk}.\]

其中 is_zk 是 0 或 1。

12.3 commit trace

PCS 对 trace 做 LDE 并承诺:

\[(C_T,\mathsf{pd}_T) \leftarrow \mathsf{PCS.Commit} \bigl( H_{\mathrm{ext}}, T \bigr).\]

若有 preprocessed trace,其 commitment 可在 setup 阶段单独生成并由 verifier key 固定。

12.4 transcript 绑定 instance

当前 prover/verifier observe:

  • extended degree bits;
  • base degree bits;
  • preprocessed width;
  • trace commitment;
  • 可选 preprocessed commitment;
  • public values。

然后采样 constraint-folding challenge:

\[\alpha\in\mathbb E.\]

这比“只吸收 trace root”更明确地绑定 proof partition 与 statement。

12.5 quotient domain

选择足够大的、与 trace domain disjoint 的 quotient domain:

\[K, \qquad |K|=N\cdot t,\]

其中 $t$ 是 quotient chunk 数的二次幂。

trace LDE 必须覆盖 $K$,从 prover data 取出:

\[\mathbf t(x), \mathbf t(\operatorname{next}(x)) \quad \text{for }x\in K.\]

12.6 计算 folded constraints

在每个 $x\in K$:

\[C_\alpha(x) = \sum_{i=0}^{m-1} \alpha^i C_i(x),\]

并算:

\[Q(x) = C_\alpha(x)Z_H(x)^{-1}.\]

prover folder 用 packed values 一次处理多个 $x$。

12.7 extension quotient 展平

$Q(x)\in\mathbb E$。若

\[[\mathbb E:\mathbb F]=D\]

且 basis 为

\[(1,\theta,\ldots,\theta^{D-1}),\]

写:

\[Q(X) = \sum_{d=0}^{D-1} Q_d(X)\theta^d, \qquad Q_d(X)\in\mathbb F[X].\]

于是 extension-valued quotient matrix 被展平成 $D$ 倍基础域 columns,便于基础域 PCS 承诺。

12.8 split quotient chunks

把 quotient domain $K$ 拆成:

\[K_0,\ldots,K_{t-1}, \qquad |K_i|\approx N.\]

每个 chunk 上得到低 degree polynomial evaluations,统一承诺:

\[(C_Q,\mathsf{pd}_Q) \leftarrow \mathsf{PCS.CommitQuotient}.\]

transcript 吸收 $C_Q$。

12.9 可选 randomization commitment

Pcs::ZK=true,prover 还生成随机 polynomial commitment:

\[C_R.\]

transcript 在采样 $\zeta$ 前吸收 $C_R$。

12.10 OOD point

采样:

\[\zeta\in\mathbb E\]

并计算:

\[\zeta_{\mathrm{next}} = \operatorname{nextPoint}_H(\zeta).\]

若 AIR 不访问 next row,可通过 main_next_row_columns() 返回空集,从而不打开 $\zeta_{\mathrm{next}}$。

12.11 聚合 openings

一次 PCS opening 覆盖:

\[\begin{aligned} \mathbf t(\zeta),\quad \mathbf t(\zeta_{\mathrm{next}}),\\ \mathbf q_i(\zeta) \quad (0\le i<t),\\ \text{可选 preprocessed openings},\\ \text{可选 random openings}. \end{aligned}\]

得到:

\[(\mathcal O,\pi_{\mathrm{PCS}}).\]

12.12 verifier

verifier 重建 transcript,检查:

  1. proof shape;
  2. public-value length;
  3. preprocessed verifier key 一致性;
  4. ZK random commitment presence;
  5. $\zeta\notin H$;
  6. periodic-column lengths;
  7. PCS openings;
  8. quotient recomposition;
  9. AIR OOD identity。
sequenceDiagram
    participant P as Prover
    participant T as Challenger
    participant V as Verifier
    P->>T: degree bits, widths, trace commit, public values
    T-->>P: alpha
    P->>P: Q = folded constraints / Z_H
    P->>T: quotient commitment
    P->>T: optional randomization commitment
    T-->>P: zeta
    P->>V: OOD openings + PCS proof
    V->>V: verify PCS
    V->>V: recompose Q(zeta)
    V->>V: evaluate AIR at zeta
    V->>V: check C_alpha(zeta) / Z_H(zeta) = Q(zeta)

13. constraint degree 与 quotient chunks

13.1 degree factor

trace column polynomial 的 degree 最多为 $N-1$。若某 AIR expression 是三个 trace variables 的乘积:

\[C(X)=t_1(X)t_2(X)t_3(X),\]

其 degree 约为:

\[3(N-1).\]

称 constraint degree factor 为 3。

13.2 selector 的细节

  • first-row selector degree 可到 $N-1$;
  • last-row selector degree 可到 $N-1$;
  • transition selector 只需在最后一行关闭,特定构造下 degree 很低。

所以:

\[s_{\mathrm{first}}(X)t_1(X)^3\]

\[s_{\mathrm{transition}}(X)t_1(X)^3\]

的精确 degree bound 不同。symbolic builder 对 selector expression 有专门 degree bookkeeping。

13.3 chunks 公式

当前非 ZK 情况粗略使用:

\[t = 2^{ \left\lceil \log_2\bigl(\max(d,2)-1\bigr) \right\rceil }.\]

ZK 时源码把 effective constraint degree 调整为:

\[d_{\mathrm{eff}} = \max(d+1,2),\]

再选择:

\[t = 2^{ \lceil\log_2(d_{\mathrm{eff}}-1)\rceil }.\]

额外随机化还会影响实际 committed quotient chunks 数。具体值由 get_log_num_quotient_chunks 与 PCS ZK layout 共同决定。

13.4 degree hint 是安全关键 hint

AIR 可实现:

1
fn max_constraint_degree(&self) -> Option<usize>

过高的 hint 只会浪费性能;过低的 hint 可能让 quotient domain 不够大。当前代码在 debug 模式用 symbolic evaluation 交叉检查,但 release 部署仍应:

  • 将 AIR code 视为 verifier policy;
  • 通过测试/审计确认 hint 是上界;
  • 不让 prover 动态控制 hint。

14. quotient chunks 的 OOD 重组

设 chunks domains 为:

\[K_0,\ldots,K_{t-1}.\]

当前 verifier 对第 $i$ 块计算:

\[\lambda_i(\zeta) = \prod_{j\ne i} \frac{ Z_{K_j}(\zeta) }{ Z_{K_j}(x_i) },\]

其中 $x_i$ 是 $K_i$ 的 first point。

每个 chunk opening 是 $D$ 个基础域 coordinates:

\[(q_{i,0}(\zeta),\ldots,q_{i,D-1}(\zeta)).\]

先恢复 extension element:

\[q_i(\zeta) = \sum_{d=0}^{D-1} q_{i,d}(\zeta)\theta^d.\]

再重组:

\[\boxed{ Q(\zeta) = \sum_{i=0}^{t-1} \lambda_i(\zeta)q_i(\zeta). }\]

这是一种按 disjoint domains 的 Lagrange glue,不应与简单 monomial decomposition

\[\sum_i\zeta^{iN}q_i(\zeta)\]

不加说明地混用。

15. preprocessed columns 与 periodic columns

两者都不是普通 private main trace,但机制不同。

15.1 preprocessed trace

是 verifier 已知、可能不规则的 matrix,例如:

  • program ROM;
  • 固定 selector table;
  • circuit wiring metadata。

它通常:

  • 在 setup 时承诺;
  • commitment 放进 verifier key/common data;
  • proof 只打开需要的点;
  • 不因 witness 改变。

15.2 periodic columns

是短周期公开序列:

\[(c_0,\ldots,c_{p-1})\]

在 trace 上重复。

若 $p\mid N$,可把短表解释为 degree $<p$ polynomial 的 evaluations,再扩成 trace-domain periodic polynomial。prover/verifier都能直接在 $\zeta$ 计算:

\[c_{\mathrm{periodic}}(\zeta),\]

无需 commitment。

15.3 安全差异

类型是否承诺verifier 如何获得 OOD value
main tracePCS opening
preprocessed trace是,通常 setupPCS opening + VK commitment
periodic column从公开短周期直接计算
public valuesapplication 直接提供并 transcript-bound

periodic column length 必须是二次幂且不超过 trace length;当前 verifier 会显式拒绝不合法长度。

16. 当前 Uni-STARK proof object

可概括为:

\[\pi = ( \mathsf{Commitments}, \mathsf{OpenedValues}, \pi_{\mathrm{PCS}}, \mathsf{degreeBits} ).\]

16.1 commitments

至少:

\[C_T,\quad C_Q,\]

ZK 模式可再有:

\[C_R.\]

preprocessed commitment 通常来自 verifier key,而非每份 proof 自报。

16.2 opened values

包含:

\[\begin{aligned} &\mathbf t(\zeta),\\ &\mathbf t(\zeta_{\mathrm{next}})\quad\text{if needed},\\ &\mathbf p_{\mathrm{pre}}(\zeta), \mathbf p_{\mathrm{pre}}(\zeta_{\mathrm{next}})\quad\text{if needed},\\ &q_i(\zeta)\text{ 的基础域 coordinates},\\ &\mathbf r(\zeta)\quad\text{in ZK mode}. \end{aligned}\]

16.3 degree bits

proof 的 API 字段虽称 degree_bits,实际存的是 extended trace domain 的 log size:

\[d_{\mathrm{proof}} = \log_2|D_{\mathrm{ext}}| = \log_2N+\texttt{is\_zk}.\]

verifier:

  • 检查它不超过 PCS 最大 domain;
  • ZK 时减去 1,恢复 base trace-domain 的 log size(API 仍称 base degree bits);
  • 用它重建所有 domains;
  • 不直接相信 proof 中任意数组长度。

17. ZK mode 到底增加了什么

17.1 不是给 prove 加一个布尔参数

是否 ZK 由 PCS type 的:

\[\texttt{Pcs::ZK}\]

决定。Uni-STARK proof shape 随之改变。

17.2 trace randomization

设 base trace domain 的大小为 $N$,因此每个插值得到的 trace polynomial 满足

\[\deg T_j<N.\]

当前协议在 ZK mode 中把 randomized committed domain 的大小扩到:

\[2N,\]

相应承诺多项式的 degree bound 变为 $<2N$,并加入随机值,使被打开的 LDE 不直接泄露原 trace polynomial 的确定函数。这里扩大的对象是 domain size/degree bound,不能把“大小为 $N$ 的 trace domain”简称为“degree 等于 $N$”。

17.3 hiding MMCS

普通 Merkle root 对 leaves 是 binding,但不是自动 hiding。hiding MMCS 可给 leaves 加:

  • salts;
  • 随机 padding;
  • backend-specific hiding data。

17.4 random polynomial

当前 Uni-STARK source 还生成 extension random polynomial $R$ 的基础域 coordinates commitment,并在 opening batch 中加入类似:

\[\frac{R(X)-R(\zeta)}{X-\zeta}.\]

这随机化 DEEP/FRI batch polynomial。

源码注释明确指出当前这一路径是 statistical ZK;若要 perfect ZK,需要更强的 extension-polynomial sampling 处理。因此文档不应把 “Pcs::ZK=true” 自动翻译为脱离 backend/版本的统一模拟定理。

17.5 verifier 的 presence checks

ZK 开启时:

\[C_R\ne\varnothing, \qquad \mathbf r(\zeta)\ne\varnothing.\]

关闭时两者必须都不存在。verifier 会拒绝:

  • ZK proof 缺 random commitment;
  • non-ZK proof 偷带 random fields;
  • commitment 与 opened value presence 不一致。

17.6 preprocessed columns 不需要 hiding

preprocessed data 是公开固定信息,所以即使 main PCS 为 ZK,preprocessed commitment 也可走 commit_preprocessing 的非随机化路径。

18. 一个具体 config 是类型级密码规范

当前测试中的典型 two-adic 配置可抽象为:

1
2
3
4
5
6
7
8
9
10
11
12
type Val = BabyBear;
type Perm = Poseidon2BabyBear<16>;
type Hash = PaddingFreeSponge<Perm, 16, 8, 8>;
type Compress = TruncatedPermutation<Perm, 2, 8, 16>;
type ValMmcs = MerkleTreeMmcs<...>;

type Challenge = BinomialExtensionField<Val, 4>;
type ChallengeMmcs = ExtensionMmcs<Val, Challenge, ValMmcs>;
type Challenger = DuplexChallenger<Val, Perm, 16, 8>;
type Dft = Radix2DitParallel<Val>;
type Pcs = TwoAdicFriPcs<Val, Dft, ValMmcs, ChallengeMmcs>;
type Config = StarkConfig<Pcs, Challenge, Challenger>;

这个 type stack 固定了:

\[\begin{aligned} &\mathbb F=\text{BabyBear},\\ &\mathbb E/\mathbb F\text{ degree}=4,\\ &\text{Merkle leaf hash/compression},\\ &\text{Fiat–Shamir permutation/rate},\\ &\text{DFT algorithm},\\ &\text{PCS 与 FRI MMCS}. \end{aligned}\]
flowchart TB
    V["BabyBear Val"] --> E["Degree-4 Challenge"]
    V --> D["Radix-2 DFT"]
    P["Poseidon2 width 16"] --> H["Sponge / compression"]
    H --> M["Val MMCS"]
    M --> CM["Extension MMCS"]
    D --> PCS["TwoAdicFriPcs"]
    M --> PCS
    CM --> PCS
    P --> CH["Duplex challenger"]
    PCS --> CFG["StarkConfig"]
    E --> CFG
    CH --> CFG

所以“换一个 hash”会改变:

  • commitment bytes;
  • transcript;
  • challenges/query indices;
  • proof compatibility;
  • recursive verifier;
  • security cap。

它不是纯性能 flag。

19. 当前仓库的模块版图

截至快照,主仓库包含或明确暴露以下类别。

19.1 fields

  • Goldilocks;
  • BabyBear;
  • KoalaBear;
  • Mersenne31;
  • BN254 field utilities;
  • binomial/complex extensions;
  • AVX2、AVX-512、NEON、SVE2 等 packed implementations。

19.2 hashes 与 AIRs

  • Poseidon / Poseidon2;
  • Rescue;
  • Monolith;
  • BLAKE3;
  • Keccak;
  • SHA-256;
  • 对应的部分 hash AIR crates。

19.3 protocol primitives

  • air
  • matrix
  • dft
  • commit
  • merkle-tree
  • challenger
  • fri
  • circle
  • whir
  • sumcheck
  • lookup
  • security

19.4 proof frameworks

  • uni-stark:单 AIR;
  • batch-stark:多 AIR/不同高度/shared opening;
  • hash AIR examples;
  • 独立官方 Plonky3-recursion 仓库。

文件夹存在不等于:

  • 所有组合都实现;
  • 所有组合都审计;
  • 所有组合都 production ready;
  • 所有 proof formats 互相兼容。

20. 当前安全计算也被模块化

当前主分支新增 p3-security / Uni-STARK security adapter,显式区分:

  • conjectured random-words estimate;
  • proven unique-decoding regime;
  • proven list-decoding regime;
  • AIR constraint batching error;
  • DEEP-ALI error;
  • FRI commit/query errors;
  • batched-function proximity error;
  • hash collision-resistance cap。

这说明安全级别不应再只写:

\[\texttt{numQueries}\times\texttt{logBlowup} +\texttt{powBits}.\]

一份 concrete config 还需要:

\[\begin{aligned} &\text{trace length},\quad |\mathbb E|,\quad \text{constraint count/degree},\\ &\text{max rotation combo},\quad \text{batched functions},\quad \text{hash collision bits}. \end{aligned}\]

下一篇会专门推导当前 FRI/LogUp/batch/recursion 的安全与协议结构。

21. 为什么没有“Plonky3 通用 proof bytes”

proof serialization 至少依赖:

\[\begin{aligned} &\text{Commitment associated type},\\ &\text{PCS Proof associated type},\\ &\text{challenge extension coordinates},\\ &\text{domain/chunk layout},\\ &\text{ZK presence fields},\\ &\text{AIR width/rotations},\\ &\text{degree bits}. \end{aligned}\]

因此两个都叫 Proof<SC> 的对象,只要 SC 不同,就可能:

  • 字段不同;
  • commitment type 不同;
  • path layout 不同;
  • extension dimension 不同;
  • transcript 不同。

生产 API 应给完整 config/schema 版本号,而不是只写:

1
{ "proofSystem": "plonky3" }

更合理的是:

1
2
3
4
5
6
7
8
9
10
{
  "proofSystem": "p3-uni-stark",
  "schemaVersion": 3,
  "field": "babybear",
  "challengeExtensionDegree": 4,
  "pcs": "two-adic-fri",
  "hash": "poseidon2-babybear-w16",
  "zk": true,
  "parameterSet": "app-v7"
}

实际字段名由项目定义;重点是完整绑定。

22. malformed proof 与 panic 边界

当前官方 README 提醒:

verifier may panic on certain malformed proofs

并建议接收不可信 proofs 的集成方考虑 catch_unwind

这不等于 panic 就是密码学伪造,但会形成:

  • verifier process DoS;
  • batch service worker crash;
  • FFI boundary unwind/abort;
  • 共识节点可用性问题。

安全接入顺序应是:

  1. byte length 上限;
  2. 安全反序列化;
  3. exact shape validation;
  4. verifier-known dimensions;
  5. panic isolation;
  6. typed verification error;
  7. resource/time limits。

不能让 proof 自报一个极大 degree_bits 后先分配内存,再检查上限。

23. 选择模块时要回答的问题

23.1 field/domain

  • trace 最大长度是否超过 two-adicity?
  • 31-bit packed throughput 还是 64-bit 简单性更重要?
  • 是否需要 Circle domain?
  • challenge extension 提供多少 algebraic bits?

23.2 PCS/MMCS

  • two-adic FRI、Circle FRI 还是 multilinear PCS?
  • Merkle hash 是 algebraic 还是 byte-oriented?
  • 是否需要 hiding?
  • multi-opening/path compression 如何编码?

23.3 AIR

  • constraint degree 上限?
  • 是否使用 next row?
  • public/preprocessed/periodic columns schema?
  • 是否有 lookup/cross-AIR buses?

23.4 transcript

  • 何时 absorb structural data?
  • domain separation?
  • extension/bit sampling?
  • grinding 放在哪个阶段?

23.5 security/operations

  • 使用 proven bound 还是明确标注 conjectured?
  • hash collision cap?
  • proof parser 是否隔离 panic?
  • target commit 是否审计?
  • recursion stack 是否另行审计?

24. 总结

Plonky3 的核心贡献不是一条新的单体 verifier equation,而是把证明系统拆成可替换、可测试的边界:

\[\boxed{ \text{Field} \to \text{Domain/DFT} \to \text{MMCS} \to \text{PCS} \to \text{AIR/PIOP} \to \text{Proof}. }\]

其中 Fiat–Shamir challenger 横跨每一层。

模块化带来:

  • 同一 AIR 可试验多个字段/PCS;
  • 同一 MMCS 可服务不同 FRI layers;
  • packed arithmetic 与 scalar verifier 分离;
  • Uni-STARK 不依赖单一 commitment backend。

模块化也带来新的责任:

  • 完整 config 才是协议;
  • 任意两个 crates 能编译不等于组合安全;
  • proof format 不是“Plonky3”一个字符串;
  • 每次替换 hash/domain/PCS 都要重做 transcript、参数和审计分析。

25. 一手资料


上一篇:Plonky2.5 跨系统递归桥
下一篇:Plonky3 的 FRI、LogUp 与原生递归
返回:总目录

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