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

# ForkId

> EIP-2124 fork identifier for network compatibility

## Overview

ForkId implements EIP-2124 fork identification for DevP2P network validation. It helps peers determine if they're on compatible forks before exchanging data.

```typescript theme={null}
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

```typescript theme={null}
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.

```typescript theme={null}
// 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.

```typescript theme={null}
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.

```typescript theme={null}
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:

1. **Identical** - Same hash and next block
2. **Remote has no future forks** - Same hash, remote next is 0
3. **Local has no future forks** - Same hash, local next is 0
4. **Remote is ahead** - Different hash but remote next >= local next

```typescript theme={null}
// 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:

```typescript theme={null}
// 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

* [Hardfork](/primitives/hardfork) - Hardfork detection
* [ChainId](/primitives/chain-id) - Chain identification
* [EIP-2124](https://eips.ethereum.org/EIPS/eip-2124) - Fork identifier spec
