Skip to main content

iota_config/
p2p.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use 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    /// The address that the p2p network will bind on.
20    #[serde(default = "default_listen_address")]
21    pub listen_address: SocketAddr,
22    /// The external address other nodes can use to reach this node.
23    /// This will be shared with other peers through the discovery service
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub external_address: Option<Multiaddr>,
26    /// SeedPeers are preferred and the node will always try to ensure a
27    /// connection is established with these nodes.
28    #[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    /// Size in bytes above which network messages are considered excessively
39    /// large. Excessively large messages will still be handled, but logged
40    /// and reported in metrics for debugging.
41    ///
42    /// If unspecified, this will default to 8 MiB.
43    #[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    /// List of "known-good" checkpoints that state sync will be forced to use.
100    /// State sync will skip verification of pinned checkpoints, and reject
101    /// checkpoints with digests that don't match pinned values for a given
102    /// sequence number.
103    ///
104    /// This can be used:
105    /// - in case of a fork, to prevent the node from syncing to the wrong
106    ///   chain.
107    /// - in case of a network stall, to force the node to proceed with a
108    ///   manually-injected checkpoint.
109    #[serde(skip_serializing_if = "Vec::is_empty", default)]
110    pub pinned_checkpoints: Vec<(CheckpointSequenceNumber, CheckpointDigest)>,
111
112    /// Query peers for their latest checkpoint every interval period.
113    ///
114    /// If unspecified, this will default to `5,000` milliseconds.
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub interval_period_ms: Option<u64>,
117
118    /// Size of the StateSync actor's mailbox.
119    ///
120    /// If unspecified, this will default to `1,024`.
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub mailbox_capacity: Option<usize>,
123
124    /// Size of the broadcast channel use for notifying other systems of newly
125    /// sync'ed checkpoints.
126    ///
127    /// If unspecified, this will default to `1,024`.
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub synced_checkpoint_broadcast_channel_capacity: Option<usize>,
130
131    /// Set the upper bound on the number of checkpoint headers to be downloaded
132    /// concurrently.
133    ///
134    /// If unspecified, this will default to `400`.
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub checkpoint_header_download_concurrency: Option<usize>,
137
138    /// Set the upper bound on the number of checkpoint contents to be
139    /// downloaded concurrently.
140    ///
141    /// If unspecified, this will default to `400`.
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub checkpoint_content_download_concurrency: Option<usize>,
144
145    /// Set the upper bound on the number of individual transactions contained
146    /// in checkpoint contents to be downloaded concurrently. If both this
147    /// value and `checkpoint_content_download_concurrency` are set, the
148    /// lower of the two will apply.
149    ///
150    /// If unspecified, this will default to `50,000`.
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub checkpoint_content_download_tx_concurrency: Option<u64>,
153
154    /// Set the timeout that should be used when sending most state-sync RPC
155    /// requests.
156    ///
157    /// If unspecified, this will default to `10,000` milliseconds.
158    #[serde(skip_serializing_if = "Option::is_none")]
159    pub timeout_ms: Option<u64>,
160
161    /// Set the timeout that should be used when sending RPC requests to sync
162    /// checkpoint contents.
163    ///
164    /// If unspecified, this will default to `10,000` milliseconds.
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub checkpoint_content_timeout_ms: Option<u64>,
167
168    /// Per-peer rate-limit (in requests/sec) for the PushCheckpointSummary RPC.
169    ///
170    /// If unspecified, this will default to no limit.
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub push_checkpoint_summary_rate_limit: Option<NonZeroU32>,
173
174    /// Per-peer rate-limit (in requests/sec) for the GetCheckpointSummary RPC.
175    ///
176    /// If unspecified, this will default to no limit.
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub get_checkpoint_summary_rate_limit: Option<NonZeroU32>,
179
180    /// Per-peer rate-limit (in requests/sec) for the GetCheckpointContents RPC.
181    ///
182    /// If unspecified, this will default to no limit.
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub get_checkpoint_contents_rate_limit: Option<NonZeroU32>,
185
186    /// Per-peer inflight limit for the GetCheckpointContents RPC.
187    ///
188    /// If unspecified, this will default to no limit.
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub get_checkpoint_contents_inflight_limit: Option<usize>,
191
192    /// Per-checkpoint inflight limit for the GetCheckpointContents RPC. This is
193    /// enforced globally across all peers.
194    ///
195    /// If unspecified, this will default to no limit.
196    #[serde(skip_serializing_if = "Option::is_none")]
197    pub get_checkpoint_contents_per_checkpoint_limit: Option<usize>,
198
199    /// The amount of time to wait before retry if there are no peers to sync
200    /// content from. If unspecified, this will set to default value
201    #[serde(skip_serializing_if = "Option::is_none")]
202    pub wait_interval_when_no_peer_to_sync_content_ms: Option<u64>,
203
204    /// Stop syncing checkpoints more than this many above the executed
205    /// watermark, and resume as execution catches up. Bounds the disk space
206    /// held by checkpoints that are synced but not yet executed, since only
207    /// executed checkpoints can be pruned. Applies to checkpoint summaries and
208    /// contents, and to sync from peers and from the checkpoint archive
209    /// alike.
210    ///
211    /// If unspecified, this will default to `100,000`.
212    #[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; // 5 seconds
219
220        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/// Access Type of a node.
317/// AccessType info is shared in the discovery process.
318/// * If the node marks itself as Public, other nodes may try to connect to it.
319/// * If the node marks itself as Private, only nodes that have it in their
320///   `allowlisted_peers` or `seed_peers` will try to connect to it.
321/// * If not set, defaults to Public.
322///
323/// AccessType is useful when a network of nodes want to stay private. To
324/// achieve this, mark every node in this network as `Private` and
325/// allowlist/seed them to each other.
326#[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    /// Query peers for their latest checkpoint every interval period.
336    ///
337    /// If unspecified, this will default to `5,000` milliseconds.
338    #[serde(skip_serializing_if = "Option::is_none")]
339    pub interval_period_ms: Option<u64>,
340
341    /// Target number of concurrent connections to establish.
342    ///
343    /// If unspecified, this will default to `4`.
344    #[serde(skip_serializing_if = "Option::is_none")]
345    pub target_concurrent_connections: Option<usize>,
346
347    /// Number of peers to query each interval.
348    ///
349    /// Sets the number of peers, to be randomly selected, that are queried for
350    /// their known peers each interval.
351    ///
352    /// If unspecified, this will default to `1`.
353    #[serde(skip_serializing_if = "Option::is_none")]
354    pub peers_to_query: Option<usize>,
355
356    /// Timeout for individual peer query requests in discovery protocol.
357    ///
358    /// If unspecified, this will default to `1` second.
359    #[serde(skip_serializing_if = "Option::is_none")]
360    pub peer_query_timeout_sec: Option<u64>,
361
362    /// Per-peer rate-limit (in requests/sec) for the GetKnownPeers RPC.
363    ///
364    /// If unspecified, this will default to no limit.
365    #[serde(skip_serializing_if = "Option::is_none")]
366    pub get_known_peers_rate_limit: Option<NonZeroU32>,
367
368    /// See docstring for `AccessType`.
369    #[serde(skip_serializing_if = "Option::is_none")]
370    pub access_type: Option<AccessType>,
371
372    /// Like `seed_peers` in `P2pConfig`, allowlisted peers will always be
373    /// allowed to establish connection with this node regardless of the
374    /// concurrency limit. Unlike `seed_peers`, a node does not reach out to
375    /// `allowlisted_peers` preferentially. It is also used to determine if
376    /// a peer is accessible when its AccessType is Private. For example, a
377    /// node will ignore a peer with Private AccessType if the peer is not in
378    /// its `allowlisted_peers`. Namely, the node will not try to establish
379    /// connections to this peer, nor advertise this peer's info to other
380    /// peers in the network.
381    #[serde(skip_serializing_if = "Vec::is_empty", default)]
382    pub allowlisted_peers: Vec<AllowlistedPeer>,
383
384    /// Maximum number of concurrent address verification attempts.
385    /// This prevents overwhelming the network when verifying many peers at
386    /// once.
387    ///
388    /// If unspecified, this will default to `10`.
389    #[serde(skip_serializing_if = "Option::is_none")]
390    pub max_concurrent_address_verifications: Option<usize>,
391
392    /// Timeout for individual address verification attempts.
393    ///
394    /// If unspecified, this will default to `3` seconds.
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub address_verification_timeout_sec: Option<u64>,
397
398    /// Total timeout for all address verification attempts to prevent DoS
399    /// attacks.
400    ///
401    /// If unspecified, this will default to `8` seconds.
402    #[serde(skip_serializing_if = "Option::is_none")]
403    pub address_verification_total_timeout_sec: Option<u64>,
404
405    /// Cooldown period in seconds for peers whose address verification failed.
406    /// During this period, new peer info from the same peer will be ignored.
407    /// Set to 0 to disable the cooldown feature entirely.
408    ///
409    /// If unspecified, this will default to `600` seconds (10 minutes).
410    #[serde(skip_serializing_if = "Option::is_none")]
411    pub address_verification_failure_cooldown_sec: Option<u64>,
412
413    /// Interval for cleaning up old entries from the verification failure
414    /// cooldown list.
415    ///
416    /// If unspecified, this will default to `300` seconds (5 minutes).
417    #[serde(skip_serializing_if = "Option::is_none")]
418    pub cooldown_cleanup_interval_sec: Option<u64>,
419
420    /// Whether to allow private IP and local DNS addresses (e.g., 192.168.0.1,
421    /// localhost, .local) when verifying peer addresses.
422    #[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; // 10 seconds
429
430        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        // defaults None to Public
457        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; // 10 minutes
487
488        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; // 5 minutes
496
497        Duration::from_secs(
498            self.cooldown_cleanup_interval_sec
499                .unwrap_or(COOLDOWN_CLEANUP_INTERVAL_SEC),
500        )
501    }
502
503    /// Returns true if address verification cooldown is enabled (cooldown > 0)
504    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    /// Whether to allow private IP and local DNS addresses (e.g., 192.168.0.1,
511    /// localhost, .local) when verifying peer addresses.
512    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    /// Maximum number of rounds ahead of our most recent completed round for
521    /// which we should accept partial signatures from other validators.
522    ///
523    /// If unspecified, this will default to 50.
524    #[serde(skip_serializing_if = "Option::is_none")]
525    pub max_partial_sigs_rounds_ahead: Option<u64>,
526
527    /// Maximum number of rounds for which partial signatures should be
528    /// concurrently sent.
529    ///
530    /// If unspecified, this will default to 20.
531    #[serde(skip_serializing_if = "Option::is_none")]
532    pub max_partial_sigs_concurrent_sends: Option<usize>,
533
534    /// Interval at which to retry sending partial signatures until the round is
535    /// complete.
536    ///
537    /// If unspecified, this will default to `5,000` milliseconds.
538    #[serde(skip_serializing_if = "Option::is_none")]
539    pub partial_signature_retry_interval_ms: Option<u64>,
540
541    /// Size of the Randomness actor's mailbox. This should be set large enough
542    /// to never overflow unless a bug is encountered.
543    ///
544    /// If unspecified, this will default to `1,000,000`.
545    #[serde(skip_serializing_if = "Option::is_none")]
546    pub mailbox_capacity: Option<usize>,
547
548    /// Per-peer inflight limit for the SendPartialSignatures RPC.
549    ///
550    /// If unspecified, this will default to 20.
551    #[serde(skip_serializing_if = "Option::is_none")]
552    pub send_partial_signatures_inflight_limit: Option<usize>,
553
554    /// Maximum proportion of total peer weight to ignore in case of byzantine
555    /// behavior.
556    ///
557    /// If unspecified, this will default to 0.2.
558    #[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; // 5 seconds
578
579        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}