通过限制状态和合约,提高EVM的可扩展性,以实现rollup发展
0xE43a
January 29th, 2022

Increasing scalability of the EVM for rollups by restricting state and contract

原文链接:

译者:Evelyn|W3.HItchhiker

可扩展性挑战的总结

目前以太坊每秒交易量(TPS)的限制很复杂,在一般情况下没有简单的解决方案,与常见的瓶颈(bottlrneck)在共识方或p2p或虚拟机(VM)的选择上的误解不同,长期瓶颈是一个三难问题(trilemma):

  • 访问不断增长的存储的成本,
  • 任意的图灵完全执行的不可预测性
  • 和带宽成本(bandwidth cost)+区块和Tx传播的延时

在这三者中,对当前以太坊主网影响最大的是存储成本——其可扩展性上限受到当前硬件的物理限制,如NVMe SSD的最大IOPS、磁盘内存的缓冲区大小以及磁盘和RAM/CPU管道之间的带宽/延迟敏感性。提高(无状态)执行速度只是这个等式的一小部分,因为无论用什么后端来存储数据,对于不断增长的动态数据集来说,都没有办法实现恒定时间的键(key)/值(value)查询——这意味着依赖于状态查询的操作码的成本随着时间的推移而单调递增。鉴于状态访问不能被并行化(parallelized),而区块生产对延迟高度敏感,对这种状态的无限制计算构成了一个重大的扩展挑战。

下面这张由EF的Martin Swende制作的图表显示了在geth完全同步的情况下EVM的大部分执行时间,以及随着 trie大小的增加,其影响的增加情况。

观察底部的图例,不难发现,随着时间的推移,增加最多的是存储-读取和账户-读取的成本。因此,现在以太坊的整体区块gas限制受最坏情况下的 "长期攻击 "影响最大,即有人通过在每个区块中使用价值30m gas的状态来更新,并且尽可能地膨胀状态。

有一些研究活动和建议以更全面的方式处理存储开销和其他限制,例如将存储成本与执行成本和带宽分开,而不是通过同一gas以相同的方式定价[1]

对特定应用的EVM链进行优化

然而,对于EVM链的具体应用实例,如rollup结算中心,可以采取一些捷径来大量摊销这一成本,并消除最坏情况下的大量攻击,这些攻击需要对执行进行保守的限制来缓解。

限制合约集以防止状态膨胀

在使用EVM作为结算中心的情况下,通过有一套固定的经过良好分析的桥接合约来限制状态访问/写入的类型,能够限制一个tx中可能发生的写入量,与它的gas限制无关,从而大大增加TPS,而不用担心节点无法跟上或状态膨胀到节点变得几乎不可能可靠地运行(正如BSC[2]所发生的那样)。

降低状态访问成本

当前版本的以太坊协议的状态访问成本是由于当前 trie的大规模的状态,超过 150GB,包含数千万个键(key)/值对(value pairs)。通过启动一个新的链,对单个区块或交易中可访问的状态进行合同强制限制,并限制每个区块可增长的状态,我们可以减少至少50%的状态访问成本,并在比主网更长时间内保持低水平。

通过可预测的访问来缓存开发

一个存储层面的改进很容易被利用,并且已经在EVM中实现了,那就是 "访问列表(access lists)"[3]——一种缓存/磁盘访问的优化,你指定了TX要访问的地址和存储键,这些访问会变得更便宜——但如果出现缓存缺失,它们又会恢复到更昂贵的价格。在正常的图灵完整合约——可以调用任何东西的EVM,在一般情况下很难提前预测这些存储键,但在有限的枢纽中,这使状态访问确定化并安全地增加tx的吞吐量成为可能。

在全节点和轻型客户端软件中预装的合同

有一种状态访问比从存储中的正常SLOAD具有更高的负载影响,那就是调用到另一个合约的行为。在撰写本文时,最新的以太坊协议版本允许合约的代码大小达到24kb——这意味着任何*CALL操作码或任何强制读取该状态的操作码,如EXTCODEHASH或EXTCODECOPY,会导致读取高达24kb的数据——这也增加了轻客户端的负载影响,因为他们不仅仅需要请求Merkle证明到N个存储槽,还可能需要K 24kb合约字节码。这可能会成为网络上的巨大开销,考虑到外部账户调用操作码会便宜到2600gas——远远低于用SLOAD加载24kb的成本,后者将是160万gas。

