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