EIP-2481 eth/66 request identifier

Final · Networking & nodes · EIP status Final · created 2020-01-17

A request number (request_id) is attached to every request and response message in the eth protocol, which Ethereum nodes use to exchange data with each other. This change bumps the protocol version from eth/65 to eth/66.

Why it is needed

Ethereum nodes operate by requesting data such as block headers, block bodies, and receipts from other nodes (peers) and receiving responses. However, the existing eth protocol had no number pairing requests with responses. If a node sent several requests to the same peer at once, there was no guarantee responses would come back in the order sent, so the node had to guess which request a given response belonged to by examining its contents against every pending request one by one. Responses that cannot be distinguished by content alone, such as empty responses, were especially hard to match. This approach forced unnecessarily complex code on every Ethereum client and also hurt communication efficiency. This EIP attaches a number when sending a request and has the response echo back the same number, allowing responses to be matched directly to requests.

What changes

Today

After EIP-2481

Who is affected

In depth

How the message structure changes

The existing message is wrapped in two layers. First, a list is created with request_id as its first element. Second, the list that previously defined the entire command is placed as the second element. For example, GetBlockHeaders(0x03) changes from eth/65's [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}] to eth/66's [request_id: P, [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]]. The response, BlockHeaders(0x04), is changed the same way to [request_id: P, [blockHeader_0, blockHeader_1, ...]].

The ten messages that change

All five request/response pairs change: GetBlockHeaders(0x03) and BlockHeaders(0x04), GetBlockBodies(0x05) and BlockBodies(0x06), GetPooledTransactions(0x09) and PooledTransactions(0x0a), GetNodeData(0x0d) and NodeData(0x0e), and GetReceipts(0x0f) and Receipts(0x10). All are unified into the structure where request_id is the first element and the existing command list is the second.

Three properties of request_id

request_id is a 64-bit integer, need not be sequential (it may be random), and duplicates are allowed. Sequentiality is not enforced because a client that reconnects after a disconnect and starts counting from 0 again could collide with numbers used in a previous session, causing confusion. Duplicates are allowed for implementation flexibility and simplicity. Since different request types are naturally distinguishable, the same number can be shared across multiple request types, and an implementation that does not rely on request_id at all and uses the same constant for every request is also possible. 64 bits was chosen for compatibility with the les protocol.

Relationship to the les protocol

The les protocol, used for light clients, already defines a request identifier for every request/response pair. This EIP has the effect of making the eth protocol more similar to les. To the question of why not simply use les instead, the original document answers that in practice it is much harder to find peers serving les on the real network, citing client default settings, immature implementations, and lack of incentive as reasons. To the question of whether adding one more integer is unnecessary overhead, it answers that adding one integer per message is justified because it reduces code complexity and improves networking efficiency.

Backward compatibility: deployed without a hard fork

Because this change extends the eth protocol in a backward-incompatible way, a new version, eth/66, must be deployed. However, since devp2p can run multiple versions of the same wire protocol side by side, clients that have not updated can simply keep using eth/65. It can therefore be deployed without coordinating timing across clients. Since the consensus engine is untouched, no hard fork is needed either. This EIP presupposes EIP-2464, which defines eth/65.

Test cases and RLP encoding

The original document provides RLP encoding test cases for every redefined message type. Each test pairs a message defined in the data section with the result of RLP-encoding it. For example, the GetBlockHeadersPacket66 test shows that a request containing fields such as RequestId 1111, Amount 5, Skip 5, and Reverse false encodes to 0xe8820457e4a0...0580. The same kind of verification data exists for all ten messages, including BlockHeaders, BlockBodies, NodeData, Receipts, and PooledTransactions, allowing client implementations to be checked against it. This EIP's status is Final, meaning the specification is finalized.

Original EIP · ← EIPs