calimero_network_primitives/
config.rs1use core::fmt::{self, Formatter};
2use core::time::Duration;
3
4use libp2p::identity::Keypair;
5use libp2p::rendezvous::Namespace;
6use multiaddr::{Multiaddr, Protocol};
7use serde::de::{Error as SerdeError, SeqAccess, Visitor};
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10pub const DEFAULT_PORT: u16 = 2428; pub const IPFS_BOOT_NODES: &[&str] = &[
14 "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
15 "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
16 "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
17 "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
18 "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
19 "/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
20];
21
22pub const CALIMERO_DEV_BOOT_NODES: &[&str] = &[
23 "/ip4/63.181.86.34/udp/4001/quic-v1/p2p/12D3KooWR5V4zmisVtVdGE6i8jfFwtgRNq5t8eDGxfckKuhXu7Eh",
24 "/ip4/63.181.86.34/tcp/4001/p2p/12D3KooWR5V4zmisVtVdGE6i8jfFwtgRNq5t8eDGxfckKuhXu7Eh",
25];
26
27#[derive(Debug)]
28#[non_exhaustive]
29pub struct NetworkConfig {
30 pub identity: Keypair,
31 pub swarm: SwarmConfig,
32 pub bootstrap: BootstrapConfig,
33 pub discovery: DiscoveryConfig,
34}
35
36impl NetworkConfig {
37 #[must_use]
38 pub const fn new(
39 identity: Keypair,
40 swarm: SwarmConfig,
41 bootstrap: BootstrapConfig,
42 discovery: DiscoveryConfig,
43 ) -> Self {
44 Self {
45 identity,
46 swarm,
47 bootstrap,
48 discovery,
49 }
50 }
51}
52
53#[derive(Debug, Deserialize, Serialize)]
54#[non_exhaustive]
55pub struct SwarmConfig {
56 pub listen: Vec<Multiaddr>,
57}
58
59impl SwarmConfig {
60 #[must_use]
61 pub const fn new(listen: Vec<Multiaddr>) -> Self {
62 Self { listen }
63 }
64}
65
66#[derive(Debug, Default, Deserialize, Serialize)]
67#[non_exhaustive]
68pub struct BootstrapConfig {
69 #[serde(default)]
70 pub nodes: BootstrapNodes,
71}
72
73impl BootstrapConfig {
74 #[must_use]
75 pub const fn new(nodes: BootstrapNodes) -> Self {
76 Self { nodes }
77 }
78}
79
80#[derive(Debug, Default, Deserialize, Serialize)]
81#[serde(transparent)]
82#[non_exhaustive]
83pub struct BootstrapNodes {
84 #[serde(deserialize_with = "deserialize_bootstrap")]
85 pub list: Vec<Multiaddr>,
86}
87
88impl BootstrapNodes {
89 #[must_use]
90 pub const fn new(list: Vec<Multiaddr>) -> Self {
91 Self { list }
92 }
93
94 #[must_use]
95 pub fn ipfs() -> Self {
96 Self {
97 list: IPFS_BOOT_NODES
98 .iter()
99 .map(|s| s.parse().expect("invalid multiaddr"))
100 .collect(),
101 }
102 }
103
104 #[must_use]
105 pub fn calimero_dev() -> Self {
106 Self {
107 list: CALIMERO_DEV_BOOT_NODES
108 .iter()
109 .map(|s| s.parse().expect("invalid multiaddr"))
110 .collect(),
111 }
112 }
113}
114
115#[derive(Debug, Deserialize, Serialize)]
116#[non_exhaustive]
117pub struct DiscoveryConfig {
118 #[serde(default = "calimero_primitives::common::bool_true")]
119 pub mdns: bool,
120
121 pub advertise_address: bool,
122
123 pub rendezvous: RendezvousConfig,
124
125 pub relay: RelayConfig,
126
127 pub autonat: AutonatConfig,
128}
129
130impl DiscoveryConfig {
131 #[must_use]
132 pub const fn new(
133 mdns: bool,
134 advertise_address: bool,
135 rendezvous: RendezvousConfig,
136 relay: RelayConfig,
137 autonat: AutonatConfig,
138 ) -> Self {
139 Self {
140 mdns,
141 advertise_address,
142 rendezvous,
143 relay,
144 autonat,
145 }
146 }
147}
148
149impl Default for DiscoveryConfig {
150 fn default() -> Self {
151 Self {
152 mdns: true,
153 advertise_address: false,
154 rendezvous: RendezvousConfig::default(),
155 relay: RelayConfig::default(),
156 autonat: AutonatConfig::default(),
157 }
158 }
159}
160
161#[derive(Clone, Debug, Deserialize, Serialize)]
162#[non_exhaustive]
163pub struct RelayConfig {
164 pub registrations_limit: usize,
165}
166
167impl RelayConfig {
168 #[must_use]
169 pub const fn new(registrations_limit: usize) -> Self {
170 Self {
171 registrations_limit,
172 }
173 }
174}
175
176impl Default for RelayConfig {
177 fn default() -> Self {
178 Self {
179 registrations_limit: 3,
180 }
181 }
182}
183
184#[derive(Clone, Debug, Deserialize, Serialize)]
185#[non_exhaustive]
186pub struct AutonatConfig {
187 pub max_candidates: usize,
188 pub probe_interval: Duration,
189}
190
191impl AutonatConfig {
192 #[must_use]
193 pub const fn new(max_candidates: usize, probe_interval: Duration) -> Self {
194 Self {
195 max_candidates,
196 probe_interval,
197 }
198 }
199}
200
201impl Default for AutonatConfig {
202 fn default() -> Self {
203 Self {
204 max_candidates: 5,
205 probe_interval: Duration::from_secs(10),
206 }
207 }
208}
209
210#[derive(Clone, Debug, Deserialize, Serialize)]
211#[non_exhaustive]
212pub struct RendezvousConfig {
213 #[serde(
214 serialize_with = "serialize_rendezvous_namespace",
215 deserialize_with = "deserialize_rendezvous_namespace"
216 )]
217 pub namespace: Namespace,
218
219 pub discovery_rpm: f32,
220
221 pub discovery_interval: Duration,
222
223 pub registrations_limit: usize,
224}
225
226impl RendezvousConfig {
227 #[must_use]
228 pub fn new(registrations_limit: usize) -> Self {
229 let default = Self::default();
230 Self {
231 namespace: default.namespace,
232 discovery_rpm: default.discovery_rpm,
233 discovery_interval: default.discovery_interval,
234 registrations_limit,
235 }
236 }
237}
238
239impl Default for RendezvousConfig {
240 fn default() -> Self {
241 Self {
242 namespace: Namespace::from_static("/calimero/devnet/global"),
243 discovery_rpm: 0.5,
244 discovery_interval: Duration::from_secs(90),
245 registrations_limit: 3,
246 }
247 }
248}
249
250fn serialize_rendezvous_namespace<S>(
251 namespace: &Namespace,
252 serializer: S,
253) -> Result<S::Ok, S::Error>
254where
255 S: Serializer,
256{
257 let namespace_str = namespace.to_string();
258 serializer.serialize_str(&namespace_str)
259}
260
261fn deserialize_rendezvous_namespace<'de, D>(deserializer: D) -> Result<Namespace, D::Error>
262where
263 D: Deserializer<'de>,
264{
265 let namespace_str = String::deserialize(deserializer)?;
266 Namespace::new(namespace_str).map_err(SerdeError::custom)
267}
268
269fn deserialize_bootstrap<'de, D>(deserializer: D) -> Result<Vec<Multiaddr>, D::Error>
270where
271 D: Deserializer<'de>,
272{
273 struct BootstrapVisitor;
274
275 impl<'de> Visitor<'de> for BootstrapVisitor {
276 type Value = Vec<Multiaddr>;
277
278 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
279 formatter.write_str("a list of multiaddresses")
280 }
281
282 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
283 where
284 A: SeqAccess<'de>,
285 {
286 let mut addrs = Vec::new();
287
288 while let Some(addr) = seq.next_element::<Multiaddr>()? {
289 let Some(Protocol::P2p(_)) = addr.iter().last() else {
290 return Err(SerdeError::custom("peer ID not allowed"));
291 };
292
293 addrs.push(addr);
294 }
295
296 Ok(addrs)
297 }
298 }
299
300 deserializer.deserialize_seq(BootstrapVisitor)
301}