Implement proposer duties v2 endpoint (#8918)

Fix the issue with the `proposer_duties` endpoint using the wrong dependent root post-Fulu by implementing the new v2 endpoint:

- https://github.com/ethereum/beacon-APIs/pull/563

We need to add this in time for Gloas, and then we can we can deprecate and remove v1.


  - Add a new API handler for the v2 endpoint
- Add client code in the `eth2` crate
- Update existing tests and add some new ones to confirm the different behaviour of v1 and v2

There's a bit of test duplication with v1, but this will be resolved once v1 and its tests are deleted.


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>

Co-Authored-By: Michael Sproul <michaelsproul@users.noreply.github.com>

Co-Authored-By: chonghe <44791194+chong-he@users.noreply.github.com>
This commit is contained in:
Michael Sproul
2026-03-10 18:57:51 +11:00
committed by GitHub
parent 9f3873f2bf
commit 081229b748
6 changed files with 438 additions and 32 deletions

View File

@@ -6,7 +6,7 @@ use crate::utils::{
AnyVersionFilter, ChainFilter, EthV1Filter, NetworkTxFilter, NotWhileSyncingFilter,
ResponseFilter, TaskSpawnerFilter, ValidatorSubscriptionTxFilter, publish_network_message,
};
use crate::version::V3;
use crate::version::{V1, V2, V3, unsupported_version_rejection};
use crate::{StateId, attester_duties, proposer_duties, sync_committees};
use beacon_chain::attestation_verification::VerifiedAttestation;
use beacon_chain::validator_monitor::timestamp_now;
@@ -971,12 +971,12 @@ pub fn post_validator_aggregate_and_proofs<T: BeaconChainTypes>(
// GET validator/duties/proposer/{epoch}
pub fn get_validator_duties_proposer<T: BeaconChainTypes>(
eth_v1: EthV1Filter,
any_version: AnyVersionFilter,
chain_filter: ChainFilter<T>,
not_while_syncing_filter: NotWhileSyncingFilter,
task_spawner_filter: TaskSpawnerFilter<T>,
) -> ResponseFilter {
eth_v1
any_version
.and(warp::path("validator"))
.and(warp::path("duties"))
.and(warp::path("proposer"))
@@ -990,13 +990,20 @@ pub fn get_validator_duties_proposer<T: BeaconChainTypes>(
.and(task_spawner_filter)
.and(chain_filter)
.then(
|epoch: Epoch,
|endpoint_version: EndpointVersion,
epoch: Epoch,
not_synced_filter: Result<(), Rejection>,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>| {
task_spawner.blocking_json_task(Priority::P0, move || {
not_synced_filter?;
proposer_duties::proposer_duties(epoch, &chain)
if endpoint_version == V1 {
proposer_duties::proposer_duties(epoch, &chain)
} else if endpoint_version == V2 {
proposer_duties::proposer_duties_v2(epoch, &chain)
} else {
Err(unsupported_version_rejection(endpoint_version))
}
})
},
)