Skip to content

Commit 5906e7d

Browse files
committed
finish initial config.
1 parent 8d0c26c commit 5906e7d

File tree

21 files changed

+594
-58
lines changed

21 files changed

+594
-58
lines changed

Cargo.lock

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

binaries/cuprated/Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ cuprate-consensus = { path = "../../consensus" }
1313
cuprate-fast-sync = { path = "../../consensus/fast-sync" }
1414
cuprate-consensus-rules = { path = "../../consensus/rules" }
1515
cuprate-cryptonight = { path = "../../cryptonight" }
16-
cuprate-helper = { path = "../../helper" }
16+
cuprate-helper = { path = "../../helper", features = ["serde"] }
1717
cuprate-epee-encoding = { path = "../../net/epee-encoding" }
1818
cuprate-fixed-bytes = { path = "../../net/fixed-bytes" }
1919
cuprate-levin = { path = "../../net/levin" }
2020
cuprate-wire = { path = "../../net/wire" }
21-
cuprate-p2p = { path = "../../p2p/p2p" }
21+
cuprate-p2p = { path = "../../p2p/p2p", features = ["serde"] }
2222
cuprate-p2p-core = { path = "../../p2p/p2p-core", features = ["serde"] }
2323
cuprate-dandelion-tower = { path = "../../p2p/dandelion-tower" }
2424
cuprate-async-buffer = { path = "../../p2p/async-buffer" }
2525
cuprate-address-book = { path = "../../p2p/address-book", features = ["serde_config"] }
2626
cuprate-blockchain = { path = "../../storage/blockchain", features = ["service"] }
27-
cuprate-database-service = { path = "../../storage/service" }
27+
cuprate-database-service = { path = "../../storage/service", features = ["serde"] }
2828
cuprate-txpool = { path = "../../storage/txpool" }
29-
cuprate-database = { path = "../../storage/database" }
29+
cuprate-database = { path = "../../storage/database", features = ["serde"] }
3030
cuprate-pruning = { path = "../../pruning" }
3131
cuprate-test-utils = { path = "../../test-utils" }
3232
cuprate-types = { path = "../../types" }
@@ -71,7 +71,8 @@ tokio-stream = { workspace = true }
7171
tokio = { workspace = true }
7272
tower = { workspace = true }
7373
tracing-subscriber = { workspace = true, features = ["std", "fmt", "default"] }
74-
tracing = { workspace = true }
74+
tracing = { workspace = true, features = ["default"] }
75+
toml = "0.8"
7576

7677
[lints]
7778
workspace = true

binaries/cuprated/src/config.rs

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,145 @@
11
//! 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};
211

312
use cuprate_consensus::ContextConfig;
4-
use cuprate_helper::network::Network;
13+
use cuprate_helper::{fs::CUPRATE_CONFIG_DIR, network::Network};
514
use cuprate_p2p::block_downloader::BlockDownloaderConfig;
615
use cuprate_p2p_core::ClearNet;
7-
use serde::{Deserialize, Serialize};
8-
use std::time::Duration;
916

17+
mod args;
18+
mod default;
1019
mod p2p;
1120
mod storage;
21+
mod tracing_config;
1222

1323
use p2p::P2PConfig;
1424
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+
};
1560

16-
pub fn config() -> Config {
17-
Config::default()
61+
args.apply_args(config)
1862
}
1963

64+
/// The config for all of Cuprate.
2065
#[derive(Default, Deserialize, Serialize)]
2166
#[serde(deny_unknown_fields, default)]
2267
pub struct Config {
68+
/// The network we should run on.
2369
network: Network,
2470

71+
/// [`tracing`] config.
72+
tracing: TracingConfig,
73+
74+
/// The P2P network config.
2575
p2p: P2PConfig,
2676

77+
/// The Storage config
2778
storage: StorageConfig,
2879
}
2980

3081
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 {
32100
self.network
33101
}
34102

103+
/// The [`ClearNet`], [`cuprate_p2p::P2PConfig`].
35104
pub fn clearnet_p2p_config(&self) -> cuprate_p2p::P2PConfig<ClearNet> {
36105
cuprate_p2p::P2PConfig {
37106
network: self.network,
107+
seeds: p2p::clear_net_seed_nodes(self.network),
38108
outbound_connections: self.p2p.clear_net.general.outbound_connections,
39109
extra_outbound_connections: self.p2p.clear_net.general.extra_outbound_connections,
40110
max_inbound_connections: self.p2p.clear_net.general.max_inbound_connections,
41111
gray_peers_percent: self.p2p.clear_net.general.gray_peers_percent,
42112
server_config: Some(self.p2p.clear_net.server.clone()),
43113
p2p_port: self.p2p.clear_net.general.p2p_port,
114+
// TODO: set this if a public RPC server is set.
44115
rpc_port: 0,
45116
address_book_config: self.p2p.clear_net.general.address_book_config.clone(),
46117
}
47118
}
48119

