Ensure finalized block is the correct fork variant when constructing light client updates (#7085)

This commit is contained in:
Eitan Seri-Levi
2025-03-16 20:39:35 -06:00
committed by GitHub
parent 50b5a72c58
commit 9db29b023b
2 changed files with 49 additions and 10 deletions

View File

@@ -213,12 +213,16 @@ impl<E: EthSpec> LightClientUpdate<E> {
.map_err(|_| Error::InconsistentFork)?
{
ForkName::Base => return Err(Error::AltairForkNotActive),
ForkName::Altair | ForkName::Bellatrix => {
fork_name @ ForkName::Altair | fork_name @ ForkName::Bellatrix => {
let attested_header =
LightClientHeaderAltair::block_to_light_client_header(attested_block)?;
let finalized_header = if let Some(finalized_block) = finalized_block {
LightClientHeaderAltair::block_to_light_client_header(finalized_block)?
if finalized_block.fork_name_unchecked() == fork_name {
LightClientHeaderAltair::block_to_light_client_header(finalized_block)?
} else {
LightClientHeaderAltair::default()
}
} else {
LightClientHeaderAltair::default()
};
@@ -233,12 +237,16 @@ impl<E: EthSpec> LightClientUpdate<E> {
signature_slot: block_slot,
})
}
ForkName::Capella => {
fork_name @ ForkName::Capella => {
let attested_header =
LightClientHeaderCapella::block_to_light_client_header(attested_block)?;
let finalized_header = if let Some(finalized_block) = finalized_block {
LightClientHeaderCapella::block_to_light_client_header(finalized_block)?
if finalized_block.fork_name_unchecked() == fork_name {
LightClientHeaderCapella::block_to_light_client_header(finalized_block)?
} else {
LightClientHeaderCapella::default()
}
} else {
LightClientHeaderCapella::default()
};
@@ -253,12 +261,16 @@ impl<E: EthSpec> LightClientUpdate<E> {
signature_slot: block_slot,
})
}
ForkName::Deneb => {
fork_name @ ForkName::Deneb => {
let attested_header =
LightClientHeaderDeneb::block_to_light_client_header(attested_block)?;
let finalized_header = if let Some(finalized_block) = finalized_block {
LightClientHeaderDeneb::block_to_light_client_header(finalized_block)?
if finalized_block.fork_name_unchecked() == fork_name {
LightClientHeaderDeneb::block_to_light_client_header(finalized_block)?
} else {
LightClientHeaderDeneb::default()
}
} else {
LightClientHeaderDeneb::default()
};
@@ -273,12 +285,16 @@ impl<E: EthSpec> LightClientUpdate<E> {
signature_slot: block_slot,
})
}
ForkName::Electra => {
fork_name @ ForkName::Electra => {
let attested_header =
LightClientHeaderElectra::block_to_light_client_header(attested_block)?;
let finalized_header = if let Some(finalized_block) = finalized_block {
LightClientHeaderElectra::block_to_light_client_header(finalized_block)?
if finalized_block.fork_name_unchecked() == fork_name {
LightClientHeaderElectra::block_to_light_client_header(finalized_block)?
} else {
LightClientHeaderElectra::default()
}
} else {
LightClientHeaderElectra::default()
};
@@ -293,12 +309,16 @@ impl<E: EthSpec> LightClientUpdate<E> {
signature_slot: block_slot,
})
}
ForkName::Fulu => {
fork_name @ ForkName::Fulu => {
let attested_header =
LightClientHeaderFulu::block_to_light_client_header(attested_block)?;
let finalized_header = if let Some(finalized_block) = finalized_block {
LightClientHeaderFulu::block_to_light_client_header(finalized_block)?
if finalized_block.fork_name_unchecked() == fork_name {
LightClientHeaderFulu::block_to_light_client_header(finalized_block)?
} else {
LightClientHeaderFulu::default()
}
} else {
LightClientHeaderFulu::default()
};

View File

@@ -264,6 +264,11 @@ pub(crate) async fn verify_light_client_updates<E: EthSpec>(
let slot = Slot::new(slot);
let previous_slot = slot - 1;
let sync_committee_period = slot
.epoch(E::slots_per_epoch())
.sync_committee_period(&E::default_spec())
.unwrap();
let previous_slot_block = client
.get_beacon_blocks::<E>(BlockId::Slot(previous_slot))
.await
@@ -329,6 +334,20 @@ pub(crate) async fn verify_light_client_updates<E: EthSpec>(
"Existing finality update too old: signature slot {signature_slot}, current slot {slot:?}"
));
}
let light_client_updates = client
.get_beacon_light_client_updates::<E>(sync_committee_period, 1)
.await
.map_err(|e| format!("Error while getting light client update: {:?}", e))?
.ok_or(format!("Light client update not found {slot:?}"))?;
// Ensure we're only storing a single light client update for the given sync committee period
if light_client_updates.len() != 1 {
return Err(format!(
"{} light client updates was returned when only one was expected.",
light_client_updates.len()
));
}
}
Ok(())