1use std::{net::SocketAddr, num::NonZeroU32, time::Duration};
6
7use iota_multiaddr::Multiaddr;
8use iota_sdk_types::CheckpointDigest;
9use iota_types::messages_checkpoint::CheckpointSequenceNumber;
10use serde::{Deserialize, Serialize};
11
12#[derive(Clone, Debug, Deserialize, Serialize)]
13#[serde(rename_all = "kebab-case")]
14pub struct P2pConfig {
15 #[serde(default = "default_listen_address")]
17 pub listen_address: SocketAddr,
18 #[serde(skip_serializing_if = "Option::is_none")]
21 pub external_address: Option<Multiaddr>,
22 #[serde(skip_serializing_if = "Vec::is_empty", default)]
25 pub seed_peers: Vec<SeedPeer>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub anemo_config: Option<anemo::Config>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub state_sync: Option<StateSyncConfig>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub discovery: Option<DiscoveryConfig>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub randomness: Option<RandomnessConfig>,
34 #[serde(skip_serializing_if = "Option::is_none")]
40 pub excessive_message_size: Option<usize>,
41}
42
43fn default_listen_address() -> SocketAddr {
44 "0.0.0.0:8084".parse().unwrap()
45}
46
47impl Default for P2pConfig {
48 fn default() -> Self {
49 Self {
50 listen_address: default_listen_address(),
51 external_address: Default::default(),
52 seed_peers: Default::default(),
53 anemo_config: Default::default(),
54 state_sync: None,
55 discovery: None,
56 randomness: None,
57 excessive_message_size: None,
58 }
59 }
60}
61
62impl P2pConfig {
63 pub fn excessive_message_size(&self) -> usize {
64 const EXCESSIVE_MESSAGE_SIZE: usize = 32 << 20;
65
66 self.excessive_message_size
67 .unwrap_or(EXCESSIVE_MESSAGE_SIZE)
68 }
69
70 pub fn set_discovery_config(mut self, discovery_config: DiscoveryConfig) -> Self {
71 self.discovery = Some(discovery_config);
72 self
73 }
74}
75
76#[derive(Clone, Debug, Deserialize, Serialize)]
77#[serde(rename_all = "kebab-case")]
78pub struct SeedPeer {
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub peer_id: Option<anemo::PeerId>,
81 pub address: Multiaddr,
82}
83
84#[derive(Clone, Debug, Deserialize, Serialize)]
85#[serde(rename_all = "kebab-case")]
86pub struct AllowlistedPeer {
87 pub peer_id: anemo::PeerId,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub address: Option<Multiaddr>,
90}
91
92#[derive(Clone, Debug, Default, Deserialize, Serialize)]
93#[serde(rename_all = "kebab-case")]
94pub struct StateSyncConfig {
95 #[serde(skip_serializing_if = "Vec::is_empty", default)]
106 pub pinned_checkpoints: Vec<(CheckpointSequenceNumber, CheckpointDigest)>,
107
108 #[serde(skip_serializing_if = "Option::is_none")]
112 pub interval_period_ms: Option<u64>,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
118 pub mailbox_capacity: Option<usize>,
119
120 #[serde(skip_serializing_if = "Option::is_none")]
125 pub synced_checkpoint_broadcast_channel_capacity: Option<usize>,
126
127 #[serde(skip_serializing_if = "Option::is_none")]
132 pub checkpoint_header_download_concurrency: Option<usize>,
133
134 #[serde(skip_serializing_if = "Option::is_none")]
139 pub checkpoint_content_download_concurrency: Option<usize>,
140
141 #[serde(skip_serializing_if = "Option::is_none")]
148 pub checkpoint_content_download_tx_concurrency: Option<u64>,
149
150 #[serde(skip_serializing_if = "Option::is_none")]
155 pub timeout_ms: Option<u64>,
156
157 #[serde(skip_serializing_if = "Option::is_none")]
162 pub checkpoint_content_timeout_ms: Option<u64>,
163
164 #[serde(skip_serializing_if = "Option::is_none")]
168 pub push_checkpoint_summary_rate_limit: Option<NonZeroU32>,
169
170 #[serde(skip_serializing_if = "Option::is_none")]
174 pub get_checkpoint_summary_rate_limit: Option<NonZeroU32>,
175
176 #[serde(skip_serializing_if = "Option::is_none")]
180 pub get_checkpoint_contents_rate_limit: Option<NonZeroU32>,
181
182 #[serde(skip_serializing_if = "Option::is_none")]
186 pub get_checkpoint_contents_inflight_limit: Option<usize>,
187
188 #[serde(skip_serializing_if = "Option::is_none")]
193 pub get_checkpoint_contents_per_checkpoint_limit: Option<usize>,
194
195 #[serde(skip_serializing_if = "Option::is_none")]
198 pub wait_interval_when_no_peer_to_sync_content_ms: Option<u64>,
199}
200
201impl StateSyncConfig {
202 pub fn interval_period(&self) -> Duration {
203 const INTERVAL_PERIOD_MS: u64 = 5_000; Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
206 }
207
208 pub fn mailbox_capacity(&self) -> usize {
209 const MAILBOX_CAPACITY: usize = 1_024;
210
211 self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
212 }
213
214 pub fn synced_checkpoint_broadcast_channel_capacity(&self) -> usize {
215 const SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY: usize = 1_024;
216
217 self.synced_checkpoint_broadcast_channel_capacity
218 .unwrap_or(SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY)
219 }
220
221 pub fn checkpoint_header_download_concurrency(&self) -> usize {
222 const CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY: usize = 400;
223
224 self.checkpoint_header_download_concurrency
225 .unwrap_or(CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY)
226 }
227
228 pub fn checkpoint_content_download_concurrency(&self) -> usize {
229 const CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY: usize = 400;
230
231 self.checkpoint_content_download_concurrency
232 .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY)
233 }
234
235 pub fn checkpoint_content_download_tx_concurrency(&self) -> u64 {
236 const CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY: u64 = 50_000;
237
238 self.checkpoint_content_download_tx_concurrency
239 .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY)
240 }
241
242 pub fn timeout(&self) -> Duration {
243 const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
244
245 self.timeout_ms
246 .map(Duration::from_millis)
247 .unwrap_or(DEFAULT_TIMEOUT)
248 }
249
250 pub fn checkpoint_content_timeout(&self) -> Duration {
251 const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
252
253 self.checkpoint_content_timeout_ms
254 .map(Duration::from_millis)
255 .unwrap_or(DEFAULT_TIMEOUT)
256 }
257
258 pub fn wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
259 self.wait_interval_when_no_peer_to_sync_content_ms
260 .map(Duration::from_millis)
261 .unwrap_or(self.default_wait_interval_when_no_peer_to_sync_content())
262 }
263
264 fn default_wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
265 if cfg!(msim) {
266 Duration::from_secs(5)
267 } else {
268 Duration::from_secs(10)
269 }
270 }
271
272 pub fn randomized_for_testing() -> Self {
273 use rand::Rng;
274 let mut rng = rand::thread_rng();
275 let config = Self {
276 mailbox_capacity: Some(rng.gen_range(16..=2048)),
277 synced_checkpoint_broadcast_channel_capacity: Some(rng.gen_range(16..=2048)),
278 checkpoint_header_download_concurrency: Some(rng.gen_range(10..=500)),
279 checkpoint_content_download_concurrency: Some(rng.gen_range(10..=500)),
280 ..Default::default()
281 };
282 tracing::info!(
283 mailbox_capacity = config.mailbox_capacity.unwrap(),
284 broadcast_capacity = config.synced_checkpoint_broadcast_channel_capacity.unwrap(),
285 header_concurrency = config.checkpoint_header_download_concurrency.unwrap(),
286 content_concurrency = config.checkpoint_content_download_concurrency.unwrap(),
287 "StateSyncConfig::randomized_for_testing"
288 );
289 config
290 }
291}
292
293#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
304pub enum AccessType {
305 Public,
306 Private,
307}
308
309#[derive(Clone, Debug, Default, Deserialize, Serialize)]
310#[serde(rename_all = "kebab-case")]
311pub struct DiscoveryConfig {
312 #[serde(skip_serializing_if = "Option::is_none")]
316 pub interval_period_ms: Option<u64>,
317
318 #[serde(skip_serializing_if = "Option::is_none")]
322 pub target_concurrent_connections: Option<usize>,
323
324 #[serde(skip_serializing_if = "Option::is_none")]
331 pub peers_to_query: Option<usize>,
332
333 #[serde(skip_serializing_if = "Option::is_none")]
337 pub peer_query_timeout_sec: Option<u64>,
338
339 #[serde(skip_serializing_if = "Option::is_none")]
343 pub get_known_peers_rate_limit: Option<NonZeroU32>,
344
345 #[serde(skip_serializing_if = "Option::is_none")]
347 pub access_type: Option<AccessType>,
348
349 #[serde(skip_serializing_if = "Vec::is_empty", default)]
359 pub allowlisted_peers: Vec<AllowlistedPeer>,
360
361 #[serde(skip_serializing_if = "Option::is_none")]
367 pub max_concurrent_address_verifications: Option<usize>,
368
369 #[serde(skip_serializing_if = "Option::is_none")]
373 pub address_verification_timeout_sec: Option<u64>,
374
375 #[serde(skip_serializing_if = "Option::is_none")]
380 pub address_verification_total_timeout_sec: Option<u64>,
381
382 #[serde(skip_serializing_if = "Option::is_none")]
388 pub address_verification_failure_cooldown_sec: Option<u64>,
389
390 #[serde(skip_serializing_if = "Option::is_none")]
395 pub cooldown_cleanup_interval_sec: Option<u64>,
396
397 #[serde(skip_serializing_if = "Option::is_none")]
400 pub allow_private_addresses: Option<bool>,
401}
402
403impl DiscoveryConfig {
404 pub fn interval_period(&self) -> Duration {
405 const INTERVAL_PERIOD_MS: u64 = 10_000; Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
408 }
409
410 pub fn target_concurrent_connections(&self) -> usize {
411 const TARGET_CONCURRENT_CONNECTIONS: usize = 4;
412
413 self.target_concurrent_connections
414 .unwrap_or(TARGET_CONCURRENT_CONNECTIONS)
415 }
416
417 pub fn peers_to_query(&self) -> usize {
418 const PEERS_TO_QUERY: usize = 1;
419
420 self.peers_to_query.unwrap_or(PEERS_TO_QUERY)
421 }
422
423 pub fn peer_query_timeout(&self) -> Duration {
424 const PEER_QUERY_TIMEOUT_SEC: u64 = 1;
425
426 Duration::from_secs(
427 self.peer_query_timeout_sec
428 .unwrap_or(PEER_QUERY_TIMEOUT_SEC),
429 )
430 }
431
432 pub fn access_type(&self) -> AccessType {
433 self.access_type.unwrap_or(AccessType::Public)
435 }
436
437 pub fn max_concurrent_address_verifications(&self) -> usize {
438 const MAX_CONCURRENT_ADDRESS_VERIFICATIONS: usize = 10;
439
440 self.max_concurrent_address_verifications
441 .unwrap_or(MAX_CONCURRENT_ADDRESS_VERIFICATIONS)
442 }
443
444 pub fn address_verification_timeout(&self) -> Duration {
445 const ADDRESS_VERIFICATION_TIMEOUT_SEC: u64 = 3;
446
447 Duration::from_secs(
448 self.address_verification_timeout_sec
449 .unwrap_or(ADDRESS_VERIFICATION_TIMEOUT_SEC),
450 )
451 }
452
453 pub fn address_verification_total_timeout(&self) -> Duration {
454 const ADDRESS_VERIFICATION_TOTAL_TIMEOUT_SEC: u64 = 8;
455
456 Duration::from_secs(
457 self.address_verification_total_timeout_sec
458 .unwrap_or(ADDRESS_VERIFICATION_TOTAL_TIMEOUT_SEC),
459 )
460 }
461
462 pub fn address_verification_failure_cooldown(&self) -> Duration {
463 const ADDRESS_VERIFICATION_FAILURE_COOLDOWN_SEC: u64 = 600; Duration::from_secs(
466 self.address_verification_failure_cooldown_sec
467 .unwrap_or(ADDRESS_VERIFICATION_FAILURE_COOLDOWN_SEC),
468 )
469 }
470
471 pub fn cooldown_cleanup_interval(&self) -> Duration {
472 const COOLDOWN_CLEANUP_INTERVAL_SEC: u64 = 300; Duration::from_secs(
475 self.cooldown_cleanup_interval_sec
476 .unwrap_or(COOLDOWN_CLEANUP_INTERVAL_SEC),
477 )
478 }
479
480 pub fn is_address_verification_cooldown_enabled(&self) -> bool {
482 self.address_verification_failure_cooldown_sec
483 .unwrap_or(600)
484 > 0
485 }
486
487 pub fn allow_private_addresses(&self) -> bool {
490 self.allow_private_addresses.unwrap_or(false)
491 }
492}
493
494#[derive(Clone, Debug, Default, Deserialize, Serialize)]
495#[serde(rename_all = "kebab-case")]
496pub struct RandomnessConfig {
497 #[serde(skip_serializing_if = "Option::is_none")]
502 pub max_partial_sigs_rounds_ahead: Option<u64>,
503
504 #[serde(skip_serializing_if = "Option::is_none")]
509 pub max_partial_sigs_concurrent_sends: Option<usize>,
510
511 #[serde(skip_serializing_if = "Option::is_none")]
516 pub partial_signature_retry_interval_ms: Option<u64>,
517
518 #[serde(skip_serializing_if = "Option::is_none")]
523 pub mailbox_capacity: Option<usize>,
524
525 #[serde(skip_serializing_if = "Option::is_none")]
529 pub send_partial_signatures_inflight_limit: Option<usize>,
530
531 #[serde(skip_serializing_if = "Option::is_none")]
536 pub max_ignored_peer_weight_factor: Option<f64>,
537}
538
539impl RandomnessConfig {
540 pub fn max_partial_sigs_rounds_ahead(&self) -> u64 {
541 const MAX_PARTIAL_SIGS_ROUNDS_AHEAD: u64 = 50;
542
543 self.max_partial_sigs_rounds_ahead
544 .unwrap_or(MAX_PARTIAL_SIGS_ROUNDS_AHEAD)
545 }
546
547 pub fn max_partial_sigs_concurrent_sends(&self) -> usize {
548 const MAX_PARTIAL_SIGS_CONCURRENT_SENDS: usize = 20;
549
550 self.max_partial_sigs_concurrent_sends
551 .unwrap_or(MAX_PARTIAL_SIGS_CONCURRENT_SENDS)
552 }
553 pub fn partial_signature_retry_interval(&self) -> Duration {
554 const PARTIAL_SIGNATURE_RETRY_INTERVAL: u64 = 5_000; Duration::from_millis(
557 self.partial_signature_retry_interval_ms
558 .unwrap_or(PARTIAL_SIGNATURE_RETRY_INTERVAL),
559 )
560 }
561
562 pub fn mailbox_capacity(&self) -> usize {
563 const MAILBOX_CAPACITY: usize = 1_000_000;
564
565 self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
566 }
567
568 pub fn send_partial_signatures_inflight_limit(&self) -> usize {
569 const SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT: usize = 20;
570
571 self.send_partial_signatures_inflight_limit
572 .unwrap_or(SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT)
573 }
574
575 pub fn max_ignored_peer_weight_factor(&self) -> f64 {
576 const MAX_IGNORED_PEER_WEIGHT_FACTOR: f64 = 0.2;
577
578 self.max_ignored_peer_weight_factor
579 .unwrap_or(MAX_IGNORED_PEER_WEIGHT_FACTOR)
580 }
581}