EIP-867 深度解析:以太坊恢复提案(ERP)的标准化格式与客户端实现指南
【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs
本文基于当前仓库中的 EIPS/eip-867.md 撰写。EIP-867 是一份Meta 类型的以太坊改进提案,它为"以太坊恢复提案(Ethereum Recovery Proposals,ERP)"定义了标准化的撰写格式、机器可读的状态变更对象(State Change Object)以及客户端实现指南。读者在阅读完本文后,将理解资金恢复提案为何长期难以成功、ERP 需要满足哪些硬性门槛、如何撰写令人信服的 Justification、如何设计可审计的验证脚本,以及各客户端如何以最小工作量且安全地应用这些状态变更。
背景与动机:为什么资金恢复提案总是失败
在以太坊区块链上,"资金恢复"(fund recovery)是一个长期存在且极具争议的话题。历史上,针对冻结资金的恢复提案几乎从未成功过,原因可以归结为两点:
- 请求形式过于临时(ad-hoc):每份提案的格式、证据标准、表述方式各不相同,社区难以横向比较和评估;
- 评估标准高度主观:是否应当恢复、恢复给谁、恢复多少,常常依赖主观判断,缺乏客观可度量的标准。
EIP-867 试图拆除这两道屏障。它不替任何具体恢复请求做价值判断,而是提供一套统一的提案格式与客观的评估标准,让未来的恢复提案能够在一致、透明的框架下被提出、审查和实现。正如文档在 Simple Summary 中所强调的:
本 EIP 既不主张接受也不反对任何特定恢复提案,其被接受本身也不会单独导致任何区块链状态变更。
也就是说,EIP-867 是一份"关于流程的流程"——它定义的是游戏规则,而不是具体的游戏结果。
EIP-867 概览:一份 Meta 类型 EIP 的三段式方案
根据 EIPS/eip-1.md 的定义,EIP 分为Standards Track(标准跟踪)、Meta(元)与Informational(信息)三种类型。其中 Meta EIP 描述的是"围绕以太坊的流程,或对流程的变更",例如程序、指南、决策流程的改变。EIP-867 的type: Meta字段正与此定义吻合——它规范的是后续 ERP 提案本身的格式与评估方式。
EIP-867 提出的解决方案分为三个部分:
- 标准(Standards):任何后续 ERP 要想进入审批流程,必须先满足的一组硬性门槛;
- 通用格式(Common Format):ERP 如何用一套客户端可解释的"纠正动作(corrective actions)"来描述自身;
- 客户端实现指南(Client Guidelines):客户端团队如何编写代码,在指定区块读取、解释并应用这些纠正动作。
第三部分的动作集合被刻意限制在最小范围内,目的是把任何 ERP 可能引入的风险降到最低。这份提案针对的是一类特定的资金丢失场景——在直接受影响各方之间对正确结果不存在分歧的情况,因此可以用低风险、及时的方式解决许多已经发生或随着以太坊发展可能再次发生的问题。
ERP 的八个标准组成部分
EIP-867 规定,每份 ERP 本质上是一个"需要非常规状态变更(irregular state change)才能解决资金恢复场景"的子类 EIP。它的目的有三:
- (a) 清晰描述需要被纠正的问题;
- (b) 论证为何非常规状态变更是必要且正当的;
- (c) 证明所提议的动作能够达成 ERP 的目标。
每个 ERP 必须使用标准格式表达提议的状态变更集合,并且必须附带一个能可靠生成这些变更的验证脚本。至少不满足这些要求的 ERP 不会被考虑批准。一份合格的 ERP 应包含以下项目:
| 组成部分 | 说明 |
|---|---|
| Preamble(前言) | EIP(RFC 822)格式的头部,包含 EIP 编号、简短标题(最长 44 个字符)以及每位作者的真实姓名(可附联系方式) |
| Simple Summary(简单摘要) | 面向普通读者、通俗易懂的 ERP 解释 |
| Detailed description(详细描述) | 对人类可读的纠正动作及确定这些动作所依据的判据的描述 |
| Justification(正当性论证) | 简明阐述为何这些纠正动作是合理的、且不太可能被任何直接受影响方质疑 |
| Verification script(验证脚本) | 机器可读的脚本,输出一个 State Change Object;脚本应清晰实现描述中概述的选择与动作生成逻辑,使审查者能够独立重新生成完全一致的 State Change Object |
| State Change Object(状态变更对象) | 验证脚本的输出、同时也是以太坊客户端的输入,规定了提议的状态变更动作的完整集合 |
| Appendix(附录,可选) | 支撑性证据,可包含验证恢复提案描述中细节的文件 |
关于 Preamble 的撰写,可以参照仓库中的 eip-template.md 模板,其头部字段(eip、title、author、discussions-to、status、type、created等)即对应 EIP-867 要求的 RFC 822 头格式。EIP-867 自身(编号 867、作者 Dan Phifer、James Levy、Reuben Youngblom,创建于 2018-02-02,状态 Stagnant)就是一个符合该格式的实例。
Justification:如何写出让人信服的恢复理由
Justification 是 ERP 中最考验写作质量的部分。它的标准是:这一动作既是合理的(不进行非常规状态变更就无法达成),又不太可能被"直接"受影响方质疑。EIP-867 用三个对比鲜明的例子演示了合格与不合格的差别。
合格示例(简洁、包含支撑证据、无负面影响):
XYZ 运营的一场众售(crowdsale)在其 2018 年 1 月 19 日启动时,错误地在其公开网站上发布了众售合约的测试网地址。在主网区块 4,235,987 至 4,236,050 之间,有 328 名用户向该错误地址发送了 501 ETH。此处为测试网合约,此处为主网上发往同一地址的交易,此处为 XYZ 在其网站上发布的声明。由于该地址在测试网上存在合约,且创建地址在主网上对应的 nonce 已被使用,可以认为不存在任何人恰好持有该私钥的可能性。我们已经验证所有交易均来自无关联代码的地址,因此将 ETH 退回给发送者不应有任何问题。
不足示例(细节不够、无支撑证据):
我们不小心把错误的合约地址贴到了网站上。能否请把发送到 0x1234 的任何 ETH 退回给发送者。谢谢。
不可接受示例(不客观,陷入一人之词对另一人之词的纠纷):
我把代币发给 X 换取服务,但他干得很差。我想要回我的钱,可他不退。请帮帮我!!
三个示例清晰地划出了边界:充分的 Justification = 具体事实 + 可验证证据 + 排除性推理(如"不存在任何人持有私钥的可能性");而个人纠纷、主观评价与无证据的请求都不属于 ERP 应当处理的范围——这正呼应了 EIP-867 的定位:它只处理"直接受影响各方对正确结果没有分歧"的情形。
Verification Script:可审计的机器可读验证脚本
验证脚本是 ERP 的核心工程产物。EIP-867 规定:
- 验证脚本应当是JavaScript 文件,可以使用web3.js库来访问链上数据;
- 脚本的输出是单一的 State Change Object。
EIP-867 给出了三条编写准则:
- 尽可能简洁:任何执行验证脚本的人都应当先审查脚本,确认其中不包含任何不安全操作;
- 绝不要求解锁的以太坊钱包:脚本不应依赖任何形式的钱包解锁或私钥签名;
- 硬编码执行期间包含的最高区块:否则不同时间运行脚本会产生不同的结果,破坏可复现性。
验证脚本的用途是通过代码无歧义地指定用于计算状态变更动作集合的判据。因此,客户端团队应避免手动预处理该产物(artifact),也不应把产物仅仅当作修改代码的参考。正确的做法是:把产物直接打包进客户端,由客户端在指定区块直接处理。这样做既能最小化每个 ERP 所需的客户端工作量,又能确保不同客户端之间的兼容性。EIP-867 也预见到某些 ERP 的验证脚本可能非常琐碎,但仍然建议保留它们,以维持流程的一致性。
State Change Object:客户端统一解释的数据格式
State Change Object(SCO)是验证脚本的输出、以太坊客户端的输入,它规定了一整套提议的状态变更动作。它是一个单一的 JSON 对象,包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| erpId | string | 该 ERP 的字符串标识(通常即关联的 EIP 编号,如"EIP-1234")。客户端将其从 ASCII 转换为十六进制字符串,并作为目标区块的 extra data写入 |
| targetBlock | 区块号 | 应用 stateChange 的区块。客户端据此判断一组状态变更应该在何时发生 |
| actions | array | State Change Action(状态变更动作)的数组 |
| metadata | object | 元数据:sourceBlock(脚本运行时考虑的最高区块)、version(脚本运行时的版本) |
根据规范字段可以构造出如下符合格式的 SCO 示例(示意,实际内容以验证脚本输出为准):
{ "erpId": "EIP-867", "targetBlock": 4236050, "actions": [ { "type": "weiTransfer", "fromAddress": "0xAbC...", "toAddress": "0xDeF...", "value": "500000000000000000000" } ], "metadata": { "sourceBlock": 4236000, "version": "1.0.0" } }State Change Actions:被刻意限制的动作类型
State Change Action 是包含一个type字段和一组data字段的 JSON 对象,其中 data 字段的内容取决于 type,且必须遵循该 type 定义的 schema。这样的设计允许客户端先支持有限的几类操作,未来如需扩展,再通过后续 EIP 增加新的动作类型。EIP-867 要求各客户端在采纳本提案时实现以下两种动作类型:
weiTransfer
weiTransfer动作将 ETH 从一个地址转移到另一个地址。
数据字段:
- type(string):
weiTransfer - fromAddress(hex string):转出 ETH 的地址
- toAddress(hex string):接收 ETH 的地址
- value(decimal string):要转移的 ETH 数量,单位为 wei;必须为大于零的整数(不能是小数、不能为零)
{ "type": "weiTransfer", "fromAddress": "0xAbC...", "toAddress": "0xDeF...", "value": "1000000000000000000" }storeCode
storeCode动作将给定代码存储在给定地址上(典型场景是恢复被意外销毁的合约代码)。
数据字段:
- type(string):
storeCode - toAddress(hex string):应恢复合约的地址
- expectedCodeHash(hex string):toAddress 上当前已有代码的预期哈希;若该地址预期无代码,应使用空字符串;其他情况下,
0x前缀可选 - code(hex string):与该合约关联的新字节码
{ "type": "storeCode", "toAddress": "0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4", "expectedCodeHash": "", "code": "0x606060405234156200000d57fe5b..." }expectedCodeHash字段是重要的安全检查:它让客户端在应用动作前确认目标地址上的代码状态与提案预期一致(例如确认合约确实已被销毁、地址确实没有代码),避免在错误的链上状态下盲目覆盖代码。
附录(Appendix)的规范要求
附录是可选的,用于补充帮助审查者理解或验证 ERP 主张的证据。对于storeCode操作,EIP-867 有额外要求:
- 应包含提议的合约源码(如 Solidity)以及足够的其他细节,使审查者可以自行编译源码并生成相同的字节码;
- 应尽可能包含该地址上原本存储的源码;
- 若新旧两份合约不完全一致,应注明差异;若完全一致,作者应说明为何无需任何修改(这不太可能发生);
- 任何与原始合约遇到的问题相关的审查(review)、审计(audit)和测试用例,都应一并纳入附录。
此外,一旦 ERP 被接受,可以很方便地编译"变更将要发生的那个区块"以及动作来源(即脚本输出的标准化对象)。这些产物可以与客户端捆绑,实现无缝执行。
ERP 审批流程与客户端实现
审批流程
ERP 是 EIP 的一个子类,因此遵循与普通 EIP 完全相同的审批流程(参见 EIPS/eip-1.md 中的 EIP 工作流描述:先在论坛等渠道预研想法、提交 Draft、邀请编辑与社区反馈、推进状态直至 Final)。关于具体的测试流程,EIP-867 的作者在当时明确注明"正在向客户端团队征求关于恰当测试流程的反馈"——即测试方法论本身仍是开放问题。
客户端实现:SCO 文件与目标区块映射
选择采纳本提案的客户端需要实现一个模块,其工作机制如下:
- 在每次客户端进程启动时,扫描一个指定的目录(designated SCO directory),收集其中的 SCO 文件;
- 基于扫描结果构建target block → SCO 文件名的映射(即
erpsByTargetBlock); - 在开始处理新区块时,先查询该映射,判断当前区块是否存在需要执行的恢复动作。
EIP-867 给出的核心处理逻辑伪代码如下:
if (erpsByTargetBlock.get(currentBlock) != null) { try { applyRecoveryActions(erpsByTargetBlock.get(currentBlock)); } catch (e) { // recovery actions should be treated as a batch. // If one fails, they all fail. } } // continue with normal block processing...这里有三个值得注意的实现约束:
- 批处理语义:恢复动作必须作为一个批次处理——任何一个动作失败,则全部失败。这避免了部分生效导致的账目不一致;
- 执行顺序:
applyRecoveryActions必须按照 SCO 文件中存储的顺序依次应用恢复动作; - 余额与地址校验:客户端负责确保没有任何 State Change Action 会导致某个账户转出超过其当前余额的金额;同时,
weiTransfer和storeCode的toAddress必须始终是有效地址(绝不能是0x0)。
区块上的变更标记
每个受 ERP 影响的区块都应包含extra data以表明状态变更确实发生了。区块中的 extra data 应为 SCO 文件中的erpId转换后的十六进制形式,即:
hexStringToBytes(asciiToHex(erpId))客户端在从对等节点接收目标区块时,还应校验该区块头部中确实出现了预期的 extra data,以此防止未经授权或伪造的状态变更被传播。
与客户端仓库的协作方式
每个 ERP 应当链接到各客户端仓库的 pull request,这些 PR 应反向链接回 ERP,并包含其 EIP preamble 与摘要。与 ERP 关联的每个 PR 应该只包含一个文件——即添加到客户端指定 SCO 目录的 SCO 文件——无需任何额外客户端代码。这正是"产物直接由客户端处理"设计哲学的落地:客户端的工作量被压缩到最小,兼容性风险也随之降低。
EIP-867 的边界与设计理性
明确的范围外事项
EIP-867 聚焦于"恢复提案如何格式化",以优化可读性、尽可能消除或最小化出错或故意滥用的可能。以下事项明确不属于本 EIP 的范围:
- 哪些资金恢复提案(如果有的话)应当被接受并实施;
- 常见的恢复提案原告方如何组织代表集体个体方的 ERP。
也就是说,EIP-867 只提供管道,不裁决内容。
Rationale:三个关键设计决策
EIP-867 的设计理性围绕"最小化恢复动作风险"这一首要考量,辅以"标准化恢复动作格式"的次要考量:
- 验证脚本保证无歧义:包含验证脚本可以保证恢复动作的确定方式是唯一且无歧义的。这不意味着恢复动作必然正确,只意味着用于确定它们的逻辑被完整指定且可审计;
- 脚本输出可被客户端直接解释:这最小化了每个客户端采纳特定 ERP 所需的工作量,也降低了两个客户端对同一 ERP 做出不同实现决策的风险;
- 动作类型刻意有限且不灵活:这降低了意外后果或恶意构造的文件影响链上状态的可能性;格式易于扩展,但新增动作类型需要单独的 EIP。
参考实现与仓库中的相关实例
EthereumJ 参考实现
EIP-867 文档指出,已经为EthereumJ 平台编写了一份参考实现(对应其仓库中的一个 pull request)。这为其他客户端团队提供了具体的落地参照。
仓库中的真实恢复提案案例
本仓库中的 EIPS/eip-999.md(状态:Withdrawn)是一个理解恢复提案背景的真实案例。该提案试图恢复0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4地址上的WalletLibrary合约代码——该合约(被 Parity Wallet 用于降低多签钱包的部署成本)因意外自毁导致大量 ETH 和其他资产无法访问,提案希望用打过补丁的版本恢复合约代码,使依赖它的多签钱包所有者能够重新访问资产。EIP-999 在正文中明确表示"与之前讨论的提案不同,这不会改变任何 EVM 语义,而是通过在单个状态转换中实现解冻资金的目标"——这恰好呼应了 EIP-867 所讨论的"非常规状态变更"场景,也体现了这类提案为何需要标准化格式来获得社区的严肃对待。
ERP 示例章节
EIP-867 文档中保留了 "ERP Examples" 章节,说明其规划是在该章节收录完整的 ERP 示例、SCO 资源文件,以及一个如何在私有测试网(private testnet)上进行测试的简短教程——该章节在文档写作时尚未填充,读者可关注后续版本。
在仓库中继续深入阅读
如果你希望进一步理解 EIP-867 在 EIP 生态中的位置,建议按以下路径阅读当前仓库中的相关文件:
- EIPS/eip-867.md:本文所依据的原始提案全文;
- EIPS/eip-1.md:EIP 目的与指南,解释了 Meta 类型 EIP 的定位与完整审批工作流;
- eip-template.md:EIP 标准模板,对应 ERP 中 Preamble(RFC 822 头)的字段规范;
- EIPS/eip-999.md:一个真实的资金恢复提案实例(恢复 Parity WalletLibrary 合约代码),可对照 EIP-867 的格式要求进行分析;
- LICENSE.md:EIP-867 声明的版权与相关权利依据(CC0 放弃声明)。
结语
EIP-867 的价值不在于它是否最终被广泛实施,而在于它为以太坊社区提供了一套思考"非常规状态变更"的纪律性框架:用可复现的验证脚本代替主观叙述,用受限的动作类型控制风险,用统一的 SCO 格式消除客户端间的实现分歧。对于任何研究链上资金恢复、协议级状态变更或 EIP 治理流程的开发者而言,理解 ERP 的格式与客户端处理模型,都是理解以太坊"如何在极端情况下谨慎地修改自身"的关键一课。
【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考