Add pending_consolidations Beacon API endpoint (#7290)

#7282


  Adds the missing `beacon/states/{state_id}/pending_consolidations` Beacon API endpoint along with related tests.
This commit is contained in:
Mac L
2025-04-10 11:21:01 +10:00
committed by GitHub
parent ec643843e0
commit 7534f5752d
3 changed files with 83 additions and 0 deletions

View File

@@ -1186,6 +1186,39 @@ pub fn serve<T: BeaconChainTypes>(
},
);
// GET beacon/states/{state_id}/pending_consolidations
let get_beacon_state_pending_consolidations = beacon_states_path
.clone()
.and(warp::path("pending_consolidations"))
.and(warp::path::end())
.then(
|state_id: StateId,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>| {
task_spawner.blocking_json_task(Priority::P1, move || {
let (data, execution_optimistic, finalized) = state_id
.map_state_and_execution_optimistic_and_finalized(
&chain,
|state, execution_optimistic, finalized| {
let Ok(consolidations) = state.pending_consolidations() else {
return Err(warp_utils::reject::custom_bad_request(
"Pending consolidations not found".to_string(),
));
};
Ok((consolidations.clone(), execution_optimistic, finalized))
},
)?;
Ok(api_types::ExecutionOptimisticFinalizedResponse {
data,
execution_optimistic: Some(execution_optimistic),
finalized: Some(finalized),
})
})
},
);
// GET beacon/headers
//
// Note: this endpoint only returns information about blocks in the canonical chain. Given that
@@ -4853,6 +4886,7 @@ pub fn serve<T: BeaconChainTypes>(
.uor(get_beacon_state_randao)
.uor(get_beacon_state_pending_deposits)
.uor(get_beacon_state_pending_partial_withdrawals)
.uor(get_beacon_state_pending_consolidations)
.uor(get_beacon_headers)
.uor(get_beacon_headers_block_id)
.uor(get_beacon_block)

View File

@@ -1246,6 +1246,33 @@ impl ApiTester {
self
}
pub async fn test_beacon_states_pending_consolidations(self) -> Self {
for state_id in self.interesting_state_ids() {
let mut state_opt = state_id
.state(&self.chain)
.ok()
.map(|(state, _execution_optimistic, _finalized)| state);
let result = self
.client
.get_beacon_states_pending_consolidations(state_id.0)
.await
.unwrap()
.map(|res| res.data);
if result.is_none() && state_opt.is_none() {
continue;
}
let state = state_opt.as_mut().expect("result should be none");
let expected = state.pending_consolidations().unwrap();
assert_eq!(result.unwrap(), expected.to_vec());
}
self
}
pub async fn test_beacon_headers_all_slots(self) -> Self {
for slot in 0..CHAIN_LENGTH {
let slot = Slot::from(slot);
@@ -6404,6 +6431,8 @@ async fn beacon_get_state_info_electra() {
.test_beacon_states_pending_deposits()
.await
.test_beacon_states_pending_partial_withdrawals()
.await
.test_beacon_states_pending_consolidations()
.await;
}

View File

@@ -821,6 +821,26 @@ impl BeaconNodeHttpClient {
self.get_opt(path).await
}
/// `GET beacon/states/{state_id}/pending_consolidations`
///
/// Returns `Ok(None)` on a 404 error.
pub async fn get_beacon_states_pending_consolidations(
&self,
state_id: StateId,
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<PendingConsolidation>>>, Error>
{
let mut path = self.eth_path(V1)?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon")
.push("states")
.push(&state_id.to_string())
.push("pending_consolidations");
self.get_opt(path).await
}
/// `GET beacon/light_client/updates`
///
/// Returns `Ok(None)` on a 404 error.