Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Overview
ForkId implements EIP-2124 fork identification for DevP2P network validation. It helps peers determine if they’re on compatible forks before exchanging data.
import * as ForkId from '@voltaire/primitives/ForkId'
const forkId = ForkId.from({
hash: new Uint8Array([0xfc, 0x64, 0xec, 0x04]),
next: 1920000n, // DAO fork block
})
Type Definition
type ForkIdType = {
readonly hash: Uint8Array // CRC32 checksum (4 bytes)
readonly next: BlockNumberType // Next fork block (0 if none)
}
Fields:
hash - CRC32 checksum of genesis hash + fork block numbers
next - Block number of next known fork (0 if no upcoming forks)
Creating ForkId
from
Create from hash and next block number.
// From Uint8Array
const forkId1 = ForkId.from({
hash: new Uint8Array([0xfc, 0x64, 0xec, 0x04]),
next: 1920000n,
})
// From hex string
const forkId2 = ForkId.from({
hash: "0xfc64ec04",
next: 1920000n,
})
// From number
const forkId3 = ForkId.from({
hash: 0xfc64ec04,
next: 0n, // No upcoming forks
})
Validation:
hash must be exactly 4 bytes
next is required (use 0 for no upcoming forks)
Methods
toBytes
Encode to 12-byte binary format for DevP2P handshake.
const bytes = ForkId.toBytes({
hash: new Uint8Array([0xfc, 0x64, 0xec, 0x04]),
next: 1920000n,
})
console.log(bytes.length) // 12
// Format: hash (4 bytes) || next (8 bytes big-endian)
matches
Check if two ForkIds are compatible per EIP-2124.
const local = ForkId.from({
hash: new Uint8Array([0xfc, 0x64, 0xec, 0x04]),
next: 1920000n,
})
const remote = ForkId.from({
hash: new Uint8Array([0xfc, 0x64, 0xec, 0x04]),
next: 1920000n,
})
if (ForkId.matches(local, remote)) {
console.log('Peers are compatible')
} else {
console.log('Fork incompatible - disconnect peer')
}
Compatibility Rules
Two ForkIds are compatible if:
- Identical - Same hash and next block
- Remote has no future forks - Same hash, remote next is 0
- Local has no future forks - Same hash, local next is 0
- Remote is ahead - Different hash but remote next >= local next
// Case 1: Identical
const a = ForkId.from({ hash: 0xfc64ec04, next: 1920000n })
const b = ForkId.from({ hash: 0xfc64ec04, next: 1920000n })
ForkId.matches(a, b) // true
// Case 2: Remote doesn't know about future forks
const local = ForkId.from({ hash: 0xfc64ec04, next: 2000000n })
const remote = ForkId.from({ hash: 0xfc64ec04, next: 0n })
ForkId.matches(local, remote) // true
// Case 3: Incompatible forks
const mainnet = ForkId.from({ hash: 0xfc64ec04, next: 1920000n })
const classic = ForkId.from({ hash: 0x12345678, next: 0n })
ForkId.matches(mainnet, classic) // false
Ethereum Mainnet Fork History
| Fork | Block | CRC32 Hash |
|---|
| Frontier | 0 | 0xfc64ec04 |
| Homestead | 1,150,000 | 0x97c2c34c |
| DAO Fork | 1,920,000 | 0x91d1f948 |
| Tangerine | 2,463,000 | 0x7a64da13 |
| Spurious | 2,675,000 | 0x3edd5b10 |
| Byzantium | 4,370,000 | 0xa00bc324 |
| Constantinople | 7,280,000 | 0x668db0af |
| Istanbul | 9,069,000 | 0x879d6e30 |
| Berlin | 12,244,000 | 0xe029e991 |
| London | 12,965,000 | 0x0eb440f6 |
| Merge | 15,537,394 | 0xb715077d |
| Shanghai | 17,034,870 | 0xf0afd0e3 |
| Cancun | 19,426,587 | 0xdce96c2d |
DevP2P Handshake
ForkId is exchanged during the DevP2P status message:
// During peer connection
const localForkId = ForkId.from({
hash: calculateForkHash(chainConfig, headBlock),
next: getNextForkBlock(chainConfig),
})
const remoteForkId = parseStatusMessage(peerStatus)
if (!ForkId.matches(localForkId, remoteForkId)) {
disconnectPeer(peer, 'Incompatible fork')
}
See Also