1use std::{net::SocketAddr, num::NonZeroU32, time::Duration};
6
7use iota_types::{
8 messages_checkpoint::{CheckpointDigest, CheckpointSequenceNumber},
9 multiaddr::Multiaddr,
10};
11use serde::{Deserialize, Serialize};
12
13#[derive(Clone, Debug, Deserialize, Serialize)]
14#[serde(rename_all = "kebab-case")]
15pub struct P2pConfig {
16 #[serde(default = "default_listen_address")]
18 pub listen_address: SocketAddr,
19 #[serde(skip_serializing_if = "Option::is_none")]
22 pub external_address: Option<Multiaddr>,
23 #[serde(skip_serializing_if = "Vec::is_empty", default)]
26 pub seed_peers: Vec<SeedPeer>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub anemo_config: Option<anemo::Config>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub state_sync: Option<StateSyncConfig>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub discovery: Option<DiscoveryConfig>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub randomness: Option<RandomnessConfig>,
35 #[serde(skip_serializing_if = "Option::is_none")]
41 pub excessive_message_size: Option<usize>,
42}
43
44fn default_listen_address() -> SocketAddr {
45 "0.0.0.0:8084".parse().unwrap()
46}
47
48impl Default for P2pConfig {
49 fn default() -> Self {
50 Self {
51 listen_address: default_listen_address(),
52 external_address: Default::default(),
53 seed_peers: Default::default(),
54 anemo_config: Default::default(),
55 state_sync: None,
56 discovery: None,
57 randomness: None,
58 excessive_message_size: None,
59 }
60 }
61}
62
63impl P2pConfig {
64 pub fn excessive_message_size(&self) -> usize {
65 const EXCESSIVE_MESSAGE_SIZE: usize = 32 << 20;
66
67 self.excessive_message_size
68 .unwrap_or(EXCESSIVE_MESSAGE_SIZE)
69 }
70
71 pub fn set_discovery_config(mut self, discovery_config: DiscoveryConfig) -> Self {
72 self.discovery = Some(discovery_config);
73 self
74 }
75}
76
77#[derive(Clone, Debug, Deserialize, Serialize)]
78#[serde(rename_all = "kebab-case")]
79pub struct SeedPeer {
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub peer_id: Option<anemo::PeerId>,
82 pub address: Multiaddr,
83}
84
85#[derive(Clone, Debug, Deserialize, Serialize)]
86#[serde(rename_all = "kebab-case")]
87pub struct AllowlistedPeer {
88 pub peer_id: anemo::PeerId,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub address: Option<Multiaddr>,
91}
92
93#[derive(Clone, Debug, Default, Deserialize, Serialize)]
94#[serde(rename_all = "kebab-case")]
95pub struct StateSyncConfig {
96 #[serde(skip_serializing_if = "Vec::is_empty", default)]
107 pub pinned_checkpoints: Vec<(CheckpointSequenceNumber, CheckpointDigest)>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
113 pub interval_period_ms: Option<u64>,
114
115 #[serde(skip_serializing_if = "Option::is_none")]
119 pub mailbox_capacity: Option<usize>,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
126 pub synced_checkpoint_broadcast_channel_capacity: Option<usize>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
133 pub checkpoint_header_download_concurrency: Option<usize>,
134
135 #[serde(skip_serializing_if = "Option::is_none")]
140 pub checkpoint_content_download_concurrency: Option<usize>,
141
142 #[serde(skip_serializing_if = "Option::is_none")]
149 pub checkpoint_content_download_tx_concurrency: Option<u64>,
150
151 #[serde(skip_serializing_if = "Option::is_none")]
156 pub timeout_ms: Option<u64>,
157
158 #[serde(skip_serializing_if = "Option::is_none")]
163 pub checkpoint_content_timeout_ms: Option<u64>,
164
165 #[serde(skip_serializing_if = "Option::is_none")]
169 pub push_checkpoint_summary_rate_limit: Option<NonZeroU32>,
170
171 #[serde(skip_serializing_if = "Option::is_none")]
175 pub get_checkpoint_summary_rate_limit: Option<NonZeroU32>,
176
177 #[serde(skip_serializing_if = "Option::is_none")]
181 pub get_checkpoint_contents_rate_limit: Option<NonZeroU32>,
182
183 #[serde(skip_serializing_if = "Option::is_none")]
187 pub get_checkpoint_contents_inflight_limit: Option<usize>,
188
189 #[serde(skip_serializing_if = "Option::is_none")]
194 pub get_checkpoint_contents_per_checkpoint_limit: Option<usize>,
195
196 #[serde(skip_serializing_if = "Option::is_none")]
199 pub wait_interval_when_no_peer_to_sync_content_ms: Option<u64>,
200}
201
202impl StateSyncConfig {
203 pub fn interval_period(&self) -> Duration {
204 const INTERVAL_PERIOD_MS: u64 = 5_000; Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
207 }
208
209 pub fn mailbox_capacity(&self) -> usize {
210 const MAILBOX_CAPACITY: usize = 1_024;
211
212 self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
213 }
214
215 pub fn synced_checkpoint_broadcast_channel_capacity(&self) -> usize {
216 const SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY: usize = 1_024;
217
218 self.synced_checkpoint_broadcast_channel_capacity
219 .unwrap_or(SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY)
220 }
221
222 pub fn checkpoint_header_download_concurrency(&self) -> usize {
223 const CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY: usize = 400;
224
225 self.checkpoint_header_download_concurrency
226 .unwrap_or(CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY)
227 }
228
229 pub fn checkpoint_content_download_concurrency(&self) -> usize {
230 const CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY: usize = 400;
231
232 self.checkpoint_content_download_concurrency
233 .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY)
234 }
235
236 pub fn checkpoint_content_download_tx_concurrency(&self) -> u64 {
237 const CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY: u64 = 50_000;
238
239 self.checkpoint_content_download_tx_concurrency
240 .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY)
241 }
242
243 pub fn timeout(&self) -> Duration {
244 const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
245
246 self.timeout_ms
247 .map(Duration::from_millis)
248 .unwrap_or(DEFAULT_TIMEOUT)
249 }
250
251 pub fn checkpoint_content_timeout(&self) -> Duration {
252 const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
253
254 self.checkpoint_content_timeout_ms
255 .map(Duration::from_millis)
256 .unwrap_or(DEFAULT_TIMEOUT)
257 }
258
259 pub fn wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
260 self.wait_interval_when_no_peer_to_sync_content_ms
261 .map(Duration::from_millis)
262 .unwrap_or(self.default_wait_interval_when_no_peer_to_sync_content())
263 }
264
265 fn default_wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
266 if cfg!(msim) {
267 Duration::from_secs(5)
268 } else {
269 Duration::from_secs(10)
270 }
271 }
272}
273
274#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
285pub enum AccessType {
286 Public,
287 Private,
288}
289
290#[derive(Clone, Debug, Default, Deserialize, Serialize)]
291#[serde(rename_all = "kebab-case")]
292pub struct DiscoveryConfig {
293 #[serde(skip_serializing_if = "Option::is_none")]
297 pub interval_period_ms: Option<u64>,
298
299 #[serde(skip_serializing_if = "Option::is_none")]
303 pub target_concurrent_connections: Option<usize>,
304
305 #[serde(skip_serializing_if = "Option::is_none")]
312 pub peers_to_query: Option<usize>,
313
314 #[serde(skip_serializing_if = "Option::is_none")]
318 pub get_known_peers_rate_limit: Option<NonZeroU32>,
319
320 #[serde(skip_serializing_if = "Option::is_none")]
322 pub access_type: Option<AccessType>,
323
324 #[serde(skip_serializing_if = "Vec::is_empty", default)]
334 pub allowlisted_peers: Vec<AllowlistedPeer>,
335
336 pub enable_node_info_signatures: Option<bool>,
341}
342
343impl DiscoveryConfig {
344 pub fn interval_period(&self) -> Duration {
345 const INTERVAL_PERIOD_MS: u64 = 5_000; Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
348 }
349
350 pub fn target_concurrent_connections(&self) -> usize {
351 const TARGET_CONCURRENT_CONNECTIONS: usize = 4;
352
353 self.target_concurrent_connections
354 .unwrap_or(TARGET_CONCURRENT_CONNECTIONS)
355 }
356
357 pub fn peers_to_query(&self) -> usize {
358 const PEERS_TO_QUERY: usize = 1;
359
360 self.peers_to_query.unwrap_or(PEERS_TO_QUERY)
361 }
362
363 pub fn access_type(&self) -> AccessType {
364 self.access_type.unwrap_or(AccessType::Public)
366 }
367
368 pub fn enable_node_info_signatures(&self) -> bool {
369 self.enable_node_info_signatures.unwrap_or(true)
370 }
371}
372
373#[derive(Clone, Debug, Default, Deserialize, Serialize)]
374#[serde(rename_all = "kebab-case")]
375pub struct RandomnessConfig {
376 #[serde(skip_serializing_if = "Option::is_none")]
381 pub max_partial_sigs_rounds_ahead: Option<u64>,
382
383 #[serde(skip_serializing_if = "Option::is_none")]
388 pub max_partial_sigs_concurrent_sends: Option<usize>,
389
390 #[serde(skip_serializing_if = "Option::is_none")]
395 pub partial_signature_retry_interval_ms: Option<u64>,
396
397 #[serde(skip_serializing_if = "Option::is_none")]
402 pub mailbox_capacity: Option<usize>,
403
404 #[serde(skip_serializing_if = "Option::is_none")]
408 pub send_partial_signatures_inflight_limit: Option<usize>,
409
410 #[serde(skip_serializing_if = "Option::is_none")]
415 pub max_ignored_peer_weight_factor: Option<f64>,
416}
417
418impl RandomnessConfig {
419 pub fn max_partial_sigs_rounds_ahead(&self) -> u64 {
420 const MAX_PARTIAL_SIGS_ROUNDS_AHEAD: u64 = 50;
421
422 self.max_partial_sigs_rounds_ahead
423 .unwrap_or(MAX_PARTIAL_SIGS_ROUNDS_AHEAD)
424 }
425
426 pub fn max_partial_sigs_concurrent_sends(&self) -> usize {
427 const MAX_PARTIAL_SIGS_CONCURRENT_SENDS: usize = 20;
428
429 self.max_partial_sigs_concurrent_sends
430 .unwrap_or(MAX_PARTIAL_SIGS_CONCURRENT_SENDS)
431 }
432 pub fn partial_signature_retry_interval(&self) -> Duration {
433 const PARTIAL_SIGNATURE_RETRY_INTERVAL: u64 = 5_000; Duration::from_millis(
436 self.partial_signature_retry_interval_ms
437 .unwrap_or(PARTIAL_SIGNATURE_RETRY_INTERVAL),
438 )
439 }
440
441 pub fn mailbox_capacity(&self) -> usize {
442 const MAILBOX_CAPACITY: usize = 1_000_000;
443
444 self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
445 }
446
447 pub fn send_partial_signatures_inflight_limit(&self) -> usize {
448 const SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT: usize = 20;
449
450 self.send_partial_signatures_inflight_limit
451 .unwrap_or(SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT)
452 }
453
454 pub fn max_ignored_peer_weight_factor(&self) -> f64 {
455 const MAX_IGNORED_PEER_WEIGHT_FACTOR: f64 = 0.2;
456
457 self.max_ignored_peer_weight_factor
458 .unwrap_or(MAX_IGNORED_PEER_WEIGHT_FACTOR)
459 }
460}