1use ckb_types::{H256, U256};
2use multiaddr::Multiaddr;
3use rand::Rng;
4use serde::{Deserialize, Serialize};
5use std::{
6 fs,
7 io::{Error, ErrorKind, Read, Write},
8 net::{IpAddr, Ipv4Addr, Ipv6Addr},
9 path::PathBuf,
10};
11use ubyte::ByteUnit;
12
13const DEFAULT_SEND_BUFFER: usize = 24 * 1024 * 1024;
15
16const DEFAULT_CHANNEL_SIZE: usize = 1024;
18
19#[derive(Clone, Debug, Serialize, Deserialize, Default)]
21#[serde(deny_unknown_fields)]
22pub struct Config {
23 #[serde(default)]
25 pub whitelist_only: bool,
26 pub max_peers: u32,
30 pub max_outbound_peers: u32,
34 #[serde(default)]
36 pub path: PathBuf,
37 #[serde(default)]
39 pub dns_seeds: Vec<String>,
40 #[serde(default)]
42 pub discovery_local_address: bool,
43 #[serde(default)]
45 pub discovery_announce_check_interval_secs: Option<u64>,
46 pub ping_interval_secs: u64,
50 pub ping_timeout_secs: u64,
54 pub connect_outbound_interval_secs: u64,
56 pub listen_addresses: Vec<Multiaddr>,
58 #[serde(default)]
62 pub public_addresses: Vec<Multiaddr>,
63 pub bootnodes: Vec<Multiaddr>,
67 #[serde(default)]
71 pub whitelist_peers: Vec<Multiaddr>,
72 #[serde(default)]
74 pub upnp: bool,
75 #[serde(default)]
80 pub bootnode_mode: bool,
81 #[serde(default = "default_support_all_protocols")]
83 pub support_protocols: Vec<SupportProtocol>,
84 pub max_send_buffer: Option<usize>,
86 #[serde(default = "default_reuse")]
88 pub reuse_port_on_linux: bool,
89 #[serde(default = "default_reuse_tcp_with_ws")]
91 pub reuse_tcp_with_ws: bool,
92 #[serde(default)]
94 pub disable_block_relay_only_connection: bool,
95 pub channel_size: Option<usize>,
97 #[serde(default = "default_trusted_proxies")]
99 pub trusted_proxies: Vec<IpAddr>,
100 #[cfg(target_family = "wasm")]
101 #[serde(skip)]
102 pub secret_key: [u8; 32],
103 #[serde(default)]
105 pub sync: SyncConfig,
106
107 #[serde(default)]
109 pub proxy: ProxyConfig,
110
111 #[serde(default)]
113 pub onion: OnionConfig,
114}
115
116#[derive(Clone, Debug, Serialize, Deserialize, Default)]
118pub struct ProxyConfig {
119 pub proxy_url: Option<String>,
121 #[serde(default = "default_proxy_random_auth")]
123 pub proxy_random_auth: bool,
124}
125
126const fn default_proxy_random_auth() -> bool {
128 true
129}
130
131#[derive(Clone, Debug, Serialize, Deserialize, Default)]
133#[serde(deny_unknown_fields)]
134pub struct OnionConfig {
135 pub listen_on_onion: bool,
137 pub onion_server: Option<String>,
139 pub p2p_listen_address: Option<String>,
143 pub onion_private_key_path: Option<String>,
145 #[serde(default = "default_tor_controller")]
147 pub tor_controller: String,
148 pub tor_password: Option<String>,
150 #[serde(default = "default_onion_external_port")]
154 pub onion_external_port: u16,
155}
156
157fn default_tor_controller() -> String {
159 "127.0.0.1:9051".to_string()
160}
161
162fn default_onion_external_port() -> u16 {
164 8115
165}
166
167fn default_trusted_proxies() -> Vec<IpAddr> {
168 vec![
169 IpAddr::V4(Ipv4Addr::LOCALHOST),
170 IpAddr::V6(Ipv6Addr::LOCALHOST),
171 ]
172}
173
174#[derive(Clone, Debug, Serialize, Deserialize, Default)]
176#[serde(deny_unknown_fields)]
177pub struct SyncConfig {
178 #[serde(default)]
180 pub header_map: HeaderMapConfig,
181 #[serde(skip, default)]
183 pub assume_valid_targets: Option<Vec<H256>>,
184 #[serde(skip, default)]
186 pub min_chain_work: U256,
187}
188
189#[derive(Clone, Debug, Serialize, Deserialize)]
193#[serde(deny_unknown_fields)]
194pub struct HeaderMapConfig {
195 pub primary_limit: Option<usize>,
197 pub backend_close_threshold: Option<usize>,
199 #[serde(default = "default_memory_limit")]
201 pub memory_limit: ByteUnit,
202}
203
204impl Default for HeaderMapConfig {
205 fn default() -> Self {
206 Self {
207 primary_limit: None,
208 backend_close_threshold: None,
209 memory_limit: default_memory_limit(),
210 }
211 }
212}
213
214const fn default_memory_limit() -> ByteUnit {
215 ByteUnit::Megabyte(256)
216}
217
218#[derive(Clone, Debug, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)]
219#[allow(missing_docs)]
220pub enum SupportProtocol {
221 Ping,
222 Discovery,
223 Identify,
224 Feeler,
225 DisconnectMessage,
226 Sync,
227 Relay,
228 Time,
229 Alert,
230 LightClient,
231 Filter,
232 HolePunching,
233}
234
235#[allow(missing_docs)]
236pub fn default_support_all_protocols() -> Vec<SupportProtocol> {
237 vec![
238 SupportProtocol::Ping,
239 SupportProtocol::Discovery,
240 SupportProtocol::Identify,
241 SupportProtocol::Feeler,
242 SupportProtocol::DisconnectMessage,
243 SupportProtocol::Sync,
244 SupportProtocol::Relay,
245 SupportProtocol::Time,
246 SupportProtocol::Alert,
247 SupportProtocol::LightClient,
248 SupportProtocol::Filter,
249 SupportProtocol::HolePunching,
250 ]
251}
252
253pub fn generate_random_key() -> [u8; 32] {
255 loop {
256 let mut key: [u8; 32] = [0; 32];
257 rand::thread_rng().fill(&mut key);
258 if secio::SecioKeyPair::secp256k1_raw_key(key).is_ok() {
259 return key;
260 }
261 }
262}
263
264pub fn write_secret_to_file(secret: &[u8], path: PathBuf) -> Result<(), Error> {
266 fs::OpenOptions::new()
267 .create(true)
268 .write(true)
269 .truncate(true)
270 .open(path)
271 .and_then(|mut file| {
272 file.write_all(secret)?;
273 #[cfg(unix)]
274 {
275 use std::os::unix::fs::PermissionsExt;
276 file.set_permissions(fs::Permissions::from_mode(0o400))
277 }
278 #[cfg(not(unix))]
279 {
280 let mut permissions = file.metadata()?.permissions();
281 permissions.set_readonly(true);
282 file.set_permissions(permissions)
283 }
284 })
285}
286
287pub fn read_secret_key(path: PathBuf) -> Result<Option<secio::SecioKeyPair>, Error> {
289 let mut file = match fs::File::open(path.clone()) {
290 Ok(file) => file,
291 Err(_) => return Ok(None),
292 };
293 let warn = |m: bool, d: &str| {
294 if m {
295 ckb_logger::warn!(
296 "Your network secret file's permission is not {}, path: {:?}. \
297 Please fix it as soon as possible",
298 d,
299 path
300 )
301 }
302 };
303 #[cfg(unix)]
304 {
305 use std::os::unix::fs::PermissionsExt;
306 warn(
307 file.metadata()?.permissions().mode() & 0o177 != 0,
308 "less than 0o600",
309 );
310 }
311 #[cfg(not(unix))]
312 {
313 warn(!file.metadata()?.permissions().readonly(), "readonly");
314 }
315 let mut buf = Vec::new();
316 file.read_to_end(&mut buf).and_then(|_read_size| {
317 secio::SecioKeyPair::secp256k1_raw_key(&buf)
318 .map(Some)
319 .map_err(|_| Error::new(ErrorKind::InvalidData, "invalid secret key data"))
320 })
321}
322
323impl Config {
324 pub fn secret_key_path(&self) -> PathBuf {
326 let mut path = self.path.clone();
327 path.push("secret_key");
328 path
329 }
330
331 pub fn onion_private_key_path(&self) -> PathBuf {
333 let mut path = self.path.clone();
334 path.push("onion_private_key");
335 path
336 }
337
338 pub fn peer_store_path(&self) -> PathBuf {
340 let mut path = self.path.clone();
341 path.push("peer_store");
342 path
343 }
344
345 pub fn create_dir_if_not_exists(&self) -> Result<(), Error> {
347 if !self.path.exists() {
348 fs::create_dir(&self.path)
349 } else {
350 Ok(())
351 }
352 }
353
354 pub fn max_inbound_peers(&self) -> u32 {
356 self.max_peers.saturating_sub(self.max_outbound_peers)
357 }
358
359 pub fn max_outbound_peers(&self) -> u32 {
361 self.max_outbound_peers
362 }
363
364 pub fn max_send_buffer(&self) -> usize {
366 self.max_send_buffer.unwrap_or(DEFAULT_SEND_BUFFER)
367 }
368
369 pub fn channel_size(&self) -> usize {
371 self.channel_size.unwrap_or(DEFAULT_CHANNEL_SIZE)
372 }
373
374 #[cfg(not(target_family = "wasm"))]
378 fn read_secret_key(&self) -> Result<Option<secio::SecioKeyPair>, Error> {
379 let path = self.secret_key_path();
380 read_secret_key(path)
381 }
382
383 #[cfg(not(target_family = "wasm"))]
385 fn write_secret_key_to_file(&self) -> Result<(), Error> {
386 let path = self.secret_key_path();
387 let random_key_pair = generate_random_key();
388 write_secret_to_file(&random_key_pair, path)
389 }
390
391 #[cfg(not(target_family = "wasm"))]
393 pub fn fetch_private_key(&self) -> Result<secio::SecioKeyPair, Error> {
394 match self.read_secret_key()? {
395 Some(key) => Ok(key),
396 None => {
397 self.write_secret_key_to_file()?;
398 Ok(self.read_secret_key()?.expect("key must exists"))
399 }
400 }
401 }
402
403 #[cfg(target_family = "wasm")]
404 pub fn fetch_private_key(&self) -> Result<secio::SecioKeyPair, Error> {
405 if self.secret_key == [0; 32] {
406 return Err(Error::new(
407 ErrorKind::InvalidData,
408 "invalid secret key data",
409 ));
410 } else {
411 secio::SecioKeyPair::secp256k1_raw_key(&self.secret_key)
412 .map_err(|_| Error::new(ErrorKind::InvalidData, "invalid secret key data"))
413 }
414 }
415
416 pub fn whitelist_peers(&self) -> Vec<Multiaddr> {
418 self.whitelist_peers.clone()
419 }
420
421 pub fn bootnodes(&self) -> Vec<Multiaddr> {
423 self.bootnodes.clone()
424 }
425
426 pub fn outbound_peer_service_enabled(&self) -> bool {
428 self.connect_outbound_interval_secs > 0
429 }
430
431 pub fn dns_seeding_service_enabled(&self) -> bool {
433 !self.dns_seeds.is_empty()
434 }
435}
436
437const fn default_reuse() -> bool {
440 true
441}
442
443const fn default_reuse_tcp_with_ws() -> bool {
445 true
446}