mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 12:47:05 +00:00
resolve merge conflicts
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use libp2p::swarm::ConnectionId;
|
||||
use types::{
|
||||
BlobSidecar, DataColumnSidecar, EthSpec, Hash256, LightClientBootstrap,
|
||||
LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock,
|
||||
};
|
||||
|
||||
use crate::rpc::{
|
||||
methods::{ResponseTermination, RpcResponse, RpcSuccessResponse, StatusMessage},
|
||||
SubstreamId,
|
||||
};
|
||||
use libp2p::swarm::ConnectionId;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::sync::Arc;
|
||||
use types::{
|
||||
BlobSidecar, DataColumnSidecar, Epoch, EthSpec, Hash256, LightClientBootstrap,
|
||||
LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock,
|
||||
};
|
||||
|
||||
/// Identifier of requests sent by a peer.
|
||||
pub type PeerRequestId = (ConnectionId, SubstreamId);
|
||||
@@ -31,8 +30,12 @@ pub enum SyncRequestId {
|
||||
SingleBlob { id: SingleLookupReqId },
|
||||
/// Request searching for a set of data columns given a hash and list of column indices.
|
||||
DataColumnsByRoot(DataColumnsByRootRequestId),
|
||||
/// Range request that is composed by both a block range request and a blob range request.
|
||||
RangeBlockAndBlobs { id: Id },
|
||||
/// Blocks by range request
|
||||
BlocksByRange(BlocksByRangeRequestId),
|
||||
/// Blobs by range request
|
||||
BlobsByRange(BlobsByRangeRequestId),
|
||||
/// Data columns by range request
|
||||
DataColumnsByRange(DataColumnsByRangeRequestId),
|
||||
}
|
||||
|
||||
/// Request ID for data_columns_by_root requests. Block lookups do not issue this request directly.
|
||||
@@ -43,12 +46,60 @@ pub struct DataColumnsByRootRequestId {
|
||||
pub requester: DataColumnsByRootRequester,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct BlocksByRangeRequestId {
|
||||
/// Id to identify this attempt at a blocks_by_range request for `parent_request_id`
|
||||
pub id: Id,
|
||||
/// The Id of the overall By Range request for block components.
|
||||
pub parent_request_id: ComponentsByRangeRequestId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct BlobsByRangeRequestId {
|
||||
/// Id to identify this attempt at a blobs_by_range request for `parent_request_id`
|
||||
pub id: Id,
|
||||
/// The Id of the overall By Range request for block components.
|
||||
pub parent_request_id: ComponentsByRangeRequestId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct DataColumnsByRangeRequestId {
|
||||
/// Id to identify this attempt at a data_columns_by_range request for `parent_request_id`
|
||||
pub id: Id,
|
||||
/// The Id of the overall By Range request for block components.
|
||||
pub parent_request_id: ComponentsByRangeRequestId,
|
||||
}
|
||||
|
||||
/// Block components by range request for range sync. Includes an ID for downstream consumers to
|
||||
/// handle retries and tie all their sub requests together.
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct ComponentsByRangeRequestId {
|
||||
/// Each `RangeRequestId` may request the same data in a later retry. This Id identifies the
|
||||
/// current attempt.
|
||||
pub id: Id,
|
||||
/// What sync component is issuing a components by range request and expecting data back
|
||||
pub requester: RangeRequestId,
|
||||
}
|
||||
|
||||
/// Range sync chain or backfill batch
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum RangeRequestId {
|
||||
RangeSync { chain_id: Id, batch_id: Epoch },
|
||||
BackfillSync { batch_id: Epoch },
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum DataColumnsByRootRequester {
|
||||
Sampling(SamplingId),
|
||||
Custody(CustodyId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum RangeRequester {
|
||||
RangeSync { chain_id: u64, batch_id: Epoch },
|
||||
BackfillSync { batch_id: Epoch },
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct SamplingId {
|
||||
pub id: SamplingRequester,
|
||||
@@ -183,9 +234,108 @@ impl slog::Value for RequestId {
|
||||
}
|
||||
}
|
||||
|
||||
// This custom impl reduces log boilerplate not printing `DataColumnsByRootRequestId` on each id log
|
||||
impl std::fmt::Display for DataColumnsByRootRequestId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} {:?}", self.id, self.requester)
|
||||
macro_rules! impl_display {
|
||||
($structname: ty, $format: literal, $($field:ident),*) => {
|
||||
impl Display for $structname {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, $format, $(self.$field,)*)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Since each request Id is deeply nested with various types, if rendered with Debug on logs they
|
||||
// take too much visual space. This custom Display implementations make the overall Id short while
|
||||
// not losing information
|
||||
impl_display!(BlocksByRangeRequestId, "{}/{}", id, parent_request_id);
|
||||
impl_display!(BlobsByRangeRequestId, "{}/{}", id, parent_request_id);
|
||||
impl_display!(DataColumnsByRangeRequestId, "{}/{}", id, parent_request_id);
|
||||
impl_display!(ComponentsByRangeRequestId, "{}/{}", id, requester);
|
||||
impl_display!(DataColumnsByRootRequestId, "{}/{}", id, requester);
|
||||
impl_display!(SingleLookupReqId, "{}/Lookup/{}", req_id, lookup_id);
|
||||
impl_display!(CustodyId, "{}", requester);
|
||||
impl_display!(SamplingId, "{}/{}", sampling_request_id, id);
|
||||
|
||||
impl Display for DataColumnsByRootRequester {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Custody(id) => write!(f, "Custody/{id}"),
|
||||
Self::Sampling(id) => write!(f, "Sampling/{id}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CustodyRequester {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RangeRequestId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::RangeSync { chain_id, batch_id } => write!(f, "RangeSync/{batch_id}/{chain_id}"),
|
||||
Self::BackfillSync { batch_id } => write!(f, "BackfillSync/{batch_id}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SamplingRequestId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SamplingRequester {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ImportedBlock(block) => write!(f, "ImportedBlock/{block}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn display_id_data_columns_by_root_custody() {
|
||||
let id = DataColumnsByRootRequestId {
|
||||
id: 123,
|
||||
requester: DataColumnsByRootRequester::Custody(CustodyId {
|
||||
requester: CustodyRequester(SingleLookupReqId {
|
||||
req_id: 121,
|
||||
lookup_id: 101,
|
||||
}),
|
||||
}),
|
||||
};
|
||||
assert_eq!(format!("{id}"), "123/Custody/121/Lookup/101");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_id_data_columns_by_root_sampling() {
|
||||
let id = DataColumnsByRootRequestId {
|
||||
id: 123,
|
||||
requester: DataColumnsByRootRequester::Sampling(SamplingId {
|
||||
id: SamplingRequester::ImportedBlock(Hash256::ZERO),
|
||||
sampling_request_id: SamplingRequestId(101),
|
||||
}),
|
||||
};
|
||||
assert_eq!(format!("{id}"), "123/Sampling/101/ImportedBlock/0x0000000000000000000000000000000000000000000000000000000000000000");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_id_data_columns_by_range() {
|
||||
let id = DataColumnsByRangeRequestId {
|
||||
id: 123,
|
||||
parent_request_id: ComponentsByRangeRequestId {
|
||||
id: 122,
|
||||
requester: RangeRequestId::RangeSync {
|
||||
chain_id: 54,
|
||||
batch_id: Epoch::new(0),
|
||||
},
|
||||
},
|
||||
};
|
||||
assert_eq!(format!("{id}"), "123/122/RangeSync/0/54");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,8 @@ use crate::rpc::{
|
||||
RequestType, ResponseTermination, RpcErrorResponse, RpcResponse, RpcSuccessResponse, RPC,
|
||||
};
|
||||
use crate::types::{
|
||||
attestation_sync_committee_topics, fork_core_topics, subnet_from_topic_hash, GossipEncoding,
|
||||
GossipKind, GossipTopic, SnappyTransform, Subnet, SubnetDiscovery, ALTAIR_CORE_TOPICS,
|
||||
BASE_CORE_TOPICS, CAPELLA_CORE_TOPICS, LIGHT_CLIENT_GOSSIP_TOPICS,
|
||||
all_topics_at_fork, core_topics_to_subscribe, is_fork_non_core_topic, subnet_from_topic_hash,
|
||||
GossipEncoding, GossipKind, GossipTopic, SnappyTransform, Subnet, SubnetDiscovery,
|
||||
};
|
||||
use crate::EnrExt;
|
||||
use crate::Eth2Enr;
|
||||
@@ -280,14 +279,39 @@ impl<E: EthSpec> Network<E> {
|
||||
// Set up a scoring update interval
|
||||
let update_gossipsub_scores = tokio::time::interval(params.decay_interval);
|
||||
|
||||
let max_topics = ctx.chain_spec.attestation_subnet_count as usize
|
||||
+ SYNC_COMMITTEE_SUBNET_COUNT as usize
|
||||
+ ctx.chain_spec.blob_sidecar_subnet_count_max() as usize
|
||||
+ ctx.chain_spec.data_column_sidecar_subnet_count as usize
|
||||
+ BASE_CORE_TOPICS.len()
|
||||
+ ALTAIR_CORE_TOPICS.len()
|
||||
+ CAPELLA_CORE_TOPICS.len() // 0 core deneb and electra topics
|
||||
+ LIGHT_CLIENT_GOSSIP_TOPICS.len();
|
||||
let current_and_future_forks = ForkName::list_all().into_iter().filter_map(|fork| {
|
||||
if fork >= ctx.fork_context.current_fork() {
|
||||
ctx.fork_context
|
||||
.to_context_bytes(fork)
|
||||
.map(|fork_digest| (fork, fork_digest))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let all_topics_for_forks = current_and_future_forks
|
||||
.map(|(fork, fork_digest)| {
|
||||
all_topics_at_fork::<E>(fork, &ctx.chain_spec)
|
||||
.into_iter()
|
||||
.map(|topic| {
|
||||
Topic::new(GossipTopic::new(
|
||||
topic,
|
||||
GossipEncoding::default(),
|
||||
fork_digest,
|
||||
))
|
||||
.into()
|
||||
})
|
||||
.collect::<Vec<TopicHash>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// For simplicity find the fork with the most individual topics and assume all forks
|
||||
// have the same topic count
|
||||
let max_topics_at_any_fork = all_topics_for_forks
|
||||
.iter()
|
||||
.map(|topics| topics.len())
|
||||
.max()
|
||||
.expect("each fork has at least 5 hardcoded core topics");
|
||||
|
||||
let possible_fork_digests = ctx.fork_context.all_fork_digests();
|
||||
let filter = gossipsub::MaxCountSubscriptionFilter {
|
||||
@@ -297,9 +321,9 @@ impl<E: EthSpec> Network<E> {
|
||||
SYNC_COMMITTEE_SUBNET_COUNT,
|
||||
),
|
||||
// during a fork we subscribe to both the old and new topics
|
||||
max_subscribed_topics: max_topics * 4,
|
||||
max_subscribed_topics: max_topics_at_any_fork * 4,
|
||||
// 424 in theory = (64 attestation + 4 sync committee + 7 core topics + 9 blob topics + 128 column topics) * 2
|
||||
max_subscriptions_per_request: max_topics * 2,
|
||||
max_subscriptions_per_request: max_topics_at_any_fork * 2,
|
||||
};
|
||||
|
||||
// If metrics are enabled for libp2p build the configuration
|
||||
@@ -332,17 +356,9 @@ impl<E: EthSpec> Network<E> {
|
||||
// If we are using metrics, then register which topics we want to make sure to keep
|
||||
// track of
|
||||
if ctx.libp2p_registry.is_some() {
|
||||
let topics_to_keep_metrics_for = attestation_sync_committee_topics::<E>()
|
||||
.map(|gossip_kind| {
|
||||
Topic::from(GossipTopic::new(
|
||||
gossip_kind,
|
||||
GossipEncoding::default(),
|
||||
enr_fork_id.fork_digest,
|
||||
))
|
||||
.into()
|
||||
})
|
||||
.collect::<Vec<TopicHash>>();
|
||||
gossipsub.register_topics_for_metrics(topics_to_keep_metrics_for);
|
||||
for topics in all_topics_for_forks {
|
||||
gossipsub.register_topics_for_metrics(topics);
|
||||
}
|
||||
}
|
||||
|
||||
(gossipsub, update_gossipsub_scores)
|
||||
@@ -700,32 +716,26 @@ impl<E: EthSpec> Network<E> {
|
||||
|
||||
/// Subscribe to all required topics for the `new_fork` with the given `new_fork_digest`.
|
||||
pub fn subscribe_new_fork_topics(&mut self, new_fork: ForkName, new_fork_digest: [u8; 4]) {
|
||||
// Subscribe to existing topics with new fork digest
|
||||
// Re-subscribe to non-core topics with the new fork digest
|
||||
let subscriptions = self.network_globals.gossipsub_subscriptions.read().clone();
|
||||
for mut topic in subscriptions.into_iter() {
|
||||
topic.fork_digest = new_fork_digest;
|
||||
self.subscribe(topic);
|
||||
if is_fork_non_core_topic(&topic, new_fork) {
|
||||
topic.fork_digest = new_fork_digest;
|
||||
self.subscribe(topic);
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to core topics for the new fork
|
||||
for kind in fork_core_topics::<E>(&new_fork, &self.fork_context.spec) {
|
||||
for kind in core_topics_to_subscribe::<E>(
|
||||
new_fork,
|
||||
&self.network_globals.as_topic_config(),
|
||||
&self.fork_context.spec,
|
||||
) {
|
||||
let topic = GossipTopic::new(kind, GossipEncoding::default(), new_fork_digest);
|
||||
self.subscribe(topic);
|
||||
}
|
||||
|
||||
// Register the new topics for metrics
|
||||
let topics_to_keep_metrics_for = attestation_sync_committee_topics::<E>()
|
||||
.map(|gossip_kind| {
|
||||
Topic::from(GossipTopic::new(
|
||||
gossip_kind,
|
||||
GossipEncoding::default(),
|
||||
new_fork_digest,
|
||||
))
|
||||
.into()
|
||||
})
|
||||
.collect::<Vec<TopicHash>>();
|
||||
self.gossipsub_mut()
|
||||
.register_topics_for_metrics(topics_to_keep_metrics_for);
|
||||
// Already registered all possible gossipsub topics for metrics
|
||||
}
|
||||
|
||||
/// Unsubscribe from all topics that doesn't have the given fork_digest
|
||||
|
||||
Reference in New Issue
Block a user