我们是如何用分片技术把7笔/秒的区块链交易提升到2488笔/秒的?



内容 | 贾瑶琪  Zilliqa技术总监、联合创始人

整理 Aholiab



众所周知,吞吐量一直是区块链的一个痛点。比特币的底层设计仅支持每秒7笔交易,还不及传统支付工具Visa每秒8000笔交易的一个零头,更别说支付宝在去年双十一创造的每秒25.6万笔的记录。这严重制约了去中心化应用的发展。去年以太猫风靡全球,造成了以太坊的大堵塞,以至于人们戏称用是否造成区块链堵塞来评价去中心化应用的热度。


针对如何提高区块链的吞吐量,业界也在不断尝试。为改善比特币网络的吞吐量,去年比特币硬分叉出了比特币现金。


近期,Zilliqa技术总监、联合创始人贾瑶琪谈到了这一问题的解决方案。


贾瑶琪来自Zilliqa团队,之前在新加坡国立大学读博士,博士期间主要研究偏底层的网络协议,以及点对点协议的隐私保护,还有可扩展性问题。2017年,跟师兄还有导师一起创建了Zilliqa团队,主要就是用分片技术,来提高整个公有链的可扩展性,以及实现高吞吐量


说到分片技术,里面包含很多种不同的技术。比如以太坊的分片技术,还有Zilliqa的分片技术。



 公有链的吞吐量问题


大家可能都了解比特币、以太坊,以及其他的公有链。区块链技术为大家提供了很多好的特性,比如去中心化、透明性、以及不可篡改性。但如果大家把区块链作为一个记账或者帐本系统,这其中有一个很大的问题,就是关于吞吐量的问题。



 

比特币每秒最多只能处理7笔的交易,如果用搭火车的例子来讲,比特币就对应着手工检票,每秒只能检7个人。而传统的记帐系统,例如信用卡、VISA或者MasterCard,他们平均的处理效率超过每秒8000笔交易,就类似于现在我们高速公路上使用的ETC,或者检票中刷脸进站的系统,可以迅速地处理大量的交易。



低吞吐量的弊端

 

由此可见,目前公有链的低吞吐量会带来很多问题,例如大家都会见到的高手续费问题。在去年有一段时间,如果你在比特币上面进行一些交易,比如A转比特币给B,手续费可能就高达50美元。另一个方面,像以太坊去年做ICO,或者做这种代币募资,很多人为了抢资格,就会花费很高很高的手续费,来竞争去加入一个代币募集。



其实,虽然你设置了这么高的手续费,有时候也是抢不到这个资格的。高手续费会限制很多功能,从而导致我们现在没有一个很好的杀手级的应用。大家可能都知道,去年在以太坊上面最火的两个应用,一个就是ICO,另一个就是风靡全网的以太猫。但以太猫在以太坊上比较火的时候,占据了以太坊上超过30%的流量,导致整个以太坊有很多的拥塞。在那个时候,如果你想做一笔简单的转帐,必须支付更高的手续费才能完成这笔交易。


因此,这个低吞吐量导致了目前还没有杀手级应用。我们可以联想到在互联网初期,大家用的整个底层系统可能还没有搭好,同时网络费用又特别得高,我们只能浏览一些简单的网页。但随着整个互联网系统生态的发展,大家慢慢也会看到一些很伟大的公司。例如像Google、Facebook、Twitter,以及国内的百度、阿里巴巴、腾讯,他们的崛起就是因为这个底层生态系统建好了。有了这样的高吞吐量,才使得更多的企业以及程序员参与进来,创建许多杀手级的应用。


 公有链的可拓展性


那么如何来解决低吞吐量问题,我们需要公有链有「可扩展性」,但可拓展性其实并不等同于高吞吐量。



很多场景下只需要高吞吐量,不需要可扩展性,所以你只需要一个很强大的服务器来提供一个很高的吞吐量。但是对于可扩展性,就要求你随着节点数的增加,你的吞吐量也得相应地增加(因为可扩展性更多地是指随着节点数目的增加,吞吐量或者性能也增加,所以很多时候大家其实是要求的高吞吐量而不是可扩展性)。



 已有的解决方案


目前来看,比特币处理交易的速度小于每秒10笔,以太坊小于每秒20笔,但传统的记帐系统,例如信用卡,交易速度超过每秒8000笔交易。我们如何去解决这个可扩展性,或者说低吞吐量的问题呢?目前有几种方案。


