本文档描述了 Engine API 的测试用例,这些测试用例都是从合并后的世界开始的,即 Genesis
是一个终端PoW块。
本文档中描述的所有测试用例都始于合并后的世界,即 Genesis
是一个最终的 PoW 区块。
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
[x] [Hive] 无效的 block_hash
<details>
<summary>点击查看详情</summary>
SYNCING
状态以及不在 SYNCING
状态时 block_hash
的验证,以确保同步不会影响验证block_hash
所有可能的不一致情况,这些情况很容易发生,例如随机哈希、如果区块是有效的 PoW 区块时的哈希等{status: INVALID_BLOCK_HASH, latestValidHash: null, validationError: errorMessage | null}
</details>
[x] [Hive] VALID
规范 链 payload
<details>
<summary>点击查看详情</summary>
P
是扩展规范链的 VALID
payloadnewPayload(P)
{status: VALID, latestValidHash: payload.blockHash, validationError: null}
P
的父级)forkchoiceUpdated(headBlock: P)
{payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash, validationError: null}, payloadId: null}
P
</details>
[x] [Hive PR] 不一致的 ForkchoiceState
<details>
<summary>点击查看详情</summary>
A: Genesis <- P1 <- P2 <- P3
,B: Genesis <- P1' <- P2' <- P3'
A
和 B
启动forkchoiceUpdated(finalized: A.P1, safe: A.P2, head: A.P3
)A.P3
,finalized
和 safe
区块符合预期forkchoiceUpdated(finalized: A.P1, safe: A.P2, head: B.P3'
)forkchoiceUpdated(finalized: A.P1, safe: B.P2', head: A.P3
)forkchoiceUpdated(finalized: B.P1', safe: A.P2, head: A.P3
){error: {code: -38002, message: "Invalid forkchoice state"}}
forkchoiceUpdated(finalized: B.P1', safe: B.P2', head: B.P3'
)B.P3
,finalized
和 safe
区块符合预期</details>
[x] [Hive] INVALID
规范 链 payload
<details>
<summary>点击查看详情</summary>
INV_P
是扩展规范链的 INVALID
payloadINV_P
具有有效的 block_hash
,但由于以下无效属性而被无效:stateRoot
无效receiptsRoot
无效blockNumber
小于或等于 parent.blockNumber
或大于 parent.blockNumber+1
gasLimit
大于 parent.gasLimit + parent.gasLimit / 1024
或小于 parent.gasLimit - parent.gasLimit / 1024
gasUsed
不等于包含的交易使用的 gastimestamp
小于或等于 parent.timestamp
baseFeePerGas
与 parent.baseFeePerGas
和 parent.gasUsed
不一致transactions
具有以下任一情况:
newPayload(INV_P)
{status: INVALID, latestValidHash: P.parentHash, validationError: errorMessage | null}
eth_getBlockByHash
访问 INV_P
</details>
[x] [Hive] 具有未知父级的 Payload <details> <summary>点击查看详情</summary>
A: Genesis <- P1 <- P2 <- P3
,B: Genesis <- P1' <- P2' <- P3'
Genesis
区块和状态启动forkchoiceUpdated(A.P1)
{status: SYNCING}
newPayload(A.P1) + forkchoiceUpdated(A.P1)
forkchoiceUpdated(A.P1)
,直到它响应 {status: VALID}
,head 设置为 A.P1
newPayload(B.P2')
{status: SYNCING}
newPayload(B.P1') + newPayload(B.P2') + forkchoiceUpdated(B.P2')
forkchoiceUpdated(B.P2')
,直到它响应 {status: VALID}
,head 设置为 B.P2'
forkchoiceUpdated(A.P1)
A.P1
newPayload(A.P3)
{status: SYNCING}
newPayload(A.P2) + newPayload(A.P3) + forkchoiceUpdated(A.P3)
forkchoiceUpdated(A.P3)
,直到它响应 {status: VALID}
,head 设置为 A.P3'
</details>
[x] [Hive] SYNCING
具有无效链
<details>
<summary>点击查看详情</summary>
A: Genesis <- P1 <- P2 <- P3 <- P4
,B: Genesis <- P1' <- INV_P2' <- P3' <- P4'
,INV_P2'
是无效的 payloadINV_P2'
具有有效的 block_hash
,但由于以下无效属性而被无效:stateRoot
无效receiptsRoot
无效blockNumber
小于或等于 parent.blockNumber
或大于 parent.blockNumber+1
gasLimit
大于 parent.gasLimit + parent.gasLimit / 1024
或小于 parent.gasLimit - parent.gasLimit / 1024
gasUsed
不等于包含的交易使用的 gastimestamp
小于或等于 parent.timestamp
baseFeePerGas
与 parent.baseFeePerGas
和 parent.gasUsed
不一致transactions
具有以下任一情况:
A: P4
区块和状态启动newPayload(INV_P2') + forkchoiceUpdated(head: INV_P2')
{status: SYNCING, latestValidHash: null, validationError: null}
P1'
newPayload(P3')
newPayload(P3')
,直到响应为 INVALID
,且 latestValidHash: P1'.blockHash
finalized
、safe
和 head 区块没有改变,即来自 A
链newPayload(P2') + forkchoiceUpdated(head: P2')
P1'
forkchoiceUpdated(P2')
,直到响应为 INVALID
,且 latestValidHash: P1'.blockHash
</details>
[x] [Hive] 构建一个 payload <details> <summary>点击查看详情</summary>
Genesis <- P1
Genesis
区块和状态启动newPayload(P1)
getPayload(payloaId: random)
{error: {code: -38001, message: "Unknown payload"}}
forkchoiceUpdated(P1, payloadAttributes: {validTimestamp, validPrevRandao, validFeeRecipient})
existingPayloadId
getPayload(payloaId: random)
{error: {code: -38001, message: "Unknown payload"}}
getPayload(payloaId: existingPayloadId)
returnedPayload
newPayload(returnedPayload)
{status: VALID}
forkchoiceUpdated(returnedPayload)
{status: VALID}
,returnedPayload
变为 headforkchoiceUpdated(returnedPayload, payloadAttributes: {validTimestamp, validPrevRandao, validFeeRecipient})
existingPayloadId2
getPayload(payloaId: existingPayloadId2)
returnedPayload2
newPayload(returnedPayload2)
{status: VALID}
returnedPayload
仍为 headgetPayload(payloaId: existingPayloadId2)
{error: {code: -38001, message: "Unknown payload"}}
</details>
[x] [Hive] 无效的 PayloadAttributes
<details>
<summary>点击查看详情</summary>
Genesis <- P1
Genesis
区块和状态启动newPayload(P1)
forkchoiceUpdated(P1, payloadAttributes: {timestamp: 0, validPrevRandao, validFeeRecipient})
{error: {code: -38003, message: "Invalid payload attributes"}}
P1
</details>
[x] [Hive] VALID
侧 链 payload
<details>
<summary>点击查看详情</summary>
P'
是扩展侧链的 VALID
payloadP
和 P'
包含相同的交易,该交易使用 PREVRANDAO
来修改存储P
和 P'
具有不同的 prevRandao
值newPayload(P')
ACCEPTED
或 VALID
forkchoiceUpdated(headBlock: P')
{payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash, validationError: null}, payloadId: null}
P'
P'.prevRandao
正确更新</details>
[x] [Hive] 更新规范链上的 finalized 和 safe 区块 <details> <summary>点击查看详情</summary>
Genesis <- P1 <- P2 <- P3 <- P4
是扩展规范链的有效 payload 的子链newPayload(P1) + forkchoiceUpdated(finalized: Genesis, safe: Genesis, head: P1)
newPayload(P2) + forkchoiceUpdated(finalized: Genesis, safe: P1, head: P2)
safe
设置为 P1
,将 head 设置为 P2
,finalized == Genesis
newPayload(P3) + forkchoiceUpdated(finalized: P1, safe: P2, head: P3)
finalized
设置为 P1
,将 safe
设置为 P2
,将 head 设置为 P3
newPayload(P4) + forkchoiceUpdated(finalized: P2, safe: P3, head: P4)
finalized
设置为 P2
,将 safe
设置为 P3
,将 head 设置为 P4
</details>
[x] [Hive] 更新侧链上的 safe 区块 <details> <summary>点击查看详情</summary>
A: Genesis <- P1 <- P2 <- P3
是扩展规范链的有效 payload 的子链,B: Genesis <- P1 <- P2' <- P3'
是扩展侧链的有效 payload 的子链A
并调用 forkchoiceUpdated(finalized: P1, safe: P2, head: P3)
finalized
设置为 P1
,将 safe
设置为 P2
,将 head 设置为 P3
newPayload(P2') + newPayload(P3')
导入 B
并调用 forkchoiceUpdated(finalized: P1, safe: P2', head: P3')
forkchoiceUpdated
轮询,因为 EL 可能会响应正在同步finalized
设置为 P1
,将 safe
设置为 P2'
,将 head 设置为 P3'
</details>
[x] [Hive] SYNCING
具有有效链
<details>
<summary>点击查看详情</summary>
Genesis <- P1 <- P2 <- P3 <- ... <- Pn
Genesis
区块和状态启动newPayload(Pn) + forkchoiceUpdated(head: Pn)
{status: SYNCING, latestValidHash: null, validationError: null}
P1 <- P2 <- P3 <- ... <- Pn-1
并成功完成同步过程newPayload(Pn+1) + forkchoiceUpdated(head: Pn+1)
newPayload + forkchoiceUpdated
,直到响应为 VALID
finalized
、safe
和 head 区块已相应设置</details>
[x] [Hive PR] 在 SYNCING
时重新组织回规范链
<details>
<summary>点击查看详情</summary>
A: Genesis <- P1 <- P2 <- P3 <- P4
, B: Genesis <- P1' <- P2' <- P3' <- P4'
A.P3
区块,即 A.P3
是 headnewPayload(B.P4') + forkchoiceUpdated(head: B.P4')
{status: SYNCING, latestValidHash: null, validationError: null}
B
链的其余部分应不可用,以使 EL 无法完成其同步过程newPayload(A.P4) + forkchoiceUpdated(A.P4)
forkchoiceUpdated(finalized: P2, safe: P3, head: P4)
,直到响应为 VALID
finalized
、safe
和 head 区块已相应设置</details>
[x] [Hive] 重新组织为删除交易的侧链 <details> <summary>点击查看详情</summary>
A: Genesis <- P1
,B: Genesis <- P1'
P1
和 P1'
是有效的 payloadP1
包含交易 Tx1
,而 P1'
不包含任何交易newPayload(A.P1) + forkchoiceUpdated(head: A.P1)
{status: VALID, latestValidHash: A.P1, validationError: null}
Tx1
收据Tx1
收据newPayload(B.P1') + forkchoiceUpdated(head: B.P1')
{status: VALID, latestValidHash: B.P1', validationError: null}
Tx1
收据Tx1
收据</details>
[x] [Hive] 具有现有规范链 payload 的 newPayload
<details>
<summary>点击查看详情</summary>
Genesis <- P1 <- P2 <- P3 <- ... <- Pn
newPayload(P1) + forkchoiceUpdated(head: P1)
到 newPayload(Pn) + forkchoiceUpdated(head: Pn)
Pn
newPayload(P1)
到 newPayload(Pn)
VALID
且没有错误newPayload(Pn+1) + forkchoiceUpdated(head: Pn+1)
</details>
[x] [Hive] 导入并重新组织到先前验证的 payload <details> <summary>点击查看详情</summary>
Genesis <- P1 <- P2 <- P3 <- P4
head: P4, safe: P3, finalized: P2
启动newPayload(P3)
{status: VALID, latestValidHash: P3.blockHash}
forkchoiceUpdated(head: P3, safe: P2, finalized: P1)
{status: VALID, latestValidHash: P3.blockHash}
</details>
[x] [Hive] 导入并重新组织到侧链上先前验证的 payload <details> <summary>点击查看详情</summary>
A: Genesis <- P1 <- P2 <- P3 <- P4
,B: Genesis <- P1 <- P2 <- P3 <- P4
A
和 B
链以及作为 head 的 A.P4
启动newPayload(B.P3)
{status: VALID, latestValidHash: B.P3.blockHash}
forkchoiceUpdated(head: B.P3, payloadAttributes: buildProcessAttributes)
payloadStatus: {status: VALID, latestValidHash: B.P3.blockHash}, payloadId: buildProcessId
getPayload(payloadId: buildProcessId)
builtPayload
newPayload(builtPayload)
{status: VALID, latestValidHash: builtPayload.blockHash}
</details>
[x] [Hive] QUANTITY
字段值已正确编码
<details>
<summary>点击查看详情</summary>
P1
具有大于 255
的所有 QUANTITY
字段值BeaconBlock(P1)
P1
QUANTITY
字段都是大端序</details>
[x] [Hive] INVALID
规范 链 payload
<details>
<summary>点击查看详情</summary>
INV_P
是扩展规范链的 INVALID
payloadBeaconBlock(INV_P)
INVALID
GET /eth/v1/beacon/headers/{block_id}
访问 BeaconBlock(INV_P)
</details>
[x] [Hive] 无效的 Timestamp
<details>
<summary>点击查看详情</summary>
INV_P
是由 EL 生成的扩展规范链的 INVALID
payload,其中 timestamp
值超出当前 slot 时间范围INV_P
</details>
[x] [Hive] 无效的 PrevRandao
<details>
<summary>点击查看详情</summary>
INV_P
是由 EL 生成的扩展规范链的 INVALID
payload,其中 prevRandao
值不是给定 slot 的预期 randao 混合值INV_P
</details>
[x] [Hive] 无效的 block_hash
<details>
<summary>点击查看详情</summary>
P
响应 INVALID_BLOCK_HASH
BeaconBlock(P)
</details>
[x] [Hive] SYNCING
具有无效链
<details>
<summary>点击查看详情</summary>
Genesis <- P1 <- P2 <- P3 <- P4
BeaconBlock(P1) ... BeaconBlock(P4)
区块newPayload(P2)
上响应 SYNCING
newPayload(P4)
上响应 status: INVALID, latestValidHash: P1.blockHash
BeaconBlock(P1)
forkchoiceUpdated(P1)
finalized
、safe
和 head 区块符合预期</details>
[x] [Hive] baseFee
编码检查
<details>
<summary>点击查看详情</summary>
P1
,其中 baseFee
字段大于或等于 256BeaconBlock(P1)
已并入链中</details>
[x] [Hive] 超时 <details> <summary>点击查看详情</summary>
P
是扩展规范链的 VALID
payloadBeaconBlock(P)
newPayload
和 forkchoiceUpdated
,在响应之前暂停 timeout - 1s
秒BeaconBlock(P)
是 CL 链的 headP
是 EL 链的 head</details>
[x] [Hive PR] 由于乐观同步而没有可行的 head <details> <summary>点击查看详情</summary>
SLOTS_PER_EPOCH = 32
... <- P0 <- P1 <- P2 <- ... <- Pn
BeaconBlock(P0).slot % SLOTS_PER_EPOCH == 0
BeaconBlock(P0).slot >= 128
距离 Genesis 足够远BeaconBlock(P0), ..., BeaconBlock(P10)
status: VALID
BeaconBlock(P11), ..., BeaconBlock(P33)
:EL 模拟返回 status: VALID
BeaconBlock(P10), ..., BeaconBlock(P32)
:EL 模拟返回 status: SYNCING
BeaconBlock(P33)
newPayload(P33)
:{status: INVALID, latestValidHash: P10.blockHash}
newPayload(P33)
:{status: SYNCING}
forkChoiceUpdated(P33)
:{status: INVALID, latestValidHash: P10.blockHash}
execution_optimistic
标志是否为 true
BeaconBlock(P10)
BeaconBlock(P11, slot34), ..., BeaconBlock(Pn, slotN)
:EL 模拟返回 status: VALID
BeaconBlock(P11, slot34), ..., BeaconBlock(Pn, slotN)
:EL 模拟返回 status: VALID
slotN
应该足够高,以便 importer 可以从乐观状态恢复,N >= 96
BeaconBlock(Pn, slotN)
是 head</details>
- 原文链接: github.com/txrx-research...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!