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> {
248 V1(V1),
250 V2(V2),
252 V3(V3),
254}
255
256impl<V3: Clone> ValidationProtocols<&'_ V3> {
257 pub fn clone_inner(&self) -> ValidationProtocols<V3> {
259 match *self {
260 ValidationProtocols::V3(inner) => ValidationProtocols::V3(inner.clone()),
261 }
262 }
263}
264
265impl<V1: Clone, V2: Clone, V3: Clone> CollationProtocols<&'_ V1, &'_ V2, &'_ V3> {
266 pub fn clone_inner(&self) -> CollationProtocols<V1, V2, V3> {
268 match *self {
269 CollationProtocols::V1(inner) => CollationProtocols::V1(inner.clone()),
270 CollationProtocols::V2(inner) => CollationProtocols::V2(inner.clone()),
271 CollationProtocols::V3(inner) => CollationProtocols::V3(inner.clone()),
272 }
273 }
274}
275
276pub type VersionedValidationProtocol = ValidationProtocols<v3::ValidationProtocol>;
278
279impl From<v3::ValidationProtocol> for VersionedValidationProtocol {
280 fn from(v3: v3::ValidationProtocol) -> Self {
281 VersionedValidationProtocol::V3(v3)
282 }
283}
284
285pub type VersionedCollationProtocol = CollationProtocols<
287 v1::CollationProtocol,
288 v2::CollationProtocol,
289 v3_collation::CollationProtocol,
290>;
291
292impl From<v1::CollationProtocol> for VersionedCollationProtocol {
293 fn from(v1: v1::CollationProtocol) -> Self {
294 VersionedCollationProtocol::V1(v1)
295 }
296}
297
298impl From<v2::CollationProtocol> for VersionedCollationProtocol {
299 fn from(v2: v2::CollationProtocol) -> Self {
300 VersionedCollationProtocol::V2(v2)
301 }
302}
303
304impl From<v3_collation::CollationProtocol> for VersionedCollationProtocol {
305 fn from(v3: v3_collation::CollationProtocol) -> Self {
306 VersionedCollationProtocol::V3(v3)
307 }
308}
309
310macro_rules! impl_versioned_validation_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 ValidationProtocols::V3(x) => ValidationProtocols::V3(x.into()),
316 }
317 }
318 }
319 };
320}
321
322macro_rules! impl_versioned_collation_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 CollationProtocols::V1(x) => CollationProtocols::V1(x.into()),
328 CollationProtocols::V2(x) => CollationProtocols::V2(x.into()),
329 CollationProtocols::V3(x) => CollationProtocols::V3(x.into()),
330 }
331 }
332 }
333 };
334}
335
336macro_rules! impl_versioned_validation_try_from {
339 (
340 $from:ty,
341 $out:ty,
342 $v3_pat:pat => $v3_out:expr
343 ) => {
344 impl TryFrom<$from> for $out {
345 type Error = crate::WrongVariant;
346
347 fn try_from(x: $from) -> Result<$out, Self::Error> {
348 #[allow(unreachable_patterns)] match x {
350 ValidationProtocols::V3($v3_pat) => Ok(ValidationProtocols::V3($v3_out)),
351 _ => Err(crate::WrongVariant),
352 }
353 }
354 }
355
356 impl<'a> TryFrom<&'a $from> for $out {
357 type Error = crate::WrongVariant;
358
359 fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
360 #[allow(unreachable_patterns)] match x {
362 ValidationProtocols::V3($v3_pat) => {
363 Ok(ValidationProtocols::V3($v3_out.clone()))
364 },
365 _ => Err(crate::WrongVariant),
366 }
367 }
368 }
369 };
370}
371
372macro_rules! impl_versioned_collation_try_from {
375 (
376 $from:ty,
377 $out:ty,
378 $v1_pat:pat => $v1_out:expr,
379 $v2_pat:pat => $v2_out:expr,
380 $v3_pat:pat => $v3_out:expr
381 ) => {
382 impl TryFrom<$from> for $out {
383 type Error = crate::WrongVariant;
384
385 fn try_from(x: $from) -> Result<$out, Self::Error> {
386 #[allow(unreachable_patterns)] match x {
388 CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out)),
389 CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out)),
390 CollationProtocols::V3($v3_pat) => Ok(CollationProtocols::V3($v3_out)),
391 _ => Err(crate::WrongVariant),
392 }
393 }
394 }
395
396 impl<'a> TryFrom<&'a $from> for $out {
397 type Error = crate::WrongVariant;
398
399 fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
400 #[allow(unreachable_patterns)] match x {
402 CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out.clone())),
403 CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out.clone())),
404 CollationProtocols::V3($v3_pat) => Ok(CollationProtocols::V3($v3_out.clone())),
405 _ => Err(crate::WrongVariant),
406 }
407 }
408 }
409 };
410}
411
412pub type BitfieldDistributionMessage = ValidationProtocols<v3::BitfieldDistributionMessage>;
414impl_versioned_validation_full_protocol_from!(
415 BitfieldDistributionMessage,
416 VersionedValidationProtocol,
417 BitfieldDistribution
418);
419impl_versioned_validation_try_from!(
420 VersionedValidationProtocol,
421 BitfieldDistributionMessage,
422 v3::ValidationProtocol::BitfieldDistribution(x) => x
423);
424
425pub type StatementDistributionMessage = ValidationProtocols<v3::StatementDistributionMessage>;
427impl_versioned_validation_full_protocol_from!(
428 StatementDistributionMessage,
429 VersionedValidationProtocol,
430 StatementDistribution
431);
432impl_versioned_validation_try_from!(
433 VersionedValidationProtocol,
434 StatementDistributionMessage,
435 v3::ValidationProtocol::StatementDistribution(x) => x
436);
437
438pub type ApprovalDistributionMessage = ValidationProtocols<v3::ApprovalDistributionMessage>;
440impl_versioned_validation_full_protocol_from!(
441 ApprovalDistributionMessage,
442 VersionedValidationProtocol,
443 ApprovalDistribution
444);
445impl_versioned_validation_try_from!(
446 VersionedValidationProtocol,
447 ApprovalDistributionMessage,
448 v3::ValidationProtocol::ApprovalDistribution(x) => x
449
450);
451
452pub type GossipSupportNetworkMessage = ValidationProtocols<v3::GossipSupportNetworkMessage>;
454
455impl TryFrom<VersionedValidationProtocol> for GossipSupportNetworkMessage {
457 type Error = WrongVariant;
458 fn try_from(_: VersionedValidationProtocol) -> Result<Self, Self::Error> {
459 Err(WrongVariant)
460 }
461}
462
463impl<'a> TryFrom<&'a VersionedValidationProtocol> for GossipSupportNetworkMessage {
464 type Error = WrongVariant;
465 fn try_from(_: &'a VersionedValidationProtocol) -> Result<Self, Self::Error> {
466 Err(WrongVariant)
467 }
468}
469
470pub type CollatorProtocolMessage = CollationProtocols<
472 v1::CollatorProtocolMessage,
473 v2::CollatorProtocolMessage,
474 v3_collation::CollatorProtocolMessage,
475>;
476impl_versioned_collation_full_protocol_from!(
477 CollatorProtocolMessage,
478 VersionedCollationProtocol,
479 CollatorProtocol
480);
481impl_versioned_collation_try_from!(
482 VersionedCollationProtocol,
483 CollatorProtocolMessage,
484 v1::CollationProtocol::CollatorProtocol(x) => x,
485 v2::CollationProtocol::CollatorProtocol(x) => x,
486 v3_collation::CollationProtocol::CollatorProtocol(x) => x
487);
488
489pub mod v1 {
491 use codec::{Decode, Encode};
492
493 use polkadot_primitives::{CollatorId, CollatorSignature, Hash, Id as ParaId};
494
495 use polkadot_node_primitives::UncheckedSignedFullStatement;
496
497 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
499 pub enum CollatorProtocolMessage {
500 #[codec(index = 0)]
503 Declare(CollatorId, ParaId, CollatorSignature),
504 #[codec(index = 1)]
507 AdvertiseCollation(Hash),
508 #[codec(index = 4)]
510 CollationSeconded(Hash, UncheckedSignedFullStatement),
511 }
512
513 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
515 pub enum CollationProtocol {
516 #[codec(index = 0)]
518 #[from]
519 CollatorProtocol(CollatorProtocolMessage),
520 }
521
522 pub fn declare_signature_payload(peer_id: &sc_network_types::PeerId) -> Vec<u8> {
527 let mut payload = peer_id.to_bytes();
528 payload.extend_from_slice(b"COLL");
529 payload
530 }
531}
532
533pub mod v2 {
535 use codec::{Decode, Encode};
536
537 use polkadot_primitives::{CandidateHash, CollatorId, CollatorSignature, Hash, Id as ParaId};
538
539 use polkadot_node_primitives::UncheckedSignedFullStatement;
540
541 pub use super::v1::declare_signature_payload;
543
544 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
546 pub enum CollatorProtocolMessage {
547 #[codec(index = 0)]
550 Declare(CollatorId, ParaId, CollatorSignature),
551 #[codec(index = 1)]
554 AdvertiseCollation {
555 scheduling_parent: Hash,
557 candidate_hash: CandidateHash,
559 parent_head_data_hash: Hash,
561 },
562 #[codec(index = 4)]
564 CollationSeconded(Hash, UncheckedSignedFullStatement),
565 }
566
567 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
569 pub enum CollationProtocol {
570 #[codec(index = 0)]
572 #[from]
573 CollatorProtocol(CollatorProtocolMessage),
574 }
575}
576
577pub mod v3_collation {
579 use codec::{Decode, Encode};
580
581 use polkadot_primitives::{
582 CandidateDescriptorVersion, CandidateHash, CollatorId, CollatorSignature, Hash,
583 Id as ParaId,
584 };
585
586 use polkadot_node_primitives::UncheckedSignedFullStatement;
587
588 pub use super::v2::declare_signature_payload;
590
591 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
593 pub enum CollatorProtocolMessage {
594 #[codec(index = 0)]
597 Declare(CollatorId, ParaId, CollatorSignature),
598 #[codec(index = 1)]
601 AdvertiseCollation {
602 scheduling_parent: Hash,
605 candidate_hash: CandidateHash,
607 parent_head_data_hash: Hash,
609 candidate_descriptor_version: CandidateDescriptorVersion,
611 relay_parent: Hash,
613 },
614 #[codec(index = 4)]
616 CollationSeconded(Hash, UncheckedSignedFullStatement),
617 }
618
619 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
621 pub enum CollationProtocol {
622 #[codec(index = 0)]
624 #[from]
625 CollatorProtocol(CollatorProtocolMessage),
626 }
627}
628
629pub mod v3 {
633 use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec};
634 use codec::{Decode, Encode};
635
636 use polkadot_primitives::{
637 CandidateHash, GroupIndex, Hash, Id as ParaId, UncheckedSignedAvailabilityBitfield,
638 UncheckedSignedStatement,
639 };
640
641 use polkadot_node_primitives::approval::v2::{
642 CandidateBitfield, IndirectAssignmentCertV2, IndirectSignedApprovalVoteV2,
643 };
644
645 pub use super::v2::declare_signature_payload;
647
648 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
650 pub enum BitfieldDistributionMessage {
651 #[codec(index = 0)]
653 Bitfield(Hash, UncheckedSignedAvailabilityBitfield),
654 }
655
656 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
659 pub struct StatementFilter {
660 pub seconded_in_group: BitVec<u8, Lsb0>,
662 pub validated_in_group: BitVec<u8, Lsb0>,
664 }
665
666 impl StatementFilter {
667 pub fn blank(group_size: usize) -> Self {
669 StatementFilter {
670 seconded_in_group: BitVec::repeat(false, group_size),
671 validated_in_group: BitVec::repeat(false, group_size),
672 }
673 }
674
675 pub fn full(group_size: usize) -> Self {
677 StatementFilter {
678 seconded_in_group: BitVec::repeat(true, group_size),
679 validated_in_group: BitVec::repeat(true, group_size),
680 }
681 }
682
683 pub fn has_len(&self, len: usize) -> bool {
686 self.seconded_in_group.len() == len && self.validated_in_group.len() == len
687 }
688
689 pub fn backing_validators(&self) -> usize {
691 self.seconded_in_group
692 .iter()
693 .by_vals()
694 .zip(self.validated_in_group.iter().by_vals())
695 .filter(|&(s, v)| s || v) .count()
697 }
698
699 pub fn has_seconded(&self) -> bool {
701 self.seconded_in_group.iter().by_vals().any(|x| x)
702 }
703
704 pub fn mask_seconded(&mut self, mask: &BitSlice<u8, Lsb0>) {
707 for (mut x, mask) in self
708 .seconded_in_group
709 .iter_mut()
710 .zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
711 {
712 *x = *x && !mask;
718 }
719 }
720
721 pub fn mask_valid(&mut self, mask: &BitSlice<u8, Lsb0>) {
724 for (mut x, mask) in self
725 .validated_in_group
726 .iter_mut()
727 .zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
728 {
729 *x = *x && !mask;
735 }
736 }
737 }
738
739 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
742 pub struct BackedCandidateManifest {
743 pub scheduling_parent: Hash,
745 pub candidate_hash: CandidateHash,
747 pub group_index: GroupIndex,
749 pub para_id: ParaId,
753 pub parent_head_data_hash: Hash,
755 pub statement_knowledge: StatementFilter,
763 }
764
765 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
767 pub struct BackedCandidateAcknowledgement {
768 pub candidate_hash: CandidateHash,
770 pub statement_knowledge: StatementFilter,
778 }
779
780 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
782 pub enum StatementDistributionMessage {
783 #[codec(index = 0)]
785 Statement(Hash, UncheckedSignedStatement),
786
787 #[codec(index = 1)]
791 BackedCandidateManifest(BackedCandidateManifest),
792
793 #[codec(index = 2)]
796 BackedCandidateKnown(BackedCandidateAcknowledgement),
797 }
798
799 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
801 pub enum ApprovalDistributionMessage {
802 #[codec(index = 0)]
812 Assignments(Vec<(IndirectAssignmentCertV2, CandidateBitfield)>),
813 #[codec(index = 1)]
815 Approvals(Vec<IndirectSignedApprovalVoteV2>),
816 }
817
818 #[derive(Debug, Clone, PartialEq, Eq)]
820 pub enum GossipSupportNetworkMessage {}
821
822 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
824 pub enum ValidationProtocol {
825 #[codec(index = 1)]
827 #[from]
828 BitfieldDistribution(BitfieldDistributionMessage),
829 #[codec(index = 3)]
831 #[from]
832 StatementDistribution(StatementDistributionMessage),
833 #[codec(index = 4)]
835 #[from]
836 ApprovalDistribution(ApprovalDistributionMessage),
837 }
838}
839
840pub fn filter_by_peer_version(
842 peers: &[(PeerId, peer_set::ProtocolVersion)],
843 version: peer_set::ProtocolVersion,
844) -> Vec<PeerId> {
845 peers.iter().filter(|(_, v)| v == &version).map(|(p, _)| *p).collect::<Vec<_>>()
846}