方案一,增加区块的大小。例如比特币,我们现在一个区块的大小可能只有1MB的存储空间。如果要进行交易的话,只能把交易加到这1MB里面。如果大家也做比特币交易,可能都知道去年底的SegWit2x,将区块大小从1MB提高到2MB。但是出于对安全性和其他因素的考虑,最终Bitcoin Core取消了这个SegWit2x硬分叉。导致了当时大量的资金都投向了以太坊的ICO项目。



当你把区块大小从1MB升级到2MB,或者10MB,甚至1GB,但这个方案是否能达到提高100倍吞吐量的效果呢?不一定,因为你虽然可以把区块大小升级到1GB,但由于你的计算性能以及带宽的限制,导致整个网络不能正常运行。像比特币或以太坊,都是要通过工作量证明达成共识,工作量证明之后还要在整个网络进行广播,如果是1MB可能还好,如果1GB的话,要进行这个广播,基本上不可能在10分钟以内通知每一个矿工。所以这里面有一个很大的限制。

 

方案二,链下交易。对应比特币的闪电网络(Lightning Network)和以太坊的Raiden Network。他们给出的解决方案大致是这样的,你提前支付一些以太坊或比特币作为押金,之后你可以在链下通过一些手段,来跟其他人进行交易。这就类似于你提前在链上存了一些押金,然后其他的终端用户可以在咖啡店里和你进行交易。交易结束后,你要把这个结算放在区块链上面,这样一个链下的方案。因为你链下处理这些交易的话,可以用一个十分强大的服务器来进行处理。这样就可以大幅度提升系统的吞吐量,可以做到每秒上万,甚至是几十万的交易量,类似于淘宝。



但是大家可以看到,这里有一些问题,就是你一旦用链下的话,虽然能够达到高吞吐量,但是交易失去了开放性、透明性的优势,相当于做了客户端服务器的一个终端。同时由于你用链下交易,就没有那么多节点去进行行为监督,那么也就少了去中心化的优势。

 

方案三,代理人共识协议解决方案。如何选出这些代理人,你可以用权益证明,也可以通过一些官方的验证。例如我有一个公司,这个公司有相应的资质,那么官方就会给我发一张牌照,我就可以作为一个代理人。



不管是7个代理人还是21个代理人,甚至可能是几十个代理人,大家会形成一个小团体。例如我们现在这些人,都可以去做一个代理人。之后我们去运行一些共识协议或者类似功能的协议,来达成一个共识,产生区块,然后再将这个区块广播给整个网络,从而达成整个网络的共识。这样做的好处就是,这个机制可以保证在一个很小的团体内部,很快就达成共识。这样做很简单,只要使用一些已有的共识协议,你就可以很快达成共识。


不过,代理人共识协议也会带来一些问题,我们刚刚也有提到大家对于去中心化的担忧。因为像比特币或以太坊都有成千上万的节点来做共识决策。代理人共识协议目前只有一个小团体的代理人来做共识,难免会被大家质疑你是否去中心化,以及你的安全性。因为这一小部分的节点可能都是一些利益团体选出来的,他们是否能代表绝大多数人的利益呢?这些都是有待考证的。


不过以上这三个解决方案都是很好的解决方案,大家如果从不同维度,不同场景出发,这几个方案都是有很大的用处。而今天我要跟大家分享一下,我们Zilliqa是如何用另外一种解决方案,我们叫做分片技术,来实现这样一个高吞吐量的。我们的方案跟前面的几个方案不在同一个维度,但是几种方案其实是可以共生的。



 一种新的解决方案


在讲分片技术前,大家可以先看看整体的结果和运行效果。这些数据都是在亚马逊的EC2上面测试得到的,通过搭测1800个节点、2400个节点以及3600个节点运行我们的算法,得到了下面的数据。直观上看,随着节点数以及分片数的提升,我们的测试数据,可以从每秒1218笔交易,达到每秒2488笔交易。



这样我们可以得出一个结论,相对于比特币或以太坊我们可以获得一个很高的吞吐量。另一点也很有意思,从图中我们可以看到随着节点数目的增加,吞吐量也是在增加的,我们真的实现了这种可扩展性。


讲了这么多,那么这个技术到底是怎样的呢?



 分片技术概览


网络分片,简而言之就是并行化的分而治之。例如我们整个网络有1万个节点,我们可以把1万节点,分成不同的小组,每一个小组,可以有不少于600个节点,这样来叫做一个划分。划分之后,我们在每一个分片里,处理不同的交易。之后先在每个分片里面达成共识,然后会有一个单独的分片将共识的结果进行汇总,广播给整个网络。

 


