零知识证明 - Groth16计算详解

Groth16算法是zkSNARK的典型算法,目前在ZCash,Filecoin,Coda等项目中使用。本文从计算量的角度详细分析Groth16计算。Groth16计算分成三个部分:Setup针对电路生成Pk/Vk(证明/验证密钥),Prove针对电路,在给定witness/statement的情况下生成证明,Verify通过Vk验证证明是否正确。

所有的术语和数学符号和Groth16论文保持一致(On the Size of Pairing-based Non-interactive Arguments,具体的计算在17/18页):

https://eprint.iacr.org/2016/260.pdf

对Groth16算法的理解可查看:
Groth16算法介绍

1. 电路描述

所有的电路描述有个专业的术语:Relation(变量和变量的关系描述)。描述Relation的语言很多:R1CS,QAP,tinyRAM,bacs等等。目前开发,电路一般采用R1CS语言描述。R1CS相对来说,非常直观。A*B=C(A/B/C分别是输入变量的线性组合)。但是,要应用Groth16算法,需要将R1CS描述的电路,转化为QAP描述。两种电路描述语言的转化,称为Reduction。

1.1 R1CS描述

给定M’个变量(第一个变量约定为恒量1),以及N’个约束,所有的R1CS描述可以表示如下:

零知识证明 - Groth16计算详解_第1张图片

每一行是一个约束。举例,第一行的约束表示的是:
( ∑ i = 0 M ′ a i u 0 i ) ∗ ( ∑ i = 0 M ′ a i v 0 i ) = ( ∑ i = 0 M ′ a i w 0 i ) (\sum_{i=0}^{M'} a_i u_{0i})*(\sum_{i=0}^{M'} a_i v_{0i}) = (\sum_{i=0}^{M'} a_i w_{0i}) (i=0Maiu0i)(i=0Maiv0i)=(i=0Maiw0i)

1.2 QAP转化
介绍具体的转化之前,先介绍一个简单的术语,拉格朗日插值以及拉格朗日basis。

给定一系列的x和y的对应关系,通过拉格朗日插值的方式,可以确定多项式:
p ( x ) = y 0 l 0 ( x ) + y 1 l 1 ( x ) + . . . + y n l n ( x ) p(x) = y_0l_0(x) + y_1l_1(x) + ... + y_nl_n(x) p(x)=y0l0(x)+y1l1(x)+...+ynln(x)

其中 l 0 ( x ) , l 1 ( x ) , . . . l n ( x ) l_0(x), l_1(x), ... l_n(x) l0(x),l1(x),...ln(x)就称为拉格朗日basis,计算公式如下:

l j ( x ) : = ∏ i = 0 , i ≠ j n x − x i x j − x i = ( x − x 0 x j − x 0 ) ( x − x 1 x j − x 1 ) . . . ( x − x j − 1 x j − x j − 1 ) ( x − x j + 1 x j − x j + 1 ) . . . ( x − x n − 1 x j − x n − 1 ) ( x − x n x j − x n ) l_j(x) := \prod_{i=0, i\neq j}^n \frac{x-x_i}{x_j-x_i} = (\frac{x-x_0}{x_j-x_0}) (\frac{x-x_1}{x_j-x_1})...(\frac{x-x_{j-1}}{x_j-x_{j-1}}) (\frac{x-x_{j+1}}{x_j-x_{j+1}})...(\frac{x-x_{n-1}}{x_j-x_{n-1}}) (\frac{x-x_{n}}{x_j-x_{n}}) lj(x):=i=0,i=jnxjxixxi=(xjx0xx0)(xjx1xx1)...(xjxj1xxj1)(xjxj+1xxj+1)...(xjxn1xxn1)(xjxnxxn)

简单的说,在给定一系列的x/y的对应关系后,可以通过拉格朗日插值表示成多项式。在R1CS的表达方式下,U/V/W多项式很自然用拉格朗日basis表示,并不是以多项式的系数表示。
在R1CS转化为QAP之前,必须对现有约束进行增强,增加 a i ∗ 0 = 0 a_i*0=0 ai0=0的约束。增加这些约束的原因是为了保证转化后的QAP的各个多项式不线性依赖。

零知识证明 - Groth16计算详解_第2张图片

1.3 domain选择
针对每个变量,已经知道N个y值。如何选择这些y值,对应的x值?这个就是domain的选择。选择domain,主要考虑两个计算性能:1/ 拉格朗日插值 2/FFT和iFFT。libfqfft的源码提供了几种domain:

  1. Basic Radix-2 2)Extended Radix-2 3) Step Radix-2 4) Arithmetic Sequence 5) Geometric Sequence

选择哪一种domain和输入个数(M)有关。为了配合特定domain的计算,domain的阶(M)会稍稍变大。

确定了domain,也就确定了domain上的一组元素s:

零知识证明 - Groth16计算详解_第3张图片

2. Setup计算
随机生成 α , β , γ , δ , x ∈ F r \alpha, \beta, \gamma, \delta, x \in F_r α,β,γ,δ,xFr。注意这里的 x x x和上一节中的x含义不同,不要混淆。

2.1 拉格朗日插值

已知 x x x的情况下,通过1.2的公式,先通过domain计算拉格朗日basis。再乘上系数,可以获得 u i ( x ) , v i ( x ) , w i ( x ) u_i(x), v_i(x), w_i(x) ui(x),vi(x),wi(x)。这些多项式的阶是M。

2.2 计算 x i x^i xi t ( x ) t(x) t(x)

