Skip to main content
netspecsEthereum networking

4.5.2.Fork choice and payloads

Stage
In progress
Version
Sources
7 pinned sources

The consensus client sends the execution head, safe block, and finalized block through engine_forkchoiceUpdated. It may attach payload attributes to start a local payload build. engine_getPayload retrieves that build.

Fork-choice state

ForkchoiceStateV1 contains headBlockHash, safeBlockHash, and finalizedBlockHash. Zero means that the safe or finalized block is not yet known. safeBlockHash must be the head or one of its ancestors. The execution client rejects an inconsistent state with -38002 and may return -38006 when the requested reorganization is too deep. An unknown head or a head whose validation data is missing returns a SYNCING payload status. A zero safe or finalized hash is allowed until the transition block is finalized.

Merge build methods

The valid methods are engine_forkchoiceUpdatedV1 and engine_getPayloadV1.

Shapella build methods

The valid methods are engine_forkchoiceUpdatedV2 and engine_getPayloadV2.

Dencun build methods

engine_forkchoiceUpdatedV3 updates the execution head and can start a payload build. engine_getPayloadV3 returns an ExecutionPayloadV3 and a BlobsBundleV1. The bundle's blobs, commitments, and proofs lists must have equal length, with one proof per blob. The commitments and proofs must verify against the payload's blob transactions.

Pectra build methods

engine_forkchoiceUpdatedV3 updates the execution head and can start a payload build. engine_getPayloadV4 returns an ExecutionPayloadV3, a BlobsBundleV1, and execution requests. The bundle's blobs, commitments, and proofs lists must have equal length, with one proof per blob. The commitments and proofs must verify against the payload's blob transactions.

Fusaka build methods

engine_forkchoiceUpdatedV3 updates the execution chain and may start a build.

engine_getPayloadV5 returns an ExecutionPayloadV3, block value, a cell-proof BlobsBundleV2, a builder-override hint, and execution requests. The bundle's blobs and commitments lists have equal length, and it carries 128 cell proofs for each blob. The cell proofs must verify against the cells derived from the returned blobs and their commitments.

Glamsterdam build methods

engine_forkchoiceUpdatedV4 carries a target gas limit and an optional custodyColumns bit array. The request uses ForkchoiceStateV1, optional PayloadAttributesV4, and a 16-byte custodyColumns value, or null when the consensus client does not provide custody. The call has an 8-second timeout and keeps the usual fork-choice response.

When custodyColumns is present, the Amsterdam Engine API requires the execution client to adopt it for type-3 transaction sampling. On expansion, the client should request the delta and may announce the expanded set. On contraction, it may prune dropped cells, but should wait two slots after it announces the reduced set. Custody-set work runs independently, so an execution-time error there must not fail the main fork-choice update.

Draft EIP-8070 specifies a different lifecycle around the same parameter. It requires the consensus client to send the set after startup, after each change, and after an Engine API reconnection. It requires delta requests on expansion, requires a reduced-set announcement before pruning on contraction, and treats an unchanged set as a blob-pool no-op. Those draft requirements are not part of the Amsterdam Engine API contract unless that specification adopts them.

engine_getPayloadV6 returns ExecutionPayloadV4, including its block access list, beside a BlobsBundleV2. The bundle's blobs and commitments lists have equal length, and it carries 128 cell proofs for each blob. The cell proofs must verify against the cells derived from the returned blobs and their commitments.

Build lifecycle

When the fork-choice state is valid, the execution client applies it before it processes payload attributes. Valid attributes start a local build and return an eight-byte payload ID. The ID names short-lived build state. The consensus client may call engine_getPayload until its proposal deadline. An unknown or expired ID gives -38001; invalid attributes give -38003, and a timestamp for an unsupported fork gives -38005.

The consensus client validates the returned timestamp, parent, fee recipient, and every field present in the selected payload version before it uses the payload. This includes withdrawals, blob data, execution requests, or block access lists only when that version defines the field.

Failure handling

Wrong fork timing gives unsupported fork. Bad attributes give invalid payload attributes. A timeout does not prove that the execution client stopped the build. The consensus client can retry or use a separate valid builder path.

Design rationale

Fork choice and payload building share one call so the execution client builds on the exact head that the consensus client selected.