ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EIP-4938 深度解析:eth/67 移除 GetNodeData,以太坊状态同步协议的演进

EIP-4938 深度解析:eth/67 移除 GetNodeData,以太坊状态同步协议的演进 EIP-4938 深度解析eth/67 移除 GetNodeData以太坊状态同步协议的演进【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs导读EIP-4938eth/67 - Removal of GetNodeData是一项已处于Final状态的以太坊网络层标准其核心动作是从eth线协议Wire Protocol中移除GetNodeData (0x0d)与NodeData (0x0e)两条消息并随之推出新的协议版本eth/67。本篇文章将以该 EIP 为骨架梳理这两条消息的历史由来fast sync 状态同步、移除动机状态存储形态与协议能力边界、精确的消息格式变更、以及以 snap 协议GetByteCodes/GetTrieNodes为核心的替代方案并结合本仓库中eth/65、eth/66、eth/68等相邻版本 EIP 的源码级佐证帮助读者完整理解以太坊同步协议十余年来的演进脉络与eth/67在整个版本序列中的坐标。一、背景eth 线协议与消息版本演进以太坊节点之间通过 devp2p 之上的eth协议交换数据该协议定义了一组请求/响应消息对用于在客户端之间传递区块头、区块体、收据、交易池内容、状态数据等。协议并非一成不变而是通过不断发布新版本eth/64→eth/65→eth/66→eth/67→eth/68来增加或移除消息每个版本号对应一组确定的消息集合。与本 EIP 直接相关的两条前置标准EIP-2464eth/65引入NewPooledTransactionHashes (0x08)、GetPooledTransactions (0x09)、PooledTransactions (0x0a)优化交易传播带宽。该 EIP 同时指出devp2p支持同一线协议的多个版本并行运行新版本发布不需要客户端协调升级——这一机制是eth协议持续演进的基石。EIP-2481eth/66为eth协议中所有请求/响应消息对增加request_id64 位整数使请求方无需遍历全部挂起请求即可将响应直接匹配到请求。在该 EIP 的规范中GetNodeData (0x0d)与NodeData (0x0e)恰好是被改造为携带request_id的消息之一。EIP-4938 正是在这一演进序列上往前再走一步与其继续给这两条消息打补丁不如直接将其从协议中移除。二、GetNodeData 的由来为 fast sync 而生EIP-4938 明确指出GetNodeData与NodeData最早在eth/63协议版本中引入服务于一种被称为fast sync的同步模式。在 fast sync 出现之前以太坊节点同步只能采用全量同步从创世块开始逐块执行所有交易重放全部状态计算最终在本地重建完整的 Ethereum 状态state。这种方式正确但代价高昂——执行整条链的交易需要耗费大量 CPU 时间。fast sync 的思路是跳过区块执行、直接下载状态客户端先同步并验证区块头与区块体然后按哈希向对等节点请求状态数据由于状态数据以 Merkle Patricia TrieMPT组织客户端需要请求状态 trie 的全部节点trie nodes以及合约代码contract code拿到全部状态后客户端本地即拥有一份完整的状态快照之后从某个历史区块开始正常执行后续区块。在这一算法中GetNodeData正是按哈希批量获取 trie 节点与合约代码的请求消息NodeData则是它的响应消息。其请求参数为一系列 32 字节哈希服务端按哈希在本地状态数据库中查找并返回对应的原始字节trie 节点 RLP 编码或合约代码。三、移除动机存储形态与协议能力边界EIP-4938 给出了移除这两条消息的两层核心动机其论证逻辑值得仔细拆解。3.1 服务 GetNodeData 要求哈希 → 节点映射存储要响应GetNodeData请求客户端必须能够按哈希直接查询到对应的 trie 节点或合约代码即本地数据库必须维护一份哈希 → trie 节点内容的映射。这是因为请求方只知道目标的 keccak 哈希服务方必须在 O(1) 或近 O(1) 时间内反查内容。然而并非所有客户端都以这种形态存储状态。部分客户端的存储布局如基于路径寻址、基于快照分层或其他自定义编码无法天然支持按哈希反查任意历史 trie 节点。避免为支持这一请求类型而被迫在数据库中维护哈希映射存储是移除GetNodeData的最主要动机。3.2 协议应如实反映客户端能力EIP-4938 还提出了一个更具原则性的论点The Ethereum Wire Protocol should accurately reflect the capabilities of clients, and should not contain messages which are impossible to implement in some clients.以太坊线协议应当如实反映客户端的能力不应包含某些客户端根本无法实现的消息。当时已有部分客户端实现无法服务GetNodeData请求——因为它们不以兼容方式存储状态。让协议中保留一条部分节点注定无法应答的消息会迫使请求方处理超时、空响应与半失败状态增加同步逻辑的复杂度也让协议本身与客户端真实能力脱节。因此移除这两条消息是对协议边界的一次诚实收敛。四、规范从 eth/66 消息集中移除两条消息EIP-4938 的规范部分极为精确从eth协议中移除以下两条消息类型。移除GetNodeData (0x0d)其在eth/66中的消息格式为[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]移除NodeData (0x0e)其在eth/66中的消息格式为[request_id: P, [value_0: B, value_1: B, ...]]字段说明结合 EIP-2481 中对该两条消息的定义字段类型含义request_idP正整数64 位整数请求方设置的请求标识符响应中原样带回用于请求/响应匹配由 EIP-2481 引入hash_iB_3232 字节目标 trie 节点或合约代码的 keccak 哈希value_iB任意字节串对应哈希所指向的原始内容trie 节点的 RLP 编码或合约代码字节码从 EIP-2481 提供的测试向量可以直观看到这两条消息在eth/66中的真实 RLP 编码形态{ type: GetNodeDataPacket66, rlp: 0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef, data: { RequestId: 1111, GetNodeDataPacket: [ 0x00000000000000000000000000000000000000000000000000000000deadc0de, 0x00000000000000000000000000000000000000000000000000000000feedbeef ] } }{ type: NodeDataPacket66, rlp: 0xce820457ca84deadc0de84feedbeef, data: { RequestId: 1111, NodeDataPacket: [ 0xdeadc0de, 0xfeedbeef ] } }在eth/67中这两个消息 ID0x0d、0x0e将从协议的消息表Message Table中整体消失任何对等方都不再发送或期望接收它们。五、替代方案snap 协议与同步算法的转向移除不等于没有替代品。EIP-4938 明确指出GetNodeData的功能可以由snap 协议承接GetByteCodes (0x04)按哈希批量请求合约代码覆盖原GetNodeData中请求合约代码的场景GetTrieNodes (0x06)按根哈希与路径请求 trie 节点覆盖原GetNodeData中请求 trie 节点的场景。snap 协议在请求语义上更为精细它允许请求方携带状态根state root与 trie 路径信息服务方基于自身状态快照按路径解析节点而非仅仅按内容哈希盲查。这使得服务方可以利用快照结构高效应答且不要求维护哈希 → 节点的全局映射——恰好绕开了导致GetNodeData被移除的存储约束。关于同步算法的选择EIP-4938 特别指出The snap protocol can be used to implement the fast sync algorithm, though it is recommended to use it for snap sync.snap 协议可以用于实现 fast sync 算法但官方建议将其用于 snap sync。即技术上 snap 协议具备实现传统 fast sync 的能力但生态的推荐路径是采用专为快照式状态下载设计的snap sync——它先下载账户快照扁平化的账户列表再基于快照并行拉取存储 trie整体上比逐哈希盲拉所有 trie 节点更高效、更易于断点续传。六、向后兼容多版本并存与无需硬分叉EIP-4938 属于网络层Networking标准其兼容性分析包含两个关键结论。6.1 新版本 eth/67旧客户端不受影响移除消息是对eth协议的破坏性变更因此需要推出新版本eth/67。由于devp2p支持同一线协议多个版本并行运行这也是从 EIP-2464、EIP-2481 一路沿用的机制发布eth/67并不会立即破坏旧客户端——未升级的节点可以继续使用eth/66互相通信协议协商handshake时双方会选择彼此都支持的最高公共版本。6.2 不触及共识无需硬分叉EIP-4938 明确声明This EIP does not change consensus rules of the EVM and does not require a hard fork.GetNodeData/NodeData仅是节点之间传输数据的辅助消息不参与区块验证与状态转换因此移除它们对 EVM 执行、区块格式、状态根计算均无影响只需网络层客户端升级无需协调全网的硬分叉。七、安全考虑EIP-4938 在 Security Considerations 一节给出的结论是None。移除一条可能被滥用于放大攻击的按哈希检索消息本身并不引入新的攻击面相关数据传输场景由 snap 协议承担其自身的安全模型如响应上限、请求配额由 snap 协议另行定义。八、eth/67 在协议演进序列中的坐标要理解eth/67的分量需要把它放入完整的版本时间线中观察均为本仓库内的正式标准协议版本对应 EIP关键变更eth/63—引入GetNodeData/NodeData支撑 fast synceth/65EIP-2464引入交易哈希公告与按需获取消息优化交易传播eth/66EIP-2481全部请求/响应消息对增加request_ideth/67EIP-4938移除GetNodeData/NodeData宣告 fast sync 时代落幕eth/68EIP-5793NewPooledTransactionHashes附加交易类型与大小且该 EIP 明确requires: 4938其eth/67基线即是不含GetNodeData的消息集两个来自后续 EIP 的旁证可以确认eth/67的最终形态EIP-5793eth/68在其 Backwards Compatibility 一节中写道旧客户端可以继续使用eth/67并直接声明requires: 4938——这证明eth/67已作为稳定基线被下一代版本依赖EIP-7542eth/70 握手扩展也提到未升级节点可继续使用eth/69、eth/68或eth/67——进一步印证eth/67在版本协商中作为可选项长期存在。从更宏观的视角看GetNodeData的移除标志着一个时代转折以太坊同步从逐节点按哈希盲拉状态转向基于快照的结构化状态下载。客户端不再需要维护与自身存储形态相悖的哈希映射协议也更准确地反映了现实世界客户端的能力集合。这一设计哲学——协议必须与实现能力对齐冗余消息宁可移除也不保留——对后续所有eth协议修订都产生了持续影响。九、小结EIP-4938 用一份简洁的规范完成了一次影响深远的协议清理移除GetNodeData (0x0d)与NodeData (0x0e)发布eth/67由 snap 协议的GetByteCodes与GetTrieNodes承接状态同步需求并在不触发硬分叉的前提下通过多版本并存完成平滑过渡。本文依据的原始规范见 EIPS/eip-4938.md其前置与后续标准分别见 EIPS/eip-2464.md、EIPS/eip-2481.md、EIPS/eip-5793.md感兴趣的读者可以沿此链路继续深入以太坊网络层协议的设计取舍。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表