1#![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
35pub mod peer_set;
37
38pub mod request_response;
40
41pub mod authority_discovery;
43pub mod grid_topology;
45
46pub const MIN_GOSSIP_PEERS: usize = 25;
48
49#[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#[derive(Debug, Clone, Copy, PartialEq)]
63pub enum ObservedRole {
64	Light,
66	Full,
68	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#[derive(Debug, Clone, Default)]
94pub struct OurView {
95	view: View,
96}
97
98impl OurView {
99	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#[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#[derive(Default, Debug, Clone, PartialEq, Eq, Encode, Decode)]
146pub struct View {
147	heads: Vec<Hash>,
150	pub finalized_number: BlockNumber,
152}
153
154#[macro_export]
166macro_rules! view {
167	( $( $hash:expr ),* $(,)? ) => {
168		$crate::View::new(vec![ $( $hash.clone() ),* ], 0)
169	};
170}
171
172impl View {
173	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	pub fn with_finalized(finalized_number: BlockNumber) -> Self {
182		Self { heads: Vec::new(), finalized_number }
183	}
184
185	pub fn len(&self) -> usize {
187		self.heads.len()
188	}
189
190	pub fn is_empty(&self) -> bool {
192		self.heads.is_empty()
193	}
194
195	pub fn iter(&self) -> impl Iterator<Item = &Hash> {
197		self.heads.iter()
198	}
199
200	pub fn into_iter(self) -> impl Iterator<Item = Hash> {
202		self.heads.into_iter()
203	}
204
205	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	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	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	pub fn contains(&self, hash: &Hash) -> bool {
226		self.heads.contains(hash)
227	}
228
229	pub fn check_heads_eq(&self, other: &Self) -> bool {
234		self.heads == other.heads
235	}
236}
237
238#[derive(Debug, Clone, PartialEq, Eq)]
240pub enum ValidationProtocols<V3> {
241	V3(V3),
243}
244
245#[derive(Debug, Clone, PartialEq, Eq)]
247pub enum CollationProtocols<V1, V2> {
248	V1(V1),
250	V2(V2),
252}
253
254impl<V3: Clone> ValidationProtocols<&'_ V3> {
255	pub fn clone_inner(&self) -> ValidationProtocols<V3> {
257		match *self {
258			ValidationProtocols::V3(inner) => ValidationProtocols::V3(inner.clone()),
259		}
260	}
261}
262
263impl<V1: Clone, V2: Clone> CollationProtocols<&'_ V1, &'_ V2> {
264	pub fn clone_inner(&self) -> CollationProtocols<V1, V2> {
266		match *self {
267			CollationProtocols::V1(inner) => CollationProtocols::V1(inner.clone()),
268			CollationProtocols::V2(inner) => CollationProtocols::V2(inner.clone()),
269		}
270	}
271}
272
273pub type VersionedValidationProtocol = ValidationProtocols<v3::ValidationProtocol>;
275
276impl From<v3::ValidationProtocol> for VersionedValidationProtocol {
277	fn from(v3: v3::ValidationProtocol) -> Self {
278		VersionedValidationProtocol::V3(v3)
279	}
280}
281
282pub type VersionedCollationProtocol =
284	CollationProtocols<v1::CollationProtocol, v2::CollationProtocol>;
285
286impl From<v1::CollationProtocol> for VersionedCollationProtocol {
287	fn from(v1: v1::CollationProtocol) -> Self {
288		VersionedCollationProtocol::V1(v1)
289	}
290}
291
292impl From<v2::CollationProtocol> for VersionedCollationProtocol {
293	fn from(v2: v2::CollationProtocol) -> Self {
294		VersionedCollationProtocol::V2(v2)
295	}
296}
297
298macro_rules! impl_versioned_validation_full_protocol_from {
299	($from:ty, $out:ty, $variant:ident) => {
300		impl From<$from> for $out {
301			fn from(versioned_from: $from) -> $out {
302				match versioned_from {
303					ValidationProtocols::V3(x) => ValidationProtocols::V3(x.into()),
304				}
305			}
306		}
307	};
308}
309
310macro_rules! impl_versioned_collation_full_protocol_from {
311	($from:ty, $out:ty, $variant:ident) => {
312		impl From<$from> for $out {
313			fn from(versioned_from: $from) -> $out {
314				match versioned_from {
315					CollationProtocols::V1(x) => CollationProtocols::V1(x.into()),
316					CollationProtocols::V2(x) => CollationProtocols::V2(x.into()),
317				}
318			}
319		}
320	};
321}
322
323macro_rules! impl_versioned_validation_try_from {
326	(
327		$from:ty,
328		$out:ty,
329		$v3_pat:pat => $v3_out:expr
330	) => {
331		impl TryFrom<$from> for $out {
332			type Error = crate::WrongVariant;
333
334			fn try_from(x: $from) -> Result<$out, Self::Error> {
335				#[allow(unreachable_patterns)] match x {
337					ValidationProtocols::V3($v3_pat) => Ok(ValidationProtocols::V3($v3_out)),
338					_ => Err(crate::WrongVariant),
339				}
340			}
341		}
342
343		impl<'a> TryFrom<&'a $from> for $out {
344			type Error = crate::WrongVariant;
345
346			fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
347				#[allow(unreachable_patterns)] match x {
349					ValidationProtocols::V3($v3_pat) =>
350						Ok(ValidationProtocols::V3($v3_out.clone())),
351					_ => Err(crate::WrongVariant),
352				}
353			}
354		}
355	};
356}
357
358macro_rules! impl_versioned_collation_try_from {
361	(
362		$from:ty,
363		$out:ty,
364		$v1_pat:pat => $v1_out:expr,
365		$v2_pat:pat => $v2_out:expr
366	) => {
367		impl TryFrom<$from> for $out {
368			type Error = crate::WrongVariant;
369
370			fn try_from(x: $from) -> Result<$out, Self::Error> {
371				#[allow(unreachable_patterns)] match x {
373					CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out)),
374					CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out)),
375					_ => Err(crate::WrongVariant),
376				}
377			}
378		}
379
380		impl<'a> TryFrom<&'a $from> for $out {
381			type Error = crate::WrongVariant;
382
383			fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
384				#[allow(unreachable_patterns)] match x {
386					CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out.clone())),
387					CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out.clone())),
388					_ => Err(crate::WrongVariant),
389				}
390			}
391		}
392	};
393}
394
395pub type BitfieldDistributionMessage = ValidationProtocols<v3::BitfieldDistributionMessage>;
397impl_versioned_validation_full_protocol_from!(
398	BitfieldDistributionMessage,
399	VersionedValidationProtocol,
400	BitfieldDistribution
401);
402impl_versioned_validation_try_from!(
403	VersionedValidationProtocol,
404	BitfieldDistributionMessage,
405	v3::ValidationProtocol::BitfieldDistribution(x) => x
406);
407
408pub type StatementDistributionMessage = ValidationProtocols<v3::StatementDistributionMessage>;
410impl_versioned_validation_full_protocol_from!(
411	StatementDistributionMessage,
412	VersionedValidationProtocol,
413	StatementDistribution
414);
415impl_versioned_validation_try_from!(
416	VersionedValidationProtocol,
417	StatementDistributionMessage,
418	v3::ValidationProtocol::StatementDistribution(x) => x
419);
420
421pub type ApprovalDistributionMessage = ValidationProtocols<v3::ApprovalDistributionMessage>;
423impl_versioned_validation_full_protocol_from!(
424	ApprovalDistributionMessage,
425	VersionedValidationProtocol,
426	ApprovalDistribution
427);
428impl_versioned_validation_try_from!(
429	VersionedValidationProtocol,
430	ApprovalDistributionMessage,
431	v3::ValidationProtocol::ApprovalDistribution(x) => x
432
433);
434
435pub type GossipSupportNetworkMessage = ValidationProtocols<v3::GossipSupportNetworkMessage>;
437
438impl TryFrom<VersionedValidationProtocol> for GossipSupportNetworkMessage {
440	type Error = WrongVariant;
441	fn try_from(_: VersionedValidationProtocol) -> Result<Self, Self::Error> {
442		Err(WrongVariant)
443	}
444}
445
446impl<'a> TryFrom<&'a VersionedValidationProtocol> for GossipSupportNetworkMessage {
447	type Error = WrongVariant;
448	fn try_from(_: &'a VersionedValidationProtocol) -> Result<Self, Self::Error> {
449		Err(WrongVariant)
450	}
451}
452
453pub type CollatorProtocolMessage =
455	CollationProtocols<v1::CollatorProtocolMessage, v2::CollatorProtocolMessage>;
456impl_versioned_collation_full_protocol_from!(
457	CollatorProtocolMessage,
458	VersionedCollationProtocol,
459	CollatorProtocol
460);
461impl_versioned_collation_try_from!(
462	VersionedCollationProtocol,
463	CollatorProtocolMessage,
464	v1::CollationProtocol::CollatorProtocol(x) => x,
465	v2::CollationProtocol::CollatorProtocol(x) => x
466);
467
468pub mod v1 {
470	use codec::{Decode, Encode};
471
472	use polkadot_primitives::{CollatorId, CollatorSignature, Hash, Id as ParaId};
473
474	use polkadot_node_primitives::UncheckedSignedFullStatement;
475
476	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
478	pub enum CollatorProtocolMessage {
479		#[codec(index = 0)]
482		Declare(CollatorId, ParaId, CollatorSignature),
483		#[codec(index = 1)]
486		AdvertiseCollation(Hash),
487		#[codec(index = 4)]
489		CollationSeconded(Hash, UncheckedSignedFullStatement),
490	}
491
492	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
494	pub enum CollationProtocol {
495		#[codec(index = 0)]
497		#[from]
498		CollatorProtocol(CollatorProtocolMessage),
499	}
500
501	pub fn declare_signature_payload(peer_id: &sc_network_types::PeerId) -> Vec<u8> {
506		let mut payload = peer_id.to_bytes();
507		payload.extend_from_slice(b"COLL");
508		payload
509	}
510}
511
512pub mod v2 {
514	use codec::{Decode, Encode};
515
516	use polkadot_primitives::{CandidateHash, CollatorId, CollatorSignature, Hash, Id as ParaId};
517
518	use polkadot_node_primitives::UncheckedSignedFullStatement;
519
520	pub use super::v1::declare_signature_payload;
522
523	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
525	pub enum CollatorProtocolMessage {
526		#[codec(index = 0)]
529		Declare(CollatorId, ParaId, CollatorSignature),
530		#[codec(index = 1)]
533		AdvertiseCollation {
534			relay_parent: Hash,
536			candidate_hash: CandidateHash,
538			parent_head_data_hash: Hash,
540		},
541		#[codec(index = 4)]
543		CollationSeconded(Hash, UncheckedSignedFullStatement),
544	}
545
546	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
548	pub enum CollationProtocol {
549		#[codec(index = 0)]
551		#[from]
552		CollatorProtocol(CollatorProtocolMessage),
553	}
554}
555
556pub mod v3 {
560	use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec};
561	use codec::{Decode, Encode};
562
563	use polkadot_primitives::{
564		CandidateHash, GroupIndex, Hash, Id as ParaId, UncheckedSignedAvailabilityBitfield,
565		UncheckedSignedStatement,
566	};
567
568	use polkadot_node_primitives::approval::v2::{
569		CandidateBitfield, IndirectAssignmentCertV2, IndirectSignedApprovalVoteV2,
570	};
571
572	pub use super::v2::declare_signature_payload;
574
575	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
577	pub enum BitfieldDistributionMessage {
578		#[codec(index = 0)]
580		Bitfield(Hash, UncheckedSignedAvailabilityBitfield),
581	}
582
583	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
586	pub struct StatementFilter {
587		pub seconded_in_group: BitVec<u8, Lsb0>,
589		pub validated_in_group: BitVec<u8, Lsb0>,
591	}
592
593	impl StatementFilter {
594		pub fn blank(group_size: usize) -> Self {
596			StatementFilter {
597				seconded_in_group: BitVec::repeat(false, group_size),
598				validated_in_group: BitVec::repeat(false, group_size),
599			}
600		}
601
602		pub fn full(group_size: usize) -> Self {
604			StatementFilter {
605				seconded_in_group: BitVec::repeat(true, group_size),
606				validated_in_group: BitVec::repeat(true, group_size),
607			}
608		}
609
610		pub fn has_len(&self, len: usize) -> bool {
613			self.seconded_in_group.len() == len && self.validated_in_group.len() == len
614		}
615
616		pub fn backing_validators(&self) -> usize {
618			self.seconded_in_group
619				.iter()
620				.by_vals()
621				.zip(self.validated_in_group.iter().by_vals())
622				.filter(|&(s, v)| s || v) .count()
624		}
625
626		pub fn has_seconded(&self) -> bool {
628			self.seconded_in_group.iter().by_vals().any(|x| x)
629		}
630
631		pub fn mask_seconded(&mut self, mask: &BitSlice<u8, Lsb0>) {
634			for (mut x, mask) in self
635				.seconded_in_group
636				.iter_mut()
637				.zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
638			{
639				*x = *x && !mask;
645			}
646		}
647
648		pub fn mask_valid(&mut self, mask: &BitSlice<u8, Lsb0>) {
651			for (mut x, mask) in self
652				.validated_in_group
653				.iter_mut()
654				.zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
655			{
656				*x = *x && !mask;
662			}
663		}
664	}
665
666	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
669	pub struct BackedCandidateManifest {
670		pub relay_parent: Hash,
672		pub candidate_hash: CandidateHash,
674		pub group_index: GroupIndex,
676		pub para_id: ParaId,
680		pub parent_head_data_hash: Hash,
682		pub statement_knowledge: StatementFilter,
690	}
691
692	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
694	pub struct BackedCandidateAcknowledgement {
695		pub candidate_hash: CandidateHash,
697		pub statement_knowledge: StatementFilter,
705	}
706
707	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
709	pub enum StatementDistributionMessage {
710		#[codec(index = 0)]
712		Statement(Hash, UncheckedSignedStatement),
713
714		#[codec(index = 1)]
718		BackedCandidateManifest(BackedCandidateManifest),
719
720		#[codec(index = 2)]
723		BackedCandidateKnown(BackedCandidateAcknowledgement),
724	}
725
726	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
728	pub enum ApprovalDistributionMessage {
729		#[codec(index = 0)]
739		Assignments(Vec<(IndirectAssignmentCertV2, CandidateBitfield)>),
740		#[codec(index = 1)]
742		Approvals(Vec<IndirectSignedApprovalVoteV2>),
743	}
744
745	#[derive(Debug, Clone, PartialEq, Eq)]
747	pub enum GossipSupportNetworkMessage {}
748
749	#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
751	pub enum ValidationProtocol {
752		#[codec(index = 1)]
754		#[from]
755		BitfieldDistribution(BitfieldDistributionMessage),
756		#[codec(index = 3)]
758		#[from]
759		StatementDistribution(StatementDistributionMessage),
760		#[codec(index = 4)]
762		#[from]
763		ApprovalDistribution(ApprovalDistributionMessage),
764	}
765}
766
767pub fn filter_by_peer_version(
769	peers: &[(PeerId, peer_set::ProtocolVersion)],
770	version: peer_set::ProtocolVersion,
771) -> Vec<PeerId> {
772	peers.iter().filter(|(_, v)| v == &version).map(|(p, _)| *p).collect::<Vec<_>>()
773}