From 8c7a995c91da16d428b92e66a4e2a9d55c1f8387 Mon Sep 17 00:00:00 2001 From: Tan Chee Keong Date: Wed, 19 Feb 2025 21:46:12 +0800 Subject: [PATCH] Add client side endpoint --- common/eth2/src/lib.rs | 16 ++++++ .../validator_services/src/duties_service.rs | 52 ++++++++++++------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index 73e9d57abc..7a87eeb90c 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -2664,6 +2664,22 @@ impl BeaconNodeHttpClient { ) .await } + + /// `POST validator/beacon_committee_selections` + pub async fn post_validator_beacon_committee_selections( + &self, + selections: &[BeaconCommitteeSelection], + ) -> Result<(), Error> { + let mut path = self.eth_path(V1)?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("beacon_committee_selections"); + + self.post_with_timeout(path, &selections, self.timeouts.attester_duties) + .await + } } /// Returns `Ok(response)` if the response is a `200 OK` response. Otherwise, creates an diff --git a/validator_client/validator_services/src/duties_service.rs b/validator_client/validator_services/src/duties_service.rs index f9bbd4897d..de695ec0eb 100644 --- a/validator_client/validator_services/src/duties_service.rs +++ b/validator_client/validator_services/src/duties_service.rs @@ -13,7 +13,8 @@ use beacon_node_fallback::{ApiTopic, BeaconNodeFallback}; use doppelganger_service::DoppelgangerStatus; use environment::RuntimeContext; use eth2::types::{ - AttesterData, BeaconCommitteeSubscription, DutiesResponse, ProposerData, StateId, ValidatorId, + AttesterData, BeaconCommitteeSelection, BeaconCommitteeSubscription, DutiesResponse, + ProposerData, StateId, ValidatorId, }; use futures::{stream, StreamExt}; use parking_lot::RwLock; @@ -132,36 +133,47 @@ async fn make_selection_proof( distributed: bool, beacon_nodes: &Arc>, ) -> Result, Error> { - if distributed { - // call the middleware for the endpoint /eth/v1/validator/beacon_committee_subscriptions + let selection_proof = if distributed { + // Call the endpoint /eth/v1/validator/beacon_committee_selections + // During the call, we submit a partial selection proof in the data field of the POST HTTP endpoint + // The end point (middleware) should return a full selection proof + + let selections = BeaconCommitteeSelection { + validator_index: duty.validator_idnex, + slot: duty.slot, + selection_proof: validator_store + .produce_selection_proof(duty.pubkey, duty.slot) + .await + .map_err(Error::FailedToProduceSelectionProof)?; + }; + beacon_nodes .first_success(|beacon_node| async move { beacon_node - .post_validator_beacon_committee_subscriptions() + .post_validator_beacon_committee_selections(selections) .await }) .await .map_err(|e| Error::FailedToProduceSelectionProof(e.to_string())) - .map(|_| None) } else { - let selection_proof = validator_store + validator_store .produce_selection_proof(duty.pubkey, duty.slot) .await .map_err(Error::FailedToProduceSelectionProof)?; - - selection_proof - .is_aggregator(duty.committee_length as usize, spec) - .map_err(Error::InvalidModulo) - .map(|is_aggregator| { - if is_aggregator { - Some(selection_proof) - } else { - // Don't bother storing the selection proof if the validator isn't an - // aggregator, we won't need it. - None - } - }) - } + }; + + selection_proof + .is_aggregator(duty.committee_length as usize, spec) + .map_err(Error::InvalidModulo) + .map(|is_aggregator| { + if is_aggregator { + Some(selection_proof) + } else { + // Don't bother storing the selection proof if the validator isn't an + // aggregator, we won't need it. + None + } + }) } impl DutyAndProof {