深入了解Lasso+Jolt

1. 引言

前序博客有:

相关论文见:

相应的开源代码实现见:

本文总体结构为:

  • 何为lookup arguments?
  • 何为Lasso/Jolt?
  • Lasso细节
  • Jolt细节
  • 如何将Lasso看成是工具?
    • 以及,lookup argument在zkVM之外的应用场景?

2. 何为lookup arguments?

lookup arguments可分为:

  • 1)Unindexed lookup argument:
    • 为subset relation proof,即,batch set-membership proof—— a a a为table t t t的某subset。
  • 2)Indexed lookup argument:【Lasso和Jolt使用的是indexed lookup argument】
    • 为对只读内存的读取。可将 t t t看成是内存, a i = t [ b i ] a_i=t[b_i] ai=t[bi]表示读取 b i b_i bi内存单元中的值。

以range check为例,lookup argument是指:

  • 1)令 t = ( 0 , 1 , 2 , 3 , ⋯   , 2 128 − 1 ) t=(0,1,2,3,\cdots,2^{128}-1) t=(0,1,2,3,,21281)为具有 N N N个table元素的向量(即 t t t为pre-determined table)。
  • 2)令 a ∈ F m a\in\mathbf{F}^m aFm为一组应包含在上述table的值列表。
  • 3)Verifier V V V已知: a a a的承诺值 c m a cm_a cma
  • 4)Prover P P P声称: a a a中所有元素均在table t t t中。
    即Prover P P P声称其知道 c m a cm_a cma的opening a a a,使得:
    • 对于每个 i = 0 , ⋯   , m − 1 i=0,\cdots, m-1 i=0,,m1,存在某index b i ∈ { 0 , 1 , ⋯   , N − 1 } b_i\in\{0,1,\cdots, N-1\} bi{ 0,1,,N1},使得 a i = t [ b i ] a_i=t[b_i] ai=t[bi]
  • 5)通常将这种lookup argument称为unindexed lookup argument。

而indexed lookup argument是指待证明元素中还附加了索引值,indexed lookup argument定义为:【Verifier知道table t t t的succinct描述。】

  • 1)令 t ∈ F n t\in\mathbf{F}^n tFn为具有 N N N个table元素的向量(即 t t t为pre-determined table)。
  • 2)Prover P P P对向量 ( ( a 1 , b 1 ) , ⋯   , ( a m , b m ) ) ((a_1,b_1),\cdots,(a_m,b_m)) ((a1,b1),,(am,bm))进行承诺。
  • 3)Prover P P P声称,对于 i = 1 , ⋯   , m i=1,\cdots,m i=1,,m,有 a i = t [ b i ] a_i=t[b_i] ai=t[bi]。【即 a i a_i ai为value, b i b_i bi对应为table t t t的索引号,Prover P P P声称 a a a中所有元素均存在于 t t t中相应的index。】

3. 何为Lasso/Jolt?

Lasso:为一组(indexed)lookup argument:

  • Lasso Prover P P P的速度要比之前的方案快一个量级。
    • Prover P P P的关键瓶颈在于:承诺开销。
  • Lasso Prover P P P对更少的field elements进行commit,且所有这些待承诺的field elements都是small的。
  • No commitment to t t t needed for many tables。【对于(Jolt中需要的)大量的lookup tables,无需honest party来对table进行 commit和预处理。基于Lasso的Verifier可自行处理巨大table(仅需约50/100/200个field运算),而不是接收table的承诺值。】
  • 支持巨大tables(可分解,或LDE-structured):
    • Prover P P P的承诺开销为: O ( c ( m + N 1 / c ) ) O(c(m+N^{1/c})) O(c(m+N1/c))个field elements。
    • 将table分解主要有2方面的Prover开销,通常取 c = 6 c=6 c=6来对这2方面开销进行平衡:
      • 仅依赖于table size的开销
      • 仅依赖于lookup次数的开销

Jolt:为新的zkVM技术:

  • Jolt Prover P P P的承诺开销要比之前的方案低得多。
  • 通过对单个指令的整个evaluation table的一次lookup,来实现Primitive instruction。

4. Lasso细节

4.1 Lasso开销细节