在这个系统的初始化阶段,我们会将整个网络划分成不同的分片,每个分片不少于600个节点。过了一段时间,可能有一些新的节点想要加入,也可能有一些旧的节点因为自身网络的问题,或者系统的问题,想要离开。这种情况下,我们该如何将这些新的节点加入网络,将那些旧的节点从网络中剔除。

 


每过一段时间,我们都需要做一次工作量证明。工作量证明部分跟以太坊基本上是一样的,这要求你将上一个区块的哈希值、节点的IP地址和你的公钥一起进行哈希计算。大家都知道,哈希计算就是工作量证明,最终你要满足哈希值的阈值。对应的难度是相匹配的,例如哈希值的前100位都是0,如果你算出来的哈希值满足这个条件,就说明你完成了工作量证明。



之后你就可以产生这样的一个结果:我们会得出你的ID,之所以要你的ID就是因为我们会根据你ID的最后几位,来决定你应该被分到哪一个分片上。这样的话,对于一个新的节点来说,是无法通过自己的意志去加入某一个分片的,只能通过工作量证明,而工作量证明难度较高,因此可以避免出现新节点自己选择分片的情况。因此工作量证明的最后几位,就可以从数学上保证你的随机性是足够的。


如果一个节点想要加入我们的系统,他加入的方法就是做工作量证明,然后被随机分配到一个分片里面。这样做的好处就是,我们可以保证一些恶意节点不能直接加入到某一个分片,因为所有的节点都是被随机分配到不同的分片里面的。



有了这些分片,每个分片里面都有很多的节点,我们要怎样进行交易处理呢?我们在这里也做了一个交易分片,就是用来处理不同的交易,不同交易会被分到不同的片里面。那么每笔交易是根据什么来分到不同片里面?我们做了一个简单的分片处理,就是根据发送者的地址分片。那样的话,如果A把钱发给B和C,那么这两个交易应该是在同一个分片里面处理的,这样保证没有双重支付问题。


如果A发给B和C,但是你把A发给C的交易分到另一个分片里面,这个分片里面的节点,会很容易检测出来,然后把这笔交易拒绝掉。通过这种很简单的方式,我们达到一个交易分片的效果。因此你在不同分片里可以处理不同的交易,之后可以在每个分片里面,验证你的交易是否是正确的。验证过程很简单,例如A发给B了10块钱,分片会检查A的余额是否是足够的,如果A发给B了10块钱然后A又发给C了10块钱,那么分片就检查有没有双重支付的问题。



在每个分片内,每个节点都会进行这样的一个对交易的处理,之后通过运行一个协议达成共识,最终附上自己的签名,生成一个叫做MicroBlock的微小区块,提交给目录委员会,目录委员会会运行另一个共识协议,从而形成了一个共识。最终生成一个区块,并向不同的分片进行广播。


在这个过程中,每一个节点都可以收到最终的区块,这个区块的内容是很小的。同时,不同区块之间也会进行交换数据,从而分享最终区块内的这些交易。整个系统有三层结构:


  • 第一层,是哈希的哈希;

  • 第二层,交易的哈希;

  • 第三层,真正的交易内容。


通过这种三层结构来保证整个系统在每一步进行广播的时候,内容量都是相对比较小的。因此过了一段时间之后,你的不同分片里面,大家都可以获得这一段时间以来交易处理之后的一个共同状态。


刚刚提到了,在每个分片里面,我们都会运行共识协议。那么我们是如何来保证每个分片里面,超过100个的节点能够很有效而且安全地运行共识协议。这里我们用到了在2000年之前学术界很出名的容错协议,叫做:实用拜占庭容错协议——PBFT。


这样一个容错协议可以保证在一个小范围内,例如几十个节点,或者上百个节点,大家同时运行这个协议,最终形成一个共识。共识就是A发给B了多少钱,C发给D了多少钱,大家有这样一个共识之后,就可以去完成刚刚提到的协议。


我们还用了一个叫做「集体签名」,或「多重签名」的方案,从而减少拜占庭协议里对不同节点签名的要求。因为如果有600或者800个节点,都对同一个信息进行签名的话,就会有600、800这么多的签名数据,这个数据是很大的。所以我们用多重签名来减少集体签名数据量的大小。


最终通过结合PBFT和集体签名,我们实现了所要求的安全、高效的共识协议。在共识协议部分,如果大家只是把它当做一个黑盒的话,其实我们还有很多种选择的。


第一种,像比特币或者以太坊里面的共识协议,学术界把它叫做Nakamoto Consensus,用中文讲就是「中本聪协议」。可能有时候大家会把这个协议理解为只能做工作量证明,这种理解其实是不完整的。比特币的共识协议其实分两部分:第一部分,大家都在做工作量证明,过了十分钟,会有一个成功获得结果的人,他会生成一个新的区块。


