吐槽C位以太坊的设计

(图片出自网络,版权归原作者所有)

我以前写过一篇名为

《区块链历史中的过度产品——Ethereum》

的文章。

在那篇文章里,我从共识机制的角度,分析了采用POW共识机制作为公链共识机制的以太坊,注定只是区块链发展进程中一个重要的过渡产品。

从发布那篇文章到现在差不多一个月的时间。在这一个月的时间里,由于播客链的需要,我再次仔细阅读了以太坊的代码。这次得出来的结果依然是——以太坊无法支撑大量的并发业务。换言之,以太坊几乎无法作为基础链推广到商业级别的应用。

为什么这么说呢?今天我就从以太坊的挖矿机制上来说一说。

首先我们来说一说以太坊是如何做到数据同步的。

这个问题,网上有各种答案,似乎都有道理,又都有缺陷。到底该听谁的?其实看看以太坊的代码就很清楚了。

以太坊的区块中记录的是一个个的交易信息,一个区块能够保存多少交易取决于这个区块的GasLimit的值。

这里需要注意的是,这个GasLimit有两个用法:第一个是针对账户(普通账户/合约账户),说明这个账户愿意为一次交易付出的最高的Gas消耗。第二个是表明一个区块能够存放多少交易。因为每次交易中都有Gas的,所以一个区块能保存多少交易,其实就是这些交易的Gas之和不能大于这个区块的GasLimit。

在以太坊中,有一个“交易池”的概念,交易池是将所有未打包的交易全放在里面。

这个交易池的存放规则是:按照每个人愿意付出的交易Gas来进行排序,同时按照每个交易的Nonce来顺序存放。

Gas,大家都是知道的,但大家可能不大理解Nonce。

这个Nonce类似于Tcp网络传输中得到SegmentIndex,其实就是针对每个账户的一个顺序值,有了这个顺序值,可以避免一个交易被执行多次,还可以避免交易的乱序。

到此为止,我们大致了解了一下以太坊中关于交易的基本概念:在以太坊的交易池中按照一定的规则对于交易进行排序。挖矿协程从交易池中获取交易,将这些交易进行验证,放到区块中。

这个过程看似没有什么问题,可是我觉得这个地方存在很大的设计瑕疵。

我们来走一遍挖矿过程。

以太坊启动一个挖矿协程,这个协程判断交易池中是否存在交易:如果有交易,这个协程就从交易池中获取交易;如果这个交易的to字段为空,说明是创建合约交易,就去创建合约;如果这个交易的to字段不为空,就调用虚拟机,将参数传递给虚拟机,让虚拟机执行这次交易,从而验证这次交易的合法性。等待这次交易如此操作完以后,下一个交易再执行相同的步骤,重复上面的过程。

大家发现没有:这个过程都是由一个单协程进行处理。这样做的确保证了交易的顺序性和处理的简单性,却为此付出了性能的代价。

另外,由于合约是外部写的,执行合约的时候极有可能出现一个合约执行过程过长,导致后续的交易被卡住的情况。

为了解决这些问题,以太坊人为地做了很多限制,例如:每个账号在交易池中只能有16笔交易同时存在,如果超过16笔,就会按照Gas进行排序后,抛弃Gas最小的一个。还有,每个交易在合约中的执行深度不能超过1024个,如果超过,就直接判定为此交易失败。

这些限制,都是简单粗暴的。解决问题的同时,埋下隐患。

怎么从根本上解决这个问题呢?

每个做高并发服务端的人都会有自己的理解。播客链的大致方法是:

首先,制定合约相互调用的限制规则,因为现实情况下很少会出现一个账户去调用一个完全不相关的合约。

其次,对交易池重新进行设计,按照更加丰富的规则进行交易池排序处理。

最后,启动多个打包(播客链采取Dpos共识)协程,并将交易数据按照一定规则进行协程区分,实现交易不乱序的处理方式。

由于今天主要说的是以太坊的挖矿设计问题,所以我对播客链处理过程只是简单地说明了一下,并没有详细的书写具体处理方法。

以后我会找更多机会分享播客链的处理方法。

希望播客链的探索,能为区块链的发展打上一个精致有用的补丁。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180814G1XRDC00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券