Merged with unstable

This commit is contained in:
Mark Mackey
2022-11-30 15:14:02 -06:00
125 changed files with 4287 additions and 1502 deletions

View File

@@ -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,
SignedBeaconBlockBase, SignedBeaconBlockCapella, SignedBeaconBlockEip4844,
SignedBeaconBlockMerge,
BlobsSidecar, EthSpec, ForkContext, ForkName, Hash256, SignedBeaconBlock,
SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockCapella,
SignedBeaconBlockEip4844, SignedBeaconBlockMerge,
};
use unsigned_varint::codec::Uvi;
@@ -72,6 +73,7 @@ impl<TSpec: EthSpec> Encoder<RPCCodedResponse<TSpec>> for SSZSnappyInboundCodec<
RPCResponse::BlocksByRange(res) => res.as_ssz_bytes(),
RPCResponse::BlocksByRoot(res) => res.as_ssz_bytes(),
RPCResponse::BlobsByRange(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.
@@ -233,6 +235,7 @@ impl<TSpec: EthSpec> Encoder<OutboundRequest<TSpec>> for SSZSnappyOutboundCodec<
OutboundRequest::BlobsByRange(req) => req.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 {
@@ -486,7 +489,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 => {
@@ -562,6 +569,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)?,
))),
}
}
@@ -923,6 +933,9 @@ mod tests {
OutboundRequest::MetaData(metadata) => {
assert_eq!(decoded, InboundRequest::MetaData(metadata))
}
OutboundRequest::LightClientBootstrap(bootstrap) => {
assert_eq!(decoded, InboundRequest::LightClientBootstrap(bootstrap))
}
}
}
}

View File

@@ -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;

View File

@@ -12,8 +12,10 @@ use std::ops::Deref;
use std::sync::Arc;
use strum::IntoStaticStr;
use superstruct::superstruct;
use types::blobs_sidecar::BlobsSidecar;
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;
@@ -260,6 +262,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 PONG response to a PING request.
Pong(Ping),
@@ -293,6 +298,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")]
@@ -342,6 +353,7 @@ impl<T: EthSpec> RPCCodedResponse<T> {
RPCResponse::BlobsByRange(_) => true,
RPCResponse::Pong(_) => false,
RPCResponse::MetaData(_) => false,
RPCResponse::LightClientBootstrap(_) => false,
},
RPCCodedResponse::Error(_, _) => true,
// Stream terminations are part of responses that have chunks
@@ -377,6 +389,7 @@ impl<T: EthSpec> RPCResponse<T> {
RPCResponse::BlobsByRange(_) => Protocol::BlobsByRange,
RPCResponse::Pong(_) => Protocol::Ping,
RPCResponse::MetaData(_) => Protocol::MetaData,
RPCResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
}
}
}
@@ -415,6 +428,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)
}
}
}
}

View File

@@ -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,
@@ -138,6 +144,7 @@ impl<Id: ReqId, TSpec: EthSpec> RPC<Id, TSpec> {
limiter,
events: Vec::new(),
fork_context,
enable_light_client_server,
log,
}
}
@@ -194,6 +201,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,
},
(),

View File

@@ -39,6 +39,7 @@ pub enum OutboundRequest<TSpec: EthSpec> {
BlocksByRange(OldBlocksByRangeRequest),
BlocksByRoot(BlocksByRootRequest),
BlobsByRange(BlobsByRangeRequest),
LightClientBootstrap(LightClientBootstrapRequest),
Ping(Ping),
MetaData(PhantomData<TSpec>),
}
@@ -90,9 +91,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.
@@ -105,6 +109,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
OutboundRequest::BlobsByRange(req) => req.count,
OutboundRequest::Ping(_) => 1,
OutboundRequest::MetaData(_) => 1,
OutboundRequest::LightClientBootstrap(_) => 1,
}
}
@@ -118,6 +123,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
OutboundRequest::BlobsByRange(_) => Protocol::BlobsByRange,
OutboundRequest::Ping(_) => Protocol::Ping,
OutboundRequest::MetaData(_) => Protocol::MetaData,
OutboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
}
}
@@ -130,6 +136,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
OutboundRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange,
OutboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot,
OutboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange,
OutboundRequest::LightClientBootstrap(_) => unreachable!(),
OutboundRequest::Status(_) => unreachable!(),
OutboundRequest::Goodbye(_) => unreachable!(),
OutboundRequest::Ping(_) => unreachable!(),
@@ -188,6 +195,9 @@ impl<TSpec: EthSpec> std::fmt::Display for OutboundRequest<TSpec> {
OutboundRequest::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req),
OutboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data),
OutboundRequest::MetaData(_) => write!(f, "MetaData request"),
OutboundRequest::LightClientBootstrap(bootstrap) => {
write!(f, "Lightclient Bootstrap: {}", bootstrap.root)
}
}
}
}

