diff --git a/beacon_node/lighthouse_network/src/lib.rs b/beacon_node/lighthouse_network/src/lib.rs index 5c12290b97..ced803add8 100644 --- a/beacon_node/lighthouse_network/src/lib.rs +++ b/beacon_node/lighthouse_network/src/lib.rs @@ -122,6 +122,6 @@ pub use peer_manager::{ ConnectionDirection, PeerConnectionStatus, PeerInfo, PeerManager, SyncInfo, SyncStatus, }; // pub use service::{load_private_key, Context, Libp2pEvent, Service, NETWORK_KEY_FILENAME}; -pub use service::api_types::{PeerRequestId, Request, Response}; +pub use service::api_types::{PeerRequestId, Response}; pub use service::utils::*; pub use service::{Gossipsub, NetworkEvent}; diff --git a/beacon_node/lighthouse_network/src/peer_manager/mod.rs b/beacon_node/lighthouse_network/src/peer_manager/mod.rs index 9f46f5daa0..1f066e9bbc 100644 --- a/beacon_node/lighthouse_network/src/peer_manager/mod.rs +++ b/beacon_node/lighthouse_network/src/peer_manager/mod.rs @@ -2,7 +2,7 @@ use crate::discovery::enr_ext::EnrExt; use crate::discovery::peer_id_to_node_id; -use crate::rpc::{GoodbyeReason, MetaData, Protocol, RPCError, RPCResponseErrorCode}; +use crate::rpc::{GoodbyeReason, MetaData, Protocol, RPCError, RpcErrorResponse}; use crate::service::TARGET_SUBNET_PEERS; use crate::{error, metrics, Gossipsub, NetworkGlobals, PeerId, Subnet, SubnetDiscovery}; use delay_map::HashSetDelay; @@ -526,8 +526,8 @@ impl PeerManager { PeerAction::HighToleranceError } RPCError::ErrorResponse(code, _) => match code { - RPCResponseErrorCode::Unknown => PeerAction::HighToleranceError, - RPCResponseErrorCode::ResourceUnavailable => { + RpcErrorResponse::Unknown => PeerAction::HighToleranceError, + RpcErrorResponse::ResourceUnavailable => { // Don't ban on this because we want to retry with a block by root request. if matches!( protocol, @@ -558,9 +558,9 @@ impl PeerManager { ConnectionDirection::Incoming => return, } } - RPCResponseErrorCode::ServerError => PeerAction::MidToleranceError, - RPCResponseErrorCode::InvalidRequest => PeerAction::LowToleranceError, - RPCResponseErrorCode::RateLimited => match protocol { + RpcErrorResponse::ServerError => PeerAction::MidToleranceError, + RpcErrorResponse::InvalidRequest => PeerAction::LowToleranceError, + RpcErrorResponse::RateLimited => match protocol { Protocol::Ping => PeerAction::MidToleranceError, Protocol::BlocksByRange => PeerAction::MidToleranceError, Protocol::BlocksByRoot => PeerAction::MidToleranceError, @@ -577,7 +577,7 @@ impl PeerManager { Protocol::MetaData => PeerAction::LowToleranceError, Protocol::Status => PeerAction::LowToleranceError, }, - RPCResponseErrorCode::BlobsNotFoundForBlock => PeerAction::LowToleranceError, + RpcErrorResponse::BlobsNotFoundForBlock => PeerAction::LowToleranceError, }, RPCError::SSZDecodeError(_) => PeerAction::Fatal, RPCError::UnsupportedProtocol => { diff --git a/beacon_node/lighthouse_network/src/rpc/codec.rs b/beacon_node/lighthouse_network/src/rpc/codec.rs index 224fb8a5f7..13af04f9b8 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec.rs @@ -2,7 +2,7 @@ use crate::rpc::methods::*; use crate::rpc::protocol::{ Encoding, ProtocolId, RPCError, SupportedProtocol, ERROR_TYPE_MAX, ERROR_TYPE_MIN, }; -use crate::rpc::{InboundRequest, OutboundRequest}; +use crate::rpc::RequestType; use libp2p::bytes::BufMut; use libp2p::bytes::BytesMut; use snap::read::FrameDecoder; @@ -61,23 +61,23 @@ impl SSZSnappyInboundCodec { /// Encodes RPC Responses sent to peers. fn encode_response( &mut self, - item: RPCCodedResponse, + item: RpcResponse, dst: &mut BytesMut, ) -> Result<(), RPCError> { let bytes = match &item { - RPCCodedResponse::Success(resp) => match &resp { - RPCResponse::Status(res) => res.as_ssz_bytes(), - RPCResponse::BlocksByRange(res) => res.as_ssz_bytes(), - RPCResponse::BlocksByRoot(res) => res.as_ssz_bytes(), - RPCResponse::BlobsByRange(res) => res.as_ssz_bytes(), - RPCResponse::BlobsByRoot(res) => res.as_ssz_bytes(), - RPCResponse::DataColumnsByRoot(res) => res.as_ssz_bytes(), - RPCResponse::DataColumnsByRange(res) => res.as_ssz_bytes(), - RPCResponse::LightClientBootstrap(res) => res.as_ssz_bytes(), - RPCResponse::LightClientOptimisticUpdate(res) => res.as_ssz_bytes(), - RPCResponse::LightClientFinalityUpdate(res) => res.as_ssz_bytes(), - RPCResponse::Pong(res) => res.data.as_ssz_bytes(), - RPCResponse::MetaData(res) => + RpcResponse::Success(resp) => match &resp { + RpcSuccessResponse::Status(res) => res.as_ssz_bytes(), + RpcSuccessResponse::BlocksByRange(res) => res.as_ssz_bytes(), + RpcSuccessResponse::BlocksByRoot(res) => res.as_ssz_bytes(), + RpcSuccessResponse::BlobsByRange(res) => res.as_ssz_bytes(), + RpcSuccessResponse::BlobsByRoot(res) => res.as_ssz_bytes(), + RpcSuccessResponse::DataColumnsByRoot(res) => res.as_ssz_bytes(), + RpcSuccessResponse::DataColumnsByRange(res) => res.as_ssz_bytes(), + RpcSuccessResponse::LightClientBootstrap(res) => res.as_ssz_bytes(), + RpcSuccessResponse::LightClientOptimisticUpdate(res) => res.as_ssz_bytes(), + RpcSuccessResponse::LightClientFinalityUpdate(res) => res.as_ssz_bytes(), + RpcSuccessResponse::Pong(res) => res.data.as_ssz_bytes(), + RpcSuccessResponse::MetaData(res) => // Encode the correct version of the MetaData response based on the negotiated version. { match self.protocol.versioned_protocol { @@ -92,8 +92,8 @@ impl SSZSnappyInboundCodec { } } }, - RPCCodedResponse::Error(_, err) => err.as_ssz_bytes(), - RPCCodedResponse::StreamTermination(_) => { + RpcResponse::Error(_, err) => err.as_ssz_bytes(), + RpcResponse::StreamTermination(_) => { unreachable!("Code error - attempting to encode a stream termination") } }; @@ -126,10 +126,10 @@ impl SSZSnappyInboundCodec { } // Encoder for inbound streams: Encodes RPC Responses sent to peers. -impl Encoder> for SSZSnappyInboundCodec { +impl Encoder> for SSZSnappyInboundCodec { type Error = RPCError; - fn encode(&mut self, item: RPCCodedResponse, dst: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, item: RpcResponse, dst: &mut BytesMut) -> Result<(), Self::Error> { dst.clear(); dst.reserve(1); dst.put_u8( @@ -142,18 +142,18 @@ impl Encoder> for SSZSnappyInboundCodec { // Decoder for inbound streams: Decodes RPC requests from peers impl Decoder for SSZSnappyInboundCodec { - type Item = InboundRequest; + type Item = RequestType; type Error = RPCError; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { if self.protocol.versioned_protocol == SupportedProtocol::MetaDataV1 { - return Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v1()))); + return Ok(Some(RequestType::MetaData(MetadataRequest::new_v1()))); } if self.protocol.versioned_protocol == SupportedProtocol::MetaDataV2 { - return Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v2()))); + return Ok(Some(RequestType::MetaData(MetadataRequest::new_v2()))); } if self.protocol.versioned_protocol == SupportedProtocol::MetaDataV3 { - return Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v3()))); + return Ok(Some(RequestType::MetaData(MetadataRequest::new_v3()))); } let Some(length) = handle_length(&mut self.inner, &mut self.len, src)? else { return Ok(None); @@ -231,7 +231,10 @@ impl SSZSnappyOutboundCodec { } // Decode an Rpc response. - fn decode_response(&mut self, src: &mut BytesMut) -> Result>, RPCError> { + fn decode_response( + &mut self, + src: &mut BytesMut, + ) -> Result>, RPCError> { // Read the context bytes if required if self.protocol.has_context_bytes() && self.fork_name.is_none() { if src.len() >= CONTEXT_BYTES_LEN { @@ -318,28 +321,33 @@ impl SSZSnappyOutboundCodec { } // Encoder for outbound streams: Encodes RPC Requests to peers -impl Encoder> for SSZSnappyOutboundCodec { +impl Encoder> for SSZSnappyOutboundCodec { type Error = RPCError; - fn encode(&mut self, item: OutboundRequest, dst: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, item: RequestType, dst: &mut BytesMut) -> Result<(), Self::Error> { let bytes = match item { - OutboundRequest::Status(req) => req.as_ssz_bytes(), - OutboundRequest::Goodbye(req) => req.as_ssz_bytes(), - OutboundRequest::BlocksByRange(r) => match r { + RequestType::Status(req) => req.as_ssz_bytes(), + RequestType::Goodbye(req) => req.as_ssz_bytes(), + RequestType::BlocksByRange(r) => match r { OldBlocksByRangeRequest::V1(req) => req.as_ssz_bytes(), OldBlocksByRangeRequest::V2(req) => req.as_ssz_bytes(), }, - OutboundRequest::BlocksByRoot(r) => match r { + RequestType::BlocksByRoot(r) => match r { BlocksByRootRequest::V1(req) => req.block_roots.as_ssz_bytes(), BlocksByRootRequest::V2(req) => req.block_roots.as_ssz_bytes(), }, - OutboundRequest::BlobsByRange(req) => req.as_ssz_bytes(), - OutboundRequest::BlobsByRoot(req) => req.blob_ids.as_ssz_bytes(), - OutboundRequest::DataColumnsByRange(req) => req.as_ssz_bytes(), - OutboundRequest::DataColumnsByRoot(req) => req.data_column_ids.as_ssz_bytes(), - OutboundRequest::Ping(req) => req.as_ssz_bytes(), - OutboundRequest::MetaData(_) => return Ok(()), // no metadata to encode + RequestType::BlobsByRange(req) => req.as_ssz_bytes(), + RequestType::BlobsByRoot(req) => req.blob_ids.as_ssz_bytes(), + RequestType::DataColumnsByRange(req) => req.as_ssz_bytes(), + RequestType::DataColumnsByRoot(req) => req.data_column_ids.as_ssz_bytes(), + RequestType::Ping(req) => req.as_ssz_bytes(), + RequestType::LightClientBootstrap(req) => req.as_ssz_bytes(), + // no metadata to encode + RequestType::MetaData(_) + | RequestType::LightClientOptimisticUpdate + | RequestType::LightClientFinalityUpdate => return Ok(()), }; + // SSZ encoded bytes should be within `max_packet_size` if bytes.len() > self.max_packet_size { return Err(RPCError::InternalError( @@ -369,7 +377,7 @@ impl Encoder> for SSZSnappyOutboundCodec { // We prefer to decode blocks and attestations with extra knowledge about the chain to perform // faster verification checks before decoding entire blocks/attestations. impl Decoder for SSZSnappyOutboundCodec { - type Item = RPCCodedResponse; + type Item = RpcResponse; type Error = RPCError; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { @@ -385,15 +393,15 @@ impl Decoder for SSZSnappyOutboundCodec { }); let inner_result = { - if RPCCodedResponse::::is_response(response_code) { + if RpcResponse::::is_response(response_code) { // decode an actual response and mutates the buffer if enough bytes have been read // returning the result. self.decode_response(src) - .map(|r| r.map(RPCCodedResponse::Success)) + .map(|r| r.map(RpcResponse::Success)) } else { // decode an error self.decode_error(src) - .map(|r| r.map(|resp| RPCCodedResponse::from_error(response_code, resp))) + .map(|r| r.map(|resp| RpcResponse::from_error(response_code, resp))) } }; // if the inner decoder was capable of decoding a chunk, we need to reset the current @@ -437,14 +445,14 @@ fn handle_error( fn context_bytes( protocol: &ProtocolId, fork_context: &ForkContext, - resp: &RPCCodedResponse, + resp: &RpcResponse, ) -> Option<[u8; CONTEXT_BYTES_LEN]> { // Add the context bytes if required if protocol.has_context_bytes() { - if let RPCCodedResponse::Success(rpc_variant) = resp { + if let RpcResponse::Success(rpc_variant) = resp { match rpc_variant { - RPCResponse::BlocksByRange(ref_box_block) - | RPCResponse::BlocksByRoot(ref_box_block) => { + RpcSuccessResponse::BlocksByRange(ref_box_block) + | RpcSuccessResponse::BlocksByRoot(ref_box_block) => { return match **ref_box_block { // NOTE: If you are adding another fork type here, be sure to modify the // `fork_context.to_context_bytes()` function to support it as well! @@ -468,10 +476,11 @@ fn context_bytes( } }; } - RPCResponse::BlobsByRange(_) | RPCResponse::BlobsByRoot(_) => { + RpcSuccessResponse::BlobsByRange(_) | RpcSuccessResponse::BlobsByRoot(_) => { return fork_context.to_context_bytes(ForkName::Deneb); } - RPCResponse::DataColumnsByRoot(d) | RPCResponse::DataColumnsByRange(d) => { + RpcSuccessResponse::DataColumnsByRoot(d) + | RpcSuccessResponse::DataColumnsByRange(d) => { // TODO(das): Remove deneb fork after `peerdas-devnet-2`. return if matches!( fork_context.spec.fork_name_at_slot::(d.slot()), @@ -482,20 +491,22 @@ fn context_bytes( fork_context.to_context_bytes(ForkName::Electra) }; } - RPCResponse::LightClientBootstrap(lc_bootstrap) => { + RpcSuccessResponse::LightClientBootstrap(lc_bootstrap) => { return lc_bootstrap .map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name)); } - RPCResponse::LightClientOptimisticUpdate(lc_optimistic_update) => { + RpcSuccessResponse::LightClientOptimisticUpdate(lc_optimistic_update) => { return lc_optimistic_update .map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name)); } - RPCResponse::LightClientFinalityUpdate(lc_finality_update) => { + RpcSuccessResponse::LightClientFinalityUpdate(lc_finality_update) => { return lc_finality_update .map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name)); } // These will not pass the has_context_bytes() check - RPCResponse::Status(_) | RPCResponse::Pong(_) | RPCResponse::MetaData(_) => { + RpcSuccessResponse::Status(_) + | RpcSuccessResponse::Pong(_) + | RpcSuccessResponse::MetaData(_) => { return None; } } @@ -536,21 +547,21 @@ fn handle_rpc_request( versioned_protocol: SupportedProtocol, decoded_buffer: &[u8], spec: &ChainSpec, -) -> Result>, RPCError> { +) -> Result>, RPCError> { match versioned_protocol { - SupportedProtocol::StatusV1 => Ok(Some(InboundRequest::Status( + SupportedProtocol::StatusV1 => Ok(Some(RequestType::Status( StatusMessage::from_ssz_bytes(decoded_buffer)?, ))), - SupportedProtocol::GoodbyeV1 => Ok(Some(InboundRequest::Goodbye( + SupportedProtocol::GoodbyeV1 => Ok(Some(RequestType::Goodbye( GoodbyeReason::from_ssz_bytes(decoded_buffer)?, ))), - SupportedProtocol::BlocksByRangeV2 => Ok(Some(InboundRequest::BlocksByRange( + SupportedProtocol::BlocksByRangeV2 => Ok(Some(RequestType::BlocksByRange( OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2::from_ssz_bytes(decoded_buffer)?), ))), - SupportedProtocol::BlocksByRangeV1 => Ok(Some(InboundRequest::BlocksByRange( + SupportedProtocol::BlocksByRangeV1 => Ok(Some(RequestType::BlocksByRange( OldBlocksByRangeRequest::V1(OldBlocksByRangeRequestV1::from_ssz_bytes(decoded_buffer)?), ))), - SupportedProtocol::BlocksByRootV2 => Ok(Some(InboundRequest::BlocksByRoot( + SupportedProtocol::BlocksByRootV2 => Ok(Some(RequestType::BlocksByRoot( BlocksByRootRequest::V2(BlocksByRootRequestV2 { block_roots: RuntimeVariableList::from_ssz_bytes( decoded_buffer, @@ -558,7 +569,7 @@ fn handle_rpc_request( )?, }), ))), - SupportedProtocol::BlocksByRootV1 => Ok(Some(InboundRequest::BlocksByRoot( + SupportedProtocol::BlocksByRootV1 => Ok(Some(RequestType::BlocksByRoot( BlocksByRootRequest::V1(BlocksByRootRequestV1 { block_roots: RuntimeVariableList::from_ssz_bytes( decoded_buffer, @@ -566,21 +577,21 @@ fn handle_rpc_request( )?, }), ))), - SupportedProtocol::BlobsByRangeV1 => Ok(Some(InboundRequest::BlobsByRange( + SupportedProtocol::BlobsByRangeV1 => Ok(Some(RequestType::BlobsByRange( BlobsByRangeRequest::from_ssz_bytes(decoded_buffer)?, ))), SupportedProtocol::BlobsByRootV1 => { - Ok(Some(InboundRequest::BlobsByRoot(BlobsByRootRequest { + Ok(Some(RequestType::BlobsByRoot(BlobsByRootRequest { blob_ids: RuntimeVariableList::from_ssz_bytes( decoded_buffer, spec.max_request_blob_sidecars as usize, )?, }))) } - SupportedProtocol::DataColumnsByRangeV1 => Ok(Some(InboundRequest::DataColumnsByRange( + SupportedProtocol::DataColumnsByRangeV1 => Ok(Some(RequestType::DataColumnsByRange( DataColumnsByRangeRequest::from_ssz_bytes(decoded_buffer)?, ))), - SupportedProtocol::DataColumnsByRootV1 => Ok(Some(InboundRequest::DataColumnsByRoot( + SupportedProtocol::DataColumnsByRootV1 => Ok(Some(RequestType::DataColumnsByRoot( DataColumnsByRootRequest { data_column_ids: RuntimeVariableList::from_ssz_bytes( decoded_buffer, @@ -588,19 +599,19 @@ fn handle_rpc_request( )?, }, ))), - SupportedProtocol::PingV1 => Ok(Some(InboundRequest::Ping(Ping { + SupportedProtocol::PingV1 => Ok(Some(RequestType::Ping(Ping { data: u64::from_ssz_bytes(decoded_buffer)?, }))), - SupportedProtocol::LightClientBootstrapV1 => Ok(Some( - InboundRequest::LightClientBootstrap(LightClientBootstrapRequest { + SupportedProtocol::LightClientBootstrapV1 => Ok(Some(RequestType::LightClientBootstrap( + LightClientBootstrapRequest { root: Hash256::from_ssz_bytes(decoded_buffer)?, - }), - )), + }, + ))), SupportedProtocol::LightClientOptimisticUpdateV1 => { - Ok(Some(InboundRequest::LightClientOptimisticUpdate)) + Ok(Some(RequestType::LightClientOptimisticUpdate)) } SupportedProtocol::LightClientFinalityUpdateV1 => { - Ok(Some(InboundRequest::LightClientFinalityUpdate)) + Ok(Some(RequestType::LightClientFinalityUpdate)) } // MetaData requests return early from InboundUpgrade and do not reach the decoder. // Handle this case just for completeness. @@ -610,7 +621,7 @@ fn handle_rpc_request( "Metadata requests shouldn't reach decoder", )) } else { - Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v3()))) + Ok(Some(RequestType::MetaData(MetadataRequest::new_v3()))) } } SupportedProtocol::MetaDataV2 => { @@ -619,14 +630,14 @@ fn handle_rpc_request( "Metadata requests shouldn't reach decoder", )) } else { - Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v2()))) + Ok(Some(RequestType::MetaData(MetadataRequest::new_v2()))) } } SupportedProtocol::MetaDataV1 => { if !decoded_buffer.is_empty() { Err(RPCError::InvalidData("Metadata request".to_string())) } else { - Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v1()))) + Ok(Some(RequestType::MetaData(MetadataRequest::new_v1()))) } } } @@ -642,31 +653,33 @@ fn handle_rpc_response( versioned_protocol: SupportedProtocol, decoded_buffer: &[u8], fork_name: Option, -) -> Result>, RPCError> { +) -> Result>, RPCError> { match versioned_protocol { - SupportedProtocol::StatusV1 => Ok(Some(RPCResponse::Status( + SupportedProtocol::StatusV1 => Ok(Some(RpcSuccessResponse::Status( StatusMessage::from_ssz_bytes(decoded_buffer)?, ))), // This case should be unreachable as `Goodbye` has no response. SupportedProtocol::GoodbyeV1 => Err(RPCError::InvalidData( "Goodbye RPC message has no valid response".to_string(), )), - SupportedProtocol::BlocksByRangeV1 => Ok(Some(RPCResponse::BlocksByRange(Arc::new( - SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), - )))), - SupportedProtocol::BlocksByRootV1 => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + SupportedProtocol::BlocksByRangeV1 => { + Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( + SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), + )))) + } + SupportedProtocol::BlocksByRootV1 => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), )))), SupportedProtocol::BlobsByRangeV1 => match fork_name { - Some(ForkName::Deneb) => Ok(Some(RPCResponse::BlobsByRange(Arc::new( + Some(ForkName::Deneb) => Ok(Some(RpcSuccessResponse::BlobsByRange(Arc::new( BlobSidecar::from_ssz_bytes(decoded_buffer)?, )))), Some(_) => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Invalid fork name for blobs by range".to_string(), )), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -674,15 +687,15 @@ fn handle_rpc_response( )), }, SupportedProtocol::BlobsByRootV1 => match fork_name { - Some(ForkName::Deneb) => Ok(Some(RPCResponse::BlobsByRoot(Arc::new( + Some(ForkName::Deneb) => Ok(Some(RpcSuccessResponse::BlobsByRoot(Arc::new( BlobSidecar::from_ssz_bytes(decoded_buffer)?, )))), Some(_) => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Invalid fork name for blobs by root".to_string(), )), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -695,18 +708,18 @@ fn handle_rpc_response( // does not advertise the topic on deneb, simply allows it to decode it. Advertise // logic is in `SupportedTopic::currently_supported`. if fork_name.deneb_enabled() { - Ok(Some(RPCResponse::DataColumnsByRoot(Arc::new( + Ok(Some(RpcSuccessResponse::DataColumnsByRoot(Arc::new( DataColumnSidecar::from_ssz_bytes(decoded_buffer)?, )))) } else { Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Invalid fork name for data columns by root".to_string(), )) } } None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -716,36 +729,36 @@ fn handle_rpc_response( SupportedProtocol::DataColumnsByRangeV1 => match fork_name { Some(fork_name) => { if fork_name.deneb_enabled() { - Ok(Some(RPCResponse::DataColumnsByRange(Arc::new( + Ok(Some(RpcSuccessResponse::DataColumnsByRange(Arc::new( DataColumnSidecar::from_ssz_bytes(decoded_buffer)?, )))) } else { Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Invalid fork name for data columns by range".to_string(), )) } } None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol ), )), }, - SupportedProtocol::PingV1 => Ok(Some(RPCResponse::Pong(Ping { + SupportedProtocol::PingV1 => Ok(Some(RpcSuccessResponse::Pong(Ping { data: u64::from_ssz_bytes(decoded_buffer)?, }))), - SupportedProtocol::MetaDataV1 => Ok(Some(RPCResponse::MetaData(MetaData::V1( + SupportedProtocol::MetaDataV1 => Ok(Some(RpcSuccessResponse::MetaData(MetaData::V1( MetaDataV1::from_ssz_bytes(decoded_buffer)?, )))), SupportedProtocol::LightClientBootstrapV1 => match fork_name { - Some(fork_name) => Ok(Some(RPCResponse::LightClientBootstrap(Arc::new( + Some(fork_name) => Ok(Some(RpcSuccessResponse::LightClientBootstrap(Arc::new( LightClientBootstrap::from_ssz_bytes(decoded_buffer, fork_name)?, )))), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -753,11 +766,14 @@ fn handle_rpc_response( )), }, SupportedProtocol::LightClientOptimisticUpdateV1 => match fork_name { - Some(fork_name) => Ok(Some(RPCResponse::LightClientOptimisticUpdate(Arc::new( - LightClientOptimisticUpdate::from_ssz_bytes(decoded_buffer, fork_name)?, - )))), + Some(fork_name) => Ok(Some(RpcSuccessResponse::LightClientOptimisticUpdate( + Arc::new(LightClientOptimisticUpdate::from_ssz_bytes( + decoded_buffer, + fork_name, + )?), + ))), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -765,11 +781,14 @@ fn handle_rpc_response( )), }, SupportedProtocol::LightClientFinalityUpdateV1 => match fork_name { - Some(fork_name) => Ok(Some(RPCResponse::LightClientFinalityUpdate(Arc::new( - LightClientFinalityUpdate::from_ssz_bytes(decoded_buffer, fork_name)?, - )))), + Some(fork_name) => Ok(Some(RpcSuccessResponse::LightClientFinalityUpdate( + Arc::new(LightClientFinalityUpdate::from_ssz_bytes( + decoded_buffer, + fork_name, + )?), + ))), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -777,40 +796,40 @@ fn handle_rpc_response( )), }, // MetaData V2/V3 responses have no context bytes, so behave similarly to V1 responses - SupportedProtocol::MetaDataV3 => Ok(Some(RPCResponse::MetaData(MetaData::V3( + SupportedProtocol::MetaDataV3 => Ok(Some(RpcSuccessResponse::MetaData(MetaData::V3( MetaDataV3::from_ssz_bytes(decoded_buffer)?, )))), - SupportedProtocol::MetaDataV2 => Ok(Some(RPCResponse::MetaData(MetaData::V2( + SupportedProtocol::MetaDataV2 => Ok(Some(RpcSuccessResponse::MetaData(MetaData::V2( MetaDataV2::from_ssz_bytes(decoded_buffer)?, )))), SupportedProtocol::BlocksByRangeV2 => match fork_name { - Some(ForkName::Altair) => Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Some(ForkName::Altair) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( SignedBeaconBlock::Altair(SignedBeaconBlockAltair::from_ssz_bytes(decoded_buffer)?), )))), - Some(ForkName::Base) => Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Some(ForkName::Base) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), )))), - Some(ForkName::Bellatrix) => Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Some(ForkName::Bellatrix) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( SignedBeaconBlock::Bellatrix(SignedBeaconBlockBellatrix::from_ssz_bytes( decoded_buffer, )?), )))), - Some(ForkName::Capella) => Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Some(ForkName::Capella) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( SignedBeaconBlock::Capella(SignedBeaconBlockCapella::from_ssz_bytes( decoded_buffer, )?), )))), - Some(ForkName::Deneb) => Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Some(ForkName::Deneb) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( SignedBeaconBlock::Deneb(SignedBeaconBlockDeneb::from_ssz_bytes(decoded_buffer)?), )))), - Some(ForkName::Electra) => Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Some(ForkName::Electra) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( SignedBeaconBlock::Electra(SignedBeaconBlockElectra::from_ssz_bytes( decoded_buffer, )?), )))), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -818,32 +837,32 @@ fn handle_rpc_response( )), }, SupportedProtocol::BlocksByRootV2 => match fork_name { - Some(ForkName::Altair) => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Some(ForkName::Altair) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Altair(SignedBeaconBlockAltair::from_ssz_bytes(decoded_buffer)?), )))), - Some(ForkName::Base) => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Some(ForkName::Base) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), )))), - Some(ForkName::Bellatrix) => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Some(ForkName::Bellatrix) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Bellatrix(SignedBeaconBlockBellatrix::from_ssz_bytes( decoded_buffer, )?), )))), - Some(ForkName::Capella) => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Some(ForkName::Capella) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Capella(SignedBeaconBlockCapella::from_ssz_bytes( decoded_buffer, )?), )))), - Some(ForkName::Deneb) => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Some(ForkName::Deneb) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Deneb(SignedBeaconBlockDeneb::from_ssz_bytes(decoded_buffer)?), )))), - Some(ForkName::Electra) => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Some(ForkName::Electra) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Electra(SignedBeaconBlockElectra::from_ssz_bytes( decoded_buffer, )?), )))), None => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "No context bytes provided for {:?} response", versioned_protocol @@ -864,7 +883,7 @@ fn context_bytes_to_fork_name( .ok_or_else(|| { let encoded = hex::encode(context_bytes); RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, format!( "Context bytes {} do not correspond to a valid fork", encoded @@ -1063,7 +1082,7 @@ mod tests { /// Encodes the given protocol response as bytes. fn encode_response( protocol: SupportedProtocol, - message: RPCCodedResponse, + message: RpcResponse, fork_name: ForkName, spec: &ChainSpec, ) -> Result { @@ -1113,7 +1132,7 @@ mod tests { message: &mut BytesMut, fork_name: ForkName, spec: &ChainSpec, - ) -> Result>, RPCError> { + ) -> Result>, RPCError> { let snappy_protocol_id = ProtocolId::new(protocol, Encoding::SSZSnappy); let fork_context = Arc::new(fork_context(fork_name)); let max_packet_size = max_rpc_size(&fork_context, spec.max_chunk_size as usize); @@ -1126,20 +1145,16 @@ mod tests { /// Encodes the provided protocol message as bytes and tries to decode the encoding bytes. fn encode_then_decode_response( protocol: SupportedProtocol, - message: RPCCodedResponse, + message: RpcResponse, fork_name: ForkName, spec: &ChainSpec, - ) -> Result>, RPCError> { + ) -> Result>, RPCError> { let mut encoded = encode_response(protocol, message, fork_name, spec)?; decode_response(protocol, &mut encoded, fork_name, spec) } /// Verifies that requests we send are encoded in a way that we would correctly decode too. - fn encode_then_decode_request( - req: OutboundRequest, - fork_name: ForkName, - spec: &ChainSpec, - ) { + fn encode_then_decode_request(req: RequestType, fork_name: ForkName, spec: &ChainSpec) { let fork_context = Arc::new(fork_context(fork_name)); let max_packet_size = max_rpc_size(&fork_context, spec.max_chunk_size as usize); let protocol = ProtocolId::new(req.versioned_protocol(), Encoding::SSZSnappy); @@ -1162,36 +1177,43 @@ mod tests { ) }); match req { - OutboundRequest::Status(status) => { - assert_eq!(decoded, InboundRequest::Status(status)) + RequestType::Status(status) => { + assert_eq!(decoded, RequestType::Status(status)) } - OutboundRequest::Goodbye(goodbye) => { - assert_eq!(decoded, InboundRequest::Goodbye(goodbye)) + RequestType::Goodbye(goodbye) => { + assert_eq!(decoded, RequestType::Goodbye(goodbye)) } - OutboundRequest::BlocksByRange(bbrange) => { - assert_eq!(decoded, InboundRequest::BlocksByRange(bbrange)) + RequestType::BlocksByRange(bbrange) => { + assert_eq!(decoded, RequestType::BlocksByRange(bbrange)) } - OutboundRequest::BlocksByRoot(bbroot) => { - assert_eq!(decoded, InboundRequest::BlocksByRoot(bbroot)) + RequestType::BlocksByRoot(bbroot) => { + assert_eq!(decoded, RequestType::BlocksByRoot(bbroot)) } - OutboundRequest::BlobsByRange(blbrange) => { - assert_eq!(decoded, InboundRequest::BlobsByRange(blbrange)) + RequestType::BlobsByRange(blbrange) => { + assert_eq!(decoded, RequestType::BlobsByRange(blbrange)) } - OutboundRequest::BlobsByRoot(bbroot) => { - assert_eq!(decoded, InboundRequest::BlobsByRoot(bbroot)) + RequestType::BlobsByRoot(bbroot) => { + assert_eq!(decoded, RequestType::BlobsByRoot(bbroot)) } - OutboundRequest::DataColumnsByRoot(dcbroot) => { - assert_eq!(decoded, InboundRequest::DataColumnsByRoot(dcbroot)) + RequestType::DataColumnsByRoot(dcbroot) => { + assert_eq!(decoded, RequestType::DataColumnsByRoot(dcbroot)) } - OutboundRequest::DataColumnsByRange(dcbrange) => { - assert_eq!(decoded, InboundRequest::DataColumnsByRange(dcbrange)) + RequestType::DataColumnsByRange(dcbrange) => { + assert_eq!(decoded, RequestType::DataColumnsByRange(dcbrange)) } - OutboundRequest::Ping(ping) => { - assert_eq!(decoded, InboundRequest::Ping(ping)) + RequestType::Ping(ping) => { + assert_eq!(decoded, RequestType::Ping(ping)) } - OutboundRequest::MetaData(metadata) => { - assert_eq!(decoded, InboundRequest::MetaData(metadata)) + RequestType::MetaData(metadata) => { + assert_eq!(decoded, RequestType::MetaData(metadata)) } + RequestType::LightClientBootstrap(light_client_bootstrap_request) => { + assert_eq!( + decoded, + RequestType::LightClientBootstrap(light_client_bootstrap_request) + ) + } + RequestType::LightClientOptimisticUpdate | RequestType::LightClientFinalityUpdate => {} } } @@ -1203,31 +1225,33 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::StatusV1, - RPCCodedResponse::Success(RPCResponse::Status(status_message())), + RpcResponse::Success(RpcSuccessResponse::Status(status_message())), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::Status(status_message()))) + Ok(Some(RpcSuccessResponse::Status(status_message()))) ); assert_eq!( encode_then_decode_response( SupportedProtocol::PingV1, - RPCCodedResponse::Success(RPCResponse::Pong(ping_message())), + RpcResponse::Success(RpcSuccessResponse::Pong(ping_message())), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::Pong(ping_message()))) + Ok(Some(RpcSuccessResponse::Pong(ping_message()))) ); assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRangeV1, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( + empty_base_block() + ))), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( empty_base_block() )))) ); @@ -1236,7 +1260,9 @@ mod tests { matches!( encode_then_decode_response( SupportedProtocol::BlocksByRangeV1, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(altair_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( + altair_block() + ))), ForkName::Altair, &chain_spec, ) @@ -1249,20 +1275,24 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRootV1, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block() + ))), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRoot( - Arc::new(empty_base_block()) - ))) + Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block() + )))) ); assert!( matches!( encode_then_decode_response( SupportedProtocol::BlocksByRootV1, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(altair_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot( + Arc::new(altair_block()) + )), ForkName::Altair, &chain_spec, ) @@ -1275,65 +1305,65 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::MetaDataV1, - RPCCodedResponse::Success(RPCResponse::MetaData(metadata())), + RpcResponse::Success(RpcSuccessResponse::MetaData(metadata())), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::MetaData(metadata()))), + Ok(Some(RpcSuccessResponse::MetaData(metadata()))), ); // A MetaDataV2 still encodes as a MetaDataV1 since version is Version::V1 assert_eq!( encode_then_decode_response( SupportedProtocol::MetaDataV1, - RPCCodedResponse::Success(RPCResponse::MetaData(metadata_v2())), + RpcResponse::Success(RpcSuccessResponse::MetaData(metadata_v2())), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::MetaData(metadata()))), + Ok(Some(RpcSuccessResponse::MetaData(metadata()))), ); // A MetaDataV3 still encodes as a MetaDataV2 since version is Version::V2 assert_eq!( encode_then_decode_response( SupportedProtocol::MetaDataV2, - RPCCodedResponse::Success(RPCResponse::MetaData(metadata_v3())), + RpcResponse::Success(RpcSuccessResponse::MetaData(metadata_v3())), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::MetaData(metadata_v2()))), + Ok(Some(RpcSuccessResponse::MetaData(metadata_v2()))), ); assert_eq!( encode_then_decode_response( SupportedProtocol::BlobsByRangeV1, - RPCCodedResponse::Success(RPCResponse::BlobsByRange(empty_blob_sidecar())), + RpcResponse::Success(RpcSuccessResponse::BlobsByRange(empty_blob_sidecar())), ForkName::Deneb, &chain_spec ), - Ok(Some(RPCResponse::BlobsByRange(empty_blob_sidecar()))), + Ok(Some(RpcSuccessResponse::BlobsByRange(empty_blob_sidecar()))), ); assert_eq!( encode_then_decode_response( SupportedProtocol::BlobsByRootV1, - RPCCodedResponse::Success(RPCResponse::BlobsByRoot(empty_blob_sidecar())), + RpcResponse::Success(RpcSuccessResponse::BlobsByRoot(empty_blob_sidecar())), ForkName::Deneb, &chain_spec ), - Ok(Some(RPCResponse::BlobsByRoot(empty_blob_sidecar()))), + Ok(Some(RpcSuccessResponse::BlobsByRoot(empty_blob_sidecar()))), ); assert_eq!( encode_then_decode_response( SupportedProtocol::DataColumnsByRangeV1, - RPCCodedResponse::Success(RPCResponse::DataColumnsByRange( + RpcResponse::Success(RpcSuccessResponse::DataColumnsByRange( empty_data_column_sidecar() )), ForkName::Deneb, &chain_spec ), - Ok(Some(RPCResponse::DataColumnsByRange( + Ok(Some(RpcSuccessResponse::DataColumnsByRange( empty_data_column_sidecar() ))), ); @@ -1341,13 +1371,13 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::DataColumnsByRootV1, - RPCCodedResponse::Success(RPCResponse::DataColumnsByRoot( + RpcResponse::Success(RpcSuccessResponse::DataColumnsByRoot( empty_data_column_sidecar() )), ForkName::Deneb, &chain_spec ), - Ok(Some(RPCResponse::DataColumnsByRoot( + Ok(Some(RpcSuccessResponse::DataColumnsByRoot( empty_data_column_sidecar() ))), ); @@ -1361,11 +1391,13 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRangeV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( + empty_base_block() + ))), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( empty_base_block() )))) ); @@ -1376,11 +1408,13 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRangeV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( + empty_base_block() + ))), ForkName::Altair, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( empty_base_block() )))) ); @@ -1388,11 +1422,13 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRangeV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(altair_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new(altair_block()))), ForkName::Altair, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRange(Arc::new(altair_block())))) + Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( + altair_block() + )))) ); let bellatrix_block_small = @@ -1403,13 +1439,13 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRangeV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new( + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( bellatrix_block_small.clone() ))), ForkName::Bellatrix, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRange(Arc::new( + Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new( bellatrix_block_small.clone() )))) ); @@ -1435,13 +1471,15 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block() + ))), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRoot( - Arc::new(empty_base_block()) - ))), + Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block() + )))), ); // Decode the smallest possible base block when current fork is altair @@ -1450,35 +1488,39 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block() + ))), ForkName::Altair, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRoot( - Arc::new(empty_base_block()) - ))) + Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block() + )))) ); assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(altair_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new(altair_block()))), ForkName::Altair, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRoot(Arc::new(altair_block())))) + Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( + altair_block() + )))) ); assert_eq!( encode_then_decode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new( + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( bellatrix_block_small.clone() ))), ForkName::Bellatrix, &chain_spec, ), - Ok(Some(RPCResponse::BlocksByRoot(Arc::new( + Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( bellatrix_block_small )))) ); @@ -1505,21 +1547,21 @@ mod tests { assert_eq!( encode_then_decode_response( SupportedProtocol::MetaDataV2, - RPCCodedResponse::Success(RPCResponse::MetaData(metadata())), + RpcResponse::Success(RpcSuccessResponse::MetaData(metadata())), ForkName::Base, &chain_spec, ), - Ok(Some(RPCResponse::MetaData(metadata_v2()))) + Ok(Some(RpcSuccessResponse::MetaData(metadata_v2()))) ); assert_eq!( encode_then_decode_response( SupportedProtocol::MetaDataV2, - RPCCodedResponse::Success(RPCResponse::MetaData(metadata_v2())), + RpcResponse::Success(RpcSuccessResponse::MetaData(metadata_v2())), ForkName::Altair, &chain_spec, ), - Ok(Some(RPCResponse::MetaData(metadata_v2()))) + Ok(Some(RpcSuccessResponse::MetaData(metadata_v2()))) ); } @@ -1533,7 +1575,9 @@ mod tests { // Removing context bytes for v2 messages should error let mut encoded_bytes = encode_response( SupportedProtocol::BlocksByRangeV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( + empty_base_block(), + ))), ForkName::Base, &chain_spec, ) @@ -1549,12 +1593,14 @@ mod tests { &chain_spec, ) .unwrap_err(), - RPCError::ErrorResponse(RPCResponseErrorCode::InvalidRequest, _), + RPCError::ErrorResponse(RpcErrorResponse::InvalidRequest, _), )); let mut encoded_bytes = encode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block(), + ))), ForkName::Base, &chain_spec, ) @@ -1570,13 +1616,15 @@ mod tests { &chain_spec, ) .unwrap_err(), - RPCError::ErrorResponse(RPCResponseErrorCode::InvalidRequest, _), + RPCError::ErrorResponse(RpcErrorResponse::InvalidRequest, _), )); // Trying to decode a base block with altair context bytes should give ssz decoding error let mut encoded_bytes = encode_response( SupportedProtocol::BlocksByRangeV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRange(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRange(Arc::new( + empty_base_block(), + ))), ForkName::Altair, &chain_spec, ) @@ -1601,7 +1649,7 @@ mod tests { // Trying to decode an altair block with base context bytes should give ssz decoding error let mut encoded_bytes = encode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(altair_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new(altair_block()))), ForkName::Altair, &chain_spec, ) @@ -1628,7 +1676,7 @@ mod tests { encoded_bytes.extend_from_slice( &encode_response( SupportedProtocol::MetaDataV2, - RPCCodedResponse::Success(RPCResponse::MetaData(metadata())), + RpcResponse::Success(RpcSuccessResponse::MetaData(metadata())), ForkName::Altair, &chain_spec, ) @@ -1646,7 +1694,9 @@ mod tests { // Sending context bytes which do not correspond to any fork should return an error let mut encoded_bytes = encode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block(), + ))), ForkName::Altair, &chain_spec, ) @@ -1664,13 +1714,15 @@ mod tests { &chain_spec, ) .unwrap_err(), - RPCError::ErrorResponse(RPCResponseErrorCode::InvalidRequest, _), + RPCError::ErrorResponse(RpcErrorResponse::InvalidRequest, _), )); // Sending bytes less than context bytes length should wait for more bytes by returning `Ok(None)` let mut encoded_bytes = encode_response( SupportedProtocol::BlocksByRootV2, - RPCCodedResponse::Success(RPCResponse::BlocksByRoot(Arc::new(empty_base_block()))), + RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(Arc::new( + empty_base_block(), + ))), ForkName::Altair, &chain_spec, ) @@ -1693,20 +1745,20 @@ mod tests { fn test_encode_then_decode_request() { let chain_spec = Spec::default_spec(); - let requests: &[OutboundRequest] = &[ - OutboundRequest::Ping(ping_message()), - OutboundRequest::Status(status_message()), - OutboundRequest::Goodbye(GoodbyeReason::Fault), - OutboundRequest::BlocksByRange(bbrange_request_v1()), - OutboundRequest::BlocksByRange(bbrange_request_v2()), - OutboundRequest::BlocksByRoot(bbroot_request_v1(&chain_spec)), - OutboundRequest::BlocksByRoot(bbroot_request_v2(&chain_spec)), - OutboundRequest::MetaData(MetadataRequest::new_v1()), - OutboundRequest::BlobsByRange(blbrange_request()), - OutboundRequest::BlobsByRoot(blbroot_request(&chain_spec)), - OutboundRequest::DataColumnsByRange(dcbrange_request()), - OutboundRequest::DataColumnsByRoot(dcbroot_request(&chain_spec)), - OutboundRequest::MetaData(MetadataRequest::new_v2()), + let requests: &[RequestType] = &[ + RequestType::Ping(ping_message()), + RequestType::Status(status_message()), + RequestType::Goodbye(GoodbyeReason::Fault), + RequestType::BlocksByRange(bbrange_request_v1()), + RequestType::BlocksByRange(bbrange_request_v2()), + RequestType::BlocksByRoot(bbroot_request_v1(&chain_spec)), + RequestType::BlocksByRoot(bbroot_request_v2(&chain_spec)), + RequestType::MetaData(MetadataRequest::new_v1()), + RequestType::BlobsByRange(blbrange_request()), + RequestType::BlobsByRoot(blbroot_request(&chain_spec)), + RequestType::DataColumnsByRange(dcbrange_request()), + RequestType::DataColumnsByRoot(dcbroot_request(&chain_spec)), + RequestType::MetaData(MetadataRequest::new_v2()), ]; for req in requests.iter() { diff --git a/beacon_node/lighthouse_network/src/rpc/handler.rs b/beacon_node/lighthouse_network/src/rpc/handler.rs index 6f338ebc8b..e76d6d2786 100644 --- a/beacon_node/lighthouse_network/src/rpc/handler.rs +++ b/beacon_node/lighthouse_network/src/rpc/handler.rs @@ -1,11 +1,12 @@ #![allow(clippy::type_complexity)] #![allow(clippy::cognitive_complexity)] -use super::methods::{GoodbyeReason, RPCCodedResponse, RPCResponseErrorCode}; +use super::methods::{GoodbyeReason, RpcErrorResponse, RpcResponse}; use super::outbound::OutboundRequestContainer; -use super::protocol::{InboundOutput, InboundRequest, Protocol, RPCError, RPCProtocol}; -use super::{RPCReceived, RPCSend, ReqId}; -use crate::rpc::outbound::{OutboundFramed, OutboundRequest}; +use super::protocol::{InboundOutput, Protocol, RPCError, RPCProtocol, RequestType}; +use super::RequestId; +use super::{RPCReceived, RPCSend, ReqId, Request}; +use crate::rpc::outbound::OutboundFramed; use crate::rpc::protocol::InboundFramed; use fnv::FnvHashMap; use futures::prelude::*; @@ -95,7 +96,7 @@ where events_out: SmallVec<[HandlerEvent; 4]>, /// Queue of outbound substreams to open. - dial_queue: SmallVec<[(Id, OutboundRequest); 4]>, + dial_queue: SmallVec<[(Id, RequestType); 4]>, /// Current number of concurrent outbound substreams being opened. dial_negotiated: u32, @@ -159,7 +160,7 @@ struct InboundInfo { /// State of the substream. state: InboundState, /// Responses queued for sending. - pending_items: VecDeque>, + pending_items: VecDeque>, /// Protocol of the original request we received from the peer. protocol: Protocol, /// Responses that the peer is still expecting from us. @@ -205,7 +206,7 @@ pub enum OutboundSubstreamState { /// The framed negotiated substream. substream: Box>, /// Keeps track of the actual request sent. - request: OutboundRequest, + request: RequestType, }, /// Closing an outbound substream> Closing(Box>), @@ -263,7 +264,7 @@ where // Queue our goodbye message. if let Some((id, reason)) = goodbye_reason { - self.dial_queue.push((id, OutboundRequest::Goodbye(reason))); + self.dial_queue.push((id, RequestType::Goodbye(reason))); } self.state = HandlerState::ShuttingDown(Box::pin(sleep(Duration::from_secs( @@ -273,7 +274,7 @@ where } /// Opens an outbound substream with a request. - fn send_request(&mut self, id: Id, req: OutboundRequest) { + fn send_request(&mut self, id: Id, req: RequestType) { match self.state { HandlerState::Active => { self.dial_queue.push((id, req)); @@ -291,10 +292,10 @@ where /// Sends a response to a peer's request. // NOTE: If the substream has closed due to inactivity, or the substream is in the // wrong state a response will fail silently. - fn send_response(&mut self, inbound_id: SubstreamId, response: RPCCodedResponse) { + fn send_response(&mut self, inbound_id: SubstreamId, response: RpcResponse) { // check if the stream matching the response still exists let Some(inbound_info) = self.inbound_substreams.get_mut(&inbound_id) else { - if !matches!(response, RPCCodedResponse::StreamTermination(..)) { + if !matches!(response, RpcResponse::StreamTermination(..)) { // the stream is closed after sending the expected number of responses trace!(self.log, "Inbound stream has expired. Response not sent"; "response" => %response, "id" => inbound_id); @@ -302,7 +303,7 @@ where return; }; // If the response we are sending is an error, report back for handling - if let RPCCodedResponse::Error(ref code, ref reason) = response { + if let RpcResponse::Error(ref code, ref reason) = response { self.events_out.push(HandlerEvent::Err(HandlerErr::Inbound { error: RPCError::ErrorResponse(*code, reason.to_string()), proto: inbound_info.protocol, @@ -329,7 +330,7 @@ where type ToBehaviour = HandlerEvent; type InboundProtocol = RPCProtocol; type OutboundProtocol = OutboundRequestContainer; - type OutboundOpenInfo = (Id, OutboundRequest); // Keep track of the id and the request + type OutboundOpenInfo = (Id, RequestType); // Keep track of the id and the request type InboundOpenInfo = (); fn listen_protocol(&self) -> SubstreamProtocol { @@ -403,8 +404,8 @@ where if info.pending_items.back().map(|l| l.close_after()) == Some(false) { // if the last chunk does not close the stream, append an error - info.pending_items.push_back(RPCCodedResponse::Error( - RPCResponseErrorCode::ServerError, + info.pending_items.push_back(RpcResponse::Error( + RpcErrorResponse::ServerError, "Request timed out".into(), )); } @@ -672,13 +673,13 @@ where let proto = entry.get().proto; let received = match response { - RPCCodedResponse::StreamTermination(t) => { + RpcResponse::StreamTermination(t) => { HandlerEvent::Ok(RPCReceived::EndOfStream(id, t)) } - RPCCodedResponse::Success(resp) => { + RpcResponse::Success(resp) => { HandlerEvent::Ok(RPCReceived::Response(id, resp)) } - RPCCodedResponse::Error(ref code, ref r) => { + RpcResponse::Error(ref code, ref r) => { HandlerEvent::Err(HandlerErr::Outbound { id, proto, @@ -888,21 +889,23 @@ where } // If we received a goodbye, shutdown the connection. - if let InboundRequest::Goodbye(_) = req { + if let RequestType::Goodbye(_) = req { self.shutdown(None); } - self.events_out.push(HandlerEvent::Ok(RPCReceived::Request( - self.current_inbound_substream_id, - req, - ))); + self.events_out + .push(HandlerEvent::Ok(RPCReceived::Request(Request { + id: RequestId::next(), + substream_id: self.current_inbound_substream_id, + r#type: req, + }))); self.current_inbound_substream_id.0 += 1; } fn on_fully_negotiated_outbound( &mut self, substream: OutboundFramed, - (id, request): (Id, OutboundRequest), + (id, request): (Id, RequestType), ) { self.dial_negotiated -= 1; // Reset any io-retries counter. @@ -958,7 +961,7 @@ where } fn on_dial_upgrade_error( &mut self, - request_info: (Id, OutboundRequest), + request_info: (Id, RequestType), error: StreamUpgradeError, ) { let (id, req) = request_info; @@ -1016,15 +1019,15 @@ impl slog::Value for SubstreamId { /// error that occurred with sending a message is reported also. async fn send_message_to_inbound_substream( mut substream: InboundSubstream, - message: RPCCodedResponse, + message: RpcResponse, last_chunk: bool, ) -> Result<(InboundSubstream, bool), RPCError> { - if matches!(message, RPCCodedResponse::StreamTermination(_)) { + if matches!(message, RpcResponse::StreamTermination(_)) { substream.close().await.map(|_| (substream, true)) } else { // chunks that are not stream terminations get sent, and the stream is closed if // the response is an error - let is_error = matches!(message, RPCCodedResponse::Error(..)); + let is_error = matches!(message, RpcResponse::Error(..)); let send_result = substream.send(message).await; diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index 6e1ba9cd30..dc7d316fb0 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -481,7 +481,7 @@ impl DataColumnsByRootRequest { // Collection of enums and structs used by the Codecs to encode/decode RPC messages #[derive(Debug, Clone, PartialEq)] -pub enum RPCResponse { +pub enum RpcSuccessResponse { /// A HELLO message. Status(StatusMessage), @@ -545,11 +545,11 @@ pub enum ResponseTermination { /// The structured response containing a result/code indicating success or failure /// and the contents of the response #[derive(Debug, Clone)] -pub enum RPCCodedResponse { +pub enum RpcResponse { /// The response is a successful. - Success(RPCResponse), + Success(RpcSuccessResponse), - Error(RPCResponseErrorCode, ErrorType), + Error(RpcErrorResponse, ErrorType), /// Received a stream termination indicating which response is being terminated. StreamTermination(ResponseTermination), @@ -564,7 +564,7 @@ pub struct LightClientBootstrapRequest { /// The code assigned to an erroneous `RPCResponse`. #[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)] #[strum(serialize_all = "snake_case")] -pub enum RPCResponseErrorCode { +pub enum RpcErrorResponse { RateLimited, BlobsNotFoundForBlock, InvalidRequest, @@ -574,13 +574,13 @@ pub enum RPCResponseErrorCode { Unknown, } -impl RPCCodedResponse { +impl RpcResponse { /// Used to encode the response in the codec. pub fn as_u8(&self) -> Option { match self { - RPCCodedResponse::Success(_) => Some(0), - RPCCodedResponse::Error(code, _) => Some(code.as_u8()), - RPCCodedResponse::StreamTermination(_) => None, + RpcResponse::Success(_) => Some(0), + RpcResponse::Error(code, _) => Some(code.as_u8()), + RpcResponse::StreamTermination(_) => None, } } @@ -592,64 +592,66 @@ impl RPCCodedResponse { /// Builds an RPCCodedResponse from a response code and an ErrorMessage pub fn from_error(response_code: u8, err: ErrorType) -> Self { let code = match response_code { - 1 => RPCResponseErrorCode::InvalidRequest, - 2 => RPCResponseErrorCode::ServerError, - 3 => RPCResponseErrorCode::ResourceUnavailable, - 139 => RPCResponseErrorCode::RateLimited, - 140 => RPCResponseErrorCode::BlobsNotFoundForBlock, - _ => RPCResponseErrorCode::Unknown, + 1 => RpcErrorResponse::InvalidRequest, + 2 => RpcErrorResponse::ServerError, + 3 => RpcErrorResponse::ResourceUnavailable, + 139 => RpcErrorResponse::RateLimited, + 140 => RpcErrorResponse::BlobsNotFoundForBlock, + _ => RpcErrorResponse::Unknown, }; - RPCCodedResponse::Error(code, err) + RpcResponse::Error(code, err) } /// Returns true if this response always terminates the stream. pub fn close_after(&self) -> bool { - !matches!(self, RPCCodedResponse::Success(_)) + !matches!(self, RpcResponse::Success(_)) } } -impl RPCResponseErrorCode { +impl RpcErrorResponse { fn as_u8(&self) -> u8 { match self { - RPCResponseErrorCode::InvalidRequest => 1, - RPCResponseErrorCode::ServerError => 2, - RPCResponseErrorCode::ResourceUnavailable => 3, - RPCResponseErrorCode::Unknown => 255, - RPCResponseErrorCode::RateLimited => 139, - RPCResponseErrorCode::BlobsNotFoundForBlock => 140, + RpcErrorResponse::InvalidRequest => 1, + RpcErrorResponse::ServerError => 2, + RpcErrorResponse::ResourceUnavailable => 3, + RpcErrorResponse::Unknown => 255, + RpcErrorResponse::RateLimited => 139, + RpcErrorResponse::BlobsNotFoundForBlock => 140, } } } use super::Protocol; -impl RPCResponse { +impl RpcSuccessResponse { pub fn protocol(&self) -> Protocol { match self { - RPCResponse::Status(_) => Protocol::Status, - RPCResponse::BlocksByRange(_) => Protocol::BlocksByRange, - RPCResponse::BlocksByRoot(_) => Protocol::BlocksByRoot, - RPCResponse::BlobsByRange(_) => Protocol::BlobsByRange, - RPCResponse::BlobsByRoot(_) => Protocol::BlobsByRoot, - RPCResponse::DataColumnsByRoot(_) => Protocol::DataColumnsByRoot, - RPCResponse::DataColumnsByRange(_) => Protocol::DataColumnsByRange, - RPCResponse::Pong(_) => Protocol::Ping, - RPCResponse::MetaData(_) => Protocol::MetaData, - RPCResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap, - RPCResponse::LightClientOptimisticUpdate(_) => Protocol::LightClientOptimisticUpdate, - RPCResponse::LightClientFinalityUpdate(_) => Protocol::LightClientFinalityUpdate, + RpcSuccessResponse::Status(_) => Protocol::Status, + RpcSuccessResponse::BlocksByRange(_) => Protocol::BlocksByRange, + RpcSuccessResponse::BlocksByRoot(_) => Protocol::BlocksByRoot, + RpcSuccessResponse::BlobsByRange(_) => Protocol::BlobsByRange, + RpcSuccessResponse::BlobsByRoot(_) => Protocol::BlobsByRoot, + RpcSuccessResponse::DataColumnsByRoot(_) => Protocol::DataColumnsByRoot, + RpcSuccessResponse::DataColumnsByRange(_) => Protocol::DataColumnsByRange, + RpcSuccessResponse::Pong(_) => Protocol::Ping, + RpcSuccessResponse::MetaData(_) => Protocol::MetaData, + RpcSuccessResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap, + RpcSuccessResponse::LightClientOptimisticUpdate(_) => { + Protocol::LightClientOptimisticUpdate + } + RpcSuccessResponse::LightClientFinalityUpdate(_) => Protocol::LightClientFinalityUpdate, } } } -impl std::fmt::Display for RPCResponseErrorCode { +impl std::fmt::Display for RpcErrorResponse { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let repr = match self { - RPCResponseErrorCode::InvalidRequest => "The request was invalid", - RPCResponseErrorCode::ResourceUnavailable => "Resource unavailable", - RPCResponseErrorCode::ServerError => "Server error occurred", - RPCResponseErrorCode::Unknown => "Unknown error occurred", - RPCResponseErrorCode::RateLimited => "Rate limited", - RPCResponseErrorCode::BlobsNotFoundForBlock => "No blobs for the given root", + RpcErrorResponse::InvalidRequest => "The request was invalid", + RpcErrorResponse::ResourceUnavailable => "Resource unavailable", + RpcErrorResponse::ServerError => "Server error occurred", + RpcErrorResponse::Unknown => "Unknown error occurred", + RpcErrorResponse::RateLimited => "Rate limited", + RpcErrorResponse::BlobsNotFoundForBlock => "No blobs for the given root", }; f.write_str(repr) } @@ -661,45 +663,47 @@ impl std::fmt::Display for StatusMessage { } } -impl std::fmt::Display for RPCResponse { +impl std::fmt::Display for RpcSuccessResponse { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RPCResponse::Status(status) => write!(f, "{}", status), - RPCResponse::BlocksByRange(block) => { + RpcSuccessResponse::Status(status) => write!(f, "{}", status), + RpcSuccessResponse::BlocksByRange(block) => { write!(f, "BlocksByRange: Block slot: {}", block.slot()) } - RPCResponse::BlocksByRoot(block) => { + RpcSuccessResponse::BlocksByRoot(block) => { write!(f, "BlocksByRoot: Block slot: {}", block.slot()) } - RPCResponse::BlobsByRange(blob) => { + RpcSuccessResponse::BlobsByRange(blob) => { write!(f, "BlobsByRange: Blob slot: {}", blob.slot()) } - RPCResponse::BlobsByRoot(sidecar) => { + RpcSuccessResponse::BlobsByRoot(sidecar) => { write!(f, "BlobsByRoot: Blob slot: {}", sidecar.slot()) } - RPCResponse::DataColumnsByRoot(sidecar) => { + RpcSuccessResponse::DataColumnsByRoot(sidecar) => { write!(f, "DataColumnsByRoot: Data column slot: {}", sidecar.slot()) } - RPCResponse::DataColumnsByRange(sidecar) => { + RpcSuccessResponse::DataColumnsByRange(sidecar) => { write!( f, "DataColumnsByRange: Data column slot: {}", sidecar.slot() ) } - RPCResponse::Pong(ping) => write!(f, "Pong: {}", ping.data), - RPCResponse::MetaData(metadata) => write!(f, "Metadata: {}", metadata.seq_number()), - RPCResponse::LightClientBootstrap(bootstrap) => { + RpcSuccessResponse::Pong(ping) => write!(f, "Pong: {}", ping.data), + RpcSuccessResponse::MetaData(metadata) => { + write!(f, "Metadata: {}", metadata.seq_number()) + } + RpcSuccessResponse::LightClientBootstrap(bootstrap) => { write!(f, "LightClientBootstrap Slot: {}", bootstrap.get_slot()) } - RPCResponse::LightClientOptimisticUpdate(update) => { + RpcSuccessResponse::LightClientOptimisticUpdate(update) => { write!( f, "LightClientOptimisticUpdate Slot: {}", update.signature_slot() ) } - RPCResponse::LightClientFinalityUpdate(update) => { + RpcSuccessResponse::LightClientFinalityUpdate(update) => { write!( f, "LightClientFinalityUpdate Slot: {}", @@ -710,12 +714,12 @@ impl std::fmt::Display for RPCResponse { } } -impl std::fmt::Display for RPCCodedResponse { +impl std::fmt::Display for RpcResponse { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RPCCodedResponse::Success(res) => write!(f, "{}", res), - RPCCodedResponse::Error(code, err) => write!(f, "{}: {}", code, err), - RPCCodedResponse::StreamTermination(_) => write!(f, "Stream Termination"), + RpcResponse::Success(res) => write!(f, "{}", res), + RpcResponse::Error(code, err) => write!(f, "{}: {}", code, err), + RpcResponse::StreamTermination(_) => write!(f, "Stream Termination"), } } } diff --git a/beacon_node/lighthouse_network/src/rpc/mod.rs b/beacon_node/lighthouse_network/src/rpc/mod.rs index 4961c31d28..e3b41ea1df 100644 --- a/beacon_node/lighthouse_network/src/rpc/mod.rs +++ b/beacon_node/lighthouse_network/src/rpc/mod.rs @@ -16,6 +16,7 @@ use libp2p::PeerId; use rate_limiter::{RPCRateLimiter as RateLimiter, RateLimitedErr}; use slog::{crit, debug, o, trace}; use std::marker::PhantomData; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::task::{Context, Poll}; use std::time::Duration; @@ -23,16 +24,15 @@ use types::{EthSpec, ForkContext}; pub(crate) use handler::{HandlerErr, HandlerEvent}; pub(crate) use methods::{ - MetaData, MetaDataV1, MetaDataV2, MetaDataV3, Ping, RPCCodedResponse, RPCResponse, + MetaData, MetaDataV1, MetaDataV2, MetaDataV3, Ping, RpcResponse, RpcSuccessResponse, }; -pub(crate) use protocol::InboundRequest; +pub use protocol::RequestType; pub use handler::SubstreamId; pub use methods::{ BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, LightClientBootstrapRequest, - RPCResponseErrorCode, ResponseTermination, StatusMessage, + ResponseTermination, RpcErrorResponse, StatusMessage, }; -pub(crate) use outbound::OutboundRequest; pub use protocol::{max_rpc_size, Protocol, RPCError}; use self::config::{InboundRateLimiterConfig, OutboundRateLimiterConfig}; @@ -48,6 +48,8 @@ mod protocol; mod rate_limiter; mod self_limiter; +static NEXT_REQUEST_ID: AtomicUsize = AtomicUsize::new(1); + /// Composite trait for a request id. pub trait ReqId: Send + 'static + std::fmt::Debug + Copy + Clone {} impl ReqId for T where T: Send + 'static + std::fmt::Debug + Copy + Clone {} @@ -59,13 +61,13 @@ pub enum RPCSend { /// /// The `Id` is given by the application making the request. These /// go over *outbound* connections. - Request(Id, OutboundRequest), + Request(Id, RequestType), /// A response sent from Lighthouse. /// /// The `SubstreamId` must correspond to the RPC-given ID of the original request received from the /// peer. The second parameter is a single chunk of a response. These go over *inbound* /// connections. - Response(SubstreamId, RPCCodedResponse), + Response(SubstreamId, RpcResponse), /// Lighthouse has requested to terminate the connection with a goodbye message. Shutdown(Id, GoodbyeReason), } @@ -77,17 +79,46 @@ pub enum RPCReceived { /// /// The `SubstreamId` is given by the `RPCHandler` as it identifies this request with the /// *inbound* substream over which it is managed. - Request(SubstreamId, InboundRequest), + Request(Request), /// A response received from the outside. /// /// The `Id` corresponds to the application given ID of the original request sent to the /// peer. The second parameter is a single chunk of a response. These go over *outbound* /// connections. - Response(Id, RPCResponse), + Response(Id, RpcSuccessResponse), /// Marks a request as completed EndOfStream(Id, ResponseTermination), } +/// Rpc `Request` identifier. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct RequestId(usize); + +impl RequestId { + /// Returns the next available [`RequestId`]. + pub fn next() -> Self { + Self(NEXT_REQUEST_ID.fetch_add(1, Ordering::SeqCst)) + } + + /// Creates an _unchecked_ [`RequestId`]. + /// + /// [`Rpc`] enforces that [`RequestId`]s are unique and not reused. + /// This constructor does not, hence the _unchecked_. + /// + /// It is primarily meant for allowing manual tests. + pub fn new_unchecked(id: usize) -> Self { + Self(id) + } +} + +/// An Rpc Request. +#[derive(Debug, Clone)] +pub struct Request { + pub id: RequestId, + pub substream_id: SubstreamId, + pub r#type: RequestType, +} + impl std::fmt::Display for RPCSend { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -177,7 +208,8 @@ impl RPC { &mut self, peer_id: PeerId, id: (ConnectionId, SubstreamId), - event: RPCCodedResponse, + _request_id: RequestId, + event: RpcResponse, ) { self.events.push(ToSwarm::NotifyHandler { peer_id, @@ -189,7 +221,7 @@ impl RPC { /// Submits an RPC request. /// /// The peer must be connected for this to succeed. - pub fn send_request(&mut self, peer_id: PeerId, request_id: Id, req: OutboundRequest) { + pub fn send_request(&mut self, peer_id: PeerId, request_id: Id, req: RequestType) { let event = if let Some(self_limiter) = self.self_limiter.as_mut() { match self_limiter.allows(peer_id, request_id, req) { Ok(event) => event, @@ -229,7 +261,7 @@ impl RPC { data: self.seq_number, }; trace!(self.log, "Sending Ping"; "peer_id" => %peer_id); - self.send_request(peer_id, id, OutboundRequest::Ping(ping)); + self.send_request(peer_id, id, RequestType::Ping(ping)); } } @@ -368,13 +400,17 @@ where event: ::ToBehaviour, ) { match event { - HandlerEvent::Ok(RPCReceived::Request(id, req)) => { + HandlerEvent::Ok(RPCReceived::Request(Request { + id, + substream_id, + r#type, + })) => { if let Some(limiter) = self.limiter.as_mut() { // check if the request is conformant to the quota - match limiter.allows(&peer_id, &req) { + match limiter.allows(&peer_id, &r#type) { Err(RateLimitedErr::TooLarge) => { // we set the batch sizes, so this is a coding/config err for most protocols - let protocol = req.versioned_protocol().protocol(); + let protocol = r#type.versioned_protocol().protocol(); if matches!( protocol, Protocol::BlocksByRange @@ -384,7 +420,7 @@ where | Protocol::BlobsByRoot | Protocol::DataColumnsByRoot ) { - debug!(self.log, "Request too large to process"; "request" => %req, "protocol" => %protocol); + debug!(self.log, "Request too large to process"; "request" => %r#type, "protocol" => %protocol); } else { // Other protocols shouldn't be sending large messages, we should flag the peer kind crit!(self.log, "Request size too large to ever be processed"; "protocol" => %protocol); @@ -393,9 +429,10 @@ where // the handler upon receiving the error code will send it back to the behaviour self.send_response( peer_id, - (conn_id, id), - RPCCodedResponse::Error( - RPCResponseErrorCode::RateLimited, + (conn_id, substream_id), + id, + RpcResponse::Error( + RpcErrorResponse::RateLimited, "Rate limited. Request too large".into(), ), ); @@ -403,30 +440,33 @@ where } Err(RateLimitedErr::TooSoon(wait_time)) => { debug!(self.log, "Request exceeds the rate limit"; - "request" => %req, "peer_id" => %peer_id, "wait_time_ms" => wait_time.as_millis()); + "request" => %r#type, "peer_id" => %peer_id, "wait_time_ms" => wait_time.as_millis()); // send an error code to the peer. // the handler upon receiving the error code will send it back to the behaviour self.send_response( peer_id, - (conn_id, id), - RPCCodedResponse::Error( - RPCResponseErrorCode::RateLimited, + (conn_id, substream_id), + id, + RpcResponse::Error( + RpcErrorResponse::RateLimited, format!("Wait {:?}", wait_time).into(), ), ); return; } // No rate limiting, continue. - Ok(_) => {} + Ok(()) => {} } } + // If we received a Ping, we queue a Pong response. - if let InboundRequest::Ping(_) = req { + if let RequestType::Ping(_) = r#type { trace!(self.log, "Received Ping, queueing Pong";"connection_id" => %conn_id, "peer_id" => %peer_id); self.send_response( peer_id, - (conn_id, id), - RPCCodedResponse::Success(RPCResponse::Pong(Ping { + (conn_id, substream_id), + id, + RpcResponse::Success(RpcSuccessResponse::Pong(Ping { data: self.seq_number, })), ); @@ -435,7 +475,11 @@ where self.events.push(ToSwarm::GenerateEvent(RPCMessage { peer_id, conn_id, - message: Ok(RPCReceived::Request(id, req)), + message: Ok(RPCReceived::Request(Request { + id, + substream_id, + r#type, + })), })); } HandlerEvent::Ok(rpc) => { @@ -496,8 +540,8 @@ where match &self.message { Ok(received) => { let (msg_kind, protocol) = match received { - RPCReceived::Request(_, req) => { - ("request", req.versioned_protocol().protocol()) + RPCReceived::Request(Request { r#type, .. }) => { + ("request", r#type.versioned_protocol().protocol()) } RPCReceived::Response(_, res) => ("response", res.protocol()), RPCReceived::EndOfStream(_, end) => ( diff --git a/beacon_node/lighthouse_network/src/rpc/outbound.rs b/beacon_node/lighthouse_network/src/rpc/outbound.rs index 2bfa42ccac..b614313a84 100644 --- a/beacon_node/lighthouse_network/src/rpc/outbound.rs +++ b/beacon_node/lighthouse_network/src/rpc/outbound.rs @@ -1,7 +1,6 @@ -use super::methods::*; use super::protocol::ProtocolId; -use super::protocol::SupportedProtocol; use super::RPCError; +use super::RequestType; use crate::rpc::codec::SSZSnappyOutboundCodec; use crate::rpc::protocol::Encoding; use futures::future::BoxFuture; @@ -21,25 +20,11 @@ use types::{EthSpec, ForkContext}; #[derive(Debug, Clone)] pub struct OutboundRequestContainer { - pub req: OutboundRequest, + pub req: RequestType, pub fork_context: Arc, pub max_rpc_size: usize, } -#[derive(Debug, Clone, PartialEq)] -pub enum OutboundRequest { - Status(StatusMessage), - Goodbye(GoodbyeReason), - BlocksByRange(OldBlocksByRangeRequest), - BlocksByRoot(BlocksByRootRequest), - BlobsByRange(BlobsByRangeRequest), - BlobsByRoot(BlobsByRootRequest), - DataColumnsByRoot(DataColumnsByRootRequest), - DataColumnsByRange(DataColumnsByRangeRequest), - Ping(Ping), - MetaData(MetadataRequest), -} - impl UpgradeInfo for OutboundRequestContainer { type Info = ProtocolId; type InfoIter = Vec; @@ -50,133 +35,6 @@ impl UpgradeInfo for OutboundRequestContainer { } } -/// Implements the encoding per supported protocol for `RPCRequest`. -impl OutboundRequest { - pub fn supported_protocols(&self) -> Vec { - match self { - // add more protocols when versions/encodings are supported - OutboundRequest::Status(_) => vec![ProtocolId::new( - SupportedProtocol::StatusV1, - Encoding::SSZSnappy, - )], - OutboundRequest::Goodbye(_) => vec![ProtocolId::new( - SupportedProtocol::GoodbyeV1, - Encoding::SSZSnappy, - )], - OutboundRequest::BlocksByRange(_) => vec![ - ProtocolId::new(SupportedProtocol::BlocksByRangeV2, Encoding::SSZSnappy), - ProtocolId::new(SupportedProtocol::BlocksByRangeV1, Encoding::SSZSnappy), - ], - OutboundRequest::BlocksByRoot(_) => vec![ - ProtocolId::new(SupportedProtocol::BlocksByRootV2, Encoding::SSZSnappy), - ProtocolId::new(SupportedProtocol::BlocksByRootV1, Encoding::SSZSnappy), - ], - OutboundRequest::BlobsByRange(_) => vec![ProtocolId::new( - SupportedProtocol::BlobsByRangeV1, - Encoding::SSZSnappy, - )], - OutboundRequest::BlobsByRoot(_) => vec![ProtocolId::new( - SupportedProtocol::BlobsByRootV1, - Encoding::SSZSnappy, - )], - OutboundRequest::DataColumnsByRoot(_) => vec![ProtocolId::new( - SupportedProtocol::DataColumnsByRootV1, - Encoding::SSZSnappy, - )], - OutboundRequest::DataColumnsByRange(_) => vec![ProtocolId::new( - SupportedProtocol::DataColumnsByRangeV1, - Encoding::SSZSnappy, - )], - OutboundRequest::Ping(_) => vec![ProtocolId::new( - SupportedProtocol::PingV1, - Encoding::SSZSnappy, - )], - OutboundRequest::MetaData(_) => vec![ - ProtocolId::new(SupportedProtocol::MetaDataV3, Encoding::SSZSnappy), - ProtocolId::new(SupportedProtocol::MetaDataV2, Encoding::SSZSnappy), - ProtocolId::new(SupportedProtocol::MetaDataV1, Encoding::SSZSnappy), - ], - } - } - /* These functions are used in the handler for stream management */ - - /// Maximum number of responses expected for this request. - pub fn max_responses(&self) -> u64 { - match self { - OutboundRequest::Status(_) => 1, - OutboundRequest::Goodbye(_) => 0, - OutboundRequest::BlocksByRange(req) => *req.count(), - OutboundRequest::BlocksByRoot(req) => req.block_roots().len() as u64, - OutboundRequest::BlobsByRange(req) => req.max_blobs_requested::(), - OutboundRequest::BlobsByRoot(req) => req.blob_ids.len() as u64, - OutboundRequest::DataColumnsByRoot(req) => req.data_column_ids.len() as u64, - OutboundRequest::DataColumnsByRange(req) => req.max_requested::(), - OutboundRequest::Ping(_) => 1, - OutboundRequest::MetaData(_) => 1, - } - } - - pub fn expect_exactly_one_response(&self) -> bool { - match self { - OutboundRequest::Status(_) => true, - OutboundRequest::Goodbye(_) => false, - OutboundRequest::BlocksByRange(_) => false, - OutboundRequest::BlocksByRoot(_) => false, - OutboundRequest::BlobsByRange(_) => false, - OutboundRequest::BlobsByRoot(_) => false, - OutboundRequest::DataColumnsByRoot(_) => false, - OutboundRequest::DataColumnsByRange(_) => false, - OutboundRequest::Ping(_) => true, - OutboundRequest::MetaData(_) => true, - } - } - - /// Gives the corresponding `SupportedProtocol` to this request. - pub fn versioned_protocol(&self) -> SupportedProtocol { - match self { - OutboundRequest::Status(_) => SupportedProtocol::StatusV1, - OutboundRequest::Goodbye(_) => SupportedProtocol::GoodbyeV1, - OutboundRequest::BlocksByRange(req) => match req { - OldBlocksByRangeRequest::V1(_) => SupportedProtocol::BlocksByRangeV1, - OldBlocksByRangeRequest::V2(_) => SupportedProtocol::BlocksByRangeV2, - }, - OutboundRequest::BlocksByRoot(req) => match req { - BlocksByRootRequest::V1(_) => SupportedProtocol::BlocksByRootV1, - BlocksByRootRequest::V2(_) => SupportedProtocol::BlocksByRootV2, - }, - OutboundRequest::BlobsByRange(_) => SupportedProtocol::BlobsByRangeV1, - OutboundRequest::BlobsByRoot(_) => SupportedProtocol::BlobsByRootV1, - OutboundRequest::DataColumnsByRoot(_) => SupportedProtocol::DataColumnsByRootV1, - OutboundRequest::DataColumnsByRange(_) => SupportedProtocol::DataColumnsByRangeV1, - OutboundRequest::Ping(_) => SupportedProtocol::PingV1, - OutboundRequest::MetaData(req) => match req { - MetadataRequest::V1(_) => SupportedProtocol::MetaDataV1, - MetadataRequest::V2(_) => SupportedProtocol::MetaDataV2, - MetadataRequest::V3(_) => SupportedProtocol::MetaDataV3, - }, - } - } - - /// Returns the `ResponseTermination` type associated with the request if a stream gets - /// terminated. - pub fn stream_termination(&self) -> ResponseTermination { - match self { - // this only gets called after `multiple_responses()` returns true. Therefore, only - // variants that have `multiple_responses()` can have values. - OutboundRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange, - OutboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot, - OutboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange, - OutboundRequest::BlobsByRoot(_) => ResponseTermination::BlobsByRoot, - OutboundRequest::DataColumnsByRoot(_) => ResponseTermination::DataColumnsByRoot, - OutboundRequest::DataColumnsByRange(_) => ResponseTermination::DataColumnsByRange, - OutboundRequest::Status(_) => unreachable!(), - OutboundRequest::Goodbye(_) => unreachable!(), - OutboundRequest::Ping(_) => unreachable!(), - OutboundRequest::MetaData(_) => unreachable!(), - } - } -} - /* RPC Response type - used for outbound upgrades */ /* Outbound upgrades */ @@ -211,22 +69,3 @@ where .boxed() } } - -impl std::fmt::Display for OutboundRequest { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - OutboundRequest::Status(status) => write!(f, "Status Message: {}", status), - OutboundRequest::Goodbye(reason) => write!(f, "Goodbye: {}", reason), - OutboundRequest::BlocksByRange(req) => write!(f, "Blocks by range: {}", req), - OutboundRequest::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req), - OutboundRequest::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req), - OutboundRequest::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req), - OutboundRequest::DataColumnsByRoot(req) => write!(f, "Data columns by root: {:?}", req), - OutboundRequest::DataColumnsByRange(req) => { - write!(f, "Data columns by range: {:?}", req) - } - OutboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data), - OutboundRequest::MetaData(_) => write!(f, "MetaData request"), - } - } -} diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index 09a18e5de6..3f78d35f5c 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -645,7 +645,7 @@ pub fn rpc_data_column_limits() -> RpcLimits { // The inbound protocol reads the request, decodes it and returns the stream to the protocol // handler to respond to once ready. -pub type InboundOutput = (InboundRequest, InboundFramed); +pub type InboundOutput = (RequestType, InboundFramed); pub type InboundFramed = Framed>>>, SSZSnappyInboundCodec>; @@ -679,19 +679,19 @@ where // MetaData requests should be empty, return the stream match versioned_protocol { SupportedProtocol::MetaDataV1 => { - Ok((InboundRequest::MetaData(MetadataRequest::new_v1()), socket)) + Ok((RequestType::MetaData(MetadataRequest::new_v1()), socket)) } SupportedProtocol::MetaDataV2 => { - Ok((InboundRequest::MetaData(MetadataRequest::new_v2()), socket)) + Ok((RequestType::MetaData(MetadataRequest::new_v2()), socket)) } SupportedProtocol::MetaDataV3 => { - Ok((InboundRequest::MetaData(MetadataRequest::new_v3()), socket)) + Ok((RequestType::MetaData(MetadataRequest::new_v3()), socket)) } SupportedProtocol::LightClientOptimisticUpdateV1 => { - Ok((InboundRequest::LightClientOptimisticUpdate, socket)) + Ok((RequestType::LightClientOptimisticUpdate, socket)) } SupportedProtocol::LightClientFinalityUpdateV1 => { - Ok((InboundRequest::LightClientFinalityUpdate, socket)) + Ok((RequestType::LightClientFinalityUpdate, socket)) } _ => { match tokio::time::timeout( @@ -713,7 +713,7 @@ where } #[derive(Debug, Clone, PartialEq)] -pub enum InboundRequest { +pub enum RequestType { Status(StatusMessage), Goodbye(GoodbyeReason), BlocksByRange(OldBlocksByRangeRequest), @@ -730,56 +730,56 @@ pub enum InboundRequest { } /// Implements the encoding per supported protocol for `RPCRequest`. -impl InboundRequest { +impl RequestType { /* These functions are used in the handler for stream management */ /// Maximum number of responses expected for this request. pub fn max_responses(&self) -> u64 { match self { - InboundRequest::Status(_) => 1, - InboundRequest::Goodbye(_) => 0, - InboundRequest::BlocksByRange(req) => *req.count(), - InboundRequest::BlocksByRoot(req) => req.block_roots().len() as u64, - InboundRequest::BlobsByRange(req) => req.max_blobs_requested::(), - InboundRequest::BlobsByRoot(req) => req.blob_ids.len() as u64, - InboundRequest::DataColumnsByRoot(req) => req.data_column_ids.len() as u64, - InboundRequest::DataColumnsByRange(req) => req.max_requested::(), - InboundRequest::Ping(_) => 1, - InboundRequest::MetaData(_) => 1, - InboundRequest::LightClientBootstrap(_) => 1, - InboundRequest::LightClientOptimisticUpdate => 1, - InboundRequest::LightClientFinalityUpdate => 1, + RequestType::Status(_) => 1, + RequestType::Goodbye(_) => 0, + RequestType::BlocksByRange(req) => *req.count(), + RequestType::BlocksByRoot(req) => req.block_roots().len() as u64, + RequestType::BlobsByRange(req) => req.max_blobs_requested::(), + RequestType::BlobsByRoot(req) => req.blob_ids.len() as u64, + RequestType::DataColumnsByRoot(req) => req.data_column_ids.len() as u64, + RequestType::DataColumnsByRange(req) => req.max_requested::(), + RequestType::Ping(_) => 1, + RequestType::MetaData(_) => 1, + RequestType::LightClientBootstrap(_) => 1, + RequestType::LightClientOptimisticUpdate => 1, + RequestType::LightClientFinalityUpdate => 1, } } /// Gives the corresponding `SupportedProtocol` to this request. pub fn versioned_protocol(&self) -> SupportedProtocol { match self { - InboundRequest::Status(_) => SupportedProtocol::StatusV1, - InboundRequest::Goodbye(_) => SupportedProtocol::GoodbyeV1, - InboundRequest::BlocksByRange(req) => match req { + RequestType::Status(_) => SupportedProtocol::StatusV1, + RequestType::Goodbye(_) => SupportedProtocol::GoodbyeV1, + RequestType::BlocksByRange(req) => match req { OldBlocksByRangeRequest::V1(_) => SupportedProtocol::BlocksByRangeV1, OldBlocksByRangeRequest::V2(_) => SupportedProtocol::BlocksByRangeV2, }, - InboundRequest::BlocksByRoot(req) => match req { + RequestType::BlocksByRoot(req) => match req { BlocksByRootRequest::V1(_) => SupportedProtocol::BlocksByRootV1, BlocksByRootRequest::V2(_) => SupportedProtocol::BlocksByRootV2, }, - InboundRequest::BlobsByRange(_) => SupportedProtocol::BlobsByRangeV1, - InboundRequest::BlobsByRoot(_) => SupportedProtocol::BlobsByRootV1, - InboundRequest::DataColumnsByRoot(_) => SupportedProtocol::DataColumnsByRootV1, - InboundRequest::DataColumnsByRange(_) => SupportedProtocol::DataColumnsByRangeV1, - InboundRequest::Ping(_) => SupportedProtocol::PingV1, - InboundRequest::MetaData(req) => match req { + RequestType::BlobsByRange(_) => SupportedProtocol::BlobsByRangeV1, + RequestType::BlobsByRoot(_) => SupportedProtocol::BlobsByRootV1, + RequestType::DataColumnsByRoot(_) => SupportedProtocol::DataColumnsByRootV1, + RequestType::DataColumnsByRange(_) => SupportedProtocol::DataColumnsByRangeV1, + RequestType::Ping(_) => SupportedProtocol::PingV1, + RequestType::MetaData(req) => match req { MetadataRequest::V1(_) => SupportedProtocol::MetaDataV1, MetadataRequest::V2(_) => SupportedProtocol::MetaDataV2, MetadataRequest::V3(_) => SupportedProtocol::MetaDataV3, }, - InboundRequest::LightClientBootstrap(_) => SupportedProtocol::LightClientBootstrapV1, - InboundRequest::LightClientOptimisticUpdate => { + RequestType::LightClientBootstrap(_) => SupportedProtocol::LightClientBootstrapV1, + RequestType::LightClientOptimisticUpdate => { SupportedProtocol::LightClientOptimisticUpdateV1 } - InboundRequest::LightClientFinalityUpdate => { + RequestType::LightClientFinalityUpdate => { SupportedProtocol::LightClientFinalityUpdateV1 } } @@ -791,19 +791,96 @@ impl InboundRequest { match self { // this only gets called after `multiple_responses()` returns true. Therefore, only // variants that have `multiple_responses()` can have values. - InboundRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange, - InboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot, - InboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange, - InboundRequest::BlobsByRoot(_) => ResponseTermination::BlobsByRoot, - InboundRequest::DataColumnsByRoot(_) => ResponseTermination::DataColumnsByRoot, - InboundRequest::DataColumnsByRange(_) => ResponseTermination::DataColumnsByRange, - InboundRequest::Status(_) => unreachable!(), - InboundRequest::Goodbye(_) => unreachable!(), - InboundRequest::Ping(_) => unreachable!(), - InboundRequest::MetaData(_) => unreachable!(), - InboundRequest::LightClientBootstrap(_) => unreachable!(), - InboundRequest::LightClientFinalityUpdate => unreachable!(), - InboundRequest::LightClientOptimisticUpdate => unreachable!(), + RequestType::BlocksByRange(_) => ResponseTermination::BlocksByRange, + RequestType::BlocksByRoot(_) => ResponseTermination::BlocksByRoot, + RequestType::BlobsByRange(_) => ResponseTermination::BlobsByRange, + RequestType::BlobsByRoot(_) => ResponseTermination::BlobsByRoot, + RequestType::DataColumnsByRoot(_) => ResponseTermination::DataColumnsByRoot, + RequestType::DataColumnsByRange(_) => ResponseTermination::DataColumnsByRange, + RequestType::Status(_) => unreachable!(), + RequestType::Goodbye(_) => unreachable!(), + RequestType::Ping(_) => unreachable!(), + RequestType::MetaData(_) => unreachable!(), + RequestType::LightClientBootstrap(_) => unreachable!(), + RequestType::LightClientFinalityUpdate => unreachable!(), + RequestType::LightClientOptimisticUpdate => unreachable!(), + } + } + + pub fn supported_protocols(&self) -> Vec { + match self { + // add more protocols when versions/encodings are supported + RequestType::Status(_) => vec![ProtocolId::new( + SupportedProtocol::StatusV1, + Encoding::SSZSnappy, + )], + RequestType::Goodbye(_) => vec![ProtocolId::new( + SupportedProtocol::GoodbyeV1, + Encoding::SSZSnappy, + )], + RequestType::BlocksByRange(_) => vec![ + ProtocolId::new(SupportedProtocol::BlocksByRangeV2, Encoding::SSZSnappy), + ProtocolId::new(SupportedProtocol::BlocksByRangeV1, Encoding::SSZSnappy), + ], + RequestType::BlocksByRoot(_) => vec![ + ProtocolId::new(SupportedProtocol::BlocksByRootV2, Encoding::SSZSnappy), + ProtocolId::new(SupportedProtocol::BlocksByRootV1, Encoding::SSZSnappy), + ], + RequestType::BlobsByRange(_) => vec![ProtocolId::new( + SupportedProtocol::BlobsByRangeV1, + Encoding::SSZSnappy, + )], + RequestType::BlobsByRoot(_) => vec![ProtocolId::new( + SupportedProtocol::BlobsByRootV1, + Encoding::SSZSnappy, + )], + RequestType::DataColumnsByRoot(_) => vec![ProtocolId::new( + SupportedProtocol::DataColumnsByRootV1, + Encoding::SSZSnappy, + )], + RequestType::DataColumnsByRange(_) => vec![ProtocolId::new( + SupportedProtocol::DataColumnsByRangeV1, + Encoding::SSZSnappy, + )], + RequestType::Ping(_) => vec![ProtocolId::new( + SupportedProtocol::PingV1, + Encoding::SSZSnappy, + )], + RequestType::MetaData(_) => vec![ + ProtocolId::new(SupportedProtocol::MetaDataV3, Encoding::SSZSnappy), + ProtocolId::new(SupportedProtocol::MetaDataV2, Encoding::SSZSnappy), + ProtocolId::new(SupportedProtocol::MetaDataV1, Encoding::SSZSnappy), + ], + RequestType::LightClientBootstrap(_) => vec![ProtocolId::new( + SupportedProtocol::LightClientBootstrapV1, + Encoding::SSZSnappy, + )], + RequestType::LightClientOptimisticUpdate => vec![ProtocolId::new( + SupportedProtocol::LightClientOptimisticUpdateV1, + Encoding::SSZSnappy, + )], + RequestType::LightClientFinalityUpdate => vec![ProtocolId::new( + SupportedProtocol::LightClientFinalityUpdateV1, + Encoding::SSZSnappy, + )], + } + } + + pub fn expect_exactly_one_response(&self) -> bool { + match self { + RequestType::Status(_) => true, + RequestType::Goodbye(_) => false, + RequestType::BlocksByRange(_) => false, + RequestType::BlocksByRoot(_) => false, + RequestType::BlobsByRange(_) => false, + RequestType::BlobsByRoot(_) => false, + RequestType::DataColumnsByRoot(_) => false, + RequestType::DataColumnsByRange(_) => false, + RequestType::Ping(_) => true, + RequestType::MetaData(_) => true, + RequestType::LightClientBootstrap(_) => true, + RequestType::LightClientOptimisticUpdate => true, + RequestType::LightClientFinalityUpdate => true, } } } @@ -819,7 +896,7 @@ pub enum RPCError { /// IO Error. IoError(String), /// The peer returned a valid response but the response indicated an error. - ErrorResponse(RPCResponseErrorCode, String), + ErrorResponse(RpcErrorResponse, String), /// Timed out waiting for a response. StreamTimeout, /// Peer does not support the protocol. @@ -898,28 +975,28 @@ impl std::error::Error for RPCError { } } -impl std::fmt::Display for InboundRequest { +impl std::fmt::Display for RequestType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - InboundRequest::Status(status) => write!(f, "Status Message: {}", status), - InboundRequest::Goodbye(reason) => write!(f, "Goodbye: {}", reason), - InboundRequest::BlocksByRange(req) => write!(f, "Blocks by range: {}", req), - InboundRequest::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req), - InboundRequest::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req), - InboundRequest::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req), - InboundRequest::DataColumnsByRoot(req) => write!(f, "Data columns by root: {:?}", req), - InboundRequest::DataColumnsByRange(req) => { + RequestType::Status(status) => write!(f, "Status Message: {}", status), + RequestType::Goodbye(reason) => write!(f, "Goodbye: {}", reason), + RequestType::BlocksByRange(req) => write!(f, "Blocks by range: {}", req), + RequestType::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req), + RequestType::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req), + RequestType::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req), + RequestType::DataColumnsByRoot(req) => write!(f, "Data columns by root: {:?}", req), + RequestType::DataColumnsByRange(req) => { write!(f, "Data columns by range: {:?}", req) } - InboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data), - InboundRequest::MetaData(_) => write!(f, "MetaData request"), - InboundRequest::LightClientBootstrap(bootstrap) => { + RequestType::Ping(ping) => write!(f, "Ping: {}", ping.data), + RequestType::MetaData(_) => write!(f, "MetaData request"), + RequestType::LightClientBootstrap(bootstrap) => { write!(f, "Light client boostrap: {}", bootstrap.root) } - InboundRequest::LightClientOptimisticUpdate => { + RequestType::LightClientOptimisticUpdate => { write!(f, "Light client optimistic update request") } - InboundRequest::LightClientFinalityUpdate => { + RequestType::LightClientFinalityUpdate => { write!(f, "Light client finality update request") } } diff --git a/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs b/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs index 523b891a00..a8e8f45b6f 100644 --- a/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs +++ b/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs @@ -252,7 +252,7 @@ pub trait RateLimiterItem { fn max_responses(&self) -> u64; } -impl RateLimiterItem for super::InboundRequest { +impl RateLimiterItem for super::RequestType { fn protocol(&self) -> Protocol { self.versioned_protocol().protocol() } @@ -262,15 +262,6 @@ impl RateLimiterItem for super::InboundRequest { } } -impl RateLimiterItem for super::OutboundRequest { - fn protocol(&self) -> Protocol { - self.versioned_protocol().protocol() - } - - fn max_responses(&self) -> u64 { - self.max_responses() - } -} impl RPCRateLimiter { pub fn new_with_config(config: RateLimiterConfig) -> Result { // Destructure to make sure every configuration value is used. diff --git a/beacon_node/lighthouse_network/src/rpc/self_limiter.rs b/beacon_node/lighthouse_network/src/rpc/self_limiter.rs index 77caecb16d..e968ad11e3 100644 --- a/beacon_node/lighthouse_network/src/rpc/self_limiter.rs +++ b/beacon_node/lighthouse_network/src/rpc/self_limiter.rs @@ -14,13 +14,13 @@ use types::EthSpec; use super::{ config::OutboundRateLimiterConfig, rate_limiter::{RPCRateLimiter as RateLimiter, RateLimitedErr}, - BehaviourAction, OutboundRequest, Protocol, RPCSend, ReqId, + BehaviourAction, Protocol, RPCSend, ReqId, RequestType, }; /// A request that was rate limited or waiting on rate limited requests for the same peer and /// protocol. struct QueuedRequest { - req: OutboundRequest, + req: RequestType, request_id: Id, } @@ -70,7 +70,7 @@ impl SelfRateLimiter { &mut self, peer_id: PeerId, request_id: Id, - req: OutboundRequest, + req: RequestType, ) -> Result, Error> { let protocol = req.versioned_protocol().protocol(); // First check that there are not already other requests waiting to be sent. @@ -101,7 +101,7 @@ impl SelfRateLimiter { limiter: &mut RateLimiter, peer_id: PeerId, request_id: Id, - req: OutboundRequest, + req: RequestType, log: &Logger, ) -> Result, (QueuedRequest, Duration)> { match limiter.allows(&peer_id, &req) { @@ -211,7 +211,7 @@ mod tests { use crate::rpc::config::{OutboundRateLimiterConfig, RateLimiterConfig}; use crate::rpc::rate_limiter::Quota; use crate::rpc::self_limiter::SelfRateLimiter; - use crate::rpc::{OutboundRequest, Ping, Protocol}; + use crate::rpc::{Ping, Protocol, RequestType}; use crate::service::api_types::{AppRequestId, RequestId, SyncRequestId}; use libp2p::PeerId; use std::time::Duration; @@ -235,7 +235,7 @@ mod tests { RequestId::Application(AppRequestId::Sync(SyncRequestId::RangeBlockAndBlobs { id: i, })), - OutboundRequest::Ping(Ping { data: i as u64 }), + RequestType::Ping(Ping { data: i as u64 }), ); } diff --git a/beacon_node/lighthouse_network/src/service/api_types.rs b/beacon_node/lighthouse_network/src/service/api_types.rs index 30400db3b6..e57e846c33 100644 --- a/beacon_node/lighthouse_network/src/service/api_types.rs +++ b/beacon_node/lighthouse_network/src/service/api_types.rs @@ -6,16 +6,9 @@ use types::{ LightClientFinalityUpdate, LightClientOptimisticUpdate, SignedBeaconBlock, }; -use crate::rpc::methods::{ - BlobsByRangeRequest, BlobsByRootRequest, DataColumnsByRangeRequest, DataColumnsByRootRequest, -}; use crate::rpc::{ - methods::{ - BlocksByRangeRequest, BlocksByRootRequest, LightClientBootstrapRequest, - OldBlocksByRangeRequest, OldBlocksByRangeRequestV1, OldBlocksByRangeRequestV2, - RPCCodedResponse, RPCResponse, ResponseTermination, StatusMessage, - }, - OutboundRequest, SubstreamId, + methods::{ResponseTermination, RpcResponse, RpcSuccessResponse, StatusMessage}, + SubstreamId, }; /// Identifier of requests sent by a peer. @@ -93,69 +86,6 @@ pub enum RequestId { Internal, } -/// The type of RPC requests the Behaviour informs it has received and allows for sending. -/// -// NOTE: This is an application-level wrapper over the lower network level requests that can be -// sent. The main difference is the absence of the Ping, Metadata and Goodbye protocols, which don't -// leave the Behaviour. For all protocols managed by RPC see `RPCRequest`. -#[derive(Debug, Clone, PartialEq)] -pub enum Request { - /// A Status message. - Status(StatusMessage), - /// A blocks by range request. - BlocksByRange(BlocksByRangeRequest), - /// A blobs by range request. - BlobsByRange(BlobsByRangeRequest), - /// A request blocks root request. - BlocksByRoot(BlocksByRootRequest), - // light client bootstrap request - LightClientBootstrap(LightClientBootstrapRequest), - // light client optimistic update request - LightClientOptimisticUpdate, - // light client finality update request - LightClientFinalityUpdate, - /// A request blobs root request. - BlobsByRoot(BlobsByRootRequest), - /// A request data columns root request. - DataColumnsByRoot(DataColumnsByRootRequest), - /// A request data columns by range request. - DataColumnsByRange(DataColumnsByRangeRequest), -} - -impl std::convert::From for OutboundRequest { - fn from(req: Request) -> OutboundRequest { - match req { - Request::BlocksByRoot(r) => OutboundRequest::BlocksByRoot(r), - Request::BlocksByRange(r) => match r { - BlocksByRangeRequest::V1(req) => OutboundRequest::BlocksByRange( - OldBlocksByRangeRequest::V1(OldBlocksByRangeRequestV1 { - start_slot: req.start_slot, - count: req.count, - step: 1, - }), - ), - BlocksByRangeRequest::V2(req) => OutboundRequest::BlocksByRange( - OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2 { - start_slot: req.start_slot, - count: req.count, - step: 1, - }), - ), - }, - Request::LightClientBootstrap(_) - | Request::LightClientOptimisticUpdate - | Request::LightClientFinalityUpdate => { - unreachable!("Lighthouse never makes an outbound light client request") - } - Request::BlobsByRange(r) => OutboundRequest::BlobsByRange(r), - Request::BlobsByRoot(r) => OutboundRequest::BlobsByRoot(r), - Request::DataColumnsByRoot(r) => OutboundRequest::DataColumnsByRoot(r), - Request::DataColumnsByRange(r) => OutboundRequest::DataColumnsByRange(r), - Request::Status(s) => OutboundRequest::Status(s), - } - } -} - /// The type of RPC responses the Behaviour informs it has received, and allows for sending. /// // NOTE: This is an application-level wrapper over the lower network level responses that can be @@ -186,44 +116,42 @@ pub enum Response { LightClientFinalityUpdate(Arc>), } -impl std::convert::From> for RPCCodedResponse { - fn from(resp: Response) -> RPCCodedResponse { +impl std::convert::From> for RpcResponse { + fn from(resp: Response) -> RpcResponse { match resp { Response::BlocksByRoot(r) => match r { - Some(b) => RPCCodedResponse::Success(RPCResponse::BlocksByRoot(b)), - None => RPCCodedResponse::StreamTermination(ResponseTermination::BlocksByRoot), + Some(b) => RpcResponse::Success(RpcSuccessResponse::BlocksByRoot(b)), + None => RpcResponse::StreamTermination(ResponseTermination::BlocksByRoot), }, Response::BlocksByRange(r) => match r { - Some(b) => RPCCodedResponse::Success(RPCResponse::BlocksByRange(b)), - None => RPCCodedResponse::StreamTermination(ResponseTermination::BlocksByRange), + Some(b) => RpcResponse::Success(RpcSuccessResponse::BlocksByRange(b)), + None => RpcResponse::StreamTermination(ResponseTermination::BlocksByRange), }, Response::BlobsByRoot(r) => match r { - Some(b) => RPCCodedResponse::Success(RPCResponse::BlobsByRoot(b)), - None => RPCCodedResponse::StreamTermination(ResponseTermination::BlobsByRoot), + Some(b) => RpcResponse::Success(RpcSuccessResponse::BlobsByRoot(b)), + None => RpcResponse::StreamTermination(ResponseTermination::BlobsByRoot), }, Response::BlobsByRange(r) => match r { - Some(b) => RPCCodedResponse::Success(RPCResponse::BlobsByRange(b)), - None => RPCCodedResponse::StreamTermination(ResponseTermination::BlobsByRange), + Some(b) => RpcResponse::Success(RpcSuccessResponse::BlobsByRange(b)), + None => RpcResponse::StreamTermination(ResponseTermination::BlobsByRange), }, Response::DataColumnsByRoot(r) => match r { - Some(d) => RPCCodedResponse::Success(RPCResponse::DataColumnsByRoot(d)), - None => RPCCodedResponse::StreamTermination(ResponseTermination::DataColumnsByRoot), + Some(d) => RpcResponse::Success(RpcSuccessResponse::DataColumnsByRoot(d)), + None => RpcResponse::StreamTermination(ResponseTermination::DataColumnsByRoot), }, Response::DataColumnsByRange(r) => match r { - Some(d) => RPCCodedResponse::Success(RPCResponse::DataColumnsByRange(d)), - None => { - RPCCodedResponse::StreamTermination(ResponseTermination::DataColumnsByRange) - } + Some(d) => RpcResponse::Success(RpcSuccessResponse::DataColumnsByRange(d)), + None => RpcResponse::StreamTermination(ResponseTermination::DataColumnsByRange), }, - Response::Status(s) => RPCCodedResponse::Success(RPCResponse::Status(s)), + Response::Status(s) => RpcResponse::Success(RpcSuccessResponse::Status(s)), Response::LightClientBootstrap(b) => { - RPCCodedResponse::Success(RPCResponse::LightClientBootstrap(b)) + RpcResponse::Success(RpcSuccessResponse::LightClientBootstrap(b)) } Response::LightClientOptimisticUpdate(o) => { - RPCCodedResponse::Success(RPCResponse::LightClientOptimisticUpdate(o)) + RpcResponse::Success(RpcSuccessResponse::LightClientOptimisticUpdate(o)) } Response::LightClientFinalityUpdate(f) => { - RPCCodedResponse::Success(RPCResponse::LightClientFinalityUpdate(f)) + RpcResponse::Success(RpcSuccessResponse::LightClientFinalityUpdate(f)) } } } diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index ede8fdd13a..4cf59e15e1 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -11,9 +11,8 @@ use crate::peer_manager::{ use crate::peer_manager::{MIN_OUTBOUND_ONLY_FACTOR, PEER_EXCESS_FACTOR, PRIORITY_PEER_EXCESS}; use crate::rpc::methods::MetadataRequest; use crate::rpc::{ - methods, BlocksByRangeRequest, GoodbyeReason, HandlerErr, InboundRequest, NetworkParams, - OutboundRequest, Protocol, RPCCodedResponse, RPCError, RPCMessage, RPCReceived, RPCResponse, - RPCResponseErrorCode, ResponseTermination, RPC, + self, GoodbyeReason, HandlerErr, NetworkParams, Protocol, RPCError, RPCMessage, RPCReceived, + RequestType, ResponseTermination, RpcErrorResponse, RpcResponse, RpcSuccessResponse, RPC, }; use crate::service::behaviour::BehaviourEvent; pub use crate::service::behaviour::Gossipsub; @@ -25,7 +24,7 @@ use crate::types::{ use crate::EnrExt; use crate::Eth2Enr; use crate::{error, metrics, Enr, NetworkGlobals, PubsubMessage, TopicHash}; -use api_types::{AppRequestId, PeerRequestId, Request, RequestId, Response}; +use api_types::{AppRequestId, PeerRequestId, RequestId, Response}; use futures::stream::StreamExt; use gossipsub::{ IdentTopic as Topic, MessageAcceptance, MessageAuthenticity, MessageId, PublishError, @@ -84,7 +83,7 @@ pub enum NetworkEvent { /// Identifier of the request. All responses to this request must use this id. id: PeerRequestId, /// Request the peer sent. - request: Request, + request: rpc::Request, }, ResponseReceived { /// Peer that sent the response. @@ -934,25 +933,28 @@ impl Network { &mut self, peer_id: PeerId, request_id: AppRequestId, - request: Request, + request: RequestType, ) -> Result<(), (AppRequestId, RPCError)> { // Check if the peer is connected before sending an RPC request if !self.swarm.is_connected(&peer_id) { return Err((request_id, RPCError::Disconnected)); } - self.eth2_rpc_mut().send_request( - peer_id, - RequestId::Application(request_id), - request.into(), - ); + self.eth2_rpc_mut() + .send_request(peer_id, RequestId::Application(request_id), request); Ok(()) } /// Send a successful response to a peer over RPC. - pub fn send_response(&mut self, peer_id: PeerId, id: PeerRequestId, response: Response) { + pub fn send_response( + &mut self, + peer_id: PeerId, + id: PeerRequestId, + request_id: rpc::RequestId, + response: Response, + ) { self.eth2_rpc_mut() - .send_response(peer_id, id, response.into()) + .send_response(peer_id, id, request_id, response.into()) } /// Inform the peer that their request produced an error. @@ -960,13 +962,15 @@ impl Network { &mut self, peer_id: PeerId, id: PeerRequestId, - error: RPCResponseErrorCode, + request_id: rpc::RequestId, + error: RpcErrorResponse, reason: String, ) { self.eth2_rpc_mut().send_response( peer_id, id, - RPCCodedResponse::Error(error, reason.into()), + request_id, + RpcResponse::Error(error, reason.into()), ) } @@ -1130,10 +1134,10 @@ impl Network { let event = if self.fork_context.spec.is_peer_das_scheduled() { // Nodes with higher custody will probably start advertising it // before peerdas is activated - OutboundRequest::MetaData(MetadataRequest::new_v3()) + RequestType::MetaData(MetadataRequest::new_v3()) } else { // We always prefer sending V2 requests otherwise - OutboundRequest::MetaData(MetadataRequest::new_v2()) + RequestType::MetaData(MetadataRequest::new_v2()) }; self.eth2_rpc_mut() .send_request(peer_id, RequestId::Internal, event); @@ -1144,12 +1148,14 @@ impl Network { &mut self, _req: MetadataRequest, id: PeerRequestId, + request_id: rpc::RequestId, peer_id: PeerId, ) { let metadata = self.network_globals.local_metadata.read().clone(); // The encoder is responsible for sending the negotiated version of the metadata - let event = RPCCodedResponse::Success(RPCResponse::MetaData(metadata)); - self.eth2_rpc_mut().send_response(peer_id, id, event); + let event = RpcResponse::Success(RpcSuccessResponse::MetaData(metadata)); + self.eth2_rpc_mut() + .send_response(peer_id, id, request_id, event); } // RPC Propagation methods @@ -1171,56 +1177,6 @@ impl Network { } } - /// Convenience function to propagate a request. - #[must_use = "actually return the event"] - fn build_request( - &mut self, - id: PeerRequestId, - peer_id: PeerId, - request: Request, - ) -> NetworkEvent { - // Increment metrics - match &request { - 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::LightClientOptimisticUpdate => metrics::inc_counter_vec( - &metrics::TOTAL_RPC_REQUESTS, - &["light_client_optimistic_update"], - ), - Request::LightClientFinalityUpdate => metrics::inc_counter_vec( - &metrics::TOTAL_RPC_REQUESTS, - &["light_client_finality_update"], - ), - Request::BlocksByRange { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blocks_by_range"]) - } - Request::BlocksByRoot { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blocks_by_root"]) - } - Request::BlobsByRange { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blobs_by_range"]) - } - Request::BlobsByRoot { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blobs_by_root"]) - } - Request::DataColumnsByRoot { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["data_columns_by_root"]) - } - Request::DataColumnsByRange { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["data_columns_by_range"]) - } - } - NetworkEvent::RequestReceived { - peer_id, - id, - request, - } - } - /// Dial cached Enrs in discovery service that are in the given `subnet_id` and aren't /// in Connected, Dialing or Banned state. fn dial_cached_enrs_in_subnet(&mut self, subnet: Subnet, spec: Arc) { @@ -1406,7 +1362,7 @@ impl Network { return None; } - let handler_id = event.conn_id; + let connection_id = event.conn_id; // The METADATA and PING RPC responses are handled within the behaviour and not propagated match event.message { Err(handler_err) => { @@ -1444,21 +1400,25 @@ impl Network { } } } - Ok(RPCReceived::Request(id, request)) => { - let peer_request_id = (handler_id, id); - match request { + Ok(RPCReceived::Request(request)) => { + match request.r#type { /* Behaviour managed protocols: Ping and Metadata */ - InboundRequest::Ping(ping) => { + RequestType::Ping(ping) => { // inform the peer manager and send the response self.peer_manager_mut().ping_request(&peer_id, ping.data); None } - InboundRequest::MetaData(req) => { + RequestType::MetaData(req) => { // send the requested meta-data - self.send_meta_data_response(req, (handler_id, id), peer_id); + self.send_meta_data_response( + req, + (connection_id, request.substream_id), + request.id, + peer_id, + ); None } - InboundRequest::Goodbye(reason) => { + RequestType::Goodbye(reason) => { // queue for disconnection without a goodbye message debug!( self.log, "Peer sent Goodbye"; @@ -1473,17 +1433,19 @@ impl Network { None } /* Protocols propagated to the Network */ - InboundRequest::Status(msg) => { + RequestType::Status(_) => { // inform the peer manager that we have received a status from a peer self.peer_manager_mut().peer_statusd(&peer_id); + metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["status"]); // propagate the STATUS message upwards - let event = - self.build_request(peer_request_id, peer_id, Request::Status(msg)); - Some(event) + Some(NetworkEvent::RequestReceived { + peer_id, + id: (connection_id, request.substream_id), + request, + }) } - InboundRequest::BlocksByRange(req) => { + RequestType::BlocksByRange(ref req) => { // Still disconnect the peer if the request is naughty. - let mut count = *req.count(); if *req.step() == 0 { self.peer_manager_mut().handle_rpc_error( &peer_id, @@ -1495,131 +1457,144 @@ impl Network { ); return None; } - // return just one block in case the step parameter is used. https://github.com/ethereum/consensus-specs/pull/2856 - if *req.step() > 1 { - count = 1; - } - let request = match req { - methods::OldBlocksByRangeRequest::V1(req) => Request::BlocksByRange( - BlocksByRangeRequest::new_v1(req.start_slot, count), - ), - methods::OldBlocksByRangeRequest::V2(req) => Request::BlocksByRange( - BlocksByRangeRequest::new(req.start_slot, count), - ), - }; - let event = self.build_request(peer_request_id, peer_id, request); - Some(event) - } - InboundRequest::BlocksByRoot(req) => { - let event = self.build_request( - peer_request_id, - peer_id, - Request::BlocksByRoot(req), + metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["blocks_by_range"], ); - Some(event) - } - InboundRequest::BlobsByRange(req) => { - let event = self.build_request( - peer_request_id, + Some(NetworkEvent::RequestReceived { peer_id, - Request::BlobsByRange(req), - ); - Some(event) + id: (connection_id, request.substream_id), + request, + }) } - InboundRequest::BlobsByRoot(req) => { - let event = - self.build_request(peer_request_id, peer_id, Request::BlobsByRoot(req)); - Some(event) - } - InboundRequest::DataColumnsByRoot(req) => { - let event = self.build_request( - peer_request_id, + RequestType::BlocksByRoot(_) => { + metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blocks_by_root"]); + Some(NetworkEvent::RequestReceived { peer_id, - Request::DataColumnsByRoot(req), - ); - Some(event) + id: (connection_id, request.substream_id), + request, + }) } - InboundRequest::DataColumnsByRange(req) => { - let event = self.build_request( - peer_request_id, + RequestType::BlobsByRange(_) => { + metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blobs_by_range"]); + Some(NetworkEvent::RequestReceived { peer_id, - Request::DataColumnsByRange(req), - ); - Some(event) + id: (connection_id, request.substream_id), + request, + }) } - InboundRequest::LightClientBootstrap(req) => { - let event = self.build_request( - peer_request_id, + RequestType::BlobsByRoot(_) => { + metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blobs_by_root"]); + Some(NetworkEvent::RequestReceived { peer_id, - Request::LightClientBootstrap(req), - ); - Some(event) + id: (connection_id, request.substream_id), + request, + }) } - InboundRequest::LightClientOptimisticUpdate => { - let event = self.build_request( - peer_request_id, - peer_id, - Request::LightClientOptimisticUpdate, + RequestType::DataColumnsByRoot(_) => { + metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["data_columns_by_root"], ); - Some(event) + Some(NetworkEvent::RequestReceived { + peer_id, + id: (connection_id, request.substream_id), + request, + }) } - InboundRequest::LightClientFinalityUpdate => { - let event = self.build_request( - peer_request_id, - peer_id, - Request::LightClientFinalityUpdate, + RequestType::DataColumnsByRange(_) => { + metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["data_columns_by_range"], ); - Some(event) + Some(NetworkEvent::RequestReceived { + peer_id, + id: (connection_id, request.substream_id), + request, + }) + } + RequestType::LightClientBootstrap(_) => { + metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["light_client_bootstrap"], + ); + Some(NetworkEvent::RequestReceived { + peer_id, + id: (connection_id, request.substream_id), + request, + }) + } + RequestType::LightClientOptimisticUpdate => { + metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["light_client_optimistic_update"], + ); + Some(NetworkEvent::RequestReceived { + peer_id, + id: (connection_id, request.substream_id), + request, + }) + } + RequestType::LightClientFinalityUpdate => { + metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["light_client_finality_update"], + ); + Some(NetworkEvent::RequestReceived { + peer_id, + id: (connection_id, request.substream_id), + request, + }) } } } Ok(RPCReceived::Response(id, resp)) => { match resp { /* Behaviour managed protocols */ - RPCResponse::Pong(ping) => { + RpcSuccessResponse::Pong(ping) => { self.peer_manager_mut().pong_response(&peer_id, ping.data); None } - RPCResponse::MetaData(meta_data) => { + RpcSuccessResponse::MetaData(meta_data) => { self.peer_manager_mut() .meta_data_response(&peer_id, meta_data); None } /* Network propagated protocols */ - RPCResponse::Status(msg) => { + RpcSuccessResponse::Status(msg) => { // inform the peer manager that we have received a status from a peer self.peer_manager_mut().peer_statusd(&peer_id); // propagate the STATUS message upwards self.build_response(id, peer_id, Response::Status(msg)) } - RPCResponse::BlocksByRange(resp) => { + RpcSuccessResponse::BlocksByRange(resp) => { self.build_response(id, peer_id, Response::BlocksByRange(Some(resp))) } - RPCResponse::BlobsByRange(resp) => { + RpcSuccessResponse::BlobsByRange(resp) => { self.build_response(id, peer_id, Response::BlobsByRange(Some(resp))) } - RPCResponse::BlocksByRoot(resp) => { + RpcSuccessResponse::BlocksByRoot(resp) => { self.build_response(id, peer_id, Response::BlocksByRoot(Some(resp))) } - RPCResponse::BlobsByRoot(resp) => { + RpcSuccessResponse::BlobsByRoot(resp) => { self.build_response(id, peer_id, Response::BlobsByRoot(Some(resp))) } - RPCResponse::DataColumnsByRoot(resp) => { + RpcSuccessResponse::DataColumnsByRoot(resp) => { self.build_response(id, peer_id, Response::DataColumnsByRoot(Some(resp))) } - RPCResponse::DataColumnsByRange(resp) => { + RpcSuccessResponse::DataColumnsByRange(resp) => { self.build_response(id, peer_id, Response::DataColumnsByRange(Some(resp))) } // Should never be reached - RPCResponse::LightClientBootstrap(bootstrap) => { + RpcSuccessResponse::LightClientBootstrap(bootstrap) => { self.build_response(id, peer_id, Response::LightClientBootstrap(bootstrap)) } - RPCResponse::LightClientOptimisticUpdate(update) => self.build_response( + RpcSuccessResponse::LightClientOptimisticUpdate(update) => self.build_response( id, peer_id, Response::LightClientOptimisticUpdate(update), ), - RPCResponse::LightClientFinalityUpdate(update) => self.build_response( + RpcSuccessResponse::LightClientFinalityUpdate(update) => self.build_response( id, peer_id, Response::LightClientFinalityUpdate(update), diff --git a/beacon_node/lighthouse_network/tests/rpc_tests.rs b/beacon_node/lighthouse_network/tests/rpc_tests.rs index 8a0416c1f8..f721c8477c 100644 --- a/beacon_node/lighthouse_network/tests/rpc_tests.rs +++ b/beacon_node/lighthouse_network/tests/rpc_tests.rs @@ -3,9 +3,9 @@ mod common; use common::Protocol; -use lighthouse_network::rpc::methods::*; +use lighthouse_network::rpc::{methods::*, RequestType}; use lighthouse_network::service::api_types::AppRequestId; -use lighthouse_network::{rpc::max_rpc_size, NetworkEvent, ReportSource, Request, Response}; +use lighthouse_network::{rpc::max_rpc_size, NetworkEvent, ReportSource, Response}; use slog::{debug, warn, Level}; use ssz::Encode; use ssz_types::VariableList; @@ -75,7 +75,7 @@ fn test_tcp_status_rpc() { .await; // Dummy STATUS RPC message - let rpc_request = Request::Status(StatusMessage { + let rpc_request = RequestType::Status(StatusMessage { fork_digest: [0; 4], finalized_root: Hash256::zero(), finalized_epoch: Epoch::new(1), @@ -128,10 +128,10 @@ fn test_tcp_status_rpc() { id, request, } => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response debug!(log, "Receiver Received"); - receiver.send_response(peer_id, id, rpc_response.clone()); + receiver.send_response(peer_id, id, request.id, rpc_response.clone()); } } _ => {} // Ignore other events @@ -177,7 +177,12 @@ fn test_tcp_blocks_by_range_chunked_rpc() { .await; // BlocksByRange Request - let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send)); + let rpc_request = + RequestType::BlocksByRange(OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2 { + start_slot: 0, + count: messages_to_send, + step: 1, + })); // BlocksByRange Response let full_block = BeaconBlock::Base(BeaconBlockBase::::full(&spec)); @@ -247,7 +252,7 @@ fn test_tcp_blocks_by_range_chunked_rpc() { id, request, } => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response warn!(log, "Receiver got request"); for i in 0..messages_to_send { @@ -260,10 +265,20 @@ fn test_tcp_blocks_by_range_chunked_rpc() { } else { rpc_response_bellatrix_small.clone() }; - receiver.send_response(peer_id, id, rpc_response.clone()); + receiver.send_response( + peer_id, + id, + request.id, + rpc_response.clone(), + ); } // send the stream termination - receiver.send_response(peer_id, id, Response::BlocksByRange(None)); + receiver.send_response( + peer_id, + id, + request.id, + Response::BlocksByRange(None), + ); } } _ => {} // Ignore other events @@ -309,7 +324,7 @@ fn test_blobs_by_range_chunked_rpc() { .await; // BlobsByRange Request - let rpc_request = Request::BlobsByRange(BlobsByRangeRequest { + let rpc_request = RequestType::BlobsByRange(BlobsByRangeRequest { start_slot: 0, count: slot_count, }); @@ -367,16 +382,26 @@ fn test_blobs_by_range_chunked_rpc() { id, request, } => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response warn!(log, "Receiver got request"); for _ in 0..messages_to_send { // Send first third of responses as base blocks, // second as altair and third as bellatrix. - receiver.send_response(peer_id, id, rpc_response.clone()); + receiver.send_response( + peer_id, + id, + request.id, + rpc_response.clone(), + ); } // send the stream termination - receiver.send_response(peer_id, id, Response::BlobsByRange(None)); + receiver.send_response( + peer_id, + id, + request.id, + Response::BlobsByRange(None), + ); } } _ => {} // Ignore other events @@ -422,7 +447,12 @@ fn test_tcp_blocks_by_range_over_limit() { .await; // BlocksByRange Request - let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send)); + let rpc_request = + RequestType::BlocksByRange(OldBlocksByRangeRequest::V1(OldBlocksByRangeRequestV1 { + start_slot: 0, + count: messages_to_send, + step: 1, + })); // BlocksByRange Response let full_block = bellatrix_block_large(&common::fork_context(ForkName::Bellatrix), &spec); @@ -460,15 +490,25 @@ fn test_tcp_blocks_by_range_over_limit() { id, request, } => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response warn!(log, "Receiver got request"); for _ in 0..messages_to_send { let rpc_response = rpc_response_bellatrix_large.clone(); - receiver.send_response(peer_id, id, rpc_response.clone()); + receiver.send_response( + peer_id, + id, + request.id, + rpc_response.clone(), + ); } // send the stream termination - receiver.send_response(peer_id, id, Response::BlocksByRange(None)); + receiver.send_response( + peer_id, + id, + request.id, + Response::BlocksByRange(None), + ); } } _ => {} // Ignore other events @@ -514,7 +554,12 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() { .await; // BlocksByRange Request - let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send)); + let rpc_request = + RequestType::BlocksByRange(OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2 { + start_slot: 0, + count: messages_to_send, + step: 1, + })); // BlocksByRange Response let empty_block = BeaconBlock::empty(&spec); @@ -583,10 +628,10 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() { }, _, )) => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response warn!(log, "Receiver got request"); - message_info = Some((peer_id, id)); + message_info = Some((peer_id, id, request.id)); } } futures::future::Either::Right((_, _)) => {} // The timeout hit, send messages if required @@ -596,8 +641,8 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() { // if we need to send messages send them here. This will happen after a delay if message_info.is_some() { messages_sent += 1; - let (peer_id, stream_id) = message_info.as_ref().unwrap(); - receiver.send_response(*peer_id, *stream_id, rpc_response.clone()); + let (peer_id, stream_id, request_id) = message_info.as_ref().unwrap(); + receiver.send_response(*peer_id, *stream_id, *request_id, rpc_response.clone()); debug!(log, "Sending message {}", messages_sent); if messages_sent == messages_to_send + extra_messages_to_send { // stop sending messages @@ -642,7 +687,12 @@ fn test_tcp_blocks_by_range_single_empty_rpc() { .await; // BlocksByRange Request - let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, 10)); + let rpc_request = + RequestType::BlocksByRange(OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2 { + start_slot: 0, + count: 10, + step: 1, + })); // BlocksByRange Response let empty_block = BeaconBlock::empty(&spec); @@ -696,15 +746,25 @@ fn test_tcp_blocks_by_range_single_empty_rpc() { id, request, } => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response warn!(log, "Receiver got request"); for _ in 1..=messages_to_send { - receiver.send_response(peer_id, id, rpc_response.clone()); + receiver.send_response( + peer_id, + id, + request.id, + rpc_response.clone(), + ); } // send the stream termination - receiver.send_response(peer_id, id, Response::BlocksByRange(None)); + receiver.send_response( + peer_id, + id, + request.id, + Response::BlocksByRange(None), + ); } } _ => {} // Ignore other events @@ -750,7 +810,7 @@ fn test_tcp_blocks_by_root_chunked_rpc() { .await; // BlocksByRoot Request - let rpc_request = Request::BlocksByRoot(BlocksByRootRequest::new( + let rpc_request = RequestType::BlocksByRoot(BlocksByRootRequest::new( vec![ Hash256::zero(), Hash256::zero(), @@ -827,7 +887,7 @@ fn test_tcp_blocks_by_root_chunked_rpc() { id, request, } => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response debug!(log, "Receiver got request"); @@ -840,11 +900,16 @@ fn test_tcp_blocks_by_root_chunked_rpc() { } else { rpc_response_bellatrix_small.clone() }; - receiver.send_response(peer_id, id, rpc_response); + receiver.send_response(peer_id, id, request.id, rpc_response); debug!(log, "Sending message"); } // send the stream termination - receiver.send_response(peer_id, id, Response::BlocksByRange(None)); + receiver.send_response( + peer_id, + id, + request.id, + Response::BlocksByRange(None), + ); debug!(log, "Send stream term"); } } @@ -888,7 +953,7 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() { .await; // BlocksByRoot Request - let rpc_request = Request::BlocksByRoot(BlocksByRootRequest::new( + let rpc_request = RequestType::BlocksByRoot(BlocksByRootRequest::new( vec![ Hash256::zero(), Hash256::zero(), @@ -971,10 +1036,10 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() { }, _, )) => { - if request == rpc_request { + if request.r#type == rpc_request { // send the response warn!(log, "Receiver got request"); - message_info = Some((peer_id, id)); + message_info = Some((peer_id, id, request.id)); } } futures::future::Either::Right((_, _)) => {} // The timeout hit, send messages if required @@ -984,8 +1049,8 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() { // if we need to send messages send them here. This will happen after a delay if message_info.is_some() { messages_sent += 1; - let (peer_id, stream_id) = message_info.as_ref().unwrap(); - receiver.send_response(*peer_id, *stream_id, rpc_response.clone()); + let (peer_id, stream_id, request_id) = message_info.as_ref().unwrap(); + receiver.send_response(*peer_id, *stream_id, *request_id, rpc_response.clone()); debug!(log, "Sending message {}", messages_sent); if messages_sent == messages_to_send + extra_messages_to_send { // stop sending messages diff --git a/beacon_node/network/src/network_beacon_processor/mod.rs b/beacon_node/network/src/network_beacon_processor/mod.rs index 7f551c544c..5ec6140828 100644 --- a/beacon_node/network/src/network_beacon_processor/mod.rs +++ b/beacon_node/network/src/network_beacon_processor/mod.rs @@ -9,12 +9,14 @@ use beacon_processor::{ DuplicateCache, GossipAggregatePackage, GossipAttestationPackage, Work, WorkEvent as BeaconWorkEvent, }; +use lighthouse_network::discovery::ConnectionId; use lighthouse_network::rpc::methods::{ BlobsByRangeRequest, BlobsByRootRequest, DataColumnsByRangeRequest, DataColumnsByRootRequest, }; +use lighthouse_network::rpc::{RequestId, SubstreamId}; use lighthouse_network::{ rpc::{BlocksByRangeRequest, BlocksByRootRequest, LightClientBootstrapRequest, StatusMessage}, - Client, MessageId, NetworkGlobals, PeerId, PeerRequestId, + Client, MessageId, NetworkGlobals, PeerId, }; use slog::{debug, Logger}; use slot_clock::ManualSlotClock; @@ -596,13 +598,21 @@ impl NetworkBeaconProcessor { pub fn send_blocks_by_range_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlocksByRangeRequest, ) -> Result<(), Error> { let processor = self.clone(); let process_fn = async move { processor - .handle_blocks_by_range_request(peer_id, request_id, request) + .handle_blocks_by_range_request( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) .await; }; @@ -616,13 +626,21 @@ impl NetworkBeaconProcessor { pub fn send_blocks_by_roots_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlocksByRootRequest, ) -> Result<(), Error> { let processor = self.clone(); let process_fn = async move { processor - .handle_blocks_by_root_request(peer_id, request_id, request) + .handle_blocks_by_root_request( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) .await; }; @@ -636,12 +654,21 @@ impl NetworkBeaconProcessor { pub fn send_blobs_by_range_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlobsByRangeRequest, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = - move || processor.handle_blobs_by_range_request(peer_id, request_id, request); + let process_fn = move || { + processor.handle_blobs_by_range_request( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: false, @@ -653,12 +680,21 @@ impl NetworkBeaconProcessor { pub fn send_blobs_by_roots_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlobsByRootRequest, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = - move || processor.handle_blobs_by_root_request(peer_id, request_id, request); + let process_fn = move || { + processor.handle_blobs_by_root_request( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: false, @@ -670,12 +706,21 @@ impl NetworkBeaconProcessor { pub fn send_data_columns_by_roots_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: DataColumnsByRootRequest, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = - move || processor.handle_data_columns_by_root_request(peer_id, request_id, request); + let process_fn = move || { + processor.handle_data_columns_by_root_request( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: false, @@ -687,12 +732,21 @@ impl NetworkBeaconProcessor { pub fn send_data_columns_by_range_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: DataColumnsByRangeRequest, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = - move || processor.handle_data_columns_by_range_request(peer_id, request_id, request); + let process_fn = move || { + processor.handle_data_columns_by_range_request( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: false, @@ -704,12 +758,21 @@ impl NetworkBeaconProcessor { pub fn send_light_client_bootstrap_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: LightClientBootstrapRequest, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = - move || processor.handle_light_client_bootstrap(peer_id, request_id, request); + let process_fn = move || { + processor.handle_light_client_bootstrap( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: true, @@ -721,11 +784,19 @@ impl NetworkBeaconProcessor { pub fn send_light_client_optimistic_update_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = - move || processor.handle_light_client_optimistic_update(peer_id, request_id); + let process_fn = move || { + processor.handle_light_client_optimistic_update( + peer_id, + connection_id, + substream_id, + request_id, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: true, @@ -737,10 +808,19 @@ impl NetworkBeaconProcessor { pub fn send_light_client_finality_update_request( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, ) -> Result<(), Error> { let processor = self.clone(); - let process_fn = move || processor.handle_light_client_finality_update(peer_id, request_id); + let process_fn = move || { + processor.handle_light_client_finality_update( + peer_id, + connection_id, + substream_id, + request_id, + ) + }; self.try_send(BeaconWorkEvent { drop_during_sync: true, diff --git a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs index 0c98f5c17e..04e06c8e06 100644 --- a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs @@ -4,6 +4,7 @@ use crate::status::ToStatusMessage; use crate::sync::SyncMessage; use beacon_chain::{BeaconChainError, BeaconChainTypes, HistoricalBlockError, WhenSlotSkipped}; use itertools::process_results; +use lighthouse_network::discovery::ConnectionId; use lighthouse_network::rpc::methods::{ BlobsByRangeRequest, BlobsByRootRequest, DataColumnsByRangeRequest, DataColumnsByRootRequest, }; @@ -33,11 +34,14 @@ impl NetworkBeaconProcessor { &self, peer_id: PeerId, response: Response, - id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, ) { self.send_network_message(NetworkMessage::SendResponse { peer_id, - id, + request_id, + id: (connection_id, substream_id), response, }) } @@ -45,15 +49,17 @@ impl NetworkBeaconProcessor { pub fn send_error_response( &self, peer_id: PeerId, - error: RPCResponseErrorCode, + error: RpcErrorResponse, reason: String, id: PeerRequestId, + request_id: RequestId, ) { self.send_network_message(NetworkMessage::SendErrorResponse { peer_id, error, reason, id, + request_id, }) } @@ -131,14 +137,24 @@ impl NetworkBeaconProcessor { pub async fn handle_blocks_by_root_request( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlocksByRootRequest, ) { self.terminate_response_stream( peer_id, + connection_id, + substream_id, request_id, self.clone() - .handle_blocks_by_root_request_inner(peer_id, request_id, request) + .handle_blocks_by_root_request_inner( + peer_id, + connection_id, + substream_id, + request_id, + request, + ) .await, Response::BlocksByRoot, ); @@ -148,9 +164,11 @@ impl NetworkBeaconProcessor { pub async fn handle_blocks_by_root_request_inner( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlocksByRootRequest, - ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + ) -> Result<(), (RpcErrorResponse, &'static str)> { let log_results = |peer_id, requested_blocks, send_block_count| { debug!( self.log, @@ -169,10 +187,7 @@ impl NetworkBeaconProcessor { Ok(block_stream) => block_stream, Err(e) => { error!(self.log, "Error getting block stream"; "error" => ?e); - return Err(( - RPCResponseErrorCode::ServerError, - "Error getting block stream", - )); + return Err((RpcErrorResponse::ServerError, "Error getting block stream")); } }; // Fetching blocks is async because it may have to hit the execution layer for payloads. @@ -183,6 +198,8 @@ impl NetworkBeaconProcessor { self.send_response( peer_id, Response::BlocksByRoot(Some(block.clone())), + connection_id, + substream_id, request_id, ); send_block_count += 1; @@ -204,7 +221,7 @@ impl NetworkBeaconProcessor { ); log_results(peer_id, requested_blocks, send_block_count); return Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "Execution layer not synced", )); } @@ -228,13 +245,23 @@ impl NetworkBeaconProcessor { pub fn handle_blobs_by_root_request( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlobsByRootRequest, ) { self.terminate_response_stream( peer_id, + connection_id, + substream_id, request_id, - self.handle_blobs_by_root_request_inner(peer_id, request_id, request), + self.handle_blobs_by_root_request_inner( + peer_id, + connection_id, + substream_id, + request_id, + request, + ), Response::BlobsByRoot, ); } @@ -243,9 +270,11 @@ impl NetworkBeaconProcessor { pub fn handle_blobs_by_root_request_inner( &self, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: BlobsByRootRequest, - ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + ) -> Result<(), (RpcErrorResponse, &'static str)> { let Some(requested_root) = request.blob_ids.as_slice().first().map(|id| id.block_root) else { // No blob ids requested. @@ -263,7 +292,13 @@ impl NetworkBeaconProcessor { for id in request.blob_ids.as_slice() { // First attempt to get the blobs from the RPC cache. if let Ok(Some(blob)) = self.chain.data_availability_checker.get_blob(id) { - self.send_response(peer_id, Response::BlobsByRoot(Some(blob)), request_id); + self.send_response( + peer_id, + Response::BlobsByRoot(Some(blob)), + connection_id, + substream_id, + request_id, + ); send_blob_count += 1; } else { let BlobIdentifier { @@ -285,6 +320,8 @@ impl NetworkBeaconProcessor { self.send_response( peer_id, Response::BlobsByRoot(Some(blob_sidecar.clone())), + connection_id, + substream_id, request_id, ); send_blob_count += 1; @@ -320,13 +357,23 @@ impl NetworkBeaconProcessor { pub fn handle_data_columns_by_root_request( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: DataColumnsByRootRequest, ) { self.terminate_response_stream( peer_id, + connection_id, + substream_id, request_id, - self.handle_data_columns_by_root_request_inner(peer_id, request_id, request), + self.handle_data_columns_by_root_request_inner( + peer_id, + connection_id, + substream_id, + request_id, + request, + ), Response::DataColumnsByRoot, ); } @@ -335,9 +382,11 @@ impl NetworkBeaconProcessor { pub fn handle_data_columns_by_root_request_inner( &self, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: DataColumnsByRootRequest, - ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + ) -> Result<(), (RpcErrorResponse, &'static str)> { let mut send_data_column_count = 0; for data_column_id in request.data_column_ids.as_slice() { @@ -350,6 +399,8 @@ impl NetworkBeaconProcessor { self.send_response( peer_id, Response::DataColumnsByRoot(Some(data_column)), + connection_id, + substream_id, request_id, ); } @@ -361,10 +412,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err(( - RPCResponseErrorCode::ServerError, - "Error getting data column", - )); + return Err((RpcErrorResponse::ServerError, "Error getting data column")); } } } @@ -384,16 +432,20 @@ impl NetworkBeaconProcessor { pub fn handle_light_client_bootstrap( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, request: LightClientBootstrapRequest, ) { self.terminate_response_single_item( peer_id, + connection_id, + substream_id, request_id, match self.chain.get_light_client_bootstrap(&request.root) { Ok(Some((bootstrap, _))) => Ok(Arc::new(bootstrap)), Ok(None) => Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "Bootstrap not available".to_string(), )), Err(e) => { @@ -402,10 +454,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - Err(( - RPCResponseErrorCode::ResourceUnavailable, - format!("{:?}", e), - )) + Err((RpcErrorResponse::ResourceUnavailable, format!("{:?}", e))) } }, Response::LightClientBootstrap, @@ -416,10 +465,14 @@ impl NetworkBeaconProcessor { pub fn handle_light_client_optimistic_update( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, ) { self.terminate_response_single_item( peer_id, + connection_id, + substream_id, request_id, match self .chain @@ -428,7 +481,7 @@ impl NetworkBeaconProcessor { { Some(update) => Ok(Arc::new(update)), None => Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "Latest optimistic update not available".to_string(), )), }, @@ -440,10 +493,14 @@ impl NetworkBeaconProcessor { pub fn handle_light_client_finality_update( self: &Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, ) { self.terminate_response_single_item( peer_id, + connection_id, + substream_id, request_id, match self .chain @@ -452,7 +509,7 @@ impl NetworkBeaconProcessor { { Some(update) => Ok(Arc::new(update)), None => Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "Latest finality update not available".to_string(), )), }, @@ -464,14 +521,24 @@ impl NetworkBeaconProcessor { pub async fn handle_blocks_by_range_request( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, req: BlocksByRangeRequest, ) { self.terminate_response_stream( peer_id, + connection_id, + substream_id, request_id, self.clone() - .handle_blocks_by_range_request_inner(peer_id, request_id, req) + .handle_blocks_by_range_request_inner( + peer_id, + connection_id, + substream_id, + request_id, + req, + ) .await, Response::BlocksByRange, ); @@ -481,9 +548,11 @@ impl NetworkBeaconProcessor { pub async fn handle_blocks_by_range_request_inner( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, req: BlocksByRangeRequest, - ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + ) -> Result<(), (RpcErrorResponse, &'static str)> { debug!(self.log, "Received BlocksByRange Request"; "peer_id" => %peer_id, "count" => req.count(), @@ -507,7 +576,7 @@ impl NetworkBeaconProcessor { }); if *req.count() > max_request_size { return Err(( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Request exceeded max size", )); } @@ -527,7 +596,7 @@ impl NetworkBeaconProcessor { "requested_slot" => slot, "oldest_known_slot" => oldest_block_slot ); - return Err((RPCResponseErrorCode::ResourceUnavailable, "Backfilling")); + return Err((RpcErrorResponse::ResourceUnavailable, "Backfilling")); } Err(e) => { error!(self.log, "Unable to obtain root iter"; @@ -535,7 +604,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err((RPCResponseErrorCode::ServerError, "Database error")); + return Err((RpcErrorResponse::ServerError, "Database error")); } }; @@ -566,7 +635,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err((RPCResponseErrorCode::ServerError, "Iteration error")); + return Err((RpcErrorResponse::ServerError, "Iteration error")); } }; @@ -607,7 +676,7 @@ impl NetworkBeaconProcessor { Ok(block_stream) => block_stream, Err(e) => { error!(self.log, "Error getting block stream"; "error" => ?e); - return Err((RPCResponseErrorCode::ServerError, "Iterator error")); + return Err((RpcErrorResponse::ServerError, "Iterator error")); } }; @@ -624,8 +693,9 @@ impl NetworkBeaconProcessor { blocks_sent += 1; self.send_network_message(NetworkMessage::SendResponse { peer_id, + request_id, response: Response::BlocksByRange(Some(block.clone())), - id: request_id, + id: (connection_id, substream_id), }); } } @@ -638,7 +708,7 @@ impl NetworkBeaconProcessor { "request_root" => ?root ); log_results(req, peer_id, blocks_sent); - return Err((RPCResponseErrorCode::ServerError, "Database inconsistency")); + return Err((RpcErrorResponse::ServerError, "Database inconsistency")); } Err(BeaconChainError::BlockHashMissingFromExecutionLayer(_)) => { debug!( @@ -650,7 +720,7 @@ impl NetworkBeaconProcessor { log_results(req, peer_id, blocks_sent); // send the stream terminator return Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "Execution layer not synced", )); } @@ -677,7 +747,7 @@ impl NetworkBeaconProcessor { } log_results(req, peer_id, blocks_sent); // send the stream terminator - return Err((RPCResponseErrorCode::ServerError, "Failed fetching blocks")); + return Err((RpcErrorResponse::ServerError, "Failed fetching blocks")); } } } @@ -690,13 +760,23 @@ impl NetworkBeaconProcessor { pub fn handle_blobs_by_range_request( self: Arc, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, req: BlobsByRangeRequest, ) { self.terminate_response_stream( peer_id, + connection_id, + substream_id, request_id, - self.handle_blobs_by_range_request_inner(peer_id, request_id, req), + self.handle_blobs_by_range_request_inner( + peer_id, + connection_id, + substream_id, + request_id, + req, + ), Response::BlobsByRange, ); } @@ -705,9 +785,11 @@ impl NetworkBeaconProcessor { fn handle_blobs_by_range_request_inner( &self, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, req: BlobsByRangeRequest, - ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + ) -> Result<(), (RpcErrorResponse, &'static str)> { debug!(self.log, "Received BlobsByRange Request"; "peer_id" => %peer_id, "count" => req.count, @@ -717,7 +799,7 @@ impl NetworkBeaconProcessor { // Should not send more than max request blocks if req.max_blobs_requested::() > self.chain.spec.max_request_blob_sidecars { return Err(( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Request exceeded `MAX_REQUEST_BLOBS_SIDECARS`", )); } @@ -728,10 +810,7 @@ impl NetworkBeaconProcessor { Some(boundary) => boundary.start_slot(T::EthSpec::slots_per_epoch()), None => { debug!(self.log, "Deneb fork is disabled"); - return Err(( - RPCResponseErrorCode::InvalidRequest, - "Deneb fork is disabled", - )); + return Err((RpcErrorResponse::InvalidRequest, "Deneb fork is disabled")); } }; @@ -752,12 +831,12 @@ impl NetworkBeaconProcessor { return if data_availability_boundary_slot < oldest_blob_slot { Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "blobs pruned within boundary", )) } else { Err(( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Req outside availability period", )) }; @@ -776,7 +855,7 @@ impl NetworkBeaconProcessor { "requested_slot" => slot, "oldest_known_slot" => oldest_block_slot ); - return Err((RPCResponseErrorCode::ResourceUnavailable, "Backfilling")); + return Err((RpcErrorResponse::ResourceUnavailable, "Backfilling")); } Err(e) => { error!(self.log, "Unable to obtain root iter"; @@ -784,7 +863,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err((RPCResponseErrorCode::ServerError, "Database error")); + return Err((RpcErrorResponse::ServerError, "Database error")); } }; @@ -821,7 +900,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err((RPCResponseErrorCode::ServerError, "Database error")); + return Err((RpcErrorResponse::ServerError, "Database error")); } }; @@ -854,7 +933,8 @@ impl NetworkBeaconProcessor { self.send_network_message(NetworkMessage::SendResponse { peer_id, response: Response::BlobsByRange(Some(blob_sidecar.clone())), - id: request_id, + request_id, + id: (connection_id, substream_id), }); } } @@ -870,7 +950,7 @@ impl NetworkBeaconProcessor { log_results(peer_id, req, blobs_sent); return Err(( - RPCResponseErrorCode::ServerError, + RpcErrorResponse::ServerError, "No blobs and failed fetching corresponding block", )); } @@ -885,13 +965,23 @@ impl NetworkBeaconProcessor { pub fn handle_data_columns_by_range_request( &self, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, req: DataColumnsByRangeRequest, ) { self.terminate_response_stream( peer_id, + connection_id, + substream_id, request_id, - self.handle_data_columns_by_range_request_inner(peer_id, request_id, req), + self.handle_data_columns_by_range_request_inner( + peer_id, + connection_id, + substream_id, + request_id, + req, + ), Response::DataColumnsByRange, ); } @@ -900,9 +990,11 @@ impl NetworkBeaconProcessor { pub fn handle_data_columns_by_range_request_inner( &self, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, req: DataColumnsByRangeRequest, - ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + ) -> Result<(), (RpcErrorResponse, &'static str)> { debug!(self.log, "Received DataColumnsByRange Request"; "peer_id" => %peer_id, "count" => req.count, @@ -912,7 +1004,7 @@ impl NetworkBeaconProcessor { // Should not send more than max request data columns if req.max_requested::() > self.chain.spec.max_request_data_column_sidecars { return Err(( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Request exceeded `MAX_REQUEST_BLOBS_SIDECARS`", )); } @@ -923,10 +1015,7 @@ impl NetworkBeaconProcessor { Some(boundary) => boundary.start_slot(T::EthSpec::slots_per_epoch()), None => { debug!(self.log, "Deneb fork is disabled"); - return Err(( - RPCResponseErrorCode::InvalidRequest, - "Deneb fork is disabled", - )); + return Err((RpcErrorResponse::InvalidRequest, "Deneb fork is disabled")); } }; @@ -948,12 +1037,12 @@ impl NetworkBeaconProcessor { return if data_availability_boundary_slot < oldest_data_column_slot { Err(( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "blobs pruned within boundary", )) } else { Err(( - RPCResponseErrorCode::InvalidRequest, + RpcErrorResponse::InvalidRequest, "Req outside availability period", )) }; @@ -972,7 +1061,7 @@ impl NetworkBeaconProcessor { "requested_slot" => slot, "oldest_known_slot" => oldest_block_slot ); - return Err((RPCResponseErrorCode::ResourceUnavailable, "Backfilling")); + return Err((RpcErrorResponse::ResourceUnavailable, "Backfilling")); } Err(e) => { error!(self.log, "Unable to obtain root iter"; @@ -980,7 +1069,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err((RPCResponseErrorCode::ServerError, "Database error")); + return Err((RpcErrorResponse::ServerError, "Database error")); } }; @@ -1017,7 +1106,7 @@ impl NetworkBeaconProcessor { "peer" => %peer_id, "error" => ?e ); - return Err((RPCResponseErrorCode::ServerError, "Database error")); + return Err((RpcErrorResponse::ServerError, "Database error")); } }; @@ -1032,10 +1121,11 @@ impl NetworkBeaconProcessor { data_columns_sent += 1; self.send_network_message(NetworkMessage::SendResponse { peer_id, + request_id, response: Response::DataColumnsByRange(Some( data_column_sidecar.clone(), )), - id: request_id, + id: (connection_id, substream_id), }); } Ok(None) => {} // no-op @@ -1049,7 +1139,7 @@ impl NetworkBeaconProcessor { "error" => ?e ); return Err(( - RPCResponseErrorCode::ServerError, + RpcErrorResponse::ServerError, "No data columns and failed fetching corresponding block", )); } @@ -1080,8 +1170,10 @@ impl NetworkBeaconProcessor { fn terminate_response_single_item Response>( &self, peer_id: PeerId, - request_id: PeerRequestId, - result: Result, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, + result: Result, into_response: F, ) { match result { @@ -1091,12 +1183,19 @@ impl NetworkBeaconProcessor { // https://github.com/sigp/lighthouse/blob/3058b96f2560f1da04ada4f9d8ba8e5651794ff6/beacon_node/lighthouse_network/src/rpc/handler.rs#L555-L558 self.send_network_message(NetworkMessage::SendResponse { peer_id, + request_id, response: into_response(resp), - id: request_id, + id: (connection_id, substream_id), }); } Err((error_code, reason)) => { - self.send_error_response(peer_id, error_code, reason, request_id); + self.send_error_response( + peer_id, + error_code, + reason, + (connection_id, substream_id), + request_id, + ); } } } @@ -1106,18 +1205,27 @@ impl NetworkBeaconProcessor { fn terminate_response_stream) -> Response>( &self, peer_id: PeerId, - request_id: PeerRequestId, - result: Result<(), (RPCResponseErrorCode, &'static str)>, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, + result: Result<(), (RpcErrorResponse, &'static str)>, into_response: F, ) { match result { Ok(_) => self.send_network_message(NetworkMessage::SendResponse { peer_id, + request_id, response: into_response(None), - id: request_id, + id: (connection_id, substream_id), }), Err((error_code, reason)) => { - self.send_error_response(peer_id, error_code, reason.into(), request_id); + self.send_error_response( + peer_id, + error_code, + reason.into(), + (connection_id, substream_id), + request_id, + ); } } } diff --git a/beacon_node/network/src/network_beacon_processor/tests.rs b/beacon_node/network/src/network_beacon_processor/tests.rs index 6e8f151a05..9d774d97c1 100644 --- a/beacon_node/network/src/network_beacon_processor/tests.rs +++ b/beacon_node/network/src/network_beacon_processor/tests.rs @@ -16,7 +16,7 @@ use beacon_chain::{BeaconChain, WhenSlotSkipped}; use beacon_processor::{work_reprocessing_queue::*, *}; use lighthouse_network::discovery::ConnectionId; use lighthouse_network::rpc::methods::BlobsByRangeRequest; -use lighthouse_network::rpc::SubstreamId; +use lighthouse_network::rpc::{RequestId, SubstreamId}; use lighthouse_network::{ discv5::enr::{self, CombinedKey}, rpc::methods::{MetaData, MetaDataV2}, @@ -360,7 +360,9 @@ impl TestRig { self.network_beacon_processor .send_blobs_by_range_request( PeerId::random(), - (ConnectionId::new_unchecked(42), SubstreamId::new(24)), + ConnectionId::new_unchecked(42), + SubstreamId::new(24), + RequestId::new_unchecked(0), BlobsByRangeRequest { start_slot: 0, count, @@ -1137,6 +1139,7 @@ async fn test_blobs_by_range() { peer_id: _, response: Response::BlobsByRange(blob), id: _, + request_id: _, } = next { if blob.is_some() { diff --git a/beacon_node/network/src/router.rs b/beacon_node/network/src/router.rs index 26c1d14f02..f05cb01fa4 100644 --- a/beacon_node/network/src/router.rs +++ b/beacon_node/network/src/router.rs @@ -15,10 +15,12 @@ use beacon_processor::{ work_reprocessing_queue::ReprocessQueueMessage, BeaconProcessorSend, DuplicateCache, }; use futures::prelude::*; +use lighthouse_network::discovery::ConnectionId; use lighthouse_network::rpc::*; use lighthouse_network::{ + rpc, service::api_types::{AppRequestId, SyncRequestId}, - MessageId, NetworkGlobals, PeerId, PeerRequestId, PubsubMessage, Request, Response, + MessageId, NetworkGlobals, PeerId, PeerRequestId, PubsubMessage, Response, }; use logging::TimeLatch; use slog::{crit, debug, o, trace}; @@ -56,7 +58,7 @@ pub enum RouterMessage { RPCRequestReceived { peer_id: PeerId, id: PeerRequestId, - request: Request, + request: rpc::Request, }, /// An RPC response has been received. RPCResponseReceived { @@ -191,51 +193,125 @@ impl Router { /* RPC - Related functionality */ /// A new RPC request has been received from the network. - fn handle_rpc_request(&mut self, peer_id: PeerId, request_id: PeerRequestId, request: Request) { + fn handle_rpc_request( + &mut self, + peer_id: PeerId, + request_id: PeerRequestId, + rpc_request: rpc::Request, + ) { if !self.network_globals.peers.read().is_connected(&peer_id) { - debug!(self.log, "Dropping request of disconnected peer"; "peer_id" => %peer_id, "request" => ?request); + debug!(self.log, "Dropping request of disconnected peer"; "peer_id" => %peer_id, "request" => ?rpc_request); return; } - match request { - Request::Status(status_message) => { - self.on_status_request(peer_id, request_id, status_message) + match rpc_request.r#type { + RequestType::Status(status_message) => self.on_status_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + status_message, + ), + RequestType::BlocksByRange(request) => { + // return just one block in case the step parameter is used. https://github.com/ethereum/consensus-specs/pull/2856 + let mut count = *request.count(); + if *request.step() > 1 { + count = 1; + } + let blocks_request = match request { + methods::OldBlocksByRangeRequest::V1(req) => { + BlocksByRangeRequest::new_v1(req.start_slot, count) + } + methods::OldBlocksByRangeRequest::V2(req) => { + BlocksByRangeRequest::new(req.start_slot, count) + } + }; + + self.handle_beacon_processor_send_result( + self.network_beacon_processor.send_blocks_by_range_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + blocks_request, + ), + ) } - Request::BlocksByRange(request) => self.handle_beacon_processor_send_result( - self.network_beacon_processor - .send_blocks_by_range_request(peer_id, request_id, request), + RequestType::BlocksByRoot(request) => self.handle_beacon_processor_send_result( + self.network_beacon_processor.send_blocks_by_roots_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + request, + ), ), - Request::BlocksByRoot(request) => self.handle_beacon_processor_send_result( - self.network_beacon_processor - .send_blocks_by_roots_request(peer_id, request_id, request), + RequestType::BlobsByRange(request) => self.handle_beacon_processor_send_result( + self.network_beacon_processor.send_blobs_by_range_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + request, + ), ), - Request::BlobsByRange(request) => self.handle_beacon_processor_send_result( - self.network_beacon_processor - .send_blobs_by_range_request(peer_id, request_id, request), + RequestType::BlobsByRoot(request) => self.handle_beacon_processor_send_result( + self.network_beacon_processor.send_blobs_by_roots_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + request, + ), ), - Request::BlobsByRoot(request) => self.handle_beacon_processor_send_result( + RequestType::DataColumnsByRoot(request) => self.handle_beacon_processor_send_result( self.network_beacon_processor - .send_blobs_by_roots_request(peer_id, request_id, request), + .send_data_columns_by_roots_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + request, + ), ), - Request::DataColumnsByRoot(request) => self.handle_beacon_processor_send_result( + RequestType::DataColumnsByRange(request) => self.handle_beacon_processor_send_result( self.network_beacon_processor - .send_data_columns_by_roots_request(peer_id, request_id, request), + .send_data_columns_by_range_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + request, + ), ), - Request::DataColumnsByRange(request) => self.handle_beacon_processor_send_result( + RequestType::LightClientBootstrap(request) => self.handle_beacon_processor_send_result( self.network_beacon_processor - .send_data_columns_by_range_request(peer_id, request_id, request), + .send_light_client_bootstrap_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + request, + ), ), - Request::LightClientBootstrap(request) => self.handle_beacon_processor_send_result( + RequestType::LightClientOptimisticUpdate => self.handle_beacon_processor_send_result( self.network_beacon_processor - .send_light_client_bootstrap_request(peer_id, request_id, request), + .send_light_client_optimistic_update_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + ), ), - Request::LightClientOptimisticUpdate => self.handle_beacon_processor_send_result( + RequestType::LightClientFinalityUpdate => self.handle_beacon_processor_send_result( self.network_beacon_processor - .send_light_client_optimistic_update_request(peer_id, request_id), - ), - Request::LightClientFinalityUpdate => self.handle_beacon_processor_send_result( - self.network_beacon_processor - .send_light_client_finality_update_request(peer_id, request_id), + .send_light_client_finality_update_request( + peer_id, + request_id.0, + request_id.1, + rpc_request.id, + ), ), + _ => {} } } @@ -461,7 +537,7 @@ impl Router { let status_message = status_message(&self.chain); debug!(self.log, "Sending Status Request"; "peer" => %peer_id, &status_message); self.network - .send_processor_request(peer_id, Request::Status(status_message)); + .send_processor_request(peer_id, RequestType::Status(status_message)); } fn send_to_sync(&mut self, message: SyncMessage) { @@ -493,7 +569,9 @@ impl Router { pub fn on_status_request( &mut self, peer_id: PeerId, - request_id: PeerRequestId, + connection_id: ConnectionId, + substream_id: SubstreamId, + request_id: RequestId, status: StatusMessage, ) { debug!(self.log, "Received Status Request"; "peer_id" => %peer_id, &status); @@ -502,6 +580,7 @@ impl Router { self.network.send_response( peer_id, Response::Status(status_message(&self.chain)), + (connection_id, substream_id), request_id, ); @@ -745,7 +824,7 @@ impl HandlerNetworkContext { } /// Sends a request to the network task. - pub fn send_processor_request(&mut self, peer_id: PeerId, request: Request) { + pub fn send_processor_request(&mut self, peer_id: PeerId, request: RequestType) { self.inform_network(NetworkMessage::SendRequest { peer_id, request_id: AppRequestId::Router, @@ -754,8 +833,15 @@ impl HandlerNetworkContext { } /// Sends a response to the network task. - pub fn send_response(&mut self, peer_id: PeerId, response: Response, id: PeerRequestId) { + pub fn send_response( + &mut self, + peer_id: PeerId, + response: Response, + id: PeerRequestId, + request_id: RequestId, + ) { self.inform_network(NetworkMessage::SendResponse { + request_id, peer_id, id, response, diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index 150402a7ab..f36d11ecdd 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -14,12 +14,13 @@ use futures::channel::mpsc::Sender; use futures::future::OptionFuture; use futures::prelude::*; use futures::StreamExt; +use lighthouse_network::rpc::{RequestId, RequestType}; use lighthouse_network::service::Network; use lighthouse_network::types::GossipKind; use lighthouse_network::{prometheus_client::registry::Registry, MessageAcceptance}; use lighthouse_network::{ - rpc::{GoodbyeReason, RPCResponseErrorCode}, - Context, PeerAction, PeerRequestId, PubsubMessage, ReportSource, Request, Response, Subnet, + rpc::{GoodbyeReason, RpcErrorResponse}, + Context, PeerAction, PeerRequestId, PubsubMessage, ReportSource, Response, Subnet, }; use lighthouse_network::{ service::api_types::AppRequestId, @@ -61,19 +62,21 @@ pub enum NetworkMessage { /// Send an RPC request to the libp2p service. SendRequest { peer_id: PeerId, - request: Request, + request: RequestType, request_id: AppRequestId, }, /// Send a successful Response to the libp2p service. SendResponse { peer_id: PeerId, + request_id: RequestId, response: Response, id: PeerRequestId, }, /// Sends an error response to an RPC request. SendErrorResponse { peer_id: PeerId, - error: RPCResponseErrorCode, + request_id: RequestId, + error: RpcErrorResponse, reason: String, id: PeerRequestId, }, @@ -623,16 +626,19 @@ impl NetworkService { peer_id, response, id, + request_id, } => { - self.libp2p.send_response(peer_id, id, response); + self.libp2p.send_response(peer_id, id, request_id, response); } NetworkMessage::SendErrorResponse { peer_id, error, id, + request_id, reason, } => { - self.libp2p.send_error_response(peer_id, id, error, reason); + self.libp2p + .send_error_response(peer_id, id, request_id, error, reason); } NetworkMessage::ValidationResult { propagation_source, diff --git a/beacon_node/network/src/sync/block_lookups/tests.rs b/beacon_node/network/src/sync/block_lookups/tests.rs index c0a766137b..ffbdd43b5f 100644 --- a/beacon_node/network/src/sync/block_lookups/tests.rs +++ b/beacon_node/network/src/sync/block_lookups/tests.rs @@ -22,13 +22,14 @@ use beacon_chain::{ AvailabilityPendingExecutedBlock, PayloadVerificationOutcome, PayloadVerificationStatus, }; use beacon_processor::WorkEvent; -use lighthouse_network::rpc::{RPCError, RPCResponseErrorCode}; +use lighthouse_network::rpc::{RPCError, RequestType, RpcErrorResponse}; use lighthouse_network::service::api_types::{ AppRequestId, DataColumnsByRootRequester, Id, SamplingRequester, SingleLookupReqId, SyncRequestId, }; use lighthouse_network::types::SyncState; -use lighthouse_network::{NetworkConfig, NetworkGlobals, Request}; +use lighthouse_network::NetworkConfig; +use lighthouse_network::NetworkGlobals; use slog::info; use slot_clock::{ManualSlotClock, SlotClock, TestingSlotClock}; use store::MemoryStore; @@ -618,7 +619,7 @@ impl TestRig { id, peer_id, RPCError::ErrorResponse( - RPCResponseErrorCode::ResourceUnavailable, + RpcErrorResponse::ResourceUnavailable, "older than deneb".into(), ), ); @@ -894,7 +895,7 @@ impl TestRig { self.pop_received_network_event(|ev| match ev { NetworkMessage::SendRequest { peer_id: _, - request: Request::BlocksByRoot(request), + request: RequestType::BlocksByRoot(request), request_id: AppRequestId::Sync(SyncRequestId::SingleBlock { id }), } if request.block_roots().to_vec().contains(&for_block) => Some(*id), _ => None, @@ -914,7 +915,7 @@ impl TestRig { self.pop_received_network_event(|ev| match ev { NetworkMessage::SendRequest { peer_id: _, - request: Request::BlobsByRoot(request), + request: RequestType::BlobsByRoot(request), request_id: AppRequestId::Sync(SyncRequestId::SingleBlob { id }), } if request .blob_ids @@ -939,7 +940,7 @@ impl TestRig { self.pop_received_network_event(|ev| match ev { NetworkMessage::SendRequest { peer_id: _, - request: Request::BlocksByRoot(request), + request: RequestType::BlocksByRoot(request), request_id: AppRequestId::Sync(SyncRequestId::SingleBlock { id }), } if request.block_roots().to_vec().contains(&for_block) => Some(*id), _ => None, @@ -961,7 +962,7 @@ impl TestRig { self.pop_received_network_event(|ev| match ev { NetworkMessage::SendRequest { peer_id: _, - request: Request::BlobsByRoot(request), + request: RequestType::BlobsByRoot(request), request_id: AppRequestId::Sync(SyncRequestId::SingleBlob { id }), } if request .blob_ids @@ -989,7 +990,7 @@ impl TestRig { .pop_received_network_event(|ev| match ev { NetworkMessage::SendRequest { peer_id: _, - request: Request::DataColumnsByRoot(request), + request: RequestType::DataColumnsByRoot(request), request_id: AppRequestId::Sync(id @ SyncRequestId::DataColumnsByRoot { .. }), } if request .data_column_ids diff --git a/beacon_node/network/src/sync/network_context.rs b/beacon_node/network/src/sync/network_context.rs index 5b7003e5e8..dc35a141d2 100644 --- a/beacon_node/network/src/sync/network_context.rs +++ b/beacon_node/network/src/sync/network_context.rs @@ -17,13 +17,16 @@ use beacon_chain::block_verification_types::RpcBlock; use beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessStatus, EngineState}; use custody::CustodyRequestResult; use fnv::FnvHashMap; -use lighthouse_network::rpc::methods::{BlobsByRangeRequest, DataColumnsByRangeRequest}; -use lighthouse_network::rpc::{BlocksByRangeRequest, GoodbyeReason, RPCError}; +use lighthouse_network::rpc::methods::{ + BlobsByRangeRequest, DataColumnsByRangeRequest, OldBlocksByRangeRequest, + OldBlocksByRangeRequestV1, OldBlocksByRangeRequestV2, +}; +use lighthouse_network::rpc::{BlocksByRangeRequest, GoodbyeReason, RPCError, RequestType}; use lighthouse_network::service::api_types::{ AppRequestId, CustodyId, CustodyRequester, DataColumnsByRootRequestId, DataColumnsByRootRequester, Id, SingleLookupReqId, SyncRequestId, }; -use lighthouse_network::{Client, NetworkGlobals, PeerAction, PeerId, ReportSource, Request}; +use lighthouse_network::{Client, NetworkGlobals, PeerAction, PeerId, ReportSource}; use rand::seq::SliceRandom; use rand::thread_rng; use requests::ActiveDataColumnsByRootRequest; @@ -336,7 +339,7 @@ impl SyncNetworkContext { "head_slot" => %status_message.head_slot, ); - let request = Request::Status(status_message.clone()); + let request = RequestType::Status(status_message.clone()); let request_id = AppRequestId::Router; let _ = self.send_network_msg(NetworkMessage::SendRequest { peer_id, @@ -365,10 +368,26 @@ impl SyncNetworkContext { "epoch" => epoch, "peer" => %peer_id, ); + let rpc_request = match request { + BlocksByRangeRequest::V1(ref req) => { + RequestType::BlocksByRange(OldBlocksByRangeRequest::V1(OldBlocksByRangeRequestV1 { + start_slot: req.start_slot, + count: req.count, + step: 1, + })) + } + BlocksByRangeRequest::V2(ref req) => { + RequestType::BlocksByRange(OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2 { + start_slot: req.start_slot, + count: req.count, + step: 1, + })) + } + }; self.network_send .send(NetworkMessage::SendRequest { peer_id, - request: Request::BlocksByRange(request.clone()), + request: rpc_request, request_id: AppRequestId::Sync(SyncRequestId::RangeBlockAndBlobs { id }), }) .map_err(|_| RpcRequestSendError::NetworkSendError)?; @@ -387,7 +406,7 @@ impl SyncNetworkContext { self.network_send .send(NetworkMessage::SendRequest { peer_id, - request: Request::BlobsByRange(BlobsByRangeRequest { + request: RequestType::BlobsByRange(BlobsByRangeRequest { start_slot: *request.start_slot(), count: *request.count(), }), @@ -421,7 +440,7 @@ impl SyncNetworkContext { self.send_network_msg(NetworkMessage::SendRequest { peer_id, - request: Request::DataColumnsByRange(columns_by_range_request), + request: RequestType::DataColumnsByRange(columns_by_range_request), request_id: AppRequestId::Sync(SyncRequestId::RangeBlockAndBlobs { id }), }) .map_err(|_| RpcRequestSendError::NetworkSendError)?; @@ -585,7 +604,7 @@ impl SyncNetworkContext { self.network_send .send(NetworkMessage::SendRequest { peer_id, - request: Request::BlocksByRoot(request.into_request(&self.chain.spec)), + request: RequestType::BlocksByRoot(request.into_request(&self.chain.spec)), request_id: AppRequestId::Sync(SyncRequestId::SingleBlock { id }), }) .map_err(|_| RpcRequestSendError::NetworkSendError)?; @@ -683,7 +702,7 @@ impl SyncNetworkContext { self.network_send .send(NetworkMessage::SendRequest { peer_id, - request: Request::BlobsByRoot(request.clone().into_request(&self.chain.spec)), + request: RequestType::BlobsByRoot(request.clone().into_request(&self.chain.spec)), request_id: AppRequestId::Sync(SyncRequestId::SingleBlob { id }), }) .map_err(|_| RpcRequestSendError::NetworkSendError)?; @@ -715,7 +734,7 @@ impl SyncNetworkContext { self.send_network_msg(NetworkMessage::SendRequest { peer_id, - request: Request::DataColumnsByRoot(request.clone().into_request(&self.chain.spec)), + request: RequestType::DataColumnsByRoot(request.clone().into_request(&self.chain.spec)), request_id: AppRequestId::Sync(SyncRequestId::DataColumnsByRoot(req_id, requester)), })?;