Remote validator client: use v2 proposer duties endpoint from Fulu - #11164
Remote validator client: use v2 proposer duties endpoint from Fulu#11164rolfyone wants to merge 6 commits into
Conversation
Summary
The /eth/v2/validator/duties/proposer/{epoch} endpoint was already implemented server-side (GetProposerDutiesV2), but the remote validator client was always calling the deprecated v1 endpoint and ignoring the isFuluCompatible flag.
At Fulu the dependent root calculation changes: BlockProposalUtilFulu returns previousTargetRoot for current-epoch duties and currentTargetRoot for next-epoch duties, whereas the pre-Fulu logic does the opposite. BlockDutyScheduler uses the
fork-correct local calculation to check whether fetched duties are still fresh after a head event. If the remote client fetched via v1 (which forces PHASE0 logic server-side), the returned dependent_root would never match the locally computed
value at Fulu, causing duties to appear stale on every head event.
Changes
- ValidatorApiMethod: add GET_PROPOSER_DUTIES_V2 (eth/v2/validator/duties/proposer/:epoch)
- GetProposerDutiesV2Request: new request handler for the v2 endpoint (mirrors v1 handler)
- OkHttpValidatorTypeDefClient: expose getProposerDutiesV2(epoch)
- RemoteValidatorApiHandler: dispatch to v2 when isFuluCompatible=true (which BlockProductionDutyLoader always passes), fall back to v1 otherwise (for the deprecated beacon API v1 path)
- Tests covering both isFuluCompatible=false (v1) and isFuluCompatible=true (v2) paths
Note on "required from Gloas"
The beacon-APIs spec says v2 is only required from Gloas in the sense that other clients aren't obligated to implement it before then. The dependent root semantics change at Fulu, so v2 is needed for correctness from Fulu onwards — restricting it
to Gloas would cause incorrect dependent roots at Fulu.
fixes Consensys#10092
|
my only concern is this: Unconditional v2 with no fallback breaks the VC against any BN without eth/v2/validator/duties/proposer (blocking) RemoteValidatorApiHandler:222-224 routes to v2 whenever isFuluCompatible, which for the VC is always. Per beacon-APIs #563 v1 is not deprecated (that's planned post-Gloas), so Failure path when the BN returns 404:
So the VC produces no block proposal duties at all, on every epoch, on every network including pre-Fulu ones, with a misleading "chain data not available" error. should we force this? |
this is a functional change, but the reality is we just ignored it for fulu, so i think every other client is using v2 now. My main concern is gloas issues, so I need to make sure glaos actually works at a minimum before i can really promote this from draft. hoping to look again today. |
…supported, but require v2 within 2 epochs of gloas
|
|
||
| boolean isWithinTwoEpochsOfGloas(final UInt64 epoch) { | ||
| return gloasForkEpoch | ||
| .filter(g -> g.isGreaterThan(UInt64.ONE)) |
There was a problem hiding this comment.
why?
assuming testnet where we start from 0 epoch, I'd expect to use V2 there inevitably
we have minusMinZero to avoid underflow
| final int validatorIndex = 472; | ||
| final ProposerDuty schemaValidatorDuties = | ||
| new ProposerDuty(blsPublicKey, validatorIndex, UInt64.ZERO); | ||
| final ProposerDuty expectedValidatorDuties = |
There was a problem hiding this comment.
vars schemaValidatorDuties and expectedValidatorDuties are the same
| .thenCompose( | ||
| result -> { | ||
| if (result.isEmpty()) { | ||
| LOG.debug( |
There was a problem hiding this comment.
I'd make it warn. It could happen only once per launch
Summary
The /eth/v2/validator/duties/proposer/{epoch} endpoint was already implemented server-side (GetProposerDutiesV2), but the remote validator client was always calling the deprecated v1 endpoint and ignoring the isFuluCompatible flag.
At Fulu the dependent root calculation changes: BlockProposalUtilFulu returns previousTargetRoot for current-epoch duties and currentTargetRoot for next-epoch duties, whereas the pre-Fulu logic does the opposite. BlockDutyScheduler uses the
fork-correct local calculation to check whether fetched duties are still fresh after a head event. If the remote client fetched via v1 (which forces PHASE0 logic server-side), the returned dependent_root would never match the locally computed
value at Fulu, causing duties to appear stale on every head event.
Changes
Note on "required from Gloas"
The beacon-APIs spec says v2 is only required from Gloas in the sense that other clients aren't obligated to implement it before then. The dependent root semantics change at Fulu, so v2 is needed for correctness from Fulu onwards — restricting it
to Gloas would cause incorrect dependent roots at Fulu.
fixes #10092
Documentation
doc-change-requiredlabel to this PR if updates are required.Changelog
Note
Medium Risk
Changes how proposer duties are fetched during Fulu/Gloas transitions; incorrect routing could affect block proposal scheduling, though fallbacks and tests limit exposure.
Overview
The remote validator client no longer always hits
GET /eth/v1/validator/duties/proposer/{epoch}; whenisFuluCompatibleis true it prefers/eth/v2/..., which returns Fulu-correctdependent_rootvalues so duties are not treated as stale on every head update.Routing in
RemoteValidatorApiHandler: pre-Fulu stays on v1; if v2 returns empty (unsupported BN), it falls back to v1 once and remembers that for later calls; within two epochs of the Gloas fork it uses v2 only (no v1 fallback) and clears the “v2 unsupported” flag so upgraded beacon nodes get a fresh try. Wiring addsGetProposerDutiesV2Request, passesSpecinto the handler for the Gloas epoch, plus tests and a changelog note.Reviewed by Cursor Bugbot for commit a299e26. Bugbot is set up for automated code reviews on this repo. Configure here.