区块链的诞生,带来了天然的运行基础平台
区块链1.0时代是以比特币为代表,2008年这个概念被首次提出,2009年正式启动了比特币的网络。这个网络有别于普通意义上互联网,因为它在互联网上面实现了价值的转移。
之前互联网经历几十年发展,主要解决的问题是信息的互联互通,我们在使用互联网服务的同时,后面是一个个的服务商和中心化的节点。
在区块链网络里,它有这样几个特点:一是去中心化、二是不可篡改、三是可信任。它用到了计算机科学、密码学、网络和经济学的博弈论等等,同时加了一些创新性的设计。
区块链的2.0是以以太坊为代表,主要特点是加入智能合约(智能合约是1995年提出的概念)。
受限于当时的环境,计算机依赖于可信的第三方,加上数据的不可篡改,操作涉及到多方会有一些限制。区块链的诞生,带来了天然的运行基础平台,区块链技术与以太坊进行结合,同时扩大了场景。溯源、经济领域、游戏等很多应用,都可以在以太坊为代表的区块链2.0上去做。
了区块链3.0时代,是区块链的大规模应用。尽管区块链技术发展了近十年,但真正走到我们身边的应用很少,可以说几乎是寥寥无几。
目前很多的应用,是基于联盟链的企业级应用,像天猫跨境物流的跟踪、跨境的支付,还有像我们前面公布的疫苗溯源方案。
掣肘规模化应用的根源
为什么发展了那么久,炒的也很热,但区块链在应用上还没有深入到用户的身边去?我们认为主要是它的可扩展性受到很大的限制,这也是目前绝大多数公链所努力攻破的一个点。
区块链的可扩展性到底有哪些问题呢?
比如去年年底风靡全球的一个游戏“加密猫”,直接导致了以太坊的严重堵塞。原因就是以太坊从设计上,不能支撑大规模的交易,导致了它在打包、入块的流程上受到了阻碍。
以太坊设计上不能支持大规模的交易,导致了打包、入块的流程上受到了阻碍。
而传统中心化的交易平台,比如Visa和支付宝,Visa的处理能力是2.4万的TPS,支付宝“双十一”峰值32.5万TPS的峰值,和比特币和以太坊最大理论的峰值(比特币是7,以太坊是15)相比有天壤之别。
什么原因让它的性能这么低下呢?区块链里有“三元悖论”,这是以太坊提出的概念,意思是说区块链领域不可能在同一时间、同一层面从去中心化、安全性和可扩展性三个方面做到提升。
2008年比特币设计的时候,主要解决是资产的价值转移,而在资产里面很重要的一个特点就是要安全性。比如说要理财、投资,肯定考虑资金的安全性,这是首要的。
在安全上的基础上,我们才能考虑的是它的收益,如果你的本金都没了,其实你投资的价值也就很少。
像比特币和以太坊,为了提升去中心化和安全性,设计的时候每一个节点、每一笔交易都需要全网去广播,全网节点去做验证,每一个块也是需要全网去同时争取这样一个记账的过程。
当然,从这两个点上就失去了它的可扩展性,全网的性能制约点就相当于取决于每个节点单点性。加入的节点越多,性能不仅没有得到提升,消息的扩大、通信的复杂度反而更高,让它的可扩展性受到了极大的限制。
比如EOS比较“聪明”,牺牲了去中心化,用了21个超级节点的概念,但前提认为这21个超级节点是可信的。共识基于21个超级节点之间去达成,虽然提供可扩展性,性能也得到比较大的提升,但是牺牲了去中心化区块链本质的特点。
另外有一些区块链公链,为了提升去中心化和可扩展,只用了一些分散的存储计算,从全网里面选出一小部分节点来做共识,选出一小部分节点,不同的节点之间存储的账本不一样,这就让去中心化和扩展性有一定的提升。但是这样的话就会让它的安全性降低,攻击的难度也降低。
区块链扩容方案
目前在区块链的扩容方案里,可扩展性有四种方法:DAG、二层扩容、共识创新和分片技术。
DAG(有向无环图)
DAG也叫有向无环图,是计算机领域里一个比较重要的数据结构。意思是从一个节点出发,沿着箭头的方向,不管从哪个路径走都不会回到这个节点本身。
我们看到在传统区块链,比如比特币和以太坊里面,存储方面是一条主链的结构,按照时间顺序由一个个的区块组成,当一个区块入块了,剩下所有的节点去竞选下一个区块的记账权,从而来获取记账的分红。
我们可以认为,这是一个同步的过程,一是全网同步的去出同一个区块,另外对每一笔交易全网都要去做验证,并且每个节点存储区块链的信息,带来的好处就是保证了严格的一致性。
而DAG里面它改变了这样一个存储结构,它认为区块链里面比特币、以太坊等,每一个块包含了多笔交易,并且基于时间顺序来做的。
在DAG这个网络里面,每一个这样的节点只是一笔交易,不是一个块的概念。后面的一笔交易通过一定的策略,会连到前面的多笔交易上面去,并且会对前面这样一个交易做一个验证。
这样做的好处,就是它把这样一个原来同步的存储改成了异步,理论上来说是支持无限的扩展。TPS也可以无限的大,但是它有一个问题,就是如果有一个节点,后面没有人链接到他,相当于没有人验证他这一笔交易的有效性,就永远得不到确认。
另外由于没有使用强一致性,尤其是智能合约运行的时候,它运行一段时间有可能会导致出现“双花”、不一致的现象,安全性并没有得到广泛的验证。在这种存储结构里,由于比特币和以太坊都是这种存储结构,运行了十年,也没出现问题,它的安全性经过了实际工程的检验。
另外在DAG里,每一笔交易之间的溯源,因为它的图复杂度极高,和区块链里单链的结构来比,它的复杂度极高。
二层扩容
其中的逻辑是把链分成两种,原来的链还是比特币、以太坊的主链,但另外又生成了侧链,将复杂的交易和频繁的交易放到链下,最终的确认放到主链上去做,这样做的好处就是减少了主链的压力。
但最后总体的性能瓶颈很明显还是主链,最高像以太坊来说也就是15,对性能的提升很有限。
Algorand是图灵奖得主Micali提出公链的设计方案,他认为这个方案突破了“不可能三角”,共识算法采用了VRF+POS+BA*的算法。
它的设计的思路是,比特币和以太坊里每一笔交易要全网广播、全网做验证,这里只是随机选出来一小部分节点,让一小部分节点去做出块的提名人、验证人和出块节点。
共识的范围降到了几个节点之间,用一些算法保证节点选取的随机性,得到了一定的安全保证,所以说加快了交易的吞吐量。但是这个方案目前并不完善,可扩展性也是有限的,它的理论值是2000,但最终的理论值是200,实测会到1000左右。
Dfinity是另外一个从共识方法上去改进区块链可扩展性的一条公链,一度被认为是区块链的3.0。它的思路和Algorand有点相似,也是将整个网络选举出一小块的局域的几个节点,在这个节点之间再选出共识的委员会,在这个委员会用了BLS多签的方法出块。
一定程度上来说,两个方面,一是共识组由全网变成局部的网络,第二是在共识的方法上做了创新,用了BLS多签的方案,也是提升了交易量。
分片技术(Sharding)
和前面两个共识相比,随机选取一小个节点来说,就更近了一步。在比特币、以太坊里性能取决于单点的性能,加入的节点越多,网络没有更好,反而更坏。
是不是存在这样一种方案让它可以并行?比如说把它切分到一块,这就有了分片技术。分片是数据库里面的概念,提供数据库横向扩展的方法,通过将数据库切分到不同的数据库上,来提升服务器对数据库访问IO的可扩展性。
把分片用在区块链里面,通过一定的机制和方法,将整个区块链网络分成若干的共识组,每个共识组交易量之和,就是整个这条链的整体吞吐量。
这个地方设计了几个重点,第一是如何进行共识组的选举?选出来的共识组,如果里面有大量的拜占庭节点(可以理解为坏的节点),相当于在这个节点组里安全性受到极大的挑战。
另外,就是分片的大小是不是合理。如果分片太小了,几个拜占庭节点有可能影响分片的安全性。如果分片太大,影响片内的交易太多,也会影响一定的吞吐量。当然,分片太小还有一个问题,就是跨片的交易会多,跨片的交易还不如原来的一个网络。
分片技术目前分为三个:网络分片、交易分片和状态分片。
交易分片是在网络分片的基础上去实现,通过将整体网络分成若干分片,每个分片并行进行交易,但是全网所存储的还是一个账本。
每个节点的存储压力依然是存在,状态分片的好处就是每个分片只存储本分片的部分账本,这样的话从交易和存储两方面去提升它的扩展性。随着分片的越多,整体网络性能也就越大。这也是OK公链选择的方式,也是我们选择分片的原因之一。
这是我们的设计目标,我们在“不可能三角”这个理论下做的一些工作。保证一定的去中心化和一定安全的前提下,去提升公链的可扩展性。其实在比特币和以太坊里面,也尝试过有很多其他的方法,比如说是增加区块的大小,一个区块是不是能打包更多的交易,第二个是缩短区块的出块时间,时间缩短。但是这些方案一是有一定问题,二是对性能的提升也极其有限。
五大角度解读OK公链技术选型
关于OK公链的技术选型,我们选择了这样的分片技术,理由有二:
- 它能够从存储和交易两个方面去提升区块链的可扩展性;
- 它的理论模型并不复杂,在可推导的理论模型里面,我们能证明它是能满足一定的去中心化和安全性,并且还能够对可扩展性做一定的提升。
它的难点我们在前文已经介绍了,而且其在工程上也是非常复杂,目前在整个业界里还没有一个公开出来的分片技术。
我们可以从网络分片、交易分片、状态分片、片内共识、分片伸缩等五个方面来具体解释和了解。
网络分片
在P2P网络里我们分成了若干的共识组,在每个共识组里再去运行一定的共识机制。这些共识组内有一个Leader节点。
我们再把这些共识组分成两类:一是委员会、二是普通分片,也可以称之为交易分片。
委员会扮演两个作用:一是对整个网络进行管理;二是管理自身委员会内部的成员。而所有委员会的内部成员,可以分为三种:委员会的成员、分片的矿工、普通矿工。
逻辑上比较复杂的是,究竟如何选举委员会、如何进行分片,来保证整个公链的安全性,同时实现片内的交易更多,跨片的交易更少?
这里共分为4大阶段,首先是准备阶段。
我们定义为一个epoch(在下面有两个管理区块,两次委员会的轮替之间的间隔)一个epoch结束时,各分片统计本分片内符合条件的账户作为侯选矿工,上报给委员会。
这是为了防止女巫攻击,我们使用了PoS股权证明的方法,每一个参与挖矿的矿工,必须交一定的保证金,这样想注册大量矿工节点去执行拜占庭攻击的时候,成本会有一定的提升,这也是我们对安全性的第一步保证。
其次分别是开始和POW阶段,委员会收集到矿工的集合,然后广播竞选的消息,各个矿工开始计算自己的PoW,并将计算结果提交给委员会,此处计算PoW不是为了挖矿,只是为了算随机值,作为分片和选举的依据。
最后是确定阶段,委员会搜集到PoW的消息,按照哈希值的排序选出新的委员会节点和分片节点(哈希值最小的节点是委员会的节点),并且将竞选结果写入管理区块,这个管理区块是在委员会里面进行共识,全网广播,同时宣布新一轮的epoch开始。
这里我们需要着重强调的有几个地方。第一,我们用了PoS来抵制女巫攻击;第二,PoW不是进行挖矿,只是计算随机值,对资源的消耗也比较少一些。
交易分片
进行网络分片只是第一步 ,只有实现了交易分片,才能使各个分片能并行处理,减少冗余计算和增加整个系统的吞吐性。
在交易分片里面会涉及到两方,一个是发送方,一个是接收方。我们采用的方法就是以发送方的地址进行分片,这样的好处就是发送方进行双发消息的时候,交易在同一个区块里进行打包共识,很容易被发现,一定程度上是让双花攻击的难度变大。
同时,我们允许一个用户用一对公钥在每一个分片里面创建账户(可以简单理解为一个用户用一个公钥可以在每一个分片里面建账户,文章后面我们会介绍它的好处)。
状态分片
状态分片里面的设计思路,是让片内的交易逐步增多,让跨片的交易逐步减少,而并不是排斥这种跨片的交易。一个跨片交易所执行的步骤,就是分片a和分片b,分片a里的用户a和分片b里的用户b进行交易,有两个步骤减少a的余额和增加b的余额。
现在,我们提出了一个支票的概念,就是分片a里出块以后,通过一个“支票”发给分片b处理,分片a在出块以后通过一个区块,会发出支票的消息。
在这个里面有三个分片,分片a、分片b和分片c,其中有三个是跨分片交易。为了减少通信复杂度,在区块里面,每个分片相关的交易会打包成一个支票区块。
将多笔支票打包成一个支票的区块,发给分片a和分片b,分片b里面两笔支票打包成一个支票区块,发给分片b,c里面有一笔,这样的话整个系统在跨分片交易的时候,通信复杂度是O(n)方,在跨分片交易足够少,因为分片也不会特别大,这是一个很容易实现的方案。
另外,我们在存储上面使用了双链的结构,每个分片内存储两条链,一个是状态区块,一个是交易区块,交易区块是只存储本分片的交易,而状态区块它是由交易区块和支票区块派生而来的。
那一笔跨分片的交易是如何进行的?我们将其分成了两个阶段:
- 假设a和b之间转账,这里有一个分片派生出来三个“支票”区块,分别是C12和C13、C21和C23,C31和C32,六个跨分片的支票区块和三个交易区块;
- 通过广播将支票区块发送到对应的分片里去,对应的分片接收支票区块,通过交易区块和支票区块生成最终的状态区块。
另外,分片里面智能合约和以太坊里面的智能合约有不一样的地方,就是它有跨分片的智能合约调用。
如何理解跨分片的智能合约调用?
首先,调用分片2里面的交易区块,锁定账户余额,发送调用信息到分片b,分片b调用相应的合约,修改合约的状态,收取交易的gas费用,将剩余的gas费用返回给分片1,涉及到三次更新和两次的跨分片交易。
为了减少跨分片调用,我们在设计的时候,只支持分片内的调用,而不支持跨分片的调用。原因是相互关联、相互调用的合约不会部署在同一个分片上,这对于开发者来说是比较合理,也是容易做到的。
另外用户可以在任意分片里创建自己的账户。比如说分片1里的用户,要想调用分片2里合约的话,可以在分片2里面去建账户,把跨分片变成了一个片内智能合约的调用交易。这从一定程度上我们希望把相关的业务都放在一个分片里,这样相关性越高,片内交易也就越高,并发性也就越好。相当于我们支持了一个片内的合约调用:用户到合约、合约到合约、合约到用户。
还有一个方法是在分片2里建一个用户,我们可以用跨分片的交易来做到。首先分片1里面的用户,调用分片2里的合约,给分片2里面的用户做一笔转账交易,然后分片2里面的用户再调用这个合约,这就是跨分片之间智能合约的调用的流程。
片内共识;
分片技术有一个值得注意的点,每个分片里节点数是固定的,比较方便用其他的共识算法。缺点是它存在51%的算力的攻击,因为它是一个开放的网络,谁都可以动态接入、动态退出,而分片里面每一个分片的用户数是一定的,比较方便用其他的共识算法,比如PBFT算法的好处,第一它能抵三分之一的拜占庭节点,它的网络依然能保证安全运行。
我们进一步改进了PBFT。首先,Leader打包一个区块(我们前面介绍的分片里面都有一个Leader的角色,PBFT共识里面需要有一个Leader,他是负责发起共识的一个发起方。),广播给其他节点,每个节点去验证这个区块,验证通过的其他节点再广播这个区块摘要。
如果一个节点收到2f+1(f是容忍的拜占庭节点的个数)个其它节点发来的摘要都和自己相等,就向全网广播一条Commit消息,即可提交新区块及其交易到本地的区块链的状态数据库。在这里,我们可以告诉他们通信的复杂度,假设节点数是n的话,这个复杂度就是O(n²)方。
另外,我们用了BLS的签名,有两个特点。一是聚合、一是短签名,可以将多笔交易聚合成一个签名,这样把消息通信的复杂度和存储签名的大小做到了降低,而且不需要进一步通信就能生成一个多重签名,减少通信的次数。
我们改进了PBFT的算法,这里的逻辑首先同样是Leader打包区块,广播给其他的节点,每个节点来验证这个区块,验证通过区块签名发送给Leader。
leader收集到2f+1个签名之后,可以聚合成一个多重签名sig1,leader将sig1和sig1参与方bitmap1广播给其他节点,其他节点对sig1和bitmap1的合法性进行验证。
为了确保全网账本一致,还需对block+sig1+bitmap1进行一轮多签;leader收集到2f+1个签名之后,可以聚合成一个多重签名sig2。leader将sig1,sig2和对应的bitmap2发送给其他节点,其他节点验证通过后将block+sig1+bitmap1写入账本,通过改进PBFT的算法,将消息的复杂度从O(n²)方变成了O(n)。
还有一个就是Leader的轮替,如果Leader是拜占庭节点的话,会阻碍区块的产生,常用方案第一个是Round-Robin顺序选取的方法,一个是VRF生成随机生成区块。
分片伸缩;
在分片里比较难的就是分片伸缩,这里有两个操作:一是新增分片,一是冻结分片。
新增分片的时候,各个分片会出现负载过重的情况,网络中有足够多的矿工可以安全性的去维护这个分片,达到一个新分片所安全运行的理论值,这个时候我们通过线上的委员会的监控和线下社区的投票,由委员会修改参数,来增加这分片。
冻结分片是在状态分片里比较难做的,相当于在每个状态分片里,每个分片存储的局部账本,如果一个分片砍掉的话,这个分片里的账本有可能失效。
在这种情况下,每个分片的节点少,不满足安全性的时候,也是通过委员会和社区共识之后,该分片迁移到其他分片。这个分片里面的账本由委员会来维护。下一次新建的时候再有委员会交给分片,这从一定程度上保证了全局账本的一致性。
【OK区块链导读】清华X-LAB区块链公开课上,OK区块链工程院负责人SHINE JIANG现场讲述了OK公链(OKCHAIN)的创新架构设计和实现其高性能的解决方案:
当前,比特币以太坊等为代表的传统公链,每笔交易都需要全网验证和存储,可扩展性受到很大的限制,导致目前的区块链底层平台上很难支撑大规模的应用。
而OK公链的设计理念就是在保障安全性和去中心化的提前下,提升区块链的可扩展性。设计上OKCHAIN采用多链状态分片方案和基于BLS多签方案的改进版PBFT快速共识算法大幅提升可扩展性和交易处理能力。
此外,OK区块链工程院技术负责人SHINE JIANG还表示,我们要抛开“浮躁”的讨论(比如颠覆互联网、下一代技术革命等等),从技术层面出发,研究一下区块链有哪些技术的特点,为什么会受到这样的关注,它目前的一些制约点是什么,以及现今在技术研究上都有哪些进展。