EIP-6122 Timestamp-based fork ID check (Forkid checks based on timestamps)

Final · Networking & nodes · EIP status Final · created 2022-12-13

Changes the fork ID (forkid) calculation, which nodes use to identify each other's chain configuration, so that it also handles forks scheduled by timestamp, not only by block number. After the Merge, forks are scheduled by time.

Why it is needed

In the proof-of-work era, Ethereum scheduled forks by block number. The proof-of-stake consensus layer, however, schedules forks by slot number, and slots are a time-based unit. For the consensus layer and execution layer to fork at the same moment after the Merge, the execution layer has no choice but to schedule forks by timestamp as well. But the fork ID (forkid) that nodes use to identify each other was built assuming only block numbers. The fork ID is a mechanism for quickly learning a peer's chain configuration and disconnecting peers that are misconfigured or configured for a different network. It makes the P2P network more reliable, but if it cannot account for timestamp-based forks, identification does not work properly. So the fork ID calculation is updated to include timestamps.

What changes

Today

After EIP-6122

Who is affected

In depth

FORK_HASH: genesis hash and CRC32 checksum of past forks

FORK_HASH is a 4-byte value: the IEEE CRC32 checksum of the genesis hash and the block numbers or timestamps of forks that have already passed. Fork points are added in ascending order, and if several forks apply at the same block or the same time, that value is checksummed only once. Block numbers and timestamps are both treated as uint64 integers and encoded in big-endian. Even if the chain is configured to start from genesis with a ruleset other than Frontier, that does not count as a fork.

FORK_NEXT: the next fork point

FORK_NEXT is a uint64 value holding the block number or timestamp of the next upcoming fork, and it is 0 if no next fork is known. The original text states explicitly that it does not matter in FORK_NEXT whether the value is a block number or a timestamp. As the test cases show, this value is used to determine whether the remote peer knows about upcoming forks, that is, whether it needs a software update.

Calculation example: a timestamp fork on top of Homestead

For a chain with a hypothetical fork scheduled at timestamp 1668000000 on top of Homestead, FORK_HASH is computed as CRC32(<genesis-hash> || uint64(1150000) || uint64(1668000000)), and the value is 0xcb37b2ee. Block number 1150000 (Homestead) and timestamp 1668000000 are both appended to the checksum input as uint64 big-endian values. Because block numbers and timestamps are handled as a single stream, the scheme does not split into two.

Additional rule: block forks first, timestamp forks later

A fork scheduled by timestamp, on mainnet or on a private network, MUST come at the same point as or after any fork scheduled by block. An implementation that validates a remote peer's fork ID MUST first filter the incoming fork ID by block, then by timestamp. According to the Rationale, this update became necessary when the Shanghai upgrade was scheduled by timestamp, and because every block-based fork precedes every time-based fork, the check order is also block first.

Backwards compatibility: disconnecting peers is the intended outcome

This change slightly alters the fork ID calculation. As a result, a node that applies the change will disconnect peers that have not applied it from the moment a timestamp-scheduled fork occurs. The source explains that this is not only expected but is the very purpose fork ID exists in the first place, because the role of fork ID is to quickly disconnect nodes with mismatched configurations.

Test cases: fork ID values and accept/reject decisions

The source presents two sets of tests, using a mainnet configuration with withdrawals at timestamp 1668000000 and the Merge netsplit block at 18000000. The first verifies fork ID values as the chain progresses. For example, in the Shanghai range the result is Hash 0xc1fdf181, Next 0. The second set covers cases where the local node decides whether to accept or reject a remote fork ID. A peer that is merely behind in syncing is accepted, an outdated remote peer that needs an update is rejected with ErrRemoteStale, and a case where the local side is incompatible or behind is rejected with ErrLocalIncompatibleOrStale.

Security and status

The source's Security Considerations section states that there are no known security risks. This EIP is a Standards Track proposal in the Networking category, and its status is Final, so its content will not change further. It requires EIP-2124, which first defined the fork ID scheme, and extends that scheme by adding the timestamp to the checksum input.

Original EIP · ← EIPs