1#![deny(unused_crate_dependencies)]
20#![warn(missing_docs)]
21
22use codec::{Decode, Encode};
23use pezkuwi_primitives::{BlockNumber, Hash};
24use std::fmt;
25
26#[doc(hidden)]
27pub use pezsc_network::IfDisconnected;
28pub use pezsc_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<pezsc_network::ObservedRole> for ObservedRole {
73 fn from(role: pezsc_network::ObservedRole) -> ObservedRole {
74 match role {
75 pezsc_network::ObservedRole::Light => ObservedRole::Light,
76 pezsc_network::ObservedRole::Authority => ObservedRole::Authority,
77 pezsc_network::ObservedRole::Full => ObservedRole::Full,
78 }
79 }
80}
81
82impl Into<pezsc_network::ObservedRole> for ObservedRole {
83 fn into(self) -> pezsc_network::ObservedRole {
84 match self {
85 ObservedRole::Light => pezsc_network::ObservedRole::Light,
86 ObservedRole::Full => pezsc_network::ObservedRole::Full,
87 ObservedRole::Authority => pezsc_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 },
352 _ => Err(crate::WrongVariant),
353 }
354 }
355 }
356 };
357}
358
359macro_rules! impl_versioned_collation_try_from {
362 (
363 $from:ty,
364 $out:ty,
365 $v1_pat:pat => $v1_out:expr,
366 $v2_pat:pat => $v2_out:expr
367 ) => {
368 impl TryFrom<$from> for $out {
369 type Error = crate::WrongVariant;
370
371 fn try_from(x: $from) -> Result<$out, Self::Error> {
372 #[allow(unreachable_patterns)] match x {
374 CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out)),
375 CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out)),
376 _ => Err(crate::WrongVariant),
377 }
378 }
379 }
380
381 impl<'a> TryFrom<&'a $from> for $out {
382 type Error = crate::WrongVariant;
383
384 fn try_from(x: &'a $from) -> Result<$out, Self::Error> {
385 #[allow(unreachable_patterns)] match x {
387 CollationProtocols::V1($v1_pat) => Ok(CollationProtocols::V1($v1_out.clone())),
388 CollationProtocols::V2($v2_pat) => Ok(CollationProtocols::V2($v2_out.clone())),
389 _ => Err(crate::WrongVariant),
390 }
391 }
392 }
393 };
394}
395
396pub type BitfieldDistributionMessage = ValidationProtocols<v3::BitfieldDistributionMessage>;
398impl_versioned_validation_full_protocol_from!(
399 BitfieldDistributionMessage,
400 VersionedValidationProtocol,
401 BitfieldDistribution
402);
403impl_versioned_validation_try_from!(
404 VersionedValidationProtocol,
405 BitfieldDistributionMessage,
406 v3::ValidationProtocol::BitfieldDistribution(x) => x
407);
408
409pub type StatementDistributionMessage = ValidationProtocols<v3::StatementDistributionMessage>;
411impl_versioned_validation_full_protocol_from!(
412 StatementDistributionMessage,
413 VersionedValidationProtocol,
414 StatementDistribution
415);
416impl_versioned_validation_try_from!(
417 VersionedValidationProtocol,
418 StatementDistributionMessage,
419 v3::ValidationProtocol::StatementDistribution(x) => x
420);
421
422pub type ApprovalDistributionMessage = ValidationProtocols<v3::ApprovalDistributionMessage>;
424impl_versioned_validation_full_protocol_from!(
425 ApprovalDistributionMessage,
426 VersionedValidationProtocol,
427 ApprovalDistribution
428);
429impl_versioned_validation_try_from!(
430 VersionedValidationProtocol,
431 ApprovalDistributionMessage,
432 v3::ValidationProtocol::ApprovalDistribution(x) => x
433
434);
435
436pub type GossipSupportNetworkMessage = ValidationProtocols<v3::GossipSupportNetworkMessage>;
438
439impl TryFrom<VersionedValidationProtocol> for GossipSupportNetworkMessage {
441 type Error = WrongVariant;
442 fn try_from(_: VersionedValidationProtocol) -> Result<Self, Self::Error> {
443 Err(WrongVariant)
444 }
445}
446
447impl<'a> TryFrom<&'a VersionedValidationProtocol> for GossipSupportNetworkMessage {
448 type Error = WrongVariant;
449 fn try_from(_: &'a VersionedValidationProtocol) -> Result<Self, Self::Error> {
450 Err(WrongVariant)
451 }
452}
453
454pub type CollatorProtocolMessage =
456 CollationProtocols<v1::CollatorProtocolMessage, v2::CollatorProtocolMessage>;
457impl_versioned_collation_full_protocol_from!(
458 CollatorProtocolMessage,
459 VersionedCollationProtocol,
460 CollatorProtocol
461);
462impl_versioned_collation_try_from!(
463 VersionedCollationProtocol,
464 CollatorProtocolMessage,
465 v1::CollationProtocol::CollatorProtocol(x) => x,
466 v2::CollationProtocol::CollatorProtocol(x) => x
467);
468
469pub mod v1 {
471 use codec::{Decode, Encode};
472
473 use pezkuwi_primitives::{CollatorId, CollatorSignature, Hash, Id as ParaId};
474
475 use pezkuwi_pez_node_primitives::UncheckedSignedFullStatement;
476
477 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
479 pub enum CollatorProtocolMessage {
480 #[codec(index = 0)]
483 Declare(CollatorId, ParaId, CollatorSignature),
484 #[codec(index = 1)]
487 AdvertiseCollation(Hash),
488 #[codec(index = 4)]
490 CollationSeconded(Hash, UncheckedSignedFullStatement),
491 }
492
493 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
495 pub enum CollationProtocol {
496 #[codec(index = 0)]
498 #[from]
499 CollatorProtocol(CollatorProtocolMessage),
500 }
501
502 pub fn declare_signature_payload(peer_id: &pezsc_network_types::PeerId) -> Vec<u8> {
507 let mut payload = peer_id.to_bytes();
508 payload.extend_from_slice(b"COLL");
509 payload
510 }
511}
512
513pub mod v2 {
515 use codec::{Decode, Encode};
516
517 use pezkuwi_primitives::{CandidateHash, CollatorId, CollatorSignature, Hash, Id as ParaId};
518
519 use pezkuwi_pez_node_primitives::UncheckedSignedFullStatement;
520
521 pub use super::v1::declare_signature_payload;
523
524 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
526 pub enum CollatorProtocolMessage {
527 #[codec(index = 0)]
530 Declare(CollatorId, ParaId, CollatorSignature),
531 #[codec(index = 1)]
534 AdvertiseCollation {
535 relay_parent: Hash,
537 candidate_hash: CandidateHash,
539 parent_head_data_hash: Hash,
541 },
542 #[codec(index = 4)]
544 CollationSeconded(Hash, UncheckedSignedFullStatement),
545 }
546
547 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
549 pub enum CollationProtocol {
550 #[codec(index = 0)]
552 #[from]
553 CollatorProtocol(CollatorProtocolMessage),
554 }
555}
556
557pub mod v3 {
561 use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec};
562 use codec::{Decode, Encode};
563
564 use pezkuwi_primitives::{
565 CandidateHash, GroupIndex, Hash, Id as ParaId, UncheckedSignedAvailabilityBitfield,
566 UncheckedSignedStatement,
567 };
568
569 use pezkuwi_pez_node_primitives::approval::v2::{
570 CandidateBitfield, IndirectAssignmentCertV2, IndirectSignedApprovalVoteV2,
571 };
572
573 pub use super::v2::declare_signature_payload;
575
576 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
578 pub enum BitfieldDistributionMessage {
579 #[codec(index = 0)]
581 Bitfield(Hash, UncheckedSignedAvailabilityBitfield),
582 }
583
584 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
587 pub struct StatementFilter {
588 pub seconded_in_group: BitVec<u8, Lsb0>,
590 pub validated_in_group: BitVec<u8, Lsb0>,
592 }
593
594 impl StatementFilter {
595 pub fn blank(group_size: usize) -> Self {
597 StatementFilter {
598 seconded_in_group: BitVec::repeat(false, group_size),
599 validated_in_group: BitVec::repeat(false, group_size),
600 }
601 }
602
603 pub fn full(group_size: usize) -> Self {
605 StatementFilter {
606 seconded_in_group: BitVec::repeat(true, group_size),
607 validated_in_group: BitVec::repeat(true, group_size),
608 }
609 }
610
611 pub fn has_len(&self, len: usize) -> bool {
614 self.seconded_in_group.len() == len && self.validated_in_group.len() == len
615 }
616
617 pub fn backing_validators(&self) -> usize {
619 self.seconded_in_group
620 .iter()
621 .by_vals()
622 .zip(self.validated_in_group.iter().by_vals())
623 .filter(|&(s, v)| s || v) .count()
625 }
626
627 pub fn has_seconded(&self) -> bool {
629 self.seconded_in_group.iter().by_vals().any(|x| x)
630 }
631
632 pub fn mask_seconded(&mut self, mask: &BitSlice<u8, Lsb0>) {
635 for (mut x, mask) in self
636 .seconded_in_group
637 .iter_mut()
638 .zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
639 {
640 *x = *x && !mask;
646 }
647 }
648
649 pub fn mask_valid(&mut self, mask: &BitSlice<u8, Lsb0>) {
652 for (mut x, mask) in self
653 .validated_in_group
654 .iter_mut()
655 .zip(mask.iter().by_vals().chain(std::iter::repeat(false)))
656 {
657 *x = *x && !mask;
663 }
664 }
665 }
666
667 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
670 pub struct BackedCandidateManifest {
671 pub relay_parent: Hash,
673 pub candidate_hash: CandidateHash,
675 pub group_index: GroupIndex,
677 pub para_id: ParaId,
681 pub parent_head_data_hash: Hash,
683 pub statement_knowledge: StatementFilter,
691 }
692
693 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
695 pub struct BackedCandidateAcknowledgement {
696 pub candidate_hash: CandidateHash,
698 pub statement_knowledge: StatementFilter,
706 }
707
708 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
710 pub enum StatementDistributionMessage {
711 #[codec(index = 0)]
713 Statement(Hash, UncheckedSignedStatement),
714
715 #[codec(index = 1)]
719 BackedCandidateManifest(BackedCandidateManifest),
720
721 #[codec(index = 2)]
724 BackedCandidateKnown(BackedCandidateAcknowledgement),
725 }
726
727 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
729 pub enum ApprovalDistributionMessage {
730 #[codec(index = 0)]
740 Assignments(Vec<(IndirectAssignmentCertV2, CandidateBitfield)>),
741 #[codec(index = 1)]
743 Approvals(Vec<IndirectSignedApprovalVoteV2>),
744 }
745
746 #[derive(Debug, Clone, PartialEq, Eq)]
748 pub enum GossipSupportNetworkMessage {}
749
750 #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, derive_more::From)]
752 pub enum ValidationProtocol {
753 #[codec(index = 1)]
755 #[from]
756 BitfieldDistribution(BitfieldDistributionMessage),
757 #[codec(index = 3)]
759 #[from]
760 StatementDistribution(StatementDistributionMessage),
761 #[codec(index = 4)]
763 #[from]
764 ApprovalDistribution(ApprovalDistributionMessage),
765 }
766}
767
768pub fn filter_by_peer_version(
770 peers: &[(PeerId, peer_set::ProtocolVersion)],
771 version: peer_set::ProtocolVersion,
772) -> Vec<PeerId> {
773 peers.iter().filter(|(_, v)| v == &version).map(|(p, _)| *p).collect::<Vec<_>>()
774}