49-
pub fn context_config(&self) -> ContextConfig {
120+
/// The [`ContextConfig`].
121+
pub const fn context_config(&self) -> ContextConfig {
50122
match self.network {
51123
Network::Mainnet => ContextConfig::main_net(),
52124
Network::Stagenet => ContextConfig::stage_net(),
53125
Network::Testnet => ContextConfig::test_net(),
54126
}
55127
}
56128

129+
/// The [`cuprate_blockchain`] config.
57130
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()
59139
}
60140

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
69144
}
70145
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# ____ _
2+
# / ___| _ _ __ _ __ __ _| |_ ___
3+
# | | | | | | '_ \| '__/ _` | __/ _ \
4+
# | |__| |_| | |_) | | | (_| | || __/
5+
# \____\__,_| .__/|_| \__,_|\__\___|
6+
# |_|
7+
#
8+
9+
## The network to run on, valid values: "Mainnet", "Testnet", "Stagenet".
10+
network = "Mainnet"
11+
12+
## Tracing config.
13+
[tracing]
14+
## The minimum level for log events to be displayed.
15+
level = "info"
16+
17+
## Clear-net config.
18+
[p2p.clear_net]
19+
## The number of outbound connections we should make and maintain.
20+
outbound_connections = 64
21+
## The number of extra connections we should make under load from the rest of Cuprate, i.e. when syncing.
22+
extra_outbound_connections = 8
23+
## The maximum number of incoming we should allow.
24+
max_inbound_connections = 128
25+
## The percent of outbound connections that should be to nodes we have not connected to before.
26+
gray_peers_percent = 0.7
27+
## The port to accept connections on, if left `0` no connections will be accepted.
28+
p2p_port = 0
29+
## The IP address to listen to connections on.
30+
server.ip = "0.0.0.0"
31+
32+
## The Clear-net addressbook config.
33+
[p2p.clear_net.address_book_config]
34+
## The size of the white peer list, which contains peers we have made a connection to before.
35+
max_white_list_length = 1_000
36+
## The size of the gray peer list, which contains peers we have not made a connection to before.
37+
max_gray_list_length = 5_000
38+
## The folder to store the address book.
39+
peer_store_folder = "{cache}"
40+
## The amount of time between address book saves.
41+
peer_save_period = {{ secs = 90, nanos = 0 }}
42+
43+
## The block downloader config.
44+
[p2p.block_downloader]
45+
## The size of the buffer of sequential blocks waiting to be verified and added to the chain (bytes).
46+
buffer_size = 50_000_000
47+
## The size of the queue of blocks which are waiting for a parent block to be downloaded (bytes).
48+
in_progress_queue_size = 50_000_000
49+
## The target size of a batch of blocks (bytes), must not exceed 100MB.
50+
target_batch_size = 5_000_000
51+
## The number of blocks in the first bacth (you probably shouldn't change this).
52+
initial_batch_len = 1
53+
## The amount of time between checking the pool of connected peers for free peers to download blocks.
54+
check_client_pool_interval = {{ secs = 30, nanos = 0 }}
55+
56+
## Storage config
57+
[storage]
58+
## The amount of reader threads to spawn.
59+
reader_threads = "OnePerThread"
60+
61+
## Txpool storage config.
62+
[storage.txpool]
63+
## The txpool storage location.
64+
path = "{txpool}"
65+
## The database sync mode for the txpool.
66+
sync_mode = "Async"
67+
## The maximum size of all the txs in the pool (bytes).
68+
max_txpool_size = 100_000_000
69+
70+
## Blockchain storage config.
71+
[storage.blockchain]
72+
## The blockchain storage location.
73+
path = "{blockchain}"
74+
## The database sync mode for the blockchain.
75+
sync_mode = "Async"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use std::{io::Write, path::PathBuf};
2+
3+
use clap::builder::TypedValueParser;
4+
5+
use cuprate_helper::network::Network;
6+
7+
use crate::config::{default::create_default_config_file, Config, DEFAULT_CONFIG_FILE_NAME};
8+
9+
#[derive(clap::Parser, Debug)]
10+
pub struct Args {
11+
/// The network we should run on.
12+
#[arg(
13+
long,
14+
default_value_t = Network::Mainnet,
15+
value_parser = clap::builder::PossibleValuesParser::new(["mainnet", "testnet", "stagenet"])
16+
.map(|s| s.parse::<Network>().unwrap()),
17+
)]
18+
pub network: Network,
19+
/// The amount of outbound clear-net connections to maintain.
20+
pub outbound_connections: Option<usize>,
21+
/// The location of the Cuprate config file.
22+
pub config_file: Option<PathBuf>,
23+
/// Generate a config file and place it in the given folder.
24+
pub generate_config: Option<PathBuf>,
25+
}
26+
27+
impl Args {
28+
/// Apply the [`Args`] to the given [`Config`].
29+
///
30+
/// This may exit the program if a config value was set that requires an early exit.
31+
pub fn apply_args(&self, mut config: Config) -> Config {
32+
if let Some(config_folder) = self.generate_config.as_ref() {
33+
// This will create the config file and exit.
34+
create_default_config_file(config_folder)
35+
};
36+
37+
config.network = self.network;
38+
39+
if let Some(outbound_connections) = self.outbound_connections {
40+
config.p2p.clear_net.general.outbound_connections = outbound_connections;
41+
}
42+
43+
config
44+
}
45+
}

0 commit comments

Comments
 (0)