-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add /eth/v0/beacon/light_client/instant_update #270
Conversation
Requests the best [`LightClientInstantUpdate`](../../../types/altair/light_client.yaml#/Altair/LightClientInstantUpdate) known by the server for the given block header. | ||
Depending on the `Accept` header it can be returned either as JSON or SSZ-serialized bytes. | ||
|
||
Servers providing this endpoint SHOULD always listen to the sync committee signature gossip and collect individual signatures. On request the best BLS | ||
signature is aggregated and returned for the specified (recent) block header. When a new block appears, the previously known best sync aggregate for its | ||
parent is compared against the sync aggregate found in the new block and replaced if the canonical one is better. Best sync aggregates are retained and | ||
served for the 16 most recent slots. | ||
Note that since always listening to the signature gossip costs some resources, it is acceptable to only start listening once this endpoint is called | ||
and stop listening if it is not called for an extended period of time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So there's SyncCommitteeMessage
and SyncCommitteeContribution
.. can we line up what's being asked for here so that its better undesrtood?
It does concern me listening to all gossip on everything running the beacon-api, especially for home stakers etc it's overhead they shouldn't require..
Aggregates will be available before a block is produced anyway, I'm wondering why we'd be pushing to listen to individual messages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we don't necessarily have to specify here how to obtain the best signatures as it does not affect the way the endpoint is used, from the consumer perspective it just affects the delays. Listening to all individual sync committee sigs is indeed expensive and it was my mistake to specify it as the default option. Listening to the four subnet aggregates is definitely better as a default suggestion. I changed the description accordingly. I see no reason to specifically forbid beacon nodes from listening to all sigs but it should not be a mandatory thing to implement (and even if implemented by a certain consensus client it should probably not be the default option). I'd even be fine with making this whole feature optional to implement, I just want to come up with a spec that makes sense so those who are interested in implementing it can stay compatible with each other.
apis/eventstream/index.yaml
Outdated
description: A new `LightClientInstantUpdate` has been generated (the node's current head and/or the best sync aggregate for the previously known head has been updated) | ||
value: | | ||
event: light_client_instant_update | ||
data: {"version":"phase0", "data": {"new_head_header": {"slot":"1", "proposer_index":"1", "parent_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "state_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "body_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"}, "best_sync_aggregate": {"sync_committee_bits":"0x01", "sync_committee_signature":"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"}, "signature_slot":"1"}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version phase0
isn't valid for sync committee...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, fixed. It was also wrong in the other update examples, fixed those too.
@@ -100,6 +100,8 @@ paths: | |||
$ref: "./apis/beacon/light_client/finality_update.yaml" | |||
/eth/v1/beacon/light_client/optimistic_update: | |||
$ref: "./apis/beacon/light_client/optimistic_update.yaml" | |||
/eth/v0/beacon/light_client/instant_update/{block_root}: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would prefer we keep this as v1 and mark experimental in the tags for the endpoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
LightClientInstantUpdate: | ||
type: object | ||
properties: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should probably add the required attrbiutes list here if we're not requiring all fields - sounds like new_head_header
is optional...
Also is new_head_header
in a spec somewhere? I'm not a huge fan of that name...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to new_head
, the description and type reference should tell the rest. Also added the required attrbiutes list.
I may be missing something but event stream may be problematic on this endpoint if you're expecting it refers to the last block root of a specific clients call, which is what it sounds like... If that's the intent, maybe leave it off the stream because it will be very difficult to correlate, especially if there's multiple LC connecting to one BN. |
I believe this endpoint is necessary since the artificial full slot delay on
|
@rolfyone Thank you for the detailed review and sorry for responding slowly. So I think the main issue is whether it makes sense to subscribe to every individual |
About the event stream: maybe the spec wasn't clear enough here, I should fix it. So in the polling version the client tells in the parameter which is the last head it knows about, the BN returns the best known signature for that head and also a new head if it's different from what the client knows about. In case of the event stream the BN pushes a continuous stream of messages and it can always assume that the last block the subscriber (any subscriber) knows about is the new block contained in its own last message that contained a new block. So it can always send the same message to every subscriber. |
I think for a general-purpose API, it might be better to keep this focused on the the aggregates instead - ie the individual messages are quite numerous and expensive to maintain a subscription over. I also think that propagating this over a the LES network is a crutch at best - ie at that point, it would make for a more resilient network if consumers simply subscribed and contributed to the libp2p gossip directly instead of developing a REST API that all CL:s must implement then feeding that into LES - the duplicated LES network over devp2p introduces fragmentation for this data that is already scarcely distributed, and it's problematic because clients participating in that network will have weaker protections than what a libp2p participant can achieve. |
@arnetheduck see my comment above regarding the aggregates vs individual messages. |
I've posted for comments on this PR, will circle back tomorrow and see where we're at. In the meantime, if you have a second to clean up that conflict @zsfelfoldi that'd save me a task :) |
A couple of thoughts after a quick read-through:
|
True, I do not believe this "instant update" should be emitted to events.
Above approach would only force the beacon node to do extra work if its consumer requires it. Also 512 sync messages / 12 seconds is not that much compared to attestations.
|
964ccce
to
2ccba87
Compare
@rolfyone fixed the conflicts :) |
@mcdee about the naming: the spec intentionally does not specify how the signature aggregate is obtained (see discussion above), the definition of this endpoint is that it gives the best available update (highest participation signature aggregate) at any moment without waiting for it to become canonical. So it's instant in the sense that the API makes it available as soon as it's available to the underlying CL client. Maybe it's possible to choose a better name though... it could be |
Per out-of-band discussion, similar information is available from https://ethereum.github.io/beacon-APIs/#/Validator/produceSyncCommitteeContribution |
Closing as stale, we can re-open if/when required. |
This PR adds a
/eth/v0/beacon/light_client/instant_update
feature that allows optimistic light clients to operate with only a few seconds of delay as opposed to/eth/v1/beacon/light_client/optimistic_update
which introduces a full block of delay. Security is not affected by the latest sync committee signature being canonized in the next block and therefore it is possible for the serving node to always listen to the sync committee signature gossip (just like it does when it is on the sync committee) and provide sync aggregates for the current head as soon as signatures are available.The endpoint receives a
block_root
parameter and when asked about the current head, assuming that the client already has the header, returns only the current best aggregate. If an olderblock_root
is specified then the most recent head header is also returned. This makes sense because the final best signature for a given block can typically be determined when its child appears, in which case the polling client is notified that the result can be considered final and the instant update for the returned new head should be polled next time.When implemented as an
eventstream
, the streaming updates should refer to theblock_root
of the head known at the time when the last update was sent, meaning that whenever a new block appears the best signature for its parent and the header of the new head should be sent. Until a new block arrives, new updates containing onlybest_sync_aggregate
andsignature_slot
are sent as soon as more signatures are available. A short (<100ms) delay is acceptable in order to avoid sending up to 512 updates per slot as the individual signatures arrive.