Prepare for network protocol version upgrades (#5084)

* explicitly tag network requests with version

* fmt

* make PeerSet more aware of versioning

* some generalization of the network bridge to support upgrades

* walk back some renaming

* walk back some version stuff

* extract version from fallback

* remove V1 from NetworkBridgeUpdate

* add accidentally-removed timer

* implement focusing for versioned messages

* fmt

* fix up network bridge & tests

* remove inaccurate version check in bridge

* remove some TODO [now]s

* fix fallout in statement distribution

* fmt

* fallout in gossip-support

* fix fallout in collator-protocol

* fix fallout in bitfield-distribution

* fix fallout in approval-distribution

* fmt

* use never!

* fmt
This commit is contained in:
asynchronous rob
2022-04-21 11:34:59 -05:00
committed by GitHub
parent 203441981f
commit fc4b04db20
45 changed files with 942 additions and 594 deletions
@@ -60,17 +60,17 @@ pub mod v1;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, EnumIter)]
pub enum Protocol {
/// Protocol for chunk fetching, used by availability distribution and availability recovery.
ChunkFetching,
ChunkFetchingV1,
/// Protocol for fetching collations from collators.
CollationFetching,
CollationFetchingV1,
/// Protocol for fetching seconded PoVs from validators of the same group.
PoVFetching,
PoVFetchingV1,
/// Protocol for fetching available data.
AvailableDataFetching,
AvailableDataFetchingV1,
/// Fetching of statements that are too large for gossip.
StatementFetching,
StatementFetchingV1,
/// Sending of dispute statements with application level confirmations.
DisputeSending,
DisputeSendingV1,
}
/// Minimum bandwidth we expect for validators - 500Mbit/s is the recommendation, so approximately
@@ -111,12 +111,12 @@ pub const MAX_PARALLEL_STATEMENT_REQUESTS: u32 = 3;
/// Response size limit for responses of POV like data.
///
/// This is larger than `MAX_POV_SIZE` to account for protocol overhead and for additional data in
/// `CollationFetching` or `AvailableDataFetching` for example. We try to err on larger limits here
/// `CollationFetchingV1` or `AvailableDataFetchingV1` for example. We try to err on larger limits here
/// as a too large limit only allows an attacker to waste our bandwidth some more, a too low limit
/// might have more severe effects.
const POV_RESPONSE_SIZE: u64 = MAX_POV_SIZE as u64 + 10_000;
/// Maximum response sizes for `StatementFetching`.
/// Maximum response sizes for `StatementFetchingV1`.
///
/// This is `MAX_CODE_SIZE` plus some additional space for protocol overhead.
const STATEMENT_RESPONSE_SIZE: u64 = MAX_CODE_SIZE as u64 + 10_000;
@@ -130,7 +130,7 @@ impl Protocol {
let p_name = self.into_protocol_name();
let (tx, rx) = mpsc::channel(self.get_channel_size());
let cfg = match self {
Protocol::ChunkFetching => RequestResponseConfig {
Protocol::ChunkFetchingV1 => RequestResponseConfig {
name: p_name,
max_request_size: 1_000,
max_response_size: POV_RESPONSE_SIZE as u64 * 3,
@@ -138,7 +138,7 @@ impl Protocol {
request_timeout: CHUNK_REQUEST_TIMEOUT,
inbound_queue: Some(tx),
},
Protocol::CollationFetching => RequestResponseConfig {
Protocol::CollationFetchingV1 => RequestResponseConfig {
name: p_name,
max_request_size: 1_000,
max_response_size: POV_RESPONSE_SIZE,
@@ -146,14 +146,14 @@ impl Protocol {
request_timeout: POV_REQUEST_TIMEOUT_CONNECTED,
inbound_queue: Some(tx),
},
Protocol::PoVFetching => RequestResponseConfig {
Protocol::PoVFetchingV1 => RequestResponseConfig {
name: p_name,
max_request_size: 1_000,
max_response_size: POV_RESPONSE_SIZE,
request_timeout: POV_REQUEST_TIMEOUT_CONNECTED,
inbound_queue: Some(tx),
},
Protocol::AvailableDataFetching => RequestResponseConfig {
Protocol::AvailableDataFetchingV1 => RequestResponseConfig {
name: p_name,
max_request_size: 1_000,
// Available data size is dominated by the PoV size.
@@ -161,7 +161,7 @@ impl Protocol {
request_timeout: POV_REQUEST_TIMEOUT_CONNECTED,
inbound_queue: Some(tx),
},
Protocol::StatementFetching => RequestResponseConfig {
Protocol::StatementFetchingV1 => RequestResponseConfig {
name: p_name,
max_request_size: 1_000,
// Available data size is dominated code size.
@@ -178,7 +178,7 @@ impl Protocol {
request_timeout: Duration::from_secs(1),
inbound_queue: Some(tx),
},
Protocol::DisputeSending => RequestResponseConfig {
Protocol::DisputeSendingV1 => RequestResponseConfig {
name: p_name,
max_request_size: 1_000,
/// Responses are just confirmation, in essence not even a bit. So 100 seems
@@ -201,18 +201,18 @@ impl Protocol {
// times (due to network delays), 100 seems big enough to accomodate for "bursts",
// assuming we can service requests relatively quickly, which would need to be measured
// as well.
Protocol::ChunkFetching => 100,
Protocol::ChunkFetchingV1 => 100,
// 10 seems reasonable, considering group sizes of max 10 validators.
Protocol::CollationFetching => 10,
Protocol::CollationFetchingV1 => 10,
// 10 seems reasonable, considering group sizes of max 10 validators.
Protocol::PoVFetching => 10,
Protocol::PoVFetchingV1 => 10,
// Validators are constantly self-selecting to request available data which may lead
// to constant load and occasional burstiness.
Protocol::AvailableDataFetching => 100,
Protocol::AvailableDataFetchingV1 => 100,
// Our queue size approximation is how many blocks of the size of
// a runtime we can transfer within a statements timeout, minus the requests we handle
// in parallel.
Protocol::StatementFetching => {
Protocol::StatementFetchingV1 => {
// We assume we can utilize up to 70% of the available bandwidth for statements.
// This is just a guess/estimate, with the following considerations: If we are
// faster than that, queue size will stay low anyway, even if not - requesters will
@@ -233,7 +233,7 @@ impl Protocol {
// Incoming requests can get bursty, we should also be able to handle them fast on
// average, so something in the ballpark of 100 should be fine. Nodes will retry on
// failure, so having a good value here is mostly about performance tuning.
Protocol::DisputeSending => 100,
Protocol::DisputeSendingV1 => 100,
}
}
@@ -245,12 +245,12 @@ impl Protocol {
/// Get the protocol name associated with each peer set as static str.
pub const fn get_protocol_name_static(self) -> &'static str {
match self {
Protocol::ChunkFetching => "/polkadot/req_chunk/1",
Protocol::CollationFetching => "/polkadot/req_collation/1",
Protocol::PoVFetching => "/polkadot/req_pov/1",
Protocol::AvailableDataFetching => "/polkadot/req_available_data/1",
Protocol::StatementFetching => "/polkadot/req_statement/1",
Protocol::DisputeSending => "/polkadot/send_dispute/1",
Protocol::ChunkFetchingV1 => "/polkadot/req_chunk/1",
Protocol::CollationFetchingV1 => "/polkadot/req_collation/1",
Protocol::PoVFetchingV1 => "/polkadot/req_pov/1",
Protocol::AvailableDataFetchingV1 => "/polkadot/req_available_data/1",
Protocol::StatementFetchingV1 => "/polkadot/req_statement/1",
Protocol::DisputeSendingV1 => "/polkadot/send_dispute/1",
}
}
}
@@ -29,29 +29,29 @@ use super::{v1, IsRequest, Protocol};
#[derive(Debug)]
pub enum Requests {
/// Request an availability chunk from a node.
ChunkFetching(OutgoingRequest<v1::ChunkFetchingRequest>),
ChunkFetchingV1(OutgoingRequest<v1::ChunkFetchingRequest>),
/// Fetch a collation from a collator which previously announced it.
CollationFetching(OutgoingRequest<v1::CollationFetchingRequest>),
CollationFetchingV1(OutgoingRequest<v1::CollationFetchingRequest>),
/// Fetch a PoV from a validator which previously sent out a seconded statement.
PoVFetching(OutgoingRequest<v1::PoVFetchingRequest>),
PoVFetchingV1(OutgoingRequest<v1::PoVFetchingRequest>),
/// Request full available data from a node.
AvailableDataFetching(OutgoingRequest<v1::AvailableDataFetchingRequest>),
AvailableDataFetchingV1(OutgoingRequest<v1::AvailableDataFetchingRequest>),
/// Requests for fetching large statements as part of statement distribution.
StatementFetching(OutgoingRequest<v1::StatementFetchingRequest>),
StatementFetchingV1(OutgoingRequest<v1::StatementFetchingRequest>),
/// Requests for notifying about an ongoing dispute.
DisputeSending(OutgoingRequest<v1::DisputeRequest>),
DisputeSendingV1(OutgoingRequest<v1::DisputeRequest>),
}
impl Requests {
/// Get the protocol this request conforms to.
pub fn get_protocol(&self) -> Protocol {
match self {
Self::ChunkFetching(_) => Protocol::ChunkFetching,
Self::CollationFetching(_) => Protocol::CollationFetching,
Self::PoVFetching(_) => Protocol::PoVFetching,
Self::AvailableDataFetching(_) => Protocol::AvailableDataFetching,
Self::StatementFetching(_) => Protocol::StatementFetching,
Self::DisputeSending(_) => Protocol::DisputeSending,
Self::ChunkFetchingV1(_) => Protocol::ChunkFetchingV1,
Self::CollationFetchingV1(_) => Protocol::CollationFetchingV1,
Self::PoVFetchingV1(_) => Protocol::PoVFetchingV1,
Self::AvailableDataFetchingV1(_) => Protocol::AvailableDataFetchingV1,
Self::StatementFetchingV1(_) => Protocol::StatementFetchingV1,
Self::DisputeSendingV1(_) => Protocol::DisputeSendingV1,
}
}
@@ -64,12 +64,12 @@ impl Requests {
/// contained in the `enum`.
pub fn encode_request(self) -> (Protocol, OutgoingRequest<Vec<u8>>) {
match self {
Self::ChunkFetching(r) => r.encode_request(),
Self::CollationFetching(r) => r.encode_request(),
Self::PoVFetching(r) => r.encode_request(),
Self::AvailableDataFetching(r) => r.encode_request(),
Self::StatementFetching(r) => r.encode_request(),
Self::DisputeSending(r) => r.encode_request(),
Self::ChunkFetchingV1(r) => r.encode_request(),
Self::CollationFetchingV1(r) => r.encode_request(),
Self::PoVFetchingV1(r) => r.encode_request(),
Self::AvailableDataFetchingV1(r) => r.encode_request(),
Self::StatementFetchingV1(r) => r.encode_request(),
Self::DisputeSendingV1(r) => r.encode_request(),
}
}
}
@@ -85,7 +85,7 @@ impl ChunkResponse {
impl IsRequest for ChunkFetchingRequest {
type Response = ChunkFetchingResponse;
const PROTOCOL: Protocol = Protocol::ChunkFetching;
const PROTOCOL: Protocol = Protocol::ChunkFetchingV1;
}
/// Request the advertised collation at that relay-parent.
@@ -107,7 +107,7 @@ pub enum CollationFetchingResponse {
impl IsRequest for CollationFetchingRequest {
type Response = CollationFetchingResponse;
const PROTOCOL: Protocol = Protocol::CollationFetching;
const PROTOCOL: Protocol = Protocol::CollationFetchingV1;
}
/// Request the advertised collation at that relay-parent.
@@ -130,7 +130,7 @@ pub enum PoVFetchingResponse {
impl IsRequest for PoVFetchingRequest {
type Response = PoVFetchingResponse;
const PROTOCOL: Protocol = Protocol::PoVFetching;
const PROTOCOL: Protocol = Protocol::PoVFetchingV1;
}
/// Request the entire available data for a candidate.
@@ -162,7 +162,7 @@ impl From<Option<AvailableData>> for AvailableDataFetchingResponse {
impl IsRequest for AvailableDataFetchingRequest {
type Response = AvailableDataFetchingResponse;
const PROTOCOL: Protocol = Protocol::AvailableDataFetching;
const PROTOCOL: Protocol = Protocol::AvailableDataFetchingV1;
}
/// Request for fetching a large statement via request/response.
@@ -188,7 +188,7 @@ pub enum StatementFetchingResponse {
impl IsRequest for StatementFetchingRequest {
type Response = StatementFetchingResponse;
const PROTOCOL: Protocol = Protocol::StatementFetching;
const PROTOCOL: Protocol = Protocol::StatementFetchingV1;
}
/// A dispute request.
@@ -213,5 +213,5 @@ pub enum DisputeResponse {
impl IsRequest for DisputeRequest {
type Response = DisputeResponse;
const PROTOCOL: Protocol = Protocol::DisputeSending;
const PROTOCOL: Protocol = Protocol::DisputeSendingV1;
}