ZK-Snarks的缺失解释:第一部分

2020-11-02 04:12:48

什么是ZK-Snarks?它们是如何工作的?这是我多年来一直存在的问题,我总是觉得我找到的资源对所有这些东西是如何工作的没有给出明确的直觉。所以今天,在我对自己的理解有了突破之后,我想用一张更容易理解的图片来重新分享我所学到的东西会很好。告诉你思考这些事情的正确方式是什么,如果你想的话,你可以为自己填补哪些空白。

问题的第一部分很容易回答。ZK-Snarks,不管他们有趣的名字可能暗示着什么,都是简单的零知识证据,它们是:

首先,零知识证明是一种密码证明,证明你知道一些东西,而不会暴露某些东西(零知识)。这个“东西”通常被称为证人,但这个细节并不重要。关于零知识证明的资源很多,所以我不会太多地解释它们是如何工作的,或者它们的确切密码属性是什么(完备性、可靠性、零知识)。零知识证明经常被用来证明您知道某个群的元素的某一底的离散对数(例如,$g^x mod p$中的$x$是什么),或者类似限制的语句。“有限的是的,但仍然有用!”Yells Schnorr,Schnorr签名方案的发明者,该方案是通过对离散对数的知识进行零知识证明并使其非交互来构建的。零知识证明或ZKP是证明者(认识证人)和验证者(必须被说服)之间的交互协议。交互式协议在现实世界中很糟糕,因为它经常限制原语的潜在用例的数量,并根据证明者和验证者之间需要发生的往返次数而降低协议的速度。幸运的是,一些ZKP可以在不与验证器交互的情况下构建。换句话说,证明者可以简单地创建证明,任何人都可以在以后的任何时间点验证该证明,而不需要证明者的进一步帮助。当ZKP变得非交互式时,我们简单地称它们为非交互式零知识证明(NIZK)。这里我更多地讨论签名和零知识证明之间的联系,ZKP和NIZK也可以构建在更一般的语句上,比如“我知道某个函数的输入,这样执行就会产生一些输出”,或者更具体地说,“我知道$a$in$f(a,b)=c$”。如果这仍然没有意义,请考虑一下用来说明通用ZKP的常见示例:“我知道数独的解决方案”。我们就快到了:ZK-snarks是通用的、非交互式的零知识证明,还有更多!它们也很简洁,这意味着它们制作的校样体积小,验证速度快,这使得它们如此特殊,以至于当之无愧地被称为ZK-snarks。并不是每一个现代的证明系统都配得上这个特殊的分类,例如斯塔克就不配:

一般用途:对更一般的陈述的证明,如程序的秘密输入或输出的知识。

但你不仅问了ZK-Snarks是什么,还问了他们是如何工作的。

哦,天哪,这是一个复杂的问题需要回答。首先也是最重要的是,有很多计划,太多了,所以我不确定如何准确地回答这个问题。但是我对它们中的一些是如何工作的有一些了解,所以我想它们中的大多数都遵循这种模式,或者对其进行改进,所以让我来解释一下…。

将程序编码或编译成证明系统可以证明的东西,我将在这篇文章(待写)的第2部分中解释。

第一部分并不太难理解,而第二部分则需要研究生课程才能进入主题…

