主页 > imtoken官网下载教程 > 转危为安:柏林升级前对以太坊的回顾显而易见

转危为安:柏林升级前对以太坊的回顾显而易见

imtoken官网下载教程 2023-04-13 07:29:37

与无条件增加gas成本的EIP-1884相比,柏林升级中的EIP-2929只增加了未访问部分的gas成本,当前网络威胁已经大大降低。

这篇博文的目的是正式揭露柏林硬分叉之前以太坊平台的一个严重而明显的问题。

状态

让我们从以太坊的背景和它的“状态”说起。

以太坊的状态由 patricia-merkle trie 组成,这是一种前缀树。 本文不会涉及技术细节。 简单地说,随着状态的增长,树的枝条会越来越密。 每个加入的帐户都是一个新的叶子。 根与叶之间,有大量的“中间”节点。

为了找到一个特定的账户,或者说这棵巨树中的一片“叶子”,从树的根部开始,通过中间节点,需要解6-9次哈希,才能最终计算出我们要找的数据的哈希值.

简而言之,对于每个查找帐户的 trie 查询,都会执行 8-9 次解析操作。 每个解析操作都是一个数据库查询,每个数据库查询可以是任意数量的实际磁盘操作。 磁盘操作的数量很难预测,但由于 trie 密钥是加密散列(抗冲突),密钥是“随机的”,这对任何数据库来说都是最坏的情况。

随着以太坊的发展,一直需要提高树访问操作的gas费。 2016年10月,“上海袭击”事件后,以太坊网络在区块高度2,463,000处进行了一次Tangerine Whistle硬分叉,其中包含EIP 150,大大增加了某些操作的gas成本,并引入了大量Change来防御抵御 DoS 攻击。

Gas 费用的另一次增加是在 2019 年 12 月的伊斯坦布尔升级中,该升级激活了 EIP 1884。

EIP-1884 对 gas 费用进行了以下更改:

SLOAD 从 200 增加到 800GAS

BALANCE 从 400 GAS 增加到 700GAS(并添加了更便宜的 SELFBALANCE)

EXTCODEHASH 从 400 增加到 700GAS

问题

2019 年 3 月,Martin Swende 进行了一些 EVM 操作码性能测量。 随后的 EIP-1884 就是基于这个调查。 Broken Meter 在 EIP-1884 激活前几个月发表了这篇论文(2019/9)。

两位以太坊安全研究人员 Hubert Ritzdorf 和 Matthias Egli 以及该论文的作者之一丹尼尔佩雷斯“武器化”了一个漏洞并将其提交给以太坊的漏洞赏金计划。 这是 2019 年 10 月 4 日。

推荐大家阅读他们提交的完整文档,非常详细。

同一天,来自 Geth、Parity 和 Aleth 的开发人员在专门用于跨客户端安全的频道中了解了该文档。

该漏洞的本质是触发随机 trie 查询。 这是一个简单的例子:

在他们的报告中,研究人员在通过 eth_call 同步主网络的节点上执行了这个 payload。 以下是他们执行过程中的数据,耗费了1000万GAS:

消耗1000万GAS的EXTCODEHASH(400GAS)

奇偶校验:~90s

Geth:~70s

消耗1000万GAS的EXTCODEHASH(700GAS)

奇偶校验:~50s

Geth:~38s

显然,EIP-1884 中的更改确实有助于降低此次攻击的影响,但还不够。

它临近大阪的开发者大会。 在开发者大会上,关于这个问题的信息在主网上与客户端开发者共享。 我们还会见了 Hubert、Mathias 和 Greg Markou(来自 Chainsafe,当时他也在做一些 ETC 工作)。 ETC的开发者也收到了这份报告。

随着 2019 年接近尾声,我们知道问题比之前预期的要严重,恶意交易可能会将区块时间缩短到分钟级。 更糟糕的是,开发者社区对EIP-1884不满,因为EIP-1884破坏了一些合约流程,用户和矿工都非常渴望提高区块的gas limit。

此外,仅仅两个月后,即 2019 年 12 月,Parity Ethereum 宣布停止运营,而 OpenEthereum 接管了代码库的维护工作。

然后建立了一个新的客户端协调渠道,来自 Geth、Nethermind、OpenEthereum 和 Besu 的开发人员继续合作。

解决方案

我们意识到要解决这个问题,我们必须两者兼顾。 一种方法是通过以太坊协议以某种方式在协议级别解决这个问题。 最好不要破坏契约并避免溢出到“良好”行为,但仍要尽量防止攻击。

第二种方式是通过软件工程来解决,在客户端修改数据模型和结构。

协议层的工作

关于如何处理这些类型的攻击的第一个版本在这里。 2020 年 2 月,它正式发布为 EIP 2583。其想法是在 trie 查找未命中时施加惩罚。

