EIP 2364: eth/64: forkid-extended protocol handshake Source

AuthorPéter Szilágyi
Discussions-Tohttps://github.com/ethereum/EIPs/issues/2365
StatusDraft
TypeStandards Track
CategoryNetworking
Created2019-11-08
Requires 2124

Abstract

The forkid (EIP-2124) was designed to permit two Ethereum nodes to quickly and cheaply decide if they are compatible or not, not only at a genesis/networking level, but also from the perspective of the currently passed network updates (i.e. forks).

EIP-2124 only defines how the forkid is calculated and validated, but does not specify how the forkid should be exchanged between peers. This EIP specifies the inclusion of the forkid as a new field in the Ethereum wire protocol (eth) handshake (releasing a new version, eth/64).

By cross-validating forkid during the handshake, incompatible nodes can disconnect before expensive block exchanges and validations take place (PoW check, EVM execution, state reconstruction). This further prevents peer slots from being taken up by nodes that are incompatible, but have not yet been detected as such.

Motivation

From a micro perspective, cutting off incompatible nodes from one another ensures that a node only spends its resources on tasks that are genuinely useful to it. The sooner we can decide the remote peer is useless, the less time and processing we expend in vain.

From a macro perspective, keeping incompatible nodes partitioned from one another ensures that disjoint clusters retain more resources for maintaining their own chain, thus raising the quality of service for all networks globally.

Specification

The specification is tiny since most parts are already specified in EIP-2124. eth/63 is not specified as an EIP, but is maintained here.

  • Implement forkid generation and validation per EIP-2124.
  • Advertise a new eth protocol capability (version) at eth/64.
    • The old eth/63 protocol should still be kept alive side-by-side, until eth/64 is sufficiently adopted by implementors.
  • Redefine Status (0x00) for eth/64 to add a trailing forkid field:
    • Old packet: [protocolVersion, networkId, td, bestHash, genesisHash]
    • New packet: [protocolVersion, networkId, td, bestHash, genesisHash, forkid], where forkid is [forkHash: [4]byte, forkNext: uint64] (fields per EIP-2124 ).

Whenever two peers connect using the eth/64 protocol, the updated Status message must be sent as the protocol handshake, and each peer must validate the remote forkid, disconnecting at a detected incompatibility.

Rationale

EIP-2124 mentions advertising the forkid in the discovery protocol too. How does that compare to advertising in the eth protocol? Why is the redundancy needed?

Advertising and validating the forkid in the discovery protocol is a more optimal solution, as it can help avoid the cost of setting up the TCP connection and cryptographic RLPx stream, only to be torn down if eth/64 rejects it.

Compared to the eth protocol however, discovery is a bit fuzzy. The goal there is to suggest potential peers, not to be fool-proof. Information may be outdated, nodes may have changed or disappeared. Discovery can do a rough filtering, but more precision is still needed afterwards.

Additionally, forkid validation via the discovery protocol requires ENR implementation (EIP-778) and ENR extension support (EIP-868), which is not mandated by the Ethereum network currently. Lastly, the discovery protocol is just one way to find peers, but systems that cannot use UDP or that rely on other mechanism (e.g. DNS discovery (EIP-1459)) still need a way to filter connections.

The forkid implicitly contains the genesis hash checksummed into the FORK_HASH field. Why doesn’t this proposal remove the genesisHash field from the eth handshake?

Originally this EIP did remove it as redundant data, since filtering based on the forkid is a superset of filtering based on genesis hash. The reason for backing out of that decision was that the genesis hash may be useful for other things too, not just connection filtering (network crawlers use it currently to split nodes across networks).

Although the forkid will hopefully take over all the roles of the genesis hash currently in use, there’s no reason to be overly aggressive in deduplicating data. It’s fine to keep both side-by-side for now, and remove in a future version when 3rd party infrastructures switch over.

Backwards Compatibility

This EIP extends the eth protocol handshake in a backwards incompatible way and requires rolling out a new version, eth/64. However, devp2p supports running multiple versions of the same wire protocol side-by-side, so rolling out eth/64 does not require client coordination, since non-updated clients can keep using eth/63.

This EIP does not change the consensus engine, thus does not require a hard fork.

Test Cases

For calculating and validating fork IDs, see test cases in EIP-2124.

Testing proper advertising and validation at the networking level will require a hive test.

Implementation

Geth: https://github.com/ethereum/go-ethereum/pull/20140

Copyright and related rights waived via CC0.