本文将会:
对前面文章介绍的协议进行调整
进行协议复杂度分析
进行优化
简要介绍现代零知识证明协议
Lior的调整
一位同事指出了零知识方面的警告,并对协议优化提出了好的建议,如下所示:
零知识修复
假设问题实例的前两个数字是5和6,而且随机的r是在0至10的范围内选取的。
如果此时证明的查询i恰巧是1,那么证明者被要求揭露证据中的第二个和第三个元素。如果它们恰巧是15和21,那么验证者会立即知道5和6(从问题实例中)属于答案的同一边。
这改变了我们想要的零知识的属性,这会发生是因为我们在一个非常小的范围进行选择,并且r恰巧成为了范围中的最大值。
这里有两个方法解决这个问题。一个是任意选择数字并做模那个数字的计算。一个更简单的方式是在更大的域上选择,比如,这会使得获得揭示内容的r的可能性变得极低。
通过循环列表来简化
我们的证据最初只有n+1个元素且第一个元素是随机数,剩余元素是问题中的部分和与赋值的点积操作(加上最初的随机数)。 这意味我们有两种类型的查询,一种是检查列表中两个连续元素的绝对值之差是否对应于问题列表中的元素。另一个类型的查询是检查第一个和最后一个元素是相等的。
正如Lior指出的,完全从证据中省略最后一个元素是更优雅的,如果i=n,使用问题实例中的最后一个元素检查证据中第一个元素和最后一个元素差的绝对值。必要的,这像把证据看成了一个循环列表。好的一方面是现在我们仅有一种查询-查询证据中相邻两个元素的差模n。
证明大小/通信复杂度
我们将要分析我们的代码生成的证明大小。这通常代表通信复杂度,因为Fiat-Shamir启发(在第二篇文章中描述)将消息(来自一个交互式协议)转化为一个证明,让这两个术语在本文的上下文中是可交换的。
所以,对每个查询,证明保存了:
- i的值;
- 证据中第i个元素的值和第(i mod n)个元素,
- 两个元素的认证路径;
这里的认证路径是重的部分,它们中的每个都是log(n)元素长的256位值的列表。
正如最后一篇文章讨论的,为了获得体面的健壮性,查询的数量大约为100n。
将这些组合起来,证明大小将被来自认证路径的个哈希值决定。
因此,一个人知道1000个数字的分割问题分配的证明需要大约2,000,000个哈希值,可以转化为64MB的数据。
小默克尔树优化
由于默克尔树的认证路径,令人吃惊地占据了证明的绝大部分,我们可以减少一点它的数量。
注意到所有的查询(除了1)都询问树中连续的叶节点,
连续的叶节点平均来说,共享它们的LCA(最接近公共祖先)在高度。一直向上到LCA,它们的认证路径也许不同,但从LCA到根节点,它们的认证路径是一致的,因此我们浪费了空间在证明中写它们两个。
省略它们中一个节点从LCA到根节点的路径将会让证明大小降至.有一个很好的25%的提升。
实现这些优化和Lior的在本文中所说的调整遗留给读者练习。
现代协议
现代零知识证明协议,像ZK-SNARKS, ZK-STARKS, Bulletproof, Ligero, Aurora以及其它协议,通常在下面四个方面被比较:
使用协议可以证明什么类型的声明
证明占据多大的空间
创建证明需要花费多久时间
验证证明需要花费多久时间
通常初始化的话题也会被讨论,但是我们这里不会涉及。
让我们看看本文提及的玩具协议的代价:
什么样的声明可以被证明?
在玩具协议中,仅有分割问题实例的解决方案的知识可以被证明。与许多协议相反,可以用那些协议证明输入的知识满足一些任意的算术电路,或是一个运行T个步骤的特定程序,并提供一个特定的输出(这是ZK-STARKS可以做到的)。
你可能会说,如果你可以证明一个NP完全问题(分割问题就是其中的一个),你就能证明它们全部,这是由于多项式时间规约,而且从理论来说你是对的。然而,在零知识证明的现实世界中, 计算处理也有自己的成本,转化也会导致问题规模的膨胀,虽然“多项式规约”是一个可以无实际代价转化的理论术语。由于这些原因,现代协议努力采用更具表现力的输入(比如算是电路和关于计算机程序的声明)。
空间
如上述分析,我们的证明占据了的空间,在现代协议中,证明大小通常是在常数和n的多项式对数之间。
这巨大的差距是使得提出的协议只不过是一个玩具示例, 这意味演示的这些方法和技巧在任何真实的应用中作用都很小。你可以追溯差距到这样的事实,我们需要线性数量的查询,每个查询都有对数数量的哈希运算的代价(默克尔认证路径)。我采用的方法受到了ZK-STARK协议技巧的启发,就证明大小而言有略微比其它协议高的代价,但是具有表现力,需要相对短的证明实际,和非常短的验证时间。在STARK中,证明的主要部分由默克尔认证路径组成,但会尽量保证查询的数量尽可能小。
证明方运行时间
在我们的协议中大约为$O(n\log n),与现代协议差距不大。
验证方运行时间
在我们的协议中是与证明大小成线性关系的,因此并不好。注意到,至少在区块链的上下文中,证明仅被写入一次但是被验证很多次(比如被矿工)。现代协议因此努力使验证者的工作量在不影响可靠性的情况下尽可能的小。
结语
这结束了本次教程中希望涵盖的内容。写作和编码都很有趣。希望我们能在某个时间再次这样做。