beacon-APIs
beacon-APIs copied to clipboard
Add lightclient routes
Adds minimal set of lightclient routes to super a server-based trust-less censorable lightclient.
Sample usage flow for these APIs:
- Gather weak subjectivity checkpoint root from some trusted source
- Call
/eth/v1/lightclient/snapshot/{block_root}to get an initial SyncCommittee - Sync from initial SyncCommittee's sync period to clock sync period with
/eth/v1/lightclient/committee_updates - Subscribe to head update events
4.1. Subscribe to
/eth/v1/events?topics=lightclient_head_update4.2. If SSE are not available or to get the first head event faster, poll/eth/v1/lightclient/head_update - Once close to the end of the current clock sync period, call
/eth/v1/lightclient/committee_updates
For a sample implementation of this routes see:
- Routes backend incorporated into a beacon node: https://github.com/ChainSafe/lodestar/blob/master/packages/lodestar/src/chain/lightClient/index.ts#L159
- Routes front-end in a stand-alone static application: https://github.com/ChainSafe/eth2-light-client-demo/blob/master/src/App.tsx
Live demo: https://lodestar-light-client-demo.netlify.app
This is great as a draft, but believe it's good to settle on a p2p protocol before enshrining / merging it such that implementations don't have to maintain two views of the same data that are slightly different - this work has started in https://github.com/ethereum/consensus-specs/pull/2267 and should be completed first - we are in the process of implementing it and will be providing updates soon.
The long-term idea here would be that beacon nodes serve light client data via p2p just like they serve blocks which enables a very fast consensus sync in general and where serving the data would be part of the standard feature set offered by clients via P2P (to later be mirrored in the REST API).
A few generic questions:
- should
/eth/v1/lightclient/snapshot/only take a block root, or should it allow the more generic block ID? Rationale behind this would be to allow simple retrieval of the snapshot from a node which is considered trusted. - how should a client obtain the period(s) in step 3 given the data obtained so far? Seems like they need the spec to be able to go from slot to sync committee period, but should this be trusted? Would it make sense to use slots here for the
fromandtoparameters, and have the beacon node translate them to sync committee periods? - for 5) how does the client know when the sync period is coming up for a change? Perhaps a
slots_until_next_sync_committee_periodor similar should be added to the snapshot information?
RE @mcdee
should /eth/v1/lightclient/snapshot/ only take a block root, or should it allow the more generic block ID? Rationale behind this would be to allow simple retrieval of the snapshot from a node which is considered trusted.
Good point! Tho at least one block ID value is not suitable "genesis". Also if you use head you will have to guess the block_root if you want to validate the merkle proof. If you want a SyncCommittee trusting the node you can just query /eth/v1/beacon/states/{state_id}/sync_committees and /eth/v1/beacon/headers/{block_id}
how should a client obtain the period(s) in step 3 given the data obtained so far? Seems like they need the spec to be able to go from slot to sync committee period, but should this be trusted? Would it make sense to use slots here for the from and to parameters, and have the beacon node translate them to sync committee periods?
The config, genesis_time and genesis_validators_root of the network should be known ahead of time by the lightclient consumer. Then you can compute sync periods from slots. Using sync periods allows to put a cache layer in front of the node to speed up responses. If using slots, the same response can be requested with way more different requests.
for 5) how does the client know when the sync period is coming up for a change? Perhaps a slots_until_next_sync_committee_period or similar should be added to the snapshot information?
This can be easily computed knowing the config, genesis_time and genesis_validators_root of the network
RE: @arnetheduck
This is great as a draft, but believe it's good to settle on a p2p protocol before enshrining / merging it such that implementations don't have to maintain two views of the same data that are slightly different - this work has started in ethereum/consensus-specs#2267 and should be completed first - we are in the process of implementing it and will be providing updates soon.
Thanks! Tho I believe there's value in iterating both publicly at the same time. Lodestar will tackle p2p next so happy to give feedback on ethereum/consensus-specs#2267 then
Will cc myself and @ryanio in here.
Feedback from discussions at Devconnect AMS:
See libp2p PR discussion: https://github.com/ethereum/consensus-specs/pull/2802#issuecomment-1104825567
- Align data types with libp2p once there is agreement there. The light client should receive the same objects regardless of the underlying transport.
- Exception being that SSE does not necessarily require the selection proof that is being discussed (similar to other events types)
- Add route for fetching latest light client update to enable use case of retrieving latest finalized block root
light_client/updates/latest
- Align naming with best practices and make it consistent across transports
- Data types: Same as libp2p
LightClientHeaderUpdate->LightClientOptimisticUpdateLightClientUpdatestays the sameLightClientSnapshotWithProof->LightClientBootstrap
- HTTP GET:
/lightclient/committee_updates?from={from}&to={to}->light_client/updates?from={from}&to={to}(or usestart_period/countto match libp2p?)lightclient/head_update/->light_client/optimistic_updatelightclient/snapshot/{block_root}->light_client/bootstrap/{block_root}
- HTTP Server-Sent Event:
lightclient_head_update->light_client_optimistic_update
- Data types: Same as libp2p
Would also change from /eth2/v1/light_client to /eth2/v1/beacon/light_client/...as this data is about the beacon chain. It is also how the libp2p reqs are currently prefixed in proposal (at the very least, it should be consistent). On libp2p there is also the relation to the Status message which is another indicator that LC stuff should be under beacon umbrella.
Adopted with a v0 suffix in Nimbus (without proofs endpoint)
Requests:
/eth/v0/beacon/light_client/bootstrap/{block_root}/eth/v0/beacon/light_client/updates?start_period={start_period}&count={count}/eth/v0/beacon/light_client/finality_update/eth/v0/beacon/light_client/optimistic_update
HTTP Server-Sent Events (SSE):
light_client_finality_update_v0light_client_optimistic_update_v0
https://github.com/status-im/nimbus-eth2/pull/3775
It would be useful if all requests support returning SSZ data if the Accept: application/octet-stream header is provided. To make this possible, we need to specify an upper limit to the number of results of the getCommitteeUpdates request (in order to encode the result as List[LightClientUpdate, Limit] in SSZ).
The format is not that simple, as each element could be from different forks. The list does not solely contain altair.LightClientUpdate but may contain different updates in the future.
On Gossipsub, this is solved by prepending the fork digest to each item (similar encoding as a SSZ union, but not processed as a SSZ union as some legacy endpoints also support having an empty fork digest to indicate phase0).
Technically, you could also peek into the first 8 bytes of the SSZ response to determine attested_header.slot and infer the fork digest from there. A more general approach would be desirable though, as the 4 bytes do not add meaningful overhead.
Note that SSZ unions are not well-supported in all SSZ encoding libraries. (or only pseudo-supported with a type of 0).
It would be useful if all requests support returning SSZ data if the
Accept: application/octet-streamheader is provided. To make this possible, we need to specify an upper limit to the number of results of thegetCommitteeUpdatesrequest (in order to encode the result asList[LightClientUpdate, Limit]in SSZ).
@etan-status something like this would be valuable for the beacon -> validator API too. Some previous discussion on how to handle fork versioning
- https://github.com/ethereum/beacon-APIs/issues/167
After discussing with @etan-status its best to separate the proof route into a different namespace TBD
- Closing for https://github.com/ethereum/beacon-APIs/pull/247 which is a superset of this PR's functionality
Proofs endpoint should be tackled separately