From 1fd7ead0109d80c98c05f229e107bb10c8ed0711 Mon Sep 17 00:00:00 2001 From: Daniel Knopik <107140945+dknopik@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:46:37 +0200 Subject: [PATCH] Do not filter validators by status if filter is an empty list (#7884) https://github.com/ethereum/beacon-APIs/blob/69d2feb12a6047c4f21e628dea8b0135b7e9013a/apis/beacon/states/validators.yaml#L128-L130 says we need to not filter if the filter is an empty list. Add a check for `statuses.is_empty()`. --- beacon_node/http_api/src/validators.rs | 23 +++++++++++++++------ beacon_node/http_api/tests/tests.rs | 28 +++++++++++++++++++------- common/eth2/src/types.rs | 2 +- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/beacon_node/http_api/src/validators.rs b/beacon_node/http_api/src/validators.rs index 755b540502..6856318265 100644 --- a/beacon_node/http_api/src/validators.rs +++ b/beacon_node/http_api/src/validators.rs @@ -18,8 +18,18 @@ pub fn get_beacon_state_validators( |state, execution_optimistic, finalized| { let epoch = state.current_epoch(); let far_future_epoch = chain.spec.far_future_epoch; - let ids_filter_set: Option> = - query_ids.as_ref().map(HashSet::from_iter); + + // Map [] to None, indicating that no filtering should be applied (return all + // validators). + let ids_filter_set: Option> = query_ids + .as_ref() + .filter(|list| !list.is_empty()) + .map(HashSet::from_iter); + + let statuses_filter_set: Option> = query_statuses + .as_ref() + .filter(|list| !list.is_empty()) + .map(HashSet::from_iter); Ok(( state @@ -42,10 +52,11 @@ pub fn get_beacon_state_validators( far_future_epoch, ); - let status_matches = query_statuses.as_ref().is_none_or(|statuses| { - statuses.contains(&status) - || statuses.contains(&status.superstatus()) - }); + let status_matches = + statuses_filter_set.as_ref().is_none_or(|statuses| { + statuses.contains(&status) + || statuses.contains(&status.superstatus()) + }); if status_matches { Some(ValidatorData { diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index b1c06dd4e6..69d2b5c21b 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -1079,7 +1079,7 @@ impl ApiTester { .get_beacon_states_validators( state_id.0, Some(validator_index_ids.as_slice()), - None, + Some(statuses.as_slice()), ) .await .unwrap() @@ -1089,20 +1089,28 @@ impl ApiTester { .get_beacon_states_validators( state_id.0, Some(validator_pubkey_ids.as_slice()), - None, + Some(statuses.as_slice()), ) .await .unwrap() .map(|res| res.data); let post_result_index_ids = self .client - .post_beacon_states_validators(state_id.0, Some(validator_index_ids), None) + .post_beacon_states_validators( + state_id.0, + Some(validator_index_ids), + Some(statuses.clone()), + ) .await .unwrap() .map(|res| res.data); let post_result_pubkey_ids = self .client - .post_beacon_states_validators(state_id.0, Some(validator_pubkey_ids), None) + .post_beacon_states_validators( + state_id.0, + Some(validator_pubkey_ids), + Some(statuses.clone()), + ) .await .unwrap() .map(|res| res.data); @@ -1113,7 +1121,13 @@ impl ApiTester { let mut validators = Vec::with_capacity(validator_indices.len()); - for i in validator_indices { + let expected_indices = if validator_indices.is_empty() { + (0..state.validators().len() as u64).collect() + } else { + validator_indices.clone() + }; + + for i in expected_indices { if i >= state.validators().len() as u64 { continue; } @@ -1123,8 +1137,8 @@ impl ApiTester { epoch, far_future_epoch, ); - if statuses.contains(&status) - || statuses.is_empty() + if statuses.is_empty() + || statuses.contains(&status) || statuses.contains(&status.superstatus()) { validators.push(ValidatorData { diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index f46d72d6f7..c554831f8b 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -366,7 +366,7 @@ pub struct ValidatorIdentityData { // this proposal: // // https://hackmd.io/bQxMDRt1RbS1TLno8K4NPg?view -#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ValidatorStatus { PendingInitialized,