x i x^i xi的计算相对简单,注意幂次计算都是在 F r F_r Fr的计算。在domain确定后,多项式t也确定,从而可以计算出 t ( x ) t(x) t(x)

2.3 生成Pk/Vk

按照如下的公式,计算Pk/Vk。 σ 1 \sigma_1 σ1是G1上的点, σ 2 \sigma_2 σ2是G2上的点。

在这里插入图片描述

其中,
( α , { β u i ( x ) + α v i ( x ) + w i ( x ) γ } i = 0 ℓ ) 1 (\alpha, \{\cfrac{\beta u_i(x)+\alpha v_i(x) + w_i(x)}{\gamma}\}_{i=0}^{\ell})_1 (α,{γβui(x)+αvi(x)+wi(x)}i=0)1
( β , γ , δ ) 2 (\beta, \gamma, \delta)_2 (β,γ,δ)2
是Vk。其他部分是Pk。可以看出,Vk的大小取决于公共输入的变量个数,相对来说数量比较小。Pk的数据量大小和所有的变量个数相关。计算过程,主要由scalarMul组成。

3. Prove计算
在domain选择后,U*V=W,可以变换为如下的多项式方程:
零知识证明 - Groth16计算详解_第4张图片
3.1 u i ( X ) , v i ( X ) , w i ( X ) u_i(X), v_i(X), w_i(X) ui(X),vi(X),wi(X)多项式系数
通过iFFT,在已知domain上元素s和值对应关系,可以计算出多项式系数。

3.2 u i ( X ) , v i ( X ) , w i ( X ) u_i(X), v_i(X), w_i(X) ui(X),vi(X),wi(X)在coset的值
已知多项式系数,通过FFT,计算出多项式在coset的值。注意,元素s以及对应的coset是特殊设计的,便于FFT/iFFT的计算,和domain的选择有关系。

3.3 h(X)在coset的值
h(X)多项式的计算公式如下:
h ( X ) = ∑ i = 0 m a i u i ( X ) ⋅ ∑ i = 0 m a i v i ( X ) − ∑ i = 0 m a i w i ( X ) t ( X ) h(X) = \cfrac{\sum_{i=0}^m a_iu_i(X) \cdot \sum_{i=0}^m a_iv_i(X) - \sum_{i=0}^m {a_iw_i(X)}}{ t(X)} h(X)=t(X)i=0maiui(X)i=0maivi(X)i=0maiwi(X)
代入3.1/3.2,直接计算出h(X)在coset的值。

3.4 计算h(X)多项式系数
通过iFFT,获取h(X)的多项式系数,阶为N-2。

【2020-02-17 更新】以上的计算过程是逻辑的计算过程,bellman的计算过程不同。bellman的计算不是从Variable的角度来看,而是从R1CS的角度看的。在给定输入的情况下, a i ∗ u i ( X ) a_i * u_i(X) aiui(X) a i ∗ u i ( X ) a_i * u_i(X) aiui(X)以及 a i ∗ u i ( X ) a_i * u_i(X) aiui(X)的值都可以获得。也就是说,每一个R1CS的 U i ( x ) , V i ( x ) , W i ( x ) U_i(x), V_i(x),W_i(x) Ui(x),Vi(x)Wi(x)都可以算出。针对每个R1CS,只要做一次FFT,就能获得多项式系数。

以上的计算方法,需要针对每个变量都需要做一次FFT,才能获取 u i ( X ) , v i ( X ) 和 w i ( X ) u_i(X), v_i(X)和w_i(X) ui(X),vi(X)wi(X)。也就是说,需要NxM个多项式转变,NxM次的FFT。显然没有bellman的方式好。

当然,在小电路的情况下,这种方法也是有好处。这种方式的好处是,FFT虽多,但是可以提前算存下来。N*M如果是百M的话,可以考虑。

3.5 生成证明
随机选择 r , s ∈ F r r,s \in F_r r,sFr,在已知 u i ( x ) , v i ( x ) , w i ( x ) , h ( x ) u_i(x), v_i(x), w_i(x), h(x) ui(x),vi(x),wi(x),h(x)的情况下,通过如下的公式计算证明A,B,C:
零知识证明 - Groth16计算详解_第5张图片
其中,A需要计算在G1上的点,B需要计算在G1/G2上的点,C需要计算G1上的点。C中的 h ( x ) t ( x ) δ \cfrac{h(x)t(x)}{\delta} δh(x)t(x)计算如下:
h ( x ) t ( x ) δ = ∑ i = 0 N − 2 h i x i t ( x ) δ \cfrac{h(x)t(x)}{\delta} = \sum_{i=0}^{N-2} \cfrac{h_i x^it(x)}{\delta} δh(x)t(x)=i=0N2δhixit(x)
很显然,生成证明的计算量主要由四个Multiexp组成(A-1,B-1,C-2),和变量个数以及约束的个数有关。在一个大型电路中,生成证明的时间比较长(秒级,甚至分钟级)。

4. Verify计算

在已知证明以及Vk的情况下,通过配对(pairing)函数,很容易计算如下的等式是否成立。计算在毫秒级。
在这里插入图片描述

总结:

Groth16算法的主要计算量由两部分组成:FFT/iFFT以及MultiExp。在生成证明时,需要4次iFFT以及三次FFT计算。Setup计算和生成证明时,需要大量的MultiExp。Verify计算量相对较小。

在这里插入图片描述

你可能感兴趣的:(零知识证明)