mirror of
https://github.com/Cuprate/cuprate.git
synced 2025-04-22 22:08:13 +00:00
cuprated: auto config docs (#418)
* auto config docs * fmt & change arg * fix clippy * add comment_out functionality * remove config files + gen in mdbook build * review fixes * Update books/user/src/config.md Co-authored-by: hinto-janai <hinto.janai@protonmail.com> --------- Co-authored-by: hinto-janai <hinto.janai@protonmail.com>
This commit is contained in:
parent
57cd96ed6c
commit
03363e393d
22 changed files with 444 additions and 242 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@ target/
|
|||
monerod
|
||||
books/*/book
|
||||
fast_sync_hashes.bin
|
||||
/books/user/Cuprated.toml
|
||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1118,6 +1118,7 @@ dependencies = [
|
|||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"toml",
|
||||
"toml_edit",
|
||||
"tower 0.5.1",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
|
|
|
@ -140,6 +140,7 @@ tokio-stream = { version = "0.1", default-features = false }
|
|||
tokio = { version = "1", default-features = false }
|
||||
tower = { git = "https://github.com/Cuprate/tower.git", rev = "6c7faf0", default-features = false } # <https://github.com/tower-rs/tower/pull/796>
|
||||
toml = { version = "0.8", default-features = false }
|
||||
toml_edit = { version = "0.22", default-features = false }
|
||||
tracing-appender = { version = "0.2", default-features = false }
|
||||
tracing-subscriber = { version = "0.3", default-features = false }
|
||||
tracing = { version = "0.1", default-features = false }
|
||||
|
|
|
@ -73,6 +73,7 @@ tokio-util = { workspace = true, features = ["rt"] }
|
|||
tokio-stream = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = { workspace = true, features = ["parse", "display"]}
|
||||
toml_edit = { workspace = true }
|
||||
tower = { workspace = true }
|
||||
tracing-appender = { workspace = true }
|
||||
tracing-subscriber = { workspace = true, features = ["std", "fmt", "default"] }
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
# ____ _
|
||||
# / ___| _ _ __ _ __ __ _| |_ ___
|
||||
# | | | | | | '_ \| '__/ _` | __/ _ \
|
||||
# | |__| |_| | |_) | | | (_| | || __/
|
||||
# \____\__,_| .__/|_| \__,_|\__\___|
|
||||
# |_|
|
||||
#
|
||||
|
||||
## The network to run on, valid values: "Mainnet", "Testnet", "Stagenet".
|
||||
network = "Mainnet"
|
||||
|
||||
## Tracing config.
|
||||
[tracing]
|
||||
## The stdout logging config.
|
||||
stdout = { level = "info" }
|
||||
## The file output logging config.
|
||||
file = { level = "debug", max_log_files = 7 }
|
||||
|
||||
## Clear-net config.
|
||||
[p2p.clear_net]
|
||||
## The number of outbound connections we should make and maintain.
|
||||
outbound_connections = 64
|
||||
## The number of extra connections we should make under load from the rest of Cuprate, i.e. when syncing.
|
||||
extra_outbound_connections = 8
|
||||
## The maximum number of incoming we should allow.
|
||||
max_inbound_connections = 128
|
||||
## The percent of outbound connections that should be to nodes we have not connected to before.
|
||||
gray_peers_percent = 0.7
|
||||
## The port to accept connections on, if left `0` no connections will be accepted.
|
||||
p2p_port = 0
|
||||
## The IP address to listen to connections on.
|
||||
listen_on = "0.0.0.0"
|
||||
|
||||
## The Clear-net addressbook config.
|
||||
[p2p.clear_net.address_book_config]
|
||||
## The size of the white peer list, which contains peers we have made a connection to before.
|
||||
max_white_list_length = 1_000
|
||||
## The size of the gray peer list, which contains peers we have not made a connection to before.
|
||||
max_gray_list_length = 5_000
|
||||
## The amount of time between address book saves.
|
||||
peer_save_period = { secs = 90, nanos = 0 }
|
||||
|
||||
## The block downloader config.
|
||||
[p2p.block_downloader]
|
||||
## The size of the buffer of sequential blocks waiting to be verified and added to the chain (bytes).
|
||||
buffer_bytes = 1_000_000_000
|
||||
## The size of the queue of blocks which are waiting for a parent block to be downloaded (bytes).
|
||||
in_progress_queue_bytes = 500_000_000
|
||||
## The target size of a batch of blocks (bytes), must not exceed 100MB.
|
||||
target_batch_bytes = 10_000_000
|
||||
## The amount of time between checking the pool of connected peers for free peers to download blocks.
|
||||
check_client_pool_interval = { secs = 30, nanos = 0 }
|
||||
|
||||
## Txpool storage config.
|
||||
[storage.txpool]
|
||||
## The database sync mode for the txpool.
|
||||
sync_mode = "Fast"
|
||||
## The maximum size of all the txs in the pool (bytes).
|
||||
max_txpool_byte_size = 100_000_000
|
||||
|
||||
## Blockchain storage config.
|
||||
[storage.blockchain]
|
||||
## The database sync mode for the blockchain.
|
||||
sync_mode = "Fast"
|
|
@ -1 +0,0 @@
|
|||
0.0.1.toml
|
|
@ -1,6 +0,0 @@
|
|||
# `cuprated` configs
|
||||
This directory holds configuration files for all `cuprated` versions.
|
||||
|
||||
For example, `0.0.1.toml` is the config file for `cuprated v0.0.1`.
|
||||
|
||||
`Cuprated.toml` is a symlink to the latest config file.
|
|
@ -3,6 +3,7 @@ use std::{
|
|||
fs::{read_to_string, File},
|
||||
io,
|
||||
path::Path,
|
||||
str::FromStr,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
|
@ -30,6 +31,9 @@ mod storage;
|
|||
mod tokio;
|
||||
mod tracing_config;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
use fs::FileSystemConfig;
|
||||
use p2p::P2PConfig;
|
||||
use rayon::RayonConfig;
|
||||
|
@ -37,6 +41,19 @@ use storage::StorageConfig;
|
|||
use tokio::TokioConfig;
|
||||
use tracing_config::TracingConfig;
|
||||
|
||||
/// Header to put at the start of the generated config file.
|
||||
const HEADER: &str = r"## ____ _
|
||||
## / ___| _ _ __ _ __ __ _| |_ ___
|
||||
## | | | | | | '_ \| '__/ _` | __/ _ \
|
||||
## | |__| |_| | |_) | | | (_| | || __/
|
||||
## \____\__,_| .__/|_| \__,_|\__\___|
|
||||
## |_|
|
||||
##
|
||||
## All these config values can be set to their default by commenting them out with #.
|
||||
## Some values are already commented out, to set the value remove the # at the start of the line.
|
||||
|
||||
";
|
||||
|
||||
/// Reads the args & config file, returning a [`Config`].
|
||||
pub fn read_config_and_args() -> Config {
|
||||
let args = args::Args::parse();
|
||||
|
@ -76,32 +93,76 @@ pub fn read_config_and_args() -> Config {
|
|||
args.apply_args(config)
|
||||
}
|
||||
|
||||
/// The config for all of Cuprate.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct Config {
|
||||
/// The network we should run on.
|
||||
network: Network,
|
||||
config_struct! {
|
||||
/// The config for all of Cuprate.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct Config {
|
||||
/// The network we should run on.
|
||||
///
|
||||
/// Valid values: ["Mainnet", "Testnet" and "Stagenet"]
|
||||
pub network: Network,
|
||||
|
||||
pub no_fast_sync: bool,
|
||||
/// Enable/disable fast sync.
|
||||
///
|
||||
/// Fast sync skips verification of old blocks by comparing block hashes to a built-in hash file,
|
||||
/// disabling this will significantly increase sync time. New blocks are still fully validated.
|
||||
pub fast_sync: bool,
|
||||
|
||||
/// [`tracing`] config.
|
||||
pub tracing: TracingConfig,
|
||||
#[child = true]
|
||||
/// The tracing/log output config.
|
||||
pub tracing: TracingConfig,
|
||||
|
||||
pub tokio: TokioConfig,
|
||||
#[child = true]
|
||||
/// The tokio config.
|
||||
///
|
||||
/// Tokio is the async threadpool, used for network operations and the major service inside `cuprated`.
|
||||
|
||||
pub rayon: RayonConfig,
|
||||
pub tokio: TokioConfig,
|
||||
#[child = true]
|
||||
/// The rayon config.
|
||||
///
|
||||
/// Rayon is the CPU threadpool, used for CPU intensive tasks.
|
||||
pub rayon: RayonConfig,
|
||||
|
||||
/// The P2P network config.
|
||||
p2p: P2PConfig,
|
||||
#[child = true]
|
||||
/// The P2P network config.
|
||||
pub p2p: P2PConfig,
|
||||
|
||||
/// The storage config.
|
||||
pub storage: StorageConfig,
|
||||
#[child = true]
|
||||
/// The storage config.
|
||||
pub storage: StorageConfig,
|
||||
|
||||
pub fs: FileSystemConfig,
|
||||
#[child = true]
|
||||
/// The filesystem config.
|
||||
pub fs: FileSystemConfig,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
network: Default::default(),
|
||||
fast_sync: true,
|
||||
tracing: Default::default(),
|
||||
tokio: Default::default(),
|
||||
rayon: Default::default(),
|
||||
p2p: Default::default(),
|
||||
storage: Default::default(),
|
||||
fs: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Returns a default [`Config`], with doc comments.
|
||||
pub fn documented_config() -> String {
|
||||
let str = toml::ser::to_string_pretty(&Self::default()).unwrap();
|
||||
let mut doc = toml_edit::DocumentMut::from_str(&str).unwrap();
|
||||
Self::write_docs(doc.as_table_mut());
|
||||
format!("{HEADER}{doc}")
|
||||
}
|
||||
|
||||
/// Attempts to read a config file in [`toml`] format from the given [`Path`].
|
||||
///
|
||||
/// # Errors
|
||||
|
@ -193,30 +254,13 @@ impl Config {
|
|||
mod test {
|
||||
use toml::from_str;
|
||||
|
||||
use crate::constants::EXAMPLE_CONFIG;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Tests the latest config is the `Default`.
|
||||
#[test]
|
||||
fn config_latest() {
|
||||
let config: Config = from_str(EXAMPLE_CONFIG).unwrap();
|
||||
assert_eq!(config, Config::default());
|
||||
}
|
||||
fn documented_config() {
|
||||
let str = Config::documented_config();
|
||||
let conf: Config = from_str(&str).unwrap();
|
||||
|
||||
/// Tests backwards compatibility.
|
||||
#[test]
|
||||
fn config_backwards_compat() {
|
||||
// (De)serialization tests.
|
||||
#[expect(
|
||||
clippy::single_element_loop,
|
||||
reason = "Remove after adding other versions"
|
||||
)]
|
||||
for version in ["0.0.1"] {
|
||||
let path = format!("config/{version}.toml");
|
||||
println!("Testing config serde backwards compat: {path}");
|
||||
let string = read_to_string(path).unwrap();
|
||||
from_str::<Config>(&string).unwrap();
|
||||
}
|
||||
assert_eq!(conf, Config::default());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use serde_json::Value;
|
|||
|
||||
use cuprate_helper::network::Network;
|
||||
|
||||
use crate::{config::Config, constants::EXAMPLE_CONFIG, version::CupratedVersionInfo};
|
||||
use crate::{config::Config, version::CupratedVersionInfo};
|
||||
|
||||
/// Cuprate Args.
|
||||
#[derive(clap::Parser, Debug)]
|
||||
|
@ -61,7 +61,7 @@ impl Args {
|
|||
}
|
||||
|
||||
if self.generate_config {
|
||||
println!("{EXAMPLE_CONFIG}");
|
||||
println!("{}", Config::documented_config());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ impl Args {
|
|||
/// This may exit the program if a config value was set that requires an early exit.
|
||||
pub const fn apply_args(&self, mut config: Config) -> Config {
|
||||
config.network = self.network;
|
||||
config.no_fast_sync = config.no_fast_sync || self.no_fast_sync;
|
||||
config.fast_sync = config.fast_sync && !self.no_fast_sync;
|
||||
|
||||
if let Some(outbound_connections) = self.outbound_connections {
|
||||
config.p2p.clear_net.general.outbound_connections = outbound_connections;
|
||||
|
|
|
@ -4,11 +4,21 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use cuprate_helper::fs::{CUPRATE_CACHE_DIR, CUPRATE_DATA_DIR};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct FileSystemConfig {
|
||||
pub data_directory: PathBuf,
|
||||
pub cache_directory: PathBuf,
|
||||
use super::macros::config_struct;
|
||||
|
||||
config_struct! {
|
||||
/// The file system config.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct FileSystemConfig {
|
||||
#[comment_out = true]
|
||||
/// The data directory.
|
||||
pub data_directory: PathBuf,
|
||||
|
||||
#[comment_out = true]
|
||||
/// The cache directory.
|
||||
pub cache_directory: PathBuf,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FileSystemConfig {
|
||||
|
|
86
binaries/cuprated/src/config/macros.rs
Normal file
86
binaries/cuprated/src/config/macros.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use toml_edit::TableLike;
|
||||
|
||||
/// A macro for config structs defined in `cuprated`. This macro generates a function that
|
||||
/// can insert toml comments created from doc comments on fields.
|
||||
///
|
||||
/// # Attributes
|
||||
/// - `#[flatten = true]`: lets the writer know that the field is flattened into the parent struct.
|
||||
/// - `#[child = true]`: writes the doc comments for all fields in the child struct.
|
||||
/// - `#[inline = true]`: inlines the struct into `{}` instead of having a separate `[]` header.
|
||||
/// - `#[comment_out = true]`: comments out the field.
|
||||
macro_rules! config_struct {
|
||||
(
|
||||
$(#[$meta:meta])*
|
||||
pub struct $name:ident {
|
||||
$(
|
||||
$(#[flatten = $flat:literal])?
|
||||
$(#[child = $child:literal])?
|
||||
$(#[inline = $inline:literal])?
|
||||
$(#[comment_out = $comment_out:literal])?
|
||||
$(#[doc = $doc:expr])*
|
||||
$(##[$field_meta:meta])*
|
||||
pub $field:ident: $field_ty:ty,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$(#[$meta])*
|
||||
pub struct $name {
|
||||
$(
|
||||
$(#[doc = $doc])*
|
||||
$(#[$field_meta])*
|
||||
pub $field: $field_ty,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[allow(unused_labels, clippy::allow_attributes)]
|
||||
pub fn write_docs(doc: &mut dyn ::toml_edit::TableLike) {
|
||||
$(
|
||||
|
||||
'write_field: {
|
||||
let key_str = &stringify!($field);
|
||||
|
||||
let mut field_prefix = [ $(
|
||||
format!("##{}\n", $doc),
|
||||
)*].concat();
|
||||
|
||||
$(
|
||||
if $comment_out {
|
||||
field_prefix.push('#');
|
||||
}
|
||||
)?
|
||||
|
||||
$(
|
||||
if $flat {
|
||||
<$field_ty>::write_docs(doc);
|
||||
break 'write_field;
|
||||
}
|
||||
)?
|
||||
|
||||
$(
|
||||
if $child {
|
||||
<$field_ty>::write_docs(doc.get_key_value_mut(&key_str).unwrap().1.as_table_like_mut().unwrap());
|
||||
}
|
||||
)?
|
||||
|
||||
if let Some(table) = doc.entry(&key_str).or_insert_with(|| panic!()).as_table_mut() {
|
||||
$(
|
||||
if $inline {
|
||||
let mut table = table.clone().into_inline_table();
|
||||
doc.insert(&key_str, ::toml_edit::Item::Value(::toml_edit::Value::InlineTable(table)));
|
||||
doc.key_mut(&key_str).unwrap().leaf_decor_mut().set_prefix(field_prefix);
|
||||
break 'write_field;
|
||||
}
|
||||
)?
|
||||
table.decor_mut().set_prefix(format!("\n{}", field_prefix));
|
||||
}else {
|
||||
doc.key_mut(&key_str).unwrap().leaf_decor_mut().set_prefix(field_prefix);
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use config_struct;
|
|
@ -8,28 +8,54 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use cuprate_helper::{fs::address_book_path, network::Network};
|
||||
|
||||
/// P2P config.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct P2PConfig {
|
||||
/// Clear-net config.
|
||||
pub clear_net: ClearNetConfig,
|
||||
/// Block downloader config.
|
||||
pub block_downloader: BlockDownloaderConfig,
|
||||
use super::macros::config_struct;
|
||||
|
||||
config_struct! {
|
||||
/// P2P config.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct P2PConfig {
|
||||
#[child = true]
|
||||
/// The clear-net P2P config.
|
||||
pub clear_net: ClearNetConfig,
|
||||
|
||||
#[child = true]
|
||||
/// Block downloader config.
|
||||
///
|
||||
/// The block downloader handles downloading old blocks from peers when we are behind.
|
||||
pub block_downloader: BlockDownloaderConfig,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct BlockDownloaderConfig {
|
||||
/// The size in bytes of the buffer between the block downloader and the place which
|
||||
/// is consuming the downloaded blocks.
|
||||
pub buffer_bytes: usize,
|
||||
/// The size of the in progress queue (in bytes) at which we stop requesting more blocks.
|
||||
pub in_progress_queue_bytes: usize,
|
||||
/// The [`Duration`] between checking the client pool for free peers.
|
||||
pub check_client_pool_interval: Duration,
|
||||
/// The target size of a single batch of blocks (in bytes).
|
||||
pub target_batch_bytes: usize,
|
||||
config_struct! {
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct BlockDownloaderConfig {
|
||||
#[comment_out = true]
|
||||
/// The size in bytes of the buffer between the block downloader and the place which
|
||||
/// is consuming the downloaded blocks (`cuprated`).
|
||||
///
|
||||
/// This value is an absolute maximum, once this is reached the block downloader will pause.
|
||||
pub buffer_bytes: usize,
|
||||
|
||||
#[comment_out = true]
|
||||
/// The size of the in progress queue (in bytes) at which we stop requesting more blocks.
|
||||
///
|
||||
/// The value is _NOT_ an absolute maximum, the in progress queue could get much larger. This value
|
||||
/// is only the value we stop requesting more blocks, if we still have requests in progress we will
|
||||
/// still accept the response and add the blocks to the queue.
|
||||
pub in_progress_queue_bytes: usize,
|
||||
|
||||
#[inline = true]
|
||||
/// The [`Duration`] between checking the client pool for free peers.
|
||||
pub check_client_pool_interval: Duration,
|
||||
|
||||
#[comment_out = true]
|
||||
/// The target size of a single batch of blocks (in bytes).
|
||||
///
|
||||
/// This value must be below 100_000_000, it is not recommended to set it above 30_000_000.
|
||||
pub target_batch_bytes: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BlockDownloaderConfig> for cuprate_p2p::block_downloader::BlockDownloaderConfig {
|
||||
|
@ -50,19 +76,24 @@ impl Default for BlockDownloaderConfig {
|
|||
buffer_bytes: 1_000_000_000,
|
||||
in_progress_queue_bytes: 500_000_000,
|
||||
check_client_pool_interval: Duration::from_secs(30),
|
||||
target_batch_bytes: 10_000_000,
|
||||
target_batch_bytes: 15_000_000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The config values for P2P clear-net.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct ClearNetConfig {
|
||||
/// The server config.
|
||||
pub listen_on: IpAddr,
|
||||
#[serde(flatten)]
|
||||
pub general: SharedNetConfig,
|
||||
config_struct! {
|
||||
/// The config values for P2P clear-net.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct ClearNetConfig {
|
||||
/// The IP address we should bind to to listen to connections on.
|
||||
pub listen_on: IpAddr,
|
||||
|
||||
#[flatten = true]
|
||||
/// Shared config values.
|
||||
##[serde(flatten)]
|
||||
pub general: SharedNetConfig,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ClearNetConfig {
|
||||
|
@ -74,26 +105,42 @@ impl Default for ClearNetConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// Network config values shared between all network zones.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct SharedNetConfig {
|
||||
/// The number of outbound connections to make and try keep.
|
||||
pub outbound_connections: usize,
|
||||
/// The amount of extra connections we can make if we are under load from the rest of Cuprate.
|
||||
pub extra_outbound_connections: usize,
|
||||
/// The maximum amount of inbound connections
|
||||
pub max_inbound_connections: usize,
|
||||
/// The percent of connections that should be to peers we haven't connected to before.
|
||||
pub gray_peers_percent: f64,
|
||||
/// port to use to accept p2p connections.
|
||||
pub p2p_port: u16,
|
||||
/// The address book config.
|
||||
address_book_config: AddressBookConfig,
|
||||
config_struct! {
|
||||
/// Network config values shared between all network zones.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct SharedNetConfig {
|
||||
#[comment_out = true]
|
||||
/// The number of outbound connections to make and try keep.
|
||||
///
|
||||
/// Recommended to keep this value above 12.
|
||||
pub outbound_connections: usize,
|
||||
|
||||
#[comment_out = true]
|
||||
/// The amount of extra connections we can make if we are under load from the rest of Cuprate.
|
||||
pub extra_outbound_connections: usize,
|
||||
|
||||
#[comment_out = true]
|
||||
/// The maximum amount of inbound connections we should allow.
|
||||
pub max_inbound_connections: usize,
|
||||
|
||||
#[comment_out = true]
|
||||
/// The percent of connections that should be to peers we haven't connected to before.
|
||||
pub gray_peers_percent: f64,
|
||||
|
||||
/// port to use to accept p2p connections.
|
||||
///
|
||||
/// Set to 0 if you do not want to accept P2P connections.
|
||||
pub p2p_port: u16,
|
||||
|
||||
#[child = true]
|
||||
/// The address book config.
|
||||
pub address_book_config: AddressBookConfig,
|
||||
}
|
||||
}
|
||||
|
||||
impl SharedNetConfig {
|
||||
/// Returns the [`AddressBookConfig`].
|
||||
/// Returns the [`cuprate_address_book::AddressBookConfig`].
|
||||
pub fn address_book_config(
|
||||
&self,
|
||||
cache_dir: &Path,
|
||||
|
@ -111,22 +158,35 @@ impl SharedNetConfig {
|
|||
impl Default for SharedNetConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
outbound_connections: 64,
|
||||
outbound_connections: 32,
|
||||
extra_outbound_connections: 8,
|
||||
max_inbound_connections: 128,
|
||||
gray_peers_percent: 0.7,
|
||||
p2p_port: 0,
|
||||
p2p_port: 18080,
|
||||
address_book_config: AddressBookConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct AddressBookConfig {
|
||||
max_white_list_length: usize,
|
||||
max_gray_list_length: usize,
|
||||
peer_save_period: Duration,
|
||||
config_struct! {
|
||||
/// The addressbook config exposed to users.
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct AddressBookConfig {
|
||||
/// The size of the white peer list.
|
||||
///
|
||||
/// The white list holds peers we have connected to before.
|
||||
pub max_white_list_length: usize,
|
||||
|
||||
/// The size of the gray peer list.
|
||||
///
|
||||
/// The gray peer list holds peers we have been told about but not connected to ourself.
|
||||
pub max_gray_list_length: usize,
|
||||
|
||||
#[inline = true]
|
||||
/// The time period between address book saves.
|
||||
pub peer_save_period: Duration,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AddressBookConfig {
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The [`rayon`] config.
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct RayonConfig {
|
||||
/// The number of threads to use for the [`rayon::ThreadPool`].
|
||||
pub threads: usize,
|
||||
use super::macros::config_struct;
|
||||
|
||||
config_struct! {
|
||||
/// The [`rayon`] config.
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct RayonConfig {
|
||||
#[comment_out = true]
|
||||
/// The number of threads to use for the rayon thread pool.
|
||||
pub threads: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RayonConfig {
|
||||
|
|
|
@ -6,16 +6,27 @@ use cuprate_database::config::SyncMode;
|
|||
use cuprate_database_service::ReaderThreads;
|
||||
use cuprate_helper::fs::CUPRATE_DATA_DIR;
|
||||
|
||||
/// The storage config.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct StorageConfig {
|
||||
/// The amount of reader threads to spawn between the tx-pool and blockchain.
|
||||
pub reader_threads: usize,
|
||||
/// The tx-pool config.
|
||||
pub txpool: TxpoolConfig,
|
||||
/// The blockchain config.
|
||||
pub blockchain: BlockchainConfig,
|
||||
use super::macros::config_struct;
|
||||
|
||||
config_struct! {
|
||||
/// The storage config.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct StorageConfig {
|
||||
#[comment_out = true]
|
||||
/// The amount of reader threads to spawn for the tx-pool and blockchain.
|
||||
///
|
||||
/// The tx-pool and blockchain both share a single threadpool.
|
||||
pub reader_threads: usize,
|
||||
|
||||
#[child = true]
|
||||
/// The tx-pool config.
|
||||
pub txpool: TxpoolConfig,
|
||||
|
||||
#[child = true]
|
||||
/// The blockchain config.
|
||||
pub blockchain: BlockchainConfig,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StorageConfig {
|
||||
|
@ -28,23 +39,31 @@ impl Default for StorageConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// The blockchain config.
|
||||
#[derive(Default, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct BlockchainConfig {
|
||||
#[serde(flatten)]
|
||||
pub shared: SharedStorageConfig,
|
||||
config_struct! {
|
||||
/// The blockchain config.
|
||||
#[derive(Default, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct BlockchainConfig {
|
||||
#[flatten = true]
|
||||
/// Shared config.
|
||||
##[serde(flatten)]
|
||||
pub shared: SharedStorageConfig,
|
||||
}
|
||||
}
|
||||
|
||||
/// The tx-pool config.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct TxpoolConfig {
|
||||
#[serde(flatten)]
|
||||
pub shared: SharedStorageConfig,
|
||||
config_struct! {
|
||||
/// The tx-pool config.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct TxpoolConfig {
|
||||
#[flatten = true]
|
||||
/// Shared config.
|
||||
##[serde(flatten)]
|
||||
pub shared: SharedStorageConfig,
|
||||
|
||||
/// The maximum size of the tx-pool.
|
||||
pub max_txpool_byte_size: usize,
|
||||
/// The maximum size of the tx-pool.
|
||||
pub max_txpool_byte_size: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TxpoolConfig {
|
||||
|
@ -56,10 +75,18 @@ impl Default for TxpoolConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// Config values shared between the tx-pool and blockchain.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct SharedStorageConfig {
|
||||
/// The [`SyncMode`] of the database.
|
||||
pub sync_mode: SyncMode,
|
||||
config_struct! {
|
||||
/// Config values shared between the tx-pool and blockchain.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct SharedStorageConfig {
|
||||
#[comment_out = true]
|
||||
/// The sync mode of the database.
|
||||
///
|
||||
/// Changing this value could make the DB a lot slower when writing data, although
|
||||
/// using "Safe" makes the DB more durable if there was an unexpected crash.
|
||||
///
|
||||
/// Valid values: ["Fast", "Safe"].
|
||||
pub sync_mode: SyncMode,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// [`tokio`] config.
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct TokioConfig {
|
||||
/// The amount of threads to spawn for the async thread-pool
|
||||
pub threads: usize,
|
||||
use super::macros::config_struct;
|
||||
|
||||
config_struct! {
|
||||
/// [`tokio`] config.
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct TokioConfig {
|
||||
#[comment_out = true]
|
||||
/// The amount of threads to spawn for the async thread-pool
|
||||
pub threads: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TokioConfig {
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tracing::level_filters::LevelFilter;
|
||||
|
||||
/// [`tracing`] config.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct TracingConfig {
|
||||
pub stdout: StdoutTracingConfig,
|
||||
pub file: FileTracingConfig,
|
||||
use super::macros::config_struct;
|
||||
|
||||
config_struct! {
|
||||
/// [`tracing`] config.
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct TracingConfig {
|
||||
#[child = true]
|
||||
/// The stdout logging config.
|
||||
pub stdout: StdoutTracingConfig,
|
||||
|
||||
#[child = true]
|
||||
/// The file logging config.
|
||||
pub file: FileTracingConfig,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct StdoutTracingConfig {
|
||||
/// The default minimum log level.
|
||||
#[serde(with = "level_filter_serde")]
|
||||
pub level: LevelFilter,
|
||||
config_struct! {
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct StdoutTracingConfig {
|
||||
/// The default minimum log level.
|
||||
##[serde(with = "level_filter_serde")]
|
||||
pub level: LevelFilter,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StdoutTracingConfig {
|
||||
|
@ -25,15 +36,18 @@ impl Default for StdoutTracingConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct FileTracingConfig {
|
||||
/// The default minimum log level.
|
||||
#[serde(with = "level_filter_serde")]
|
||||
pub level: LevelFilter,
|
||||
/// The maximum amount of log files to keep, once this number is passed the oldest file
|
||||
/// will be deleted.
|
||||
pub max_log_files: usize,
|
||||
config_struct! {
|
||||
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct FileTracingConfig {
|
||||
/// The default minimum log level.
|
||||
##[serde(with = "level_filter_serde")]
|
||||
pub level: LevelFilter,
|
||||
|
||||
/// The maximum amount of log files to keep, once this number is passed the oldest file
|
||||
/// will be deleted.
|
||||
pub max_log_files: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FileTracingConfig {
|
||||
|
|
|
@ -34,8 +34,6 @@ pub const DEFAULT_CONFIG_WARNING: &str = formatcp!(
|
|||
|
||||
pub const DEFAULT_CONFIG_STARTUP_DELAY: Duration = Duration::from_secs(15);
|
||||
|
||||
pub const EXAMPLE_CONFIG: &str = include_str!("../config/Cuprated.toml");
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -55,7 +55,7 @@ fn main() {
|
|||
|
||||
let config = config::read_config_and_args();
|
||||
|
||||
blockchain::set_fast_sync_hashes(!config.no_fast_sync, config.network());
|
||||
blockchain::set_fast_sync_hashes(config.fast_sync, config.network());
|
||||
|
||||
// Initialize logging.
|
||||
logging::init_logging(&config);
|
||||
|
|
|
@ -21,17 +21,16 @@ cargo install mdbook
|
|||
|
||||
## Building
|
||||
|
||||
To build a book, go into a book's directory and build:
|
||||
To build a book, from the root of Cuprate:
|
||||
|
||||
```bash
|
||||
# This build Cuprate's user book.
|
||||
cd user/
|
||||
mdbook build
|
||||
mdbook build ./books/user
|
||||
```
|
||||
|
||||
The output will be in the `book` subdirectory (`user/book` for the above example). To open the book, you can open it in
|
||||
your web browser like so:
|
||||
|
||||
```bash
|
||||
mdbook build --open
|
||||
mdbook build ./books/user --open
|
||||
```
|
||||
|
|
|
@ -10,3 +10,6 @@ git-repository-url = "https://github.com/Cuprate/cuprate/books/user"
|
|||
default-theme = "ayu"
|
||||
preferred-dark-theme = "ayu"
|
||||
no-section-label = true
|
||||
|
||||
[preprocessor.gen_config]
|
||||
command = "bash ./books/user/gen_config.sh"
|
||||
|
|
16
books/user/gen_config.sh
Normal file
16
books/user/gen_config.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
# https://rust-lang.github.io/mdBook/for_developers/preprocessors.html
|
||||
|
||||
# This script is called twice, the first is just to check support.
|
||||
if [ "$1" == "supports" ]; then
|
||||
# return 0 - we support everything.
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
# Second call - generate config.
|
||||
cargo run --bin cuprated -- --generate-config > ./books/user/Cuprated.toml
|
||||
|
||||
# This looks weird but mdbook hands us 2 JSON maps, we need to return the second with any edits we want to make.
|
||||
# We don't want to make any edits, so we can just read & return the second JSON map straight away.
|
||||
jq '.[1]'
|
|
@ -7,10 +7,12 @@
|
|||
- [OS specific directory](./resources/disk.md)
|
||||
|
||||
## `Cuprated.toml`
|
||||
This is the default configuration file `cuprated` creates and uses, sourced from [here](https://github.com/Cuprate/cuprate/blob/main/binaries/cuprated/config/Cuprated.toml).
|
||||
This is the default configuration file `cuprated` creates and uses.
|
||||
|
||||
If `cuprated` is started with no [`--options`](./cli.md), then the configuration used will be equivalent to this config file.
|
||||
|
||||
> Some values may be different for your exact system, generate the config with `cuprated --generate-config` to see the defaults for your system.
|
||||
|
||||
```toml
|
||||
{{#include ../../../binaries/cuprated/config/Cuprated.toml}}
|
||||
{{#include ../Cuprated.toml}}
|
||||
```
|
||||
|
|
Loading…
Reference in a new issue