Polygon zkEVM PIL-STARK Spearbit审计报告解读(2023年3月版)

1. 引言

前序博客有:

主要内容见:

本轮审计历时2周,重点关注:

  • PIL(Polynomial Interpolation Language)argument,具体包括:lookup argument、multiset equality argument、connection argument。
  • STARK recursion pipeline,其proofs会被压缩并递归组合,以实现高效验证。

Spearbit团队审计了所提供的概述密码学证明系统的白皮书,并随后审查了其实施情况,以确保该协议在书面描述方面得到了忠实实施。总体而言,在密码学或实现审查中都没有发现重大的可靠性问题。一些较小的编辑、信息和优化问题浮出水面,但没有一个需要Polygon团队立即采取行动。

在论文和代码中发现:

  • 5个是轻微漏洞,
  • 4个是信息提示类,
  • 2个是不一致问题,
  • 3个是优化建议。

具体的审计内容为:

  • 1)PIL论文:Polynomial Identity Language (PIL): A Machine Description Language for Verifiable Computation,2023年2月13日v1.0版本。
  • 2)eSTARK论文:eSTARK: Extending the STARK Protocol with Arguments,2023年2月10日v1.0版本,和,2023年3月15日v1.2版本。
  • 3)Recursion论文:Recursion, aggregation, and composition of proofs,2023年2月13日v1.0版本。
  • 4)fflonk论文:fflonk: a Fast-Fourier inspired verifier efficient verson of PlonK,见Fflonk hackmd笔记-2023022020211101:124505版本Fflonk论文
  • 5)Recursion pipeline:
  • 6)对PIL的STARK prover和verifier:
    • https://github.com/0xPolygonHermez/pil-stark
    • 具体文件为:stark_gen、stark_setup、stark_verify、starkinfo、starkinfo_cp_prover、starkinfo_cp_verifier、starkinfo_fri_prover、starkinfo_fri_verifier、starkinfo_step1、starkinfo_step2、transcript。
    • 针对包含lookup argument、multiset equality argument和connection argument的某PIL描述,相应的STARK proof generation代码和verification代码。

2. 协议文档/白皮书审计

审计的文档有:

  • 1)PIL论文:Polynomial Identity Language (PIL): A Machine Description Language for Verifiable Computation,2023年2月13日v1.0版本。
  • 2)eSTARK论文:eSTARK: Extending the STARK Protocol with Arguments,2023年2月10日v1.0版本,和,2023年3月15日v1.2版本。
  • 3)Recursion论文:Recursion, aggregation, and composition of proofs,2023年2月13日v1.0版本。
  • 4)fflonk论文:fflonk: a Fast-Fourier inspired verifier efficient verson of PlonK,见Fflonk hackmd笔记-2023022020211101:124505版本Fflonk论文

2.1 PIL论文 + eSTARK论文

2.1.1 信息提示类:PIL中的connection argument定义,与eSTARK v1.0文档中的不一致

eSTARK中,1.5节的connection argument,应与PIL文档中1.9节的Definition 4(标记为Multi-Column Copy-Satisfiability)一致。但1.9节的Definition 3(标记为Connection Argument),指向的是Single-Column变种。

建议:

  • 在PIL文档中,将Definition 3标记为Single-Column Connection Argument,并在eSTARK的1.5节的描述明确为Multi-Column Connection Argument。

2.1.2 不一致问题:eSTARK v1.0的connection argument定义中,包含了不一致的partition定义

eSTARK的1.5节connection argument中定义了某partition T = { T 1 , ⋯   , T k } T=\{T_1,\cdots,T_k\} T={T1,,Tk},暗示 T 1 , ⋯   , T k T_1,\cdots,T_k T1,,Tk为partition sets。但是,并没有必要限制partition sets的数量为 k k k。如1.4节的Definition 4所莫奥数,列的数量可(且通常)不同于partition sets的数量。我们认为,这混淆了,partition sets,与,用于编码该partition permutation的向量。用于编码partition permutation的向量数,与,列数,是一样的。
修复:

  • Polygon zkEVM团队已在eSTARK v1.2版本中解决。