对size为 N N N、具有参数 c c c的table,做 m m m次indexed lookup:

  • Lasso Prover P P P开销为:对 3 c m + c N 1 / c 3cm+cN^{1/c} 3cm+cN1/c个field elements进行commit。
    • 所有field elements都是small的,即在set { 0 , 1 , ⋯   , m } \{0,1,\cdots,m\} { 0,1,,m}中:
      • 基于MSM的多项式承诺方案,Lasso Prover P P P对每个(small)committed field element,仅需要约做1次group 运算。
        目前基于MSM的多项式承诺方案有:
        • KZG-based多项式承诺方案
        • IPA/Bulletproofs多项式承诺方案
        • Hyrax多项式承诺方案
        • Dory多项式承诺方案
  • Lasso Verifier V V V开销为:
    • O ( log ⁡ m ) O(\log m) O(logm)次field运算 和 hash evaluations(from Fiat-Shamir)。
    • + 1个evaluation proof for a committed polynomial of size N 1 / c N^{1/c} N1/c
    • 通过composition/recursion,可将以上足够低的 Lasso Verifier V V V开销 进一步reduce。

c = 1 c=1 c=1时,对应的为Lasso的特例情况——Basic-Lasso:

  • Basic-Lasso Prover P P P m + N m+N m+N个field elements进行commit。
  • m + N m+N m+N个field elements中,有很多为0值。在MSM-based多项式承诺方案中,对0值进行commit的开销也为0,即“free”。
  • m + N m+N m+N个field elements中,最多有 2 m 2m 2m个为非零值:
    • 若每次读取的为不同的table cell,则有 m m m个field elements为1,其它的均为0。

4.2 将Lasso用于巨型table: c > 1 c>1 c>1

实际上,大多数大型lookup table都是可分解的

  • 可将对大型size为 N N N的table的一次lookup,分解为,对size为 N 1 / c N^{1/c} N1/c的table的约 c c c次lookup,然后"整理(collating)"这 c c c个lookup的结果 :
    • Lasso使用sum-check protocol来"整理"这 c c c个lookup的结果。因此对Lasso Prover P P P来说,没有额外的承诺开销。

可将Lasso看成是 c > 1 c>1 c>1,将对单个大型、可分解table的lookup,reduce为,对多个small tables的 c c c个lookup:

  • 对small tables,可使用任意lookup argument。
    • 对于small tables,Lasso中使用Basic-Lasso lookup argument方案。
  • 附加说明:small-table lookup argument必须是indexed。
  • 目前已知的方案来将unindexed lookup argument 转换为 indexed lookup argument。
    • 但是,这些已知方案要么无法保留table entries的“smallness”,要么无法保留big table的可分解性——原因在于,这些方案将indices和values "pack"为了单个field element。

【proof size不取决于不同table的数量,也不取决于small table的size。Verifier需在某random point上 evaluate每个small table的 multi-linear extension polynomial,small tables数量的增加会引起Verifier time的增加,但这些都是field运算,相比于其它密码学操作来说,这不会成为Verifier的瓶颈。
Jolt中有约45种不同的subtables。

4.3 背景知识:Grand Product Arguments

所有已知的lookup argument都采用了grand product argument

  • grand product argument是一种SNARK方案,用于证明 n n n个committed values的乘积。
  • 当今流行的grand product argument,其Prover P P P需额外再对 n n n个值(partial products)进行commit。
  • 这是没必要的。
  • T13论文中:给出了GKR protocol的优化版本(所谓GKR protocol,为sum-check-based interactive proof for circuit evaluation):【对类似于binary tree of multiplication gates的电路进行了优化。】
    • Prover P P P无承诺开销。
    • Prover P P P做线性次数的field运算。
    • Proof size/Verifier V V V time为 O ( log ⁡ ( n ) 2 ) O(\log(n)^2) O(log(n)2)次field运算(以及hash evaluations from Fiat-Shamir):
      • 远少于FRI的Proof size/Verifier V V V time。
      • [Lee, Setty 2019]中将Verifier V V V开销进一步reduce为约 O ( log ⁡ ( n ) ) O(\log(n)) O(log(n)),只需增加Prover P P P的一点点承诺开销。

4.4 Basic-Lasso关键点

  • 对于很多现有的lookup arguments,若swap out the invoked grand product argument for T13,则Prover P P P仅需对small field elements进行commit。
  • Lasso/Jolt需要使用indexed lookup argument,来将small-table lookup results “collating” into big-table results。
  • 技术卖点:当前社区仍未充分利用sum-check的潜力来避免Prover P P P的开销。
  • 关于Basic-Lasso的工作原理,可参看:

5. Jolt细节

当前VM execution的前端(front-end):

  • Prover P P P声称运行某computer program for m m m steps:
    • 该程序以某VM的汇编语言来编写。
    • 流行的VM面向目标有:RISC-V、Ethereum Virtual Machine(EVM)。
  • 当前,前端为每个computation step生成一个电路:
    • 步骤1:指出在该step应执行哪个指令。
    • 步骤2:执行该指令。
  • 而Lasso将上面的 步骤2 替换为 a single lookup:
    • 对于每个指令,该table中存储了该指令的整个evaluation table
    • 若指令 f f f有2个64-bit输入,则对于每个64-bit input pair ( x , y ) (x,y) (x,y),lookup table会存储所有的 f ( x , y ) f(x,y) f(x,y)
      • 该lookup table size为 2 128 2^{128} 2128
      • Jolt中展示了,所有的RISC-V指令都是可分解的。

