diff --git a/Cargo.lock b/Cargo.lock index 755271705..f78a6f832 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2036,6 +2036,7 @@ dependencies = [ "structopt", "structopt-toml", "tinyjson", + "toml 0.8.8", "url", ] diff --git a/bin/darkfid2/Cargo.toml b/bin/darkfid2/Cargo.toml index b9b41a49b..9a2d2fac8 100644 --- a/bin/darkfid2/Cargo.toml +++ b/bin/darkfid2/Cargo.toml @@ -22,8 +22,9 @@ blake3 = "1.5.0" bs58 = "0.5.0" log = "0.4.20" num-bigint = "0.4.4" -sled = "0.34.7" rand = "0.8.5" +sled = "0.34.7" +toml = "0.8.8" # JSON-RPC async-trait = "0.1.77" diff --git a/bin/darkfid2/darkfid_config.toml b/bin/darkfid2/darkfid_config.toml index 5de8e4377..3d2ffd473 100644 --- a/bin/darkfid2/darkfid_config.toml +++ b/bin/darkfid2/darkfid_config.toml @@ -13,7 +13,7 @@ rpc_listen = "tcp://127.0.0.1:8340" network = "testnet" # Localnet blockchain network configuration -[localnet] +[network_config."localnet"] # Path to the blockchain database directory database = "~/.local/darkfi/darkfid_blockchain_localnet" @@ -53,7 +53,7 @@ skip_sync = true pos_testing_mode = true ## Localnet sync P2P network settings -[localnet.sync_net] +[network_config."localnet".sync_net] # P2P accept addresses the instance listens on for inbound connections inbound = ["tcp+tls://0.0.0.0:8242"] @@ -107,7 +107,7 @@ localnet = true #outbound_peer_discovery_attempt_time = 5 ## Localnet consensus P2P network settings -[localnet.consensus_net] +[network_config."localnet".consensus_net] # P2P accept addresses the instance listens on for inbound connections #inbound = ["tcp+tls://0.0.0.0:8241"] @@ -157,7 +157,7 @@ localnet = true #outbound_peer_discovery_attempt_time = 5 # Testnet blockchain network configuration -[testnet] +[network_config."testnet"] # Path to the blockchain database directory database = "~/.local/darkfi/darkfid_blockchain_testnet" @@ -192,7 +192,7 @@ skip_sync = false pos_testing_mode = false ## Testnet sync P2P network settings -[testnet.sync_net] +[network_config."testnet".sync_net] # P2P accept addresses the instance listens on for inbound connections # You can also use an IPv6 address inbound = ["tcp+tls://0.0.0.0:8342"] @@ -256,7 +256,7 @@ localnet = false #outbound_peer_discovery_attempt_time = 5 ## Testnet consensus P2P network settings -[testnet.consensus_net] +[network_config."testnet".consensus_net] # P2P accept addresses the instance listens on for inbound connections # You can also use an IPv6 address inbound = ["tcp+tls://0.0.0.0:8341"] @@ -316,7 +316,7 @@ localnet = false #outbound_peer_discovery_attempt_time = 5 # Mainnet blockchain network configuration -[mainnet] +[network_config."mainnet"] # Path to the blockchain database directory database = "~/.local/darkfi/darkfid_blockchain_mainnet" @@ -351,7 +351,7 @@ skip_sync = false pos_testing_mode = false ## Mainnet sync P2P network settings -[mainnet.sync_net] +[network_config."mainnet".sync_net] # P2P accept addresses the instance listens on for inbound connections # You can also use an IPv6 address inbound = ["tcp+tls://0.0.0.0:8442"] @@ -415,7 +415,7 @@ localnet = false #outbound_peer_discovery_attempt_time = 5 ## Mainnet consensus P2P network settings -[mainnet.consensus_net] +[network_config."mainnet".consensus_net] # P2P accept addresses the instance listens on for inbound connections # You can also use an IPv6 address inbound = ["tcp+tls://0.0.0.0:8441"] diff --git a/bin/darkfid2/src/main.rs b/bin/darkfid2/src/main.rs index ea78ae888..a6f462a71 100644 --- a/bin/darkfid2/src/main.rs +++ b/bin/darkfid2/src/main.rs @@ -65,7 +65,7 @@ mod proto; /// Utility functions mod utils; -use utils::{spawn_consensus_p2p, spawn_sync_p2p}; +use utils::{parse_blockchain_config, spawn_consensus_p2p, spawn_sync_p2p}; const CONFIG_FILE: &str = "darkfid_config.toml"; const CONFIG_FILE_CONTENTS: &str = include_str!("../darkfid_config.toml"); @@ -84,26 +84,14 @@ struct Args { /// Configuration file to use config: Option, - #[structopt(long, default_value = "tcp://127.0.0.1:8340")] + #[structopt(short, long, default_value = "tcp://127.0.0.1:8340")] /// JSON-RPC listen URL rpc_listen: Url, - #[structopt(long, default_value = "testnet")] + #[structopt(short, long, default_value = "testnet")] /// Blockchain network to use network: String, - #[structopt(flatten)] - /// Localnet blockchain network configuration - localnet: BlockchainNetwork, - - #[structopt(flatten)] - /// Testnet blockchain network configuration - testnet: BlockchainNetwork, - - #[structopt(flatten)] - /// Mainnet blockchain network configuration - mainnet: BlockchainNetwork, - #[structopt(short, long)] /// Set log file to ouput into log: Option, @@ -216,9 +204,15 @@ async fn realmain(args: Args, ex: Arc>) -> Result<()> { // Grab blockchain network configuration let (blockchain_config, genesis_block) = match args.network.as_str() { - "localnet" => (args.localnet, GENESIS_BLOCK_LOCALNET), - "testnet" => (args.testnet, GENESIS_BLOCK_TESTNET), - "mainnet" => (args.mainnet, GENESIS_BLOCK_MAINNET), + "localnet" => { + (parse_blockchain_config(args.config, "localnet").await?, GENESIS_BLOCK_LOCALNET) + } + "testnet" => { + (parse_blockchain_config(args.config, "testnet").await?, GENESIS_BLOCK_TESTNET) + } + "mainnet" => { + (parse_blockchain_config(args.config, "mainnet").await?, GENESIS_BLOCK_MAINNET) + } _ => { error!("Unsupported chain `{}`", args.network); return Err(Error::UnsupportedChain) diff --git a/bin/darkfid2/src/utils.rs b/bin/darkfid2/src/utils.rs index 1bc2a7661..c5ab9339f 100644 --- a/bin/darkfid2/src/utils.rs +++ b/bin/darkfid2/src/utils.rs @@ -18,16 +18,22 @@ use std::{collections::HashMap, sync::Arc}; -use log::info; -use smol::Executor; +use log::{debug, error, info}; +use smol::{fs::read_to_string, Executor}; +use structopt_toml::StructOptToml; use darkfi::{ net::{P2p, P2pPtr, Settings, SESSION_ALL}, rpc::jsonrpc::JsonSubscriber, + util::path::get_config_path, validator::ValidatorPtr, + Error, Result, }; -use crate::proto::{ProtocolBlock, ProtocolProposal, ProtocolSync, ProtocolTx}; +use crate::{ + proto::{ProtocolBlock, ProtocolProposal, ProtocolSync, ProtocolTx}, + BlockchainNetwork, CONFIG_FILE, +}; /// Auxiliary function to generate the sync P2P network and register all its protocols. pub async fn spawn_sync_p2p( @@ -94,3 +100,48 @@ pub async fn spawn_consensus_p2p( p2p } + +/// Auxiliary function to parse darkfid configuration file and extract requested +/// blockchain network config. +pub async fn parse_blockchain_config( + config: Option, + network: &str, +) -> Result { + // Grab config path + let config_path = get_config_path(config, CONFIG_FILE)?; + debug!(target: "darkfid", "Parsing configuration file: {:?}", config_path); + + // Parse TOML file contents + let contents = read_to_string(&config_path).await?; + let contents: toml::Value = match toml::from_str(&contents) { + Ok(v) => v, + Err(e) => { + error!(target: "darkfid", "Failed parsing TOML config: {}", e); + return Err(Error::ParseFailed("Failed parsing TOML config")) + } + }; + + // Grab requested network config + let Some(table) = contents.as_table() else { return Err(Error::ParseFailed("TOML not a map")) }; + let Some(network_configs) = table.get("network_config") else { + return Err(Error::ParseFailed("TOML does not contain network configurations")) + }; + let Some(network_configs) = network_configs.as_table() else { + return Err(Error::ParseFailed("`network_config` not a map")) + }; + let Some(network_config) = network_configs.get(network) else { + return Err(Error::ParseFailed("TOML does not contain requested network configuration")) + }; + let network_config = toml::to_string(&network_config).unwrap(); + let network_config = + match BlockchainNetwork::from_iter_with_toml::>(&network_config, vec![]) { + Ok(v) => v, + Err(e) => { + error!(target: "darkfid", "Failed parsing requested network configuration: {}", e); + return Err(Error::ParseFailed("Failed parsing requested network configuration")) + } + }; + debug!(target: "darkfid", "Parsed network configuration: {:?}", network_config); + + Ok(network_config) +}