Alert Source Discuss
Standards Track: Networking

EIP-2481: eth/66 请求标识符

为 eth 协议的所有请求引入一个请求 ID

Authors Christoph Burgdorf (@cburgdorf)
Created 2020-01-17
Requires EIP-2464

摘要

eth 协议定义了各种请求和响应命令,用于在以太坊节点之间交换数据。例如,要向对等节点请求一组特定的标头,节点会向其发送 GetBlockHeaders 命令。

引用自 GetBlockHeaders 规范定义:

[block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]

要求对等节点返回 BlockHeaders 消息。答复必须包含若干区块头,当 reverse0 时,区块头编号递增;当 1 时,编号递减,skip 区块分开,从规范链中的区块 block(由编号或哈希表示)开始,并且最多包含 maxHeaders 个项目。

接收 GetBlockHeaders 命令的节点应该相应地使用 BlockHeaders 响应命令来回答它。

引用自 BlockHeaders 规范定义:

[blockHeader_0, blockHeader_1, ...]

回复 GetBlockHeaders。列表中的项目(在消息 ID 之后)是区块头,格式在主以太坊规范中描述,之前在 GetBlockHeaders 消息中被请求。如果未找到任何请求的区块头,则此消息可能有效地不包含任何区块头。单个消息中可以请求的标头数量可能受到实现定义的限制。

让我们考虑一个客户端同时向其一个对等节点发出多个 GetBlockHeaders 请求。本质上,不能保证预期的响应以与发送顺序相同的顺序到达。为了使客户端将传入的响应与正确的请求相关联,它必须遍历所有挂起的请求,尝试根据其内容将其与传入的响应进行匹配。

对于诸如空响应之类的模棱两可的响应,这可能特别棘手。

此 EIP 建议更改 GetBlockHeadersBlockHeaders 命令以包含 request_id

request_id 是一个 64 位整数,由客户端在发出请求时设置。在响应端,来自传入请求的完全相同的 request_id 被放回响应对象中。

此更改允许请求客户端将传入的响应 直接 匹配回其挂起的请求,而无需遍历所有挂起的请求以检查它们是否可能基于响应数据进行匹配。

所选的请求/响应对是 eth 网络协议中许多类似请求/响应对的示例。

动机

eth 协议的请求/响应对中缺少请求标识符,这给每个以太坊客户端带来了不必要的代码复杂性负担。这也使得通信效率稍低。另一个论点是,添加请求标识符使协议与 les 协议更加一致,后者 已经 为每个请求/响应对定义了请求标识符。

规范

更改 eth 协议中的以下消息类型:

  • GetBlockHeaders (0x03)
    • 当前 (eth/65): [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]
    • 然后 (eth/66): [request_id: P, [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]]
  • BlockHeaders (0x04)
    • 当前 (eth/65): [blockHeader_0, blockHeader_1, ...]
    • 然后 (eth/66): [request_id: P, [blockHeader_0, blockHeader_1, ...]]
  • GetBlockBodies (0x05)
    • 当前 (eth/65): [hash_0: B_32, hash_1: B_32, ...]
    • 然后 (eth/66): [request_id: P, [hash_0: B_32, hash_1: B_32, ...]]
  • GetPooledTransactions (0x09):
    • 当前 (eth/65)[hash_0: B_32, hash_1: B_32, ...]
    • 然后 (eth/66)[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]
  • PooledTransactions (0x0a):
    • 当前 (eth/65)[[nonce: P, receivingAddress: B_20, value: P, ...], ...]
    • 然后 (eth/66)[request_id: P, [[nonce: P, receivingAddress: B_20, value: P, ...], ...]]
  • BlockBodies (0x06)
    • 当前 (eth/65): [hash_0: B_32, hash_1: B_32, ...]
    • 然后 (eth/66): [request_id: P, [hash_0: B_32, hash_1: B_32, ...]]
  • GetNodeData (0x0d)
    • 当前 (eth/65): [hash_0: B_32, hash_1: B_32, ...]
    • 然后 (eth/66): [request_id: P, [hash_0: B_32, hash_1: B_32, ...]]
  • NodeData (0x0e)
    • 当前 (eth/65): [value_0: B, value_1: B, ...]
    • 然后 (eth/66): [request_id: P, [value_0: B, value_1: B, ...]]
  • GetReceipts (0x0f)
    • 当前 (eth/65): [blockHash_0: B_32, blockHash_1: B_32, ...]
    • 然后 (eth/66): [request_id: P, [blockHash_0: B_32, blockHash_1: B_32, ...]]
  • Receipts (0x10)
    • 当前 (eth/65): [[receipt_0, receipt_1], ...]
    • 然后 (eth/66): [request_id: P, [[receipt_0, receipt_1], ...]]

详细说明,每个命令都以以下方式更改:

  1. 创建一个列表,其中 request_id 是第一个元素。
  2. 使第二个元素成为定义当前方案中整个命令的列表。

request_id 具有以下特征:

  • 64 位整数
  • 不需要是顺序的(可以是随机的)
  • 允许重复

理由

问:效率的提高可能会鼓励客户端用过多的并发请求来淹没其对等节点

如果对等节点感觉没有得到很好的对待,他们总是可以进行限制或断开连接。这与今天的情况相同。

