|
1 | 1 | //! cuprated config
|
| 2 | +use std::{ |
| 3 | + fs::{read_to_string, File}, |
| 4 | + io, |
| 5 | + path::Path, |
| 6 | + time::Duration, |
| 7 | +}; |
| 8 | + |
| 9 | +use clap::Parser; |
| 10 | +use serde::{Deserialize, Serialize}; |
2 | 11 |
|
3 | 12 | use cuprate_consensus::ContextConfig;
|
4 |
| -use cuprate_helper::network::Network; |
| 13 | +use cuprate_helper::{fs::CUPRATE_CONFIG_DIR, network::Network}; |
5 | 14 | use cuprate_p2p::block_downloader::BlockDownloaderConfig;
|
6 | 15 | use cuprate_p2p_core::ClearNet;
|
7 |
| -use serde::{Deserialize, Serialize}; |
8 |
| -use std::time::Duration; |
9 | 16 |
|
| 17 | +mod args; |
| 18 | +mod default; |
10 | 19 | mod p2p;
|
11 | 20 | mod storage;
|
| 21 | +mod tracing_config; |
12 | 22 |
|
13 | 23 | use p2p::P2PConfig;
|
14 | 24 | use storage::StorageConfig;
|
| 25 | +use tracing_config::TracingConfig; |
| 26 | + |
| 27 | +/// The default name of Cuprate's config file. |
| 28 | +const DEFAULT_CONFIG_FILE_NAME: &str = "Cuprate.toml"; |
| 29 | + |
| 30 | +/// Reads the args & config file, returning a [`Config`]. |
| 31 | +pub fn read_config_and_args() -> Config { |
| 32 | + let args = args::Args::parse(); |
| 33 | + |
| 34 | + let config: Config = if let Some(config_file) = &args.config_file { |
| 35 | + // If a config file was set in the args try read it and exit if we can't. |
| 36 | + match Config::read_from_file(config_file) { |
| 37 | + Ok(config) => config, |
| 38 | + Err(e) => { |
| 39 | + tracing::error!("Failed to read config from file: {}", e); |
| 40 | + std::process::exit(1); |
| 41 | + } |
| 42 | + } |
| 43 | + } else { |
| 44 | + // First attempt to read the config file from the current directory. |
| 45 | + std::env::current_dir() |
| 46 | + .map_err(Into::into) |
| 47 | + .and_then(Config::read_from_file) |
| 48 | + .inspect_err(|e| tracing::debug!("Failed to read config from current dir: {e}")) |
| 49 | + // otherwise try the main config directory. |
| 50 | + .or_else(|_| { |
| 51 | + let file = CUPRATE_CONFIG_DIR.join(DEFAULT_CONFIG_FILE_NAME); |
| 52 | + Config::read_from_file(file) |
| 53 | + }) |
| 54 | + .inspect_err(|e| { |
| 55 | + tracing::debug!("Failed to read config from config dir: {e}"); |
| 56 | + tracing::warn!("Failed to find/read config file, using default config."); |
| 57 | + }) |
| 58 | + .unwrap_or_default() |
| 59 | + }; |
15 | 60 |
|
16 |
| -pub fn config() -> Config { |
17 |
| - Config::default() |
| 61 | + args.apply_args(config) |
18 | 62 | }
|
19 | 63 |
|
| 64 | +/// The config for all of Cuprate. |
20 | 65 | #[derive(Default, Deserialize, Serialize)]
|
21 | 66 | #[serde(deny_unknown_fields, default)]
|
22 | 67 | pub struct Config {
|
| 68 | + /// The network we should run on. |
23 | 69 | network: Network,
|
24 | 70 |
|
| 71 | + /// [`tracing`] config. |
| 72 | + tracing: TracingConfig, |
| 73 | + |
| 74 | + /// The P2P network config. |
25 | 75 | p2p: P2PConfig,
|
26 | 76 |
|
| 77 | + /// The Storage config |
27 | 78 | storage: StorageConfig,
|
28 | 79 | }
|
29 | 80 |
|
30 | 81 | impl Config {
|
31 |
| - pub fn network(&self) -> Network { |
| 82 | + /// Attempts to read a config file in [`toml`] format from the given [`Path`. |
| 83 | + /// |
| 84 | + /// # Errors |
| 85 | + /// |
| 86 | + /// Will return an [`Err`] if the file cannot be read or if the file is not a valid [`toml`] config. |
| 87 | + fn read_from_file(file: impl AsRef<Path>) -> Result<Self, anyhow::Error> { |
| 88 | + let file_text = read_to_string(file.as_ref())?; |
| 89 | + |
| 90 | + Ok(toml::from_str(&file_text).inspect_err(|_| { |
| 91 | + tracing::warn!( |
| 92 | + "Failed to parse config file at: {}", |
| 93 | + file.as_ref().to_string_lossy() |
| 94 | + ); |
| 95 | + })?) |
| 96 | + } |
| 97 | + |
| 98 | + /// Returns the current [`Network`] we are running on. |
| 99 | + pub const fn network(&self) -> Network { |
32 | 100 | self.network
|
33 | 101 | }
|
34 | 102 |
|
| 103 | + /// The [`ClearNet`], [`cuprate_p2p::P2PConfig`]. |
35 | 104 | pub fn clearnet_p2p_config(&self) -> cuprate_p2p::P2PConfig<ClearNet> {
|
36 | 105 | cuprate_p2p::P2PConfig {
|
37 | 106 | network: self.network,
|
| 107 | + seeds: p2p::clear_net_seed_nodes(self.network), |
38 | 108 | outbound_connections: self.p2p.clear_net.general.outbound_connections,
|
39 | 109 | extra_outbound_connections: self.p2p.clear_net.general.extra_outbound_connections,
|
40 | 110 | max_inbound_connections: self.p2p.clear_net.general.max_inbound_connections,
|
41 | 111 | gray_peers_percent: self.p2p.clear_net.general.gray_peers_percent,
|
42 | 112 | server_config: Some(self.p2p.clear_net.server.clone()),
|
43 | 113 | p2p_port: self.p2p.clear_net.general.p2p_port,
|
| 114 | + // TODO: set this if a public RPC server is set. |
44 | 115 | rpc_port: 0,
|
45 | 116 | address_book_config: self.p2p.clear_net.general.address_book_config.clone(),
|
46 | 117 | }
|
47 | 118 | }
|
48 | 119 |
|
49 |
| - pub fn context_config(&self) -> ContextConfig { |
| 120 | + /// The [`ContextConfig`]. |
| 121 | + pub const fn context_config(&self) -> ContextConfig { |
50 | 122 | match self.network {
|
51 | 123 | Network::Mainnet => ContextConfig::main_net(),
|
52 | 124 | Network::Stagenet => ContextConfig::stage_net(),
|
53 | 125 | Network::Testnet => ContextConfig::test_net(),
|
54 | 126 | }
|
55 | 127 | }
|
56 | 128 |
|
| 129 | + /// The [`cuprate_blockchain`] config. |
57 | 130 | pub fn blockchain_config(&self) -> cuprate_blockchain::config::Config {
|
58 |
| - self.storage.blockchain.clone() |
| 131 | + let blockchain = &self.storage.blockchain; |
| 132 | + |
| 133 | + // We don't set reader threads as we manually make the reader threadpool. |
| 134 | + cuprate_blockchain::config::ConfigBuilder::default() |
| 135 | + .network(self.network) |
| 136 | + .db_directory(blockchain.shared.path.clone()) |
| 137 | + .sync_mode(blockchain.shared.sync_mode) |
| 138 | + .build() |
59 | 139 | }
|
60 | 140 |
|
61 |
| - pub fn block_downloader_config(&self) -> BlockDownloaderConfig { |
62 |
| - BlockDownloaderConfig { |
63 |
| - buffer_size: 50_000_000, |
64 |
| - in_progress_queue_size: 50_000_000, |
65 |
| - check_client_pool_interval: Duration::from_secs(30), |
66 |
| - target_batch_size: 5_000_000, |
67 |
| - initial_batch_size: 1, |
68 |
| - } |
| 141 | + /// The [`BlockDownloaderConfig`]. |
| 142 | + pub const fn block_downloader_config(&self) -> BlockDownloaderConfig { |
| 143 | + self.p2p.block_downloader |
69 | 144 | }
|
70 | 145 | }
|
0 commit comments