1use std::{
6 net::SocketAddr,
7 num::{NonZeroU32, NonZeroU64},
8 time::Duration,
9};
10
11use iota_multiaddr::Multiaddr;
12use iota_sdk_types::CheckpointDigest;
13use iota_types::messages_checkpoint::CheckpointSequenceNumber;
14use serde::{Deserialize, Serialize};
15
16#[derive(Clone, Debug, Deserialize, Serialize)]
17#[serde(rename_all = "kebab-case")]
18pub struct P2pConfig {
19 #[serde(default = "default_listen_address")]
21 pub listen_address: SocketAddr,
22 #[serde(skip_serializing_if = "Option::is_none")]
25 pub external_address: Option<Multiaddr>,
26 #[serde(skip_serializing_if = "Vec::is_empty", default)]
29 pub seed_peers: Vec<SeedPeer>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub anemo_config: Option<anemo::Config>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub state_sync: Option<StateSyncConfig>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub discovery: Option<DiscoveryConfig>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub randomness: Option<RandomnessConfig>,
38 #[serde(skip_serializing_if = "Option::is_none")]
44 pub excessive_message_size: Option<usize>,
45}
46
47fn default_listen_address() -> SocketAddr {
48 "0.0.0.0:8084".parse().unwrap()
49}
50
51impl Default for P2pConfig {
52 fn default() -> Self {
53 Self {
54 listen_address: default_listen_address(),
55 external_address: Default::default(),
56 seed_peers: Default::default(),
57 anemo_config: Default::default(),
58 state_sync: None,
59 discovery: None,
60 randomness: None,
61 excessive_message_size: None,
62 }
63 }
64}
65
66impl P2pConfig {
67 pub fn excessive_message_size(&self) -> usize {
68 const EXCESSIVE_MESSAGE_SIZE: usize = 32 << 20;
69
70 self.excessive_message_size
71 .unwrap_or(EXCESSIVE_MESSAGE_SIZE)
72 }
73
74 pub fn set_discovery_config(mut self, discovery_config: DiscoveryConfig) -> Self {
75 self.discovery = Some(discovery_config);
76 self
77 }
78}
79
80#[derive(Clone, Debug, Deserialize, Serialize)]
81#[serde(rename_all = "kebab-case")]
82pub struct SeedPeer {
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub peer_id: Option<anemo::PeerId>,
85 pub address: Multiaddr,
86}
87
88#[derive(Clone, Debug, Deserialize, Serialize)]
89#[serde(rename_all = "kebab-case")]
90pub struct AllowlistedPeer {
91 pub peer_id: anemo::PeerId,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub address: Option<Multiaddr>,
94}
95
96#[derive(Clone, Debug, Default, Deserialize, Serialize)]
97#[serde(rename_all = "kebab-case")]
98pub struct StateSyncConfig {
99 #[serde(skip_serializing_if = "Vec::is_empty", default)]
110 pub pinned_checkpoints: Vec<(CheckpointSequenceNumber, CheckpointDigest)>,
111
112 #[serde(skip_serializing_if = "Option::is_none")]
116 pub interval_period_ms: Option<u64>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
122 pub mailbox_capacity: Option<usize>,
123
124 #[serde(skip_serializing_if = "Option::is_none")]
129 pub synced_checkpoint_broadcast_channel_capacity: Option<usize>,
130
131 #[serde(skip_serializing_if = "Option::is_none")]
136 pub checkpoint_header_download_concurrency: Option<usize>,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
143 pub checkpoint_content_download_concurrency: Option<usize>,
144
145 #[serde(skip_serializing_if = "Option::is_none")]
152 pub checkpoint_content_download_tx_concurrency: Option<u64>,
153
154 #[serde(skip_serializing_if = "Option::is_none")]
159 pub timeout_ms: Option<u64>,
160
161 #[serde(skip_serializing_if = "Option::is_none")]
166 pub checkpoint_content_timeout_ms: Option<u64>,
167
168 #[serde(skip_serializing_if = "Option::is_none")]
172 pub push_checkpoint_summary_rate_limit: Option<NonZeroU32>,
173
174 #[serde(skip_serializing_if = "Option::is_none")]
178 pub get_checkpoint_summary_rate_limit: Option<NonZeroU32>,
179
180 #[serde(skip_serializing_if = "Option::is_none")]
184 pub get_checkpoint_contents_rate_limit: Option<NonZeroU32>,
185
186 #[serde(skip_serializing_if = "Option::is_none")]
190 pub get_checkpoint_contents_inflight_limit: Option<usize>,
191
192 #[serde(skip_serializing_if = "Option::is_none")]
197 pub get_checkpoint_contents_per_checkpoint_limit: Option<usize>,
198
199 #[serde(skip_serializing_if = "Option::is_none")]
202 pub wait_interval_when_no_peer_to_sync_content_ms: Option<u64>,
203
204 #[serde(skip_serializing_if = "Option::is_none")]
213 pub max_checkpoints_ahead_of_execution: Option<NonZeroU64>,
214}
215
216impl StateSyncConfig {
217 pub fn interval_period(&self) -> Duration {
218 const INTERVAL_PERIOD_MS: u64 = 5_000; Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
221 }
222
223 pub fn mailbox_capacity(&self) -> usize {
224 const MAILBOX_CAPACITY: usize = 1_024;
225
226 self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
227 }
228
229 pub fn synced_checkpoint_broadcast_channel_capacity(&self) -> usize {
230 const SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY: usize = 1_024;
231
232 self.synced_checkpoint_broadcast_channel_capacity
233 .unwrap_or(SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY)
234 }
235
236 pub fn checkpoint_header_download_concurrency(&self) -> usize {
237 const CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY: usize = 400;
238
239 self.checkpoint_header_download_concurrency
240 .unwrap_or(CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY)
241 }
242
243 pub fn checkpoint_content_download_concurrency(&self) -> usize {
244 const CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY: usize = 400;
245
246 self.checkpoint_content_download_concurrency
247 .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY)
248 }
249
250 pub fn checkpoint_content_download_tx_concurrency(&self) -> u64 {
251 const CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY: u64 = 50_000;
252
253 self.checkpoint_content_download_tx_concurrency
254 .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY)
255 }
256
257 pub fn timeout(&self) -> Duration {
258 const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
259
260 self.timeout_ms
261 .map(Duration::from_millis)
262 .unwrap_or(DEFAULT_TIMEOUT)
263 }
264
265 pub fn checkpoint_content_timeout(&self) -> Duration {
266 const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
267
268 self.checkpoint_content_timeout_ms
269 .map(Duration::from_millis)
270 .unwrap_or(DEFAULT_TIMEOUT)
271 }
272
273 pub fn max_checkpoints_ahead_of_execution(&self) -> u64 {
274 const MAX_CHECKPOINTS_AHEAD_OF_EXECUTION: u64 = 100_000;
275
276 self.max_checkpoints_ahead_of_execution
277 .map(NonZeroU64::get)
278 .unwrap_or(MAX_CHECKPOINTS_AHEAD_OF_EXECUTION)
279 }
280
281 pub fn wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
282 self.wait_interval_when_no_peer_to_sync_content_ms
283 .map(Duration::from_millis)
284 .unwrap_or(self.default_wait_interval_when_no_peer_to_sync_content())
285 }
286
287 fn default_wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
288 if cfg!(msim) {
289 Duration::from_secs(5)
290 } else {
291 Duration::from_secs(10)
292 }
293 }
294
295 pub fn randomized_for_testing() -> Self {
296 use rand::Rng;
297 let mut rng = rand::thread_rng();
298 let config = Self {
299 mailbox_capacity: Some(rng.gen_range(16..=2048)),
300 synced_checkpoint_broadcast_channel_capacity: Some(rng.gen_range(16..=2048)),
301 checkpoint_header_download_concurrency: Some(rng.gen_range(10..=500)),
302 checkpoint_content_download_concurrency: Some(rng.gen_range(10..=500)),
303 ..Default::default()
304 };
305 tracing::info!(
306 mailbox_capacity = config.mailbox_capacity.unwrap(),
307 broadcast_capacity = config.synced_checkpoint_broadcast_channel_capacity.unwrap(),
308 header_concurrency = config.checkpoint_header_download_concurrency.unwrap(),
309 content_concurrency = config.checkpoint_content_download_concurrency.unwrap(),
310 "StateSyncConfig::randomized_for_testing"
311 );
312 config
313 }
314}
315
316#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
327pub enum AccessType {
328 Public,
329 Private,
330}
331
332#[derive(Clone, Debug, Default, Deserialize, Serialize)]
333#[serde(rename_all = "kebab-case")]
334pub struct DiscoveryConfig {
335 #[serde(skip_serializing_if = "Option::is_none")]
339 pub interval_period_ms: Option<u64>,
340
341 #[serde(skip_serializing_if = "Option::is_none")]
345 pub target_concurrent_connections: Option<usize>,
346
347 #[serde(skip_serializing_if = "Option::is_none")]
354 pub peers_to_query: Option<usize>,
355
356 #[serde(skip_serializing_if = "Option::is_none")]
360 pub peer_query_timeout_sec: Option<u64>,
361
362 #[serde(skip_serializing_if = "Option::is_none")]
366 pub get_known_peers_rate_limit: Option<NonZeroU32>,
367
368 #[serde(skip_serializing_if = "Option::is_none")]
370 pub access_type: Option<AccessType>,
371
372 #[serde(skip_serializing_if = "Vec::is_empty", default)]
382 pub allowlisted_peers: Vec<AllowlistedPeer>,
383
384 #[serde(skip_serializing_if = "Option::is_none")]
390 pub max_concurrent_address_verifications: Option<usize>,
391
392 #[serde(skip_serializing_if = "Option::is_none")]
396 pub address_verification_timeout_sec: Option<u64>,
397
398 #[serde(skip_serializing_if = "Option::is_none")]
403 pub address_verification_total_timeout_sec: Option<u64>,
404
405 #[serde(skip_serializing_if = "Option::is_none")]
411 pub address_verification_failure_cooldown_sec: Option<u64>,
412
413 #[serde(skip_serializing_if = "Option::is_none")]
418 pub cooldown_cleanup_interval_sec: Option<u64>,
419
420 #[serde(skip_serializing_if = "Option::is_none")]
423 pub allow_private_addresses: Option<bool>,
424}
425
426impl DiscoveryConfig {
427 pub fn interval_period(&self) -> Duration {
428 const INTERVAL_PERIOD_MS: u64 = 10_000; Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
431 }
432
433 pub fn target_concurrent_connections(&self) -> usize {
434 const TARGET_CONCURRENT_CONNECTIONS: usize = 4;
435
436 self.target_concurrent_connections
437 .unwrap_or(TARGET_CONCURRENT_CONNECTIONS)
438 }
439
440 pub fn peers_to_query(&self) -> usize {
441 const PEERS_TO_QUERY: usize = 1;
442
443 self.peers_to_query.unwrap_or(PEERS_TO_QUERY)
444 }
445
446 pub fn peer_query_timeout(&self) -> Duration {
447 const PEER_QUERY_TIMEOUT_SEC: u64 = 1;
448
449 Duration::from_secs(
450 self.peer_query_timeout_sec
451 .unwrap_or(PEER_QUERY_TIMEOUT_SEC),
452 )
453 }
454
455 pub fn access_type(&self) -> AccessType {
456 self.access_type.unwrap_or(AccessType::Public)
458 }
459
460 pub fn max_concurrent_address_verifications(&self) -> usize {
461 const MAX_CONCURRENT_ADDRESS_VERIFICATIONS: usize = 10;
462
463 self.max_concurrent_address_verifications
464 .unwrap_or(MAX_CONCURRENT_ADDRESS_VERIFICATIONS)
465 }
466
467 pub fn address_verification_timeout(&self) -> Duration {
468 const ADDRESS_VERIFICATION_TIMEOUT_SEC: u64 = 3;
469
470 Duration::from_secs(
471 self.address_verification_timeout_sec
472 .unwrap_or(ADDRESS_VERIFICATION_TIMEOUT_SEC),
473 )
474 }
475
476 pub fn address_verification_total_timeout(&self) -> Duration {
477 const ADDRESS_VERIFICATION_TOTAL_TIMEOUT_SEC: u64 = 8;
478
479 Duration::from_secs(
480 self.address_verification_total_timeout_sec
481 .unwrap_or(ADDRESS_VERIFICATION_TOTAL_TIMEOUT_SEC),
482 )
483 }
484
485 pub fn address_verification_failure_cooldown(&self) -> Duration {
486 const ADDRESS_VERIFICATION_FAILURE_COOLDOWN_SEC: u64 = 600; Duration::from_secs(
489 self.address_verification_failure_cooldown_sec
490 .unwrap_or(ADDRESS_VERIFICATION_FAILURE_COOLDOWN_SEC),
491 )
492 }
493
494 pub fn cooldown_cleanup_interval(&self) -> Duration {
495 const COOLDOWN_CLEANUP_INTERVAL_SEC: u64 = 300; Duration::from_secs(
498 self.cooldown_cleanup_interval_sec
499 .unwrap_or(COOLDOWN_CLEANUP_INTERVAL_SEC),
500 )
501 }
502
503 pub fn is_address_verification_cooldown_enabled(&self) -> bool {
505 self.address_verification_failure_cooldown_sec
506 .unwrap_or(600)
507 > 0
508 }
509
510 pub fn allow_private_addresses(&self) -> bool {
513 self.allow_private_addresses.unwrap_or(false)
514 }
515}
516
517#[derive(Clone, Debug, Default, Deserialize, Serialize)]
518#[serde(rename_all = "kebab-case")]
519pub struct RandomnessConfig {
520 #[serde(skip_serializing_if = "Option::is_none")]
525 pub max_partial_sigs_rounds_ahead: Option<u64>,
526
527 #[serde(skip_serializing_if = "Option::is_none")]
532 pub max_partial_sigs_concurrent_sends: Option<usize>,
533
534 #[serde(skip_serializing_if = "Option::is_none")]
539 pub partial_signature_retry_interval_ms: Option<u64>,
540
541 #[serde(skip_serializing_if = "Option::is_none")]
546 pub mailbox_capacity: Option<usize>,
547
548 #[serde(skip_serializing_if = "Option::is_none")]
552 pub send_partial_signatures_inflight_limit: Option<usize>,
553
554 #[serde(skip_serializing_if = "Option::is_none")]
559 pub max_ignored_peer_weight_factor: Option<f64>,
560}
561
562impl RandomnessConfig {
563 pub fn max_partial_sigs_rounds_ahead(&self) -> u64 {
564 const MAX_PARTIAL_SIGS_ROUNDS_AHEAD: u64 = 50;
565
566 self.max_partial_sigs_rounds_ahead
567 .unwrap_or(MAX_PARTIAL_SIGS_ROUNDS_AHEAD)
568 }
569
570 pub fn max_partial_sigs_concurrent_sends(&self) -> usize {
571 const MAX_PARTIAL_SIGS_CONCURRENT_SENDS: usize = 20;
572
573 self.max_partial_sigs_concurrent_sends
574 .unwrap_or(MAX_PARTIAL_SIGS_CONCURRENT_SENDS)
575 }
576 pub fn partial_signature_retry_interval(&self) -> Duration {
577 const PARTIAL_SIGNATURE_RETRY_INTERVAL: u64 = 5_000; Duration::from_millis(
580 self.partial_signature_retry_interval_ms
581 .unwrap_or(PARTIAL_SIGNATURE_RETRY_INTERVAL),
582 )
583 }
584
585 pub fn mailbox_capacity(&self) -> usize {
586 const MAILBOX_CAPACITY: usize = 1_000_000;
587
588 self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
589 }
590
591 pub fn send_partial_signatures_inflight_limit(&self) -> usize {
592 const SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT: usize = 20;
593
594 self.send_partial_signatures_inflight_limit
595 .unwrap_or(SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT)
596 }
597
598 pub fn max_ignored_peer_weight_factor(&self) -> f64 {
599 const MAX_IGNORED_PEER_WEIGHT_FACTOR: f64 = 0.2;
600
601 self.max_ignored_peer_weight_factor
602 .unwrap_or(MAX_IGNORED_PEER_WEIGHT_FACTOR)
603 }
604}