资讯动态

EIP-1965 解读:在指定区块高度校验 ChainID 有效性的预编译方案

发布时间:2026/9/15 1:33:38 来源:尧图企业网站定制
EIP-1965 解读在指定区块高度校验 ChainID 有效性的预编译方案【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs导读EIP-1965Method to check if a chainID is valid at a specific block Number是 Ethereum Improvement Proposal 仓库中一份 Core 类标准提案提出通过新增预编译precompile的方式让智能合约能够查询某个 chainID 在某个区块高度上是否有效从而为 Layer 2 签名、元交易meta-transaction等链下消息提供跨分叉的重放攻击防护。本文以 EIPS/eip-1965.md 为主体结合仓库内 EIP-155、EIP-1344、EIP-1959、EIP-712 等关联提案完整梳理该提案的动机、技术规格、分叉场景分析与向后兼容要求帮助读者理解 chainID 历史校验问题在 EVM 生态中的演进脉络与设计取舍。背景chainID 与重放攻击防护的起源要理解 EIP-1965首先需要回到 EIP-155Simple replay attack protection已 Final。EIP-155 在交易签名中引入了CHAIN_ID当block.number FORK_BLKNUM且CHAIN_ID可用时签名哈希从原来的 6 个 RLP 编码元素(nonce, gasprice, startgas, to, value, data)扩展为 9 个元素(nonce, gasprice, startgas, to, value, data, chainid, 0, 0)同时v值必须设置为{0,1} CHAIN_ID * 2 35。这样为某条链签名的交易天然无法在另一条链上重放——因为链不同、chainID 不同签名校验必然失败。EIP-155 还在文档末尾列出了当时的 chainID 注册表mainnet1、Morden/Expanse2、Ropsten3、Rinkeby4、Goerli5、Kovan42、Geth 私链默认 1337。EIP-155 解决的是链上交易的重放问题但它并未覆盖链下签名消息off-chain messages。当合约需要验证用户链下签署的消息例如 EIP-712 类型化数据签名时合约必须在编译期把 chainID 写死在代码里。这正是 EIP-1344已 Final实现了CHAINID操作码0x46试图改进的点它让合约在运行时读取当前链的 chainID。但正如 EIP-1965 所指出这条路径存在根本性缺陷——chainID 是会变化的。问题剖析为什么只读当前 chainID不够安全EIP-1344 的CHAINID操作码让智能合约能够访问链上配置的当前 chainID成本为G_base。乍看之下合约用它校验签名即可实现重放防护。但 EIP-1965 的 Motivation 明确指出这insufficient不够充分chainID 是一个变化的值。当一次改变 chainID 的硬分叉发生时所有在分叉前按旧 chainID 签名的 EIP-712 消息在分叉后都会因为chainID ! CHAIN_ID()而被合约拒绝。对于普通应用用户重新提交一次消息即可顶多造成不便但对于状态通道state channel这类应用整个链下状态会变得不可访问后果可能是灾难性的。EIP-1344 的方案依赖合约自行实现信任无关缓存。EIP-1344 的 Rationale 自己就承认用户需要实现/使用一种通过智能合约维护的 trustless cache 来验证历史 chainID。这种缓存方案成本更高、可能留下时间空隙gap而且很容易被开发者忽略——只要某个合约简单地写chainID CHAIN_ID()而不回溯历史 chainID就会暴露重放风险。直接使用最新 chainID本质上是危险的。最新 chainID 只是 chainID 历史的一个尖端tip它作为变化中的值不适合作为链下消息有效性的判据。链下消息在签署时刻即应被视为链的链下状态的一部分不应被未来的硬分叉作废。因此 EIP-1965 认为更好的方案是让合约能直接、廉价、安全地查询某个 chainID 在某个历史区块上是否有效从而彻底替代缓存合约这种绕路做法。从 EIP-1959 到 EIP-1965补齐少数派分叉场景在 EIP-1965 之前同一作者Ronan Sandford先提出了 EIP-1959New Opcode to check if a chainID is part of the history of chainIDs同样 Stagnant。EIP-1959 的设计是新增VALID_CHAINID操作码0x46与 EIP-1344 的CHAINID同字节码位但参数不同接收一个 32 字节的 chainID 参数若该值处于本链的 chainID 历史中自创世起含当前值则压入0x1否则压入0x0执行成本为G_blockhash。EIP-1959 解决了分叉后旧消息失效的问题——所有曾在历史上有效过的 chainID 都被视为有效链下消息跨分叉保持连续性。但它没有解决少数派发起分叉时的重放问题如果多数链忽略少数派分叉、不更新自己的 chainID那么多数链上的新消息使用多数链当前 chainID 签名可以在少数派分叉上被重放因为多数链的当前 chainID 同样属于少数派分叉的 chainID 历史。EIP-1959 的 Rationale 承认了这一点并假设少数派分叉不会在日后获得牵引力因此不需要保护。EIP-1965 正是在这里与 EIP-1959 分道扬镳。EIP-1965 认为这是一个失误它剥夺了部分分叉的自由而所有分叉理应获得平等的机会。虽然无法解决多数方完全无视某分叉的固有难题但同时使用少数派分叉与多数链的用户不应被迫等待多数链更新 chainID 才能免受重放攻击。EIP-1965 技术规格双参数预编译EIP-1965 的核心规格非常简洁属于 Core 类标准precompile 级别的协议变更新增一个预编译precompile接收 2 个参数参数 1一个 32 字节值表示要测试的 chainID参数 2一个 32 字节值表示测试该 chainID 所对应的区块高度blockNumber。返回语义若该 chainID 在指定的区块高度上有效返回0x1否则返回0x0。有效性规则chainID 自其引入之时起直到被新 chainID 替换的那个区块为止都被视为有效——也就是说chainID 在其被替换之后的所有区块高度上依然有效valid up to the blockNumber at which they get replaced。在 gas 成本上EIP 给出明确界定The operation will costs no more thanG_blockhashG_verylowto execute. This could be lower as chainID are only introduced during hardfork.即执行成本不超过G_blockhashG_verylow并可能更低因为 chainID 只在硬分叉时引入历史通常很短。EIP 同时提醒随着链的 chainID 历史不断增长该操作的 gas 成本未来可能需要调整。相较之下EIP-1344 所提议的智能合约缓存方案整体 gas 成本更高因此这里的气费是该功能必要的代价。从 EIP 家族整体看chainID 相关的标准还包括 EIP-695JSON-RPC 层新增eth_chainId方法已 Final与 EIP-2294Explicit bound to Chain ID sizeStagnant定义 Safe Range(1, 2^31 - 1)与 Max RangeMAX_CHAIN_ID 9,223,372,036,854,775,771以避免 EIP-155 的v CHAIN_ID * 2 35运算在 uint64 下溢出。它们共同构成了围绕 chainID 的协议、RPC 与数值边界三层规范。设计动因两种分叉场景的完整推演EIP-1965 的 Rationale 是对为什么需要按区块高度校验最核心的论证它归纳了两种分叉场景场景 1多数派发起分叉少数派反对如 ETC 案例分叉计划在区块 X 发生。多数派若不采取行动为双方自动分配不同 chainID少数派有充足时间在同一个区块 X安排自己的 chainID 升级。若少数派不这样做其用户的消息将能在多数链上被重放反向则不成立因为假设是多数派改了 chainID。由于这是明显的风险少数派没有理由放任不管。场景 2少数派发起分叉多数派反对或直接忽略同理多数派有可能根本不在乎少数派分叉因此没有动力升级自己的 chainID。此时除非采取额外预防措施分叉双方的用户在少数派链上签署的、面向多数链的消息都将可被重放即使少数派链更换了自己的 chainID。解决方案正是本 EIP 的核心理念在链下消息中加入签署时刻的区块高度并将其作为上述预编译的参数。当少数派以新 chainID 分叉时旧 chainID 从那一刻起失效——因此面向多数链的新消息无法在少数派分叉上重放。这就是 EIP-1965 相比 EIP-1959 多出的按 blockNumber 维度校验的意义所在。以下表格对比了三个提案的定位差异依据三份文档规格整理维度EIP-1344FinalEIP-1959StagnantEIP-1965Stagnant机制CHAINID操作码0x46VALID_CHAINID操作码0x46新增预编译参数无1 个chainID2 个chainID blockNumber查询能力当前 chainIDchainID 是否在历史中有效chainID 在指定区块是否有效主要问题分叉后旧消息失效依赖缓存合约无法防护少数派分叉重放针对少数派分叉提供防护本提案目标向后兼容与对 EIP-712 生态的影响EIP-1965 的 Backwards Compatibility 部分给出了对签名生态的具体约束这是落地该方案的关键EIP-712 需要更新。EIP-712已 Final目前将chainId作为EIP712Domain域分隔符的可选字段而域分隔符的设计意图是只生成一次。EIP-1965 明确指出由于 chainID 和 blockNumber 都会变化它们不应放入 domain separator而应作为消息的另一部分。成对出现的规则对于不关心重放或已有其他防护手段的合约chainID/blockNumber 组合可以是可选的但一旦 chainID 存在blockNumber 必须同时存在。钱包的责任若消息中携带了二者之一钱包必须确保 chainID 确实是所使用链的最新 chainID而 blockNumber 是签署时刻的最新区块高度。在分叉过渡期间钱包可以利用 blockNumber 判断该使用哪个 chainID 来签署消息——这正是按区块校验赋予钱包的关键能力。当前状态与总结在仓库中EIPS/eip-1965.md 的状态为Stagnant停滞其元数据标注category: Core、type: Standards Track、requires: 155创建于 2019-04-20并在 References 中注明该方案最早脱胎于 EIP-1959 的讨论。从仓库的 EIPS/eip-1959.md 可以看到EIP-1959 的 Test Cases 与 Implementation 均为 TBD而 EIP-1965 同样未提供实现与测试相比之下EIP-1344 已成为 Final 并被主流客户端实现。也就是说chainID 历史校验的演进最终停留在提案层面但其提出的**按区块高度查询 chainID 有效性**的设计思想——包括预编译方案对缓存合约方案的成本优势、对少数派分叉重放问题的显式防护、以及 blockNumber 必须进入签名消息的兼容性要求——对于今天 Layer 2、元交易与跨链签名场景的重放防护设计仍具有重要的参考价值。延伸阅读EIP-1965 原始提案本文主体EIP-1959Valid ChainID Opcode同作者的前序提案EIP-1344ChainID opcode已 Final 的当前 chainID 访问方案EIP-155Simple replay attack protectionchainID 机制源头EIP-712Typed structured data hashing and signing链下消息签名标准EIP-695eth_chainIdJSON-RPC 方法EIP-2294Chain ID 数值边界约束仓库状态定义见 _data/statuses.yaml【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价