2.1.3 轻微漏洞:lookup argument和multiset equality argument中的selection变量未被约束

eSTARK v1.0文档2.4节中,Step 1描述了Prover发送的selector多项式,其存在2个潜在问题:

  • 1)若Verifier未将selector多项式,视为常量(预处理)多项式,则该关系将是trivially satisfiable的。Prover可简单设置这些selectors为相同的0值,使得Selected Vector Argument毫无意义。
  • 2)此外,除上面的trivial satisfying selection问题之外,若Prover有意发送自己的selectors,则没有verification check来确认基于 G G G的selector多项式是 { 0 , 1 } \{0,1\} {0,1}

建议:

  • 完备的Selected Vector Argument中,应包含,基于 G G G的selector多项式是 { 0 , 1 } \{0,1\} {0,1},的verification check。

修复:

  • Polygon zkEVM团队指出,在其zkEVM上下文中,存在额外的约束,来确保Prover所提供的selector多项式在 { 0 , 1 } \{0,1\} {0,1},即其为对某仅包含 { 0 , 1 } \{0,1\} {0,1}的预处理table的lookup结果。

2.1.4 轻微漏洞:在Verifier challenges中误用Poseidon哈希,导致unexploitable length-extension weakness

eSARK v1.0版本的2.2节,为根据第7、8、9个域元素生成第3个verifier challenge,需生成一组新的8个域元素(第9个域元素不包含在之前集合内)。为此, 8 zeroes are hashed with the previous capacity。这样的输出,与直接在消息中附加8个0值(即 M ∣ ∣ 00000000 M||00000000 M∣∣00000000)的哈希结果是一样的。

建议:

  • STARK prover中这种特殊的误用情况,可能不会引起问题,因该transcript的输入可能不是length-extended的。推荐将Poseidon哈希函数看做是具有连续可变长度输出的XOF,来生成额外的verifier challenges。将完整的12个元素(capacity + output)用作下一轮Poseidon permutation的输入,然后使用前8个元素(without the capacity)作为partial output,根据需要可重复多次。从而可模仿sponge哈希函数的squeeze操作。

2.1.5 优化建议:使用Poseidon的XOF模式,来生成所需的verifier challenges

eSTARK v1.0中限定了所需的verifier challenges数量。不确定这种设计是否会影响可靠性,但若是基于生成额外verifier challenges的灵活性考虑,则可避免该限定。

  • 1)eSTARK v1.0的2.2节中声称,其可生成的verifier challenges数量是有限定的。
  • 2)eSTARK v1.0的2.5节中声称,难以为生成quotient多项式来生成大量的verifier challenges。
  • 3)eSTARK v1.0的2.7节中声称,为生成FRI多项式来生成大量verifier challenges是个问题。

如果是为了降低recursion中STARK verifier的size,而将减少verifier challenges数量作为一种优化策略,则可忽略如下建议:

  • 若使用Poseidon XOF模式,则以上都将不是问题。

回复:

  • Polygon zkEVM团队确认,减少verifier challenges数量不是因为无法灵活生成更多,而是作为优化策略,以避免额外编码更多的Poseidon rounds,从而使recursive circuit最小化。

2.1.6 信息提示类:preprocessed多项式未包含在首个prover message内

在eSTARK v1.2的4.5节完整协议描述中,preprocessed多项式未包含在Merkle tree commitment内。

建议:

  • 按之前章节所描述的那样,在首个prover message内包含preprocessed多项式。

2.2 Recursion论文

2.2.1 不一致问题:所使用与所描述的rootC不一致

在recursion论文的4.2.6节的图17中,public input rootC,与hard-coded rec1 rootC是复用的。图17中的描述有误。

建议:

2.3 fflonk论文

2.3.1 信息提示类:小的soundness bound错误

