The following article is from Nervos 中文社区 Author Cyte
Nervos 致力于为下一代加密经济打造基础设施,包含以区块链技术为核心、相互兼容的一组分层协议,通过一层公有链协议保证网络的安全性与去中心化,二层协议提供具有可扩展性的交易和计算服务,以及多个应用层协议衔接商业场景。
在之前的文章中,我们介绍了零知识证明的基础概念以及构造 zkSNARK 的基本思想和方法。从本文开始,我们将逐一介绍目前最热门的 zkSNARK 方案。文章旨在让读者理解这些方案的基本原理。为了方便叙述并容易理解,在叙述方案时,我们会做一些简化处理,重在传达方案的核心思想。
本文介绍的是 Groth16 方案。Groth16 方案,顾名思义,就是 Groth 在 2016 年发表的一篇论文 [Gro16] 中提出的方案。目前为止,Groth16 是在实践中使用最广泛的 zkSNARK (没有之一)。特别一提的,Zcash 目前使用的 zkSNARK 方案就是 Groth16。从性能上,Groth16 的 Verifier 性能是所有 zkSNARK 中最快的,其证明字符串也是最短的。
而 Groth16 的最大缺点就是它需要对每个电路都执行一次可信初始化。
在介绍 Groth16 之前,简单回顾一下 zkSNARK 所要解决的问题。我们称这个问题为“计算验证问题”。
计算验证问题
一句话概括计算验证问题:Verifier 能否在不知道秘密输入的情况下,高效地验证计算结果?
从电路到 R1CS 问题
一个 zkSNARK 就是对上述问题的一个解决方案。使用 zkSNARK,一个证明者,叫做 Prover,可以为计算过程生成一个简短的证明字符串。Verifier 读取这个字符串,就可以判断给定的公开输入和输出是否合法。
Groth16 是众多 zkSNARK 构造方案中的一种。接下来,我们介绍 Groth16 是怎么解决计算验证问题的。
首先,我们重新审视一下 Verifier 的任务:我们只知道电路的前两个输入是 ,我们的目标是要判断是否存在一组合法的秘密输入,使得电路的输出是 。如果我们换个角度看这个问题,它其实可以描述为:给一个电路,上面有些空格可以填数字,有些空格已经填上了数字,请问是否存在一种填法,能够同时满足每个门的逻辑?
从这个新的角度,计算验证问题被转换成了一个类似于数独那样的填数字游戏:有一些空格,一部分已经填上,请你填上另外一些空格,满足一些限制条件。
接下来,我们再把这个填数字游戏变成一个数学问题。这个转换其实就是列方程,用到的是小学时就学过的技巧:如果你想要求出一个数字,就把它设为 。只不过,遵循零知识证明领域的规范,这里我们把没有填的空格命名为变量 ,而把已经知道的空格命名为变量 。如下图所示,我们把值已经公开的空格标记为绿色,待求的空格标记为蓝色:
然后,我们为每一个要满足的条件列一个方程。这里,每个要满足的条件其实就是一个门的逻辑:加法门的输出等于两个输入之和,乘法门的输出等于两个输入之积。于是,原来的填空游戏就变成了一个多元方程组。上述例子转化得到的方程组如下:
最后,我们对这个方程做一些整理,使得它能够写成矩阵和向量的形式,更加整齐和简洁。我们把每个方程都写成 的模式。尽管并不是所有方程中都有乘法,但我们可以给没有乘法的式子乘上一个 。于是方程组变成了下面这个样子:
此时,每个 中都只包含加法,而不包含乘法。确切地说,每个 都是若干变量的相加,有时可能会加上一个常数。更进一步地说,每个 都是所有变量 和常数 的线性组合。于是,设向量 为所有变量以及常数 组成的向量。那么,每个 都是 与另外一个常向量的内积。例如,,这里用 表示内积。于是,每个方程都可以写成 的形式,其中 , 和 是方程组中第 个方程对应的三个常向量。
把所有方程合到一起,就得到了原方程组的矩阵表示
其中 的行向量就是所有的 ,矩阵 和 也类似。这里 表示向量的逐项相乘。这三个矩阵 的值完全取决于电路的结构。
我们把最终得到的这个矩阵向量方程叫做一个 Rank-1 Constraint System (R1CS)。
至于名字中的 "Rank-1" 是怎么来的,如果你感兴趣的话,可以这么理解。每个方程 的等号右侧可以写成 ,其中 就是一个秩为 的矩阵。
总结一下,这一节中我们把计算验证问题转化成了数学问题 R1CS。
在计算验证问题中,Verifier 知道一个电路,拿到公开部分的输入,以及电路的输出,判断它们是否合法。
而在 R1CS 问题中,Verifier 知道三个矩阵 ,并拿到向量 的一个前缀,判断是否存在一个完整的 ,满足 。
从 R1CS 问题到 QAP 问题
在零知识证明领域,R1CS 基本上就是电路的代名词。许多 zkSNARK 把 R1CS 问题作为目标问题。不过,大部分 zkSNARK 不会直接对 R1CS 下手,而是把 R1CS 问题继续转化,得到一个等价的多项式问题,再对这个多项式问题设计证明方案。Groth16 也不例外。不同的 zkSNARK 选择的多项式问题各不相同,Groth16 选择的是一个叫做Quadratic Arithmetic Programming (QAP)的问题。
这一节中介绍一下怎样把 R1CS 问题转化为等价的 QAP 问题。
首先,把矩阵和向量的乘积看做对矩阵的列向量的线性组合,这个线性组合的系数由被乘的向量决定。从这个角度看,R1CS 问题就是:给定三个向量集合 (也就是 的列向量),判断是否存在一个线性组合 (也就是 ),使得 的列向量分别组合起来 (也就是 ),逐项乘积等于 的列向量的组合 (也就是 )。如下图所示
多项式插值
QAP 问题
现在,我们直接把 R1CS 矩阵中的列向量换成它们的多项式插值,得到的结果如下图所示。
已知信息 | 秘密信息 | 满足条件 | 固定信息 | |
为 QAP 问题构造 zkSNARK
QAP 问题就是 Groth16 要用来构造 zkSNARK 的最终问题了。不过,在解释 Groth16 的构造细节之前,我们先准备一些工具。 准备工具
我们假设读者对椭圆曲线群的基本特性和应用有所了解,并采用加法群的记号来描述椭圆曲线群中的点和运算。椭圆曲线群中的元素可以用来表示多项式,并限制 Prover 必须使用给定的多项式来进行线性组合。这正是 QAP 所需要用到的特性。
我们看一下椭圆曲线是怎么用来表示多项式的。 KoE 假设
考虑一对点 和 ,如果它们满足 ,我们说 是一个 -对。根据离散对数假设,从 是难以计算出 来的。
双线性配对
双线性配对的三个群仅要求大小相同,至于是否是同一个群并没有限制。可能两两不同,某两个相同,甚至三个都相同,由此划分了 I 型,II 型和 III 型等不同种类的双线性配对方案。这些细节不在本文的讨论范围之内。
Groth16 方案
Setup
Prover
Verify
解析
我们简单解释一下上述构造为什么能够工作。至于它为什么是安全的,请感兴趣的读者参阅 [Gro16] 原文。
小结
本文中,我们解释了 Groth16 这个 zkSNARK 方案的构造原理。我们从算术电路开始,介绍了怎样将计算验证问题转化为 R1CS 问题以及 QAP 问题。然后我们解释了怎样使用 Groth16 方案来证明知道一个 QAP 问题的解。Groth16 方案使用了 KoE 假设以及双线性配对。它的缺点是需要可信第三方进行初始化,而且初始化过程需要对每个电路进行一次。与此同时,Groth16 享有最高效的 Verifier 算法以及最短的证明字符串,使得 Groth16 成为至今仍然应用最广的 zkSNARK 方案。
参考资料
[Gro16] Jen Groth. On the Size of Pairing-based Non-interactive Argument. 2016.
封面图来自 Unsplash,作者 Mel Poole 往期回顾 格密码学之iO入门(一):什么是iO(Indistinguishability Obfuscation) 探索零知识证明系列(三):读心术:从零知识证明中提取「知识」 探索零知识证明系列(四):亚瑟王的「随机」挑战:从交互到非交互式零知识证明 探索零知识证明系列(五):云中「秘密」:构建非交互式零知识证明 zkPoD:区块链,零知识证明与形式化验证,实现无中介、零信任的公平交易 从零开始学习 zk-SNARK(二)——多项式的非交互式零知识证明 从零开始学习 zk-SNARK(三)——从程序到多项式的构造 从零开始学习 zk-SNARK(五)—— Pinocchio 协议 零知识证明 Learn by Coding:libsnark 入门篇 长按二维码添加微信进群讨论 info@secbit.io 安比(SECBIT)实验室
Scan to Follow