arc_malachitebft_network/
channel.rs1use core::fmt;
2
3use libp2p::gossipsub;
4use libp2p_broadcast as broadcast;
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, Copy)]
8pub struct ChannelNames {
9 pub consensus: &'static str,
10 pub proposal_parts: &'static str,
11 pub sync: &'static str,
12 pub liveness: &'static str,
13}
14
15impl Default for ChannelNames {
16 fn default() -> Self {
17 Self {
18 consensus: "/consensus",
19 proposal_parts: "/proposal_parts",
20 sync: "/sync",
21 liveness: "/liveness",
22 }
23 }
24}
25
26#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
27pub enum Channel {
28 Consensus,
29 Liveness,
30 ProposalParts,
31 Sync,
32}
33
34impl Channel {
35 pub fn all() -> &'static [Channel] {
36 &[
37 Channel::Consensus,
38 Channel::ProposalParts,
39 Channel::Sync,
40 Channel::Liveness,
41 ]
42 }
43
44 pub fn consensus() -> &'static [Channel] {
45 &[
46 Channel::Consensus,
47 Channel::ProposalParts,
48 Channel::Liveness,
49 ]
50 }
51
52 pub fn to_gossipsub_topic(self, channel_names: ChannelNames) -> gossipsub::IdentTopic {
53 gossipsub::IdentTopic::new(self.as_str(channel_names))
54 }
55
56 pub fn to_broadcast_topic(self, channel_names: ChannelNames) -> broadcast::Topic {
57 broadcast::Topic::new(self.as_str(channel_names).as_bytes())
58 }
59
60 pub fn as_str(&self, channel_names: ChannelNames) -> &'static str {
61 match self {
62 Channel::Consensus => channel_names.consensus,
63 Channel::ProposalParts => channel_names.proposal_parts,
64 Channel::Sync => channel_names.sync,
65 Channel::Liveness => channel_names.liveness,
66 }
67 }
68
69 pub fn has_gossipsub_topic(
70 topic_hash: &gossipsub::TopicHash,
71 channel_names: ChannelNames,
72 ) -> bool {
73 Self::all()
74 .iter()
75 .any(|channel| &channel.to_gossipsub_topic(channel_names).hash() == topic_hash)
76 }
77
78 pub fn has_broadcast_topic(topic: &broadcast::Topic, channel_names: ChannelNames) -> bool {
79 Self::all()
80 .iter()
81 .any(|channel| &channel.to_broadcast_topic(channel_names) == topic)
82 }
83
84 pub fn from_gossipsub_topic_hash(
85 topic: &gossipsub::TopicHash,
86 channel_names: ChannelNames,
87 ) -> Option<Self> {
88 if topic == &Self::Consensus.to_gossipsub_topic(channel_names).hash() {
89 Some(Self::Consensus)
90 } else if topic == &Self::ProposalParts.to_gossipsub_topic(channel_names).hash() {
91 Some(Self::ProposalParts)
92 } else if topic == &Self::Sync.to_gossipsub_topic(channel_names).hash() {
93 Some(Self::Sync)
94 } else if topic == &Self::Liveness.to_gossipsub_topic(channel_names).hash() {
95 Some(Self::Liveness)
96 } else {
97 None
98 }
99 }
100
101 pub fn from_broadcast_topic(
102 topic: &broadcast::Topic,
103 channel_names: ChannelNames,
104 ) -> Option<Self> {
105 if topic == &Self::Consensus.to_broadcast_topic(channel_names) {
106 Some(Self::Consensus)
107 } else if topic == &Self::ProposalParts.to_broadcast_topic(channel_names) {
108 Some(Self::ProposalParts)
109 } else if topic == &Self::Sync.to_broadcast_topic(channel_names) {
110 Some(Self::Sync)
111 } else if topic == &Self::Liveness.to_broadcast_topic(channel_names) {
112 Some(Self::Liveness)
113 } else {
114 None
115 }
116 }
117}
118
119impl fmt::Display for Channel {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 write!(f, "{self:?}")
122 }
123}