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}