cuprated/config/p2p.rs
1use std::{
2 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
3 path::Path,
4 time::Duration,
5};
6
7use serde::{Deserialize, Serialize};
8
9use cuprate_helper::{fs::address_book_path, network::Network};
10use cuprate_p2p::config::TransportConfig;
11use cuprate_p2p_core::{
12 transports::{Tcp, TcpServerConfig},
13 ClearNet, Transport,
14};
15
16use super::macros::config_struct;
17
18config_struct! {
19 /// P2P config.
20 #[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
21 #[serde(deny_unknown_fields, default)]
22 pub struct P2PConfig {
23 #[child = true]
24 /// The clear-net P2P config.
25 pub clear_net: ClearNetConfig,
26
27 #[child = true]
28 /// Block downloader config.
29 ///
30 /// The block downloader handles downloading old blocks from peers when we are behind.
31 pub block_downloader: BlockDownloaderConfig,
32 }
33}
34
35config_struct! {
36 #[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
37 #[serde(deny_unknown_fields, default)]
38 pub struct BlockDownloaderConfig {
39 #[comment_out = true]
40 /// The size in bytes of the buffer between the block downloader
41 /// and the place which is consuming the downloaded blocks (`cuprated`).
42 ///
43 /// This value is an absolute maximum,
44 /// once this is reached the block downloader will pause.
45 ///
46 /// Type | Number
47 /// Valid values | >= 0
48 /// Examples | 1_000_000_000, 5_500_000_000, 500_000_000
49 pub buffer_bytes: usize,
50
51 #[comment_out = true]
52 /// The size of the in progress queue (in bytes)
53 /// at which cuprated stops requesting more blocks.
54 ///
55 /// The value is _NOT_ an absolute maximum,
56 /// the in-progress queue could get much larger.
57 /// This value is only the value cuprated stops requesting more blocks,
58 /// if cuprated still has requests in progress,
59 /// it will still accept the response and add the blocks to the queue.
60 ///
61 /// Type | Number
62 /// Valid values | >= 0
63 /// Examples | 500_000_000, 1_000_000_000,
64 pub in_progress_queue_bytes: usize,
65
66 #[inline = true]
67 /// The duration between checking the client pool for free peers.
68 ///
69 /// Type | Duration
70 /// Examples | { secs = 30, nanos = 0 }, { secs = 35, nano = 123 }
71 pub check_client_pool_interval: Duration,
72
73 #[comment_out = true]
74 /// The target size of a single batch of blocks (in bytes).
75 ///
76 /// This value must be below 100_000,000,
77 /// it is not recommended to set it above 30_000_000.
78 ///
79 /// Type | Number
80 /// Valid values | 0..100_000,000
81 pub target_batch_bytes: usize,
82 }
83}
84
85impl From<BlockDownloaderConfig> for cuprate_p2p::block_downloader::BlockDownloaderConfig {
86 fn from(value: BlockDownloaderConfig) -> Self {
87 Self {
88 buffer_bytes: value.buffer_bytes,
89 in_progress_queue_bytes: value.in_progress_queue_bytes,
90 check_client_pool_interval: value.check_client_pool_interval,
91 target_batch_bytes: value.target_batch_bytes,
92 initial_batch_len: 1,
93 }
94 }
95}
96
97impl Default for BlockDownloaderConfig {
98 fn default() -> Self {
99 Self {
100 buffer_bytes: 1_000_000_000,
101 in_progress_queue_bytes: 500_000_000,
102 check_client_pool_interval: Duration::from_secs(30),
103 target_batch_bytes: 15_000_000,
104 }
105 }
106}
107
108config_struct! {
109 Shared {
110 #[comment_out = true]
111 /// The number of outbound connections to make and try keep.
112 ///
113 /// It's recommended to keep this value above 12.
114 ///
115 /// Type | Number
116 /// Valid values | >= 0
117 /// Examples | 12, 32, 64, 100, 500
118 pub outbound_connections: usize,
119
120 #[comment_out = true]
121 /// The amount of extra connections to make if cuprated is under load.
122 ///
123 /// Type | Number
124 /// Valid values | >= 0
125 /// Examples | 0, 12, 32, 64, 100, 500
126 pub extra_outbound_connections: usize,
127
128 #[comment_out = true]
129 /// The maximum amount of inbound connections to allow.
130 ///
131 /// Type | Number
132 /// Valid values | >= 0
133 /// Examples | 0, 12, 32, 64, 100, 500
134 pub max_inbound_connections: usize,
135
136 #[comment_out = true]
137 /// The percent of connections that should be
138 /// to peers that haven't connected to before.
139 ///
140 /// 0.0 is 0%.
141 /// 1.0 is 100%.
142 ///
143 /// Type | Floating point number
144 /// Valid values | 0.0..1.0
145 /// Examples | 0.0, 0.5, 0.123, 0.999, 1.0
146 pub gray_peers_percent: f64,
147
148 /// The port to use to accept incoming IPv4 P2P connections.
149 ///
150 /// Setting this to 0 will disable incoming P2P connections.
151 ///
152 /// Type | Number
153 /// Valid values | 0..65534
154 /// Examples | 18080, 9999, 5432
155 pub p2p_port: u16,
156
157 #[child = true]
158 /// The address book config.
159 pub address_book_config: AddressBookConfig,
160 }
161
162 /// The config values for P2P clear-net.
163 #[derive(Debug, Deserialize, Serialize, PartialEq)]
164 #[serde(deny_unknown_fields, default)]
165 pub struct ClearNetConfig {
166 /// The IPv4 address to bind and listen for connections on.
167 ///
168 /// Type | IPv4 address
169 /// Examples | "0.0.0.0", "192.168.1.50"
170 pub listen_on: Ipv4Addr,
171
172 /// Enable IPv6 inbound server.
173 ///
174 /// Setting this to `false` will disable incoming IPv6 P2P connections.
175 ///
176 /// Type | boolean
177 /// Valid values | false, true
178 /// Examples | false
179 pub enable_inbound_v6: bool,
180
181 /// The IPv6 address to bind and listen for connections on.
182 ///
183 /// Type | IPv6 address
184 /// Examples | "::", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
185 pub listen_on_v6: Ipv6Addr,
186 }
187}
188
189impl Default for ClearNetConfig {
190 fn default() -> Self {
191 Self {
192 listen_on: Ipv4Addr::UNSPECIFIED,
193 enable_inbound_v6: false,
194 listen_on_v6: Ipv6Addr::UNSPECIFIED,
195 outbound_connections: 32,
196 extra_outbound_connections: 8,
197 max_inbound_connections: 128,
198 gray_peers_percent: 0.7,
199 p2p_port: 18080,
200 address_book_config: AddressBookConfig::default(),
201 }
202 }
203}
204
205impl From<&ClearNetConfig> for TransportConfig<ClearNet, Tcp> {
206 fn from(value: &ClearNetConfig) -> Self {
207 let server_config = if value.p2p_port != 0 {
208 let mut sc = TcpServerConfig::default();
209 sc.ipv4 = Some(value.listen_on);
210 sc.ipv6 = value.enable_inbound_v6.then_some(value.listen_on_v6);
211 sc.port = value.p2p_port;
212 Some(sc)
213 } else {
214 None
215 };
216
217 Self {
218 client_config: (),
219 server_config,
220 }
221 }
222}
223
224config_struct! {
225 /// The addressbook config exposed to users.
226 #[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
227 #[serde(deny_unknown_fields, default)]
228 pub struct AddressBookConfig {
229 /// The size of the white peer list.
230 ///
231 /// The white list holds peers that have been connected to before.
232 ///
233 /// Type | Number
234 /// Valid values | >= 0
235 /// Examples | 1000, 500, 241
236 pub max_white_list_length: usize,
237
238 /// The size of the gray peer list.
239 ///
240 /// The gray peer list holds peers that have been
241 /// told about but not connected to cuprated.
242 ///
243 /// Type | Number
244 /// Valid values | >= 0
245 /// Examples | 1000, 500, 241
246 pub max_gray_list_length: usize,
247
248 #[inline = true]
249 /// The time period between address book saves.
250 ///
251 /// Type | Duration
252 /// Examples | { secs = 90, nanos = 0 }, { secs = 100, nano = 123 }
253 pub peer_save_period: Duration,
254 }
255}
256
257impl Default for AddressBookConfig {
258 fn default() -> Self {
259 Self {
260 max_white_list_length: 1_000,
261 max_gray_list_length: 5_000,
262 peer_save_period: Duration::from_secs(90),
263 }
264 }
265}
266
267impl AddressBookConfig {
268 /// Returns the [`cuprate_address_book::AddressBookConfig`].
269 pub fn address_book_config(
270 &self,
271 cache_dir: &Path,
272 network: Network,
273 ) -> cuprate_address_book::AddressBookConfig {
274 cuprate_address_book::AddressBookConfig {
275 max_white_list_length: self.max_white_list_length,
276 max_gray_list_length: self.max_gray_list_length,
277 peer_store_directory: address_book_path(cache_dir, network),
278 peer_save_period: self.peer_save_period,
279 }
280 }
281}
282
283/// Seed nodes for [`ClearNet`].
284pub fn clear_net_seed_nodes(network: Network) -> Vec<SocketAddr> {
285 let seeds = match network {
286 Network::Mainnet => [
287 "176.9.0.187:18080",
288 "88.198.163.90:18080",
289 "66.85.74.134:18080",
290 "51.79.173.165:18080",
291 "192.99.8.110:18080",
292 "37.187.74.171:18080",
293 "77.172.183.193:18080",
294 ]
295 .as_slice(),
296 Network::Stagenet => [
297 "176.9.0.187:38080",
298 "51.79.173.165:38080",
299 "192.99.8.110:38080",
300 "37.187.74.171:38080",
301 "77.172.183.193:38080",
302 ]
303 .as_slice(),
304 Network::Testnet => [
305 "176.9.0.187:28080",
306 "51.79.173.165:28080",
307 "192.99.8.110:28080",
308 "37.187.74.171:28080",
309 "77.172.183.193:28080",
310 ]
311 .as_slice(),
312 };
313
314 seeds
315 .iter()
316 .map(|s| s.parse())
317 .collect::<Result<_, _>>()
318 .unwrap()
319}