作者:John Otander,以太坊核心开发人员;翻译:金色财经xiaozou
这篇文章的灵感来自于以太坊常使人Vitalik在最近的 Reddit AMA 中的回答。
Vitalik指出,适度提高Gas Limit是合理的,Gas Limit已经近三年没有增加,这是该协议历史上最长的时间,。Vitalik还做了一些简单的计算表示将以太坊Gas Limit提高到4000万。
本文讲述了为何说提高以太坊Gas Limit比较困难?提高以太坊Gas Limit带来的风险,以及相关解决方案。
1、Gas Limit(Gas限制)
Gas limit决定了一个区块内的工作完成量,因此决定了每个区块可以执行多少交易。提高gas limit将使以太坊能够处理更高的交易吞吐量或更复杂的交易。一直以来,具体的gas limit设置受矿工/质押者影响,并且多年来限额一直在增加。下图来自etherscan.io,显示了gas历史用量(非常接近gas limit,所有限额增加都被市场消化掉了)。
2、风险
现在提高gas limit涉及到几个风险。
(1)漏块率
我在之前的文章中提到,叔块率(uncle rate)是评估gas limit增加时讨论最多的一个指标。现在,在以太坊合并之后,再也没有叔块了。我们要想知道节点是否能很好地处理了当前的gas limit,唯一的方法就是看漏块率。但这个指标是有瑕疵的,因为它只显示当前供应不足的节点。它并没有提供给我们一个很好的指标来显示gas limit的增加,而且它只显示了平均情况,而不是在攻击中可能发生的最坏情况。
(2)状态大小
区块18418786(2023年10月24日)的账户快照为10.33GB,存储快照为76.59GB,因此整体状态大致为87GB。区块17419840(2023年6月6日)的状态略小于80GB。这意味着状态在4个月内大约增长了7GB,也就是说每月增长约2GB。
如果我们使用87+(2*12*#年)来推断,一年后的状态将是111GB,五年后将是207 GB。这里的问题不在于大小。每个人都可以存储这么多的数据,但是访问和修改这些数据却会变得越来越慢。
这还只是快照,是一般状态。Geth还需要以不同的形式存储此状态,以便验证状态根。区块18418786的另一种状态存储形式(trie节点)大约需要180GB。
因此,目前仅用于状态存储的总空间大小约为267GB。如果我们提高gas limit,状态大小会增长得更快。
状态增长的问题在于,与过去不同,我们没有明确的途径来移除状态。没有我们可以迅速实施的具体的状态期限建议来让我们摆脱不断增长的状态。
(3)历史规模
在我2021年的一篇文章中曾提到,一个完整的geth节点大约为350GB(新修剪的)。大约三年过后,一个完整的geth节点(在pbss上)超过900GB。下图显示了交易的总累积量。从中很容易看出,交易量在三年内增加了一倍多,从大约9.8亿笔增加到超22亿笔。
随着L2的崛起,历史规模已经成为一个更大的问题,因为它们现在(在4844上线之前)存储数据的方式是calldata。区块18418786的块体超过427GB,区块17419840(同样是4个月前)的块体为339GB,这意味着4个月内增长28GB,也就是说大约每月增长9GB。我们可以用427+(9*12*#年)来推断这种增长,即一年后为535GB,五年后为967GB(再次假设为线性增长)。
希望在EIP-4844上线后,这种增长会放缓,届时L2将停止使用CALLDATA来获取数据可用性,并转为使用几周后到期的blob。
EIP-4444将解决历史增长问题,因为全节点不再需要存储所有历史。实现EIP-4444需要一个可靠的网络来检索历史,然后我们才能使全节点停止历史数据服务。
(4)同步时间
Gas limit在很多方面都可以影响同步时间:
· 完全同步变得很慢,一个geth节点需要一周多的时间才能完全同步链,其他客户端已经优化了更好的完全同步模式。
· 同步历史数据比较慢。因为我们需要下载更多的数据,所以同步历史数据部分就会比较慢。
· 快照同步状态比较慢,因为我们需要下载的状态更多了。
· 快照恢复较慢。由于pivot point(枢轴点)在快照同步期间移动,因此我们在磁盘上有许多需要修复的不完整状态。如果pivot移动更频繁,并且每个块有更多的更改,那么该修复阶段就会变慢。
· 由于节点需要通过更多的更改才能形成区块头,因此与链同步的速度会更慢。
(5)客户端多样性
构建一个新的EL客户端本身就是一项艰巨的任务。增加gas limit还有一个额外的缺点,那就是会使构建客户端并优化以供主网使用变得更加困难。Geth已经开发了10多年,进行了大量优化。可能存在相反的观点,认为新客户端可以借鉴现有客户端,不再犯同样的错误。
然而,我们已经看到了两个客户端(用python编写的Execution Specs和使用javascript编写的EthereumJ)的主网困境。这也意味着现在使用某些语言编写的客户端行不通了。受限于语言开销和代码库的成熟度,增加gas limit将让一些客户端掉队。
我们在KZG中也看到了这一点,为了获得所需的性能,大多数客户端依赖于调用C-KZG(一个用C语言编写的代码库),而不是使用用他们所选的语言编写的库。
(6)最差情况
在考虑gas limit时,我们不能只看一般情况。我们总是要考虑最差的情况。当然,当链处于平均负载情况下,节点可能会运行得很好,但是如果突然连续5个块的磁盘I/O增加一倍会发生什么?
运行时间并不是我们需要考虑的唯一指标,如果攻击者可以占用其他资源,如磁盘I/O、CPU时间或内存,他们可能会迫使较低配置的机器脱机。特别是在以太坊合并后,在同一台机器上运行两个客户端,攻击其中一个客户端可能也会让另一个客户端状态不稳定。在以太坊合并测试的早期,我们目睹过几次这样的情况:一个客户端的内存泄漏会导致整个系统崩溃。
另一个需要考虑的最坏情况是证明大小(proof size)。随着gas limit的增加,两个区块之间可能发生的潜在状态变化也会增加。这对前面讨论的快照同步是有影响的,但它也会影响执行层轻客户端的证明大小。现在这还不是什么大事,merkle-patricia tree(默克尔-帕特里夏树)的证明太大了,无法通过网络发送。但是,如果我们想要实现在同一台机器上运行多个轻客户端的交叉验证思想,那么证明大小就会非常重要。
3、解决方案
我们就这么完了吗?我们会一直保持30MGas的上限吗?不是的!
在我2021年的一篇文章中,我为当时我们面临的困境提出了解决方案。对于我们在2021年面临的完全同步问题,geth实现了快照同步和快照。对于修剪和数据库布局的问题,geth实现了PBSS。Txpool在处理高交易负载方面变得更加可靠,并且大部分MEV抢跑交易都转移给了建设者。许多交易也转移到了L2,这反过来又增加了主网交易的平均规模。
唯一没有实现的解决方案是regenesis。多年来,人们的观点发生了一些变化,大多数人似乎都倾向于将EIP-4444历史期限作为历史数据增长的短期解决方案。对于EIP-4444的发布,我们需要一个强大的历史数据服务节点网络,这样历史就不会丢失,即使它不再被所有全节点存储(顺便说一句,大多数比特币节点根本不存储历史数据)。
我们至今仍然没有找到一个体面的、现实的状态期限方式。
正如你在上海升级之前看到的攻击,有一些已知攻击阻止了我们提高gaslimit。(据我所知)所有漏洞都已解决了。
在撰写本文时,EIP-4844正在测试网上发布。该EIP将提高节点的存储和I/O需求。在我看来,在尝试任何类型的gas limit增加之前,等等看这一变化对主网的影响是最安全的做法。一旦L2转向Blob交易,我们就应该增加calldata成本(因为在我看来,与数据需要存储的其他东西相比,calldata的价格被低估了)。这也可以作为L2使用blobspace的一个强制函数。
总之,我想提醒大家在考虑提高gas limit时要小心行事,因为它会影响节点的很多方面,有些影响会相对明显。在相关讨论中,考虑gas limit变化的长期和短期影响是非常重要的。