演讲:郭宇,安比实验室创始人兼 CEO
整理:Amber,Foresight News
今天我主要是跟大家分享一下关于 ZK 的学习心得和一点体会。因为在以太坊接下来的几个升级中,都包含了很多最新的 ZKP 或者是 zkSNARK 的技术。最近有很多人在学习这些知识,我们也参加了一些公学的小组,在这里深度讲一下其中很共性的问题。
Why ZKP or zkSNARK?
首先我们能感受到 ZK 的项目是很 FOMO 的,我更想从技术层面讲一下我们为什么要有 ZKP 和 zkSNARK。当然,它自身本来就是密码学里一个非常重要的分支,但我认为它在以太坊的发展过程中发现这个东西异常强大,包括 Vitalik 自身也做过一些布道的工作,所以说得到了非常长足的发展,也解决了以太坊未来的发展途径。
从最早期的 Sharding 发展到现在以 Rollup 为中心的新方向上,我认为 zkSNARK 或 ZKP 在其中起到了非常重要的作用。在我看来,首先它是「产生信任的机制」。比特币为我们带来的,像共识协、POW 协议和一些分布式算法,能够产生一些信任,但这种信任是有存在 51% 诚实的前提假设的。另一种是我在从事区块链相关研究之前,做了十几年的 formal logic 和 formal verification 的工作,本质上是通过 formal logic 保证代码的执行满足某种预期,但我认为这也是一种信任,只不过它的假设是通过逻辑系统本身的一致性去保证信任。ZKP 和 zkSNARK 是我第一眼看到的时候,就觉得和我研究了很长时间的领域不一样的信任创造方式,因为他们从另外一个角度,几乎正交地提供了另外一种创造信任的方式,就是通过交互进行概率性证明,同时提供信任。正如 Vitalik 所说,他们是正交于共识协议的另外一种非常重要的区块链核心技术。
第二点我觉得可能很少有人提到,但是我认为是非常重要的,就是可组合性。我们听到这个词大概是 19 年,以太坊还处在 DeFi 早期探索过程中的时候,大家提出来的概念。因为以太坊上的所有智能合约都部署在一个平台上,这些合约之间可以没有任何调用的障碍和壁垒,就像没有农田里没有横亘在里面的篱笆一样。正是这种可以无障碍调用的可组合性让 DeFi 有了现在这样的繁荣。虽然可组合性不是一个特定的编程语言,但它是一种更高维度的编程,是一种可编程的手段,本质上是更抽象的编程。其实在 zkSNARK 里,可组合性是肉眼可见的。且不用说最近两年 zkSNARK 技术本身的发展,当我们去看 paper 的时候,我们已经可以非常清晰地看到一个协议,是通过很多子协议的排列组合构造出来的,并且这种可组合性以肉眼可见的速度扩大,这也就意味着 zkSNARK 不再是我们想象中的某一种算法,比如 Groth16 或者 PlonK。它们本身也很复杂,拆开来看,每个算法都由一些精巧的小组件构成,这些精妙的算法之间又可以构成一个更大一点的协议,甚至比我的描述更加复杂,它不是严格的、有层级的划分,它甚至更灵活一些。
这些可组合性的发展、爆炸很有可能带来新的空间。而且这个空间能有多大?我觉得基本上可以说大到无法想象,尤其是最近一两年关于递归零知识证明技术的一些突破,带来了非常大的创新空间。而至于它是不是下一个「big thing」,我觉得冠上「之一」,可能是一个比较稳妥保守的说法,但我仍然觉得这是一个非常让人激动的领域,尤其是在 Blockchain 或 Crypto 的圈子之外,目前注意到的人还很少,因此我觉得这是非常好的机会。
说到体会,我先谈一谈我自己是如何入坑开始做 ZK 研究的。首先,我在 17 年买了很多 Zcash(ZEC),当然,从投资回报角度来看,这就是非常糟糕的一笔投资。但我觉得也正是这个举动让我深入地了解 zkSNARK,并不务正业地用业余时间读了一些东西,但我发现非常难懂。当时网上也很少这样的文章能作参考。同时当我去翻传统密码学的书时,也失望地发现几乎都没有提及到这类知识。
在一些国外的教材里面,可能在整个教科书的最后一章会花两三页讲解一下,就已经很不错了。但很幸运的是,我在 2017 年年底发现了 Dan Boneh 和 Victor Shuop 写的教材,虽然还没有完全写完,却已经出现了一部分关于 zkSNARK 的讲解。我觉得如获至宝,因为在资料很少的情况下,居然有一本书能从最简单的概念讲起,这本教材我认为是非常好的密码学入门教材。于是在 18 年的时候,我就开始慢慢读那本书,学习一些基本概念。
然后在 18 年年底到 19 年的一整年中,我们创立了安比实验室,早期我们一直在做 smart contract audit,去帮一些朋友解决智能合约的安全问题,但是我们同时还是用了大量的时间去学习基础的密码学知识。在 19 年我们开始着手做一个用于 data trading 的协议,叫做 zkPoD。20 年,我们讲之前的工作总结了一下并发表在了 CCS2021 上,也得到了一些密码学学者的帮助。而在 2021 年之后,因为整个密码学领域发展太快了,我们的很多想法跟不上整个领域的理论工具的发展速度,所以我们之前的工作就暂停了。那时候真的特别感慨,我们之前面临的很多技术困难,很快就会被人解决,甚至还有好多种解决办法,我们就不得不去看全这些解决方案,可能还没有完全理解,又有新的工具被创造出来。所以说我们这几年基本上都在不断学习,学习速度还远远赶不上创新的速度,说这是一个寒武纪大爆炸,我觉得一点都不夸张。我觉得它的威力可能不亚于 ChatGPT 对整个社会的影响,只是说现在还没有那么明显,没有特别杀手级应用出来,但我觉得这个是必然的。
另一点感想就是,在早期的时候,我们读的资料都是来源于学术界,来自于专门长期从事密码学理论研究的教授和专家学者的论文。但是从 2020 年往后,我们其实发现大量资料来源于工业界的工程师。因为在 Crypto 领域,大家迫切的想要使用密码学去解决 Blockchain 和 Crypto 中非常核心的问题,有些快速的工程应用甚至领先了理论的发展。我就举几个例子,首先是 Halo,Halo 最早是由 Zcash 团队创造出来的,然后学术界从中获得了启发发展出了 accumulation scheme,包括最新的在递归零知识证明里非常重要的技术。它最早的起点就是在工程实践中发现的一些一开始不起眼的一些小规律。
第二个就是 PlonKish Arithmetization,最早也是在工业应用领域从 Aztec 团队慢慢发展起来的,之前有很多 code,但是它真正的理论研究是后来逐步补上的。但现在为止基本上以 PlonKish Arithmetization 为主导的很多学术研究已经慢慢扩散开来了。很像我右边图上的几棵树,当然这几棵树我只是借用了 slides 中的,zkSNARK 就像一棵很大的树,并且在不断成长,于是就有了 zkEVM 和 zkVM 这样的概念。我经常感慨在 19 年,预想 zkEVM 或者 zkRollup 之类的概念,都要是 10 年之后才有可能出现的东西,因为在当时我们能感受到 zkSNARK 能做的应用是非常有限的。但是没想到这三年来,Halo 和 PlonKish 的发展能够让 zkEVM 基本上成为现实。这是非常恐怖的,包括像 Lookup Arugment 还有一些很有意思的技术,反过来对学术界都有很大的推动能力。
第三点就是这整个过程是非常愉悦的,不管里面遇到了多大的困难,或者是解决了一些小问题所带来的成就感,都让我们感到非常有趣。
我觉得绝大多数人对这个东西的印象就是特别难学的月球数学,但实际上从我们的经历来看其实也不是那样。
它其实要求的前置数学基础并不多,但它最难的部分其实是关键概念超级多,而且这些概念还在随着时间演化,也就是说你可能从别人嘴里听来了,或者在某个地方讲到的,或者是在一个文档里看到的东西,过了 3 年之后可能需要重新去审视它,它又可能表述都不一定准确,或者是它在表达另外一层意思。
第二个就是协议相对复杂,因为它属于密码学协议,可以说密码学这个分支,整个大方向上都是属于内部协议比较复杂的这类,于是它的形式化定义特别多。不同的学者去写形式化定义使用的符号体系也不尽相同,公式也是量多且复杂,即使背了也记不住,可能睡一觉醒来就忘。
第三点是,核心代码很短,但内部结构足够复杂,密码学有一个很有意思的点,就是你无法通过看代码去学习算法,因为你看他弄来弄去,都不知道他想干什么,还是需要一些理论的指引才能读懂代码。
第四点就是,很多朋友还是会按照论文上的算法去实现一遍,但能实现就证明真的懂了吗?这显然还是相去甚远的,这个我们会稍后讨论的。
零知识证明的学习曲线还是相对陡峭的,陡峭的原因并不在于 zkSNARK 或 ZKP 有多难,而是在于,首先开发工具很缺乏,也就是说想直观地体验一下并不容易,还需要做很多工作,去搜去看相关理论知识之后才能下手。第二就是学习资料其实更缺乏,现在跟 4 年前相比还是多了很多资料的,但要知道资料的增加速度远远赶不上创新的速度,也就是说有大量新的理论技术并没有被总结成文章,有的甚至都没有行文写下来,它们存在一些系统的角落里,或者说它只有代码但没有理论。因为是寒武纪大爆发,导致了学习资料相对更少,即便是需要的数学基础并不多,前置知识覆盖秒依然很广。所以有些朋友认为自己数学不好,并不是根本性问题。还有一点是论文挺难看懂的,这是我在早期学习时的感触,有些套路需要慢慢适应。
一些心得和经验
下面想给各位朋友再讲一些心得和经验。
首先给第一类想要快速入门的新手朋友,或者说看过一些非常简单的概念,无论出于哪种目的想要快速入门的朋友们。首先,有诀窍吗?诚实一点说时没有的,但确实可以把几个地方作为切入点。其一,写代码是一件很重要的事,这里的代码可以分很多种,我认为现在很多可用的 library 都是很不错的。比如 Circum,可以在网页端试着写一些电路代码。第二类的 Halo2,我认为如果想要深入学习的话,可以用 Rust 吗,Halo2 也恰好是 Rust 的一个 library,也是在社区中广泛使用的。现在以太坊基金会也在基于 Halo2 进行一些工作,可以去看一下这个 library,并根据它去写一些基础的 demo 或者例子。第三个是 Gnark,是 Consensys 开发的用 go 语言写的库。如果你对 Rust 不熟悉或者没有写过 Rust 的话,可以优先选择 Gnark,因为它是用 Golang 写的,上手更简单一些。最后,还有 zkSNARK 社区的 Cairo,虽然我自己没有写过 Cairo,但我已经看到不少人已经成功启动了,所以我认为 Cairo 的效果应该是不错的。
关于代码围绕什么去写,我认为可以基于 KZG 多样式承诺、IPA、Baby SNARK、Sumcheck 等非常简单的密码学协议,是可以做一些实现的。因为,实现了之后,可能会获得一些教科书上所不能提供的很直观的概念。比如,代码运行的速度,对稍大一点的例子电路是否能够正常使用,浏览器最大能承受的电路等等。
我觉得手动写代码这一方面,首先有助于大家理解很多概念,比如,到底什么是电路。相信不少朋友都听说过电路,就是挺难写的,如果动手写一下电路就会发现,它其实不算是在写正常的程序,而是在写一个证明过程,因为本身零知识证明就是一个证明过程,因此写电路其实就是写证明,而非写计算。写证明的过程有一些特定的套路和经验模式,这个需要慢慢熟悉和思考的。
第二个我觉得是有助于对运营效率有所感知,就是知道运行的速度能有多快,以及假如说你想去 build 一个应用,他大概能用在什么地方。比如说你在以太坊一层的合约里做一个电路的 verify,你大概需要多少 gas。事实上这些都是需要你实际操作完之后才能有的一个初步印象。
第三个就是对协议借口、协议流程有一个基础的了解和大概的感觉。
第四个就是你能对基础的数学原理有初步的认识,但不需要去学很多,不需要去重新找一本代数的书去翻,因为一本完整的教材包含太多内容了。我觉得通常情况下是没有必要的,但是可以通过 Google 或者 ChatGPT 去快速学习一下基础的数据原理。直接通过编程学习的话,感觉是完全不同的,特别是对于使用的参数、输出的结果,以及如何在代码中 encode,用什么样的数据结构,都会有非常直接的认识和理解。
这里我想要推荐 zkiap.com 的课程,它是一个注重实践的简单代码学习课程,每周花点时间就基本上可以慢慢明白是怎么一回事,推荐给所有能写代码的朋友们。
但有些朋友可能会问,假如说我不会写代码,或者说我没有时间写代码,但是我仍然想快速入门,那该怎么办呢。我认为第一点就是要准确地理解相关概念,所谓的准确理解就不是一些模模糊糊的理解,比如,我们说零知识有 zero-knowledge,那么到底什么是 knowledge?我觉得是需要搞很清楚的,这些关键概念搞得越清楚,看文章就会越顺利,包括还有像 witness 这种概念。还有像 Random Oracle 还有 Commitment 之类的概念。为了搞懂 Random Oracle 是什么,我前后可能花了一年时间去看各种东西,慢慢尝试理解,但但是的资料很少,我觉得现在的资料已经足够丰富了,已经有一些教科书能够吧这些概念讲的相当清楚了。然后还有一些概念,像 CRS、SRS 是什么,如何用 Polynomial IOP 做一些 plunk 应用。其次像 extractability 还有 preprocessing,这个适合具体应用开发相关的。我认为对这些基础概念有必要有非常精确的理解,如果不是很理解或者模糊的话,我的建议是先去看这些概念,Google 和 ChatGPT 能够在这里起到很大的作用。对于基本概念的掌握程度,我认为首先需要能看懂科普文章中的一些密码,一些黑话。
第二个是能够对 zkSNARK 有一个清晰的抽象的认识,也就是说能大概知道它是什么,能用一句话去讲一下什么是 zkSNARK,而不是只是将它描述为一个 library,或者用一个方式函数调用一下,或者说就是一段代码,真正的掌握是要比这些都再深入一层。第三个就是如果好奇的同学或者有更多时间的朋友可以去看一下学术论文,如果第一节能看懂的话,我觉得已经是相当不错了,这意味着很多密码学黑话都已经理解了。如果有一些频繁出现的黑话不理解,就可以去 Google 或者 ChatGPT 弄明白,有些实在很难懂了就可以先放一放。最后就是能初步理解 zkSNARK 的一些应用,如果能做到这一点的话,对一个不会写代码的人,已经是对 zkSNARK 已经又了相当深的认识了。
接下来我说的这一类朋友,他们不满足于一些基础概念的理解,始终对内部工作原理感到好奇,关于黑盒如何运行,为什么能 work,为什么能提供信任,他的信任又基于哪些东西,应用条件是什么,等等。我这边的建议是,需要先充分理解一个算法代码,就是先把一个算法吃透,其实非常重要。因为在算法之间就好比再学一个编程语言一样,如果 Java 用得很熟练了,再去切换到其他语言,其实并没有很复杂。前提是,这个语言需要用得特别熟练,如果只是浅浅地能写一些 Hello World,可能差距还比较大。我觉得可以先针对一个算法,比如说我觉得像 PlonK 是首选的,因为它比 Groth16 简单很多。PlonK 是我认为我见过的所有算法里最简单的,虽然 Groth16 的科普文章更多,但事实上它是一个复杂难懂的算法。然后还可以选择 zkSTARK,Marlin,Spartan,他们的对看论文的要求可能会更高一些。总之,我推荐先学 PlonK。
第二个就是去阅读一些 Github 上的开源代码,现在有非常非常多的有意思的项目,几乎每两三天都能发现一个很不错的开源项目,并且代码质量不错,我在这里就不给大家推荐了。
第三个点就是如果你想了解内部工作原理的话,你不可避免地要去理解这些公式,但对于初学者的最大问题是,公式无法理解或者并不能记住。我认为这里的核心窍门就是,多抄公式。不停地重复抄公式,同时再思考,在这个过程中就会有神奇的力量,能让人不知不觉中就明白了一些东西。
在这里推荐一个 MOOC,叫做 zk-learning.org,他们的课程深度不错,也会涉及到内部的工作原理,也会用非常简单的语言去抽象地解释一个或者一类算法是如何工作的。我认为如果能看懂并实现一个最简版本的代码并且能看懂 70% 的相关论文,且能不需要任何辅助地手推公式,并能够大致理解 Soundness 思路,我觉得已经达到了理解 zkSNARK 的要求了,但在这个阶段还是不要自行修改和优化协议,这是非常危险的动作,除非有非常多的经验,否则千万不要自行修改优化协议,因为密码学协议中有非常多没有写出来的东西。相关的反面教材有很多,我觉得最著名的就是 BCTV14,它是 14 年的一篇论文,他们的论文在做了一次修改优化之后出了一个 bug,然后修了 bug 之后又是一个 bug,而且都是非常严重的 bug,也就是说这些顶尖的密码学家都会犯这样的问题,那更不要说一个初学者。对初学者而言,你可以自己去设计一个协议,但是你一旦去修改别人的时候,你还要确保对这个东西有足够清晰的理解。
接下来对于更高阶的朋友,可能你是在 build 自己的项目,想用 ZK 去解决一些必要性的问题,需要自己设计协议。首先,我觉得你需要反反复复地读大量的论文。第二个就是需要补最基础的计算理论,而不是代数或者射影几何,或是那些数学概念。我觉得这里面其实最重要的是计算理论,我在这里推荐两本书,一本是《Computational Complexity: A Modern Approach》,另一本是《Computational Complexity: A Conceptual Perspective by Oded Goldreich》。第三点就是要跳出兔子洞,关注基本问题。因为有些算法还是很深、很烧脑的,有时候需要在一个非常小的细节卡上好几个月。但我觉得这里面的核心点是为了理解它为什么 work,有些时候你要跳到最外面来问一些最简单、最直接也最基础的问题,再去反思这个细节。就是你需要不断进到一个非常小的细节,同时又要不断地跳到外面去反复对比思考,这样就很容易弄懂这一点细枝末节的东西。第四个就是逆向思考,因为很多协议的设计是非常精巧的,有时候需要我们去理解而不是简单地 follow。但事实上理解又是一件很困难的事,多数情况下我在理解算法的过程中所用到的方法论是逆向思考,也就是说如果将原来的算法换成另外一种,又会产生怎样的效果。大多数情况下,它是不 work 的,那么它为什么不 work?这是很重要的。
最后,给大家说一下读论文的心得,因为论文确实比较难读,都是些非常学术的文章。第一,请务必反复仔细阅读论文第一节,因为论文第一节通常是论文最精华的部分,他通常描述了这篇论文最主要的贡献,包括他和前人的不同以及他的新协议或者新算法最重要的特点。通过读很多论文的第一节,能够快速找到一个知识网络。
第二点就是,你需要把论文的参考文献这几页,特地打出来,有助于形成一个知识网络,就可以沿着参考文献,找到更多的资料,而不单纯是通过 Google 或者 ChatGPT,而是通过这个论文所依赖的前置论文,形成一套理解体系。
第三点是要从历史的角度看概念的变迁、算法的演化和技巧的组合,这里面能发现非常非常有意思的故事。我觉得也可以找机会和大家分享一下,但这需要很多时间去准备。虽然密码学已经历经了 40 年的发展,但是从历史的角度看,它经过了一个非常快速的发展与变迁的过程。
第四点是,一篇论文需要反复看,大概看懂其中的 90%,需要好几个星期甚至好几个月。我最开始去学习这个东西的时候,一开始非常难受,非常有挫败感的一点是有篇论文我看了半年都还看不懂。但突然有一天,我看到一个密码学家他的分享里面说他看论文也是要几个星期才能看完,这时候我才如释重负,我才觉得原来他们也是这样。所以说一篇论文看不懂其实是非常正常的一件事。
第五个是,我认为参与社区讨论特别有用。
最后一点,找一个 Crypto 领域的问题点,找一个你觉得有意义的工作,然后 get hands dirty,这个能驱动你把关注点集中到一些点上面,更容易做出一些突破性的工作成绩。