这样是不够达成一个共识的,因为你之后还要再继续做工作量证明,在后面,要生成超过6个的确认区块,才能保证你在第一个区块里面那些交易被整个网络接收。所以比特币的共识协议分两部分,第一部分是工作量证明,第二部分还要有超过6个确认区块,才能保证你的共识结果是有效的。


但问题是这样的共识协议消耗的时间是很大的,例如在比特币里面,一个共识中运行一轮工作量证明要花费10分钟,再加上6个确认的区块时间,超过1个小时。那么你整体算下来,有可能会超过一个半小时才能确认你的交易。这样就导致比特币的吞吐量低,同时时间消耗高。


 

我们是否有其他选择呢?在学术界,只要使用PBFT或者类似的共识协议就可以相对高效地去实现多个节点之间的共识。举个例子,在一个房间里,A要给B发10块钱,A要给C发20块钱,B要给D发50块钱,那么我们这个屋子要形成一个共识,最终有哪些交易要加入到区块链里面?可能初期的话,会有一个领导者把大家的建议都收集起来,然后再分发给每一个人,说我现在收集到这么多交易,大家就跟随我把这些交易收集起来加入到区块链里面。这样每个节点都会收到一个请求,对于节点该如何决策呢?我作为一个节点,我怎么确定其他人也收到同样一个请求,或者同样一个区块呢?


那我就全网广播我收到的信息,广播给所有人,其他人也会广播给我。这样通过预准备,达到了初步共识的效果,即每个人都确定我收到这样一个区块,或者对应一系列的交易。最终再通过这样一个广播,来保证我知道超过三分之二的人也收到同样一个区块,或者同样一系列的交易信息。这样才能保证整个网络里面,大家都在同一个状态下面,每个人都知道,所有人收到了同样一个区块,大家可以继续往下一步走了。

 


这个共识协议很高效,运行几十个节点达成一个共识,大概只需要几十秒的时间。同时也很节能,不用做工作量证明。你的电脑不用无时无刻都在做哈希运算才能获得最终性。我们都知道,在下一个区块里面,这些交易是会被加进去的。


但是有一个问题,这中间有好多轮的广播。我收到交易之后,要广播给大家,大家也要广播给我,这样的话,信息的交换量是很大的,导致整个网络的拥塞程度是很高的。如果我们只用一个简单的数字签名来做,比如你把你的信息发给我,其他人广播也把他们的信息发给我,同时附上他们的签名。这样的话,如果600个人用传统数字签名,可能就会产生600条数字签名信息。这会导致整个网络非常拥塞,网络会很慢。所以我们之后就采用了多重签名技术。这个技术不算是新的密码学技术。好处就是可以把600个签名压缩成一个签名,大家可以想象,如果之前广播600个签名,现在换成一个签名,整个网络的拥塞程度会减轻很多。通过使用多重签名,整个网络的消息规模会减少,同时沟通成本会降低。




做一个简要的总结,就是每一个分片首先收到了多条交易,接着会运行拜占庭容错协议,大家先达成一个共识,有哪些交易要被写到区块里面。之后因为要记录下来,我们整个屋子N个人都同意把N个交易写在区块链上,我们就会采用多重签名,从而减少签名的大小,使得整个协议消耗比较小。



智能合约

 

当我们知道了分片技术带来的好处,以及分片技术给整个系统带来的高吞吐量之后,相当于我们有了一条高速跑道,还应该有一个相对安全,同时可以支撑高速性能的一辆跑车。所以我们就要开发对应的智能合约。

 

对于已有的智能合约,大家如果作为开发者可能都知道以太坊上的Solidity,在过去的两年里,以太坊上面的智能合约遇到了很多的漏洞和攻击。例如两年前,其中的The DAO漏洞导致价值6000万美金的以太坊被盗,去年Parity多重签名钱包的漏洞,导致超过3亿美金的帐户被冻结。


究其原因的话,首先是因为智能合约是一个很年轻,同时也是很复杂的编程框架。很多程序员写的一些逻辑,复杂性是很难想象的。我们知道编程时很多时候我们都是随着逻辑写代码,但是问题是我们写出来的代码,可能会有很多的不可预知性,比如那些边边角角的漏洞。还有就是目前的智能合约,没有一个形式化证明。在学术界现在有很多语言,它们都是支持形式化证明。形式化证明的意思很简单,就是我写出来了一系列的代码,我可以保证我写的代码就是我想要的逻辑,没有越出我想要的逻辑的框架