不过,Peter 找到了一个对策,“屏蔽中继”攻击,可以有效限制这个惩罚的上限(800 左右)。

惩罚未命中查询的问题在于,首先需要进行查找以确定是否施加惩罚。 但如果剩余的gas不足以支付penalty,则未支付的消费已经执行。 即使它确实导致抛出异常,也可以将这些状态读取包装到嵌套调用中,从而允许外部调用者继续重复攻击而无需支付(全部)惩罚。

为此,这个 EIP 被放弃了,我们正在寻找更好的替代品。

Alexey Akhunov 提出了 Oil 的概念,它是 GAS 的第二来源,但它与 GAS 有本质区别,因为它对执行层是不可见的,可能导致交易全局回滚。

Martin 在 2020 年 5 月也写了类似的提案 (GAS And Karma)

在迭代这些不同的机制时,Vitalik Buterin 提出直接增加 gas 成本并保留访问列表。 2020 年 8 月,Martin 和 Vitalik 开始完善 EIP-2929 及其配套 EIP-2930。

EIP-2929有效解决了之前的很多问题。

与无条件增加gas成本的EIP-1884相比,EIP-2929只增加未访问部分的gas成本。 这导致净成本增加不到一个百分点。

加上 EIP-2930,不会中断任何合约流程

以及在不造成中断的情况下进一步调整天然气成本的能力

2021 年 4 月 15 日,两个 EIP 在柏林升级中被激活。

开发工作

Peter 在 2019 年 10 月提出的解决方案是“动态状态快照”。

快照是用于以平面格式存储以太坊状态的辅助数据结构,可以在 Geth 节点实时运行期间完全在线构建。 快照的好处是它们充当状态访问的加速结构:

快照提供直接 O(1) 访问时间(x LevelDB 开销),而不是 O(log N) 磁盘读取(x LevelDB 开销)来访问帐户或存储槽。

快照支持以 O(1) 的复杂性对每个条目的帐户和存储进行迭代,这使远程节点能够比以前更便宜地检索顺序状态数据。

快照还支持更多奇特的用例,例如离线修剪状态尝试或迁移到其他数据格式。

快照的缺点是原始帐户和存储数据被有效复制。 对于主网,这意味着额外的 25GB SSD 空间。

动态快照的概念从2019年年中开始,最初的目的主要是为了推动快照同步的实现。 当时 Geth 团队正忙于许多“大项目”。

离线修剪

动态快照+快照同步

通过sharding state实现LES(Light Ethereum Subprotocol)状态分布

然而,最终决定优先考虑快照并暂时搁置其他项目。 这构成了后来于 2020 年 3 月合并的 snap/1 同步算法的基础。

随着动态快照功能的发布,我们有了一些喘息的空间。 如果以太坊网络受到攻击会很痛苦,是的,但至少可以通知用户启用快照。 完整的快照将花费大量时间,并且当时不会同步快照,但网络至少会继续运行。

总结

2021 年 3 月至 4 月,在 geth 客户端中实现了 snap/1 协议,通过一种新的基于快照的算法实现了同步。 虽然这仍然不是默认的同步模式,但这是使快照不仅可用作攻击防御而且对用户来说也是一项重要优化的重要步骤。

协议方面以太坊漏洞,柏林升级将于2021年4月完成。

以下是在我们的 AWS 监控环境中开发的一些基准:

柏林升级前,无快照,25MGAS:14.3s

柏林升级前,带快照,25MGAS:1.5s

柏林升级后,无快照,25MGAS:~3.1s

柏林升级后,使用快照,25MGAS:~0.3s

粗略的数字表明,柏林升级可以将攻击的有效性降低 5 倍,而快照可以将其降低 10 倍,总共降低 50 倍的影响。

我们估计目前在主网(15MGAS)上,不使用快照的geth节点可以创建一个执行时间为2.5-3秒的区块。 对于非快照节点,这个数字随着状态的增长而变得更糟。

如果通过 gas 退款增加区块内的有效 gas 使用量,这可能会因(最大)2 倍的因素而进一步加剧。 随着EIP 1559的实施,区块的GAS limit将更具弹性,并在临时爆发时再增加2倍(ELASTICITY_MULTIPLIER)。

至于进行这种攻击的可行性以太坊漏洞,攻击者购买一整块的成本大约是几个ETH(15MGAS是1.5ETH换100Gwei)。

为什么现在发布?

事实上,这个风险一直是一个“公开的秘密”,不止一次不小心被公开披露,在核心开发者会议上也多次被提及,但并未涉及细节。

现在 berlin 升级已经实施,geth 的节点也默认使用快照同步,我们估计现在威胁很低,是时候全面披露幕后发生的事情了。

重要的是让社区有机会了解一些对用户体验产生负面影响的变化背后的原因,例如增加的天然气成本和对天然气回收的限制。