Add getNodeVersionV2 endpoint#568
Conversation
6fe82bf to
e0ea5c8
Compare
|
Similar to griffiti watermarks, it's reasonable to expect that there are nodes that either can't or choose not to pass back version specifics..... It's also seen sometimes in these watermarks that only one client (typically the CL) is declared (harder to tell if its unknown or no space). |
|
I consider this to be quite different from graffiti data since that is public, whereas the Beacon API is not generally exposed publicly. I don't really see an issue with passing back precise version information here. On the current V1 endpoint most clients already include everything that is proposed in this PR for the CL side, just in a less structured "User-agent" way:
I can see the beacon node not having EL-side information for some reason (e.g. because the EL client is not responding to the beacon node's Engine API requests). In such cases we could either not include the "execution_client" field in the return data (and make that entire field optional), or explicitly define an For the usecase I'm looking for, just the client names would suffice, e.g. this node is running Lodestar+Reth. But since most clients already include much more in their current user-agent, I decided to just reuse the Engine API schema. |
nflaig
left a comment
There was a problem hiding this comment.
Overall looks good to me, this was pretty straight forward to implement ChainSafe/lodestar#8772 for us.
|
I've added the following changes just now:
I left the conversations regarding the "unknown" behavior unresolved for now in case anyone else wants to chime in on that. |
|
LGTM, happy with "unknown" to signal an EL that is unresponsive or doesn't support the version endpoint |
|
I think using "magic strings" like "Unknown", "XX" and empty strings could be problematic because it forces the consumer to know and handle them (they could consider them valid values since non standard). I'd rather prefer making them nullable or optional. And the get method response: TLDR;
|
generally we don't want that because the response can't be ssz encoded if a field is nullable or optional but for this endpoint it doesn't matter, I would be fine with allowing there is one example for this Lines 49 to 52 in f49e171 it doesn't use
this api should never return an error, I don't see why the CL wouldn't be able to return it's own client info |
|
Thanks for the clarifications. for objects. By error I meant the already defined 500 error could be enough (if the API isn't able to respond for any reason) |
|
generally the field would just not be marked required, so if its null its not included in the output... |
not required would be the normal in the beacon-api - we generally don't pass back 'null' fields, i'd far prefer a field thats not required and just dont pass back the field rather than having 'null' or having strings like unknown, but if it was for execution specifically i'd probably be less worried about saying 'unknown' if a non required field is an issue for some reason. |
|
I am also fine with making fields optional if that's what everyone prefers to do |
Agreed, I don't like these too much either.
I am against doing this. Right now,
Based on the discussion above I'm leaning towards making the entire I've reverted the "unknown" / "XX" magic strings and gone for the optional Let me know if there are any more concerns. |
agreed, they are not optional on the engine api, I don't see a good reason why we would change that here, checking our existing type schema in Lodestar, all fields are required changes look good to me, just need to resolve merge conflicts |
james-prysm
left a comment
There was a problem hiding this comment.
seems good to us too, good discussion on null vs optional always good to clearly define those
Align format with engine api spec
nflaig
left a comment
There was a problem hiding this comment.
looks good, even though I don't like making execution_client an array but for the sake of aligning it with the engine api format I am fine either way
I'd rather prioritise the consumer and a clean abstraction over rigid adherence to an underlying implementation detail. The api should not be just a wrapper around an internal RPC call imo. |
## Description Updates the `getNodeVersionV2` endpoint to match the latest [beacon-APIs spec (PR #568)](ethereum/beacon-APIs#568), which changed `execution_client` from a single `ClientVersionV1` to an **array** of `ClientVersionV1`. This supports multiplexed EL connections where `engine_getClientVersionV1` may return multiple entries. ### Changes - `NodeVersionV2.executionClient` → `ClientVersion[]` (optional array) - `IExecutionEngine.clientVersion` → `clientVersions` (stores full array from Engine API) - Graffiti uses `clientVersions?.[0]` for the default graffiti string - Test data updated to match new array type ### Spec Reference From `apis/node/version.v2.yaml`: ```yaml execution_client: type: array items: $ref: '../../beacon-node-oapi.yaml#/components/schemas/ClientVersionV1' ``` > The `execution_client` field is an array because the Engine API's `engine_getClientVersionV1` may return multiple entries when using multiplexed connections. --- *This PR was authored with AI assistance (Claude/Lodekeeper 🌟)* --------- Co-authored-by: lodekeeper <lodekeeper@users.noreply.github.com>
The thing is, the beacon node may not necessarily know. If something like this EL multiplexer is used, the beacon node only sees one EL endpoint but would (presumably) receive an array with multiple values back from the Engine API call. Which of the multiplexed EL clients is/are actually used to determine whether a payload is valid in subsequent API calls is not quite clear from this response. I think it is still valuable to return a list with multiple values if multiple EL clients are somehow used by a single beacon node. Though for my usecase (Vero) this kind of response (multiple values) will simply be unsupported and raise an error.
Yes but I don't see that as that big of a downside, the list of values is the more correct information in case there are multiple EL clients connected. How the consumer decides to handle that is up to them. |
Since the multiplexer use case isn't standard, the BN should use deterministic heuristic if it's completely blind: the first from the list is the primary/active one for example. Decided by the BN and not the consumer.
I agree. That's why I suggested a "hybrid" approach:
If a consumer is always interested in a single EL, it should, ideally, not be forced to handle a list imo. Anyway, this is not a strong blocker for me |
In case of the external multiplexer, the beacon node has no say over which client is used as primary/active, it doesn't know – the external multiplexer decides which EL node(s) processes each Engine API request. The multiplexer logic may be trivial (picking the first healthy node) but can also be much more complex (e.g. require 2 out of 3 EL clients to agree on payload validity). The above is why I consider the hybrid approach interesting but insufficient to capture the full range of possibilities (from the point of view of behavior during consensus bugs which Beacon API consumers like Vero would be interested in). I believe we may have reached the point where there is no single correct answer what should be returned here. There are many possible options once you consider a beacon node is connected to multiple EL clients and they depend on how the beacon node interacts with those multiple EL clients, whether that's through a separate multiplexer or some internal logic. Trying to capture the full nuance of that in this Beacon API endpoint seems difficult to me.
The overlap between people running EL multiplexers and people interested in consuming this Therefore I propose we refocus on that standard in this PR and simplify by simply returning a single object for the If there's enough appetite in the future to work out the nuances for EL multiplexers, we can iterate on a v3 endpoint then but I think there's a good chance nobody will ever need that. |
this makes sense also when looking at how current client implementations work
all clients only use the first entry |
I agree with this approach. I initially approved that version of the PR. |
Return single object for `execution_client`
The beacon-APIs spec PR ethereum/beacon-APIs#568 changed execution_client from an array to a single optional ClientVersionV1 object. If the Engine API returns multiple values, the beacon node should return only the first one for consistent behavior across clients. Changes: - NodeVersionV2.executionClient: ClientVersion[] -> ClientVersion - Updated implementation to return single object instead of array - Updated test data accordingly
…ent (#8891) ## Description Aligns `getNodeVersionV2` with the latest spec change in [ethereum/beacon-APIs#568](ethereum/beacon-APIs#568). The spec [reverted `execution_client` from an array to a single optional object](eth2353/beacon-APIs@938aa33d) — if the Engine API returns multiple values, the beacon node should return only the first one for consistent behavior across clients. ### Changes - `NodeVersionV2.executionClient`: `ClientVersion[]` → `ClientVersion` (optional singular) - Updated implementation to return single object instead of wrapping in array - Updated test data ### Type of change - [x] Bug fix (non-breaking) ### Checklist - [x] Types compile (`pnpm build` passes) - [x] Unit tests pass (`pnpm --filter @lodestar/api test:unit` — 611/611) _This PR was created with AI assistance (Lodekeeper 🌟)_ Co-authored-by: lodekeeper <lodekeeper@users.noreply.github.com>
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
See ethereum/beacon-APIs#568 --------- Co-authored-by: Lodekeeper <258435968+lodekeeper@users.noreply.github.com> Co-authored-by: lodekeeper <lodekeeper@users.noreply.github.com> Co-authored-by: NC <17676176+ensi321@users.noreply.github.com>
Adds a
/eth/v2/node/versionendpoint for structured version information that also includes information about the attached EL client.Changes:
/eth/v1/node/versionendpointThe main motivation for this change is for validator clients to have access to information about the EL client attached to a beacon node. Right now, validator clients cannot see "past" the beacon node easily and are therefore blind to what kind of EL client is validating the execution payload. By exposing this information, multi-node validator clients can make safer decisions, e.g. they can require 3 different EL clients to declare the execution payload as valid before they attest to its validity.