问:如果 les 已经这样定义了命令,为什么不直接使用 les 协议?

实际上,在网络中很难找到提供 les 协议的对等节点。造成这种情况的原因有很多,但可能归结为客户端默认设置、不成熟的实现或缺乏激励。

问:网络今天可以正常工作,这难道不是在增加膨胀吗?

这在每个命令中添加了一个整数,同时降低了代码复杂性并提高了网络效率。这种添加似乎是合理的。

问:为什么不要求请求 ID 是顺序的?

假设请求 ID 在连接时始终从 0 开始计数,那么当连接丢失并且客户端重新连接并重新开始使用他们在上一个会话中使用过的相同请求 ID 时,事情会变得混乱。

问:为什么允许重复的请求 ID?

主要的好处是实现方面的灵活性和简单性。客户端可以决定在多个不同的请求类型之间共享相同的 ID,因为它们无论如何都是自然分离的。客户端甚至可以决定完全不依赖请求 ID,因此在所有请求中使用相同的常量请求 ID。

问:为什么选择 64 位整数作为请求 ID

选择 64 位整数是为了与 les 协议保持兼容性。

向后兼容性

此 EIP 以向后不兼容的方式扩展了 eth 协议,并且需要推出一个新版本 eth/66。但是,devp2p 支持并行运行同一线路协议的多个版本,因此推出 eth/66 不需要客户端协调,因为未更新的客户端可以继续使用 eth/65

此 EIP 不会更改共识引擎,因此 不需要 硬分叉。

测试用例

这些测试用例涵盖了所有重新定义的消息类型的 RLP 编码,其中 rlp 部分是 data 部分中定义的消息的 rlp 编码。

{
  "type": "GetBlockHeadersPacket66",
  "rlp": "0xe8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580",
  "data": {
    "RequestId": 1111,
    "Origin": {
      "Hash": "0x00000000000000000000000000000000000000000000000000000000deadc0de",
      "Number": 0
    },
    "Amount": 5,
    "Skip": 5,
    "Reverse": false
  }
}
{
  "type": "GetBlockHeadersPacket66",
  "rlp": "0xca820457c682270f050580",
  "data": {
    "RequestId": 1111,
    "Origin": {
      "Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "Number": 9999
    },
    "Amount": 5,
    "Skip": 5,
    "Reverse": false
  }
}
{
  "type": "BlockHeadersPacket66",
  "rlp": "0xf90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000",
  "data": {
    "RequestId": 1111,
    "BlockHeadersPacket": [
      {
        "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "sha3Uncles": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "miner": "0x0000000000000000000000000000000000000000",
        "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
        "difficulty": "0x8ae",
        "number": "0xd05",
        "gasLimit": "0x115c",
        "gasUsed": "0x15b3",
        "timestamp": "0x1a0a",
        "extraData": "0x7788",
        "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "nonce": "0x0000000000000000",
        "hash": "0x8c2f2af15b7b563b6ab1e09bed0e9caade7ed730aec98b70a993597a797579a9"
      }
    ]
  }
}
{
  "type": "GetBlockBodiesPacket66",
  "rlp": "0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef",
  "data": {
    "RequestId": 1111,
    "GetBlockBodiesPacket": [
      "0x00000000000000000000000000000000000000000000000000000000deadc0de",
      "0x00000000000000000000000000000000000000000000000000000000feedbeef"
    ]
  }
}

```json { “type”: “BlockBodiesPacket66”, “rlp”: “0xf902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000000”, “data”: { “RequestId”: 1111, “BlockBodiesPacket”: [ { “Transactions”: [ { “nonce”: “0x8”, “gasPrice”: “0x4a817c808”, “gas”: “0x2e248”, “to”: “0x3535353535353535353535353535353535353535”, “value”: “0x200”, “input”: “0x”, “v”: “0x25”, “r”: “0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12”, “s”: “0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10”, “hash”: “0x588df025c4c2d757d3e314bd3dfbfe352687324e6b8557ad1731585e96928aed” }, { “nonce”: “0x9”, “gasPrice”: “0x4a817c809”, “gas”: “0x33450”, “to”: “0x3535353535353535353535353535353535353535”, “value”: “0x2d9”, “input”: “0x”, “v”: “0x25”, “r”: “0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb”, “s”: “0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb”, “hash”: “0xf39c7dac06a9f3abf09faf5e30439a349d3717611b3ed337cd52b0d192bc72da” } ], “Uncles”: [ { “parentHash”: “0x0000000000000000000000000000000000000000000000000000000000000000”, “sha3Uncles”: “0x0000000000000000000000000000000000000000000000000000000000000000”, “miner”: “0x0000000000000000000000000000000000000000”, “stateRoot”: “0x0000000000000000000000000000000000000000000000000000000000000000”, “transactionsRoot”: “0x0000000000000000000000000000000000000000000000000000000000000000”, “receiptsRoot”: “0x0000000000000000000000000000000000000000000000000000000000000000”, “logsBloom”: “0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Citation

Please cite this document as:

Christoph Burgdorf (@cburgdorf), "EIP-2481: eth/66 请求标识符," Ethereum Improvement Proposals, no. 2481, January 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2481.