Skip to content

Commit

Permalink
Define endpoints for light client sync
Browse files Browse the repository at this point in the history
Introduces additional REST endpoints for light client sync, compatible
with the libp2p specification defined in `ethereum/consensus-specs`:
https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/p2p-interface.md

Endpoints are defined to be fork-aware to allow potential optimizations
such as including EL block hash into `BeaconBlockHeader` in the future.

The `getLightClientUpdatesByRange` endpoint is a new kind of endpoint,
as it introduces the concept of list responses. Each list item could
potentially be of a different fork. Likewise, for the events stream,
the fork may update between events. Both the list response and the event
are additionall wrapped with a per-item `version` indicator in JSON.
For SSZ, the list items are encoded as length/version/payload triples.
Note that the events endpoint does not support the SSZ format.

This builds on prior work from:
- @dapplion at #181

The proof endpoint in that PR is out-of-scope here, but could be useful
as part of the debug API as an `eth_getProof` equivalent for CL data.
  • Loading branch information
etan-status committed Sep 22, 2022
1 parent 1624ad8 commit acc7526
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 1 deletion.
54 changes: 54 additions & 0 deletions apis/beacon/light_client/bootstrap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
get:
operationId: getLightClientBootstrap
summary: Get `LightClientBootstrap` structure for a requested block root
description: |
Requests the [`LightClientBootstrap`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#lightclientbootstrap) structure corresponding to a given post-Altair beacon block root.
Depending on the `Accept` header it can be returned either as JSON or SSZ-serialized bytes.
Servers SHOULD provide results as defined in [`create_light_client_bootstrap`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/full-node.md#create_light_client_bootstrap). To fulfill a request, the requested block's post state needs to be known.
tags:
- Beacon
parameters:
- name: block_root
in: path
required: true
$ref: '../../../beacon-node-oapi.yaml#/components/parameters/BlockRoot'
responses:
"200":
description: Success
headers:
Eth-Consensus-Version:
$ref: '../../../beacon-node-oapi.yaml#/components/headers/Eth-Consensus-Version'
content:
application/json:
schema:
title: GetLightClientBootstrapResponse
type: object
properties:
version:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/ConsensusVersion'
data:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/Altair.LightClientBootstrap'
application/octet-stream:
schema:
description: "SSZ serialized `LightClientBootstrap` bytes. Use Accept header to choose this response type"
"400":
description: Malformed request parameter
content:
application/json:
schema:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage"
example:
code: 400
message: "Invalid block root value"
"404":
description: "`LightClientBootstrap` instance cannot be produced for the given block root"
content:
application/json:
schema:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage"
example:
code: 404
message: "LC bootstrap unavailable"
"500":
$ref: "../../../beacon-node-oapi.yaml#/components/responses/InternalError"
40 changes: 40 additions & 0 deletions apis/beacon/light_client/finality_update.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
get:
operationId: getLightClientFinalityUpdate
summary: Get the latest known `LightClientFinalityUpdate`
description: |
Requests the latest [`LightClientFinalityUpdate`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate) known by the server.
Depending on the `Accept` header it can be returned either as JSON or SSZ-serialized bytes.
Servers SHOULD provide results as defined in [`create_light_client_finality_update`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/full-node.md#create_light_client_finality_update).
tags:
- Beacon
responses:
"200":
description: Success
headers:
Eth-Consensus-Version:
$ref: '../../../beacon-node-oapi.yaml#/components/headers/Eth-Consensus-Version'
content:
application/json:
schema:
title: GetLightClientFinalityUpdateResponse
type: object
properties:
version:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/ConsensusVersion'
data:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/Altair.LightClientFinalityUpdate'
application/octet-stream:
schema:
description: "SSZ serialized `LightClientFinalityUpdate` bytes. Use Accept header to choose this response type"
"404":
description: "No `LightClientFinalityUpdate` is available"
content:
application/json:
schema:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage"
example:
code: 404
message: "LC finality update unavailable"
"500":
$ref: "../../../beacon-node-oapi.yaml#/components/responses/InternalError"
40 changes: 40 additions & 0 deletions apis/beacon/light_client/optimistic_update.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
get:
operationId: getLightClientOptimisticUpdate
summary: Get the latest known `LightClientOptimisticUpdate`
description: |
Requests the latest [`LightClientOptimisticUpdate`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate) known by the server.
Depending on the `Accept` header it can be returned either as JSON or SSZ-serialized bytes.
Servers SHOULD provide results as defined in [`create_light_client_optimistic_update`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/full-node.md#create_light_client_optimistic_update).
tags:
- Beacon
responses:
"200":
description: Success
headers:
Eth-Consensus-Version:
$ref: '../../../beacon-node-oapi.yaml#/components/headers/Eth-Consensus-Version'
content:
application/json:
schema:
title: GetLightClientOptimisticUpdateResponse
type: object
properties:
version:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/ConsensusVersion'
data:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/Altair.LightClientOptimisticUpdate'
application/octet-stream:
schema:
description: "SSZ serialized `LightClientOptimisticUpdate` bytes. Use Accept header to choose this response type"
"404":
description: "No `LightClientOptimisticUpdate` is available"
content:
application/json:
schema:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage"
example:
code: 404
message: "LC optimistic update unavailable"
"500":
$ref: "../../../beacon-node-oapi.yaml#/components/responses/InternalError"
84 changes: 84 additions & 0 deletions apis/beacon/light_client/updates.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
get:
operationId: getLightClientUpdatesByRange
summary: Get `LightClientUpdate` instances in a requested sync committee period range
description: |
Requests the [`LightClientUpdate`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#lightclientupdate) instances in the sync committee period range `[start_period, start_period + count)`, leading up to the current head sync committee period as selected by fork choice.
Depending on the `Accept` header they can be returned either as JSON or SSZ-serialized bytes.
Servers SHOULD provide results as defined in [`create_light_client_update`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/full-node.md#create_light_client_update). They MUST respond with at least the earliest known result within the requested range, and MUST send results in consecutive order (by period). The response MUST NOT contain more than [`min(MAX_REQUEST_LIGHT_CLIENT_UPDATES, count)`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/p2p-interface.md#configuration) results.
tags:
- Beacon
parameters:
- name: start_period
in: query
required: true
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/Uint64'
- name: count
in: query
required: true
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/Uint64'
responses:
"200":
description: Success
content:
application/json:
schema:
title: GetLightClientUpdatesByRangeResponse
type: array
items:
type: object
properties:
version:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/ConsensusVersion'
data:
$ref: '../../../beacon-node-oapi.yaml#/components/schemas/Altair.LightClientUpdate'
application/octet-stream:
schema:
description: |
Sequence of zero or more `response_chunk`. Each _successful_ `response_chunk` MUST contain a single `LightClientUpdate` payload:
```
(
response_chunk_len: Little-endian Uint64 byte length of `response_chunk`
response_chunk: (
context: 4 byte `ForkDigest`
payload: SSZ serialized payload bytes
)
)
```
Use Accept header to choose this response type
For each `response_chunk`, a `ForkDigest`-context based on `compute_fork_version(compute_epoch_at_slot(update.attested_header.slot))` is used to select the fork namespace of the Response type. Note that this `fork_version` may be different from the one used to verify the `update.sync_aggregate`, which is based on `update.signature_slot`.
Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
| `fork_version` | Response chunk SSZ type |
| -------------------------------------------- | ------------------------------------ |
| `GENESIS_FORK_VERSION` | n/a |
| <nobr>`ALTAIR_FORK_VERSION` and later</nobr> | `altair.LightClientUpdate` |
"400":
description: Malformed or missing request parameter
content:
application/json:
schema:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage"
examples:
InvalidSyncPeriod:
value:
code: 400
message: "Invalid sync committee period requested"
InvalidCount:
value:
code: 400
message: "Invalid count requested"
MissingStartPeriodValue:
value:
code: 400
message: "Missing `start_period` value"
MissingCountValue:
value:
code: 400
message: "Missing `count` value"

"500":
$ref: "../../../beacon-node-oapi.yaml#/components/responses/InternalError"
12 changes: 12 additions & 0 deletions apis/eventstream/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ get:
- finalized_checkpoint
- chain_reorg
- contribution_and_proof
- light_client_finality_update
- light_client_optimistic_update
responses:
"200":
description: Opened SSE stream.
Expand Down Expand Up @@ -73,6 +75,16 @@ get:
value: |
event: contribution_and_proof
data: {"message": {"aggregator_index": "997", "contribution": {"slot": "168097", "beacon_block_root": "0x56f1fd4262c08fa81e27621c370e187e621a67fc80fe42340b07519f84b42ea1", "subcommittee_index": "0", "aggregation_bits": "0xffffffffffffffffffffffffffffffff", "signature": "0x85ab9018e14963026476fdf784cc674da144b3dbdb47516185438768774f077d882087b90ad642469902e782a8b43eed0cfc1b862aa9a473b54c98d860424a702297b4b648f3f30bdaae8a8b7627d10d04cb96a2cc8376af3e54a9aa0c8145e3"}, "selection_proof": "0x87c305f04bfe5db27c2b19fc23e00d7ac496ec7d3e759cbfdd1035cb8cf6caaa17a36a95a08ba78c282725e7b66a76820ca4eb333822bd399ceeb9807a0f2926c67ce67cfe06a0b0006838203b493505a8457eb79913ce1a3bcd1cc8e4ef30ed"}, "signature": "0xac118511474a94f857300b315c50585c32a713e4452e26a6bb98cdb619936370f126ed3b6bb64469259ee92e69791d9e12d324ce6fd90081680ce72f39d85d50b0ff977260a8667465e613362c6d6e6e745e1f9323ec1d6f16041c4e358839ac"}
light_client_finality_update:
description: The node's latest known `LightClientFinalityUpdate` has been updated
value: |
event: light_client_finality_update
data: {"version":"phase0", "data": {"attested_header": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}, "finalized_header": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}, "finality_branch": ["0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"], "sync_aggregate": {"sync_committee_bits":"0x01", "sync_committee_signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}, "signature_slot":"1"}}
light_client_optimistic_update:
description: The node's latest known `LightClientOptimisticUpdate` has been updated
value: |
event: light_client_optimimstic_update
data: {"version":"phase0", "data": {"attested_header": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}, "sync_aggregate": {"sync_committee_bits":"0x01", "sync_committee_signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}, "signature_slot":"1"}}
"400":
description: "The topics supplied could not be parsed"
content:
Expand Down
19 changes: 18 additions & 1 deletion beacon-node-oapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,14 @@ paths:
$ref: "./apis/beacon/blocks/root.yaml"
/eth/v1/beacon/blocks/{block_id}/attestations:
$ref: "./apis/beacon/blocks/attestations.yaml"

/eth/v1/beacon/light_client/bootstrap/{block_root}:
$ref: "./apis/beacon/light_client/bootstrap.yaml"
/eth/v1/beacon/light_client/updates:
$ref: "./apis/beacon/light_client/updates.yaml"
/eth/v1/beacon/light_client/finality_update:
$ref: "./apis/beacon/light_client/finality_update.yaml"
/eth/v1/beacon/light_client/optimistic_update:
$ref: "./apis/beacon/light_client/optimistic_update.yaml"
/eth/v1/beacon/pool/attestations:
$ref: "./apis/beacon/pool/attestations.yaml"
/eth/v1/beacon/pool/attester_slashings:
Expand Down Expand Up @@ -236,6 +243,14 @@ components:
$ref: './types/http.yaml#/ErrorMessage'
IndexedErrorMessage:
$ref: './types/http.yaml#/IndexedErrorMessage'
Altair.LightClientBootstrap:
$ref: './types/altair/light_client.yaml#/Altair/LightClientBootstrap'
Altair.LightClientUpdate:
$ref: './types/altair/light_client.yaml#/Altair/LightClientUpdate'
Altair.LightClientFinalityUpdate:
$ref: './types/altair/light_client.yaml#/Altair/LightClientFinalityUpdate'
Altair.LightClientOptimisticUpdate:
$ref: './types/altair/light_client.yaml#/Altair/LightClientOptimisticUpdate'
Altair.SignedBeaconBlock:
$ref: './types/altair/block.yaml#/Altair/SignedBeaconBlock'
Altair.BeaconBlock:
Expand Down Expand Up @@ -277,6 +292,8 @@ components:
$ref: './params/index.yaml#/StateId'
BlockId:
$ref: './params/index.yaml#/BlockId'
BlockRoot:
$ref: './params/index.yaml#/BlockRoot'

responses:
InvalidRequest:
Expand Down
5 changes: 5 additions & 0 deletions params/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ BlockId:
description: |
Block identifier.
Can be one of: "head" (canonical head in node's view), "genesis", "finalized", \<slot\>, \<hex encoded blockRoot with 0x prefix\>.
BlockRoot:
$ref: "../types/primitive.yaml#/Root"
description: |
Block root.
\<hex encoded blockRoot with 0x prefix\>.
71 changes: 71 additions & 0 deletions types/altair/light_client.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Altair:
FinalityBranch:
type: array
items:
$ref: '../primitive.yaml#/Root'
description: "Merkle proof consisting of [`log2trunc(FINALIZED_ROOT_INDEX])`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#constants) roots"
minItems: 6
maxItems: 6
CurrentSyncCommitteeBranch:
type: array
items:
$ref: '../primitive.yaml#/Root'
description: "Merkle proof consisting of [`log2trunc(CURRENT_SYNC_COMMITTEE_INDEX])`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#constants) roots"
minItems: 5
maxItems: 5
NextSyncCommitteeBranch:
type: array
items:
$ref: '../primitive.yaml#/Root'
description: "Merkle proof consisting of [`log2trunc(NEXT_SYNC_COMMITTEE_INDEX])`](https://github.com/ethereum/consensus-specs/blob/v1.2.0-rc.3/specs/altair/light-client/sync-protocol.md#constants) roots"
minItems: 5
maxItems: 5

LightClientBootstrap:
type: object
properties:
header:
$ref: '../block.yaml#/BeaconBlockHeader'
current_sync_committee:
$ref: './sync_committee.yaml#/Altair/SyncCommittee'
current_sync_committee_branch:
$ref: '#/Altair/CurrentSyncCommitteeBranch'
LightClientUpdate:
type: object
properties:
attested_header:
$ref: '../block.yaml#/BeaconBlockHeader'
next_sync_committee:
$ref: './sync_committee.yaml#/Altair/SyncCommittee'
next_sync_committee_branch:
$ref: '#/Altair/NextSyncCommitteeBranch'
finalized_header:
$ref: '../block.yaml#/BeaconBlockHeader'
finality_branch:
$ref: '#/Altair/FinalityBranch'
sync_aggregate:
$ref: './sync_aggregate.yaml#/Altair/SyncAggregate'
signature_slot:
$ref: '../primitive.yaml#/Uint64'
LightClientFinalityUpdate:
type: object
properties:
attested_header:
$ref: '../block.yaml#/BeaconBlockHeader'
finalized_header:
$ref: '../block.yaml#/BeaconBlockHeader'
finality_branch:
$ref: '#/Altair/FinalityBranch'
sync_aggregate:
$ref: './sync_aggregate.yaml#/Altair/SyncAggregate'
signature_slot:
$ref: '../primitive.yaml#/Uint64'
LightClientOptimisticUpdate:
type: object
properties:
attested_header:
$ref: '../block.yaml#/BeaconBlockHeader'
sync_aggregate:
$ref: './sync_aggregate.yaml#/Altair/SyncAggregate'
signature_slot:
$ref: '../primitive.yaml#/Uint64'

1 comment on commit acc7526

@amirkhan7javi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for help

Please sign in to comment.