Jolt概览图为:
在这里插入图片描述
Jolt有望实现Barry Whitehat的Lookup Singularity愿景:

  • 具有易审计、简单化、可扩展性等优势
  • 性能优势
  • 本质不同的构建zkVM的方式:
    • 与人们现有在做的事情有很多相似之处。
    • 人们愿景将类似bitwise-AND这样的计算函数转换为 对small tables的多次lookup,并将结果合并。
    • Jolt的关键不同之处在于:
      • a)新的small-table lookup argument具有快得多的Jolt Prover P P P
      • b)新的small-table lookup argument为天然indexed。
      • c)Jolt Prover P P P具有快得多的collating技术:
        • 可对small-table lookup results进行“Free” multiply和add。
    • Jolt的这些不同之处,使得可借助lookup 来实现VM emulation中的almost everything

5.1 Jolt分解示例1——Bitwise-AND

对于有2个64-bit输入 x , y x,y x,y的bitwise-AND原酸,其分解思路为:

  • x , y x,y x,y分解为 c = 8 c=8 c=8个chunks,每个chunk有8 bit。
  • 计算每个chunk的bitwise-AND
  • 将各chunk结果拼接起来,即输出为:
    ∑ i = 1 8 8 i − 1 ⋅ bitwiseAND ( x i , y i ) \sum_{i=1}^{8}8^{i-1}\cdot \text{bitwiseAND}(x_i,y_i) i=188i1bitwiseAND(xi,yi)

为避免需要honest-party来对sub-table进行commit:

  • bitwiseAND ( x i , y i ) = ∑ j = 1 8 2 j − 1 ⋅ x j ⋅ y j \text{bitwiseAND}(x_i,y_i)=\sum_{j=1}^{8}2^{j-1}\cdot x_j\cdot y_j bitwiseAND(xi,yi)=j=182j1xjyj为multilinear多项式,可 以少于25个field运算来evaluate。
  • Lasso Verifier V V V需要知道该sub-table,转为,只需要知道该多项式的一个evaluation。

5.2 Jolt分解示例2——RISC-V Addition

对2个64-bit number x , y x,y x,y 求和,RISC-V规定其相加正确,并忽略任意“overflow bit”。

Jolt(通过对ancillary R1CS添加一个约束来)在有限域内计算 z = x + y z=x+y z=x+y,然后使用lookup来标识相应的overflow bit,若有overflow bit,则据此调整相应的结果。

  • Jolt Prover P P P,对field element z = x + y z=x+y z=x+y的“limb-decomposition” ( b 1 , ⋯   , b c ) (b_1,\cdots,b_c) (b1,,bc)进行commit。
  • M = 2 64 / c M=2^{64/c} M=264/c为每个limb的最大值。
  • 向R1CS添加一个约束,以确认:
    • 步骤1: z = ∑ j = 1 c M j − 1 ⋅ b j z=\sum_{j=1}^{c}M^{j-1}\cdot b_j z=j=1cMj1bj
    • 步骤2:并对每个 b j b_j bj通过lookup into 存储了 { 0 , ⋯   , M − 1 } \{0,\cdots,M-1\} { 0,,M1}的subtable,来做range check。
  • 通过以上约束的步骤1和步骤2,就可确保 b 1 , ⋯   , b j b_1,\cdots,b_j b1,,bj确实为 z z z的规定的limb-decomposition。
  • 为识别overflow bit,仅需要做a lookup at index b c b_c bc, into a table whose i i i’th entry spits out the relevant high-order bit of i i i

5.3 Jolt分解示例2——LESS THAN UNSIGNED

对2个64-bit输入 x , y x,y x,y做less than运算:

  • x , y x,y x,y分解为 c = 8 c=8 c=8个chunks,每个chunk有8 bit。
  • 计算每个chunk的LESS-THAN(LT) 和 EQUALITY(EQ)
  • 输出为: ∑ i = 1 8 2 i − 1 ⋅ LT ( x i , y i ) ∏ j = i + 1 8 EQ ( x j , y j ) \sum_{i=1}^{8}2^{i-1}\cdot \text{LT}(x_i,y_i)\prod_{j=i+1}^{8}\text{EQ}(x_j,y_j) i=182i1LT(xi,yi)j=i+18EQ(xj,yj)

