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}