# SHPLONK
在Plonk协议中,多项式承诺是非常重要的一个环节,协议中的多项式承诺实现了多个多项式在两个点上的open。但是在实际的应用场景下,有可能会出现需要多个多项式在多个不同点处open的场景,如果能通过改进多项式承诺协议来使得plonk支持多个多项式在不同的子集点处的open。
若$z \in S$,那么 $Z_S(x) = \prod_{z \in S} (X-z)$。
假设有一个数据集$T = \{z_1, z_2, ..., z_t\}$,并且它的子集$S_1,S_2,...,S_k \subset T$。如果有k个多项式$f_1(x), f_2(x),...,f_k(x)$,它们的承诺分别为$cm_1, cm_2,...,cm_k$,要分别在$S_1,S_2,...,S_k $上open。
首先若要使用KZG10对一个多项式做验证的话,那么
* prover计算多项式
$$
h(x) = \frac{f_i(x) - r_i(x)}{Z_{S_i}(x)}
$$
其中$r_i(x)$ 是一个$|s_i|$ 阶的多项式,且满足再$f_i(x) = r_i(x), x \in S_i$。
再使用srs参数计算证明$W =[h(x)]_1 = g^{h(x)}$,发送给verifier。
* Verifier 拿到证明W后进行验证,这里需要两次pairing运算。
$$
e(cm_i-[r_i(x)]_1, g_2) = e(W,g_2^{Z_{S_i}(x)})
$$
如果要一次性得对这k个多项式进行验证,只需要引入一个随机数
* verifier 生成一个随机数$\gamma$,并发送给prover
* prover 拿着随机数将k组多项式的证明计算
$$
h_i(x) = \frac{f_i(x) - r_i(x)}{Z_{S_i}(x)}
$$
再使用srs参数计算证明$W_i =[h(x)_i]_1 = g^{h_i(x)}$,发送给verifier。
* verifier拿到证明W后进行验证
$$
\prod_{i \in [k]} e(\gamma^{i-1} (cm_i-[r_i(x)]_1), g_2) = \prod_{i \in [k]}e(W_i,g_2^{Z_{S_i}(x)})
$$
这个合并尚还不能降低计算量,需要2k次pairing运算。SHPlonk 中在验证步骤做了一个优化
* 首先verifier先计算一组
$$
Z_i = g_2^{Z_{T/S_i}(x)},i \in [k]
$$
其中$Z_{T/S_i}(x) = \frac{Z_T(x)}{Z_{S_i(x)}}$
* prover 拿着随机数将k组多项式的证明计算合并起来
$$
h(x) = \sum_{i \in [k]}\gamma^{i-1} \cdot \frac{f_i(x) - r_i(x)}{Z_{S_i}(x)} \\ = \sum_{i \in [k]}\gamma^{i-1} \cdot \frac{(f_i(x) - r_i(x)) \cdot Z_{T/S_i}(x)}{Z_{T}(x)} \\ = \frac{\sum_{i \in [k]}\gamma^{i-1} \cdot(f_i(x) - r_i(x)) \cdot Z_{T/S_i}(x)}{Z_{T}(x)}
$$
再使用srs参数计算证明$W =[h(x)]_1 = g^{h(x)}$,发送给verifier。
* 那么验证步骤就被改造为
$$
\prod_{i \in [k]} e(\gamma^{i-1} (cm_i-[r_i(x)]_1), Z_i) =e(W,g_2^{Z_T(x)})
$$
这样pairing运算的数量就降低到了k+1次。
这里右侧已经不能合并了,未来进一步优化计算量
* 首先令
$$
f_Z(X) = \sum_{i \in [k]}\gamma^{i-1} \cdot Z_{T/S_i}(X)\cdot(f_i(X) - r_i(X))
$$
那么
$$
h(X) = \frac{f_Z(X)}{Z_T(X)}
$$
再使用srs参数计算证明$W =[h(x)]_1 = g^{h(x)}$,发送给verifier。
* verifier 产生一个随机数$z$,并发送给prover。
* 再继续变换多项式的形式
$$
L(x) = f_Z(X) - h(X)\cdot Z_T(z)
$$
其中
$$
f_Z(X) = \sum_{i \in [k]}\gamma^{i-1} \cdot Z_{T/S_i}(z)\cdot(f_i(X) - r_i(z))
$$
显然$L(z) = 0$。所以L(x)必然能被$(x-z)$整除。
所以prover可以继续构造证明
$$
h'(x) = \frac{L(x)}{x-z}
$$
再使用srs参数计算证明$W' =[h'(x)]_1 = g^{h'(x)}$,发送给verifier。这里就相当于把再S个点处opening的问题转换到了在一个点open的问题上了。
* Verifier 首先去计算
$$
F = [f_Z(x)]_1=\sum_{i \in [k]}\gamma^{i-1} \cdot Z_{T/S_i(z)}(cm_i - [r_i(z)]_1) - Z_T(z)\cdot W
$$
再继续验证
$$
e(F,[1]_2) = e(W',[x-z]_2)
$$
只剩下两个pairing 和k+1次的椭圆曲线上的乘法运算,这远远小于k+1次的计算消耗。
原本的方案中,右侧的pairing已经不能合并了,所以这里优化的关键就是将$Z_{T/S}(x)$ 和 $Z_{Y}(x)$ 的计算变换成了在一个已知点处的计算,即$Z_{T/S}(z)$ 和 $Z_{Y}(z)$,因为$Z_{T/S}(x)$ 和 $Z_{Y}(x)$ 多项式是公开的,z是公开的,那么计算就可以只能在有限域上进行了,而不必管srs,因此原本pairing运算中在g2上算的这两项都可以直接乘到g1上了,这样也就合并了原来的多个pairing。
fflonk也是一种新的优化方案,它在SHPlonk的基础之上设计的优化方案,它继续沿用了SHPlonk的验证步骤,并结合了一种新的类似FFT运算的方法。fflonk的验证步骤中仅需要3次椭圆曲线上的运算,及2次pairing,与SHPlonk相比,又进一步优化了计算步骤。