为避免对2个sub-table进行commit:

  • EQ ( x j , y j ) = ∏ k = 1 8 ( x j , k y j , k + ( 1 − x j , k ) ( 1 − y j , k ) ) \text{EQ}(x_j,y_j)=\prod_{k=1}^{8}(x_{j,k}y_{j,k}+(1-x_{j,k})(1-y_{j,k})) EQ(xj,yj)=k=18(xj,kyj,k+(1xj,k)(1yj,k))
  • LT ( x i , y i ) = ∑ k = 1 8 ( 1 − x i ) y i ∏ z = k 8 ( x i , k y i , k + ( 1 − x i , k ) ( 1 − y i , k ) ) \text{LT}(x_i,y_i)=\sum_{k=1}^{8}(1-x_i)y_i\prod_{z=k}^{8}(x_{i,k}y_{i,k}+(1-x_{i,k})(1-y_{i,k})) LT(xi,yi)=k=18(1xi)yiz=k8(xi,kyi,k+(1xi,k)(1yi,k))
  • 这些均为multilinear多项式,可 以少于50个filed运算来evaluate。

6. 如何将Lasso看成是工具?以及,lookup argument在zkVM之外的应用场景?

6.1 Lasso as a tool的直觉

  • Lasso支持对field element的bit-decompositions的简单运算,无需Lasso Prover P P P对各个bit进行commit。
  • sub-tables具有quickly-evaluable multilinear extension,若每个sub-table对应a simple function on the (bits of) the table indices:
    • 从而可确保无需honest party在预处理时对这些sub-tables进行commit。
  • 对2个field elements取值为 { 0 , 1 , ⋯   , 2 64 − 1 } \{0,1,\cdots,2^{64}-1\} { 0,1,,2641}的bitwiseAND运算,相比于Plonk中每个加法或乘法门的开销,Lasso Prover 开销更低。
  • 注意:Lookup arguments为规模经济。适于do many lookups into one table(即对同一函数的多次调用)。

6.2 将indexed lookup arguments看成是repeated function evaluation的SNARKs方案

之前有很多关于“SNARKs for repeated function evaluation”的研究:

  • 基于很多不同输入 x 1 , ⋯   , x m x_1,\cdots,x_m x1,,xm,计算同一函数 f f f
  • 可将其看成是“polynomial” amount of data parallelism:
    • 若函数 f f f的输入长度为 n n n,则不同输入的数量为 m = poly ( n ) m=\text{poly}(n) m=poly(n)
  • 仍要求Prover P P P evaluate f f f in a very specific way:
    • Executing a specific circuit to compute f f f

看待lookup arguments新视角:

  • 将lookup table看成是存储了某函数 f f f的所有evaluations
  • lookup argument则为a SNARK for highly repeated evaluation of f f f
    • 令Prover证明,committed vector ( ( a 1 , f ( a 1 ) ) , ⋯   , ( a m , f ( a m ) ) ) ((a_1,f(a_1)),\cdots,(a_m,f(a_m))) ((a1,f(a1)),,(am,f(am))),中包含了对不同输入 a 1 , ⋯   , a m a_1,\cdots,a_m a1,,am的正确 f f f evaluations。
  • Lasso Prover P P P的开销为 O ( c ( m + N 1 / c ) ) O(c(m+N^{1/c})) O(c(m+N1/c)),当lookup次数 m m m 不比 table size N N N,小太多时,Lasso Prover P P P是高效的:
    • 即运行 f f f的次数 应为 exponential in the input size of f f f

7. 小结

  • Lasso适于对同一函数evaluate很多次的场景。
  • zkVM只是Lasso的应用场景之一:
    • 根据定义,VM抽象表示的是对primitive指令的重复执行的计算。
    • 实现VM抽象通常具有大量的性能开销。
  • 未来感兴趣的方向:
    • 隔离计算中重复结构的其它更好方式
    • 示例工作有:
      • Bit-slicing
      • evaluate 哈希函数或block cipher(如SHA/AES),可构建具有64个不同输入的Boolean circuit C C C来计算:
        • 将每个输入的第一个bit pack进a single field element,将每个输入的第二个bit pack进a single field element,以此类推。
        • 将circuit C C C中的每个AND 门,替换为bitwiseAND;将circuit C C C中的每个OR 门,替换为bitwiseOR等等。
        • circuit C C C中每个gate的output为SHA/AES所有64 evaluations的one bit。
        • 对circuit C C C运用Lasso。

参考资料

[1] Justin Thaler 2023年8月在zkStudyClub视频分享 zkStudyClub - Lasso/Jolt (Justin Thaler, Georgetown University/a16z)
相应slide见:zkStudyClub - Lasso/Jolt (Justin Thaler, GWU/a16z)

Justin Thaler系列博客

lookup系列博客

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/132516398