Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra-focil

This commit is contained in:
Eitan Seri-Levi
2025-03-09 10:28:45 -06:00
142 changed files with 1058 additions and 8225 deletions

View File

@@ -114,7 +114,7 @@ const API_PREFIX: &str = "eth";
///
/// This helps prevent attacks where nodes can convince us that we're syncing some non-existent
/// finalized head.
const SYNC_TOLERANCE_EPOCHS: u64 = 8;
const DEFAULT_SYNC_TOLERANCE_EPOCHS: u64 = 8;
/// A custom type which allows for both unsecured and TLS-enabled HTTP servers.
type HttpServer = (SocketAddr, Pin<Box<dyn Future<Output = ()> + Send>>);
@@ -157,8 +157,8 @@ pub struct Config {
pub enable_beacon_processor: bool,
#[serde(with = "eth2::types::serde_status_code")]
pub duplicate_block_status_code: StatusCode,
pub enable_light_client_server: bool,
pub target_peers: usize,
pub sync_tolerance_epochs: Option<u64>,
}
impl Default for Config {
@@ -173,8 +173,8 @@ impl Default for Config {
sse_capacity_multiplier: 1,
enable_beacon_processor: true,
duplicate_block_status_code: StatusCode::ACCEPTED,
enable_light_client_server: true,
target_peers: 100,
sync_tolerance_epochs: None,
}
}
}
@@ -300,18 +300,6 @@ pub fn prometheus_metrics() -> warp::filters::log::Log<impl Fn(warp::filters::lo
})
}
fn enable(is_enabled: bool) -> impl Filter<Extract = (), Error = warp::Rejection> + Clone {
warp::any()
.and_then(move || async move {
if is_enabled {
Ok(())
} else {
Err(warp::reject::not_found())
}
})
.untuple_one()
}
/// Creates a server that will serve requests using information from `ctx`.
///
/// The server will shut down gracefully when the `shutdown` future resolves.
@@ -477,7 +465,10 @@ pub fn serve<T: BeaconChainTypes>(
)
})?;
let tolerance = SYNC_TOLERANCE_EPOCHS * T::EthSpec::slots_per_epoch();
let sync_tolerance_epochs = config
.sync_tolerance_epochs
.unwrap_or(DEFAULT_SYNC_TOLERANCE_EPOCHS);
let tolerance = sync_tolerance_epochs * T::EthSpec::slots_per_epoch();
if head_slot + tolerance >= current_slot {
Ok(())
@@ -497,6 +488,18 @@ pub fn serve<T: BeaconChainTypes>(
},
);
// Create a `warp` filter that returns 404s if the light client server is disabled.
let light_client_server_filter =
warp::any()
.and(chain_filter.clone())
.then(|chain: Arc<BeaconChain<T>>| async move {
if chain.config.enable_light_client_server {
Ok(())
} else {
Err(warp::reject::not_found())
}
});
// Create a `warp` filter that provides access to the logger.
let inner_ctx = ctx.clone();
let log_filter = warp::any().map(move || inner_ctx.log.clone());
@@ -1943,10 +1946,10 @@ pub fn serve<T: BeaconChainTypes>(
query: api_types::AttestationPoolQuery| {
task_spawner.blocking_response_task(Priority::P1, move || {
let query_filter = |data: &AttestationData| {
query.slot.map_or(true, |slot| slot == data.slot)
query.slot.is_none_or(|slot| slot == data.slot)
&& query
.committee_index
.map_or(true, |index| index == data.index)
.is_none_or(|index| index == data.index)
};
let mut attestations = chain.op_pool.get_filtered_attestations(query_filter);
@@ -2487,6 +2490,7 @@ pub fn serve<T: BeaconChainTypes>(
let beacon_light_client_path = eth_v1
.and(warp::path("beacon"))
.and(warp::path("light_client"))
.and(light_client_server_filter)
.and(chain_filter.clone());
// GET beacon/light_client/bootstrap/{block_root}
@@ -2502,11 +2506,13 @@ pub fn serve<T: BeaconChainTypes>(
.and(warp::path::end())
.and(warp::header::optional::<api_types::Accept>("accept"))
.then(
|chain: Arc<BeaconChain<T>>,
|light_client_server_enabled: Result<(), Rejection>,
chain: Arc<BeaconChain<T>>,
task_spawner: TaskSpawner<T::EthSpec>,
block_root: Hash256,
accept_header: Option<api_types::Accept>| {
task_spawner.blocking_response_task(Priority::P1, move || {
light_client_server_enabled?;
get_light_client_bootstrap::<T>(chain, &block_root, accept_header)
})
},
@@ -2520,10 +2526,12 @@ pub fn serve<T: BeaconChainTypes>(
.and(warp::path::end())
.and(warp::header::optional::<api_types::Accept>("accept"))
.then(
|chain: Arc<BeaconChain<T>>,
|light_client_server_enabled: Result<(), Rejection>,
chain: Arc<BeaconChain<T>>,
task_spawner: TaskSpawner<T::EthSpec>,
accept_header: Option<api_types::Accept>| {
task_spawner.blocking_response_task(Priority::P1, move || {
light_client_server_enabled?;
let update = chain
.light_client_server_cache
.get_latest_optimistic_update()
@@ -2567,10 +2575,12 @@ pub fn serve<T: BeaconChainTypes>(
.and(warp::path::end())
.and(warp::header::optional::<api_types::Accept>("accept"))
.then(
|chain: Arc<BeaconChain<T>>,
|light_client_server_enabled: Result<(), Rejection>,
chain: Arc<BeaconChain<T>>,
task_spawner: TaskSpawner<T::EthSpec>,
accept_header: Option<api_types::Accept>| {
task_spawner.blocking_response_task(Priority::P1, move || {
light_client_server_enabled?;
let update = chain
.light_client_server_cache
.get_latest_finality_update()
@@ -2615,11 +2625,13 @@ pub fn serve<T: BeaconChainTypes>(
.and(warp::query::<api_types::LightClientUpdatesQuery>())
.and(warp::header::optional::<api_types::Accept>("accept"))
.then(
|chain: Arc<BeaconChain<T>>,
|light_client_server_enabled: Result<(), Rejection>,
chain: Arc<BeaconChain<T>>,
task_spawner: TaskSpawner<T::EthSpec>,
query: LightClientUpdatesQuery,
accept_header: Option<api_types::Accept>| {
task_spawner.blocking_response_task(Priority::P1, move || {
light_client_server_enabled?;
get_light_client_updates::<T>(chain, query, accept_header)
})
},
@@ -3194,11 +3206,11 @@ pub fn serve<T: BeaconChainTypes>(
peer_info.connection_status(),
);
let state_matches = query.state.as_ref().map_or(true, |states| {
let state_matches = query.state.as_ref().is_none_or(|states| {
states.iter().any(|state_param| *state_param == state)
});
let direction_matches =
query.direction.as_ref().map_or(true, |directions| {
query.direction.as_ref().is_none_or(|directions| {
directions.iter().any(|dir_param| *dir_param == direction)
});
@@ -4837,22 +4849,10 @@ pub fn serve<T: BeaconChainTypes>(
.uor(get_lighthouse_database_info)
.uor(get_lighthouse_block_rewards)
.uor(get_lighthouse_attestation_performance)
.uor(
enable(ctx.config.enable_light_client_server)
.and(get_beacon_light_client_optimistic_update),
)
.uor(
enable(ctx.config.enable_light_client_server)
.and(get_beacon_light_client_finality_update),
)
.uor(
enable(ctx.config.enable_light_client_server)
.and(get_beacon_light_client_bootstrap),
)
.uor(
enable(ctx.config.enable_light_client_server)
.and(get_beacon_light_client_updates),
)
.uor(get_beacon_light_client_optimistic_update)
.uor(get_beacon_light_client_finality_update)
.uor(get_beacon_light_client_bootstrap)
.uor(get_beacon_light_client_updates)
.uor(get_lighthouse_block_packing_efficiency)
.uor(get_lighthouse_merge_readiness)
.uor(get_events)

View File

@@ -147,7 +147,7 @@ pub async fn produce_blinded_block_v2<T: BeaconChainTypes>(
.produce_block_with_verification(
randao_reveal,
slot,
query.graffiti.map(Into::into),
query.graffiti,
randao_verification,
None,
BlockProductionVersion::BlindedV2,
@@ -178,7 +178,7 @@ pub async fn produce_block_v2<T: BeaconChainTypes>(
.produce_block_with_verification(
randao_reveal,
slot,
query.graffiti.map(Into::into),
query.graffiti,
randao_verification,
None,
BlockProductionVersion::FullV2,

View File

@@ -86,6 +86,8 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlock<T>>(
network_globals: Arc<NetworkGlobals<T::EthSpec>>,
) -> Result<Response, Rejection> {
let seen_timestamp = timestamp_now();
let block_publishing_delay_for_testing = chain.config.block_publishing_delay;
let data_column_publishing_delay_for_testing = chain.config.data_column_publishing_delay;
let (unverified_block, unverified_blobs, is_locally_built_block) = match provenanced_block {
ProvenancedBlock::Local(block, blobs, _) => (block, blobs, true),
@@ -147,6 +149,14 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlock<T>>(
let should_publish_block = gossip_verified_block_result.is_ok();
if BroadcastValidation::Gossip == validation_level && should_publish_block {
if let Some(block_publishing_delay) = block_publishing_delay_for_testing {
debug!(
log,
"Publishing block with artificial delay";
"block_publishing_delay" => ?block_publishing_delay
);
tokio::time::sleep(block_publishing_delay).await;
}
publish_block_p2p(
block.clone(),
sender_clone.clone(),
@@ -207,6 +217,23 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlock<T>>(
}
if gossip_verified_columns.iter().map(Option::is_some).count() > 0 {
if let Some(data_column_publishing_delay) = data_column_publishing_delay_for_testing {
// Subtract block publishing delay if it is also used.
// Note: if `data_column_publishing_delay` is less than `block_publishing_delay`, it
// will still be delayed by `block_publishing_delay`. This could be solved with spawning
// async tasks but the limitation is minor and I believe it's probably not worth
// affecting the mainnet code path.
let block_publishing_delay = block_publishing_delay_for_testing.unwrap_or_default();
let delay = data_column_publishing_delay.saturating_sub(block_publishing_delay);
if !delay.is_zero() {
debug!(
log,
"Publishing data columns with artificial delay";
"data_column_publishing_delay" => ?data_column_publishing_delay
);
tokio::time::sleep(delay).await;
}
}
publish_column_sidecars(network_tx, &gossip_verified_columns, &chain).map_err(|_| {
warp_utils::reject::custom_server_error("unable to publish data column sidecars".into())
})?;

View File

@@ -249,7 +249,6 @@ pub async fn create_api_server_with_config<T: BeaconChainTypes>(
enabled: true,
listen_port: port,
data_dir: std::path::PathBuf::from(DEFAULT_ROOT_DIR),
enable_light_client_server: true,
..http_config
},
chain: Some(chain),

View File

@@ -29,7 +29,7 @@ pub fn get_beacon_state_validators<T: BeaconChainTypes>(
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, (validator, _))| {
ids_filter_set.as_ref().map_or(true, |ids_set| {
ids_filter_set.as_ref().is_none_or(|ids_set| {
ids_set.contains(&ValidatorId::PublicKey(validator.pubkey))
|| ids_set.contains(&ValidatorId::Index(*index as u64))
})
@@ -42,7 +42,7 @@ pub fn get_beacon_state_validators<T: BeaconChainTypes>(
far_future_epoch,
);
let status_matches = query_statuses.as_ref().map_or(true, |statuses| {
let status_matches = query_statuses.as_ref().is_none_or(|statuses| {
statuses.contains(&status)
|| statuses.contains(&status.superstatus())
});
@@ -92,7 +92,7 @@ pub fn get_beacon_state_validator_balances<T: BeaconChainTypes>(
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, (validator, _))| {
ids_filter_set.as_ref().map_or(true, |ids_set| {
ids_filter_set.as_ref().is_none_or(|ids_set| {
ids_set.contains(&ValidatorId::PublicKey(validator.pubkey))
|| ids_set.contains(&ValidatorId::Index(*index as u64))
})