View File

@@ -185,6 +185,8 @@ pub enum Protocol {
Ping,
/// The `MetaData` protocol name.
MetaData,
/// The `LightClientBootstrap` protocol name.
LightClientBootstrap,
}
/// RPC Versions
@@ -212,6 +214,7 @@ impl std::fmt::Display for Protocol {
Protocol::BlobsByRange => "blobs_sidecars_by_range",
Protocol::Ping => "ping",
Protocol::MetaData => "metadata",
Protocol::LightClientBootstrap => "light_client_bootstrap",
};
f.write_str(repr)
}
@@ -240,6 +243,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>,
}
@@ -249,7 +253,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
@@ -260,7 +264,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
}
}
@@ -349,6 +365,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(),
),
}
}
@@ -455,62 +475,13 @@ pub enum InboundRequest<TSpec: EthSpec> {
BlocksByRange(OldBlocksByRangeRequest),
BlocksByRoot(BlocksByRootRequest),
BlobsByRange(BlobsByRangeRequest),
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::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.
@@ -523,6 +494,7 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
InboundRequest::BlobsByRange(req) => req.count,
InboundRequest::Ping(_) => 1,
InboundRequest::MetaData(_) => 1,
InboundRequest::LightClientBootstrap(_) => 1,
}
}
@@ -536,6 +508,7 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
InboundRequest::BlobsByRange(_) => Protocol::BlobsByRange,
InboundRequest::Ping(_) => Protocol::Ping,
InboundRequest::MetaData(_) => Protocol::MetaData,
InboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
}
}
@@ -552,6 +525,7 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
InboundRequest::Goodbye(_) => unreachable!(),
InboundRequest::Ping(_) => unreachable!(),
InboundRequest::MetaData(_) => unreachable!(),
InboundRequest::LightClientBootstrap(_) => unreachable!(),
}
}
}
@@ -656,6 +630,9 @@ impl<TSpec: EthSpec> std::fmt::Display for InboundRequest<TSpec> {
InboundRequest::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req),
InboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data),
InboundRequest::MetaData(_) => write!(f, "MetaData request"),
InboundRequest::LightClientBootstrap(bootstrap) => {
write!(f, "LightClientBootstrap: {}", bootstrap.root)
}
}
}
}

View File

@@ -75,6 +75,8 @@ pub struct RPCRateLimiter {
bbroots_rl: Limiter<PeerId>,
/// BlobsByRange rate limiter.
blbrange_rl: Limiter<PeerId>,
/// LightClientBootstrap rate limiter.
lcbootstrap_rl: Limiter<PeerId>,
}
/// Error type for non conformant requests
@@ -102,6 +104,8 @@ pub struct RPCRateLimiterBuilder {
bbroots_quota: Option<Quota>,
/// Quota for the BlobsByRange protocol.
blbrange_quota: Option<Quota>,
/// Quota for the LightClientBootstrap protocol.
lcbootstrap_quota: Option<Quota>,
}
impl RPCRateLimiterBuilder {
@@ -121,6 +125,7 @@ impl RPCRateLimiterBuilder {
Protocol::BlocksByRange => self.bbrange_quota = q,
Protocol::BlocksByRoot => self.bbroots_quota = q,
Protocol::BlobsByRange => self.blbrange_quota = q,
Protocol::LightClientBootstrap => self.lcbootstrap_quota = q,
}
self
}
@@ -160,6 +165,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
@@ -173,6 +181,7 @@ impl RPCRateLimiterBuilder {
let bbroots_rl = Limiter::from_quota(bbroots_quota)?;
let bbrange_rl = Limiter::from_quota(bbrange_quota)?;
let blbrange_rl = Limiter::from_quota(blbrange_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);
@@ -187,6 +196,7 @@ impl RPCRateLimiterBuilder {
bbroots_rl,
bbrange_rl,
blbrange_rl,
lcbootstrap_rl,
init_time: Instant::now(),
})
}
@@ -211,6 +221,7 @@ impl RPCRateLimiter {
Protocol::BlocksByRange => &mut self.bbrange_rl,
Protocol::BlocksByRoot => &mut self.bbroots_rl,
Protocol::BlobsByRange => &mut self.blbrange_rl,
Protocol::LightClientBootstrap => &mut self.lcbootstrap_rl,
};
check(limiter)
}