在fflonk论文的Lemma 6.4的soundness bound proof中,存在off-by-one error(差一错误)。注意 A ∣ ( p − 1 ) A|(p-1) A(p1),其中 p p p F F F的size。 F F F A A A-th powers集合 S S S中包含 0 0 0,因此, ∣ S ∣ = p − 1 A + 1 |S|=\frac{p-1}{A}+1 S=Ap1+1。令 F i F_i Fi为非零多项式。对于从 S S S中均匀采样的 s s s,其概率:
f i ( s ) = 0 ≤ def  F i p − 1 A + 1 < def ( F i ) ⋅ A p − 1 f_i(s)=0\leq \frac{\text{def } F_i}{\frac{p-1}{A}+1}<\frac{\text{def}(F_i)\cdot A}{p-1} fi(s)=0Ap1+1def Fi<p1def(Fi)A

3. 代码审计

代码审计范围为:

  • 1)Recursion pipeline:
  • 2)对PIL的STARK prover和verifier:
    • https://github.com/0xPolygonHermez/pil-stark
    • 具体文件为:stark_gen、stark_setup、stark_verify、starkinfo、starkinfo_cp_prover、starkinfo_cp_verifier、starkinfo_fri_prover、starkinfo_fri_verifier、starkinfo_step1、starkinfo_step2、transcript。
    • 针对包含lookup argument、multiset equality argument和connection argument的某PIL描述,相应的STARK proof generation代码和verification代码。

zkEVM安全审计需对所有与zkEVM相关的密码学完整代码都进行审计,当前本报告形成时,未对如下代码进行审计:

  • 1)将PIL文件编译为STARK prover输入数据架构。见:pilcom
  • 2)将PIL-derived STARK verifier,编码为cricom
  • 3)将circom-produced R1CS,编码为PlonK-like PIL
  • 4)FRI (batched) polynomial commitment and opening

3.1 recursion pipeline 代码审计

根据Verification dragonfruit文档,对zkevm-proverjs的v0.8.0.0-rc.2-forkid.2版本进行build。检查了所有circom文件,是否与该文档中所描述的recursion pipeline已知。此外,审计了最终的fflonk verifier Solidity代码。

3.1.1 轻微漏洞:实际build与文档不匹配

zkevm-proverjs的v0.8.0.0-rc.2-forkid.2版本所生成的final.fflonk.verifier.sol文件,采用是snarkjscommit之前的一个已过期的模板。该过期模板未正确计算verifier challenges(未包含preprocessed多项式,且未保持连续transcript state)。此外,https://github.com/0xPolygonHermez/zkevm-proverjs/blob/v0.8.0.0-rc.2-forkid.2/README.md,该README文档内信息也是过期的。

建议:

  • 1)应双向检查所发布的zkevm-proverjs release版本使用的是更新后的模板,否则,所生成的fflonk verifier合约,可能有Fiat-Shamir vulnerabilities。
  • 2)使用Felicia所提供的更新文档:Verification dragonfruit

回复:

  • Polygon zkEVM团队确认其release build pipeline中使用了正确的版本。

3.1.2 轻微漏洞:batch number比较逻辑溢出

在recursive2 circuit中,使用mux来选择是将hardcoded root,还是将public input root,传送至subverifier circuits中。在recursivef circuit中,使用mux来选择2个hardcoded roots中哪个传入subverifier circuits中。
这2个mux都采用如下比较形式作为输入:

component test = IsZero();
test.in <== oldBatchNum - newBatchNum -1;
....
mux.s <== test.out;

由于bn128 scalar field 大于 goldilocks field,因此在以上field运算中,存在溢出的可能。这将影响基于goldilocks域的比较逻辑:

  • p p p为larger bn128 scalar域的order, q q q为goldilocks域的order。注意有 p > q p>q p>q,因bn128域远大于goldilocks域。定义整数 a , b a,b a,b,有 a q + b ≡ b ( m o d    q ) aq+b\equiv b(\mod q) aq+bb(modq),但 a ⋅ q + b ≠ b a\cdot q +b\neq b aq+b=b。若oldBatchNume为 b − 1 b-1 b1,且newBatchNum为 a ⋅ q + b a\cdot q +b aq+b,则以上比较将返回true,尽管这2个batch是不相邻的。Prover可让Verifier信服:其have done a ⋅ q + 1 a \cdot q + 1 aq+1 iterations of work by using a valid final proof of an execution from b − 1 b − 1 b1 to b b b

