Skip to main content
netspecsEthereum networking

4.2.5.Light-client networking

Stage
In progress
Version
Sources
5 pinned sources

An Altair light client starts from a trusted beacon block root and follows sync-committee signatures. It does not download or execute every block. The wire objects carry beacon headers, Merkle branches, a sync aggregate, and the signature slot.

Wire inventory

Gossip topics carry LightClientFinalityUpdate and LightClientOptimisticUpdate. Req/Resp uses:

/eth2/beacon_chain/req/light_client_bootstrap/1/
/eth2/beacon_chain/req/light_client_updates_by_range/1/
/eth2/beacon_chain/req/light_client_finality_update/1/
/eth2/beacon_chain/req/light_client_optimistic_update/1/

light_client_bootstrap/1 requests one Root and returns LightClientBootstrap. light_client_updates_by_range/1 requests (start_period, count) and returns at most MAX_REQUEST_LIGHT_CLIENT_UPDATES = 128 updates. The range is consecutive sync-committee periods. The two no-body methods return the latest finality or optimistic update, or ResourceUnavailable when none exists.

SSZ payloads

LightClientHeader:
  beacon: BeaconBlockHeader

LightClientBootstrap:
  header: LightClientHeader
  current_sync_committee: SyncCommittee
  current_sync_committee_branch: CurrentSyncCommitteeBranch

LightClientUpdate:
  attested_header: LightClientHeader
  next_sync_committee: SyncCommittee
  next_sync_committee_branch: NextSyncCommitteeBranch
  finalized_header: LightClientHeader
  finality_branch: FinalityBranch
  sync_aggregate: SyncAggregate
  signature_slot: Slot

Finality updates omit the next committee and optimistic updates omit both the next committee and finality branch. The response context is the four-byte fork digest derived from the attested header slot, while the sync aggregate's signature domain uses signature_slot.

Bootstrap and update validation

The client verifies that the bootstrap header root equals the trusted root and that the current committee branch reaches the header state root. For an update it requires at least MIN_SYNC_COMMITTEE_PARTICIPANTS = 1, current_slot >= signature_slot > attested_slot >= finalized_slot, and no skipped sync-committee period. It verifies every non-empty normalized Merkle branch, the sync aggregate under the committee for signature_slot, and the fork-specific light-client header shape.

An update must advance the finalized header or introduce the next committee that the store does not yet know. Invalid, stale, or irrelevant updates do not change the store and must not be forwarded by a full node.

Gossip and quality

Finality gossip ignores an update that does not improve the highest finalized slot, or that arrives before the signature block has had the sync-message due time plus the 500-millisecond clock allowance. Optimistic gossip applies the same due-time rule and requires a newer attested slot. Light clients reject an update that fails processing and ignore one that does not advance their local store; full nodes ignore a message that differs from their locally computed update.

When several valid updates compete, the store prefers supermajority sync participation over non-supermajority, then higher participation, a relevant next committee, finality, and sync-committee finality. Ties prefer the older attested slot and then the earlier signature slot. This ranking controls local state and does not create a peer-scoring penalty for a valid lower-quality update.

Fork-specific types

The response context selects the Altair, Bellatrix, Capella, or Deneb light-client type for the attested fork. A node must not decode by wall-clock fork alone.

The active light-client type uses the Electra shape. A response's context selects the exact SSZ type; a node must not decode by wall-clock fork alone.

The active light-client header includes an execution component and uses the Gloas SSZ types. A response's context selects the exact SSZ type; a node must not decode by wall-clock fork alone.

Serving and failure handling

A peer should return the earliest known consecutive update in a requested range and no more than the requested count or 128-item bound. It returns ResourceUnavailable when it cannot produce a bootstrap or latest update. A requester validates each chunk before applying it and keeps a valid prefix if a stream ends early. Invalid context, Merkle branch, sync signature, or SSZ is a bad response; missing historical data is a serving-window miss.