Skip to main content

hotshot_libp2p_networking/network/node/
config.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7use std::{collections::HashSet, num::NonZeroUsize, time::Duration};
8
9use libp2p::{Multiaddr, identity::Keypair};
10use libp2p_identity::PeerId;
11
12use super::MAX_GOSSIP_MSG_SIZE;
13
14/// The default Kademlia replication factor
15pub const DEFAULT_REPLICATION_FACTOR: Option<NonZeroUsize> = NonZeroUsize::new(20);
16
17/// describe the configuration of the network
18#[derive(Default, derive_builder::Builder, derive_more::Debug)]
19pub struct NetworkNodeConfig {
20    /// The keypair for the node
21    #[builder(setter(into, strip_option), default)]
22    #[debug(skip)]
23    pub keypair: Option<Keypair>,
24
25    /// The address to bind to
26    #[builder(default)]
27    pub bind_address: Option<Multiaddr>,
28
29    /// Addresses to announce as external addresses to peers.
30    ///
31    /// Each is added via `Swarm::add_external_address` during node setup. Identify will publish
32    /// them, and Kademlia will record them in our self-routing-table entry. Required when the
33    /// node is behind NAT, K8s NodePort, Docker bridge, etc., where the bind address is not
34    /// reachable from peers.
35    #[builder(default)]
36    pub announce_addresses: Vec<Multiaddr>,
37
38    /// Replication factor for entries in the DHT
39    #[builder(setter(into, strip_option), default = "DEFAULT_REPLICATION_FACTOR")]
40    pub replication_factor: Option<NonZeroUsize>,
41
42    #[builder(default)]
43    /// Configuration for `GossipSub`
44    pub gossip_config: GossipConfig,
45
46    #[builder(default)]
47    /// Configuration for `RequestResponse`
48    pub request_response_config: RequestResponseConfig,
49
50    /// list of addresses to connect to at initialization
51    pub to_connect_addrs: HashSet<(PeerId, Multiaddr)>,
52
53    /// republication interval in DHT, must be much less than `ttl`
54    #[builder(default)]
55    pub republication_interval: Option<Duration>,
56
57    /// expiratiry for records in DHT
58    #[builder(default)]
59    pub ttl: Option<Duration>,
60
61    /// The path to the file to save the DHT to
62    #[builder(default)]
63    pub dht_file_path: Option<String>,
64
65    /// The signed authentication message sent to the remote peer
66    /// If not supplied we will not send an authentication message during the handshake
67    #[builder(default)]
68    pub auth_message: Option<Vec<u8>>,
69
70    #[builder(default)]
71    /// The timeout for DHT lookups.
72    pub dht_timeout: Option<Duration>,
73}
74
75impl Clone for NetworkNodeConfig {
76    fn clone(&self) -> Self {
77        Self {
78            keypair: self.keypair.clone(),
79            bind_address: self.bind_address.clone(),
80            announce_addresses: self.announce_addresses.clone(),
81            replication_factor: self.replication_factor,
82            gossip_config: self.gossip_config.clone(),
83            request_response_config: self.request_response_config.clone(),
84            to_connect_addrs: self.to_connect_addrs.clone(),
85            republication_interval: self.republication_interval,
86            ttl: self.ttl,
87            dht_file_path: self.dht_file_path.clone(),
88            auth_message: self.auth_message.clone(),
89            dht_timeout: self.dht_timeout,
90        }
91    }
92}
93
94/// Configuration for Libp2p's Gossipsub
95#[derive(Clone, Debug)]
96#[allow(missing_docs)]
97pub struct GossipConfig {
98    /// The heartbeat interval
99    pub heartbeat_interval: Duration,
100
101    /// The number of past heartbeats to gossip about
102    pub history_gossip: usize,
103    /// The number of past heartbeats to remember the full messages for
104    pub history_length: usize,
105
106    /// The target number of peers in the mesh
107    pub mesh_n: usize,
108    /// The maximum number of peers in the mesh
109    pub mesh_n_high: usize,
110    /// The minimum number of peers in the mesh
111    pub mesh_n_low: usize,
112    /// The minimum number of mesh peers that must be outbound
113    pub mesh_outbound_min: usize,
114
115    /// The maximum gossip message size
116    pub max_transmit_size: usize,
117
118    /// The maximum number of messages in an IHAVE message
119    pub max_ihave_length: usize,
120
121    /// Maximum number of IHAVE messages to accept from a peer within a heartbeat
122    pub max_ihave_messages: usize,
123
124    /// Cache duration for published message IDs
125    pub published_message_ids_cache_time: Duration,
126
127    /// Time to wait for a message requested through IWANT following an IHAVE advertisement
128    pub iwant_followup_time: Duration,
129
130    /// The maximum number of messages we will process in a given RPC
131    pub max_messages_per_rpc: Option<usize>,
132
133    /// Controls how many times we will allow a peer to request the same message id through IWANT gossip before we start ignoring them.
134    pub gossip_retransmission: u32,
135
136    /// If enabled newly created messages will always be sent to all peers that are subscribed to the topic and have a good enough score.
137    pub flood_publish: bool,
138
139    /// The time period that messages are stored in the cache
140    pub duplicate_cache_time: Duration,
141
142    /// Time to live for fanout peers
143    pub fanout_ttl: Duration,
144
145    /// Initial delay in each heartbeat
146    pub heartbeat_initial_delay: Duration,
147
148    /// Affects how many peers we will emit gossip to at each heartbeat
149    pub gossip_factor: f64,
150
151    /// Minimum number of peers to emit gossip to during a heartbeat
152    pub gossip_lazy: usize,
153}
154
155impl Default for GossipConfig {
156    fn default() -> Self {
157        Self {
158            heartbeat_interval: Duration::from_secs(1), // Default of Libp2p
159
160            // The following are slightly modified defaults of Libp2p
161            history_gossip: 6, // The number of past heartbeats to gossip about
162            history_length: 8, // The number of past heartbeats to remember the full messages for
163
164            // The mesh parameters are borrowed from Ethereum:
165            // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub
166            mesh_n: 8,            // The target number of peers in the mesh
167            mesh_n_high: 12,      // The maximum number of peers in the mesh
168            mesh_n_low: 6,        // The minimum number of peers in the mesh
169            mesh_outbound_min: 2, // The minimum number of mesh peers that must be outbound
170
171            max_ihave_length: 5000,
172            max_ihave_messages: 10,
173            published_message_ids_cache_time: Duration::from_secs(60 * 20), // 20 minutes
174            iwant_followup_time: Duration::from_secs(3),
175            max_messages_per_rpc: None,
176            gossip_retransmission: 3,
177            flood_publish: true,
178            duplicate_cache_time: Duration::from_secs(60),
179            fanout_ttl: Duration::from_secs(60),
180            heartbeat_initial_delay: Duration::from_secs(5),
181            gossip_factor: 0.25,
182            gossip_lazy: 6,
183
184            max_transmit_size: MAX_GOSSIP_MSG_SIZE, // The maximum gossip message size
185        }
186    }
187}
188
189/// Configuration for Libp2p's request-response
190#[derive(Clone, Debug)]
191pub struct RequestResponseConfig {
192    /// The maximum request size in bytes
193    pub request_size_maximum: u64,
194    /// The maximum response size in bytes
195    pub response_size_maximum: u64,
196}
197
198impl Default for RequestResponseConfig {
199    fn default() -> Self {
200        Self {
201            request_size_maximum: 20 * 1024 * 1024,
202            response_size_maximum: 20 * 1024 * 1024,
203        }
204    }
205}