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}