这里,记住这一点:ZK-snarks完全是关于证明你知道某些有根的多项式$f(X)$。根我的意思是验证者心里有一些值(例如$1$和$2$),证明者必须证明他们头脑中的秘密多项式对于这个值的计算结果是$0$(例如$f(1)=f(2)=0$)。顺便说一句,我的意思是验证者心里有一些值(例如$1$和$2$),并且证明者必须证明他们头脑中的秘密多项式对于这个值的计算结果是$0$(例如$f(1)=f(2)=0$)。以1和2为根的多项式(在我们的示例中)可以写为$f(X)=(x-1)(x-2)h(X)$,对于某个多项式$h(X)$。(如果您不信服,请尝试在$x=1$和$x=2$时求值。因此,我们说证明者必须证明他们知道$f(X)$和$h(X)$,使得$f(X)=t(X)h(X)$对于某个目标多项式$t(X)=(x-1)(x-2)$(在该示例中,$1$和$2$是验证者想要检查的根)。

但仅此而已,这就是ZK-Snarks证明系统通常提供的:证明你知道某个多项式的东西。我之所以重复这一点,是因为我第一次了解到这一点对我来说毫无意义:如果你能证明的只是你知道一个多项式,你怎么能证明你知道某个程序的一些秘密输入呢?这就是为什么这个解释的第二部分如此困难:它是关于将程序转换成多项式的。但稍后会有更多关于这一点的报道。

回到我们的证明系统,如何证明他们知道这样一个函数$f(X)$?他们只需要证明他们知道一个$h(X)$,这样你就可以把$f(X)$写成$f(X)=t(X)h(X)$。UGH…。这里不要那么快。我们谈论的是零知识证明,对吗?在不给出$f(X)$的情况下,我们如何证明这一点呢?那就用三招吧!

第一个技巧是使用承诺来隐藏我们发送给证明者的值。但我们不仅要隐藏它们,我们还希望允许验证者对它们执行一些操作,以便他们可以验证证据。具体地说,验证如果证明者提交他们的多项式$f(X)$和$h(X)$,则我们有$$com(f(X))=com(t(X))com(h(X))=com(t(X)h(X))$$。

其中$com(t(X))$由验证器计算,因为这些是对多项式的已知约束。这些操作称为同态操作,如果我们使用哈希函数作为提交机制,则不能执行这些操作。相反,我们可以简单地“隐藏指数中的值”(例如,对于值$v$,然后发送承诺$g^v\mod{p}$),因为这些承诺允许这些同态操作。(为了说服自己,观察如果$a=bc$,则$g^a=g^b g^c=g^{b+c}$。

$g^a=(g^b)^c=g^{bc}$可以实现目标,但前提是$c$是已知值,而不是承诺(例如,$g^c$)。不幸的是,这是我们的证明协议的一个限制,因为在承诺之间将有乘法运算。这就是我们可以使用双线性对来解除阻碍的地方,这也是我们在ZK-snark中使用双线性对的唯一原因(实际上只是为了能够将承诺中的值相乘)。我不想太深入地讨论什么是双线性对,但只知道它只是我们工具包中的另一个工具:

取我们组的两个值(由$g$生成的值以$p$为模,取不同的幂),并将它们放入另一个组。

通过把东西从一组搬到另一组,我们可以把以前不能乘的东西成倍增加。

因此,使用$e$作为编写双线性对的典型方法,我们有$e(g_1,g_2)=h_3$,我们可以使用它通过以下公式执行隐藏在指数中的乘法:

但是不要再谈双线性配对了!这也是我们在ZK-snarks中使用这些的唯一原因。这只是一个让我们的同态承诺更同态的把戏,让我们可以做到:

最后,ZK-snarks的简洁性来自于这样一个事实,即两个不同的函数在大多数情况下会计算到不同的点。这对我们意味着,如果我的$f(X)$不是真正的$t(X)h(X)$),这意味着我没有真正具有我们用验证器选择的根的多项式$f(X)$,那么在任意点$r$计算$f(X)$和$t(X)h(X)$不会给出相同的结果(大多数情况下)。换句话说,对于几乎所有的$r$,$f(R)\neq t(R)h(R)$。

了解了这一点,证明某个随机点$r$的$com(f(R))=com(t(R)h(R))$就足够了。这就是ZK-snark如此小的原因;通过比较一组中的点,您最终可以比较整个多项式!

但这也是为什么在大多数ZK-Snark可以工作之前,需要一个“可信的设置”。如果证明者学习了随机点$r$,那么他们就可以伪造将被验证的坏多项式。因此,受信任的设置与以下内容有关:

对其进行不同的求幂$g^r、g^{r^2}、g^{r^3}、\ldots$,以便证明者可以在不知道点$r$的情况下使用它们来计算其多项式。

第二点说得通吗?如果我的多项式作为证明者是$f(X)=x^2+x$,那么我所要做的就是计算$g^{r^2}g^r$,以获得我的多项式在该随机点$r$处求值的承诺。

接下来,我要写这篇博文的第二部分,你得等我写完了。