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