有了这篇博客文章,其目的是正式披露对以太坊平台的严重威胁,直到柏林硬币直到柏林硬福克)是一种明显的危险。
状态
让我们从以太坊和状态的一些背景开始。
以太坊国家由一个前缀树的Patricia-Merkle Trie组成。这篇文章不会详细地介绍它,足以说,随着状态的成长,这棵树中的树枝变得更加密集。每个添加的帐户是另一片叶子。在树的根和叶子本身之间,有许多“中间”节点。
为了在这条巨大的树上查找给定的帐户或“叶子”,需要从根部通过中间节点解决6-9哈希的某个地方,以最终解决最后一个导致的哈希我们正在寻找的数据。
简单地说:每当执行Trie查找以查找帐户时,都会执行8-9个决心操作。每个解析操作都是一个数据库查找,每个数据库查找可以是许多实际磁盘操作。磁盘操作的数量很难估计,但是由于TRIE键是加密哈希(抗碰撞),因此键是“随机的”,对任何数据库都击中了确切的最坏情况。
随着以太坊的成长,有必要提高进入Trie的运营的汽油价格。这是在 橘子哨子 在街区 2,463,000 2016年10月,其中包括 EIP 150。 EIP 150积极地提高了某些气体,并引入了一系列的变化,以防止DOS攻击,在所谓的“上海袭击”之后。
在 伊斯坦布尔 升级,在街区 9,069,000 在2019年12月。在此升级中, EIP 1884 被激活。
EIP-1884介绍了以下更改:
- Sload 去了 200 到 800 气体,
- 平衡 去了 400 到 700 汽油(更便宜 自我平衡)添加,
- ExtCodeHash 去了 400 到 700 气体,
问题
2019年3月,马丁·斯文德(Martin Swende)正在做一些 测量 EVM OpCode性能。该调查后来导致了EIP-1884的创建。在EIP-1884上线之前的几个月,纸 破碎的仪表 出版(2019年9月)。
两名以太坊安全研究人员 – 休伯特·里兹多夫(Hubert Ritzdorf)和马蒂亚斯·埃格利(Matthias Egli) – 与纸张背后的一位作者合作;丹尼尔·佩雷斯(Daniel Perez),并“武器化”了他们提交给以太坊虫子赏金的漏洞。这是2019年10月4日。
我们建议您阅读 提交 完整地是一份写得很好的报告。
在专门针对跨客户安全的渠道上,Geth,Parity和Aleth的开发人员在同一天被告知提交。
利用的本质是触发随机的Trie查找。一个非常简单的变体是:
jumpdest ; jump label, start of loop gas ; get a 'random' value on the stack extcodesize ; trigger trie lookup pop ; ignore the extcodesize result push1 0x00 ; jump label dest jump ; jump back to start
在他们的报告中,研究人员通过同步到Mainnet的节点执行了有效载荷 eth_call,这些是执行时的数字 10m 气体:
- 10m 使用煤气利用 ExtCodeHash (在400天气)
- 10m 使用煤气利用 ExtCodesize (在700天气)
显然,EIP 1884的变化肯定在减少攻击的影响方面产生了影响,但还远远不够。
这是在大阪的Devcon之前。在DEVCON期间,Mainnet客户开发人员共享了有关该问题的知识。我们还遇到了休伯特和马蒂亚斯,以及格雷格·马克(Greg Markou)(来自Chainsafe – 正在从事的工作等)。 ETC开发人员还收到了报告。
随着2019年的结束,我们知道我们的问题比以前预期的要大,恶意交易可能会导致分钟范围内的障碍。为了进一步加剧困境:开发人员对EIP-1884不满意,而EIP-1884使某些合同流失了,用户和矿工都非常渴望增加升降机的气体限制。
此外,仅两个月后,2019年12月,以太坊 宣布 他们离开现场,OpenEthereum接管了代码库的维护。
创建了一个新的客户协调渠道,Geth,Nethermind,OpenEthereum和Besu开发人员继续进行协调。
解决方案
我们意识到,我们将不得不采取两管制的方法来解决这些问题。一种方法是处理以太坊协议,并以某种方式在协议层解决此问题。最好不要违反合同,而不是不惩罚“良好”行为,但仍设法防止攻击。
第二种方法是通过软件工程,通过更改客户端内的数据模型和结构。
协议工作
如何处理这些类型攻击的第一次迭代是 这里。 2020年2月,它正式发射为 EIP 2583。它背后的想法是每当Trie查找会导致错过时,请简单地增加罚款。
但是,彼得发现了这一想法的工作 – “屏蔽接力”攻击 – 将上限(约800左右)限制在有效的大小上。
问题 对错过的处罚 是否需要首先进行查找,以确定必须施加罚款。但是,如果没有足够的气体罚款,则进行了未付的消费。即使这确实导致了投掷,这些状态读数也可以包裹在嵌套的呼叫中。允许外呼叫者继续重复攻击,而无需支付(全部)罚款。
因此,EIP被放弃了,而我们正在寻找更好的选择。
在迭代这些各种方案的同时,Vitalik Buterin提议仅增加天然气成本并保持访问清单。 2020年8月,马丁(Martin)和维塔利克(Vitalik)开始迭代什么 EIP-2929 及其伴侣, EIP-2930。
EIP-2929有效地解决了许多以前的问题。
- 与EIP-1884无条件增加的成本相比,它仅针对尚未访问的东西筹集了成本。这仅导致 次级增加 净成本。
- 另外,与EIP-2930一起,它不会打破任何合同流程,
- 可以用升高的气体(而不破坏东西)进一步调整它。
2021年4月15日,他们俩都与 柏林 升级。
发展工作
彼得解决这一问题的尝试是 动态状态快照,2019年10月。
快照是将以太坊状态存储在Geth Node实时操作期间,可以完全在线构建的二级数据结构。快照的好处是它充当州访问的加速结构:
- 而不是做 o(log n) 磁盘读取(x LevelDB开销)要访问帐户 /存储插槽,该快照可以提供直接, o(1) 访问时间(x LevelDB开销)。
- 快照支持帐户和存储迭代 o(1) 每个条目的复杂性,这使远程节点能够比以前更便宜地检索顺序状态数据。
- 快照的存在还可以使更多异国情调的用例,例如脱机状态Trie或迁移到其他数据格式。
快照的缺点是原始帐户和存储数据基本上是重复的。对于主网,这意味着额外 25GB 使用的SSD空间。
动态快照的想法已经在2019年中期开始,主要是为了成为推动者 折断 同步。当时,Geth团队正在进行许多“大型项目”。
- 离线状态修剪
- 动态快照 +快照同步
- LES国家通过碎片状态分布
但是,决定完全优先考虑快照,现在推迟其他项目。这些奠定了以后变为的基础 快照/1 同步 算法。它于2020年3月合并。
随着“动态快照”功能释放到野外,我们有一些呼吸空间。如果以太坊网络会受到攻击的打击,那将是痛苦的,是的,但是至少可以通知用户启用快照。整个快照的生成将需要很多时间,而且还无法同步快照,但是网络至少可以继续运行。
绑线
在2021年3月至4月 快照/1 协议是在Geth推出的,可以使用新的基于快照的算法同步。虽然仍然不是默认同步模式,但它是使快照不仅有用的攻击保护,而且是用户的重大改进的一步。
在协议方面, 柏林 升级发生在2021年4月。
在我们的AWS监视环境上进行的一些基准如下:
- 前伯林,没有快照, 25m 气体: 14.3s
- 前伯林,带有快照, 25m 气体: 1.5s
- 伯林后,没有快照, 25m 气体: 〜3.1s
- 伯林后,带有快照, 25m 气体: 〜0.3s
(粗糙)数字表明 柏林 降低了攻击的效率 5倍并通过快照将其降低 10倍,总计 50x 减少影响。
我们估计,目前,在Mainnet(1500万气)上,可以创建将需要的块 2.5-3s 执行 格斯 节点 没有 快照。随着状态的增长,该数字将继续恶化(对于非刺激节点)。
如果使用退款来增加块内有效的气体使用情况,则可以进一步加剧(最大) 2倍 。和 EIP 1559,块气体极限将具有较高的弹性,并允许进一步 2倍 (这 Elasticity_multiplier)临时爆发。
至于执行此攻击的可行性;购买完整块的攻击者的费用将按照几个以太的顺序(15m 气体 100gwei 是 1.5 醚)。
为什么现在披露
长期以来,这种威胁一直是一个“公开秘密” – 实际上,它至少被错误地公开披露一次,并且在ACD呼叫中已在没有明确的细节的情况下被引用了几次。
由于柏林的升级现在已经在我们身后,而且由于Geth Nodes默认情况下正在使用快照,因此我们估计威胁足够低以至于透明度胜过,现在该全面披露幕后作品了。
重要的是,社区有机会了解变化背后的推理会对用户体验产生负面影响,例如提高天然气成本和限制退款。
这篇文章是由马丁·霍尔斯特·斯文德(Martin Holst Swende)和彼得·塞拉吉(Peter Szilagyi)撰写的2021-04-23。它与其他基于以太坊的项目分享了2021-04-26,并公开披露了2021-05-18。