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 chain.
106    /// - in case of a network stall, to force the node to proceed with a manually-injected
107    ///   checkpoint.
108    #[serde(skip_serializing_if = "Vec::is_empty", default)]
109    pub pinned_checkpoints: Vec<(CheckpointSequenceNumber, CheckpointDigest)>,
110
111    /// Query peers for their latest checkpoint every interval period.
112    ///
113    /// If unspecified, this will default to `5,000` milliseconds.
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub interval_period_ms: Option<u64>,
116
117    /// Size of the StateSync actor's mailbox.
118    ///
119    /// If unspecified, this will default to `1,024`.
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub mailbox_capacity: Option<usize>,
122
123    /// Size of the broadcast channel use for notifying other systems of newly
124    /// sync'ed checkpoints.
125    ///
126    /// If unspecified, this will default to `1,024`.
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub synced_checkpoint_broadcast_channel_capacity: Option<usize>,
129
130    /// Set the upper bound on the number of checkpoint headers to be downloaded
131    /// concurrently.
132    ///
133    /// If unspecified, this will default to `400`.
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub checkpoint_header_download_concurrency: Option<usize>,
136
137    /// Set the upper bound on the number of checkpoint contents to be
138    /// downloaded concurrently.
139    ///
140    /// If unspecified, this will default to `400`.
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub checkpoint_content_download_concurrency: Option<usize>,
143
144    /// Set the upper bound on the number of individual transactions contained
145    /// in checkpoint contents to be downloaded concurrently. If both this
146    /// value and `checkpoint_content_download_concurrency` are set, the
147    /// lower of the two will apply.
148    ///
149    /// If unspecified, this will default to `50,000`.
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub checkpoint_content_download_tx_concurrency: Option<u64>,
152
153    /// Set the timeout that should be used when sending most state-sync RPC
154    /// requests.
155    ///
156    /// If unspecified, this will default to `10,000` milliseconds.
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub timeout_ms: Option<u64>,
159
160    /// Set the timeout that should be used when sending RPC requests to sync
161    /// checkpoint contents.
162    ///
163    /// If unspecified, this will default to `10,000` milliseconds.
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub checkpoint_content_timeout_ms: Option<u64>,
166
167    /// Per-peer rate-limit (in requests/sec) for the PushCheckpointSummary RPC.
168    ///
169    /// If unspecified, this will default to no limit.
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub push_checkpoint_summary_rate_limit: Option<NonZeroU32>,
172
173    /// Per-peer rate-limit (in requests/sec) for the GetCheckpointSummary RPC.
174    ///
175    /// If unspecified, this will default to no limit.
176    #[serde(skip_serializing_if = "Option::is_none")]
177    pub get_checkpoint_summary_rate_limit: Option<NonZeroU32>,
178
179    /// Per-peer rate-limit (in requests/sec) for the GetCheckpointContents RPC.
180    ///
181    /// If unspecified, this will default to no limit.
182    #[serde(skip_serializing_if = "Option::is_none")]
183    pub get_checkpoint_contents_rate_limit: Option<NonZeroU32>,
184
185    /// Per-peer inflight limit for the GetCheckpointContents RPC.
186    ///
187    /// If unspecified, this will default to no limit.
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub get_checkpoint_contents_inflight_limit: Option<usize>,
190
191    /// Per-checkpoint inflight limit for the GetCheckpointContents RPC. This is
192    /// enforced globally across all peers.
193    ///
194    /// If unspecified, this will default to no limit.
195    #[serde(skip_serializing_if = "Option::is_none")]
196    pub get_checkpoint_contents_per_checkpoint_limit: Option<usize>,
197
198    /// The amount of time to wait before retry if there are no peers to sync
199    /// content from. If unspecified, this will set to default value
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub wait_interval_when_no_peer_to_sync_content_ms: Option<u64>,
202
203    /// Stop syncing checkpoints more than this many above the executed
204    /// watermark, and resume as execution catches up. Bounds the disk space
205    /// held by checkpoints that are synced but not yet executed, since only
206    /// executed checkpoints can be pruned. Applies to checkpoint summaries and
207    /// contents, and to sync from peers and from the checkpoint archive
208    /// alike.
209    ///
210    /// If unspecified, this will default to `100,000`.
211    #[serde(skip_serializing_if = "Option::is_none")]
212    pub max_checkpoints_ahead_of_execution: Option<NonZeroU64>,
213}
214
215impl StateSyncConfig {
216    pub fn interval_period(&self) -> Duration {
217        const INTERVAL_PERIOD_MS: u64 = 5_000; // 5 seconds
218
219        Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
220    }
221
222    pub fn mailbox_capacity(&self) -> usize {
223        const MAILBOX_CAPACITY: usize = 1_024;
224
225        self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
226    }
227
228    pub fn synced_checkpoint_broadcast_channel_capacity(&self) -> usize {
229        const SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY: usize = 1_024;
230
231        self.synced_checkpoint_broadcast_channel_capacity
232            .unwrap_or(SYNCED_CHECKPOINT_BROADCAST_CHANNEL_CAPACITY)
233    }
234
235    pub fn checkpoint_header_download_concurrency(&self) -> usize {
236        const CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY: usize = 400;
237
238        self.checkpoint_header_download_concurrency
239            .unwrap_or(CHECKPOINT_HEADER_DOWNLOAD_CONCURRENCY)
240    }
241
242    pub fn checkpoint_content_download_concurrency(&self) -> usize {
243        const CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY: usize = 400;
244
245        self.checkpoint_content_download_concurrency
246            .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_CONCURRENCY)
247    }
248
249    pub fn checkpoint_content_download_tx_concurrency(&self) -> u64 {
250        const CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY: u64 = 50_000;
251
252        self.checkpoint_content_download_tx_concurrency
253            .unwrap_or(CHECKPOINT_CONTENT_DOWNLOAD_TX_CONCURRENCY)
254    }
255
256    pub fn timeout(&self) -> Duration {
257        const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
258
259        self.timeout_ms
260            .map(Duration::from_millis)
261            .unwrap_or(DEFAULT_TIMEOUT)
262    }
263
264    pub fn checkpoint_content_timeout(&self) -> Duration {
265        const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
266
267        self.checkpoint_content_timeout_ms
268            .map(Duration::from_millis)
269            .unwrap_or(DEFAULT_TIMEOUT)
270    }
271
272    pub fn max_checkpoints_ahead_of_execution(&self) -> u64 {
273        const MAX_CHECKPOINTS_AHEAD_OF_EXECUTION: u64 = 100_000;
274
275        self.max_checkpoints_ahead_of_execution
276            .map(NonZeroU64::get)
277            .unwrap_or(MAX_CHECKPOINTS_AHEAD_OF_EXECUTION)
278    }
279
280    pub fn wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
281        self.wait_interval_when_no_peer_to_sync_content_ms
282            .map(Duration::from_millis)
283            .unwrap_or(self.default_wait_interval_when_no_peer_to_sync_content())
284    }
285
286    fn default_wait_interval_when_no_peer_to_sync_content(&self) -> Duration {
287        if cfg!(msim) {
288            Duration::from_secs(5)
289        } else {
290            Duration::from_secs(10)
291        }
292    }
293
294    pub fn randomized_for_testing() -> Self {
295        use rand::RngExt;
296        let mut rng = rand::rng();
297        let config = Self {
298            mailbox_capacity: Some(rng.random_range(16..=2048)),
299            synced_checkpoint_broadcast_channel_capacity: Some(rng.random_range(16..=2048)),
300            checkpoint_header_download_concurrency: Some(rng.random_range(10..=500)),
301            checkpoint_content_download_concurrency: Some(rng.random_range(10..=500)),
302            ..Default::default()
303        };
304        tracing::info!(
305            mailbox_capacity = config.mailbox_capacity.unwrap(),
306            broadcast_capacity = config.synced_checkpoint_broadcast_channel_capacity.unwrap(),
307            header_concurrency = config.checkpoint_header_download_concurrency.unwrap(),
308            content_concurrency = config.checkpoint_content_download_concurrency.unwrap(),
309            "StateSyncConfig::randomized_for_testing"
310        );
311        config
312    }
313}
314
315/// Access Type of a node.
316/// AccessType info is shared in the discovery process.
317/// * If the node marks itself as Public, other nodes may try to connect to it.
318/// * If the node marks itself as Private, only nodes that have it in their `allowlisted_peers` or
319///   `seed_peers` will try to connect to it.
320/// * If not set, defaults to Public.
321///
322/// AccessType is useful when a network of nodes want to stay private. To
323/// achieve this, mark every node in this network as `Private` and
324/// allowlist/seed them to each other.
325#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
326pub enum AccessType {
327    Public,
328    Private,
329}
330
331#[derive(Clone, Debug, Default, Deserialize, Serialize)]
332#[serde(rename_all = "kebab-case")]
333pub struct DiscoveryConfig {
334    /// Query peers for their latest checkpoint every interval period.
335    ///
336    /// If unspecified, this will default to `5,000` milliseconds.
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub interval_period_ms: Option<u64>,
339
340    /// Target number of concurrent connections to establish.
341    ///
342    /// If unspecified, this will default to `4`.
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub target_concurrent_connections: Option<usize>,
345
346    /// Number of peers to query each interval.
347    ///
348    /// Sets the number of peers, to be randomly selected, that are queried for
349    /// their known peers each interval.
350    ///
351    /// If unspecified, this will default to `1`.
352    #[serde(skip_serializing_if = "Option::is_none")]
353    pub peers_to_query: Option<usize>,
354
355    /// Timeout for individual peer query requests in discovery protocol.
356    ///
357    /// If unspecified, this will default to `1` second.
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub peer_query_timeout_sec: Option<u64>,
360
361    /// Per-peer rate-limit (in requests/sec) for the GetKnownPeers RPC.
362    ///
363    /// If unspecified, this will default to no limit.
364    #[serde(skip_serializing_if = "Option::is_none")]
365    pub get_known_peers_rate_limit: Option<NonZeroU32>,
366
367    /// See docstring for `AccessType`.
368    #[serde(skip_serializing_if = "Option::is_none")]
369    pub access_type: Option<AccessType>,
370
371    /// Like `seed_peers` in `P2pConfig`, allowlisted peers will always be
372    /// allowed to establish connection with this node regardless of the
373    /// concurrency limit. Unlike `seed_peers`, a node does not reach out to
374    /// `allowlisted_peers` preferentially. It is also used to determine if
375    /// a peer is accessible when its AccessType is Private. For example, a
376    /// node will ignore a peer with Private AccessType if the peer is not in
377    /// its `allowlisted_peers`. Namely, the node will not try to establish
378    /// connections to this peer, nor advertise this peer's info to other
379    /// peers in the network.
380    #[serde(skip_serializing_if = "Vec::is_empty", default)]
381    pub allowlisted_peers: Vec<AllowlistedPeer>,
382
383    /// Maximum number of concurrent address verification attempts.
384    /// This prevents overwhelming the network when verifying many peers at
385    /// once.
386    ///
387    /// If unspecified, this will default to `10`.
388    #[serde(skip_serializing_if = "Option::is_none")]
389    pub max_concurrent_address_verifications: Option<usize>,
390
391    /// Timeout for individual address verification attempts.
392    ///
393    /// If unspecified, this will default to `3` seconds.
394    #[serde(skip_serializing_if = "Option::is_none")]
395    pub address_verification_timeout_sec: Option<u64>,
396
397    /// Total timeout for all address verification attempts to prevent DoS
398    /// attacks.
399    ///
400    /// If unspecified, this will default to `8` seconds.
401    #[serde(skip_serializing_if = "Option::is_none")]
402    pub address_verification_total_timeout_sec: Option<u64>,
403
404    /// Cooldown period in seconds for peers whose address verification failed.
405    /// During this period, new peer info from the same peer will be ignored.
406    /// Set to 0 to disable the cooldown feature entirely.
407    ///
408    /// If unspecified, this will default to `600` seconds (10 minutes).
409    #[serde(skip_serializing_if = "Option::is_none")]
410    pub address_verification_failure_cooldown_sec: Option<u64>,
411
412    /// Interval for cleaning up old entries from the verification failure
413    /// cooldown list.
414    ///
415    /// If unspecified, this will default to `300` seconds (5 minutes).
416    #[serde(skip_serializing_if = "Option::is_none")]
417    pub cooldown_cleanup_interval_sec: Option<u64>,
418
419    /// Whether to allow private IP and local DNS addresses (e.g., 192.168.0.1,
420    /// localhost, .local) when verifying peer addresses.
421    #[serde(skip_serializing_if = "Option::is_none")]
422    pub allow_private_addresses: Option<bool>,
423}
424
425impl DiscoveryConfig {
426    pub fn interval_period(&self) -> Duration {
427        const INTERVAL_PERIOD_MS: u64 = 10_000; // 10 seconds
428
429        Duration::from_millis(self.interval_period_ms.unwrap_or(INTERVAL_PERIOD_MS))
430    }
431
432    pub fn target_concurrent_connections(&self) -> usize {
433        const TARGET_CONCURRENT_CONNECTIONS: usize = 4;
434
435        self.target_concurrent_connections
436            .unwrap_or(TARGET_CONCURRENT_CONNECTIONS)
437    }
438
439    pub fn peers_to_query(&self) -> usize {
440        const PEERS_TO_QUERY: usize = 1;
441
442        self.peers_to_query.unwrap_or(PEERS_TO_QUERY)
443    }
444
445    pub fn peer_query_timeout(&self) -> Duration {
446        const PEER_QUERY_TIMEOUT_SEC: u64 = 1;
447
448        Duration::from_secs(
449            self.peer_query_timeout_sec
450                .unwrap_or(PEER_QUERY_TIMEOUT_SEC),
451        )
452    }
453
454    pub fn access_type(&self) -> AccessType {
455        // defaults None to Public
456        self.access_type.unwrap_or(AccessType::Public)
457    }
458
459    pub fn max_concurrent_address_verifications(&self) -> usize {
460        const MAX_CONCURRENT_ADDRESS_VERIFICATIONS: usize = 10;
461
462        self.max_concurrent_address_verifications
463            .unwrap_or(MAX_CONCURRENT_ADDRESS_VERIFICATIONS)
464    }
465
466    pub fn address_verification_timeout(&self) -> Duration {
467        const ADDRESS_VERIFICATION_TIMEOUT_SEC: u64 = 3;
468
469        Duration::from_secs(
470            self.address_verification_timeout_sec
471                .unwrap_or(ADDRESS_VERIFICATION_TIMEOUT_SEC),
472        )
473    }
474
475    pub fn address_verification_total_timeout(&self) -> Duration {
476        const ADDRESS_VERIFICATION_TOTAL_TIMEOUT_SEC: u64 = 8;
477
478        Duration::from_secs(
479            self.address_verification_total_timeout_sec
480                .unwrap_or(ADDRESS_VERIFICATION_TOTAL_TIMEOUT_SEC),
481        )
482    }
483
484    pub fn address_verification_failure_cooldown(&self) -> Duration {
485        const ADDRESS_VERIFICATION_FAILURE_COOLDOWN_SEC: u64 = 600; // 10 minutes
486
487        Duration::from_secs(
488            self.address_verification_failure_cooldown_sec
489                .unwrap_or(ADDRESS_VERIFICATION_FAILURE_COOLDOWN_SEC),
490        )
491    }
492
493    pub fn cooldown_cleanup_interval(&self) -> Duration {
494        const COOLDOWN_CLEANUP_INTERVAL_SEC: u64 = 300; // 5 minutes
495
496        Duration::from_secs(
497            self.cooldown_cleanup_interval_sec
498                .unwrap_or(COOLDOWN_CLEANUP_INTERVAL_SEC),
499        )
500    }
501
502    /// Returns true if address verification cooldown is enabled (cooldown > 0)
503    pub fn is_address_verification_cooldown_enabled(&self) -> bool {
504        self.address_verification_failure_cooldown_sec
505            .unwrap_or(600)
506            > 0
507    }
508
509    /// Whether to allow private IP and local DNS addresses (e.g., 192.168.0.1,
510    /// localhost, .local) when verifying peer addresses.
511    pub fn allow_private_addresses(&self) -> bool {
512        self.allow_private_addresses.unwrap_or(false)
513    }
514}
515
516#[derive(Clone, Debug, Default, Deserialize, Serialize)]
517#[serde(rename_all = "kebab-case")]
518pub struct RandomnessConfig {
519    /// Maximum number of rounds ahead of our most recent completed round for
520    /// which we should accept partial signatures from other validators.
521    ///
522    /// If unspecified, this will default to 50.
523    #[serde(skip_serializing_if = "Option::is_none")]
524    pub max_partial_sigs_rounds_ahead: Option<u64>,
525
526    /// Maximum number of rounds for which partial signatures should be
527    /// concurrently sent.
528    ///
529    /// If unspecified, this will default to 20.
530    #[serde(skip_serializing_if = "Option::is_none")]
531    pub max_partial_sigs_concurrent_sends: Option<usize>,
532
533    /// Interval at which to retry sending partial signatures until the round is
534    /// complete.
535    ///
536    /// If unspecified, this will default to `5,000` milliseconds.
537    #[serde(skip_serializing_if = "Option::is_none")]
538    pub partial_signature_retry_interval_ms: Option<u64>,
539
540    /// Size of the Randomness actor's mailbox. This should be set large enough
541    /// to never overflow unless a bug is encountered.
542    ///
543    /// If unspecified, this will default to `1,000,000`.
544    #[serde(skip_serializing_if = "Option::is_none")]
545    pub mailbox_capacity: Option<usize>,
546
547    /// Per-peer inflight limit for the SendPartialSignatures RPC.
548    ///
549    /// If unspecified, this will default to 20.
550    #[serde(skip_serializing_if = "Option::is_none")]
551    pub send_partial_signatures_inflight_limit: Option<usize>,
552
553    /// Maximum proportion of total peer weight to ignore in case of byzantine
554    /// behavior.
555    ///
556    /// If unspecified, this will default to 0.2.
557    #[serde(skip_serializing_if = "Option::is_none")]
558    pub max_ignored_peer_weight_factor: Option<f64>,
559}
560
561impl RandomnessConfig {
562    pub fn max_partial_sigs_rounds_ahead(&self) -> u64 {
563        const MAX_PARTIAL_SIGS_ROUNDS_AHEAD: u64 = 50;
564
565        self.max_partial_sigs_rounds_ahead
566            .unwrap_or(MAX_PARTIAL_SIGS_ROUNDS_AHEAD)
567    }
568
569    pub fn max_partial_sigs_concurrent_sends(&self) -> usize {
570        const MAX_PARTIAL_SIGS_CONCURRENT_SENDS: usize = 20;
571
572        self.max_partial_sigs_concurrent_sends
573            .unwrap_or(MAX_PARTIAL_SIGS_CONCURRENT_SENDS)
574    }
575    pub fn partial_signature_retry_interval(&self) -> Duration {
576        const PARTIAL_SIGNATURE_RETRY_INTERVAL: u64 = 5_000; // 5 seconds
577
578        Duration::from_millis(
579            self.partial_signature_retry_interval_ms
580                .unwrap_or(PARTIAL_SIGNATURE_RETRY_INTERVAL),
581        )
582    }
583
584    pub fn mailbox_capacity(&self) -> usize {
585        const MAILBOX_CAPACITY: usize = 1_000_000;
586
587        self.mailbox_capacity.unwrap_or(MAILBOX_CAPACITY)
588    }
589
590    pub fn send_partial_signatures_inflight_limit(&self) -> usize {
591        const SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT: usize = 20;
592
593        self.send_partial_signatures_inflight_limit
594            .unwrap_or(SEND_PARTIAL_SIGNATURES_INFLIGHT_LIMIT)
595    }
596
597    pub fn max_ignored_peer_weight_factor(&self) -> f64 {
598        const MAX_IGNORED_PEER_WEIGHT_FACTOR: f64 = 0.2;
599
600        self.max_ignored_peer_weight_factor
601            .unwrap_or(MAX_IGNORED_PEER_WEIGHT_FACTOR)
602    }
603}