本文档描述了以太坊合并转换的测试案例,重点关注了TERMINAL_TOTAL_DIFFICULTY和TERMINAL_BLOCK_HASH两个关键参数在以太坊从PoW到PoS过渡期间的作用。测试覆盖了EL和CL客户端在不同场景下的行为,包括链重组、无效终端块处理、以及在启用TERMINAL_BLOCK_HASH覆盖时的特定情况。这些测试旨在验证以太坊客户端在各种合并转换场景中的正确性和鲁棒性。
本文档中描述的所有测试用例都从合并前的世界开始,并在执行过程中达到终端 PoW,以执行 PoS 转换。
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- 不要编辑此部分,请重新运行 doctoc 以更新 -->
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
TERMINAL_TOTAL_DIFFICULTY[x] [Hive] 重新组织为更高总难度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B1.totalDifficulty > TTD, B1'.totalDifficulty > TTDB1'.totalDifficulty > B1.totalDifficultyforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1' <- P1B1' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- P1 <- ... <- Pn</details>
[x] [Hive PR] 合并后重新组织为更高总难度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B1.totalDifficulty > TTD, B1'.totalDifficulty > TTDB1'.totalDifficulty > B1.totalDifficultyforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1 <- P1forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1') + forkchoiceUpdated(head: P1'),其中 B1' <- P1'B1' 及其后代,并对 forkchoiceUpdated(head: Pn') 响应 {status: VALID, latestValidHash: Pn', validationError: null},其中 B1' <- P1' <- ... <- Pn'</details>
[x] [Hive] 重新组织为更低总难度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B1.totalDifficulty > TTD, B1'.totalDifficulty > TTDB1.totalDifficulty > B1'.totalDifficultyforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1' <- P1B1' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- P1 <- ... <- Pn</details>
[x] [Hive PR] 合并后重新组织为更低总难度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B1.totalDifficulty > TTD, B1'.totalDifficulty > TTDB1.totalDifficulty > B1'.totalDifficultyforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1 <- P1forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1') + forkchoiceUpdated(head: P1'),其中 B1' <- P1'B1' 及其后代,并对 forkchoiceUpdated(head: Pn') 响应 {status: VALID, latestValidHash: Pn', validationError: null},其中 B1' <- P1' <- ... <- Pn'</details>
[x] [Hive] 双区块重新组织为更高总难度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1 <- B2, B: Genesis <- B1' <- B2'A 开始,EL 客户端 2 从 B 开始TTD 配置B2.totalDifficulty > TTD, B2'.totalDifficulty > TTDB2'.totalDifficulty > B2.totalDifficultyforkchoiceUpdated(head: B2){status: VALID, latestValidHash: B2, validationError: null}forkchoiceUpdated(head: B2'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B2' <- P1B1'、B2' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- B2' <- P1 <- ... <- Pn</details>
[x] [Hive] 双区块重新组织为更低总难度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1 <- B2, B: Genesis <- B1' <- B2'A 开始,EL 客户端 2 从 B 开始TTD 配置B2.totalDifficulty > TTD, B2'.totalDifficulty > TTDB2.totalDifficulty > B2'.totalDifficultyforkchoiceUpdated(head: B2){status: VALID, latestValidHash: B2, validationError: null}forkchoiceUpdated(head: B2'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B2' <- P1B1'、B2' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- B2' <- P1 <- ... <- Pn</details>
[x] [Hive] 重新组织为更高高度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1' <- B2'A 开始,EL 客户端 2 从 B 开始TTD 配置B1.totalDifficulty > TTD, B2'.totalDifficulty > TTDforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}forkchoiceUpdated(head: B2'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B2' <- P1B1'、B2' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- B2' <- P1 <- ... <- Pn</details>
[x] [Hive PR] 合并后重新组织为更高高度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1' <- B2'A 开始,EL 客户端 2 从 B 开始TTD 配置B1.totalDifficulty > TTD, B2'.totalDifficulty > TTDforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1 <- P1forkchoiceUpdated(head: B2'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1') + forkchoiceUpdated(head: P1'),其中 B2' <- P1'B1'、B2' 及其后代,并对 forkchoiceUpdated(head: Pn') 响应 {status: VALID, latestValidHash: Pn', validationError: null},其中 B1' <- B2' <- P1' <- ... <- Pn'</details>
[x] [Hive] 重新组织为更低高度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1 <- B2, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B2.totalDifficulty > TTD, B1'.totalDifficulty > TTDforkchoiceUpdated(head: B2){status: VALID, latestValidHash: B2, validationError: null}forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1' <- P1B1' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- P1 <- ... <- Pn</details>
[x] [Hive PR] 合并后重新组织为更低高度 PoW 链 <details> <summary>点击查看详情</summary>
A: Genesis <- B1 <- B2, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B2.totalDifficulty > TTD, B1'.totalDifficulty > TTDforkchoiceUpdated(head: B2){status: VALID, latestValidHash: B2, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B2 <- P1forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1') + forkchoiceUpdated(head: P1'),其中 B1' <- P1'B1' 及其后代,并对 forkchoiceUpdated(head: Pn') 响应 {status: VALID, latestValidHash: Pn', validationError: null},其中 B1' <- P1' <- ... <- Pn'</details>
[x] [Hive PR] 重新组织为具有无效终端区块的链(Block.totalDifficulty < TTD)
<details>
<summary>点击查看详情</summary>
A: Genesis <- B1 <- B2, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置,因此:B2.totalDifficulty > TTD, B1.totalDifficulty < TTD, B1'.totalDifficulty < TTDB1.totalDifficulty > TTD, B1'.totalDifficulty > TTDforkchoiceUpdated(head: B2){status: VALID, latestValidHash: B2, validationError: null}forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1' <- P1B1' 及其后代,但 head 仍然是 B2</details>
[x] [Hive PR] 重新组织为具有无效终端区块的链(Block.Parent.totalDifficulty > TTD)
<details>
<summary>点击查看详情</summary>
A: Genesis <- B1, B: Genesis <- B1' <- B2'A 开始,EL 客户端 2 从 B 开始TTD 配置,因此:B1.totalDifficulty > TTD, B1'.totalDifficulty > TTDB1.totalDifficulty < TTD, B1'.totalDifficulty < TTD, B2'.totalDifficulty > TTDforkchoiceUpdated(head: B1){status: VALID, latestValidHash: B1, validationError: null}forkchoiceUpdated(head: B2'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B2' <- P1B1'、B2' 及其后代,但 head 仍然是 B1</details>
[x] [Hive PR] 使用 PREVRANDAO 操作码交易重新组织为更低高度 PoW 链
<details>
<summary>点击查看详情</summary>
A: Genesis <- B1 <- B2, B: Genesis <- B1'A 开始,EL 客户端 2 从 B 开始TTD 配置B2.totalDifficulty > TTD, B1'.totalDifficulty > TTDB1 和 B1' 包含 Tx1B2 包含 Tx2Tx1 和 Tx2 将 DIFFICULTY 操作码保存到存储forkchoiceUpdated(head: B2){status: VALID, latestValidHash: B2, validationError: null}DIFFICULTY 操作码forkchoiceUpdated(head: B1'){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1' <- P1P1 包含 Tx2B1' 及其后代,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1' <- P1 <- ... <- PnPREVRANDAO 操作码</details>
[x] [Hive] 停止跟随 PoW 链 <details> <summary>点击查看详情</summary>
Genesis <- B1 <- B2B1 之前的链开始,EL 客户端 2 从区块 B2 之前的链开始TTD 配置forkchoiceUpdated 未发送到 EL 客户端 1B2 合并到其链中</details>
[x] [Hive] 长 PoW 链同步 <details> <summary>点击查看详情</summary>
Genesis <- B1 <- ... <- B1024B1 之前的链开始,EL 客户端 2 从区块 B1024 之前的链开始TTD 配置B1024.totalDifficulty > TTDforkchoiceUpdated(head: B1024){status: SYNCING, latestValidHash: null, validationError: null}newPayload(P1) + forkchoiceUpdated(head: P1),其中 B1024 <- P1B1 <- ... <- B1024,并对 forkchoiceUpdated(head: Pn) 响应 {status: VALID, latestValidHash: Pn, validationError: null},其中 B1 <- ... <- B1024 <- P1 <- ... <- Pn</details>
[x] [Hive] 提议有效的转换区块 <details> <summary>点击查看详情</summary>
Genesis <- ... <- TB,TB 是有效的终端区块TB 作为头部开始forkchoiceUpdated(headBlockHash: TB.blockHash, payloadAttributes: mergeTransitionBlockAttributes)headBlockHash{status: VALID, payloadId: mergeTransitionPayloadId}getPayload(mergeTransitionPayloadId)ommersHash == 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347difficulty == 0mixHash == mergeTransitionBlockAttributes.prevRandaononce == 0x0000000000000000newPayload(mergeTransitionPayload)VALID</details>
[x] [Hive] 在错过 fcU 的有效链上转换
<details>
<summary>点击查看详情</summary>
Genesis <- ... <- TB <- P1 <- P2 <- P3,TB 是有效的终端区块TB 作为头部开始newPayload(P1){status: VALID, latestValidHash: payload.blockHash}TBnewPayload(P2){status: VALID, latestValidHash: payload.blockHash}TBnewPayload(P3){status: VALID, latestValidHash: payload.blockHash}TBforkchoiceUpdated(head: P3, safe: P2, finalized: P1)P3eth_getBlockByNumber(safe) 返回 P2eth_getBlockByNumber(finalized) 返回 P1</details>
[x] [Hive] 在无效终端区块之上构建 <details> <summary>点击查看详情</summary>
Genesis <- ... <- INV_TB,INV_TB 是一个有效 PoW 但无效终端区块,即 INV_TB.TD < TTD;INV_TB.parent.TD >= TTD 无法轻松检查,因为 EL 不会处理此类区块INV_TB 作为头部开始forkchoiceUpdated(headBlockHash: TB.blockHash, payloadAttributes: mergeTransitionBlockAttributes){status: INVALID, latestValidHash: 0x00..00, payloadId: null}INV_TB.TD < TTD,则 EL 的头部指向 INV_TB,如果 INV_TB.parent.TD >= TTD,则指向 INV_TB.parent</details>
[x] [Hive] 在有效链上转换 <details> <summary>点击查看详情</summary>
Genesis <- ... <- TB <- P1 <- P2 <- P3,TB 是有效的终端区块TB 作为头部开始newPayload(P1){status: VALID, latestValidHash: payload.blockHash}TBforkchoiceUpdated(head: P1, safe: 0x00..00, finalized: 0x00..00){status: VALID, latestValidHash: forkchoiceState.headBlockHash}P1eth_getBlockByNumber(safe) 返回 -39001: Unknown block 错误eth_getBlockByNumber(finalized) 返回 -39001: Unknown block 错误newPayload(P2) + forkchoiceUpdated(head: P2, safe: P1, finalized: 0x00..00)P2eth_getBlockByNumber(safe) 返回 -39001: Unknown block 错误eth_getBlockByNumber(finalized) 返回 -39001: Unknown block 错误newPayload(P3) + forkchoiceUpdated(head: P3, safe: P2, finalized: P1)P3eth_getBlockByNumber(safe) 返回 P2eth_getBlockByNumber(finalized) 返回 P1</details>
[x] [Hive] 在无效链上转换 <details> <summary>点击查看详情</summary>
Genesis <- ... <- INV_TB <- P1,INV_TB 是一个有效 PoW 但无效终端区块:INV_TB.TD < TTDINV_TB.parent.TD >= TTD -- 可能需要第二个具有更高 TTD 值的 ELINV_TB 作为头部开始newPayload(P1){status: INVALID, latestValidHash: 0x00..00}INV_TB.TD < TTD,则 EL 的头部指向 INV_TB,如果 INV_TB.parent.TD >= TTD,则指向 INV_TB.parent</details>
[x] [Hive] 重新组织为具有无效转换区块的链 <details> <summary>点击查看详情</summary>
A: Genesis <- ... <- TB <- P1 <- P2, B: Genesis <- ... <- TB <- INV_P1,A.TB 和 B.TB 是有效的终端区块A.TB 作为头部开始newPayload(A.P1) + newPayload(A.P2){status: VALID, latestValidHash: payload.blockHash}A.TBforkchoiceUpdated(head: A.P2, safe: A.P1, finalized: 0x00..00)A.P2newPayload(B.INV_P1){status: INVALID/ACCEPTED, latestValidHash: null/0x00..00}A.P2forkchoiceUpdated(head: B.INV_P1, safe: 0x00..00, finalized: 0x00..00){status: INVALID, latestValidHash: 0x00..00}A.P2</details>
[x] [Hive] 与具有有效转换的链同步 <details> <summary>点击查看详情</summary>
Genesis <- ... <- Bn <- TB <- P1,TB 是有效的终端区块Bn 作为头部开始newPayload(P1) + forkchoiceUpdated(P1){status: SYNCING}BnTB <- P1forkchoiceUpdated(P1){status: VALID, latestValidHash: null}P1</details>
[x] [Hive] 与具有无效终端区块的链同步 <details> <summary>点击查看详情</summary>
Genesis <- ... <- Bn <- INV_TB <- P1 <- P2,INV_TB 是一个有效 PoW 但无效终端区块:INV_TB.TD < TTDINV_TB.parent.TD >= TTD -- 可能需要第二个具有更高 TTD 值的 ELBn 作为头部开始newPayload(P1) + forkchoiceUpdated(P1){status: SYNCING}BnINV_TB <- P1forkchoiceUpdated(P1){status: INVALID, latestValidHash: 0x00..00}Bn</details>
[x] [Hive] 与终端区块对于 EE 无效的链同步 <details> <summary>点击查看详情</summary>
Genesis <- ... <- Bn <- INV_TB <- P1 <- P2,INV_TB 满足 TTD,但在执行方面无效Bn 作为头部开始newPayload(P1) + forkchoiceUpdated(P1){status: SYNCING}BnINV_TB <- P1forkchoiceUpdated(P1){status: INVALID, latestValidHash: 0x00..00}Bn</details>
[x] [Hive] 与具有无效转换区块的链同步
<* A: Genesis <- ... <- TB <- P1 <- P2, B: Genesis <- ... <- INV_TB <- P1 <- P2, B.INV_TB 是一个 有效的PoW 但一个 无效的终端 区块:
INV_TB.TD < TTDINV_TB.parent.TD >= TTDTTD 值A.P2 作为头开始newPayload(B.P2) + forkchoiceUpdated(P2){status: SYNCING}A.P2B: INV_TB <- P1 <- P2forkchoiceUpdated(B.P2){status: INVALID, latestValidHash: 0x00..00}A.P2</details>
[x] [Hive] 使用具有无效转换(transition)区块的链进行重组和同步 <details> <summary>点击查看详情</summary>
A: Genesis <- ... <- TB <- P1 <- P2, B: Genesis <- ... <- TB <- INV_P1 <- P2, B.TB 是一个有效的终端区块, B.INV_P1 是一个无效的 payloadA.P2 作为头开始newPayload(B.P2) + forkchoiceUpdated(B.P2){status: SYNCING}A.P2forkchoiceUpdated(B.P2){status: INVALID, latestValidHash: 0x00..00}A.P2</details>
[x] [Hive] 使用具有无效的后转换(post-transition)区块的链进行重组和同步 <details> <summary>点击查看详情</summary>
A: Genesis <- ... <- TB <- P1 <- P2 <- P3, B: Genesis <- ... <- TB <- P1 <- INV_P2 <- P3, B.TB 是一个有效的终端区块, B.INV_P2 是一个无效的 payloadA.P2 作为头开始newPayload(B.P3) + forkchoiceUpdated(B.P3){status: SYNCING}A.P3forkchoiceUpdated(B.P3){status: INVALID, latestValidHash: B.P1.blockHash}A.P3 (在这种情况下, fcU 将根本不会被应用, 因为它指向无效链上的一个区块, 因此不应该发生 forkchoice 状态的更新; 通常, 当获得 lvh = B.P1.blockHash 时, CL 会发送 fcU(B.P1), 并将规范链切换到 B, 并以 B.P1 作为头)</details>
[x] [Hive] 停止处理gossiped PoW 区块 <details> <summary>点击查看详情</summary>
</details>
[x] [Hive] 停止处理同步的 PoW 区块 <details> <summary>点击查看详情</summary>
Genesis <- ... <- TB <- B1 <- B2 <- ... <- Bn 链开始, 其中 TB 是一个有效的终端区块TB</details>
[x] [Hive] 终端区块被gossiped <details> <summary>点击查看详情</summary>
PoW <-> EL1 <-> EL2 视为连接到 EL 客户端 EL1 的 PoW 客户端, 而 EL1 又连接到 EL 客户端 EL2。EL2 和 PoW 客户端之间没有直接连接。PoW 客户端 gossip 一个终端区块 TBEL2 客户端的头指向 TBPoW 客户端 gossip TB 的后代EL2 客户端的头指向 TB</details>
[x] [Hive] 通过 gossip 在多个终端区块之后构建 Payload <details> <summary>点击查看详情</summary>
PoW <-> EL 视为连接到 EL 客户端 EL 的 PoW 客户端。PoW 客户端生成并 gossip 多个终端区块 TB1, TB2, ... TBNnewPayload(TBN) 被发送到 ELEL 立即返回 {status: VALID, latestValidHash: TBN.BlockHash}</details>
[x] [Hive] 在有效的链上转换 <details> <summary>点击查看详情</summary>
EL: Genesis <- ... <- TB, TB 是一个有效的终端区块CL: Genesis <- ... <- BellatrixTB 作为头开始或者挖掘一条链直到 TBGenesis 开始并构建一条链直到 Bellatrix 并升级到 Bellatrixeth_getBlockByNumber(latest) 返回头eth_getBlockByNumber(safe) 返回最近被证明是合理的区块eth_getBlockByNumber(finalized) 返回最近被最终确定的区块</details>
[x] [Hive] 在无效的终端区块之上构建 <details> <summary>点击查看详情</summary>
Genesis <- ... <- Bn, Bn 是一个有效的 PoW 但一个 无效的终端 区块, 也就是 Bn.TD < EL.TTDBn 是对 CL 观察来说的有效的终端区块, 也就是 CL 的 TERMINAL_TOTAL_DIFFICULTY 被配置成以下方式:Bn.TD >= CL.TTD && Bn.parent.TD < CL.TTDBn 作为头开始Genesis 开始并构建一条链直到 BellatrixExecutionPayload())</details>
[x] [Hive] 在具有无效的终端区块的链上转换 <details> <summary>点击查看详情</summary>
EL: Genesis <- ... <- BnBn 是对 builder 观察来说的有效的终端区块, 也就是说 builder 的 TERMINAL_TOTAL_DIFFICULTY 被配置成以下方式:Bn.TD >= TTD && Bn.parent.TD < TTDBn 是对 importer 观察来说的 无效的 终端区块, 也就是说 builder 的 TERMINAL_TOTAL_DIFFICULTY 被配置成以下方式:Bn.TD < TTDBn 作为头开始Genesis 开始并构建一条链直到 Bellatrix 甚至更远</details>
[x] [Hive] 在具有无效的转换区块的链上转换 <details> <summary>点击查看详情</summary>
EL: Genesis <- ... <- BnBn 是对 builder 和 importer 观察来说的有效的终端区块Bn 作为头开始Genesis 开始并且 builder 构建一条链直到 Bellatrix 甚至更远INVALID</details>
[x] [Hive] 与具有有效的转换区块的链同步 <details> <summary>点击查看详情</summary>
EL.A: Genesis <- ... <- Bn, EL.B: Genesis <- ... <- Bn; A 和 B 具有相等的 TDEL.A 同步, importer 与 EL.B 同步, 两条链上相同的 TD 值阻止了 importer 提前拉取 builder 的链CL: Genesis 开始并且构建一条链直到 Bellatrix 甚至更远EL.ASAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY 继续 -- 这可能值得检查</details>
[x] [Hive] 与具有无效的转换区块的链同步 <details> <summary>点击查看详情</summary>
EL.A: Genesis <- ... <- Bn, EL.B: Genesis <- ... <- Bn; A 和 B 具有相等的 TDEL.A 同步, importer 与 EL.B 同步, 两条链上相同的 TD 值阻止了 importer 提前拉取 builder 的链A.Bn 是对 builder 观察来说的有效的终端区块A.Bn 可能是对 importer 观察来说的 无效的 终端区块, 但这不是必须的, 因为 EL mock 将模拟这种无效性CL: Genesis 开始并且构建一条链直到 Bellatrix 甚至更远EL.ASAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY 继续 -- 在这个场景中可能不会被检查SYNCING 以便让 importer 的 CL 达到离转换区块更远的点newPayload 和 forkchoiceUpdated 调用使用 {status: INVALID, latestValidHash: 0x00..00} 进行响应 -- 如果终端区块或者转换区块是无效的, 这将会在现实生活中发生</details>
[x] [Hive] 与具有无效的后转换区块的链同步 <details> <summary>点击查看详情</summary>
EL.A: Genesis <- ... <- Bn, EL.B: Genesis <- ... <- Bn; A 和 B 具有相等的 TDEL.A 同步, importer 与 EL.B 同步, 两条链上相同的 TD 值阻止了 importer 提前拉取 builder 的链A.Bn 是对 builder 和 importer 观察来说的有效的终端区块CL: Genesis 开始并且构建一条链直到 Bellatrix 甚至更远EL.ASAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY 继续 -- 在这个场景中可能不会被检查SYNCING 以便让 importer 的 CL 达到离 后转换 区块更远的点newPayload 和 forkchoiceUpdated 调用使用 {status: INVALID, latestValidHash: transitionBlock.blockHash} 进行响应 -- 如果终端区块或者转换区块是无效的, 这将会在现实生活中发生</details>
[x] [Hive] 使用具有无效的终端区块的链进行重组和同步 <details> <summary>点击查看详情</summary>
EL.A: Genesis <- ... <- Bn, EL.B: Genesis <- ... <- Bn; A 和 B 具有相等的 TDEL.A 同步, 无效的 builder 和 EL.B 同步, 两条链上相同的 TD 值阻止了 importer 和有效的 builder 提前拉取无效的 builder 的链. 有效的 builder 具有 1/2n - x 的验证者, 无效的 builder 具有 1/2 + x 的验证者, 其中 x 是一个很小的数字A.Bn 是对有效的 builder 和 importer 观察来说的有效的终端区块B.Bn 是对 importer 的观察来说的 无效的 终端区块, 但是对无效的 builder 的观察来说是有效的CL: Genesis 开始并且构建一条链直到 Bellatrix 甚至更远. 他们应该保持在 Bellatrix 之前的共识, 然后从转换区块开始分离SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY 超时进行乐观地应用 -- 这将给 importer 一个遵循有效链的时间{status: INVALID, latestValidHash: 0x00..00} 进行响应</details>
[x] [Hive] Bellatrix 之前的 TTD
<details>
<summary>点击查看详情</summary>
Genesis <- ... <- BnBn 作为工作量证明链的头开始Bn 对所有客户端来说是一个有效的终端区块Bn 之后, 到达 Bellatrix epochBn 之上构建, 因此转换是成功的。</details>
TERMINAL_BLOCK_HASH本节中的场景涵盖了通过指定由 TERMINAL_BLOCK_HASH 参数指定的某个 blockHash 值来指定终端 PoW 区块的情况。
此方案也称为 TERMINAL_BLOCK_HASH 覆盖, 是一种紧急情况方案。在 EL 侧, 覆盖涉及指定以下参数 (按照 EIP-3675):
TERMINAL_BLOCK_HASH – 设置为某个区块的哈希,以成为终端 PoW 区块。TERMINAL_BLOCK_NUMBER – 设置为由 TERMINAL_BLOCK_HASH 指定的区块的编号。TERMINAL_TOTAL_DIFFICULTY – 设置为由 TERMINAL_BLOCK_HASH 指定的区块的总难度值。在 CL 侧,必须通过更新 以下参数 来启用覆盖:
TERMINAL_BLOCK_HASH – 设置为某个区块的哈希,以成为终端 PoW 区块。TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH - 设置为 Merge 转换将被激活的 epoch 。TBH (TERMINAL_BLOCK_HASH) 覆盖的 EL 客户端测试是根据以下 潜在的 实现设计的:
TERMINAL_TOTAL_DIFFICULTY 时触发 Merge 升级TERMINAL_BLOCK_HASH + TERMINAL_BLOCK_NUMBER 将规范链列入白名单实际上,这种语义给出了想要的结果。但是,如果 EL 有两条已达到 TTD 的链,则 EL 可能不会拒绝建立在 blockHash != TBH 的区块之上的转换 payload。但是我们有 CL 侧来强制执行终端区块的 blockHash == TBH。这意味着省略此检查在 EL 侧是可以的。本节中的测试 不 假设 blockHash == TBH 由 EL 客户端实现强制执行。
考虑到以上想法,本节的目标是检查 TBH 覆盖是否会影响 TTD 区块条件。
[ ] 提出具有启用 TBH 覆盖的有效转换区块
<details>
<summary>点击查看详情</summary>
A: Genesis <- ... <- TB, TB 是一个有效的终端区块, TB.blockHash == TBHB: Genesis <- ... <- Bn, B 链比 A 更重, 除非激活 TBH 覆盖,否则将成为规范链A 和 B 开始forkchoiceUpdated(headBlockHash: TB.blockHash, payloadAttributes: mergeTransitionBlockAttributes)headBlockHash{status: VALID, payloadId: mergeTransitionPayloadId}getPayload(mergeTransitionPayloadId)newPayload(mergeTransitionPayload)VALID</details>
[ ] 在启用 TBH 覆盖的情况下,在无效终端区块之上构建
<details>
<summary>点击查看详情</summary>
Genesis <- ... <- INV_TB, INV_TB 是一个有效的 PoW 但一个无效的终端区块,即 INV_TB.TD < TTD 并且 TBH != INV_TB.blockHashINV_TB 作为头开始forkchoiceUpdated(headBlockHash: TB.blockHash, payloadAttributes: mergeTransitionBlockAttributes){status: INVALID, latestValidHash: 0x00..00, payloadId: null}INV_TB.TD < TTD,则 EL 的头指向 INV_TB,如果 INV_TB.parent.TD >= TTD,则指向 INV_TB.parent</details>
[ ] 使用启用的 TBH 覆盖,在有效链上转换
<details>
<summary>点击查看详情</summary>
A: Genesis <- ... <- TB <- P1 <- P2 <- P3, TB 是一个有效的终端区块, 也就是 TB.blockHash == TBHB: Genesis <- ... <- Bn, B 链比 A 更重,除非激活 TBH 覆盖,否则将成为规范链A 导入到 TB 并且 B 导入到 Bn 开始newPayload(A.P1){status: VALID, latestValidHash: payload.blockHash}TBforkchoiceUpdated(head: P1, safe: 0x00..00, finalized: 0x00..00){status: VALID, latestValidHash: forkchoiceState.headBlockHash}P1eth_getBlockByNumber(safe) 返回 -39001: Unknown block 错误eth_getBlockByNumber(finalized) 返回 -39001: Unknown block 错误newPayload(P2) + forkchoiceUpdated(head: P2, safe: P1, finalized: 0x00..00)P2eth_getBlockByNumber(safe) 返回 -39001: Unknown block 错误eth_getBlockByNumber(finalized) 返回 -39001: Unknown block 错误newPayload(P3) + forkchoiceUpdated(head: P3, safe: P2, finalized: P1)P3eth_getBlockByNumber(safe) 返回 P2eth_getBlockByNumber(finalized) 返回 P1</details>
[ ] 在启用 TBH 覆盖的情况下,在无效链上转换
<details>
<summary>点击查看详情</summary>
Genesis <- ... <- INV_TB <- P1, INV_TB 是一个 有效的 PoW 但一个 无效的终端 区块, 也就是说 TBH != INV_TB.blockHash 并且以下任何一个为真:INV_TB.TD < TTDINV_TB.parent.TD >= TTD -- 这可能需要第二个具有更高 TTD 值的 ELINV_TB 作为头开始newPayload(P1){status: INVALID, latestValidHash: 0x00..00}INV_TB.TD < TTD,则 EL 的头指向 INV_TB,如果 INV_TB.parent.TD >= TTD,则指向 INV_TB.parent</details>
[ ] 与具有有效转换的链同步,启用 TBH 覆盖
<details>
<summary>点击查看详情</summary>
A: Genesis <- ... <- Bn <- TB <- P1, TB 是一个有效的终端区块,也就是 TB.blockHash == TBHB: Genesis <- ... <- Bn, B 链比 A 更重,除非激活 TBH 覆盖,否则将成为规范链B 开始newPayload(P1) + forkchoiceUpdated(P1){status: SYNCING}BnTB <- P1forkchoiceUpdated(P1){status: VALID, latestValidHash: null}P1</details>
[ ] 停止处理启用了 TBH 覆盖的同步 PoW 区块
<details>
<summary>点击查看详情</summary>
Genesis <- ... <- TB <- B1 <- B2 <- ... <- Bn 链开始,其中 TB 是一个有效的终端区块,也就是 TB.blockHash == TBHTB</details>
在本节中,builder 节点意味着在其上运行所有验证者并因此构建链的节点。 Importer 是一个导入由 builder 构建并从 builder 接收的链的节点。
[ ] 在启用 TBH 覆盖的情况下,在有效链上转换
<details>
<summary>点击查看详情</summary>
EL.A: Genesis <- ... <- TB, TB 是一个有效的终端区块。也就是 TB.blockHash == TBHEL.B: Genesis <- ... <- Bn, B 链比 A 更重,除非激活 TBH 覆盖,否则将成为规范链CL: Genesis <- ... <- BellatrixA 和 B 开始TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH 大于 BELLATRIX_FORK_EPOCHGenesis 开始并构建一条链直到 Bellatrix 并升级到 BellatrixTERMINAL_BLOCK_HASH_ACTIVATION_EPOCH 时开始EL.A.TB,并且 PoS 链建立在该区块之上eth_getBlockByNumber(latest) 返回头eth_getBlockByNumber(safe) 返回最近被证明是合理的区块eth_getBlockByNumber(finalized) 返回最近被最终确定的区块</details>
[ ] 在 TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH 之前转换
<details>
<summary>点击查看详情</summary>
EL: Genesis <- ... <- BnBn 是对 builder 和 importer 观察来说的有效的终端区块,也就是说 TBH == Bn.blockHashTERMINAL_BLOCK_HASH_ACTIVATION_EPOCH 比 builder 侧的要大得多Bn 作为头开始Genesis 开始并构建一条链直到 Bellatrix 甚至更远</details>
[ ] 转换与不匹配的 TERMINAL_BLOCK_HASH
<details>
<summary>点击查看详情</summary>
EL: Genesis <- ... <- BnBn 是对 builder 的观察来说的有效的终端区块,也就是说 builder 的 TBH == Bn.blockHashBn 是对 importer 的观察来说的 无效的 终端区块,也就是说 builder 的 TBH != Bn.blockHashTERMINAL_BLOCK_HASH_ACTIVATION_EPOCH 在 builder 和 importer 侧是相同的Bn 作为头开始Genesis 开始并构建一条链直到 Bellatrix 甚至更远</details>
- 原文链接: github.com/txrx-research...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!