polkadot_node_network_protocol/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Network protocol types for parachains.
18
19#![deny(unused_crate_dependencies)]
20#![warn(missing_docs)]
21
22use codec::{Decode, Encode};
23use polkadot_primitives::{BlockNumber, Hash};
24use std::{collections::HashMap, fmt};
25
26#[doc(hidden)]
27pub use polkadot_node_jaeger as jaeger;
28pub use sc_network::IfDisconnected;
29pub use sc_network_types::PeerId;
30#[doc(hidden)]
31pub use std::sync::Arc;
32
33mod reputation;
34pub use self::reputation::{ReputationChange, UnifiedReputationChange};
35
36/// Peer-sets and protocols used for parachains.
37pub mod peer_set;
38
39/// Request/response protocols used in Polkadot.
40pub mod request_response;
41
42/// Accessing authority discovery service
43pub mod authority_discovery;
44/// Grid topology support module
45pub mod grid_topology;
46
47/// The minimum amount of peers to send gossip messages to.
48pub const MIN_GOSSIP_PEERS: usize = 25;
49
50/// An error indicating that this the over-arching message type had the wrong variant
51#[derive(Debug, Clone, Copy, PartialEq)]
52pub struct WrongVariant;
53
54impl fmt::Display for WrongVariant {
55	fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
56		write!(formatter, "Wrong message variant")
57	}
58}
59
60impl std::error::Error for WrongVariant {}
61
62/// The advertised role of a node.
63#[derive(Debug, Clone, Copy, PartialEq)]
64pub enum ObservedRole {
65	/// A light node.
66	Light,
67	/// A full node.
68	Full,
69	/// A node claiming to be an authority (unauthenticated)
70	Authority,
71}
72
73impl From<sc_network::ObservedRole> for ObservedRole {
74	fn from(role: sc_network::ObservedRole) -> ObservedRole {
75		match role {
76			sc_network::ObservedRole::Light => ObservedRole::Light,
77			sc_network::ObservedRole::Authority => ObservedRole::Authority,
78			sc_network::ObservedRole::Full => ObservedRole::Full,
79		}
80	}
81}
82
83impl Into<sc_network::ObservedRole> for ObservedRole {
84	fn into(self) -> sc_network::ObservedRole {
85		match self {
86			ObservedRole::Light => sc_network::ObservedRole::Light,
87			ObservedRole::Full => sc_network::ObservedRole::Full,
88			ObservedRole::Authority => sc_network::ObservedRole::Authority,
89		}
90	}
91}
92
93/// Specialized wrapper around [`View`].
94///
95/// Besides the access to the view itself, it also gives access to the [`jaeger::Span`] per
96/// leave/head.
97#[derive(Debug, Clone, Default)]
98pub struct OurView {
99	view: View,
100	span_per_head: HashMap<Hash, Arc<jaeger::Span>>,
101}
102
103impl OurView {
104	/// Creates a new instance.
105	pub fn new(
106		heads: impl IntoIterator<Item = (Hash, Arc<jaeger::Span>)>,
107		finalized_number: BlockNumber,
108	) -> Self {
109		let state_per_head = heads.into_iter().collect::<HashMap<_, _>>();
110		let view = View::new(state_per_head.keys().cloned(), finalized_number);
111		Self { view, span_per_head: state_per_head }
112	}
113
114	/// Returns the span per head map.
115	///
116	/// For each head there exists one span in this map.
117	pub fn span_per_head(&self) -> &HashMap<Hash, Arc<jaeger::Span>> {
118		&self.span_per_head
119	}
120}
121
122impl PartialEq for OurView {
123	fn eq(&self, other: &Self) -> bool {
124		self.view == other.view
125	}
126}
127
128impl std::ops::Deref for OurView {
129	type Target = View;
130
131	fn deref(&self) -> &View {
132		&self.view
133	}
134}
135
136/// Construct a new [`OurView`] with the given chain heads, finalized number 0 and disabled
137/// [`jaeger::Span`]'s.
138///
139/// NOTE: Use for tests only.
140///
141/// # Example
142///
143/// ```
144/// # use polkadot_node_network_protocol::our_view;
145/// # use polkadot_primitives::Hash;
146/// let our_view = our_view![Hash::repeat_byte(1), Hash::repeat_byte(2)];
147/// ```
148#[macro_export]
149macro_rules! our_view {
150	( $( $hash:expr ),* $(,)? ) => {
151		$crate::OurView::new(
152			vec![ $( $hash.clone() ),* ].into_iter().map(|h| (h, $crate::Arc::new($crate::jaeger::Span::Disabled))),
153			0,
154		)
155	};
156}
157
158/// A succinct representation of a peer's view. This consists of a bounded amount of chain heads
159/// and the highest known finalized block number.
160///
161/// Up to `N` (5?) chain heads.
162#[derive(Default, Debug, Clone, PartialEq, Eq, Encode, Decode)]
163pub struct View {
164	/// A bounded amount of chain heads.
165	/// Invariant: Sorted.
166	heads: Vec<Hash>,
167	/// The highest known finalized block number.
168	pub finalized_number: BlockNumber,
169}
170
171/// Construct a new view with the given chain heads and finalized number 0.
172///
173/// NOTE: Use for tests only.
174///
175/// # Example
176///
177/// ```
178/// # use polkadot_node_network_protocol::view;
179/// # use polkadot_primitives::Hash;
180/// let view = view![Hash::repeat_byte(1), Hash::repeat_byte(2)];
181/// ```
182#[macro_export]
183macro_rules! view {
184	( $( $hash:expr ),* $(,)? ) => {
185		$crate::View::new(vec![ $( $hash.clone() ),* ], 0)
186	};
187}
188
189impl View {
190	/// Construct a new view based on heads and a finalized block number.
191	pub fn new(heads: impl IntoIterator<Item = Hash>, finalized_number: BlockNumber) -> Self {
192		let mut heads = heads.into_iter().collect::<Vec<Hash>>();
193		heads.sort();
194		Self { heads, finalized_number }
195	}
196
197	/// Start with no heads, but only a finalized block number.
198	pub fn with_finalized(finalized_number: BlockNumber) -> Self {
199		Self { heads: Vec::new(), finalized_number }
200	}
201
202	/// Obtain the number of heads that are in view.
203	pub fn len(&self) -> usize {
204		self.heads.len()
205	}
206
207	/// Check if the number of heads contained, is null.
208	pub fn is_empty(&self) -> bool {
209		self.heads.is_empty()
210	}
211
212	/// Obtain an iterator over all heads.
213	pub fn iter(&self) -> impl Iterator<Item = &Hash> {
214		self.heads.iter()
215	}
216
217	/// Obtain an iterator over all heads.
218	pub fn into_iter(self) -> impl Iterator<Item = Hash> {
219		self.heads.into_iter()
220	}
221
222	/// Replace `self` with `new`.
223	///
224	/// Returns an iterator that will yield all elements of `new` that were not part of `self`.
225	pub fn replace_difference(&mut self, new: View) -> impl Iterator<Item = &Hash> {
226		let old = std::mem::replace(self, new);
227
228		self.heads.iter().filter(move |h| !old.contains(h))
229	}
230
231	/// Returns an iterator of the hashes present in `Self` but not in `other`.
232	pub fn difference<'a>(&'a self, other: &'a View) -> impl Iterator<Item = &'a Hash> + 'a {
233		self.heads.iter().filter(move |h| !other.contains(h))
234	}
235
236	/// An iterator containing hashes present in both `Self` and in `other`.
237	pub fn intersection<'a>(&'a self, other: &'a View) -> impl Iterator<Item = &'a Hash> + 'a {
238		self.heads.iter().filter(move |h| other.contains(h))
239	}
240
241	/// Whether the view contains a given hash.
242	pub fn contains(&self, hash: &Hash) -> bool {
243		self.heads.contains(hash)
244	}
245
246	/// Check if two views have the same heads.
247	///
248	/// Equivalent to the `PartialEq` function,
249	/// but ignores the `finalized_number` field.
250	pub fn check_heads_eq(&self, other: &Self) -> bool {
251		self.heads == other.heads
252	}
253}
254
255/// A protocol-versioned type.
256#[derive(Debug, Clone, PartialEq, Eq)]
257pub enum Versioned<V1, V2, V3 = V2> {
258	/// V1 type.
259	V1(V1),
260	/// V2 type.
261	V2(V2),
262	/// V3 type
263	V3(V3),
264}
265
266impl<V1: Clone, V2: Clone, V3: Clone> Versioned<&'_ V1, &'_ V2, &'_ V3> {
267	/// Convert to a fully-owned version of the message.
268	pub fn clone_inner(&self) -> Versioned<V1, V2, V3> {
269		match *self {
270			Versioned::V1(inner) => Versioned::V1(inner.clone()),
271			Versioned::V2(inner) => Versioned::V2(inner.clone()),
272			Versioned::V3(inner) => Versioned::V3(inner.clone()),
273		}
274	}
275}
276
277/// All supported versions of the validation protocol message.
278pub type VersionedValidationProtocol =
279	Versioned<v1::ValidationProtocol, v2::ValidationProtocol, v3::ValidationProtocol>;
280
281impl From<v1::ValidationProtocol> for VersionedValidationProtocol {
282	fn from(v1: v1::ValidationProtocol) -> Self {
283		VersionedValidationProtocol::V1(v1)
284	}
285}
286
287impl From<v2::ValidationProtocol> for VersionedValidationProtocol {
288	fn from(v2: v2::ValidationProtocol) -> Self {
289		VersionedValidationProtocol::V2(v2)
290	}
291}
292
293impl From<v3::ValidationProtocol> for VersionedValidationProtocol {
294	fn from(v3: v3::ValidationProtocol) -> Self {
295		VersionedValidationProtocol::V3(v3)
296	}
297}
298
299/// All supported versions of the collation protocol message.
300pub type VersionedCollationProtocol = Versioned<v1::CollationProtocol, v2::CollationProtocol>;
301
302impl From<v1::CollationProtocol> for VersionedCollationProtocol {
303	fn from(v1: v1::CollationProtocol) -> Self {
304		VersionedCollationProtocol::V1(v1)
305	}
306}
307
308impl From<v2::CollationProtocol> for VersionedCollationProtocol {
309	fn from(v2: v2::CollationProtocol) -> Self {
310		VersionedCollationProtocol::V2(v2)
311	}
312}
313
314macro_rules! impl_versioned_full_protocol_from {
315	($from:ty, $out:ty, $variant:ident) => {
316		impl From<$from> for $out {
317			fn from(versioned_from: $from) -> $out {
318				match versioned_from {
319					Versioned::V1(x) => Versioned::V1(x.into()),
320					Versioned::V2(x) => Versioned::V2(x.into()),
321					Versioned::V3(x) => Versioned::V3(x.into()),
322				}
323			}
324		}
325	};
326}
327/// Implement `TryFrom` for one versioned enum variant into the inner type.
328/// `$m_ty::$variant(inner) -> Ok(inner)`
329macro_rules! impl_versioned_try_from {
330	(
331		$from:ty,
332		$out:ty,
333		$v1_pat:pat => $v1_out:expr,
334		$v2_pat:pat => $v2_out:expr,
335		$v3_pat:pat => $v3_out:expr
336	) => {
337		impl TryFrom<$from> for $out {
338			type Error = crate::WrongVariant;
339
340			fn try_from(x: $from) -> Result<$out, Self::Error> {
341				#[allow(unreachable_patterns)] // when there is only one variant
342				match x {
343					Versioned::V1($v1_pat) => Ok(Versioned::V1($v1_out)),
344					Versioned::V2($v2_pat) => Ok(Versioned::V2($v2_out)),
345					Versioned::V3($v3_pat) => Ok(Versioned::V3($v3_out)),
346					_ => Err(crate::WrongVariant),
347				}
348			}
349		}
350
351		impl<'a> TryFrom<&'a $from> for $out {
352			type Error = crate::WrongVariant;
353
354			fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
355				#[allow(unreachable_patterns)] // when there is only one variant
356				match x {
357					Versioned::V1($v1_pat) => Ok(Versioned::V1($v1_out.clone())),
358					Versioned::V2($v2_pat) => Ok(Versioned::V2($v2_out.clone())),
359					Versioned::V3($v3_pat) => Ok(Versioned::V3($v3_out.clone())),
360					_ => Err(crate::WrongVariant),
361				}
362			}
363		}
364	};
365}
366
367/// Version-annotated messages used by the bitfield distribution subsystem.
368pub type BitfieldDistributionMessage = Versioned<
369	v1::BitfieldDistributionMessage,
370	v2::BitfieldDistributionMessage,
371	v3::BitfieldDistributionMessage,
372>;
373impl_versioned_full_protocol_from!(
374	BitfieldDistributionMessage,
375	VersionedValidationProtocol,
376	BitfieldDistribution
377);
378impl_versioned_try_from!(
379	VersionedValidationProtocol,
380	BitfieldDistributionMessage,
381	v1::ValidationProtocol::BitfieldDistribution(x) => x,
382	v2::ValidationProtocol::BitfieldDistribution(x) => x,
383	v3::ValidationProtocol::BitfieldDistribution(x) => x
384);
385
386/// Version-annotated messages used by the statement distribution subsystem.
387pub type StatementDistributionMessage = Versioned<
388	v1::StatementDistributionMessage,
389	v2::StatementDistributionMessage,
390	v3::StatementDistributionMessage,
391>;
392impl_versioned_full_protocol_from!(
393	StatementDistributionMessage,
394	VersionedValidationProtocol,
395	StatementDistribution
396);
397impl_versioned_try_from!(
398	VersionedValidationProtocol,
399	StatementDistributionMessage,
400	v1::ValidationProtocol::StatementDistribution(x) => x,
401	v2::ValidationProtocol::StatementDistribution(x) => x,
402	v3::ValidationProtocol::StatementDistribution(x) => x
403);
404
405/// Version-annotated messages used by the approval distribution subsystem.
406pub type ApprovalDistributionMessage = Versioned<
407	v1::ApprovalDistributionMessage,
408	v2::ApprovalDistributionMessage,
409	v3::ApprovalDistributionMessage,
410>;
411impl_versioned_full_protocol_from!(
412	ApprovalDistributionMessage,
413	VersionedValidationProtocol,
414	ApprovalDistribution
415);
416impl_versioned_try_from!(
417	VersionedValidationProtocol,
418	ApprovalDistributionMessage,
419	v1::ValidationProtocol::ApprovalDistribution(x) => x,
420	v2::ValidationProtocol::ApprovalDistribution(x) => x,
421	v3::ValidationProtocol::ApprovalDistribution(x) => x
422
423);
424
425/// Version-annotated messages used by the gossip-support subsystem (this is void).
426pub type GossipSupportNetworkMessage = Versioned<
427	v1::GossipSupportNetworkMessage,
428	v2::GossipSupportNetworkMessage,
429	v3::GossipSupportNetworkMessage,
430>;
431
432// This is a void enum placeholder, so never gets sent over the wire.
433impl TryFrom<VersionedValidationProtocol> for GossipSupportNetworkMessage {
434	type Error = WrongVariant;
435	fn try_from(_: VersionedValidationProtocol) -> Result<Self, Self::Error> {
436		Err(WrongVariant)
437	}
438}
439
440impl<'a> TryFrom<&'a VersionedValidationProtocol> for GossipSupportNetworkMessage {
441	type Error = WrongVariant;
442	fn try_from(_: &'a VersionedValidationProtocol) -> Result<Self, Self::Error> {
443		Err(WrongVariant)
444	}
445}
446
447/// Version-annotated messages used by the bitfield distribution subsystem.
448pub type CollatorProtocolMessage =
449	Versioned<v1::CollatorProtocolMessage, v2::CollatorProtocolMessage>;
450impl_versioned_full_protocol_from!(
451	CollatorProtocolMessage,
452	VersionedCollationProtocol,
453	CollatorProtocol
454);
455impl_versioned_try_from!(
456	VersionedCollationProtocol,
457	CollatorProtocolMessage,
458	v1::CollationProtocol::CollatorProtocol(x) => x,
459	v2::CollationProtocol::CollatorProtocol(x) => x,
460	v2::CollationProtocol::CollatorProtocol(x) => x
461);
462
463/// v1 notification protocol types.
464pub mod v1 {
465	use codec::{Decode, Encode};
466
467	use polkadot_primitives::{
468		CandidateHash, CandidateIndex, CollatorId, CollatorSignature, CompactStatement, Hash,
469		Id as ParaId, UncheckedSignedAvailabilityBitfield, ValidatorIndex, ValidatorSignature,
470	};
471
472	use polkadot_node_primitives::{
473		approval::v1::{IndirectAssignmentCert, IndirectSignedApprovalVote},
474		UncheckedSignedFullStatement,
475	};
476
477	/// Network messages used by the bitfield distribution subsystem.
478	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
479	pub enum BitfieldDistributionMessage {
480		/// A signed availability bitfield for a given relay-parent hash.
481		#[codec(index = 0)]
482		Bitfield(Hash, UncheckedSignedAvailabilityBitfield),
483	}
484
485	/// Network messages used by the statement distribution subsystem.
486	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
487	pub enum StatementDistributionMessage {
488		/// A signed full statement under a given relay-parent.
489		#[codec(index = 0)]
490		Statement(Hash, UncheckedSignedFullStatement),
491		/// Seconded statement with large payload (e.g. containing a runtime upgrade).
492		///
493		/// We only gossip the hash in that case, actual payloads can be fetched from sending node
494		/// via request/response.
495		#[codec(index = 1)]
496		LargeStatement(StatementMetadata),
497	}
498
499	/// Data that makes a statement unique.
500	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, Hash)]
501	pub struct StatementMetadata {
502		/// Relay parent this statement is relevant under.
503		pub relay_parent: Hash,
504		/// Hash of the candidate that got validated.
505		pub candidate_hash: CandidateHash,
506		/// Validator that attested the validity.
507		pub signed_by: ValidatorIndex,
508		/// Signature of seconding validator.
509		pub signature: ValidatorSignature,
510	}
511
512	impl StatementDistributionMessage {
513		/// Get fingerprint describing the contained statement uniquely.
514		pub fn get_fingerprint(&self) -> (CompactStatement, ValidatorIndex) {
515			match self {
516				Self::Statement(_, statement) => (
517					statement.unchecked_payload().to_compact(),
518					statement.unchecked_validator_index(),
519				),
520				Self::LargeStatement(meta) =>
521					(CompactStatement::Seconded(meta.candidate_hash), meta.signed_by),
522			}
523		}
524
525		/// Get the signature from the statement.
526		pub fn get_signature(&self) -> ValidatorSignature {
527			match self {
528				Self::Statement(_, statement) => statement.unchecked_signature().clone(),
529				Self::LargeStatement(metadata) => metadata.signature.clone(),
530			}
531		}
532
533		/// Get contained relay parent.
534		pub fn get_relay_parent(&self) -> Hash {
535			match self {
536				Self::Statement(r, _) => *r,
537				Self::LargeStatement(meta) => meta.relay_parent,
538			}
539		}
540
541		/// Whether this message contains a large statement.
542		pub fn is_large_statement(&self) -> bool {
543			if let Self::LargeStatement(_) = self {
544				true
545			} else {
546				false
547			}
548		}
549	}
550
551	/// Network messages used by the approval distribution subsystem.
552	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
553	pub enum ApprovalDistributionMessage {
554		/// Assignments for candidates in recent, unfinalized blocks.
555		///
556		/// Actually checking the assignment may yield a different result.
557		#[codec(index = 0)]
558		Assignments(Vec<(IndirectAssignmentCert, CandidateIndex)>),
559		/// Approvals for candidates in some recent, unfinalized block.
560		#[codec(index = 1)]
561		Approvals(Vec<IndirectSignedApprovalVote>),
562	}
563
564	/// Dummy network message type, so we will receive connect/disconnect events.
565	#[derive(Debug, Clone, PartialEq, Eq)]
566	pub enum GossipSupportNetworkMessage {}
567
568	/// Network messages used by the collator protocol subsystem
569	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
570	pub enum CollatorProtocolMessage {
571		/// Declare the intent to advertise collations under a collator ID, attaching a
572		/// signature of the `PeerId` of the node using the given collator ID key.
573		#[codec(index = 0)]
574		Declare(CollatorId, ParaId, CollatorSignature),
575		/// Advertise a collation to a validator. Can only be sent once the peer has
576		/// declared that they are a collator with given ID.
577		#[codec(index = 1)]
578		AdvertiseCollation(Hash),
579		/// A collation sent to a validator was seconded.
580		#[codec(index = 4)]
581		CollationSeconded(Hash, UncheckedSignedFullStatement),
582	}
583
584	/// All network messages on the validation peer-set.
585	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
586	pub enum ValidationProtocol {
587		/// Bitfield distribution messages
588		#[codec(index = 1)]
589		#[from]
590		BitfieldDistribution(BitfieldDistributionMessage),
591		/// Statement distribution messages
592		#[codec(index = 3)]
593		#[from]
594		StatementDistribution(StatementDistributionMessage),
595		/// Approval distribution messages
596		#[codec(index = 4)]
597		#[from]
598		ApprovalDistribution(ApprovalDistributionMessage),
599	}
600
601	/// All network messages on the collation peer-set.
602	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
603	pub enum CollationProtocol {
604		/// Collator protocol messages
605		#[codec(index = 0)]
606		#[from]
607		CollatorProtocol(CollatorProtocolMessage),
608	}
609
610	/// Get the payload that should be signed and included in a `Declare` message.
611	///
612	/// The payload is the local peer id of the node, which serves to prove that it
613	/// controls the collator key it is declaring an intention to collate under.
614	pub fn declare_signature_payload(peer_id: &sc_network_types::PeerId) -> Vec<u8> {
615		let mut payload = peer_id.to_bytes();
616		payload.extend_from_slice(b"COLL");
617		payload
618	}
619}
620
621/// v2 network protocol types.
622pub mod v2 {
623	use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec};
624	use codec::{Decode, Encode};
625
626	use polkadot_primitives::{
627		CandidateHash, CandidateIndex, CollatorId, CollatorSignature, GroupIndex, Hash,
628		Id as ParaId, UncheckedSignedAvailabilityBitfield, UncheckedSignedStatement,
629	};
630
631	use polkadot_node_primitives::{
632		approval::v1::{IndirectAssignmentCert, IndirectSignedApprovalVote},
633		UncheckedSignedFullStatement,
634	};
635
636	/// Network messages used by the bitfield distribution subsystem.
637	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
638	pub enum BitfieldDistributionMessage {
639		/// A signed availability bitfield for a given relay-parent hash.
640		#[codec(index = 0)]
641		Bitfield(Hash, UncheckedSignedAvailabilityBitfield),
642	}
643
644	/// Bitfields indicating the statements that are known or undesired
645	/// about a candidate.
646	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
647	pub struct StatementFilter {
648		/// Seconded statements. '1' is known or undesired.
649		pub seconded_in_group: BitVec<u8, Lsb0>,
650		/// Valid statements. '1' is known or undesired.
651		pub validated_in_group: BitVec<u8, Lsb0>,
652	}
653
654	impl StatementFilter {
655		/// Create a new blank filter with the given group size.
656		pub fn blank(group_size: usize) -> Self {
657			StatementFilter {
658				seconded_in_group: BitVec::repeat(false, group_size),
659				validated_in_group: BitVec::repeat(false, group_size),
660			}
661		}
662
663		/// Create a new full filter with the given group size.
664		pub fn full(group_size: usize) -> Self {
665			StatementFilter {
666				seconded_in_group: BitVec::repeat(true, group_size),
667				validated_in_group: BitVec::repeat(true, group_size),
668			}
669		}
670
671		/// Whether the filter has a specific expected length, consistent across both
672		/// bitfields.
673		pub fn has_len(&self, len: usize) -> bool {
674			self.seconded_in_group.len() == len && self.validated_in_group.len() == len
675		}
676
677		/// Determine the number of backing validators in the statement filter.
678		pub fn backing_validators(&self) -> usize {
679			self.seconded_in_group
680				.iter()
681				.by_vals()
682				.zip(self.validated_in_group.iter().by_vals())
683				.filter(|&(s, v)| s || v) // no double-counting
684				.count()
685		}
686
687		/// Whether the statement filter has at least one seconded statement.
688		pub fn has_seconded(&self) -> bool {
689			self.seconded_in_group.iter().by_vals().any(|x| x)
690		}
691
692		/// Mask out `Seconded` statements in `self` according to the provided
693		/// bitvec. Bits appearing in `mask` will not appear in `self` afterwards.
694		pub fn mask_seconded(&mut self, mask: &BitSlice<u8, Lsb0>) {
695			for (mut x, mask) in self
696				.seconded_in_group
697				.iter_mut()
698				.zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
699			{
700				// (x, mask) => x
701				// (true, true) => false
702				// (true, false) => true
703				// (false, true) => false
704				// (false, false) => false
705				*x = *x && !mask;
706			}
707		}
708
709		/// Mask out `Valid` statements in `self` according to the provided
710		/// bitvec. Bits appearing in `mask` will not appear in `self` afterwards.
711		pub fn mask_valid(&mut self, mask: &BitSlice<u8, Lsb0>) {
712			for (mut x, mask) in self
713				.validated_in_group
714				.iter_mut()
715				.zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
716			{
717				// (x, mask) => x
718				// (true, true) => false
719				// (true, false) => true
720				// (false, true) => false
721				// (false, false) => false
722				*x = *x && !mask;
723			}
724		}
725	}
726
727	/// A manifest of a known backed candidate, along with a description
728	/// of the statements backing it.
729	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
730	pub struct BackedCandidateManifest {
731		/// The relay-parent of the candidate.
732		pub relay_parent: Hash,
733		/// The hash of the candidate.
734		pub candidate_hash: CandidateHash,
735		/// The group index backing the candidate at the relay-parent.
736		pub group_index: GroupIndex,
737		/// The para ID of the candidate. It is illegal for this to
738		/// be a para ID which is not assigned to the group indicated
739		/// in this manifest.
740		pub para_id: ParaId,
741		/// The head-data corresponding to the candidate.
742		pub parent_head_data_hash: Hash,
743		/// A statement filter which indicates which validators in the
744		/// para's group at the relay-parent have validated this candidate
745		/// and issued statements about it, to the advertiser's knowledge.
746		///
747		/// This MUST have exactly the minimum amount of bytes
748		/// necessary to represent the number of validators in the assigned
749		/// backing group as-of the relay-parent.
750		pub statement_knowledge: StatementFilter,
751	}
752
753	/// An acknowledgement of a backed candidate being known.
754	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
755	pub struct BackedCandidateAcknowledgement {
756		/// The hash of the candidate.
757		pub candidate_hash: CandidateHash,
758		/// A statement filter which indicates which validators in the
759		/// para's group at the relay-parent have validated this candidate
760		/// and issued statements about it, to the advertiser's knowledge.
761		///
762		/// This MUST have exactly the minimum amount of bytes
763		/// necessary to represent the number of validators in the assigned
764		/// backing group as-of the relay-parent.
765		pub statement_knowledge: StatementFilter,
766	}
767
768	/// Network messages used by the statement distribution subsystem.
769	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
770	pub enum StatementDistributionMessage {
771		/// A notification of a signed statement in compact form, for a given relay parent.
772		#[codec(index = 0)]
773		Statement(Hash, UncheckedSignedStatement),
774
775		/// A notification of a backed candidate being known by the
776		/// sending node, for the purpose of being requested by the receiving node
777		/// if needed.
778		#[codec(index = 1)]
779		BackedCandidateManifest(BackedCandidateManifest),
780
781		/// A notification of a backed candidate being known by the sending node,
782		/// for the purpose of informing a receiving node which already has the candidate.
783		#[codec(index = 2)]
784		BackedCandidateKnown(BackedCandidateAcknowledgement),
785
786		/// All messages for V1 for compatibility with the statement distribution
787		/// protocol, for relay-parents that don't support asynchronous backing.
788		///
789		/// These are illegal to send to V1 peers, and illegal to send concerning relay-parents
790		/// which support asynchronous backing. This backwards compatibility should be
791		/// considered immediately deprecated and can be removed once the node software
792		/// is not required to support logic from before asynchronous backing anymore.
793		#[codec(index = 255)]
794		V1Compatibility(crate::v1::StatementDistributionMessage),
795	}
796
797	/// Network messages used by the approval distribution subsystem.
798	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
799	pub enum ApprovalDistributionMessage {
800		/// Assignments for candidates in recent, unfinalized blocks.
801		///
802		/// Actually checking the assignment may yield a different result.
803		#[codec(index = 0)]
804		Assignments(Vec<(IndirectAssignmentCert, CandidateIndex)>),
805		/// Approvals for candidates in some recent, unfinalized block.
806		#[codec(index = 1)]
807		Approvals(Vec<IndirectSignedApprovalVote>),
808	}
809
810	/// Dummy network message type, so we will receive connect/disconnect events.
811	#[derive(Debug, Clone, PartialEq, Eq)]
812	pub enum GossipSupportNetworkMessage {}
813
814	/// Network messages used by the collator protocol subsystem
815	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
816	pub enum CollatorProtocolMessage {
817		/// Declare the intent to advertise collations under a collator ID, attaching a
818		/// signature of the `PeerId` of the node using the given collator ID key.
819		#[codec(index = 0)]
820		Declare(CollatorId, ParaId, CollatorSignature),
821		/// Advertise a collation to a validator. Can only be sent once the peer has
822		/// declared that they are a collator with given ID.
823		#[codec(index = 1)]
824		AdvertiseCollation {
825			/// Hash of the relay parent advertised collation is based on.
826			relay_parent: Hash,
827			/// Candidate hash.
828			candidate_hash: CandidateHash,
829			/// Parachain head data hash before candidate execution.
830			parent_head_data_hash: Hash,
831		},
832		/// A collation sent to a validator was seconded.
833		#[codec(index = 4)]
834		CollationSeconded(Hash, UncheckedSignedFullStatement),
835	}
836
837	/// All network messages on the validation peer-set.
838	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
839	pub enum ValidationProtocol {
840		/// Bitfield distribution messages
841		#[codec(index = 1)]
842		#[from]
843		BitfieldDistribution(BitfieldDistributionMessage),
844		/// Statement distribution messages
845		#[codec(index = 3)]
846		#[from]
847		StatementDistribution(StatementDistributionMessage),
848		/// Approval distribution messages
849		#[codec(index = 4)]
850		#[from]
851		ApprovalDistribution(ApprovalDistributionMessage),
852	}
853
854	/// All network messages on the collation peer-set.
855	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
856	pub enum CollationProtocol {
857		/// Collator protocol messages
858		#[codec(index = 0)]
859		#[from]
860		CollatorProtocol(CollatorProtocolMessage),
861	}
862
863	/// Get the payload that should be signed and included in a `Declare` message.
864	///
865	/// The payload is the local peer id of the node, which serves to prove that it
866	/// controls the collator key it is declaring an intention to collate under.
867	pub fn declare_signature_payload(peer_id: &sc_network_types::PeerId) -> Vec<u8> {
868		let mut payload = peer_id.to_bytes();
869		payload.extend_from_slice(b"COLL");
870		payload
871	}
872}
873
874/// v3 network protocol types.
875/// Purpose is for changing ApprovalDistributionMessage to
876/// include more than one assignment and approval in a message.
877pub mod v3 {
878	use codec::{Decode, Encode};
879
880	use polkadot_node_primitives::approval::v2::{
881		CandidateBitfield, IndirectAssignmentCertV2, IndirectSignedApprovalVoteV2,
882	};
883
884	/// This parts of the protocol did not change from v2, so just alias them in v3.
885	pub use super::v2::{
886		declare_signature_payload, BackedCandidateAcknowledgement, BackedCandidateManifest,
887		BitfieldDistributionMessage, GossipSupportNetworkMessage, StatementDistributionMessage,
888		StatementFilter,
889	};
890
891	/// Network messages used by the approval distribution subsystem.
892	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
893	pub enum ApprovalDistributionMessage {
894		/// Assignments for candidates in recent, unfinalized blocks.
895		/// We use a bitfield to reference claimed candidates, where the bit index is equal to
896		/// candidate index.
897		///
898		/// Actually checking the assignment may yield a different result.
899		///
900		/// TODO at next protocol upgrade opportunity:
901		/// - remove redundancy `candidate_index` vs `core_index`
902		/// - `<https://github.com/paritytech/polkadot-sdk/issues/675>`
903		#[codec(index = 0)]
904		Assignments(Vec<(IndirectAssignmentCertV2, CandidateBitfield)>),
905		/// Approvals for candidates in some recent, unfinalized block.
906		#[codec(index = 1)]
907		Approvals(Vec<IndirectSignedApprovalVoteV2>),
908	}
909
910	/// All network messages on the validation peer-set.
911	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
912	pub enum ValidationProtocol {
913		/// Bitfield distribution messages
914		#[codec(index = 1)]
915		#[from]
916		BitfieldDistribution(BitfieldDistributionMessage),
917		/// Statement distribution messages
918		#[codec(index = 3)]
919		#[from]
920		StatementDistribution(StatementDistributionMessage),
921		/// Approval distribution messages
922		#[codec(index = 4)]
923		#[from]
924		ApprovalDistribution(ApprovalDistributionMessage),
925	}
926}
927
928/// Returns the subset of `peers` with the specified `version`.
929pub fn filter_by_peer_version(
930	peers: &[(PeerId, peer_set::ProtocolVersion)],
931	version: peer_set::ProtocolVersion,
932) -> Vec<PeerId> {
933	peers.iter().filter(|(_, v)| v == &version).map(|(p, _)| *p).collect::<Vec<_>>()
934}