mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-16 11:22:56 +00:00
Merge branch 'unstable' into vc-fallback
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::local_network::LocalNetwork;
|
||||
use crate::ACCEPTABLE_FALLBACK_ATTESTATION_HIT_PERCENTAGE;
|
||||
use node_test_rig::eth2::types::{BlockId, StateId};
|
||||
use node_test_rig::eth2::types::{BlockId, FinalityCheckpointsData, StateId};
|
||||
use std::time::Duration;
|
||||
use types::{Epoch, EthSpec, ExecPayload, ExecutionBlockHash, Hash256, Slot, Unsigned};
|
||||
|
||||
@@ -245,6 +245,96 @@ pub async fn verify_transition_block_finalized<E: EthSpec>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn verify_light_client_updates<E: EthSpec>(
|
||||
network: LocalNetwork<E>,
|
||||
start_slot: Slot,
|
||||
end_slot: Slot,
|
||||
slot_duration: Duration,
|
||||
) -> Result<(), String> {
|
||||
slot_delay(start_slot, slot_duration).await;
|
||||
|
||||
// Tolerance of 2 slot allows for 1 single missed slot.
|
||||
let light_client_update_slot_tolerance = Slot::new(2);
|
||||
let remote_nodes = network.remote_nodes()?;
|
||||
let client = remote_nodes.first().unwrap();
|
||||
let mut have_seen_block = false;
|
||||
let mut have_achieved_finality = false;
|
||||
|
||||
for slot in start_slot.as_u64()..=end_slot.as_u64() {
|
||||
slot_delay(Slot::new(1), slot_duration).await;
|
||||
let slot = Slot::new(slot);
|
||||
let previous_slot = slot - 1;
|
||||
|
||||
let previous_slot_block = client
|
||||
.get_beacon_blocks::<E>(BlockId::Slot(previous_slot))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
format!("Unable to get beacon block for previous slot {previous_slot:?}: {e:?}")
|
||||
})?;
|
||||
let previous_slot_has_block = previous_slot_block.is_some();
|
||||
|
||||
if !have_seen_block {
|
||||
// Make sure we have seen the first block in Altair, to make sure we have sync aggregates available.
|
||||
if previous_slot_has_block {
|
||||
have_seen_block = true;
|
||||
}
|
||||
// Wait for another slot before we check the first update to avoid race condition.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure previous slot has a block, otherwise skip checking for the signature slot distance
|
||||
if !previous_slot_has_block {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify light client optimistic update. `signature_slot_distance` should be 1 in the ideal scenario.
|
||||
let signature_slot = client
|
||||
.get_beacon_light_client_optimistic_update::<E>()
|
||||
.await
|
||||
.map_err(|e| format!("Error while getting light client updates: {:?}", e))?
|
||||
.ok_or(format!("Light client optimistic update not found {slot:?}"))?
|
||||
.data
|
||||
.signature_slot;
|
||||
let signature_slot_distance = slot - signature_slot;
|
||||
if signature_slot_distance > light_client_update_slot_tolerance {
|
||||
return Err(format!("Existing optimistic update too old: signature slot {signature_slot}, current slot {slot:?}"));
|
||||
}
|
||||
|
||||
// Verify light client finality update. `signature_slot_distance` should be 1 in the ideal scenario.
|
||||
// NOTE: Currently finality updates are produced as long as the finalized block is known, even if the finalized header
|
||||
// sync committee period does not match the signature slot committee period.
|
||||
// TODO: This complies with the current spec, but we should check if this is a bug.
|
||||
if !have_achieved_finality {
|
||||
let FinalityCheckpointsData { finalized, .. } = client
|
||||
.get_beacon_states_finality_checkpoints(StateId::Head)
|
||||
.await
|
||||
.map_err(|e| format!("Unable to get beacon state finality checkpoint: {e:?}"))?
|
||||
.ok_or("Unable to get head state".to_string())?
|
||||
.data;
|
||||
if !finalized.root.is_zero() {
|
||||
// Wait for another slot before we check the first finality update to avoid race condition.
|
||||
have_achieved_finality = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let signature_slot = client
|
||||
.get_beacon_light_client_finality_update::<E>()
|
||||
.await
|
||||
.map_err(|e| format!("Error while getting light client updates: {:?}", e))?
|
||||
.ok_or(format!("Light client finality update not found {slot:?}"))?
|
||||
.data
|
||||
.signature_slot;
|
||||
let signature_slot_distance = slot - signature_slot;
|
||||
if signature_slot_distance > light_client_update_slot_tolerance {
|
||||
return Err(format!(
|
||||
"Existing finality update too old: signature slot {signature_slot}, current slot {slot:?}"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Causes the execution node at `node_index` to disconnect from the execution layer 1 epoch after
|
||||
// the merge transition.
|
||||
pub async fn disconnect_from_execution_layer<E: EthSpec>(
|
||||
|
||||
@@ -78,6 +78,9 @@ pub async fn create_local_network<E: EthSpec>(
|
||||
beacon_config.network.target_peers = node_count + proposer_nodes - 1;
|
||||
|
||||
beacon_config.network.enr_address = (Some(Ipv4Addr::LOCALHOST), None);
|
||||
beacon_config.network.enable_light_client_server = true;
|
||||
beacon_config.chain.enable_light_client_server = true;
|
||||
beacon_config.http_api.enable_light_client_server = true;
|
||||
|
||||
if post_merge_sim {
|
||||
let el_config = execution_layer::Config {
|
||||
|
||||
@@ -214,6 +214,7 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
fork,
|
||||
sync_aggregate,
|
||||
transition,
|
||||
light_client_update,
|
||||
) = futures::join!(
|
||||
// Check that the chain finalizes at the first given opportunity.
|
||||
checks::verify_first_finalization(network.clone(), slot_duration),
|
||||
@@ -266,6 +267,13 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
Epoch::new(TERMINAL_BLOCK / MinimalEthSpec::slots_per_epoch()),
|
||||
slot_duration,
|
||||
post_merge_sim
|
||||
),
|
||||
checks::verify_light_client_updates(
|
||||
network.clone(),
|
||||
// Sync aggregate available from slot 1 after Altair fork transition.
|
||||
Epoch::new(ALTAIR_FORK_EPOCH).start_slot(MinimalEthSpec::slots_per_epoch()) + 1,
|
||||
Epoch::new(END_EPOCH).start_slot(MinimalEthSpec::slots_per_epoch()),
|
||||
slot_duration
|
||||
)
|
||||
);
|
||||
|
||||
@@ -276,6 +284,7 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
fork?;
|
||||
sync_aggregate?;
|
||||
transition?;
|
||||
light_client_update?;
|
||||
|
||||
// The `final_future` either completes immediately or never completes, depending on the value
|
||||
// of `continue_after_checks`.
|
||||
|
||||
Reference in New Issue
Block a user