回复:

  • Polygon zkEVM团队,其在final.verifier.circom中,会将oldBatchNum和newBatchNum分解为63 bits。因为 2 63 < q 2^{63}<q 263<q q q q为goldilocks域order),这样该比较逻辑不会出现溢出问题。

3.1.3 信息提示类:on-curve checks拒绝point-at-infinity的微小完备性问题

bn128曲线上的有效点,要么满足曲线方程式,要么为无穷远点。在EIP-196:预编译合约中,point-at-infinity编码为 ( 0 , 0 ) (0,0) (0,0)https://github.com/iden3/snarkjs/blob/782894ab72b09cfad4dd8b517599d5e7b2340468/templates/verifier_fflonk.sol.ejs#L216中的checkPointBelongsToBN128Curve函数,若该点满足曲线方程式,则返回true,其拒绝point-at-infinity。当某prover message为point-at-infinity,这存在有效性问题。

建议:

  • 在on-curve check中增加point-at-infinity检查。

回复:

  • Polygon zkEVM团队倾向于避免在on-curve check中增加point-at-infinity检查。由于协议中的随机blinding factors,以及随机verifier challenges,对于honest prover来说,出现该完备性问题的概率可忽略。

3.2 对PIL的STARK prover和verifier 代码审计

审计了根据parsed PIL对象,生成starkinfo对象,以相应的STARK prover和verifier实现。验证了STARK Prover遵循了所审计的eSTARK协议设计,特别地,其实现了新添加的lookup argument、multiset equality argument、connection argument。

3.2.1 细微漏洞:verifier challenges中误用Poseidon哈希。

具体见上面的“2.1.4 轻微漏洞:在Verifier challenges中误用Poseidon哈希,导致unexploitable length-extension weakness”。具体见https://github.com/0xPolygonHermez/pil-stark/blob/a934b3e3a2148f506fbd265f4d3333f36b913c15/src/transcript.js#L16中的第16-20行。建议也同上。

3.2.2 优化建议:在FRI多项式中,没必要包含所有committed多项式

当Prover计算FRI多项式时,具体见https://github.com/0xPolygonHermez/pil-stark/blob/a934b3e3a2148f506fbd265f4d3333f36b913c15/src/starkinfo_fri_prover.js#L12中第12-19行,该线性组合内包含了所有committed多项式。约束中已包含的所有committed多项式,将再次包含在该线性组合中,以证明其evaluation的正确性,以证实该committed多项式的degree bound。因此,添加所有committed多项式到该线性组合内的唯一好处为:

  • 对不包含在任意约束中的多项式做degree bound检查。

检查:

  • 根据线性组合计算FRI多项式时,可移除committed多项式。若因为某些原因,某committed多项式不包含在任何约束中,则需要将其添加到该线性组合内。符合这样条件的committed多项式很少。所有在约束内的committed多项式,无需再次包含在计算FRI多项式的线性组合内。

3.2.3 优化建议:verifier中无需对vanishing多项式进行evaluate

Verifier对 G G G的vanishing多项式在 g ⋅ z g\cdot z gz点进行evaluate,其中 g g g G G G的generator, z z z为verifier evaluation challenge。但是,在验证时,无需做该evaluation。具体见https://github.com/0xPolygonHermez/pil-stark/blob/a934b3e3a2148f506fbd265f4d3333f36b913c15/src/stark_verify.js#L70第70行。

建议:

  • 移除该evaluation。

附录:Polygon Hermez 2.0 zkEVM系列博客

  • 18
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值