Sepolia 测试网在 Pectra 升级期间发生意外,原因是 Sepolia 的许可存款合约与 EIP-6110 交互存在问题,攻击者通过发送恶意交易触发该问题。开发团队迅速响应,在数小时内修复并重新部署,网络恢复正常,未丢失最终性。此次事件仅限于 Sepolia 测试网,不会影响以太坊主网。
Sepolia Pectra 事件事后分析
作者:Mario Havel
状态:已解决
日期:2025年3月12日,18:00 UTC
当前状态
Sepolia 测试网已完全从2025年3月5日 Pectra 升级期间发生的事件中恢复。在快速识别问题后,客户端团队协调响应,首先缓解攻击者的持续攻击,同时开发和部署修复程序。在事件发生后的几个小时内,当天晚些时候,网络再次正常运行,处理交易、构建区块和完成最终确认。
事件概述
2025年3月5日,UTC 时间 7:29(epoch 222464),Pectra 网络升级在 Sepolia 测试网上激活。激活后不久,验证者开始遇到交易包含问题,导致产生空块。该问题特别与 Sepolia 的许可存款合约及其与 EIP-6110 的交互有关,EIP-6110 改变了验证者存款的处理方式。Sepolia 运行一个许可的验证者集,该集合由一个自定义 ERC-20 代币控制存款,而不是普通的 ETH。当合约发出意外的 ERC-20 相关日志时,处理来自存款合约的事件的 EL 客户端遇到了问题。在修复问题的同时,攻击者积极地推送触发该问题的交易。核心团队准备了修复程序并协调发布,同时替换导致空块的恶意交易。协调的推出发生在 UTC 时间 14:00,并成功缓解了任何进一步的问题。
请注意,此问题特定于 Sepolia 的测试网配置,不会发生在 Ethereum 主网上。
尽管发生了该事件,网络:
- 从未失去最终确认性
- 继续产生区块(尽管是空的)
- 在问题发生后大约 6.5 小时内完全恢复
事件响应和修复
事件的高级概述时间表,基于开发者聊天记录的详细时间表如下。
Pectra 分叉后识别出问题 (7:30 - 10:30 UTC)
Pectra 在 epoch 222464,UTC 时间 7:29 激活。不久之后,开发者和 PandaOps 注意到空块。客户端日志和区块追踪揭示了处理自定义存款合约的问题。团队加入了紧急呼叫,讨论了修复程序,并确定未经协调的推出将导致链分裂,因此他们安排在 UTC 时间 14:00 一起更新。
修复准备和攻击缓解 (10:30 - 14:00 UTC)
客户端团队开始在其客户端中实施修复程序。go-ethereum 团队的 Felix 开发了一个简单的修复程序,该程序忽略了来自存款合约的错误日志。然而,在此期间,发送恶意交易并触发该问题的攻击者仍然活跃。同时,PandaOps 积极地用更高费用的交易替换触发交易,以允许完全的区块生产。然而,据推测攻击者实际上阅读了公共开发者频道,因此一些修复程序在私下讨论。攻击者仍然可以向存款合约发送交易并不断触发问题,因为 ERC-20 允许零代币转账。临时修复程序是在私下开发的,并部署到 EF DevOps 节点(约占网络的 10%)。这至少允许这些节点提出完整的区块,直到协调部署修复程序。
协调部署 (14:00 UTC)
在 UTC 时间 14:00,开发者加入了另一个协调呼叫,所有节点都使用包含适当修复程序的新客户端版本进行了更新。这被证实是成功的,链继续稳定,有常规区块,并且先前有问题的交易也被包含在内,没有进一步的问题。
客户端发布
客户端团队发布了包含 Sepolia 问题热修复的版本。所有节点运营商都必须升级其执行层客户端以遵循 Sepolia:
根本原因分析
执行层问题
该问题发生在执行层中,因为 EIP-6110 实现与 Sepolia 的自定义存款合约不兼容。与主网或 Holešky 不同,Sepolia 验证是许可的,这是通过使用基于 ERC-20 代币而不是 ETH 的代币门控存款合约来实现的。
当发送存款以测试执行触发的提款功能时,执行客户端遇到错误:“无法解析存款数据:存款长度错误:需要 576,有 32”。这是因为存款合约发出了不是常规合约一部分的 ERC-20 转移事件,并且 EIP-6110 实现逻辑未预期到这些事件。失败的事件解析使包含存款交易的区块无效,迫使验证者产生空块。
修复过程中的一个重要障碍是正在进行的触发该问题的攻击。因为 ERC-20 允许零代币转账,这可以由任何人发起,即使没有拥有该代币,攻击者仍然可以发送恶意交易,从而在合约中发出不正确的事件。
根本原因补救措施
- 执行客户端实施了用于解析存款合约日志的修复程序,例如 Geth #31317
- EIP-6110 已更新以添加事件过滤
- 区块链测试已更新以涵盖相关场景
进一步的缓解措施和经验教训
测试网配置需要更紧密地反映主网,从而减少特定于测试网的极端情况。自定义存款合约已被证明是一个比预期更大的问题。
合约事件的 ABI 解码需要更具弹性和容错性。关于 ABI 解码库的更多讨论正在进行中。
Besu 团队使用了一个插件系统,该系统允许部署快速的临时热修复,排除恶意交易,而无需完全发布。他们还将审查在关键共识路径中第三方库的使用情况。
Geth 注意到他们还没有 Cancun 的覆盖标志,已在 #31341 中修复
更多资源:
事件时间线
注意:LLM 用于根据 Discord 聊天记录进行编译。我已经对其中的大部分进行了健全性检查,但可能存在轻微的不准确之处。
由于缓解了活跃的攻击者,一些修复程序没有公开讨论,而只是发生在开发者之间的私人聊天中。
2025年3月5日:Sepolia 测试网问题时间线
一些开发者和 PandaOps 已经亲自会面,发现了这个问题,之后不久公共聊天开始:
~上午 9:43:识别问题
- 9:44:Tim Beiko 报告:“Sepolia 上出现了一个问题,原因是某些 EL 客户端在处理交易时遇到问题,原因是 Sepolia 上的存款合约不同。PandaOps + Geth 正在 IRL 调查。”
- 9:51:Ahmad Bitar 警告说:“此修复可能会导致共识上的分歧,因此,要部署的任何修复都必须是计划好的分叉。”
- 10:01-10:02:Ahmad Bitar 和 lightclient 敦促:“请不要部署此修复”/“是的,请不要立即部署任何修复”,以防止进一步的链分裂
上午 10:07-10:29:紧急协调
- 10:07:共享 Zoom 会议链接,客户端团队正在加入
- 10:21:fjl 询问:“关于修复,我们是否同意匹配日志主题?”
- 10:27:lightclient 报告:“看起来 geth、nethermind 和 erigon 达成了一致?”
- 10:28:parithosh 确认:“交易再次流动,我们将讨论和协调适当的修复”
- 10:29:kamil_chodola 指出:“看起来 erigon 验证者仍然宕机”
上午 10:45-11:37:修复开发与测试
- 10:45:Mario Vega 共享了此问题的区块链测试
- 10:45:parithosh 更新:“客户端同意了一个修复,可以部署它们,理想情况下进行一些协调以谨慎起见”
- 11:05:danceratopz 共享了用于测试不正确行为的 hive 命令
- 11:10:fjl 确认:“修复现在在 Geth master 分支中”
- 11:23-11:37:关于 Sepolia 和其他网络之间存款合约差异的讨论
- 11:37:M.Kalinin 开始更新 EIP-6110,更新 PR:“PTAL, https://github.com/ethereum/EIPs/pull/9453”
- 11:42:proto 询问:“是否会有用于 L1 sepolia 存款日志选择修复的客户端版本?”
- 11:43:ralexstokes 确认:“是的,l1 客户端团队正在开发版本”
- 11:50:共享 PSA:“存款日志主题 0x649BBC62D0E31342AFEA4E5CD82D4049E7E1EE912FC0889AA790803BE39038C5”
- 11:57-12:08:关于日志的 ABI 解码方法的讨论
- 1:17:Mario Vega 共享 ABI 解码的更新测试
- 1:19-1:20:Som 和 danceratopz 确认该修复程序通过了 Erigon 的 main 和 Nethermind
下午 1:42-1:59:客户端发布与验证
- 1:42:spencer 确认:“Geth/Reth 通过。Ethjs/Besu 草案 PR 也通过。”
- 1:44:danceratopz 列出了测试版本
- 1:45:Nethermind 1.31.4 发布
- 1:49:parithosh 共享了更新的状态和已发布客户端的列表
- 1:51:宣布了 Reth v1.2.2 和 Erigon-3 修复版本
下午 2:00-3:25:协调部署
- 2:12:Andrew Ashikhmin 宣布了 Erigon v2.61.3 版本
- 2:27:spencer 确认:“所有这些版本都在我的端通过了!”
- 2:52:ralexstokes 共享了 Sepolia 推出电话链接
- 2:57:parithosh 要求 CL 团队确认可用性
- 3:01:parithosh 指示:“请继续更新你的节点”
- 3:04:jakubgs 报告:“完成”
- 3:07:skylenet 报告了孤立的块,并要求验证节点更新
- 3:08:jakubgs 确认所有节点都已更新到 Geth v1.15.5
- 3:12-3:18:讨论确定 Nimbus 节点仍然缺少块
- 3:21:jakubgs 报告:“BN 同步距离正在增长”,并附有显示同步问题的屏幕截图
- 3:24-3:25:tersec 调查并指出 Nimbus 可能在一个分叉上
- 3:25:Barnabas 建议:“可能是 Nimbus 的一个错误?”
下午 3:25-4:09:Nimbus 问题调查
- 3:26:Barnabas 报告:“我们的 Nimbus 节点也在一个不同的分叉上”(带有主题讨论)
- 4:09:parithosh 发布更新:“更新按预期工作。网络正在完成最终确认,交易正在按预期处理。我们测试了一个存款,现在可以正常工作。”
下午 4:09-4:56:事件后跟进
- 4:09:parithosh 宣布了 EF 博客文章,网址为 https://blog.ethereum.org/2025/03/05/sepolia-pectra-incident
- 4:09:parithosh 概述了后续步骤:“测试更新,未来几天的详细事件报告,对修复的更深入讨论”
- 4:44:agnish 报告了 Pectra-devnet-7 上的 Nimbus-Erigon 问题
- 4:48-4:56:Andrew Ashikhmin 和 Som 调查了 Erigon 问题,指出“来自某个区块的状态根不匹配”
- 4:53:Justin Florentine 询问了在 Sepolia 上运行的 L2
下午 5:38-10:57:回顾性讨论
- 5:38:Justin Florentine 回忆起之前建议在分叉之前对测试网进行 shadowforking
- 9:35:Barnabas 解释说,shadowforking 不会发现这些错误:“因为通常我们总是重新部署一个类似主网的存款合约”
- 10:44-10:57:关于 shadowforking 是否可以发现该错误的讨论
- 10:57:parithosh 提供了详细的解释:“当前流程对 shadowfork 使用主网存款合约”,并承认“很明显,我们的测试网与主网的差异变得笨拙,我们将在未来修改事物,使其尽可能接近主网”