该EIP提出了将以太坊的snap协议从v1升级到v2的方案。核心变化是用基于EIP-7928引入的区块级访问列表(BALs)的状态恢复机制,取代了迭代获取Merkle树节点的方法。新协议定义了BALs的请求与响应消息,并详细阐述了基于BALs的同步算法,旨在提升快照同步的效率和鲁棒性。
本 EIP 将 snap 协议从版本 1 升级到版本 2,移除了 GetTrieNodes (0x06) / TrieNodes (0x07),并用 GetBlockAccessLists (0x06) / BlockAccessLists (0x07) 取代它们,以实现 snap 同步期间基于 BAL 的状态修复。
EIP-7928 引入了区块级访问列表 (BAL),它捕获每个区块的所有状态更改,并通过 block-access-list-hash 提交到区块头。有了可用的 BAL,snap 同步的修复阶段——该阶段通过 GetTrieNodes 迭代地获取单个 Merkle trie 节点以解决状态不一致性——可以完全取代。
同步节点不再通过多次往返发现和获取 trie 节点,而是下载在同步期间前进的区块的 BAL,并顺序应用状态差异。每个 BAL 都根据其头承诺进行验证。需要追赶的区块集是预先知道的,从而消除了迭代发现。
协议版本从 snap/1 递增到 snap/2。对等节点在 RLPx 能力握手期间协商版本。
| 消息 | ID | 原因 |
|---|---|---|
GetTrieNodes |
0x06 | 被基于 BAL 的修复取代 |
TrieNodes |
0x07 | 被基于 BAL 的修复取代 |
释放的消息 ID 被重用于 BAL 交换。
[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]
请求给定区块哈希的 BAL。每个请求的哈希数量受限于实现定义的限制。
BAL 仅适用于 EIP-7928 激活后的区块,并在其中定义的保留期内可用。
注意:
[request-id: P, [block-access-list₁, block-access-list₂, ...]]
对 GetBlockAccessLists 的响应。每个元素都与请求中的区块哈希按位置对应。在 BAL 不可用的区块处返回空 BAL(零长度字节切片)。
BlockAccessLists 响应的推荐软限制为 10 MiB。
消息 0x00–0x05 (GetAccountRange, AccountRange, GetStorageRanges, StorageRanges, GetByteCodes, ByteCodes) 与 snap/1 保持不变。
收到的 BAL 必须通过计算 keccak256(rlp.encode(bal)) 并与相应区块头中的 block-access-list-hash 进行比较来验证。有关 BAL 编码格式,请参阅 EIP-7928。
snap/2 用基于 BAL 的追赶取代了 trie 修复:
GetAccountRange、GetStorageRanges、GetByteCodes 批量下载 P 处的状态。GetBlockAccessLists 获取 P+1 到 P+K 的 BAL,在本地应用状态差异,并立即使用 P+K 作为新的同步目标。每个 BAL 在应用前都根据其头哈希进行验证。如果链条重组(reorgs)超过枢轴区块 P,设 W 为旧链和新规范链的共同祖先。同步节点收集旧分叉上 W+1 到 P 的 BAL,识别在旧分叉上被修改但未在新分叉上被修改的状态条目,在本地删除这些条目,并通过 GetAccountRange / GetStorageRanges 重新获取它们。然后应用新规范链上从 W+1 开始的 BAL,并以新的枢轴继续同步。如果所需的孤立 BAL 不可用,节点必须丢弃状态并重新启动同步。
这遵循了既定的 snap 设计理念。GetByteCodes 从 eth 复制到 snap 的原因相同:
此功能从
eth/65复制到snap,以允许eth长期仅作为链维护协议,并将同步原语移至卫星协议。
同步原语属于卫星协议。snap 是可选的,并且独立版本化;在此处复制 BAL 交换避免了将同步功能与 eth 耦合。
基于 BAL 的修复使得 trie 节点获取以进行状态协调变得不必要。移除这些消息避免了维护两种修复机制,并释放了消息 ID 以供重用。
消息 ID 的作用域限定在协议版本内,并在 RLPx 能力握手期间进行协商。snap/1 对等节点永远不会收到 snap/2 消息。
此 EIP 需要推出一个新的协议版本,snap/2。旧客户端继续使用 snap/1。snap/2 仅对 Amsterdam 后区块有意义,因为 block-access-list-hash 头字段 (EIP-7928) 在更早的区块中不存在。snap/2 对等节点必须也运行 eth/71 或更高版本,因为 snap 是 eth 的一个依赖卫星协议。
对于正在同步数据的节点,如果同时支持 snap/1 和 snap/2,它应该使用 snap/1 或 snap/2 进行状态同步;不建议同时运行两者。一旦同步阶段完成,节点可以为两个协议提供请求服务。
GetBlockAccessLists 请求可以触发比请求本身大得多的响应。实现应该应用速率限制,并遵守 10 MiB 的软响应限制。
对可用区块返回空条目的对等节点可能是行为不端或合法地修剪了数据。实现应该跟踪对等节点的可靠性,并降低不可靠对等节点的优先级。
BAL 必须按严格的区块顺序应用,并在应用前验证每个 BAL 哈希。错误的顺序或错误分叉的 BAL 会产生无效的状态根,这将在最终状态根验证期间被检测到。
版权和相关权利通过 CC0 放弃。
- 原文链接: github.com/nerolation/EI...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!