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