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