mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
merge with upstream
This commit is contained in:
@@ -130,6 +130,9 @@ pub struct Config {
|
||||
|
||||
/// Whether metrics are enabled.
|
||||
pub metrics_enabled: bool,
|
||||
|
||||
/// Whether light client protocols should be enabled.
|
||||
pub enable_light_client_server: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -207,6 +210,7 @@ impl Default for Config {
|
||||
shutdown_after_sync: false,
|
||||
topics: Vec::new(),
|
||||
metrics_enabled: false,
|
||||
enable_light_client_server: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,9 +288,11 @@ impl From<u8> for NetworkLoad {
|
||||
/// Return a Lighthouse specific `GossipsubConfig` where the `message_id_fn` depends on the current fork.
|
||||
pub fn gossipsub_config(network_load: u8, fork_context: Arc<ForkContext>) -> GossipsubConfig {
|
||||
// The function used to generate a gossipsub message id
|
||||
// We use the first 8 bytes of SHA256(data) for content addressing
|
||||
let fast_gossip_message_id =
|
||||
|message: &RawGossipsubMessage| FastMessageId::from(&Sha256::digest(&message.data)[..8]);
|
||||
// We use the first 8 bytes of SHA256(topic, data) for content addressing
|
||||
let fast_gossip_message_id = |message: &RawGossipsubMessage| {
|
||||
let data = [message.topic.as_str().as_bytes(), &message.data].concat();
|
||||
FastMessageId::from(&Sha256::digest(data)[..8])
|
||||
};
|
||||
fn prefix(
|
||||
prefix: [u8; 4],
|
||||
message: &GossipsubMessage,
|
||||
|
||||
@@ -834,6 +834,17 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
||||
|
||||
// Map each subnet query's min_ttl to the set of ENR's returned for that subnet.
|
||||
queries.iter().for_each(|query| {
|
||||
let query_str = match query.subnet {
|
||||
Subnet::Attestation(_) => "attestation",
|
||||
Subnet::SyncCommittee(_) => "sync_committee",
|
||||
};
|
||||
|
||||
if let Some(v) = metrics::get_int_counter(
|
||||
&metrics::TOTAL_SUBNET_QUERIES,
|
||||
&[query_str],
|
||||
) {
|
||||
v.inc();
|
||||
}
|
||||
// A subnet query has completed. Add back to the queue, incrementing retries.
|
||||
self.add_subnet_query(query.subnet, query.min_ttl, query.retries + 1);
|
||||
|
||||
@@ -845,6 +856,12 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
||||
.filter(|enr| subnet_predicate(enr))
|
||||
.map(|enr| enr.peer_id())
|
||||
.for_each(|peer_id| {
|
||||
if let Some(v) = metrics::get_int_counter(
|
||||
&metrics::SUBNET_PEERS_FOUND,
|
||||
&[query_str],
|
||||
) {
|
||||
v.inc();
|
||||
}
|
||||
let other_min_ttl = mapped_results.get_mut(&peer_id);
|
||||
|
||||
// map peer IDs to the min_ttl furthest in the future
|
||||
|
||||
@@ -112,6 +112,19 @@ lazy_static! {
|
||||
&["client"]
|
||||
);
|
||||
|
||||
pub static ref SUBNET_PEERS_FOUND: Result<IntCounterVec> =
|
||||
try_create_int_counter_vec(
|
||||
"discovery_query_peers_found",
|
||||
"Total number of peers found in attestation subnets and sync subnets",
|
||||
&["type"]
|
||||
);
|
||||
pub static ref TOTAL_SUBNET_QUERIES: Result<IntCounterVec> =
|
||||
try_create_int_counter_vec(
|
||||
"discovery_total_queries",
|
||||
"Total number of discovery subnet queries",
|
||||
&["type"]
|
||||
);
|
||||
|
||||
/*
|
||||
* Inbound/Outbound peers
|
||||
*/
|
||||
|
||||
@@ -405,7 +405,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
||||
debug!(self.log, "Identified Peer"; "peer" => %peer_id,
|
||||
"protocol_version" => &info.protocol_version,
|
||||
"agent_version" => &info.agent_version,
|
||||
"listening_ addresses" => ?info.listen_addrs,
|
||||
"listening_addresses" => ?info.listen_addrs,
|
||||
"observed_address" => ?info.observed_addr,
|
||||
"protocols" => ?info.protocols
|
||||
);
|
||||
@@ -502,6 +502,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
||||
Protocol::BlocksByRange => PeerAction::MidToleranceError,
|
||||
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
|
||||
Protocol::BlobsByRange => PeerAction::MidToleranceError,
|
||||
Protocol::LightClientBootstrap => PeerAction::LowToleranceError,
|
||||
Protocol::BlobsByRoot => PeerAction::MidToleranceError,
|
||||
Protocol::Goodbye => PeerAction::LowToleranceError,
|
||||
Protocol::MetaData => PeerAction::LowToleranceError,
|
||||
@@ -521,6 +522,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
||||
Protocol::BlobsByRange => return,
|
||||
Protocol::BlobsByRoot => return,
|
||||
Protocol::Goodbye => return,
|
||||
Protocol::LightClientBootstrap => return,
|
||||
Protocol::MetaData => PeerAction::LowToleranceError,
|
||||
Protocol::Status => PeerAction::LowToleranceError,
|
||||
}
|
||||
@@ -537,6 +539,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
||||
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
|
||||
Protocol::BlobsByRange => PeerAction::MidToleranceError,
|
||||
Protocol::BlobsByRoot => PeerAction::MidToleranceError,
|
||||
Protocol::LightClientBootstrap => return,
|
||||
Protocol::Goodbye => return,
|
||||
Protocol::MetaData => return,
|
||||
Protocol::Status => return,
|
||||
|
||||
@@ -139,7 +139,7 @@ impl<TSpec: EthSpec> NetworkBehaviour for PeerManager<TSpec> {
|
||||
// TODO: directly emit the ban event?
|
||||
BanResult::BadScore => {
|
||||
// This is a faulty state
|
||||
error!(self.log, "Connected to a banned peer, re-banning"; "peer_id" => %peer_id);
|
||||
error!(self.log, "Connected to a banned peer. Re-banning"; "peer_id" => %peer_id);
|
||||
// Reban the peer
|
||||
self.goodbye_peer(peer_id, GoodbyeReason::Banned, ReportSource::PeerManager);
|
||||
return;
|
||||
|
||||
@@ -15,10 +15,11 @@ use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
use types::light_client_bootstrap::LightClientBootstrap;
|
||||
use types::{
|
||||
BlobsSidecar, EthSpec, ForkContext, ForkName, SignedBeaconBlock, SignedBeaconBlockAltair,
|
||||
SignedBeaconBlockAndBlobsSidecar, SignedBeaconBlockBase, SignedBeaconBlockCapella,
|
||||
SignedBeaconBlockEip4844, SignedBeaconBlockMerge,
|
||||
BlobsSidecar, EthSpec, ForkContext, ForkName, Hash256, SignedBeaconBlock,
|
||||
SignedBeaconBlockAltair, SignedBeaconBlockAndBlobsSidecar, SignedBeaconBlockBase,
|
||||
SignedBeaconBlockCapella, SignedBeaconBlockEip4844, SignedBeaconBlockMerge,
|
||||
};
|
||||
use unsigned_varint::codec::Uvi;
|
||||
|
||||
@@ -73,6 +74,7 @@ impl<TSpec: EthSpec> Encoder<RPCCodedResponse<TSpec>> for SSZSnappyInboundCodec<
|
||||
RPCResponse::BlocksByRoot(res) => res.as_ssz_bytes(),
|
||||
RPCResponse::BlobsByRange(res) => res.as_ssz_bytes(),
|
||||
RPCResponse::BlobsByRoot(res) => res.as_ssz_bytes(),
|
||||
RPCResponse::LightClientBootstrap(res) => res.as_ssz_bytes(),
|
||||
RPCResponse::Pong(res) => res.data.as_ssz_bytes(),
|
||||
RPCResponse::MetaData(res) =>
|
||||
// Encode the correct version of the MetaData response based on the negotiated version.
|
||||
@@ -235,6 +237,7 @@ impl<TSpec: EthSpec> Encoder<OutboundRequest<TSpec>> for SSZSnappyOutboundCodec<
|
||||
OutboundRequest::BlobsByRoot(req) => req.block_roots.as_ssz_bytes(),
|
||||
OutboundRequest::Ping(req) => req.as_ssz_bytes(),
|
||||
OutboundRequest::MetaData(_) => return Ok(()), // no metadata to encode
|
||||
OutboundRequest::LightClientBootstrap(req) => req.as_ssz_bytes(),
|
||||
};
|
||||
// SSZ encoded bytes should be within `max_packet_size`
|
||||
if bytes.len() > self.max_packet_size {
|
||||
@@ -495,7 +498,11 @@ fn handle_v1_request<T: EthSpec>(
|
||||
Protocol::Ping => Ok(Some(InboundRequest::Ping(Ping {
|
||||
data: u64::from_ssz_bytes(decoded_buffer)?,
|
||||
}))),
|
||||
|
||||
Protocol::LightClientBootstrap => Ok(Some(InboundRequest::LightClientBootstrap(
|
||||
LightClientBootstrapRequest {
|
||||
root: Hash256::from_ssz_bytes(decoded_buffer)?,
|
||||
},
|
||||
))),
|
||||
// MetaData requests return early from InboundUpgrade and do not reach the decoder.
|
||||
// Handle this case just for completeness.
|
||||
Protocol::MetaData => {
|
||||
@@ -605,6 +612,9 @@ fn handle_v1_response<T: EthSpec>(
|
||||
Protocol::MetaData => Ok(Some(RPCResponse::MetaData(MetaData::V1(
|
||||
MetaDataV1::from_ssz_bytes(decoded_buffer)?,
|
||||
)))),
|
||||
Protocol::LightClientBootstrap => Ok(Some(RPCResponse::LightClientBootstrap(
|
||||
LightClientBootstrap::from_ssz_bytes(decoded_buffer)?,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -966,6 +976,9 @@ mod tests {
|
||||
OutboundRequest::MetaData(metadata) => {
|
||||
assert_eq!(decoded, InboundRequest::MetaData(metadata))
|
||||
}
|
||||
OutboundRequest::LightClientBootstrap(bootstrap) => {
|
||||
assert_eq!(decoded, InboundRequest::LightClientBootstrap(bootstrap))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ where
|
||||
} else {
|
||||
if !matches!(response, RPCCodedResponse::StreamTermination(..)) {
|
||||
// the stream is closed after sending the expected number of responses
|
||||
trace!(self.log, "Inbound stream has expired, response not sent";
|
||||
trace!(self.log, "Inbound stream has expired. Response not sent";
|
||||
"response" => %response, "id" => inbound_id);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -12,9 +12,11 @@ use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use strum::IntoStaticStr;
|
||||
use superstruct::superstruct;
|
||||
use types::blobs_sidecar::BlobsSidecar;
|
||||
use types::SignedBeaconBlockAndBlobsSidecar;
|
||||
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};
|
||||
use types::{
|
||||
blobs_sidecar::BlobsSidecar, light_client_bootstrap::LightClientBootstrap, Epoch, EthSpec,
|
||||
Hash256, SignedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
/// Maximum number of blocks in a single request.
|
||||
pub type MaxRequestBlocks = U1024;
|
||||
@@ -268,6 +270,9 @@ pub enum RPCResponse<T: EthSpec> {
|
||||
/// A response to a get BLOBS_BY_RANGE request
|
||||
BlobsByRange(Arc<BlobsSidecar<T>>),
|
||||
|
||||
/// A response to a get LIGHTCLIENT_BOOTSTRAP request.
|
||||
LightClientBootstrap(LightClientBootstrap<T>),
|
||||
|
||||
/// A response to a get BLOBS_BY_ROOT request.
|
||||
BlobsByRoot(Arc<SignedBeaconBlockAndBlobsSidecar<T>>),
|
||||
|
||||
@@ -307,6 +312,12 @@ pub enum RPCCodedResponse<T: EthSpec> {
|
||||
StreamTermination(ResponseTermination),
|
||||
}
|
||||
|
||||
/// Request a light_client_bootstrap for lightclients peers.
|
||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
||||
pub struct LightClientBootstrapRequest {
|
||||
pub root: Hash256,
|
||||
}
|
||||
|
||||
/// The code assigned to an erroneous `RPCResponse`.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
@@ -357,6 +368,7 @@ impl<T: EthSpec> RPCCodedResponse<T> {
|
||||
RPCResponse::BlobsByRoot(_) => true,
|
||||
RPCResponse::Pong(_) => false,
|
||||
RPCResponse::MetaData(_) => false,
|
||||
RPCResponse::LightClientBootstrap(_) => false,
|
||||
},
|
||||
RPCCodedResponse::Error(_, _) => true,
|
||||
// Stream terminations are part of responses that have chunks
|
||||
@@ -393,6 +405,7 @@ impl<T: EthSpec> RPCResponse<T> {
|
||||
RPCResponse::BlobsByRoot(_) => Protocol::BlobsByRoot,
|
||||
RPCResponse::Pong(_) => Protocol::Ping,
|
||||
RPCResponse::MetaData(_) => Protocol::MetaData,
|
||||
RPCResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,6 +451,9 @@ impl<T: EthSpec> std::fmt::Display for RPCResponse<T> {
|
||||
}
|
||||
RPCResponse::Pong(ping) => write!(f, "Pong: {}", ping.data),
|
||||
RPCResponse::MetaData(metadata) => write!(f, "Metadata: {}", metadata.seq_number()),
|
||||
RPCResponse::LightClientBootstrap(bootstrap) => {
|
||||
write!(f, "LightClientBootstrap Slot: {}", bootstrap.header.slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ pub(crate) use protocol::{InboundRequest, RPCProtocol};
|
||||
use crate::rpc::methods::MAX_REQUEST_BLOBS_SIDECARS;
|
||||
pub use handler::SubstreamId;
|
||||
pub use methods::{
|
||||
BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, MaxRequestBlocks,
|
||||
RPCResponseErrorCode, ResponseTermination, StatusMessage, MAX_REQUEST_BLOCKS,
|
||||
BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, LightClientBootstrapRequest,
|
||||
MaxRequestBlocks, RPCResponseErrorCode, ResponseTermination, StatusMessage, MAX_REQUEST_BLOCKS,
|
||||
};
|
||||
pub(crate) use outbound::OutboundRequest;
|
||||
pub use protocol::{max_rpc_size, Protocol, RPCError};
|
||||
@@ -109,18 +109,24 @@ pub struct RPC<Id: ReqId, TSpec: EthSpec> {
|
||||
/// Queue of events to be processed.
|
||||
events: Vec<NetworkBehaviourAction<RPCMessage<Id, TSpec>, RPCHandler<Id, TSpec>>>,
|
||||
fork_context: Arc<ForkContext>,
|
||||
enable_light_client_server: bool,
|
||||
/// Slog logger for RPC behaviour.
|
||||
log: slog::Logger,
|
||||
}
|
||||
|
||||
impl<Id: ReqId, TSpec: EthSpec> RPC<Id, TSpec> {
|
||||
pub fn new(fork_context: Arc<ForkContext>, log: slog::Logger) -> Self {
|
||||
pub fn new(
|
||||
fork_context: Arc<ForkContext>,
|
||||
enable_light_client_server: bool,
|
||||
log: slog::Logger,
|
||||
) -> Self {
|
||||
let log = log.new(o!("service" => "libp2p_rpc"));
|
||||
let limiter = RPCRateLimiterBuilder::new()
|
||||
.n_every(Protocol::MetaData, 2, Duration::from_secs(5))
|
||||
.n_every(Protocol::Ping, 2, Duration::from_secs(10))
|
||||
.n_every(Protocol::Status, 5, Duration::from_secs(15))
|
||||
.one_every(Protocol::Goodbye, Duration::from_secs(10))
|
||||
.one_every(Protocol::LightClientBootstrap, Duration::from_secs(10))
|
||||
.n_every(
|
||||
Protocol::BlocksByRange,
|
||||
methods::MAX_REQUEST_BLOCKS,
|
||||
@@ -139,6 +145,7 @@ impl<Id: ReqId, TSpec: EthSpec> RPC<Id, TSpec> {
|
||||
limiter,
|
||||
events: Vec::new(),
|
||||
fork_context,
|
||||
enable_light_client_server,
|
||||
log,
|
||||
}
|
||||
}
|
||||
@@ -195,6 +202,7 @@ where
|
||||
RPCProtocol {
|
||||
fork_context: self.fork_context.clone(),
|
||||
max_rpc_size: max_rpc_size(&self.fork_context),
|
||||
enable_light_client_server: self.enable_light_client_server,
|
||||
phantom: PhantomData,
|
||||
},
|
||||
(),
|
||||
|
||||
@@ -40,6 +40,7 @@ pub enum OutboundRequest<TSpec: EthSpec> {
|
||||
BlocksByRoot(BlocksByRootRequest),
|
||||
BlobsByRange(BlobsByRangeRequest),
|
||||
BlobsByRoot(BlobsByRootRequest),
|
||||
LightClientBootstrap(LightClientBootstrapRequest),
|
||||
Ping(Ping),
|
||||
MetaData(PhantomData<TSpec>),
|
||||
}
|
||||
@@ -96,9 +97,12 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
ProtocolId::new(Protocol::MetaData, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V1, Encoding::SSZSnappy),
|
||||
],
|
||||
// Note: This match arm is technically unreachable as we only respond to light client requests
|
||||
// that we generate from the beacon state.
|
||||
// We do not make light client rpc requests from the beacon node
|
||||
OutboundRequest::LightClientBootstrap(_) => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/* These functions are used in the handler for stream management */
|
||||
|
||||
/// Number of responses expected for this request.
|
||||
@@ -112,6 +116,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
OutboundRequest::BlobsByRoot(req) => req.block_roots.len() as u64,
|
||||
OutboundRequest::Ping(_) => 1,
|
||||
OutboundRequest::MetaData(_) => 1,
|
||||
OutboundRequest::LightClientBootstrap(_) => 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +131,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
OutboundRequest::BlobsByRoot(_) => Protocol::BlobsByRoot,
|
||||
OutboundRequest::Ping(_) => Protocol::Ping,
|
||||
OutboundRequest::MetaData(_) => Protocol::MetaData,
|
||||
OutboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +145,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
OutboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot,
|
||||
OutboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange,
|
||||
OutboundRequest::BlobsByRoot(_) => ResponseTermination::BlobsByRoot,
|
||||
OutboundRequest::LightClientBootstrap(_) => unreachable!(),
|
||||
OutboundRequest::Status(_) => unreachable!(),
|
||||
OutboundRequest::Goodbye(_) => unreachable!(),
|
||||
OutboundRequest::Ping(_) => unreachable!(),
|
||||
@@ -198,6 +205,9 @@ impl<TSpec: EthSpec> std::fmt::Display for OutboundRequest<TSpec> {
|
||||
OutboundRequest::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req),
|
||||
OutboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data),
|
||||
OutboundRequest::MetaData(_) => write!(f, "MetaData request"),
|
||||
OutboundRequest::LightClientBootstrap(bootstrap) => {
|
||||
write!(f, "Lightclient Bootstrap: {}", bootstrap.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +181,8 @@ pub enum Protocol {
|
||||
Ping,
|
||||
/// The `MetaData` protocol name.
|
||||
MetaData,
|
||||
/// The `LightClientBootstrap` protocol name.
|
||||
LightClientBootstrap,
|
||||
}
|
||||
|
||||
/// RPC Versions
|
||||
@@ -209,6 +211,7 @@ impl std::fmt::Display for Protocol {
|
||||
Protocol::BlobsByRoot => "beacon_block_and_blobs_sidecar_by_root",
|
||||
Protocol::Ping => "ping",
|
||||
Protocol::MetaData => "metadata",
|
||||
Protocol::LightClientBootstrap => "light_client_bootstrap",
|
||||
};
|
||||
f.write_str(repr)
|
||||
}
|
||||
@@ -237,6 +240,7 @@ impl std::fmt::Display for Version {
|
||||
pub struct RPCProtocol<TSpec: EthSpec> {
|
||||
pub fork_context: Arc<ForkContext>,
|
||||
pub max_rpc_size: usize,
|
||||
pub enable_light_client_server: bool,
|
||||
pub phantom: PhantomData<TSpec>,
|
||||
}
|
||||
|
||||
@@ -246,7 +250,7 @@ impl<TSpec: EthSpec> UpgradeInfo for RPCProtocol<TSpec> {
|
||||
|
||||
/// The list of supported RPC protocols for Lighthouse.
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
vec![
|
||||
let mut supported_protocols = vec![
|
||||
ProtocolId::new(Protocol::Status, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::Goodbye, Version::V1, Encoding::SSZSnappy),
|
||||
// V2 variants have higher preference then V1
|
||||
@@ -257,7 +261,15 @@ impl<TSpec: EthSpec> UpgradeInfo for RPCProtocol<TSpec> {
|
||||
ProtocolId::new(Protocol::Ping, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V1, Encoding::SSZSnappy),
|
||||
]
|
||||
];
|
||||
if self.enable_light_client_server {
|
||||
supported_protocols.push(ProtocolId::new(
|
||||
Protocol::LightClientBootstrap,
|
||||
Version::V1,
|
||||
Encoding::SSZSnappy,
|
||||
));
|
||||
}
|
||||
supported_protocols
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +338,10 @@ impl ProtocolId {
|
||||
<Ping as Encode>::ssz_fixed_len(),
|
||||
<Ping as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
Protocol::LightClientBootstrap => RpcLimits::new(
|
||||
<LightClientBootstrapRequest as Encode>::ssz_fixed_len(),
|
||||
<LightClientBootstrapRequest as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
Protocol::MetaData => RpcLimits::new(0, 0), // Metadata requests are empty
|
||||
}
|
||||
}
|
||||
@@ -353,6 +369,10 @@ impl ProtocolId {
|
||||
<MetaDataV1<T> as Encode>::ssz_fixed_len(),
|
||||
<MetaDataV2<T> as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
Protocol::LightClientBootstrap => RpcLimits::new(
|
||||
<LightClientBootstrapRequest as Encode>::ssz_fixed_len(),
|
||||
<LightClientBootstrapRequest as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,67 +480,13 @@ pub enum InboundRequest<TSpec: EthSpec> {
|
||||
BlocksByRoot(BlocksByRootRequest),
|
||||
BlobsByRange(BlobsByRangeRequest),
|
||||
BlobsByRoot(BlobsByRootRequest),
|
||||
LightClientBootstrap(LightClientBootstrapRequest),
|
||||
Ping(Ping),
|
||||
MetaData(PhantomData<TSpec>),
|
||||
}
|
||||
|
||||
impl<TSpec: EthSpec> UpgradeInfo for InboundRequest<TSpec> {
|
||||
type Info = ProtocolId;
|
||||
type InfoIter = Vec<Self::Info>;
|
||||
|
||||
// add further protocols as we support more encodings/versions
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
self.supported_protocols()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements the encoding per supported protocol for `RPCRequest`.
|
||||
impl<TSpec: EthSpec> InboundRequest<TSpec> {
|
||||
pub fn supported_protocols(&self) -> Vec<ProtocolId> {
|
||||
match self {
|
||||
// add more protocols when versions/encodings are supported
|
||||
InboundRequest::Status(_) => vec![ProtocolId::new(
|
||||
Protocol::Status,
|
||||
Version::V1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
InboundRequest::Goodbye(_) => vec![ProtocolId::new(
|
||||
Protocol::Goodbye,
|
||||
Version::V1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
InboundRequest::BlocksByRange(_) => vec![
|
||||
// V2 has higher preference when negotiating a stream
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V1, Encoding::SSZSnappy),
|
||||
],
|
||||
InboundRequest::BlocksByRoot(_) => vec![
|
||||
// V2 has higher preference when negotiating a stream
|
||||
ProtocolId::new(Protocol::BlocksByRoot, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRoot, Version::V1, Encoding::SSZSnappy),
|
||||
],
|
||||
InboundRequest::BlobsByRange(_) => vec![ProtocolId::new(
|
||||
Protocol::BlobsByRange,
|
||||
Version::V1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
InboundRequest::BlobsByRoot(_) => vec![ProtocolId::new(
|
||||
Protocol::BlobsByRoot,
|
||||
Version::V1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
InboundRequest::Ping(_) => vec![ProtocolId::new(
|
||||
Protocol::Ping,
|
||||
Version::V1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
InboundRequest::MetaData(_) => vec![
|
||||
ProtocolId::new(Protocol::MetaData, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V1, Encoding::SSZSnappy),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
/* These functions are used in the handler for stream management */
|
||||
|
||||
/// Number of responses expected for this request.
|
||||
@@ -534,6 +500,7 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
|
||||
InboundRequest::BlobsByRoot(req) => req.block_roots.len() as u64,
|
||||
InboundRequest::Ping(_) => 1,
|
||||
InboundRequest::MetaData(_) => 1,
|
||||
InboundRequest::LightClientBootstrap(_) => 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,6 +515,7 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
|
||||
InboundRequest::BlobsByRoot(_) => Protocol::BlobsByRoot,
|
||||
InboundRequest::Ping(_) => Protocol::Ping,
|
||||
InboundRequest::MetaData(_) => Protocol::MetaData,
|
||||
InboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,6 +533,7 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
|
||||
InboundRequest::Goodbye(_) => unreachable!(),
|
||||
InboundRequest::Ping(_) => unreachable!(),
|
||||
InboundRequest::MetaData(_) => unreachable!(),
|
||||
InboundRequest::LightClientBootstrap(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,6 +639,9 @@ impl<TSpec: EthSpec> std::fmt::Display for InboundRequest<TSpec> {
|
||||
InboundRequest::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req),
|
||||
InboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data),
|
||||
InboundRequest::MetaData(_) => write!(f, "MetaData request"),
|
||||
InboundRequest::LightClientBootstrap(bootstrap) => {
|
||||
write!(f, "LightClientBootstrap: {}", bootstrap.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ pub struct RPCRateLimiter {
|
||||
blbrange_rl: Limiter<PeerId>,
|
||||
/// BlobsByRoot rate limiter.
|
||||
blbroot_rl: Limiter<PeerId>,
|
||||
/// LightClientBootstrap rate limiter.
|
||||
lcbootstrap_rl: Limiter<PeerId>,
|
||||
}
|
||||
|
||||
/// Error type for non conformant requests
|
||||
@@ -106,6 +108,8 @@ pub struct RPCRateLimiterBuilder {
|
||||
blbrange_quota: Option<Quota>,
|
||||
/// Quota for the BlobsByRoot protocol.
|
||||
blbroot_quota: Option<Quota>,
|
||||
/// Quota for the LightClientBootstrap protocol.
|
||||
lcbootstrap_quota: Option<Quota>,
|
||||
}
|
||||
|
||||
impl RPCRateLimiterBuilder {
|
||||
@@ -126,6 +130,7 @@ impl RPCRateLimiterBuilder {
|
||||
Protocol::BlocksByRoot => self.bbroots_quota = q,
|
||||
Protocol::BlobsByRange => self.blbrange_quota = q,
|
||||
Protocol::BlobsByRoot => self.blbroot_quota = q,
|
||||
Protocol::LightClientBootstrap => self.lcbootstrap_quota = q,
|
||||
}
|
||||
self
|
||||
}
|
||||
@@ -165,6 +170,9 @@ impl RPCRateLimiterBuilder {
|
||||
let bbrange_quota = self
|
||||
.bbrange_quota
|
||||
.ok_or("BlocksByRange quota not specified")?;
|
||||
let lcbootstrap_quote = self
|
||||
.lcbootstrap_quota
|
||||
.ok_or("LightClientBootstrap quota not specified")?;
|
||||
|
||||
let blbrange_quota = self
|
||||
.blbrange_quota
|
||||
@@ -183,6 +191,7 @@ impl RPCRateLimiterBuilder {
|
||||
let bbrange_rl = Limiter::from_quota(bbrange_quota)?;
|
||||
let blbrange_rl = Limiter::from_quota(blbrange_quota)?;
|
||||
let blbroot_rl = Limiter::from_quota(blbroots_quota)?;
|
||||
let lcbootstrap_rl = Limiter::from_quota(lcbootstrap_quote)?;
|
||||
|
||||
// check for peers to prune every 30 seconds, starting in 30 seconds
|
||||
let prune_every = tokio::time::Duration::from_secs(30);
|
||||
@@ -198,6 +207,7 @@ impl RPCRateLimiterBuilder {
|
||||
bbrange_rl,
|
||||
blbrange_rl,
|
||||
blbroot_rl,
|
||||
lcbootstrap_rl,
|
||||
init_time: Instant::now(),
|
||||
})
|
||||
}
|
||||
@@ -223,6 +233,7 @@ impl RPCRateLimiter {
|
||||
Protocol::BlocksByRoot => &mut self.bbroots_rl,
|
||||
Protocol::BlobsByRange => &mut self.blbrange_rl,
|
||||
Protocol::BlobsByRoot => &mut self.blbroot_rl,
|
||||
Protocol::LightClientBootstrap => &mut self.lcbootstrap_rl,
|
||||
};
|
||||
check(limiter)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use libp2p::core::connection::ConnectionId;
|
||||
use types::light_client_bootstrap::LightClientBootstrap;
|
||||
use types::{BlobsSidecar, EthSpec, SignedBeaconBlock};
|
||||
|
||||
use crate::rpc::methods::{BlobsByRangeRequest, BlobsByRootRequest};
|
||||
use crate::rpc::{
|
||||
methods::{
|
||||
BlocksByRangeRequest, BlocksByRootRequest, OldBlocksByRangeRequest, RPCCodedResponse,
|
||||
RPCResponse, ResponseTermination, StatusMessage,
|
||||
BlocksByRangeRequest, BlocksByRootRequest, LightClientBootstrapRequest,
|
||||
OldBlocksByRangeRequest, RPCCodedResponse, RPCResponse, ResponseTermination, StatusMessage,
|
||||
},
|
||||
OutboundRequest, SubstreamId,
|
||||
};
|
||||
@@ -38,6 +39,8 @@ pub enum Request {
|
||||
BlobsByRange(BlobsByRangeRequest),
|
||||
/// A request blocks root request.
|
||||
BlocksByRoot(BlocksByRootRequest),
|
||||
// light client bootstrap request
|
||||
LightClientBootstrap(LightClientBootstrapRequest),
|
||||
/// A request blobs root request.
|
||||
BlobsByRoot(BlobsByRootRequest),
|
||||
}
|
||||
@@ -54,6 +57,7 @@ impl<TSpec: EthSpec> std::convert::From<Request> for OutboundRequest<TSpec> {
|
||||
})
|
||||
}
|
||||
Request::BlobsByRange(r) => OutboundRequest::BlobsByRange(r),
|
||||
Request::LightClientBootstrap(b) => OutboundRequest::LightClientBootstrap(b),
|
||||
Request::BlobsByRoot(r) => OutboundRequest::BlobsByRoot(r),
|
||||
Request::Status(s) => OutboundRequest::Status(s),
|
||||
}
|
||||
@@ -76,6 +80,8 @@ pub enum Response<TSpec: EthSpec> {
|
||||
BlobsByRange(Option<Arc<BlobsSidecar<TSpec>>>),
|
||||
/// A response to a get BLOCKS_BY_ROOT request.
|
||||
BlocksByRoot(Option<Arc<SignedBeaconBlock<TSpec>>>),
|
||||
/// A response to a LightClientUpdate request.
|
||||
LightClientBootstrap(LightClientBootstrap<TSpec>),
|
||||
/// A response to a get BLOBS_BY_ROOT request.
|
||||
BlobsByRoot(Option<Arc<SignedBeaconBlockAndBlobsSidecar<TSpec>>>),
|
||||
}
|
||||
@@ -100,6 +106,9 @@ impl<TSpec: EthSpec> std::convert::From<Response<TSpec>> for RPCCodedResponse<TS
|
||||
None => RPCCodedResponse::StreamTermination(ResponseTermination::BlobsByRange),
|
||||
},
|
||||
Response::Status(s) => RPCCodedResponse::Success(RPCResponse::Status(s)),
|
||||
Response::LightClientBootstrap(b) => {
|
||||
RPCCodedResponse::Success(RPCResponse::LightClientBootstrap(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use libp2p::gossipsub::subscription_filter::{
|
||||
};
|
||||
use libp2p::gossipsub::Gossipsub as BaseGossipsub;
|
||||
use libp2p::identify::Identify;
|
||||
use libp2p::swarm::NetworkBehaviour;
|
||||
use libp2p::NetworkBehaviour;
|
||||
use types::EthSpec;
|
||||
|
||||
|
||||
@@ -262,7 +262,11 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
(gossipsub, update_gossipsub_scores)
|
||||
};
|
||||
|
||||
let eth2_rpc = RPC::new(ctx.fork_context.clone(), log.clone());
|
||||
let eth2_rpc = RPC::new(
|
||||
ctx.fork_context.clone(),
|
||||
config.enable_light_client_server,
|
||||
log.clone(),
|
||||
);
|
||||
|
||||
let discovery = {
|
||||
// Build and start the discovery sub-behaviour
|
||||
@@ -981,6 +985,9 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
Request::Status(_) => {
|
||||
metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["status"])
|
||||
}
|
||||
Request::LightClientBootstrap(_) => {
|
||||
metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["light_client_bootstrap"])
|
||||
}
|
||||
Request::BlocksByRange { .. } => {
|
||||
metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blocks_by_range"])
|
||||
}
|
||||
@@ -1269,6 +1276,14 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
self.build_request(peer_request_id, peer_id, Request::BlobsByRoot(req));
|
||||
Some(event)
|
||||
}
|
||||
InboundRequest::LightClientBootstrap(req) => {
|
||||
let event = self.build_request(
|
||||
peer_request_id,
|
||||
peer_id,
|
||||
Request::LightClientBootstrap(req),
|
||||
);
|
||||
Some(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(RPCReceived::Response(id, resp)) => {
|
||||
@@ -1302,6 +1317,10 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
RPCResponse::BlobsByRoot(resp) => {
|
||||
self.build_response(id, peer_id, Response::BlobsByRoot(Some(resp)))
|
||||
}
|
||||
// Should never be reached
|
||||
RPCResponse::LightClientBootstrap(bootstrap) => {
|
||||
self.build_response(id, peer_id, Response::LightClientBootstrap(bootstrap))
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(RPCReceived::EndOfStream(id, termination)) => {
|
||||
|
||||
@@ -74,6 +74,17 @@ impl SyncState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_syncing_finalized(&self) -> bool {
|
||||
match self {
|
||||
SyncState::SyncingFinalized { .. } => true,
|
||||
SyncState::SyncingHead { .. } => false,
|
||||
SyncState::SyncTransition => false,
|
||||
SyncState::BackFillSyncing { .. } => false,
|
||||
SyncState::Synced => false,
|
||||
SyncState::Stalled => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the node is synced.
|
||||
///
|
||||
/// NOTE: We consider the node synced if it is fetching old historical blocks.
|
||||
|
||||
Reference in New Issue
Block a user