Skip to content

Commit d46a8e5

Browse files
authored
fix: corrected the sync-protocol implementation on next sync committee updates (#406)
1 parent da3a351 commit d46a8e5

File tree

3 files changed

+36
-15
lines changed

3 files changed

+36
-15
lines changed
219 Bytes
Binary file not shown.

packages/ethereum/ethereum-light-client/src/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ pub enum EthereumIBCError {
128128
#[error("expected next sync committee to be known and stored in state")]
129129
NextSyncCommitteeUnknown,
130130

131+
#[error("unexpected next sync committee in the update")]
132+
UnexpectedNextSyncCommittee,
133+
131134
#[error("bls aggregate error: {0}")]
132135
BlsAggregateError(String),
133136

packages/ethereum/ethereum-light-client/src/verify.rs

+33-15
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ pub fn validate_light_client_update<V: BlsVerify>(
187187
let signature_period =
188188
client_state.compute_sync_committee_period_at_slot(update.signature_slot);
189189

190-
if trusted_consensus_state.next_sync_committee().is_some() {
190+
let is_next_sync_committee_known = trusted_consensus_state.next_sync_committee().is_some();
191+
if is_next_sync_committee_known {
191192
ensure!(
192193
signature_period == stored_period || signature_period == stored_period + 1,
193194
EthereumIBCError::InvalidSignaturePeriodWhenNextSyncCommitteeExists {
@@ -209,16 +210,18 @@ pub fn validate_light_client_update<V: BlsVerify>(
209210
let update_attested_period =
210211
client_state.compute_sync_committee_period_at_slot(update_attested_slot);
211212

213+
let is_next_sync_committee_update = update.next_sync_committee_branch.is_some();
214+
let update_has_next_sync_committee = !is_next_sync_committee_known
215+
&& is_next_sync_committee_update
216+
&& update_attested_period == stored_period;
212217
// There are two options to do a light client update:
213218
// 1. We are updating the header with a newer one.
214219
// 2. We haven't set the next sync committee yet and we can use any attested header within the same
215220
// signature period to set the next sync committee. This means that the stored header could be larger.
216221
// The light client implementation needs to take care of it.
217222
ensure!(
218223
update_attested_slot > trusted_consensus_state.finalized_slot()
219-
|| (update_attested_period == stored_period
220-
&& update.next_sync_committee.is_some()
221-
&& trusted_consensus_state.next_sync_committee().is_none()),
224+
|| update_has_next_sync_committee,
222225
EthereumIBCError::IrrelevantUpdate {
223226
update_attested_slot,
224227
trusted_finalized_slot: trusted_consensus_state.finalized_slot(),
@@ -251,31 +254,46 @@ pub fn validate_light_client_update<V: BlsVerify>(
251254

252255
// Verify that if the update contains the next sync committee, and the signature periods do match,
253256
// next sync committees match too.
254-
if let (Some(next_sync_committee), Some(stored_next_sync_committee)) = (
255-
&update.next_sync_committee,
256-
trusted_consensus_state.next_sync_committee(),
257-
) {
258-
if update_attested_period == stored_period {
257+
if is_next_sync_committee_update {
258+
if update_attested_period == stored_period && is_next_sync_committee_known {
259259
ensure!(
260-
next_sync_committee == stored_next_sync_committee,
260+
update.next_sync_committee.as_ref().unwrap()
261+
== trusted_consensus_state.next_sync_committee().unwrap(),
261262
EthereumIBCError::NextSyncCommitteeMismatch {
262-
expected: stored_next_sync_committee.aggregate_pubkey,
263-
found: next_sync_committee.aggregate_pubkey,
263+
expected: trusted_consensus_state
264+
.next_sync_committee()
265+
.unwrap()
266+
.aggregate_pubkey,
267+
found: update
268+
.next_sync_committee
269+
.as_ref()
270+
.unwrap()
271+
.aggregate_pubkey,
264272
}
265273
);
266274
}
275+
267276
// This validates the given next sync committee against the attested header's state root.
268277
validate_merkle_branch(
269-
next_sync_committee.tree_hash_root(),
270-
update.next_sync_committee_branch.unwrap_or_default().into(),
278+
update
279+
.next_sync_committee
280+
.as_ref()
281+
.unwrap()
282+
.tree_hash_root(),
283+
update.next_sync_committee_branch.unwrap().into(),
271284
NEXT_SYNC_COMMITTEE_BRANCH_DEPTH,
272285
get_subtree_index(next_sync_committee_gindex_at_slot(
273286
client_state,
274-
update.finalized_header.beacon.slot,
287+
update.attested_header.beacon.slot,
275288
)?),
276289
update.attested_header.beacon.state_root,
277290
)
278291
.map_err(|e| EthereumIBCError::ValidateNextSyncCommitteeFailed(Box::new(e)))?;
292+
} else {
293+
ensure!(
294+
update.next_sync_committee.is_none(),
295+
EthereumIBCError::UnexpectedNextSyncCommittee
296+
);
279297
}
280298

281299
// Verify sync committee aggregate signature

0 commit comments

Comments
 (0)