致谢:郭宇 撰文:李画,安比实验室特约研究员
性能是阻碍公链发展的瓶颈,提升性能则是绝大多数希望超越以太坊的公链的主要设计目标,但当我们站在今天回望时,会发现这些公链选择的方法大多是通过机制的设计来增强一个分布式系统的性能,但受困于分布式系统CAP定理(不可能三角),改善性能是要付出代价的,当这个分布式系统的用途是账本时,这些代价甚至可能是难以被接受的。以太坊也一直在尝试各种方法以提升性能,在2.0被推出的前夜,它「试」出了密码学。
以太坊2.0将是一个以「分布式系统+密码学」为基础来运转的公链,这个密码学不是指被用于签名和隐私的那部分,而是指作为一个高性能系统的核心组件的那部分。从这个角度而言,或许我们可以说颠覆以太坊的不是别人,而是它自己。它从分布式系统设计的单一思路中跳了出来,走上分布式系统+密码学组合设计的道路。这篇文章将试着介绍在以太坊2.0中,分布式系统设计如何与密码学设计结合,实现公链在性能上突破。
一
状态分片:从单账本到多账本
区块链是一个分布式账本,出块节点是记账的矿工,它们负责把交易写入账本。除了竞争记账权,出块节点最重要的工作,或者说本职工作就是检查自己打包的这些交易是否合法。完成这个工作并不难,因为出块节点手中握有账本,它去查一下交易发送方有没有这笔钱即可。
对于未分片的公链,所有节点都持有一个相同的账本;而为了防止记账冲突,每次也只允许一个出块节点记账。以太坊提出状态分片,实际上就是把一个账本分成多个账本,这样一来,一些节点在1号账本记账,一些节点在2号账本记账……(相当于7-11从一个收银台增加为多个收银台),多个节点同时记账,整个公链的性能就会得到质的提升。但如果我们把出块节点与账本/分片的关系固定,比如确定由a、b、c、d四个节点负责1号账本,那坏人只需收买a、b、c、d中的一部分就能破坏账本,公链在提升性能的同时,安全性同比例下降。因此,出块节点需要被随机、动态地分配到不同账本,以此保证分片后的公链与未分片的公链具有相同的安全性。但动态分配会带来新的问题:节点手中该拿哪一个账本?它可能会被分配到64个账本(以太坊计划启动64个分片)中的任何一个去记账。以太坊给出的方案是出块节点不拿任何一个账本,或者说,让出块节点不需要账本就能记账。这会带来两大好处,一是不管节点被分配到哪个分片,它都可以立刻开始记账(出块)工作,几乎不用花费时间来获得以及同步该分片的账本,节点也因此可以在不同分片间轻松跳转;二是出块节点不需要存储账本,也就不需要高硬件配置,任何人抵押32ETH就能成为一个验证者,这非常有助于以太坊PoS的去中心化以及整个公链的安全。但新问题跃然纸上:如果出块节点手中没有账本,它怎么知道交易发送方的钱够不够?密码学就在这时候登场了。
二
向量承诺:从查询到证明
不需要账本就能记账听上去不可思议,但其思路是简单的:在以前,节点有账本,一笔交易来后它翻看账本,查询交易是否合法;在以后,节点没有账本,交易发送方在提交交易的同时需要提交一个密码学证明(为了区分,后文特指密码学证明时都用proof表示),自己证明自己的这笔交易是合法的。
可出块节点为什么能够通过一个proof来判断某笔交易是否合法?这里涉及到两个密码学的重要概念,第一个叫「成员证明」。它指的是通过某种方法,证明个体是群体的一部分。如果能够证明某个账户状态是整个账本状态的一部分,出块节点当然就能相信这个账户状态,并以此为根据进行交易合法性的判断。第二个叫「向量承诺」,它可以将群体,不管这个群体有多庞大,压缩成仅仅一个数,然后给出成员证明,该成员证明表明的是某个个体是属于这个数背后所关联的群体的,且能证明个体在群体中的位置,以及进行证明的更新。Merkle树是可被用于向量承诺的方法之一,我们以它为例来看如何实现成员证明。下图是一棵Merkle树,最下一层的叶子节点存储的是应用数据,其他非叶节点存储的是其子节点的哈希值。如果知道绿色节点和所有黄色节点的值,就可以从下至上进行三次哈希运算,得到该Merkle树根的值,也就是6c0a。
那么,如果验证方手中有树根的值(6c0a),证明提供方把绿色节点的值和所有黄色节点的值作为一个proof给验证方,验证方是不是就能通过计算三次哈希的值是否等于6c0a来判断绿色节点的值是否在这棵Merkle树中?答案是可以。这就是对绿色节点属于Merkle树的成员证明,它是以向量承诺的方式完成的,而这也几乎就是比特币SPV节点(简单支付验证)的工作方式。
如下图所示,SPV节点不存储完整的区块/账本,但存储了每个区块中Merkle树的树根(此Merkle树的叶子节点存储的是该区块所有交易),当它需要查询一笔交易是否存在时,会找全节点要一个该交易的proof,该proof类似于上文中绿色节点和黄色节点值的一个打包(Merkle路径),然后SPV节点会计算这些值的总的哈希值是否等于自己手中Merkle树根的值,如果相等,则说明这笔交易是该Merkle树的一个成员,即这笔交易是存在的。
SPV节点只存储区块头(绿框),区块头中包含Merkle树根(红框)
SPV节点通过成员证明判断交易是否存在,该证明系统包含三个部分:节点手中有一个简短的摘要(树根);证明提供方给出一个proof;节点计算此proof,看是否与自己手中的摘要相符合。到此,我们就完成了「不需要账本就能查账」,它是把查询思路改为了证明思路;接下来我们要实现的是「不需要账本就能记账」。对于以太坊2.0分片上的出块节点而言,它的证明系统同样是由摘要、证明、验证这三部分构成,但它要做到是使用交易发送方(而不是全节点)给出的proof来判断一笔新交易是否合法(而不是旧交易是否存在),并以此判断为基础记账。
三
无状态:从证明账本到证明行为
想象有一个很小的村庄,这个村庄每天只有3笔村民间的交易,村长拿着账本负责记账。A现在要给B转5块钱,传统的思路很简单:村长看A的账户上是否有5块钱,如果有,就记下这笔新交易。现在换一个思路:假设A在今天早上要给B转5块钱,村长知道A的账户在昨天早上有10块钱,那么如果A能够证明昨天的3笔交易都和他没有关系,是不是就意味着他的账户在今天早上依然有10块钱?这样一来,村长是不是不用查账本就能放心记下这笔新交易?答案是肯定的。如果A昨天有一笔交易怎么办?很简单,A这时不是证明自己没交易,而是证明自己昨天只有一笔交易,且那笔交易用掉了3块钱;村长就知道他还有7块钱,可以记下新交易。这个思路的转变至关重要,你一定要去理解它,这是「无状态」这件事的奥妙所在。不难发现,即使是不拿账本的SPV节点,它在查询交易时实际上也是要用到账本,或者说状态的,只不过它不是自己存储状态,而是去找全节点要这个状态的证明;但在这个新思路下,状态的作用可以彻底被「行为证明」取代,那么这条链就能够以无状态的方式去设计。(注:行为证明这个词并无出处,是作者为了易于理解这样描述的)如何实现无状态?如何借助于行为证明完成记账?依然是成员证明的方法。能够利用Merkle树来完成这种成员证明吗?理论上可以,但对于「无状态」这个应用场景来说,用它的开销过大。
在
文章评论
冷萃财经原创,作者:Awing,转载请注明出处:https://www.lccjd.top/2020/06/15/%e4%bb%a5%e5%a4%aa%e5%9d%8a%e9%a2%a0%e8%a6%86%e4%ba%86%e4%bb%a5%e5%a4%aa%e5%9d%8a%ef%bc%9a%e5%bc%95%e5%85%a5%e5%af%86%e7%a0%81%e5%ad%a6%e5%ae%9e%e7%8e%b02-0%e6%80%a7%e8%83%bd%e7%aa%81%e7%a0%b4/
文章评论