Implement validator_identities Beacon API endpoint (#7462)

* #7442
This commit is contained in:
chonghe
2025-06-23 16:37:49 +08:00
committed by GitHub
parent 3fefda68e5
commit cef04ee2ee
5 changed files with 200 additions and 2 deletions

View File

@@ -48,7 +48,8 @@ use directory::DEFAULT_ROOT_DIR;
use eth2::types::{
self as api_types, BroadcastValidation, ContextDeserialize, EndpointVersion, ForkChoice,
ForkChoiceNode, LightClientUpdatesQuery, PublishBlockRequest, StateId as CoreStateId,
ValidatorBalancesRequestBody, ValidatorId, ValidatorStatus, ValidatorsRequestBody,
ValidatorBalancesRequestBody, ValidatorId, ValidatorIdentitiesRequestBody, ValidatorStatus,
ValidatorsRequestBody,
};
use eth2::{CONSENSUS_VERSION_HEADER, CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER};
use health_metrics::observe::Observe;
@@ -702,6 +703,34 @@ pub fn serve<T: BeaconChainTypes>(
},
);
// POST beacon/states/{state_id}/validator_identities
let post_beacon_state_validator_identities = beacon_states_path
.clone()
.and(warp::path("validator_identities"))
.and(warp::path::end())
.and(warp_utils::json::json_no_body())
.then(
|state_id: StateId,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
query: ValidatorIdentitiesRequestBody| {
// Prioritise requests for validators at the head. These should be fast to service
// and could be required by the validator client.
let priority = if let StateId(eth2::types::StateId::Head) = state_id {
Priority::P0
} else {
Priority::P1
};
task_spawner.blocking_json_task(priority, move || {
crate::validators::get_beacon_state_validator_identities(
state_id,
chain,
Some(&query.ids),
)
})
},
);
// GET beacon/states/{state_id}/validators?id,status
let get_beacon_state_validators = beacon_states_path
.clone()
@@ -4852,6 +4881,7 @@ pub fn serve<T: BeaconChainTypes>(
.uor(post_beacon_pool_bls_to_execution_changes)
.uor(post_beacon_state_validators)
.uor(post_beacon_state_validator_balances)
.uor(post_beacon_state_validator_identities)
.uor(post_beacon_rewards_attestations)
.uor(post_beacon_rewards_sync_committee)
.uor(post_validator_duties_attester)

View File

@@ -2,7 +2,7 @@ use crate::state_id::StateId;
use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2::types::{
self as api_types, ExecutionOptimisticFinalizedResponse, ValidatorBalanceData, ValidatorData,
ValidatorId, ValidatorStatus,
ValidatorId, ValidatorIdentityData, ValidatorStatus,
};
use std::{collections::HashSet, sync::Arc};
@@ -119,3 +119,51 @@ pub fn get_beacon_state_validator_balances<T: BeaconChainTypes>(
finalized: Some(finalized),
})
}
pub fn get_beacon_state_validator_identities<T: BeaconChainTypes>(
state_id: StateId,
chain: Arc<BeaconChain<T>>,
optional_ids: Option<&[ValidatorId]>,
) -> Result<ExecutionOptimisticFinalizedResponse<Vec<ValidatorIdentityData>>, warp::Rejection> {
let (data, execution_optimistic, finalized) = state_id
.map_state_and_execution_optimistic_and_finalized(
&chain,
|state, execution_optimistic, finalized| {
let ids_filter_set: Option<HashSet<&ValidatorId>> = match optional_ids {
// Same logic as validator_balances endpoint above
Some([]) => None,
Some(ids) => Some(HashSet::from_iter(ids.iter())),
None => None,
};
Ok((
// From the BeaconState, extract the Validator data and convert it into ValidatorIdentityData type
state
.validators()
.iter()
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, validator)| {
ids_filter_set.as_ref().is_none_or(|ids_set| {
ids_set.contains(&ValidatorId::PublicKey(validator.pubkey))
|| ids_set.contains(&ValidatorId::Index(*index as u64))
})
})
.map(|(index, validator)| ValidatorIdentityData {
index: index as u64,
pubkey: validator.pubkey,
activation_epoch: validator.activation_epoch,
})
.collect::<Vec<_>>(),
execution_optimistic,
finalized,
))
},
)?;
Ok(api_types::ExecutionOptimisticFinalizedResponse {
data,
execution_optimistic: Some(execution_optimistic),
finalized: Some(finalized),
})
}