通过限制用户能够部署的任意合约(arbitrary contract),这个攻击媒介也被移除,因为固定的部署和可部署的合约集可以预装在创世文件(genesis file)中,或在一个辅助存储中,只在协议版本更新时更新。因此,一个轻客户端总是默认拥有呼叫目的地的代码,而不需要从网络上请求。即使在我们允许用户在通过工厂合同创建新合同的情况下,通过要求代码哈希(codehash)保持不变(限制工厂只能初始化状态)也可以避免传播开销(propagation overhead)。tx可以在访问列表中包含一个代码哈希,该代码哈希类似于在该地址部署的预加载字节码(preloaded bytecode)。

委托的安全性和数据可用性

当然,还有三难问题的第三个支柱,即传输、处理大区块和交易的传播延迟影响,但这是一个短暂的成本——传播一个大区块时有可能只是在传播的那个时候拖慢网络,但不一定会成为所有未来节点的负担。例如,如果区块只是通过简单的存储哈希值来rollup提交大量的calldata,那么calldata不能被智能合约引用,因此人们不能强迫全节点通过tx执行来检索它。所以它是一个在传播时刻有延迟影响的区块,但执行、存储和同步成本很低。这些短暂的成本更容易处理,特别是在不需要有那么多节点来支撑安全性的链中,比如建立在Celestia上的链,将安全和数据可用性委托给Celestia链。

此外,在可能的交易空间中拥有一个受限的领域的话,可以防止出现决策问题,即优先选择rollup txs,而对普通txs进行定价,正如geth团队对EIP-4488[4]的评论中所说的一样。

具体来说,我们担心EIP-4488由于方案的二维(2-dimensional)性质,会对rollup交易有很大的偏爱(favor),以至于非rollup交易无法使用区块链。EIP应该提出更多的证据来证明情况不会是这样的。

目前,EIP-4488试图通过以允许小于300字节的交易来保持使用平衡,即使已经达到了区块大小的限制。虽然这个例外允许简单的值传输与数据量大的rollup交易一起出现,但任何大于300字节的交易都需要比所有rollup交易的区块空间大。

由于结算中心只针对rollup txs和支持承诺,这对中心的设计并不构成机制问题。

一个特定应用的EVM是可以防欺诈的

上述所有的优化组合进一步实现了另一个理想的功能:通过中间状态根(ISRs)提供紧凑的欺诈证明,这也可以提供给轻客户端,而轻客户端不需要潜在地请求100MB以上的状态,就能够对照两个状态根检查欺诈证明。对写入和访问的限制,合约部署,以及一个tx可以访问多少状态的可预测性,无论其gas限制如何,都可以实现这些高效的单轮中间状态根欺诈证明(single-round intermediate state root fraud proofs),并删除2/3ds诚实的多数对轻型节点的要求——这很重要,因为一个特定应用的EVM链/中心可能会有一个较低的验证者或区块生产者的总数,而不是像以太坊那样需要提供自己的共识安全。

可扩展性 + 灵活性 + 易于集成 & 可扩展性

通过使用受应用限制(application-restricted)/应用优化(application-optimized)的EVM链,我们获得了两全其美的效果,虚拟机链的灵活性,其行为可以仅仅通过编写智能合约并通过协议升级(例如通过DAO投票)来启用,并且让这些合约与更广泛的EVM生态系统的标准、工具、程序库等兼容,但有能力化解完全不可预测的执行所带来的最大问题。

由于上述优化,为充当枢纽而定制的特定应用EVM将能够比不受限制的以太坊协议更好地扩展,在相同数量的区块gas中,rollup txs的TPS可能会高出2或3个数量级。

References

[1] Should storage be priced separately from execution? - Economics - Ethereum Research 16

[2] https://github.com/binance-chain/bsc/issues/553 8

[3] EIP-2930: Optional access lists 2

[4] https://notes.ethereum.org/EH_xVCD8SnaLCEDrXxUyYA 6

Arweave TX
4EuEKAPozgDpUAvS_mkZ7LyWUqoXN_O_64ov8bpGnjE
Ethereum Address
0xE43a21Ee76b591fe6E479da8a8a388FCfea6F77F
Content Digest
EvtC0fuaAWBVgqt0kPajD5_ZsAh9vkaofq69R9KiB9w