diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index 84b913b284c62..9b55cc8d6a8d2 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -38,7 +38,7 @@ use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, CheckedSub }; use sp_arithmetic::traits::SaturatedConversion; -use message::{BlockAnnounce, Message}; +use message::{BlockAnnounce, Message, MessageV6}; use message::generic::{Message as GenericMessage, ConsensusMessage, Roles}; use prometheus_endpoint::{Registry, Gauge, GaugeVec, HistogramVec, PrometheusError, Opts, register, U64}; use sync::{ChainSync, SyncState}; @@ -91,7 +91,7 @@ const MAX_KNOWN_BLOCKS: usize = 1024; // ~32kb per peer + LruHashSet overhead const MAX_KNOWN_EXTRINSICS: usize = 4096; // ~128kb per peer + overhead /// Current protocol version. -pub(crate) const CURRENT_VERSION: u32 = 6; +pub(crate) const CURRENT_VERSION: u32 = 7; /// Lowest version we support pub(crate) const MIN_VERSION: u32 = 3; @@ -524,12 +524,24 @@ impl Protocol { data: BytesMut, ) -> CustomMessageOutcome { - let message = match as Decode>::decode(&mut &data[..]) { - Ok(message) => message, - Err(err) => { - debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what()); - self.peerset_handle.report_peer(who.clone(), rep::BAD_MESSAGE); - return CustomMessageOutcome::None; + let input = &mut &data[..]; + let decoded_result = as Decode>::decode(input); + let all_read = input.is_empty(); + let message = match (all_read, decoded_result) { + (true, Ok(message)) => message, + (false, _) | (_, Err(_)) => match as Decode>::decode(&mut &data[..]) { + Ok(message) => if let Some(message) = message.into_latest() { + message + } else { + debug!(target: "sync", "Couldn't call packet sent by {}: {:?}: {}", who, data, "Invalid input."); + self.peerset_handle.report_peer(who.clone(), rep::BAD_MESSAGE); + return CustomMessageOutcome::None; + }, + Err(err) => { + debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what()); + self.peerset_handle.report_peer(who.clone(), rep::BAD_MESSAGE); + return CustomMessageOutcome::None; + } } }; diff --git a/client/network/src/protocol/message.rs b/client/network/src/protocol/message.rs index 8638e9afc59b9..bc9d0f79facb7 100644 --- a/client/network/src/protocol/message.rs +++ b/client/network/src/protocol/message.rs @@ -25,6 +25,7 @@ pub use self::generic::{ RemoteChangesRequest, RemoteChangesResponse, FinalityProofRequest, FinalityProofResponse, FromBlock, RemoteReadChildRequest, Roles, + RemoteReadChildRequestV6, }; use sc_client_api::StorageProof; @@ -39,6 +40,17 @@ pub type Message = generic::Message< ::Extrinsic, >; +/// Type alias for using the message type using block type parameters. +/// +/// This could be removed as soon as MIN_VERSION switch to 7. +pub type MessageV6 = generic::MessageV6< + ::Header, + ::Hash, + <::Header as HeaderT>::Number, + ::Extrinsic, +>; + + /// Type alias for using the status type using block type parameters. pub type Status = generic::Status< ::Hash, @@ -237,6 +249,49 @@ pub mod generic { Number(Number), } + /// A protocol V6 network message, this is only for backward compatibility. + /// It should only be use when we fail to decode a message + /// with the latest encoding. + #[derive(Decode)] + pub enum MessageV6 { + /// Status packet. + Status(Status), + /// Block request. + BlockRequest(BlockRequest), + /// Block response. + BlockResponse(BlockResponse), + /// Block announce. + BlockAnnounce(BlockAnnounce
), + /// Transactions. + Transactions(Transactions), + /// Consensus protocol message. + Consensus(ConsensusMessage), + /// Remote method call request. + RemoteCallRequest(RemoteCallRequest), + /// Remote method call response. + RemoteCallResponse(RemoteCallResponse), + /// Remote storage read request. + RemoteReadRequest(RemoteReadRequest), + /// Remote storage read response. + RemoteReadResponse(RemoteReadResponse), + /// Remote header request. + RemoteHeaderRequest(RemoteHeaderRequest), + /// Remote header response. + RemoteHeaderResponse(RemoteHeaderResponse
), + /// Remote changes request. + RemoteChangesRequest(RemoteChangesRequest), + /// Remote changes response. + RemoteChangesResponse(RemoteChangesResponse), + /// Remote child storage read request. + RemoteReadChildRequest(RemoteReadChildRequestV6), + /// Finality proof request. + FinalityProofRequest(FinalityProofRequest), + /// Finality proof response. + FinalityProofResponse(FinalityProofResponse), + /// Batch of consensus protocol messages. + ConsensusBatch(Vec), + } + /// A network message. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub enum Message { @@ -278,6 +333,39 @@ pub mod generic { ConsensusBatch(Vec), } + impl MessageV6 { + /// Get matching latest protocol message for a protocol V6 message. + /// + /// Note that this function expect that V6 message are only created + /// after a failed latest message decoding, so we do only convert for diverging + /// decoding path. + pub fn into_latest(self) -> Option> { + match self { + MessageV6::RemoteReadChildRequest(RemoteReadChildRequestV6 { + id, + block, + storage_key, + child_info: _, + child_type, + keys, + }) => { + // V6 protocol only got implementation for child type 1. + if child_type != 1 { + None + } else { + Some(Message::RemoteReadChildRequest(RemoteReadChildRequest { + id, + block, + storage_key, + keys, + })) + } + }, + _ => None, + } + } + } + impl Message { /// Message id useful for logging. pub fn id(&self) -> &'static str { @@ -468,6 +556,24 @@ pub mod generic { pub keys: Vec>, } + #[derive(Decode)] + /// Backward compatibility remote storage read child request. + pub struct RemoteReadChildRequestV6 { + /// Unique request id. + pub id: RequestId, + /// Block at which to perform call. + pub block: H, + /// Child Storage key. + pub storage_key: Vec, + /// Child trie source information. + pub child_info: Vec, + /// Child type, its required to resolve `child_info` + /// content and choose child implementation. + pub child_type: u32, + /// Storage key. + pub keys: Vec>, + } + #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] /// Remote storage read child request. pub struct RemoteReadChildRequest {