基于这些原因,我们团队设计开发了一个基于自动机的智能合约语言,叫做SCILLA。



对于一个程序,例如开关灯的操作,你可以有不同的状态,例如关闭、暗光、明亮,同时你也有很多行为来去触发使一个状态跳到另一个状态。例如短按一下、按一秒、以及长按。如果你在关闭状态,简单地按一下,就会切换到暗光状态,再按一下,切换到明亮状态。在智能合约里面,你可以很清楚地把这些状态互相进行切换的行为定义清楚。


这样我们就可以提供一个形式化的证明。同时对于程序员来说,也可以很清晰地得出自己想要执行的逻辑。目前SCILLA是非图灵完备的。之所以我强调非图灵完备,是因为我们发现像以太坊的Solidity,虽然是图灵完备的,但有时候是不需要的。你如果写以太坊智能合约,应该知道它的燃料限制,因此很多时候智能合约是不需要做无限循环的,同时燃料的限制也支持不了无限循环。虽然支持图灵完备,但更多的时候对于程序来说,非图灵完备可以保证一个更加安全的逻辑执行,而且非图灵完备其实大多时候也可以实现很多你想要的功能。



上图是一个SCILLA提供的众筹智能合约。大家可以看到,类似于以太坊上智能合约的这些不可变参数,以及可变的状态。不同于智能合约里面,我们这里用的是一个状态转换来实现每个人要贡献多少钱,以及退款是如何进行的。


下图是模拟的一个两年前的攻击,大家可以看到,智能公约要进行一个退款行为。最开始智能合约会检查发起人当时有没有给我打钱。如果给我打钱了,我在退款的时候就会按同样的数目退款给你,最终把智能合约针对投资人部分,设置为0。但问题是在攻击的时候,不是最终直接把这个状态设置为0,而是在最终设置为0。中间的部分,进行了一个跨智能合约的调用。结果是,如果智能合约碰到一个恶意的程序可以退回重来,再执行一遍这部分逻辑。这部分逻辑就会导致这个投资人的钱数,可以循环地进行增加。例如你运行一次代码,可以使得投资人的钱数增加一倍,反过来恶意的程序再运行回来,进行一个回调,又可以使得把投资人的钱数再增加一倍。这样无限地运行下去,导致他损失了超过6000万美元。


 

那么我们如何去做安全补救?很简单,如果程序员小心一点的话,可以去遵循这样一个模式。先去检查这个投资人是否当初投资了我,之后进行执行:如果你投资了我,我先把你这部分的数目在我这里设置为0(反正我后面要转帐的),之后再进行交互。交互时把那部分钱转帐给之前的投资人。


说起来很简单,但很多时候,作为程序员,我们可能会忽略掉这些安全检查。在SCILLA这里,我们可以用自己的编译器,做一个自动的检查。就是你如果在写类似代码的时候,必须要符合安全规范。就像刚才说的,先去检查,然后再去进行交互。如果你不遵循这个规范的话,我们的编译器是不会通过的,或者会给你提供一些对应的提示。



 去中心化应用的落地场景


未来的话,因为我们有了这样一个相对高吞吐量的区块链平台系统,共享经济,例如OfO、Uber,这样的共享经济公司都可以将主要的业务逻辑放在区块链上,运用智能合约来处理不同的用户请求。目前大家都是通过一个服务器来进行这种中心化交易,但之后如果用区块链进行去中心化的交易,就可以省去很多中间的费用,以及中间的一些可能比较灰色的花销。当然区块链也可以用作支付网络,支付网络目前的痛点就是手续费很高,但是如果能实现高吞吐量,大家可以用相对低廉的手续费去做一些支付。



另一个方面,因为有了分片技术,我们之后可以做一些分片的并行计算,即类似于MapReduce的一些计算。包括深度学习,在不同分片里面,可以放不同的神经元(neuron)来进行科学计算。我们目前还是在做更多的测试,以及其他功能例如智能合约的开发。在上个月,我们已经放出了我们的测试网络,以及数字钱包。

  

大家可以通过https://explorer.zilliqa.com,去访问Zilliqa的测试网络。目前我们在其中加入了很多自己的交易,对这个网络进行压力测试。钱包的话,你可以通过https://wallet.zilliqa.com去访问,来生成自己的帐户,之后我们还会将一些测试代币放到你钱包里,你可以在我们的测试网络中进行一些简单的测试,包括对交易的测试。


最后,Zilliqa团队也在大量地招工程师,总部在新加坡(目前还没有分部)。包括核心工程师和去中心化程序开发工程师,我们也需要一些商业开发、市场开发的人才。

阅读更多
上一篇活动幂等性
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