cs_mwc_libp2p_gossipsub/
config.rs

1// Copyright 2020 Sigma Prime Pty Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use std::borrow::Cow;
22use std::time::Duration;
23
24use mwc_libp2p_core::PeerId;
25
26use crate::types::{FastMessageId, GossipsubMessage, MessageId, RawGossipsubMessage};
27
28/// The types of message validation that can be employed by gossipsub.
29#[derive(Debug, Clone)]
30pub enum ValidationMode {
31    /// This is the default setting. This requires the message author to be a valid [`PeerId`] and to
32    /// be present as well as the sequence number. All messages must have valid signatures.
33    ///
34    /// NOTE: This setting will reject messages from nodes using
35    /// [`crate::behaviour::MessageAuthenticity::Anonymous`] and all messages that do not have
36    /// signatures.
37    Strict,
38    /// This setting permits messages that have no author, sequence number or signature. If any of
39    /// these fields exist in the message these are validated.
40    Permissive,
41    /// This setting requires the author, sequence number and signature fields of a message to be
42    /// empty. Any message that contains these fields is considered invalid.
43    Anonymous,
44    /// This setting does not check the author, sequence number or signature fields of incoming
45    /// messages. If these fields contain data, they are simply ignored.
46    ///
47    /// NOTE: This setting will consider messages with invalid signatures as valid messages.
48    None,
49}
50
51/// Configuration parameters that define the performance of the gossipsub network.
52#[derive(Clone)]
53pub struct GossipsubConfig {
54    protocol_id_prefix: Cow<'static, str>,
55    history_length: usize,
56    history_gossip: usize,
57    mesh_n: usize,
58    mesh_n_low: usize,
59    mesh_n_high: usize,
60    retain_scores: usize,
61    gossip_lazy: usize,
62    gossip_factor: f64,
63    heartbeat_initial_delay: Duration,
64    heartbeat_interval: Duration,
65    fanout_ttl: Duration,
66    check_explicit_peers_ticks: u64,
67    max_transmit_size: usize,
68    duplicate_cache_time: Duration,
69    validate_messages: bool,
70    validation_mode: ValidationMode,
71    message_id_fn: fn(&GossipsubMessage) -> MessageId,
72    fast_message_id_fn: Option<fn(&RawGossipsubMessage) -> FastMessageId>,
73    allow_self_origin: bool,
74    do_px: bool,
75    prune_peers: usize,
76    prune_backoff: Duration,
77    backoff_slack: u32,
78    flood_publish: bool,
79    graft_flood_threshold: Duration,
80    mesh_outbound_min: usize,
81    opportunistic_graft_ticks: u64,
82    opportunistic_graft_peers: usize,
83    gossip_retransimission: u32,
84    max_messages_per_rpc: Option<usize>,
85    max_ihave_length: usize,
86    max_ihave_messages: usize,
87    iwant_followup_time: Duration,
88    support_floodsub: bool,
89    published_message_ids_cache_time: Duration,
90    connection_update_ticks: u64,
91    ban_peer_duration: Duration,
92    // if true, will reject connections from all peers except that identified by Dalek PK.
93    // It is critical for MWC, expected that peer PK will match the tor address to connect.
94    accept_dalek_pk_peers_only: bool,
95}
96
97impl GossipsubConfig {
98    // All the getters
99
100    /// The protocol id prefix to negotiate this protocol. The protocol id is of the form
101    /// `/<prefix>/<supported-versions>`. As gossipsub supports version 1.0 and 1.1, there are two
102    /// protocol id's supported.
103    ///
104    /// The default prefix is `meshsub`, giving the supported protocol ids: `/meshsub/1.1.0` and `/meshsub/1.0.0`, negotiated in that order.
105    pub fn protocol_id_prefix(&self) -> &Cow<'static, str> {
106        &self.protocol_id_prefix
107    }
108
109    // Overlay network parameters.
110    /// Number of heartbeats to keep in the `memcache` (default is 5).
111    pub fn history_length(&self) -> usize {
112        self.history_length
113    }
114
115    /// Number of past heartbeats to gossip about (default is 3).
116    pub fn history_gossip(&self) -> usize {
117        self.history_gossip
118    }
119
120    /// Target number of peers for the mesh network (D in the spec, default is 6).
121    pub fn mesh_n(&self) -> usize {
122        self.mesh_n
123    }
124
125    /// Minimum number of peers in mesh network before adding more (D_lo in the spec, default is 5).
126    pub fn mesh_n_low(&self) -> usize {
127        self.mesh_n_low
128    }
129
130    /// Maximum number of peers in mesh network before removing some (D_high in the spec, default
131    /// is 12).
132    pub fn mesh_n_high(&self) -> usize {
133        self.mesh_n_high
134    }
135
136    /// Affects how peers are selected when pruning a mesh due to over subscription.
137    ///
138    ///  At least `retain_scores` of the retained peers will be high-scoring, while the remainder are
139    ///  chosen randomly (D_score in the spec, default is 4).
140    pub fn retain_scores(&self) -> usize {
141        self.retain_scores
142    }
143
144    /// Minimum number of peers to emit gossip to during a heartbeat (D_lazy in the spec,
145    /// default is 6).
146    pub fn gossip_lazy(&self) -> usize {
147        self.gossip_lazy
148    }
149
150    /// Affects how many peers we will emit gossip to at each heartbeat.
151    ///
152    /// We will send gossip to `gossip_factor * (total number of non-mesh peers)`, or
153    /// `gossip_lazy`, whichever is greater. The default is 0.25.
154    pub fn gossip_factor(&self) -> f64 {
155        self.gossip_factor
156    }
157
158    /// Initial delay in each heartbeat (default is 5 seconds).
159    pub fn heartbeat_initial_delay(&self) -> Duration {
160        self.heartbeat_initial_delay
161    }
162
163    /// Time between each heartbeat (default is 1 second).
164    pub fn heartbeat_interval(&self) -> Duration {
165        self.heartbeat_interval
166    }
167
168    /// Time to live for fanout peers (default is 60 seconds).
169    pub fn fanout_ttl(&self) -> Duration {
170        self.fanout_ttl
171    }
172
173    /// The number of heartbeat ticks until we recheck the connection to explicit peers and
174    /// reconnecting if necessary (default 300).
175    pub fn check_explicit_peers_ticks(&self) -> u64 {
176        self.check_explicit_peers_ticks
177    }
178
179    /// The maximum byte size for each gossipsub RPC (default is 65536 bytes).
180    ///
181    /// This represents the maximum size of the entire protobuf payload. It must be at least
182    /// large enough to support basic control messages. If Peer eXchange is enabled, this
183    /// must be large enough to transmit the desired peer information on pruning. It must be at
184    /// least 100 bytes. Default is 65536 bytes.
185    pub fn max_transmit_size(&self) -> usize {
186        self.max_transmit_size
187    }
188
189    /// Duplicates are prevented by storing message id's of known messages in an LRU time cache.
190    /// This settings sets the time period that messages are stored in the cache. Duplicates can be
191    /// received if duplicate messages are sent at a time greater than this setting apart. The
192    /// default is 1 minute.
193    pub fn duplicate_cache_time(&self) -> Duration {
194        self.duplicate_cache_time
195    }
196
197    /// When set to `true`, prevents automatic forwarding of all received messages. This setting
198    /// allows a user to validate the messages before propagating them to their peers. If set to
199    /// true, the user must manually call [`crate::Gossipsub::report_message_validation_result()`]
200    /// on the behaviour to forward message once validated (default is `false`).
201    /// The default is `false`.
202    pub fn validate_messages(&self) -> bool {
203        self.validate_messages
204    }
205
206    /// Determines the level of validation used when receiving messages. See [`ValidationMode`]
207    /// for the available types. The default is ValidationMode::Strict.
208    pub fn validation_mode(&self) -> &ValidationMode {
209        &self.validation_mode
210    }
211
212    /// A user-defined function allowing the user to specify the message id of a gossipsub message.
213    /// The default value is to concatenate the source peer id with a sequence number. Setting this
214    /// parameter allows the user to address packets arbitrarily. One example is content based
215    /// addressing, where this function may be set to `hash(message)`. This would prevent messages
216    /// of the same content from being duplicated.
217    ///
218    /// The function takes a [`GossipsubMessage`] as input and outputs a String to be interpreted as
219    /// the message id.
220    pub fn message_id(&self, message: &GossipsubMessage) -> MessageId {
221        (self.message_id_fn)(message)
222    }
223
224    /// A user-defined optional function that computes fast ids from raw messages. This can be used
225    /// to avoid possibly expensive transformations from [`RawGossipsubMessage`] to
226    /// [`GossipsubMessage`] for duplicates. Two semantically different messages must always
227    /// have different fast message ids, but it is allowed that two semantically identical messages
228    /// have different fast message ids as long as the message_id_fn produces the same id for them.
229    ///
230    /// The function takes a [`RawGossipsubMessage`] as input and outputs a String to be
231    /// interpreted as the fast message id. Default is None.
232    pub fn fast_message_id(&self, message: &RawGossipsubMessage) -> Option<FastMessageId> {
233        self.fast_message_id_fn
234            .map(|fast_message_id_fn| fast_message_id_fn(message))
235    }
236
237    /// By default, gossipsub will reject messages that are sent to us that have the same message
238    /// source as we have specified locally. Enabling this, allows these messages and prevents
239    /// penalizing the peer that sent us the message. Default is false.
240    pub fn allow_self_origin(&self) -> bool {
241        self.allow_self_origin
242    }
243
244    /// Whether Peer eXchange is enabled; this should be enabled in bootstrappers and other well
245    /// connected/trusted nodes. The default is true.
246    pub fn do_px(&self) -> bool {
247        self.do_px
248    }
249
250    /// Controls the number of peers to include in prune Peer eXchange.
251    /// When we prune a peer that's eligible for PX (has a good score, etc), we will try to
252    /// send them signed peer records for up to `prune_peers` other peers that we
253    /// know of. It is recommended that this value is larger than `mesh_n_high` so that the pruned
254    /// peer can reliably form a full mesh. The default is typically 16 however until signed
255    /// records are spec'd this is disabled and set to 0.
256    pub fn prune_peers(&self) -> usize {
257        self.prune_peers
258    }
259
260    /// Controls the backoff time for pruned peers. This is how long
261    /// a peer must wait before attempting to graft into our mesh again after being pruned.
262    /// When pruning a peer, we send them our value of `prune_backoff` so they know
263    /// the minimum time to wait. Peers running older versions may not send a backoff time,
264    /// so if we receive a prune message without one, we will wait at least `prune_backoff`
265    /// before attempting to re-graft. The default is one minute.
266    pub fn prune_backoff(&self) -> Duration {
267        self.prune_backoff
268    }
269
270    /// Number of heartbeat slots considered as slack for backoffs. This guarantees that we wait
271    /// at least backoff_slack heartbeats after a backoff is over before we try to graft. This
272    /// solves problems occuring through high latencies. In particular if
273    /// `backoff_slack * heartbeat_interval` is longer than any latencies between processing
274    /// prunes on our side and processing prunes on the receiving side this guarantees that we
275    /// get not punished for too early grafting. The default is 1.
276    pub fn backoff_slack(&self) -> u32 {
277        self.backoff_slack
278    }
279
280    /// Whether to do flood publishing or not. If enabled newly created messages will always be
281    /// sent to all peers that are subscribed to the topic and have a good enough score.
282    /// The default is true.
283    pub fn flood_publish(&self) -> bool {
284        self.flood_publish
285    }
286
287    /// If a GRAFT comes before `graft_flood_threshold` has elapsed since the last PRUNE,
288    /// then there is an extra score penalty applied to the peer through P7.
289    pub fn graft_flood_threshold(&self) -> Duration {
290        self.graft_flood_threshold
291    }
292
293    /// Minimum number of outbound peers in the mesh network before adding more (D_out in the spec).
294    /// This value must be smaller or equal than `mesh_n / 2` and smaller than `mesh_n_low`.
295    /// The default is 2.
296    pub fn mesh_outbound_min(&self) -> usize {
297        self.mesh_outbound_min
298    }
299
300    /// Number of heartbeat ticks that specify the interval in which opportunistic grafting is
301    /// applied. Every `opportunistic_graft_ticks` we will attempt to select some high-scoring mesh
302    /// peers to replace lower-scoring ones, if the median score of our mesh peers falls below a
303    /// threshold (see https://godoc.org/github.com/libp2p/go-libp2p-pubsub#PeerScoreThresholds).
304    /// The default is 60.
305    pub fn opportunistic_graft_ticks(&self) -> u64 {
306        self.opportunistic_graft_ticks
307    }
308
309    /// Number of heartbeat ticks that specify the interval when number of open connection will be
310    /// rebalanced. Default is 5
311    pub fn connection_update_ticks(&self) -> u64 {
312        self.connection_update_ticks
313    }
314
315    /// Controls how many times we will allow a peer to request the same message id through IWANT
316    /// gossip before we start ignoring them. This is designed to prevent peers from spamming us
317    /// with requests and wasting our resources. The default is 3.
318    pub fn gossip_retransimission(&self) -> u32 {
319        self.gossip_retransimission
320    }
321
322    /// The maximum number of new peers to graft to during opportunistic grafting. The default is 2.
323    pub fn opportunistic_graft_peers(&self) -> usize {
324        self.opportunistic_graft_peers
325    }
326
327    /// The maximum number of messages we will process in a given RPC. If this is unset, there is
328    /// no limit. The default is None.
329    pub fn max_messages_per_rpc(&self) -> Option<usize> {
330        self.max_messages_per_rpc
331    }
332
333    /// The maximum number of messages to include in an IHAVE message.
334    /// Also controls the maximum number of IHAVE ids we will accept and request with IWANT from a
335    /// peer within a heartbeat, to protect from IHAVE floods. You should adjust this value from the
336    /// default if your system is pushing more than 5000 messages in GossipSubHistoryGossip
337    /// heartbeats; with the defaults this is 1666 messages/s. The default is 5000.
338    pub fn max_ihave_length(&self) -> usize {
339        self.max_ihave_length
340    }
341
342    /// GossipSubMaxIHaveMessages is the maximum number of IHAVE messages to accept from a peer
343    /// within a heartbeat.
344    pub fn max_ihave_messages(&self) -> usize {
345        self.max_ihave_messages
346    }
347
348    /// Time to wait for a message requested through IWANT following an IHAVE advertisement.
349    /// If the message is not received within this window, a broken promise is declared and
350    /// the router may apply behavioural penalties. The default is 3 seconds.
351    pub fn iwant_followup_time(&self) -> Duration {
352        self.iwant_followup_time
353    }
354
355    /// Enable support for flooodsub peers. Default false.
356    pub fn support_floodsub(&self) -> bool {
357        self.support_floodsub
358    }
359
360    /// Published message ids time cache duration. The default is 10 seconds.
361    pub fn published_message_ids_cache_time(&self) -> Duration {
362        self.published_message_ids_cache_time
363    }
364
365    /// Peer Ban time interval. Default is 1 hour.
366    pub fn ban_peer_duration(&self) -> &Duration { &self.ban_peer_duration }
367
368    /// Accept peers with Dalek PK identity only.
369    pub fn accept_dalek_pk_peers_only(&self) -> bool { self.accept_dalek_pk_peers_only }
370}
371
372impl Default for GossipsubConfig {
373    fn default() -> Self {
374        // use ConfigBuilder to also validate defaults
375        GossipsubConfigBuilder::default()
376            .build()
377            .expect("Default config parameters should be valid parameters")
378    }
379}
380
381/// The builder struct for constructing a gossipsub configuration.
382pub struct GossipsubConfigBuilder {
383    config: GossipsubConfig,
384}
385
386impl Default for GossipsubConfigBuilder {
387    fn default() -> Self {
388        GossipsubConfigBuilder {
389            config: GossipsubConfig {
390                protocol_id_prefix: Cow::Borrowed("meshsub"),
391                history_length: 5,
392                history_gossip: 3,
393                mesh_n: 6,
394                mesh_n_low: 5,
395                mesh_n_high: 12,
396                retain_scores: 4,
397                gossip_lazy: 6, // default to mesh_n
398                gossip_factor: 0.25,
399                heartbeat_initial_delay: Duration::from_secs(5),
400                heartbeat_interval: Duration::from_secs(1),
401                fanout_ttl: Duration::from_secs(60),
402                check_explicit_peers_ticks: 300,
403                max_transmit_size: 65536,
404                duplicate_cache_time: Duration::from_secs(60),
405                validate_messages: false,
406                validation_mode: ValidationMode::Strict,
407                message_id_fn: |message| {
408                    // default message id is: source + sequence number
409                    // NOTE: If either the peer_id or source is not provided, we set to 0;
410                    let mut source_string = if let Some(peer_id) = message.source.as_ref() {
411                        peer_id.to_base58()
412                    } else {
413                        PeerId::from_bytes(&[0, 1, 0])
414                            .expect("Valid peer id")
415                            .to_base58()
416                    };
417                    source_string
418                        .push_str(&message.sequence_number.unwrap_or_default().to_string());
419                    MessageId::from(source_string)
420                },
421                fast_message_id_fn: None,
422                allow_self_origin: false,
423                do_px: false,
424                prune_peers: 0, // NOTE: Increasing this currently has little effect until Signed records are implemented.
425                prune_backoff: Duration::from_secs(60),
426                backoff_slack: 1,
427                flood_publish: true,
428                graft_flood_threshold: Duration::from_secs(10),
429                mesh_outbound_min: 2,
430                opportunistic_graft_ticks: 60,
431                opportunistic_graft_peers: 2,
432                gossip_retransimission: 3,
433                max_messages_per_rpc: None,
434                max_ihave_length: 5000,
435                max_ihave_messages: 10,
436                iwant_followup_time: Duration::from_secs(3),
437                support_floodsub: false,
438                published_message_ids_cache_time: Duration::from_secs(10),
439                connection_update_ticks: 10,
440                ban_peer_duration: Duration::from_secs(3600),
441                accept_dalek_pk_peers_only: false,
442            },
443        }
444    }
445}
446
447impl From<GossipsubConfig> for GossipsubConfigBuilder {
448    fn from(config: GossipsubConfig) -> Self {
449        GossipsubConfigBuilder { config }
450    }
451}
452
453impl GossipsubConfigBuilder {
454    /// The protocol id to negotiate this protocol (default is `/meshsub/1.0.0`).
455    pub fn protocol_id_prefix(&mut self, protocol_id: impl Into<Cow<'static, str>>) -> &mut Self {
456        self.config.protocol_id_prefix = protocol_id.into();
457        self
458    }
459
460    /// Number of heartbeats to keep in the `memcache` (default is 5).
461    pub fn history_length(&mut self, history_length: usize) -> &mut Self {
462        self.config.history_length = history_length;
463        self
464    }
465
466    /// Number of past heartbeats to gossip about (default is 3).
467    pub fn history_gossip(&mut self, history_gossip: usize) -> &mut Self {
468        self.config.history_gossip = history_gossip;
469        self
470    }
471
472    /// Target number of peers for the mesh network (D in the spec, default is 6).
473    pub fn mesh_n(&mut self, mesh_n: usize) -> &mut Self {
474        self.config.mesh_n = mesh_n;
475        self
476    }
477
478    /// Minimum number of peers in mesh network before adding more (D_lo in the spec, default is 4).
479    pub fn mesh_n_low(&mut self, mesh_n_low: usize) -> &mut Self {
480        self.config.mesh_n_low = mesh_n_low;
481        self
482    }
483
484    /// Maximum number of peers in mesh network before removing some (D_high in the spec, default
485    /// is 12).
486    pub fn mesh_n_high(&mut self, mesh_n_high: usize) -> &mut Self {
487        self.config.mesh_n_high = mesh_n_high;
488        self
489    }
490
491    /// Affects how peers are selected when pruning a mesh due to over subscription.
492    ///
493    /// At least [`Self::retain_scores`] of the retained peers will be high-scoring, while the remainder are
494    /// chosen randomly (D_score in the spec, default is 4).
495    pub fn retain_scores(&mut self, retain_scores: usize) -> &mut Self {
496        self.config.retain_scores = retain_scores;
497        self
498    }
499
500    /// Minimum number of peers to emit gossip to during a heartbeat (D_lazy in the spec,
501    /// default is 6).
502    pub fn gossip_lazy(&mut self, gossip_lazy: usize) -> &mut Self {
503        self.config.gossip_lazy = gossip_lazy;
504        self
505    }
506
507    /// Affects how many peers we will emit gossip to at each heartbeat.
508    ///
509    /// We will send gossip to `gossip_factor * (total number of non-mesh peers)`, or
510    /// `gossip_lazy`, whichever is greater. The default is 0.25.
511    pub fn gossip_factor(&mut self, gossip_factor: f64) -> &mut Self {
512        self.config.gossip_factor = gossip_factor;
513        self
514    }
515
516    /// Initial delay in each heartbeat (default is 5 seconds).
517    pub fn heartbeat_initial_delay(&mut self, heartbeat_initial_delay: Duration) -> &mut Self {
518        self.config.heartbeat_initial_delay = heartbeat_initial_delay;
519        self
520    }
521
522    /// Time between each heartbeat (default is 1 second).
523    pub fn heartbeat_interval(&mut self, heartbeat_interval: Duration) -> &mut Self {
524        self.config.heartbeat_interval = heartbeat_interval;
525        self
526    }
527
528    /// The number of heartbeat ticks until we recheck the connection to explicit peers and
529    /// reconnecting if necessary (default 300).
530    pub fn check_explicit_peers_ticks(&mut self, check_explicit_peers_ticks: u64) -> &mut Self {
531        self.config.check_explicit_peers_ticks = check_explicit_peers_ticks;
532        self
533    }
534
535    /// Time to live for fanout peers (default is 60 seconds).
536    pub fn fanout_ttl(&mut self, fanout_ttl: Duration) -> &mut Self {
537        self.config.fanout_ttl = fanout_ttl;
538        self
539    }
540
541    /// The maximum byte size for each gossip (default is 2048 bytes).
542    pub fn max_transmit_size(&mut self, max_transmit_size: usize) -> &mut Self {
543        self.config.max_transmit_size = max_transmit_size;
544        self
545    }
546
547    /// Duplicates are prevented by storing message id's of known messages in an LRU time cache.
548    /// This settings sets the time period that messages are stored in the cache. Duplicates can be
549    /// received if duplicate messages are sent at a time greater than this setting apart. The
550    /// default is 1 minute.
551    pub fn duplicate_cache_time(&mut self, cache_size: Duration) -> &mut Self {
552        self.config.duplicate_cache_time = cache_size;
553        self
554    }
555
556    /// When set, prevents automatic forwarding of all received messages. This setting
557    /// allows a user to validate the messages before propagating them to their peers. If set,
558    /// the user must manually call [`crate::Gossipsub::report_message_validation_result()`] on the
559    /// behaviour to forward a message once validated.
560    pub fn validate_messages(&mut self) -> &mut Self {
561        self.config.validate_messages = true;
562        self
563    }
564
565    /// Determines the level of validation used when receiving messages. See [`ValidationMode`]
566    /// for the available types. The default is ValidationMode::Strict.
567    pub fn validation_mode(&mut self, validation_mode: ValidationMode) -> &mut Self {
568        self.config.validation_mode = validation_mode;
569        self
570    }
571
572    /// A user-defined function allowing the user to specify the message id of a gossipsub message.
573    /// The default value is to concatenate the source peer id with a sequence number. Setting this
574    /// parameter allows the user to address packets arbitrarily. One example is content based
575    /// addressing, where this function may be set to `hash(message)`. This would prevent messages
576    /// of the same content from being duplicated.
577    ///
578    /// The function takes a [`GossipsubMessage`] as input and outputs a String to be
579    /// interpreted as the message id.
580    pub fn message_id_fn(&mut self, id_fn: fn(&GossipsubMessage) -> MessageId) -> &mut Self {
581        self.config.message_id_fn = id_fn;
582        self
583    }
584
585    /// A user-defined optional function that computes fast ids from raw messages. This can be used
586    /// to avoid possibly expensive transformations from [`RawGossipsubMessage`] to
587    /// [`GossipsubMessage`] for duplicates. Two semantically different messages must always
588    /// have different fast message ids, but it is allowed that two semantically identical messages
589    /// have different fast message ids as long as the message_id_fn produces the same id for them.
590    ///
591    /// The function takes a [`RawGossipsubMessage`] as input and outputs a String to be interpreted
592    /// as the fast message id. Default is None.
593    pub fn fast_message_id_fn(
594        &mut self,
595        fast_id_fn: fn(&RawGossipsubMessage) -> FastMessageId,
596    ) -> &mut Self {
597        self.config.fast_message_id_fn = Some(fast_id_fn);
598        self
599    }
600
601    /// Enables Peer eXchange. This should be enabled in bootstrappers and other well
602    /// connected/trusted nodes. The default is true.
603    pub fn do_px(&mut self) -> &mut Self {
604        self.config.do_px = true;
605        self
606    }
607
608    /// Controls the number of peers to include in prune Peer eXchange.
609    ///
610    /// When we prune a peer that's eligible for PX (has a good score, etc), we will try to
611    /// send them signed peer records for up to [`Self::prune_peers] other peers that we
612    /// know of. It is recommended that this value is larger than [`Self::mesh_n_high`] so that the
613    /// pruned peer can reliably form a full mesh. The default is 16.
614    pub fn prune_peers(&mut self, prune_peers: usize) -> &mut Self {
615        self.config.prune_peers = prune_peers;
616        self
617    }
618
619    /// Controls the backoff time for pruned peers. This is how long
620    /// a peer must wait before attempting to graft into our mesh again after being pruned.
621    /// When pruning a peer, we send them our value of [`Self::prune_backoff`] so they know
622    /// the minimum time to wait. Peers running older versions may not send a backoff time,
623    /// so if we receive a prune message without one, we will wait at least [`Self::prune_backoff`]
624    /// before attempting to re-graft. The default is one minute.
625    pub fn prune_backoff(&mut self, prune_backoff: Duration) -> &mut Self {
626        self.config.prune_backoff = prune_backoff;
627        self
628    }
629
630    /// Number of heartbeat slots considered as slack for backoffs. This gurantees that we wait
631    /// at least backoff_slack heartbeats after a backoff is over before we try to graft. This
632    /// solves problems occuring through high latencies. In particular if
633    /// `backoff_slack * heartbeat_interval` is longer than any latencies between processing
634    /// prunes on our side and processing prunes on the receiving side this guarantees that we
635    /// get not punished for too early grafting. The default is 1.
636    pub fn backoff_slack(&mut self, backoff_slack: u32) -> &mut Self {
637        self.config.backoff_slack = backoff_slack;
638        self
639    }
640
641    /// Whether to do flood publishing or not. If enabled newly created messages will always be
642    /// sent to all peers that are subscribed to the topic and have a good enough score.
643    /// The default is true.
644    pub fn flood_publish(&mut self, flood_publish: bool) -> &mut Self {
645        self.config.flood_publish = flood_publish;
646        self
647    }
648
649    /// If a GRAFT comes before `graft_flood_threshold` has elapsed since the last PRUNE,
650    /// then there is an extra score penalty applied to the peer through P7.
651    pub fn graft_flood_threshold(&mut self, graft_flood_threshold: Duration) -> &mut Self {
652        self.config.graft_flood_threshold = graft_flood_threshold;
653        self
654    }
655
656    /// Minimum number of outbound peers in the mesh network before adding more (D_out in the spec).
657    /// This value must be smaller or equal than `mesh_n / 2` and smaller than `mesh_n_low`.
658    /// The default is 2.
659    pub fn mesh_outbound_min(&mut self, mesh_outbound_min: usize) -> &mut Self {
660        self.config.mesh_outbound_min = mesh_outbound_min;
661        self
662    }
663
664    /// Number of heartbeat ticks that specifcy the interval in which opportunistic grafting is
665    /// applied. Every `opportunistic_graft_ticks` we will attempt to select some high-scoring mesh
666    /// peers to replace lower-scoring ones, if the median score of our mesh peers falls below a
667    /// threshold (see https://godoc.org/github.com/libp2p/go-libp2p-pubsub#PeerScoreThresholds).
668    /// The default is 60.
669    pub fn opportunistic_graft_ticks(&mut self, opportunistic_graft_ticks: u64) -> &mut Self {
670        self.config.opportunistic_graft_ticks = opportunistic_graft_ticks;
671        self
672    }
673
674    /// Controls how many times we will allow a peer to request the same message id through IWANT
675    /// gossip before we start ignoring them. This is designed to prevent peers from spamming us
676    /// with requests and wasting our resources.
677    pub fn gossip_retransimission(&mut self, gossip_retransimission: u32) -> &mut Self {
678        self.config.gossip_retransimission = gossip_retransimission;
679        self
680    }
681
682    /// The maximum number of new peers to graft to during opportunistic grafting. The default is 2.
683    pub fn opportunistic_graft_peers(&mut self, opportunistic_graft_peers: usize) -> &mut Self {
684        self.config.opportunistic_graft_peers = opportunistic_graft_peers;
685        self
686    }
687
688    /// The maximum number of messages we will process in a given RPC. If this is unset, there is
689    /// no limit. The default is None.
690    pub fn max_messages_per_rpc(&mut self, max: Option<usize>) -> &mut Self {
691        self.config.max_messages_per_rpc = max;
692        self
693    }
694
695    /// The maximum number of messages to include in an IHAVE message.
696    /// Also controls the maximum number of IHAVE ids we will accept and request with IWANT from a
697    /// peer within a heartbeat, to protect from IHAVE floods. You should adjust this value from the
698    /// default if your system is pushing more than 5000 messages in GossipSubHistoryGossip
699    /// heartbeats; with the defaults this is 1666 messages/s. The default is 5000.
700    pub fn max_ihave_length(&mut self, max_ihave_length: usize) -> &mut Self {
701        self.config.max_ihave_length = max_ihave_length;
702        self
703    }
704
705    /// GossipSubMaxIHaveMessages is the maximum number of IHAVE messages to accept from a peer
706    /// within a heartbeat.
707    pub fn max_ihave_messages(&mut self, max_ihave_messages: usize) -> &mut Self {
708        self.config.max_ihave_messages = max_ihave_messages;
709        self
710    }
711
712    /// By default, gossipsub will reject messages that are sent to us that has the same message
713    /// source as we have specified locally. Enabling this, allows these messages and prevents
714    /// penalizing the peer that sent us the message. Default is false.
715    pub fn allow_self_origin(&mut self, allow_self_origin: bool) -> &mut Self {
716        self.config.allow_self_origin = allow_self_origin;
717        self
718    }
719
720    /// Time to wait for a message requested through IWANT following an IHAVE advertisement.
721    /// If the message is not received within this window, a broken promise is declared and
722    /// the router may apply behavioural penalties. The default is 3 seconds.
723    pub fn iwant_followup_time(&mut self, iwant_followup_time: Duration) -> &mut Self {
724        self.config.iwant_followup_time = iwant_followup_time;
725        self
726    }
727
728    /// Enable support for flooodsub peers.
729    pub fn support_floodsub(&mut self) -> &mut Self {
730        self.config.support_floodsub = true;
731        self
732    }
733
734    /// Published message ids time cache duration. The default is 10 seconds.
735    pub fn published_message_ids_cache_time(
736        &mut self,
737        published_message_ids_cache_time: Duration,
738    ) -> &mut Self {
739        self.config.published_message_ids_cache_time = published_message_ids_cache_time;
740        self
741    }
742
743    /// Duration fir the peer ban.
744    pub fn ban_peer_duration(&mut self, duration: Duration ) -> &mut Self {
745        self.config.ban_peer_duration = duration;
746        self
747    }
748
749    /// Accept peers that identified by Dalek Public Key only. It is required for Tor connction
750    /// In this case PeerId will have it's tor address to call in.
751    pub fn accept_dalek_pk_peers_only(&mut self) -> &mut Self {
752        self.config.accept_dalek_pk_peers_only = true;
753        self
754    }
755
756    /// Constructs a [`GossipsubConfig`] from the given configuration and validates the settings.
757    pub fn build(&self) -> Result<GossipsubConfig, &str> {
758        // check all constraints on config
759
760        if self.config.max_transmit_size < 100 {
761            return Err("The maximum transmission size must be greater than 100 to permit basic control messages");
762        }
763
764        if self.config.history_length < self.config.history_gossip {
765            return Err(
766                "The history_length must be greater than or equal to the history_gossip \
767                length",
768            );
769        }
770
771        if !(self.config.mesh_outbound_min < self.config.mesh_n_low
772            && self.config.mesh_n_low <= self.config.mesh_n
773            && self.config.mesh_n <= self.config.mesh_n_high)
774        {
775            return Err("The following inequality doesn't hold \
776                mesh_outbound_min < mesh_n_low <= mesh_n <= mesh_n_high");
777        }
778
779        if self.config.mesh_outbound_min * 2 > self.config.mesh_n {
780            return Err(
781                "The following inequality doesn't hold mesh_outbound_min <= self.config.mesh_n / 2",
782            );
783        }
784        Ok(self.config.clone())
785    }
786}
787
788impl std::fmt::Debug for GossipsubConfig {
789    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
790        let mut builder = f.debug_struct("GossipsubConfig");
791        let _ = builder.field("protocol_id_prefix", &self.protocol_id_prefix);
792        let _ = builder.field("history_length", &self.history_length);
793        let _ = builder.field("history_gossip", &self.history_gossip);
794        let _ = builder.field("mesh_n", &self.mesh_n);
795        let _ = builder.field("mesh_n_low", &self.mesh_n_low);
796        let _ = builder.field("mesh_n_high", &self.mesh_n_high);
797        let _ = builder.field("retain_scores", &self.retain_scores);
798        let _ = builder.field("gossip_lazy", &self.gossip_lazy);
799        let _ = builder.field("gossip_factor", &self.gossip_factor);
800        let _ = builder.field("heartbeat_initial_delay", &self.heartbeat_initial_delay);
801        let _ = builder.field("heartbeat_interval", &self.heartbeat_interval);
802        let _ = builder.field("fanout_ttl", &self.fanout_ttl);
803        let _ = builder.field("max_transmit_size", &self.max_transmit_size);
804        let _ = builder.field("duplicate_cache_time", &self.duplicate_cache_time);
805        let _ = builder.field("validation_mode", &self.validation_mode);
806        let _ = builder.field("allow_self_origin", &self.allow_self_origin);
807        let _ = builder.field("do_px", &self.do_px);
808        let _ = builder.field("prune_peers", &self.prune_peers);
809        let _ = builder.field("prune_backoff", &self.prune_backoff);
810        let _ = builder.field("backoff_slack", &self.backoff_slack);
811        let _ = builder.field("flood_publish", &self.flood_publish);
812        let _ = builder.field("graft_flood_threshold", &self.graft_flood_threshold);
813        let _ = builder.field("mesh_outbound_min", &self.mesh_outbound_min);
814        let _ = builder.field("opportunistic_graft_ticks", &self.opportunistic_graft_ticks);
815        let _ = builder.field("opportunistic_graft_peers", &self.opportunistic_graft_peers);
816        let _ = builder.field("max_messages_per_rpc", &self.max_messages_per_rpc);
817        let _ = builder.field("max_ihave_length", &self.max_ihave_length);
818        let _ = builder.field("max_ihave_messages", &self.max_ihave_messages);
819        let _ = builder.field("iwant_followup_time", &self.iwant_followup_time);
820        let _ = builder.field("support_floodsub", &self.support_floodsub);
821        let _ = builder.field(
822            "published_message_ids_cache_time",
823            &self.published_message_ids_cache_time,
824        );
825        builder.finish()
826    }
827}
828
829#[cfg(test)]
830mod test {
831    use super::*;
832
833    #[test]
834    fn create_thing() {
835        let builder: GossipsubConfig = GossipsubConfigBuilder::default()
836            .protocol_id_prefix("purple")
837            .build()
838            .unwrap();
839
840        dbg!(builder);
841    }
842}