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, V3, V4> {
248 V1(V1),
250 V2(V2),
252 V3(V3),
254 V4(V4),
256}
257
258impl<V3: Clone> ValidationProtocols<&'_ V3> {
259 pub fn clone_inner(&self) -> ValidationProtocols<V3> {
261 match *self {
262 ValidationProtocols::V3(inner) => ValidationProtocols::V3(inner.clone()),
263 }
264 }
265}
266
267impl<V1: Clone, V2: Clone, V3: Clone, V4: Clone>
268 CollationProtocols<&'_ V1, &'_ V2, &'_ V3, &'_ V4>
269{
270 pub fn clone_inner(&self) -> CollationProtocols<V1, V2, V3, V4> {
272 match *self {
273 CollationProtocols::V1(inner) => CollationProtocols::V1(inner.clone()),
274 CollationProtocols::V2(inner) => CollationProtocols::V2(inner.clone()),
275 CollationProtocols::V3(inner) => CollationProtocols::V3(inner.clone()),
276 CollationProtocols::V4(inner) => CollationProtocols::V4(inner.clone()),
277 }
278 }
279}
280
281pub type VersionedValidationProtocol = ValidationProtocols<v3::ValidationProtocol>;
283
284impl From<v3::ValidationProtocol> for VersionedValidationProtocol {
285 fn from(v3: v3::ValidationProtocol) -> Self {
286 VersionedValidationProtocol::V3(v3)
287 }
288}
289
290pub type VersionedCollationProtocol = CollationProtocols<
292 v1::CollationProtocol,
293 v2::CollationProtocol,
294 v3_collation::CollationProtocol,
295 v4_collation::CollationProtocol,
296>;
297
298impl From<v1::CollationProtocol> for VersionedCollationProtocol {
299 fn from(v1: v1::CollationProtocol) -> Self {
300 VersionedCollationProtocol::V1(v1)
301 }
302}
303
304impl From<v2::CollationProtocol> for VersionedCollationProtocol {
305 fn from(v2: v2::CollationProtocol) -> Self {
306 VersionedCollationProtocol::V2(v2)
307 }
308}
309
310impl From<v3_collation::CollationProtocol> for VersionedCollationProtocol {
311 fn from(v3: v3_collation::CollationProtocol) -> Self {
312 VersionedCollationProtocol::V3(v3)
313 }
314}
315
316impl From<v4_collation::CollationProtocol> for VersionedCollationProtocol {
317 fn from(v4: v4_collation::CollationProtocol) -> Self {
318 VersionedCollationProtocol::V4(v4)
319 }
320}
321
322macro_rules! impl_versioned_validation_full_protocol_from {
323 ($from:ty, $out:ty, $variant:ident) => {
324 impl From<$from> for $out {
325 fn from(versioned_from: $from) -> $out {
326 match versioned_from {
327 ValidationProtocols::V3(x) => ValidationProtocols::V3(x.into()),
328 }
329 }
330 }
331 };
332}
333
334macro_rules! impl_versioned_collation_full_protocol_from {
335 ($from:ty, $out:ty, $variant:ident) => {
336 impl From<$from> for $out {
337 fn from(versioned_from: $from) -> $out {
338 match versioned_from {
339 CollationProtocols::V1(x) => CollationProtocols::V1(x.into()),
340 CollationProtocols::V2(x) => CollationProtocols::V2(x.into()),
341 CollationProtocols::V3(x) => CollationProtocols::V3(x.into()),
342 CollationProtocols::V4(x) => CollationProtocols::V4(x.into()),
343 }
344 }
345 }
346 };
347}
348
349macro_rules! impl_versioned_validation_try_from {
352 (
353 $from:ty,
354 $out:ty,
355 $v3_pat:pat => $v3_out:expr
356 ) => {
357 impl TryFrom<$from> for $out {
358 type Error = crate::WrongVariant;
359
360 fn try_from(x: $from) -> Result<$out, Self::Error> {
361 #[allow(unreachable_patterns)] match x {
363 ValidationProtocols::V3($v3_pat) => Ok(ValidationProtocols::V3($v3_out)),
364 _ => Err(crate::WrongVariant),
365 }
366 }
367 }
368
369 impl<'a> TryFrom<&'a $from> for $out {
370 type Error = crate::WrongVariant;
371
372 fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
373 #[allow(unreachable_patterns)] match x {
375 ValidationProtocols::V3($v3_pat) => {
376 Ok(ValidationProtocols::V3($v3_out.clone()))
377 },
378 _ => Err(crate::WrongVariant),
379 }
380 }
381 }
382 };
383}
384
385macro_rules! impl_versioned_collation_try_from {
388 (
389 $from:ty,
390 $out:ty,
391 $v1_pat:pat => $v1_out:expr,
392 $v2_pat:pat => $v2_out:expr,
393 $v3_pat:pat => $v3_out:expr,
394 $v4_pat:pat => $v4_out:expr
395 ) => {
396 impl TryFrom<$from> for $out {
397 type Error = crate::WrongVariant;
398
399 fn try_from(x: $from) -> Result<$out, Self::Error> {
400 #[allow(unreachable_patterns)] match x {
402 CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out)),
403 CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out)),
404 CollationProtocols::V3($v3_pat) => Ok(CollationProtocols::V3($v3_out)),
405 CollationProtocols::V4($v4_pat) => Ok(CollationProtocols::V4($v4_out)),
406 _ => Err(crate::WrongVariant),
407 }
408 }
409 }
410
411 impl<'a> TryFrom<&'a $from> for $out {
412 type Error = crate::WrongVariant;
413
414 fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
415 #[allow(unreachable_patterns)] match x {
417 CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out.clone())),
418 CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out.clone())),
419 CollationProtocols::V3($v3_pat) => Ok(CollationProtocols::V3($v3_out.clone())),
420 CollationProtocols::V4($v4_pat) => Ok(CollationProtocols::V4($v4_out.clone())),
421 _ => Err(crate::WrongVariant),
422 }
423 }
424 }
425 };
426}
427
428pub type BitfieldDistributionMessage = ValidationProtocols<v3::BitfieldDistributionMessage>;
430impl_versioned_validation_full_protocol_from!(
431 BitfieldDistributionMessage,
432 VersionedValidationProtocol,
433 BitfieldDistribution
434);
435impl_versioned_validation_try_from!(
436 VersionedValidationProtocol,
437 BitfieldDistributionMessage,
438 v3::ValidationProtocol::BitfieldDistribution(x) => x
439);
440
441pub type StatementDistributionMessage = ValidationProtocols<v3::StatementDistributionMessage>;
443impl_versioned_validation_full_protocol_from!(
444 StatementDistributionMessage,
445 VersionedValidationProtocol,
446 StatementDistribution
447);
448impl_versioned_validation_try_from!(
449 VersionedValidationProtocol,
450 StatementDistributionMessage,
451 v3::ValidationProtocol::StatementDistribution(x) => x
452);
453
454pub type ApprovalDistributionMessage = ValidationProtocols<v3::ApprovalDistributionMessage>;
456impl_versioned_validation_full_protocol_from!(
457 ApprovalDistributionMessage,
458 VersionedValidationProtocol,
459 ApprovalDistribution
460);
461impl_versioned_validation_try_from!(
462 VersionedValidationProtocol,
463 ApprovalDistributionMessage,
464 v3::ValidationProtocol::ApprovalDistribution(x) => x
465
466);
467
468pub type GossipSupportNetworkMessage = ValidationProtocols<v3::GossipSupportNetworkMessage>;
470
471impl TryFrom<VersionedValidationProtocol> for GossipSupportNetworkMessage {
473 type Error = WrongVariant;
474 fn try_from(_: VersionedValidationProtocol) -> Result<Self, Self::Error> {
475 Err(WrongVariant)
476 }
477}
478
479impl<'a> TryFrom<&'a VersionedValidationProtocol> for GossipSupportNetworkMessage {
480 type Error = WrongVariant;
481 fn try_from(_: &'a VersionedValidationProtocol) -> Result<Self, Self::Error> {
482 Err(WrongVariant)
483 }
484}
485
486pub type CollatorProtocolMessage = CollationProtocols<
488 v1::CollatorProtocolMessage,
489 v2::CollatorProtocolMessage,
490 v3_collation::CollatorProtocolMessage,
491 v4_collation::AdvertiseSegment,
492>;
493impl_versioned_collation_full_protocol_from!(
494 CollatorProtocolMessage,
495 VersionedCollationProtocol,
496 CollatorProtocol
497);
498impl_versioned_collation_try_from!(
499 VersionedCollationProtocol,
500 CollatorProtocolMessage,
501 v1::CollationProtocol::CollatorProtocol(x) => x,
502 v2::CollationProtocol::CollatorProtocol(x) => x,
503 v3_collation::CollationProtocol::CollatorProtocol(x) => x,
504 x => x
505);
506
507pub mod v1 {
509 use codec::{Decode, Encode};
510
511 use polkadot_primitives::{CollatorId, CollatorSignature, Hash, Id as ParaId};
512
513 use polkadot_node_primitives::UncheckedSignedFullStatement;
514
515 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
517 pub enum CollatorProtocolMessage {
518 #[codec(index = 0)]
521 Declare(CollatorId, ParaId, CollatorSignature),
522 #[codec(index = 1)]
525 AdvertiseCollation(Hash),
526 #[codec(index = 4)]
528 CollationSeconded(Hash, UncheckedSignedFullStatement),
529 }
530
531 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
533 pub enum CollationProtocol {
534 #[codec(index = 0)]
536 #[from]
537 CollatorProtocol(CollatorProtocolMessage),
538 }
539
540 pub fn declare_signature_payload(peer_id: &sc_network_types::PeerId) -> Vec<u8> {
545 let mut payload = peer_id.to_bytes();
546 payload.extend_from_slice(b"COLL");
547 payload
548 }
549}
550
551pub mod v2 {
553 use codec::{Decode, Encode};
554
555 use polkadot_primitives::{CandidateHash, CollatorId, CollatorSignature, Hash, Id as ParaId};
556
557 use polkadot_node_primitives::UncheckedSignedFullStatement;
558
559 pub use super::v1::declare_signature_payload;
561
562 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
564 pub enum CollatorProtocolMessage {
565 #[codec(index = 0)]
568 Declare(CollatorId, ParaId, CollatorSignature),
569 #[codec(index = 1)]
572 AdvertiseCollation {
573 scheduling_parent: Hash,
575 candidate_hash: CandidateHash,
577 parent_head_data_hash: Hash,
579 },
580 #[codec(index = 4)]
582 CollationSeconded(Hash, UncheckedSignedFullStatement),
583 }
584
585 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
587 pub enum CollationProtocol {
588 #[codec(index = 0)]
590 #[from]
591 CollatorProtocol(CollatorProtocolMessage),
592 }
593}
594
595pub mod v3_collation {
597 use codec::{Decode, Encode};
598
599 use polkadot_primitives::{
600 CandidateDescriptorVersion, CandidateHash, CollatorId, CollatorSignature, Hash,
601 Id as ParaId,
602 };
603
604 use polkadot_node_primitives::UncheckedSignedFullStatement;
605
606 pub use super::v2::declare_signature_payload;
608
609 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
611 pub enum CollatorProtocolMessage {
612 #[codec(index = 0)]
615 Declare(CollatorId, ParaId, CollatorSignature),
616 #[codec(index = 1)]
619 AdvertiseCollation {
620 scheduling_parent: Hash,
623 candidate_hash: CandidateHash,
625 parent_head_data_hash: Hash,
627 candidate_descriptor_version: CandidateDescriptorVersion,
629 relay_parent: Hash,
631 },
632 #[codec(index = 4)]
634 CollationSeconded(Hash, UncheckedSignedFullStatement),
635 }
636
637 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
639 pub enum CollationProtocol {
640 #[codec(index = 0)]
642 #[from]
643 CollatorProtocol(CollatorProtocolMessage),
644 }
645}
646
647pub mod v4_collation {
649 use codec::{Decode, Encode};
650 pub use polkadot_node_primitives::MAX_SEGMENT_LEN;
652 use polkadot_primitives::{CandidateDescriptorVersion, Hash, Id as ParaId};
653 use sp_runtime::{traits::ConstU32, BoundedVec};
654
655 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
669 pub struct AdvertiseSegment {
670 pub scheduling_parent: Hash,
672 pub para_id: ParaId,
674 pub candidates_descriptor_version: CandidateDescriptorVersion,
676 pub candidates: BoundedVec<CandidateFingerprint, ConstU32<MAX_SEGMENT_LEN>>,
678 }
679
680 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
682 pub struct CandidateFingerprint {
683 pub output_head_data_hash: Hash,
687 pub parent_head_data_hash: Hash,
689 pub claim_queue_offset: u8,
691 }
692
693 pub type CollationProtocol = AdvertiseSegment;
698}
699
700pub mod v3 {
704 use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec};
705 use codec::{Decode, Encode};
706
707 use polkadot_primitives::{
708 CandidateHash, GroupIndex, Hash, Id as ParaId, UncheckedSignedAvailabilityBitfield,
709 UncheckedSignedStatement,
710 };
711
712 use polkadot_node_primitives::approval::v2::{
713 CandidateBitfield, IndirectAssignmentCertV2, IndirectSignedApprovalVoteV2,
714 };
715
716 pub use super::v2::declare_signature_payload;
718
719 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
721 pub enum BitfieldDistributionMessage {
722 #[codec(index = 0)]
724 Bitfield(Hash, UncheckedSignedAvailabilityBitfield),
725 }
726
727 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
730 pub struct StatementFilter {
731 pub seconded_in_group: BitVec<u8, Lsb0>,
733 pub validated_in_group: BitVec<u8, Lsb0>,
735 }
736
737 impl StatementFilter {
738 pub fn blank(group_size: usize) -> Self {
740 StatementFilter {
741 seconded_in_group: BitVec::repeat(false, group_size),
742 validated_in_group: BitVec::repeat(false, group_size),
743 }
744 }
745
746 pub fn full(group_size: usize) -> Self {
748 StatementFilter {
749 seconded_in_group: BitVec::repeat(true, group_size),
750 validated_in_group: BitVec::repeat(true, group_size),
751 }
752 }
753
754 pub fn has_len(&self, len: usize) -> bool {
757 self.seconded_in_group.len() == len && self.validated_in_group.len() == len
758 }
759
760 pub fn backing_validators(&self) -> usize {
762 self.seconded_in_group
763 .iter()
764 .by_vals()
765 .zip(self.validated_in_group.iter().by_vals())
766 .filter(|&(s, v)| s || v) .count()
768 }
769
770 pub fn has_seconded(&self) -> bool {
772 self.seconded_in_group.iter().by_vals().any(|x| x)
773 }
774
775 pub fn mask_seconded(&mut self, mask: &BitSlice<u8, Lsb0>) {
778 for (mut x, mask) in self
779 .seconded_in_group
780 .iter_mut()
781 .zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
782 {
783 *x = *x && !mask;
789 }
790 }
791
792 pub fn mask_valid(&mut self, mask: &BitSlice<u8, Lsb0>) {
795 for (mut x, mask) in self
796 .validated_in_group
797 .iter_mut()
798 .zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
799 {
800 *x = *x && !mask;
806 }
807 }
808 }
809
810 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
813 pub struct BackedCandidateManifest {
814 pub scheduling_parent: Hash,
816 pub candidate_hash: CandidateHash,
818 pub group_index: GroupIndex,
820 pub para_id: ParaId,
824 pub parent_head_data_hash: Hash,
826 pub statement_knowledge: StatementFilter,
834 }
835
836 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
838 pub struct BackedCandidateAcknowledgement {
839 pub candidate_hash: CandidateHash,
841 pub statement_knowledge: StatementFilter,
849 }
850
851 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
853 pub enum StatementDistributionMessage {
854 #[codec(index = 0)]
856 Statement(Hash, UncheckedSignedStatement),
857
858 #[codec(index = 1)]
862 BackedCandidateManifest(BackedCandidateManifest),
863
864 #[codec(index = 2)]
867 BackedCandidateKnown(BackedCandidateAcknowledgement),
868 }
869
870 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
872 pub enum ApprovalDistributionMessage {
873 #[codec(index = 0)]
883 Assignments(Vec<(IndirectAssignmentCertV2, CandidateBitfield)>),
884 #[codec(index = 1)]
886 Approvals(Vec<IndirectSignedApprovalVoteV2>),
887 }
888
889 #[derive(Debug, Clone, PartialEq, Eq)]
891 pub enum GossipSupportNetworkMessage {}
892
893 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
895 pub enum ValidationProtocol {
896 #[codec(index = 1)]
898 #[from]
899 BitfieldDistribution(BitfieldDistributionMessage),
900 #[codec(index = 3)]
902 #[from]
903 StatementDistribution(StatementDistributionMessage),
904 #[codec(index = 4)]
906 #[from]
907 ApprovalDistribution(ApprovalDistributionMessage),
908 }
909}
910
911pub 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}