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::{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    /// The address that the p2p network will bind on.
16    #[serde(default = "default_listen_address")]
17    pub listen_address: SocketAddr,
18    /// The external address other nodes can use to reach this node.
19    /// This will be shared with other peers through the discovery service
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub external_address: Option<Multiaddr>,
22    /// SeedPeers are preferred and the node will always try to ensure a
23    /// connection is established with these nodes.
24    #[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    /// Size in bytes above which network messages are considered excessively
35    /// large. Excessively large messages will still be handled, but logged
36    /// and reported in metrics for debugging.
37    ///
38    /// If unspecified, this will default to 8 MiB.
39    #[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    /// List of "known-good" checkpoints that state sync will be forced to use.
96    /// State sync will skip verification of pinned checkpoints, and reject
97    /// checkpoints with digests that don't match pinned values for a given
98    /// sequence number.
99    ///
100    /// This can be used:
101    /// - in case of a fork, to prevent the node from syncing to the wrong
102    ///   chain.
103    /// - in case of a network stall, to force the node to proceed with a
104    ///   manually-injected checkpoint.
105    #[serde(skip_serializing_if = "Vec::is_empty", default)]
106    pub pinned_checkpoints: Vec<(CheckpointSequenceNumber, CheckpointDigest)>,
107
108    /// Query peers for their latest checkpoint every interval period.
109    ///
110    /// If unspecified, this will default to `5,000` milliseconds.
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub interval_period_ms: Option<u64>,
113
114    /// Size of the StateSync actor's mailbox.
115    ///
116    /// If unspecified, this will default to `1,024`.
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub mailbox_capacity: Option<usize>,
119
120    /// Size of the broadcast channel use for notifying other systems of newly
121    /// sync'ed checkpoints.
122    ///
123    /// If unspecified, this will default to `1,024`.
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub synced_checkpoint_broadcast_channel_capacity: Option<usize>,
126
127    /// Set the upper bound on the number of checkpoint headers to be downloaded
128    /// concurrently.
129    ///
130    /// If unspecified, this will default to `400`.
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub checkpoint_header_download_concurrency: Option<usize>,
133
134    /// Set the upper bound on the number of checkpoint contents to be
135    /// downloaded concurrently.
136    ///
137    /// If unspecified, this will default to `400`.
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub checkpoint_content_download_concurrency: Option<usize>,
140
141    /// Set the upper bound on the number of individual transactions contained
142    /// in checkpoint contents to be downloaded concurrently. If both this
143    /// value and `checkpoint_content_download_concurrency` are set, the
144    /// lower of the two will apply.
145    ///
146    /// If unspecified, this will default to `50,000`.
147    #[serde(skip_serializing_if = "Option::is_none")]
148    pub checkpoint_content_download_tx_concurrency: Option<u64>,
149
150    /// Set the timeout that should be used when sending most state-sync RPC
151    /// requests.
152    ///
153    /// If unspecified, this will default to `10,000` milliseconds.
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub timeout_ms: Option<u64>,
156
157    /// Set the timeout that should be used when sending RPC requests to sync
158    /// checkpoint contents.
159    ///
160    /// If unspecified, this will default to `10,000` milliseconds.
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub checkpoint_content_timeout_ms: Option<u64>,
163
164    /// Per-peer rate-limit (in requests/sec) for the PushCheckpointSummary RPC.
165    ///
166    /// If unspecified, this will default to no limit.
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub push_checkpoint_summary_rate_limit: Option<NonZeroU32>,
169
170    /// Per-peer rate-limit (in requests/sec) for the GetCheckpointSummary RPC.
171    ///
172    /// If unspecified, this will default to no limit.
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub get_checkpoint_summary_rate_limit: Option<NonZeroU32>,
175
176    /// Per-peer rate-limit (in requests/sec) for the GetCheckpointContents RPC.
177    ///
178    /// If unspecified, this will default to no limit.
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub get_checkpoint_contents_rate_limit: Option<NonZeroU32>,
181
182    /// Per-peer inflight limit for the GetCheckpointContents RPC.
183    ///
184    /// If unspecified, this will default to no limit.
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub get_checkpoint_contents_inflight_limit: Option<usize>,
187
188    /// Per-checkpoint inflight limit for the GetCheckpointContents RPC. This is
189    /// enforced globally across all peers.
190    ///
191    /// If unspecified, this will default to no limit.
192    #[serde(skip_serializing_if = "Option::is_none")]
193    pub get_checkpoint_contents_per_checkpoint_limit: Option<usize>,
194
195    /// The amount of time to wait before retry if there are no peers to sync
196    /// content from. If unspecified, this will set to default value
197    #[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; // 5 seconds
204
205        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/// Access Type of a node.
294/// AccessType info is shared in the discovery process.
295/// * If the node marks itself as Public, other nodes may try to connect to it.
296/// * If the node marks itself as Private, only nodes that have it in their
297///   `allowlisted_peers` or `seed_peers` will try to connect to it.
298/// * If not set, defaults to Public.
299///
300/// AccessType is useful when a network of nodes want to stay private. To
301/// achieve this, mark every node in this network as `Private` and
302/// allowlist/seed them to each other.
303#[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    /// Query peers for their latest checkpoint every interval period.
313    ///
314    /// If unspecified, this will default to `5,000` milliseconds.
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub interval_period_ms: Option<u64>,
317
318    /// Target number of concurrent connections to establish.
319    ///
320    /// If unspecified, this will default to `4`.
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub target_concurrent_connections: Option<usize>,
323
324    /// Number of peers to query each interval.
325    ///
326    /// Sets the number of peers, to be randomly selected, that are queried for
327    /// their known peers each interval.
328    ///
329    /// If unspecified, this will default to `1`.
330    #[serde(skip_serializing_if = "Option::is_none")]
331    pub peers_to_query: Option<usize>,
332
333    /// Timeout for individual peer query requests in discovery protocol.
334    ///
335    /// If unspecified, this will default to `1` second.
336    #[serde(skip_serializing_if = "Option::is_none")]
337    pub peer_query_timeout_sec: Option<u64>,
338
339    /// Per-peer rate-limit (in requests/sec) for the GetKnownPeers RPC.
340    ///
341    /// If unspecified, this will default to no limit.
342    #[serde(skip_serializing_if = "Option::is_none")]
343    pub get_known_peers_rate_limit: Option<NonZeroU32>,
344
345    /// See docstring for `AccessType`.
346    #[serde(skip_serializing_if = "Option::is_none")]
347    pub access_type: Option<AccessType>,
348
349    /// Like `seed_peers` in `P2pConfig`, allowlisted peers will always be
350    /// allowed to establish connection with this node regardless of the
351    /// concurrency limit. Unlike `seed_peers`, a node does not reach out to
352    /// `allowlisted_peers` preferentially. It is also used to determine if
353    /// a peer is accessible when its AccessType is Private. For example, a
354    /// node will ignore a peer with Private AccessType if the peer is not in
355    /// its `allowlisted_peers`. Namely, the node will not try to establish
356    /// connections to this peer, nor advertise this peer's info to other
357    /// peers in the network.
358    #[serde(skip_serializing_if = "Vec::is_empty", default)]
359    pub allowlisted_peers: Vec<AllowlistedPeer>,
360
361    /// Maximum number of concurrent address verification attempts.
362    /// This prevents overwhelming the network when verifying many peers at
363    /// once.
364    ///
365    /// If unspecified, this will default to `10`.
366    #[serde(skip_serializing_if = "Option::is_none")]
367    pub max_concurrent_address_verifications: Option<usize>,
368
369    /// Timeout for individual address verification attempts.
370    ///
371    /// If unspecified, this will default to `3` seconds.
372    #[serde(skip_serializing_if = "Option::is_none")]
373    pub address_verification_timeout_sec: Option<u64>,
374
375    /// Total timeout for all address verification attempts to prevent DoS
376    /// attacks.
377    ///
378    /// If unspecified, this will default to `8` seconds.
379    #[serde(skip_serializing_if = "Option::is_none")]
380    pub address_verification_total_timeout_sec: Option<u64>,
381
382    /// Cooldown period in seconds for peers whose address verification failed.
383    /// During this period, new peer info from the same peer will be ignored.
384    /// Set to 0 to disable the cooldown feature entirely.
385    ///
386    /// If unspecified, this will default to `600` seconds (10 minutes).
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub address_verification_failure_cooldown_sec: Option<u64>,
389
390    /// Interval for cleaning up old entries from the verification failure
391    /// cooldown list.
392    ///
393    /// If unspecified, this will default to `300` seconds (5 minutes).
394    #[serde(skip_serializing_if = "Option::is_none")]
395    pub cooldown_cleanup_interval_sec: Option<u64>,
396
397    /// Whether to allow private IP and local DNS addresses (e.g., 192.168.0.1,
398    /// localhost, .local) when verifying peer addresses.
399    #[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; // 10 seconds
406
407        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        // defaults None to Public
434        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; // 10 minutes
464
465        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; // 5 minutes
473
474        Duration::from_secs(
475            self.cooldown_cleanup_interval_sec
476                .unwrap_or(COOLDOWN_CLEANUP_INTERVAL_SEC),
477        )
478    }
479
480    /// Returns true if address verification cooldown is enabled (cooldown > 0)
481    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    /// Whether to allow private IP and local DNS addresses (e.g., 192.168.0.1,
488    /// localhost, .local) when verifying peer addresses.
489    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    /// Maximum number of rounds ahead of our most recent completed round for
498    /// which we should accept partial signatures from other validators.
499    ///
500    /// If unspecified, this will default to 50.
501    #[serde(skip_serializing_if = "Option::is_none")]
502    pub max_partial_sigs_rounds_ahead: Option<u64>,
503
504    /// Maximum number of rounds for which partial signatures should be
505    /// concurrently sent.
506    ///
507    /// If unspecified, this will default to 20.
508    #[serde(skip_serializing_if = "Option::is_none")]
509    pub max_partial_sigs_concurrent_sends: Option<usize>,
510
511    /// Interval at which to retry sending partial signatures until the round is
512    /// complete.
513    ///
514    /// If unspecified, this will default to `5,000` milliseconds.
515    #[serde(skip_serializing_if = "Option::is_none")]
516    pub partial_signature_retry_interval_ms: Option<u64>,
517
518    /// Size of the Randomness actor's mailbox. This should be set large enough
519    /// to never overflow unless a bug is encountered.
520    ///
521    /// If unspecified, this will default to `1,000,000`.
522    #[serde(skip_serializing_if = "Option::is_none")]
523    pub mailbox_capacity: Option<usize>,
524
525    /// Per-peer inflight limit for the SendPartialSignatures RPC.
526    ///
527    /// If unspecified, this will default to 20.
528    #[serde(skip_serializing_if = "Option::is_none")]
529    pub send_partial_signatures_inflight_limit: Option<usize>,
530
531    /// Maximum proportion of total peer weight to ignore in case of byzantine
532    /// behavior.
533    ///
534    /// If unspecified, this will default to 0.2.
535    #[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; // 5 seconds
555
556        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}