Try   HackMD

teku light client table

As described in the latest dev update, persisting light-client data on disk and serving requests with a table lookup will be the best way to provide light client support in teku. It has the advantages of:

  • Providing the best light client update per is_better_update, given that light client updates can be compared and saved per sync-committee period
  • Providing the highest rate of data availability, as all nodes that see a block will be able to serve light client data corresponding to the block (previously an archive node would be required for historic states)
  • Code maintainability, as the logic of updating when we sync and serving from the table is much simpler than computing the slot required for light client updates and retrieving the relevant beacon states on-the-fly

This doc will briefly describe the interface and details of this table in teku.

Light client data schemas

Add two columns with type:

<Bytes32> --> LightClientBootstrap

  • Map of block root to the LightClientBootstrap associated with the block
  • One entry per finalized epoch boundary block is expected, in the range of the block retention period
    • Per the spec, this includes all blocks whose block root can occur as part of a valid Checkpoint (initial slot of epoch, or the slot where all following slots through the initial slot of the next epoch are empty)
  • Space can be saved by deduplicating sync committees, storing them in a separate column

<Uint64> --> LightClientUpdate

  • Map of sync committee period number to the best light client update for that period
  • One entry per sync committee period is expected, in the range of the light client data retention period (== block retention period)
  • Updates are determined while syncing blocks (see Writes section below)

LightClientFinalityUpdate: single field tracking the latest known (by slot) LightClientFinalityUpdate

LightClientOptimisticUpdate : single field tracking the latest known (by slot) LightClientOptimisticUpdate

Reads

GET /eth/v1/beacon/light_client/bootstrap/{block_root}

  • Lookup LightClientBootstrap by `BlockRoot
  • Return result, or 404 if not found

GET /eth/v1/beacon/light_client/updates?startPeriod=x&count=y

  • Lookup LightClientUpdate by given sync committee period (both startPeriod and for count periods after startPeriod)
  • Return list of updates if found, or 400 otherwise (misspecified parameters, not yet synced, etc.)

GET /eth/v1/beacon/light_client/finality_update

  • Return the current result, or 404 if not found (e.g. during startup period)

GET /eth/v1/beacon/light_client/optimistic_update

  • Return the current result, or 404 if not found (e.g. during startup period)

Writes

Upon applying a block:

  • Compute the merkle proofs on the pre state
  • Apply the block
  • Compute light client data on the post state
    • LightClientBootstrap: save in database with the block root
    • LightClientUpdate: compute current sync committee period. Compare the update against the current known for the period according to is_better_update. Save the best update for the period.
    • LightClientFinalityUpdate: save if the result has a higher slot than the current update
    • LightClientOptimisticUpdate: save if the result has a higher slot than the current update

Implementation

The bulk of the data is stored in two new columns, keyed by block root and slot. Light client data is cheap to store, with the sparsity of Checkpoint for LightClientBootstrap and sync committee period for LightClientUpdate. Data is populated upon block apply (e.g. during sync), and is only required to be kept for the block retention period. In practice this means nodes will have all light client data for each block seen during sync, and an archive node is not required. The light client spec permits nodes serving 404 for blocks not seen (e.g. due to checkpoint sync).