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

Introduces validation of the `forkid` when handshaking with peers.


Metadata
Status: FinalStandards Track: NetworkingCreated: 2019-11-08
Authors
Péter Szilágyi (peterke@gmail.com), Péter Szilágyi (@karalabe), Tim Beiko (@timbeiko)
Requires

Abstract


This EIP specifies the inclusion of the forkid, originally defined in (EIP-2124), as a new field in the Ethereum wire protocol (eth) handshake. This change is implemented as a new version of the wire protocol, eth/64.

Motivation


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.

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


  • 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


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

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)) 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.

Security Considerations


None.

Copyright


Copyright and related rights waived via CC0.