Skip to content

Commit 87cb6dc

Browse files
authored
Merge of #5174
2 parents 4068bcf + b384c3f commit 87cb6dc

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2567,7 +2567,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
25672567
&self,
25682568
epoch: Epoch,
25692569
validator_indices: &[u64],
2570-
) -> Result<Vec<Option<SyncDuty>>, Error> {
2570+
) -> Result<Vec<Result<Option<SyncDuty>, BeaconStateError>>, Error> {
25712571
self.with_head(move |head| {
25722572
head.beacon_state
25732573
.get_sync_committee_duties(epoch, validator_indices, &self.spec)

beacon_node/http_api/src/sync_committees.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ pub fn sync_committee_duties<T: BeaconChainTypes>(
4545
// the vast majority of requests. Rather than checking if we think the request will succeed in a
4646
// way prone to data races, we attempt the request immediately and check the error code.
4747
match chain.sync_committee_duties_from_head(request_epoch, request_indices) {
48-
Ok(duties) => return Ok(convert_to_response(duties, execution_optimistic)),
48+
Ok(duties) => {
49+
return Ok(convert_to_response(
50+
verify_unknown_validators(duties, request_epoch, chain)?,
51+
execution_optimistic,
52+
))
53+
}
4954
Err(BeaconChainError::SyncDutiesError(BeaconStateError::SyncCommitteeNotKnown {
5055
..
5156
}))
@@ -64,7 +69,10 @@ pub fn sync_committee_duties<T: BeaconChainTypes>(
6469
)),
6570
e => warp_utils::reject::beacon_chain_error(e),
6671
})?;
67-
Ok(convert_to_response(duties, execution_optimistic))
72+
Ok(convert_to_response(
73+
verify_unknown_validators(duties, request_epoch, chain)?,
74+
execution_optimistic,
75+
))
6876
}
6977

7078
/// Slow path for duties: load a state and use it to compute the duties.
@@ -73,7 +81,7 @@ fn duties_from_state_load<T: BeaconChainTypes>(
7381
request_indices: &[u64],
7482
altair_fork_epoch: Epoch,
7583
chain: &BeaconChain<T>,
76-
) -> Result<Vec<Option<SyncDuty>>, BeaconChainError> {
84+
) -> Result<Vec<Result<Option<SyncDuty>, BeaconStateError>>, BeaconChainError> {
7785
// Determine what the current epoch would be if we fast-forward our system clock by
7886
// `MAXIMUM_GOSSIP_CLOCK_DISPARITY`.
7987
//
@@ -121,6 +129,45 @@ fn duties_from_state_load<T: BeaconChainTypes>(
121129
}
122130
}
123131

132+
fn verify_unknown_validators<T: BeaconChainTypes>(
133+
duties: Vec<Result<Option<SyncDuty>, BeaconStateError>>,
134+
request_epoch: Epoch,
135+
chain: &BeaconChain<T>,
136+
) -> Result<Vec<Option<SyncDuty>>, warp::reject::Rejection> {
137+
// Lazily load the request_epoch_state, as it is only needed if there are any UnknownValidator
138+
let mut request_epoch_state = None;
139+
140+
duties
141+
.into_iter()
142+
.map(|res| {
143+
res.or_else(|err| {
144+
// Make sure the validator is really unknown w.r.t. the request_epoch
145+
if let BeaconStateError::UnknownValidator(idx) = err {
146+
let request_epoch_state = match &mut request_epoch_state {
147+
Some(state) => state,
148+
None => request_epoch_state.insert(chain.state_at_slot(
149+
request_epoch.start_slot(T::EthSpec::slots_per_epoch()),
150+
StateSkipConfig::WithoutStateRoots,
151+
)?),
152+
};
153+
request_epoch_state
154+
.get_validator(idx)
155+
.map_err(BeaconChainError::SyncDutiesError)
156+
.map(|_| None)
157+
} else {
158+
Err(BeaconChainError::SyncDutiesError(err))
159+
}
160+
})
161+
})
162+
.collect::<Result<Vec<_>, _>>()
163+
.map_err(|err| match err {
164+
BeaconChainError::SyncDutiesError(BeaconStateError::UnknownValidator(idx)) => {
165+
warp_utils::reject::custom_bad_request(format!("invalid validator index: {idx}"))
166+
}
167+
e => warp_utils::reject::beacon_chain_error(e),
168+
})
169+
}
170+
124171
fn convert_to_response(duties: Vec<Option<SyncDuty>>, execution_optimistic: bool) -> SyncDuties {
125172
api_types::GenericResponse::from(duties.into_iter().flatten().collect::<Vec<_>>())
126173
.add_execution_optimistic(execution_optimistic)

consensus/types/src/beacon_state.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -960,10 +960,10 @@ impl<T: EthSpec> BeaconState<T> {
960960
epoch: Epoch,
961961
validator_indices: &[u64],
962962
spec: &ChainSpec,
963-
) -> Result<Vec<Option<SyncDuty>>, Error> {
963+
) -> Result<Vec<Result<Option<SyncDuty>, Error>>, Error> {
964964
let sync_committee = self.get_built_sync_committee(epoch, spec)?;
965965

966-
validator_indices
966+
Ok(validator_indices
967967
.iter()
968968
.map(|&validator_index| {
969969
let pubkey = self.get_validator(validator_index as usize)?.pubkey;
@@ -974,7 +974,7 @@ impl<T: EthSpec> BeaconState<T> {
974974
sync_committee,
975975
))
976976
})
977-
.collect()
977+
.collect())
978978
}
979979

980980
/// Get the canonical root of the `latest_block_header`, filling in its state root if necessary.

0 commit comments

Comments
 (0)