Kaynağa Gözat

darkfid2: enchanched args configuration

aggstam 2 yıl önce
ebeveyn
işleme
44482105c8

+ 1 - 1
bin/darkfid2/Cargo.toml

@@ -10,7 +10,7 @@ edition = "2021"
 
 [dependencies]
 # Darkfi
-darkfi = {path = "../../", features = ["async-daemonize"]}
+darkfi = {path = "../../", features = ["async-daemonize", "bs58"]}
 darkfi-consensus-contract = {path = "../../src/contract/consensus"}
 darkfi-money-contract = {path = "../../src/contract/money"}
 darkfi-contract-test-harness = {path = "../../src/contract/test-harness"}

+ 367 - 23
bin/darkfid2/darkfid_config.toml

@@ -7,7 +7,174 @@
 ## uncommenting, or by using the command-line.
 
 # JSON-RPC listen URL
-rpc_listen = "tcp://127.0.0.1:18340"
+rpc_listen = "tcp://127.0.0.1:8340"
+
+# Blockchain network to use
+network = "testnet"
+
+# Localnet blockchain network configuration
+[localnet]
+# Path to the blockchain database directory
+database = "~/.local/darkfi/darkfid_blockchain_localnet"
+
+# Finalization threshold, denominated by number of blocks
+threshold = 3
+
+# PoW miner number of threads to use
+pow_threads = 4
+
+# PoW block production target, in seconds
+pow_target = 10
+
+# Epoch duration, denominated by number of blocks/slots
+epoch_length = 10
+
+# PoS slot duration, in seconds
+slot_time = 10
+
+# Whitelisted faucet addresses
+faucet_pub = []
+
+# Participate in the consensus protocol
+consensus = true
+
+# Wallet address to receive consensus rewards.
+# This is a dummy one so the miner can start,
+# replace with your own one.
+recipient = "5ZHfYpt4mpJcwBNxfEyxLzeFJUEeoePs5NQ5jVEgHrMf"
+
+# Skip syncing process and start node right away
+skip_sync = true
+
+# Enable testing mode for local testing
+testing_mode = true
+
+## Localnet sync P2P network settings
+[localnet.sync_net]
+# P2P accept addresses the instance listens on for inbound connections
+inbound = ["tcp+tls://0.0.0.0:8242"]
+
+# P2P external addresses the instance advertises so other peers can
+# reach us and connect to us, as long as inbound addrs are configured.
+#external_addrs = []
+
+# Peer nodes to manually connect to
+#peers = []
+
+# Seed nodes to connect to for peer discovery and/or adversising our
+# own external addresses
+#seeds = []
+
+# Whitelisted network transports for outbound connections
+#allowed_transports = []
+
+# Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
+#transport_mixing = true
+
+# Outbound connection slots number, this many connections will be
+# attempted. (This does not include manual connections)
+#outbound_connections = 8
+
+# Inbound connections slots number, this many active inbound connections
+# will be allowed. (This does not include manual or outbound connections)
+#inbound_connections = 0
+
+# Manual connections retry limit, 0 for forever looping
+#manual_attempt_limit = 0
+
+# Outbound connection timeout (in seconds)
+#outbound_connect_timeout = 10
+
+# Exchange versions (handshake) timeout (in seconds)
+#channel_handshake_timeout = 4
+
+# Ping-pong exchange execution interval (in seconds)
+#channel_heartbeat_interval = 10
+
+# Allow localnet hosts
+localnet = true
+
+# Delete a peer from hosts if they've been quarantined N times
+#hosts_quarantine_limit = 50
+
+# Cooling off time for peer discovery when unsuccessful
+#outbound_peer_discovery_cooloff_time = 30
+
+# Time between peer discovery attempts
+#outbound_peer_discovery_attempt_time = 5
+
+## Localnet consensus P2P network settings
+[localnet.consensus_net]
+# P2P accept addresses the instance listens on for inbound connections
+#inbound = ["tcp+tls://0.0.0.0:8241"]
+
+# P2P external addresses the instance advertises so other peers can
+# reach us and connect to us, as long as inbound addrs are configured.
+#external_addrs = []
+
+# Peer nodes to manually connect to
+#peers = []
+
+# Seed nodes to connect to for peer discovery and/or adversising our
+# own external addresses
+#seeds = []
+
+# Whitelisted network transports for outbound connections
+#allowed_transports = []
+
+# Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
+#transport_mixing = true
+
+# Outbound connection slots number, this many connections will be
+# attempted. (This does not include manual connections)
+#outbound_connections = 8
+
+# Manual connections retry limit, 0 for forever looping
+#manual_attempt_limit = 0
+
+# Outbound connection timeout (in seconds)
+#outbound_connect_timeout = 10
+
+# Exchange versions (handshake) timeout (in seconds)
+#channel_handshake_timeout = 4
+
+# Ping-pong exchange execution interval (in seconds)
+#channel_heartbeat_interval = 10
+
+# Allow localnet hosts
+localnet = true
+
+# Delete a peer from hosts if they've been quarantined N times
+#hosts_quarantine_limit = 50
+
+# Cooling off time for peer discovery when unsuccessful
+#outbound_peer_discovery_cooloff_time = 30
+
+# Time between peer discovery attempts
+#outbound_peer_discovery_attempt_time = 5
+
+# Testnet blockchain network configuration
+[testnet]
+# Path to the blockchain database directory
+database = "~/.local/darkfi/darkfid_blockchain_testnet"
+
+# Finalization threshold, denominated by number of blocks
+threshold = 6
+
+# PoW miner number of threads to use
+pow_threads = 6
+
+# PoW block production target, in seconds
+pow_target = 90
+
+# Epoch duration, denominated by number of blocks/slots
+epoch_length = 10
+
+# PoS slot duration, in seconds
+slot_time = 90
+
+# Whitelisted faucet addresses
+faucet_pub = ["3ce5xa3PjuQGFtTaF7AvMJp7fGxqeGRJx7zj3LCwNCkP"]
 
 # Participate in the consensus protocol
 consensus = false
@@ -21,34 +188,34 @@ skip_sync = false
 # Enable testing mode for local testing
 testing_mode = false
 
-## Sync P2P network settings
-[sync_net]
+## Testnet sync P2P network settings
+[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:18342"]
+inbound = ["tls://0.0.0.0:8342"]
 # IPv6 version:
-#inbound = ["tcp+tls://[::]:8342"]
+#inbound = ["tls://[::]:8342"]
 # Combined:
-#inbound = ["tcp+tls://0.0.0.0:8342", "tcp+tls://[::]:8342"]
+#inbound = ["tls://0.0.0.0:8342", "tls://[::]:8342"]
 
 # P2P external addresses the instance advertises so other peers can
 # reach us and connect to us, as long as inbound addrs are configured.
 # You can also use an IPv6 address
-#external_addrs = ["tcp+tls://XXX.XXX.XXX.XXX:8342"]
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8342"]
 # IPv6 version:
-#external_addrs = ["tcp+tls://[ipv6 address here]:8342"]
+#external_addrs = ["tls://[ipv6 address here]:8342"]
 # Combined:
-#external_addrs = ["tcp+tls://XXX.XXX.XXX.XXX:8342", "tcp+tls://[ipv6 address here]:8342"]
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8342", "tls://[ipv6 address here]:8342"]
 
 # Peer nodes to manually connect to
 #peers = []
 
 # Seed nodes to connect to for peer discovery and/or adversising our
 # own external addresses
-#seeds = ["tcp+tls://lilith0.dark.fi:8342", "tcp+tls://lilith1.dark.fi:8342"]
+seeds = ["tls://lilith0.dark.fi:8342", "tls://lilith1.dark.fi:8342"]
 
 # Whitelisted network transports for outbound connections
-allowed_transports = ["tcp+tls"]
+allowed_transports = ["tls"]
 
 # Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
 #transport_mixing = true
@@ -74,36 +241,45 @@ outbound_connections = 8
 #channel_heartbeat_interval = 10
 
 # Allow localnet hosts
-#localnet = false
+localnet = false
+
+# Delete a peer from hosts if they've been quarantined N times
+#hosts_quarantine_limit = 50
+
+# Cooling off time for peer discovery when unsuccessful
+#outbound_peer_discovery_cooloff_time = 30
 
-## Sync P2P network settings
-[consensus_net]
+# Time between peer discovery attempts
+#outbound_peer_discovery_attempt_time = 5
+
+## Testnet consensus P2P network settings
+[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"]
+inbound = ["tls://0.0.0.0:8341"]
 # IPv6 version:
-#inbound = ["tcp+tls://[::]:8341"]
+#inbound = ["tls://[::]:8341"]
 # Combined:
-#inbound = ["tcp+tls://0.0.0.0:8341", "tcp+tls://[::]:8341"]
+#inbound = ["tls://0.0.0.0:8341", "tls://[::]:8341"]
 
 # P2P external addresses the instance advertises so other peers can
 # reach us and connect to us, as long as inbound addrs are configured.
 # You can also use an IPv6 address
-#external_addrs = ["tcp+tls://XXX.XXX.XXX.XXX:8341"]
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8341"]
 # IPv6 version:
-#external_addrs = ["tcp+tls://[ipv6 address here]:8341"]
+#external_addrs = ["tls://[ipv6 address here]:8341"]
 # Combined:
-#external_addrs = ["tcp+tls://XXX.XXX.XXX.XXX:8341", "tcp+tls://[ipv6 address here]:8341"]
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8341", "tls://[ipv6 address here]:8341"]
 
 # Peer nodes to manually connect to
 #peers = []
 
 # Seed nodes to connect to for peer discovery and/or adversising our
 # own external addresses
-#seeds = ["tcp+tls://lilith0.dark.fi:8341", "tcp+tls://lilith1.dark.fi:8341"]
+seeds = ["tls://lilith0.dark.fi:8341", "tls://lilith1.dark.fi:8341"]
 
 # Whitelisted network transports for outbound connections
-#allowed_transports = ["tcp+tls"]
+allowed_transports = ["tls"]
 
 # Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
 #transport_mixing = true
@@ -125,4 +301,172 @@ outbound_connections = 8
 #channel_heartbeat_interval = 10
 
 # Allow localnet hosts
-#localnet = false
+localnet = false
+
+# Delete a peer from hosts if they've been quarantined N times
+#hosts_quarantine_limit = 50
+
+# Cooling off time for peer discovery when unsuccessful
+#outbound_peer_discovery_cooloff_time = 30
+
+# Time between peer discovery attempts
+#outbound_peer_discovery_attempt_time = 5
+
+# Mainnet blockchain network configuration
+[mainnet]
+# Path to the blockchain database directory
+database = "~/.local/darkfi/darkfid_blockchain_mainnet"
+
+# Finalization threshold, denominated by number of blocks
+threshold = 11
+
+# PoW miner number of threads to use
+pow_threads = 8
+
+# PoW block production target, in seconds
+pow_target = 90
+
+# Epoch duration, denominated by number of blocks/slots
+epoch_length = 10
+
+# PoS slot duration, in seconds
+slot_time = 90
+
+# Whitelisted faucet addresses
+faucet_pub = []
+
+# Participate in the consensus protocol
+consensus = false
+
+# Wallet address to receive consensus rewards
+#recipient = "YOUR_WALLET_ADDRESS_HERE"
+
+# Skip syncing process and start node right away
+skip_sync = false
+
+# Enable testing mode for local testing
+testing_mode = false
+
+## Mainnet sync P2P network settings
+[mainnet.sync_net]
+# P2P accept addresses the instance listens on for inbound connections
+# You can also use an IPv6 address
+inbound = ["tls://0.0.0.0:8442"]
+# IPv6 version:
+#inbound = ["tls://[::]:8442"]
+# Combined:
+#inbound = ["tls://0.0.0.0:8442", "tls://[::]:8442"]
+
+# P2P external addresses the instance advertises so other peers can
+# reach us and connect to us, as long as inbound addrs are configured.
+# You can also use an IPv6 address
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8442"]
+# IPv6 version:
+#external_addrs = ["tls://[ipv6 address here]:8442"]
+# Combined:
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8442", "tls://[ipv6 address here]:8442"]
+
+# Peer nodes to manually connect to
+#peers = []
+
+# Seed nodes to connect to for peer discovery and/or adversising our
+# own external addresses
+seeds = ["tls://lilith0.dark.fi:8442", "tls://lilith1.dark.fi:8442"]
+
+# Whitelisted network transports for outbound connections
+allowed_transports = ["tls"]
+
+# Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
+#transport_mixing = true
+
+# Outbound connection slots number, this many connections will be
+# attempted. (This does not include manual connections)
+outbound_connections = 8
+
+# Inbound connections slots number, this many active inbound connections
+# will be allowed. (This does not include manual or outbound connections)
+#inbound_connections = 0
+
+# Manual connections retry limit, 0 for forever looping
+#manual_attempt_limit = 0
+
+# Outbound connection timeout (in seconds)
+#outbound_connect_timeout = 10
+
+# Exchange versions (handshake) timeout (in seconds)
+#channel_handshake_timeout = 4
+
+# Ping-pong exchange execution interval (in seconds)
+#channel_heartbeat_interval = 10
+
+# Allow localnet hosts
+localnet = false
+
+# Delete a peer from hosts if they've been quarantined N times
+#hosts_quarantine_limit = 50
+
+# Cooling off time for peer discovery when unsuccessful
+#outbound_peer_discovery_cooloff_time = 30
+
+# Time between peer discovery attempts
+#outbound_peer_discovery_attempt_time = 5
+
+## Mainnet consensus P2P network settings
+[mainnet.consensus_net]
+# P2P accept addresses the instance listens on for inbound connections
+# You can also use an IPv6 address
+inbound = ["tls://0.0.0.0:8441"]
+# IPv6 version:
+#inbound = ["tls://[::]:8441"]
+# Combined:
+#inbound = ["tls://0.0.0.0:8441", "tls://[::]:8441"]
+
+# P2P external addresses the instance advertises so other peers can
+# reach us and connect to us, as long as inbound addrs are configured.
+# You can also use an IPv6 address
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8441"]
+# IPv6 version:
+#external_addrs = ["tls://[ipv6 address here]:8441"]
+# Combined:
+#external_addrs = ["tls://XXX.XXX.XXX.XXX:8441", "tls://[ipv6 address here]:8441"]
+
+# Peer nodes to manually connect to
+#peers = []
+
+# Seed nodes to connect to for peer discovery and/or adversising our
+# own external addresses
+seeds = ["tls://lilith0.dark.fi:8441", "tls://lilith1.dark.fi:8441"]
+
+# Whitelisted network transports for outbound connections
+allowed_transports = ["tls"]
+
+# Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
+#transport_mixing = true
+
+# Outbound connection slots number, this many connections will be
+# attempted. (This does not include manual connections)
+#outbound_connections = 8
+
+# Manual connections retry limit, 0 for forever looping
+#manual_attempt_limit = 0
+
+# Outbound connection timeout (in seconds)
+#outbound_connect_timeout = 10
+
+# Exchange versions (handshake) timeout (in seconds)
+#channel_handshake_timeout = 4
+
+# Ping-pong exchange execution interval (in seconds)
+#channel_heartbeat_interval = 10
+
+# Allow localnet hosts
+localnet = false
+
+# Delete a peer from hosts if they've been quarantined N times
+#hosts_quarantine_limit = 50
+
+# Cooling off time for peer discovery when unsuccessful
+#outbound_peer_discovery_cooloff_time = 30
+
+# Time between peer discovery attempts
+#outbound_peer_discovery_attempt_time = 5

+ 1 - 0
bin/darkfid2/genesis_block_localnet

@@ -0,0 +1 @@
+3N337zZEeEFfZFBPotybXsdtKNjrAUx56QLqcr4izXLvyTVCY6E4MgUvUpEj57f6RNbkqMtZ4vqxFzWKGEnhvoMuaj1QK1fs7nRA4bY3JNrbvfzvP5UBCL9F7uTT3vpDbUiNEWwwr1UnvrzFkj7jryLLGkFDo7VMYXgovrnxMfQQczSiPVSQWGm8yXXMp9SaWeDW96r6GLbJWVc5roofVyGYYw4Cdd4vrbRMGnP7n78xWRGcmmHRebBHru2TqDSFnxYRKN3vtu1s42TkyxbbWVLrJft8ta1sq6PPPvk4idJsboEaxX9gj1DCMdvkq5gKFp5WohfhfMz7jXJod6do4xdPfutedLK3fUVYvTkRRqoSVogbzr2jdjiRPzf9WuvJyULZY7KT6Knby6aenGLdPPd3TcndiqXyWscU1LcWFX59Z7Nkp63no6rmps

+ 1 - 0
bin/darkfid2/genesis_block_mainnet

@@ -0,0 +1 @@
+3N337zZEeEFfZFBPotybXsdtKNjrAUx56QLqcr4izXLvyTVCY6E4MgUvUpEj57f6RNbkqMtZ4vqxFzWKGEnhvoMuaj1QK1fs7nRA4bY3JNrbvfzvP5UBCL9F7uTT3vpDbUiNEWwwr1UnvrzFkj7jryLLGkFDo7VMYXgovrnxMfQQczSiPVSQWGm8yXXMp9SaWeDW96r6GLbJWVc5roofVyGYYw4Cdd4vrbRMGnP7n78xWRGcmmHRebBHru2TqDSFnxYRKN3vtu1s42TkyxbbWVLrJft8ta1sq6PPPvk4idJsboEaxX9gj1DCMdvkq5gKFp5WohfhfMz7jXJod6do4xdPfutedLK3fUVYvTkRRqoSVogbzr2jdjiRPzf9WuvJyULZY7KT6Knby6aenGLdPPd3TcndiqXyWscU1LcWFX59Z7Nkp63no6rmps

+ 1 - 0
bin/darkfid2/genesis_block_testnet

@@ -0,0 +1 @@
+3N337zZEeEFfZFBPotybXsdtKNjrAUx56QLqcr4izXLvyTVCY6E4MgUvUpEj57f6RNbkqMtZ4vqxFzWKGEnhvoMuaj1QK1fs7nRA4bY3JNrbvfzvP5UBCL9F7uTT3vpDbUiNEWwwr1UnvrzFkj7jryLLGkFDo7VMYXgovrnxMfQQczSiPVSQWGm8yXXMp9SaWeDW96r6GLbJWVc5roofVyGYYw4Cdd4vrbRMGnP7n78xWRGcmmHRebBHru2TqDSFnxYRKN3vtu1s42TkyxbbWVLrJft8ta1sq6PPPvk4idJsboEaxX9gj1DCMdvkq5gKFp5WohfhfMz7jXJod6do4xdPfutedLK3fUVYvTkRRqoSVogbzr2jdjiRPzf9WuvJyULZY7KT6Knby6aenGLdPPd3TcndiqXyWscU1LcWFX59Z7Nkp63no6rmps

+ 120 - 42
bin/darkfid2/src/main.rs

@@ -37,12 +37,12 @@ use darkfi::{
         server::{listen_and_serve, RequestHandler},
     },
     system::{StoppableTask, StoppableTaskPtr},
-    util::time::TimeKeeper,
+    util::{path::expand_path, time::TimeKeeper},
     validator::{utils::genesis_txs_total, Validator, ValidatorConfig, ValidatorPtr},
     Error, Result,
 };
-use darkfi_contract_test_harness::vks;
 use darkfi_sdk::crypto::PublicKey;
+use darkfi_serial::deserialize;
 
 #[cfg(test)]
 mod tests;
@@ -68,6 +68,12 @@ use utils::{spawn_consensus_p2p, spawn_sync_p2p};
 
 const CONFIG_FILE: &str = "darkfid_config.toml";
 const CONFIG_FILE_CONTENTS: &str = include_str!("../darkfid_config.toml");
+/// Note:
+/// If you change these don't forget to remove their corresponding database folder,
+/// since if it already has a genesis block, provided one is ignored.
+const GENESIS_BLOCK_LOCALNET: &str = include_str!("../genesis_block_localnet");
+const GENESIS_BLOCK_TESTNET: &str = include_str!("../genesis_block_testnet");
+const GENESIS_BLOCK_MAINNET: &str = include_str!("../genesis_block_mainnet");
 
 #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
 #[serde(default)]
@@ -81,37 +87,87 @@ struct Args {
     /// JSON-RPC listen URL
     rpc_listen: Url,
 
+    #[structopt(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<String>,
+
+    #[structopt(short, parse(from_occurrences))]
+    /// Increase verbosity (-vvv supported)
+    verbose: u8,
+}
+
+/// Defines a blockchain network configuration.
+/// Default values correspond to a local network.
+#[derive(Clone, Debug, serde::Deserialize, structopt::StructOpt, structopt_toml::StructOptToml)]
+#[structopt()]
+pub struct BlockchainNetwork {
+    #[structopt(long, default_value = "~/.local/darkfi/darkfid_blockchain_localnet")]
+    /// Path to blockchain database
+    pub database: String,
+
+    #[structopt(long, default_value = "3")]
+    /// Finalization threshold, denominated by number of blocks
+    pub threshold: usize,
+
+    #[structopt(long, default_value = "4")]
+    /// PoW miner number of threads to use
+    pub pow_threads: usize,
+
+    #[structopt(long, default_value = "10")]
+    /// PoW block production target, in seconds
+    pub pow_target: usize,
+
+    #[structopt(long, default_value = "10")]
+    /// Epoch duration, denominated by number of blocks/slots
+    pub epoch_length: u64,
+
+    #[structopt(long, default_value = "10")]
+    /// PoS slot duration, in seconds
+    pub slot_time: u64,
+
+    #[structopt(long)]
+    /// Whitelisted faucet public key (repeatable flag)
+    pub faucet_pub: Vec<String>,
+
     #[structopt(long)]
     /// Participate in the consensus protocol
-    consensus: bool,
+    pub consensus: bool,
 
     #[structopt(long)]
     /// Wallet address to receive consensus rewards
-    recipient: Option<String>,
+    pub recipient: Option<String>,
 
     #[structopt(long)]
     /// Skip syncing process and start node right away
-    skip_sync: bool,
+    pub skip_sync: bool,
+
+    #[structopt(long)]
+    /// Enable testing mode for local testing
+    pub testing_mode: bool,
 
     /// Syncing network settings
     #[structopt(flatten)]
-    sync_net: SettingsOpt,
+    pub sync_net: SettingsOpt,
 
     /// Consensus network settings
     #[structopt(flatten)]
-    consensus_net: SettingsOpt,
-
-    #[structopt(long)]
-    /// Enable testing mode for local testing
-    testing_mode: bool,
-
-    #[structopt(short, long)]
-    /// Set log file to ouput into
-    log: Option<String>,
-
-    #[structopt(short, parse(from_occurrences))]
-    /// Increase verbosity (-vvv supported)
-    verbose: u8,
+    pub consensus_net: SettingsOpt,
 }
 
 /// Daemon structure
@@ -149,30 +205,46 @@ async_daemonize!(realmain);
 async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
     info!(target: "darkfid", "Initializing DarkFi node...");
 
-    if args.testing_mode {
+    // 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),
+        _ => {
+            error!("Unsupported chain `{}`", args.network);
+            return Err(Error::UnsupportedChain)
+        }
+    };
+
+    if blockchain_config.testing_mode {
         info!(target: "darkfid", "Node is configured to run in testing mode!");
     }
 
-    // NOTE: everything is dummy for now
-    // FIXME: The VKS should only ever have to be generated on initial run.
-    //        Do not use the precompiles for actual production code.
+    // Parse the genesis block
+    let bytes = bs58::decode(&genesis_block.trim()).into_vec()?;
+    let genesis_block: BlockInfo = deserialize(&bytes)?;
+
     // Initialize or open sled database
-    let sled_db = sled::Config::new().temporary(true).open()?;
-    let (_, vks) = vks::read_or_gen_vks_and_pks()?;
-    vks::inject(&sled_db, &vks)?;
+    let db_path = expand_path(&blockchain_config.database)?;
+    let sled_db = sled::open(&db_path)?;
 
     // Initialize validator configuration
-    let genesis_block = BlockInfo::default();
     let genesis_txs_total = genesis_txs_total(&genesis_block.txs)?;
-    let time_keeper = TimeKeeper::new(genesis_block.header.timestamp, 10, 90, 0);
-    // TODO: add miner threads arg
+    let time_keeper = TimeKeeper::new(
+        genesis_block.header.timestamp,
+        blockchain_config.epoch_length,
+        blockchain_config.slot_time,
+        0,
+    );
     let config = ValidatorConfig::new(
         time_keeper,
-        Some(40),
+        blockchain_config.threshold,
+        blockchain_config.pow_threads,
+        blockchain_config.pow_target,
         genesis_block,
         genesis_txs_total,
         vec![],
-        args.testing_mode,
+        blockchain_config.testing_mode,
     );
 
     // Initialize validator
@@ -182,19 +254,25 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
     let mut subscribers = HashMap::new();
     subscribers.insert("blocks", JsonSubscriber::new("blockchain.subscribe_blocks"));
     subscribers.insert("txs", JsonSubscriber::new("blockchain.subscribe_txs"));
-    if args.consensus {
+    if blockchain_config.consensus {
         subscribers.insert("proposals", JsonSubscriber::new("blockchain.subscribe_proposals"));
     }
 
     // Initialize syncing P2P network
     let sync_p2p =
-        spawn_sync_p2p(&args.sync_net.into(), &validator, &subscribers, ex.clone()).await;
+        spawn_sync_p2p(&blockchain_config.sync_net.into(), &validator, &subscribers, ex.clone())
+            .await;
 
     // Initialize consensus P2P network
-    let consensus_p2p = if args.consensus {
+    let consensus_p2p = if blockchain_config.consensus {
         Some(
-            spawn_consensus_p2p(&args.consensus_net.into(), &validator, &subscribers, ex.clone())
-                .await,
+            spawn_consensus_p2p(
+                &blockchain_config.consensus_net.into(),
+                &validator,
+                &subscribers,
+                ex.clone(),
+            )
+            .await,
         )
     } else {
         None
@@ -230,7 +308,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
     sync_p2p.clone().start().await?;
 
     // Consensus protocol
-    if args.consensus {
+    if blockchain_config.consensus {
         info!(target: "darkfid", "Starting consensus P2P network");
         let consensus_p2p = consensus_p2p.clone().unwrap();
         consensus_p2p.clone().start().await?;
@@ -239,7 +317,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
     }
 
     // Sync blockchain
-    if !args.skip_sync {
+    if !blockchain_config.skip_sync {
         sync_task(&darkfid).await?;
     } else {
         darkfid.validator.write().await.synced = true;
@@ -249,13 +327,13 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
     darkfid.validator.write().await.purge_pending_txs().await?;
 
     // Consensus protocol
-    let (consensus_task, consensus_sender) = if args.consensus {
+    let (consensus_task, consensus_sender) = if blockchain_config.consensus {
         info!(target: "darkfid", "Starting consensus protocol task");
         // Grab rewards recipient public key(address)
-        if args.recipient.is_none() {
+        if blockchain_config.recipient.is_none() {
             return Err(Error::ParseFailed("Recipient address missing"))
         }
-        let recipient = match PublicKey::from_str(&args.recipient.unwrap()) {
+        let recipient = match PublicKey::from_str(&blockchain_config.recipient.unwrap()) {
             Ok(address) => address,
             Err(_) => return Err(Error::InvalidAddress),
         };
@@ -291,7 +369,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
     info!(target: "darkfid", "Stopping syncing P2P network...");
     sync_p2p.stop().await;
 
-    if args.consensus {
+    if blockchain_config.consensus {
         info!(target: "darkfid", "Stopping consensus P2P network...");
         consensus_p2p.unwrap().stop().await;
 

+ 1 - 1
bin/darkfid2/src/tests/forks.rs

@@ -30,7 +30,7 @@ fn forks() -> Result<()> {
 
     // Create a temporary blockchain and a PoW module
     let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
-    let module = PoWModule::new(blockchain.clone(), None, Some(90))?;
+    let module = PoWModule::new(blockchain.clone(), 2, 90)?;
 
     // Create a fork
     let fork = Fork::new(&blockchain, module)?;

+ 19 - 3
bin/darkfid2/src/tests/harness.rs

@@ -42,7 +42,8 @@ use crate::{
 };
 
 pub struct HarnessConfig {
-    pub pow_target: Option<usize>,
+    pub pow_threads: usize,
+    pub pow_target: usize,
     pub testing_node: bool,
     pub alice_initial: u64,
     pub bob_initial: u64,
@@ -82,6 +83,8 @@ impl Harness {
         let time_keeper = TimeKeeper::new(genesis_block.header.timestamp, 10, 90, 0);
         let validator_config = ValidatorConfig::new(
             time_keeper,
+            3,
+            config.pow_threads,
             config.pow_target,
             genesis_block,
             genesis_txs_total,
@@ -136,8 +139,21 @@ impl Harness {
         let alice = &self.alice.validator.read().await;
         let bob = &self.bob.validator.read().await;
 
-        alice.validate_blockchain(genesis_txs_total, vec![], self.config.pow_target).await?;
-        bob.validate_blockchain(genesis_txs_total, vec![], self.config.pow_target).await?;
+        alice
+            .validate_blockchain(
+                genesis_txs_total,
+                vec![],
+                self.config.pow_threads,
+                self.config.pow_target,
+            )
+            .await?;
+        bob.validate_blockchain(
+            genesis_txs_total,
+            vec![],
+            self.config.pow_threads,
+            self.config.pow_target,
+        )
+        .await?;
 
         let alice_blockchain_len = alice.blockchain.len();
         assert_eq!(alice_blockchain_len, bob.blockchain.len());

+ 10 - 4
bin/darkfid2/src/tests/mod.rs

@@ -32,9 +32,15 @@ async fn sync_pos_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
     init_logger();
 
     // Initialize harness in testing mode
-    let pow_target = Some(90);
-    let config =
-        HarnessConfig { testing_node: true, pow_target, alice_initial: 1000, bob_initial: 500 };
+    let pow_threads = 2;
+    let pow_target = 90;
+    let config = HarnessConfig {
+        pow_threads,
+        pow_target,
+        testing_node: true,
+        alice_initial: 1000,
+        bob_initial: 500,
+    };
     let th = Harness::new(config, &ex).await?;
 
     // Retrieve genesis block
@@ -67,7 +73,7 @@ async fn sync_pos_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
     let genesis_txs_total = th.config.alice_initial + th.config.bob_initial;
     let alice = &th.alice.validator.read().await;
     let charlie = &charlie.validator.read().await;
-    charlie.validate_blockchain(genesis_txs_total, vec![], pow_target).await?;
+    charlie.validate_blockchain(genesis_txs_total, vec![], pow_threads, pow_target).await?;
     assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
     assert_eq!(alice.blockchain.slots.len(), charlie.blockchain.slots.len());
 

+ 3 - 1
src/contract/test-harness/src/lib.rs

@@ -157,7 +157,9 @@ impl Wallet {
         let time_keeper = TimeKeeper::new(genesis_block.header.timestamp, 10, 90, 0);
         let config = ValidatorConfig::new(
             time_keeper,
-            Some(90),
+            3,
+            1,
+            90,
             genesis_block.clone(),
             0,
             faucet_pubkeys.to_vec(),

+ 4 - 0
src/net/settings.rs

@@ -162,6 +162,7 @@ pub struct SettingsOpt {
     #[structopt(long = "transports")]
     pub allowed_transports: Vec<String>,
 
+    /// Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
     #[structopt(long)]
     pub transport_mixing: Option<bool>,
 
@@ -170,12 +171,15 @@ pub struct SettingsOpt {
     #[structopt(long)]
     pub localnet: bool,
 
+    /// Delete a peer from hosts if they've been quarantined N times
     #[structopt(skip)]
     pub hosts_quarantine_limit: Option<usize>,
 
+    /// Cooling off time for peer discovery when unsuccessful
     #[structopt(skip)]
     pub outbound_peer_discovery_cooloff_time: Option<u64>,
 
+    /// Time between peer discovery attempts
     #[structopt(skip)]
     pub outbound_peer_discovery_attempt_time: Option<u64>,
 }

+ 9 - 6
src/validator/consensus.rs

@@ -38,8 +38,6 @@ use crate::{
 // Consensus configuration
 /// Block/proposal maximum transactions
 pub const TXS_CAP: usize = 50;
-/// Fork size(length) after which it can be finalized
-const FINALIZATION_SECURITY_THRESSHOLD: usize = 3;
 
 /// This struct represents the information required by the consensus algorithm
 pub struct Consensus {
@@ -47,6 +45,8 @@ pub struct Consensus {
     pub blockchain: Blockchain,
     /// Helper structure to calculate time related operations
     pub time_keeper: TimeKeeper,
+    /// Fork size(length) after which it can be finalized
+    pub finalization_threshold: usize,
     /// Node is participating to consensus
     pub participating: bool,
     /// Last slot node check for finalization
@@ -64,13 +64,16 @@ impl Consensus {
     pub fn new(
         blockchain: Blockchain,
         time_keeper: TimeKeeper,
-        pow_target: Option<usize>,
+        finalization_threshold: usize,
+        pow_threads: usize,
+        pow_target: usize,
         testing_mode: bool,
     ) -> Result<Self> {
-        let module = PoWModule::new(blockchain.clone(), None, pow_target)?;
+        let module = PoWModule::new(blockchain.clone(), pow_threads, pow_target)?;
         Ok(Self {
             blockchain,
             time_keeper,
+            finalization_threshold,
             participating: false,
             checked_finalization: 0,
             forks: vec![],
@@ -393,7 +396,7 @@ impl Consensus {
     }
 
     /// Consensus finalization logic:
-    /// - If the current best fork has reached greater length than the security thresshold, and
+    /// - If the current best fork has reached greater length than the security threshold, and
     ///   no other fork exist with same rank, all proposals excluding the last one in that fork
     //    can be finalized (append to canonical blockchain).
     /// When best fork can be finalized, blocks(proposals) should be appended to canonical, excluding the
@@ -417,7 +420,7 @@ impl Consensus {
 
         // Check its length
         let length = fork.proposals.len();
-        if length < FINALIZATION_SECURITY_THRESSHOLD {
+        if length < self.finalization_threshold {
             debug!(target: "validator::consensus::finalization", "Nothing to finalize yet, best fork size: {}", length);
             return Ok(vec![])
         }

+ 16 - 4
src/validator/mod.rs

@@ -70,8 +70,12 @@ pub mod float_10;
 pub struct ValidatorConfig {
     /// Helper structure to calculate time related operations
     pub time_keeper: TimeKeeper,
+    /// Currently configured finalization security threshold
+    pub finalization_threshold: usize,
+    /// Currently configured PoW miner number of threads to use
+    pub pow_threads: usize,
     /// Currently configured PoW target
-    pub pow_target: Option<usize>,
+    pub pow_target: usize,
     /// Genesis block
     pub genesis_block: BlockInfo,
     /// Total amount of minted tokens in genesis block
@@ -83,9 +87,12 @@ pub struct ValidatorConfig {
 }
 
 impl ValidatorConfig {
+    #[allow(clippy::too_many_arguments)]
     pub fn new(
         time_keeper: TimeKeeper,
-        pow_target: Option<usize>,
+        finalization_threshold: usize,
+        pow_threads: usize,
+        pow_target: usize,
         genesis_block: BlockInfo,
         genesis_txs_total: u64,
         faucet_pubkeys: Vec<PublicKey>,
@@ -93,6 +100,8 @@ impl ValidatorConfig {
     ) -> Self {
         Self {
             time_keeper,
+            finalization_threshold,
+            pow_threads,
             pow_target,
             genesis_block,
             genesis_txs_total,
@@ -150,6 +159,8 @@ impl Validator {
         let consensus = Consensus::new(
             blockchain.clone(),
             config.time_keeper,
+            config.finalization_threshold,
+            config.pow_threads,
             config.pow_target,
             testing_mode,
         )?;
@@ -527,7 +538,8 @@ impl Validator {
         &self,
         genesis_txs_total: u64,
         faucet_pubkeys: Vec<PublicKey>,
-        pow_target: Option<usize>,
+        pow_threads: usize,
+        pow_target: usize,
     ) -> Result<()> {
         let blocks = self.blockchain.get_all()?;
 
@@ -546,7 +558,7 @@ impl Validator {
 
         // Create a time keeper and a PoW module to validate each block
         let mut time_keeper = self.consensus.time_keeper.clone();
-        let mut module = PoWModule::new(blockchain.clone(), None, pow_target)?;
+        let mut module = PoWModule::new(blockchain.clone(), pow_threads, pow_target)?;
 
         // Deploy native wasm contracts
         deploy_native_contracts(&overlay, &time_keeper, &faucet_pubkeys)?;

+ 8 - 19
src/validator/pow.rs

@@ -45,8 +45,6 @@ use crate::{
 };
 
 // Note: We have combined some constants for better performance.
-/// Default number of threads to use for hashing
-const N_THREADS: usize = 4;
 /// Amount of max items(blocks) to use for next difficulty calculation.
 /// Must be >= 2 and == BUF_SIZE - DIFFICULTY_LAG.
 const DIFFICULTY_WINDOW: usize = 720;
@@ -71,9 +69,6 @@ const RETAINED: usize = 600;
 const CUT_BEGIN: usize = 60;
 /// Already known cutoff end index for this config
 const CUT_END: usize = 660;
-/// Default target block time, in seconds
-const DIFFICULTY_TARGET: usize = 20;
-// TODO: maybe add more difficulty targets (testnet, mainnet, etc)
 /// How many most recent blocks to use to verify new blocks' timestamp
 const BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW: usize = 60;
 /// Time limit in the future of what blocks can be
@@ -82,11 +77,9 @@ const BLOCK_FUTURE_TIME_LIMIT: u64 = 60 * 60 * 2;
 /// This struct represents the information required by the PoW algorithm
 #[derive(Clone)]
 pub struct PoWModule {
-    /// Number of threads to use for hashing,
-    /// if None provided will use N_THREADS
+    /// Number of threads to use for hashing
     pub threads: usize,
-    /// Target block time, in seconds,
-    /// if None provided will use DIFFICULTY_TARGET
+    /// Target block time, in seconds
     pub target: usize,
     /// Latest block timestamps ringbuffer
     pub timestamps: RingBuffer<u64, BUF_SIZE>,
@@ -100,14 +93,7 @@ pub struct PoWModule {
 }
 
 impl PoWModule {
-    pub fn new(
-        blockchain: Blockchain,
-        threads: Option<usize>,
-        target: Option<usize>,
-    ) -> Result<Self> {
-        let threads = if let Some(t) = threads { t } else { N_THREADS };
-        let target = if let Some(t) = target { t } else { DIFFICULTY_TARGET };
-
+    pub fn new(blockchain: Blockchain, threads: usize, target: usize) -> Result<Self> {
         // Retrieving last BUF_ZISE difficulties from blockchain to build the buffers
         let mut timestamps = RingBuffer::<u64, BUF_SIZE>::new();
         let mut difficulties = RingBuffer::<BigUint, BUF_SIZE>::new();
@@ -390,13 +376,15 @@ mod tests {
 
     use super::PoWModule;
 
+    const DEFAULT_TEST_THREADS: usize = 2;
     const DEFAULT_TEST_DIFFICULTY_TARGET: usize = 120;
 
     #[test]
     fn test_wide_difficulty() -> Result<()> {
         let sled_db = sled::Config::new().temporary(true).open()?;
         let blockchain = Blockchain::new(&sled_db)?;
-        let mut module = PoWModule::new(blockchain, None, Some(DEFAULT_TEST_DIFFICULTY_TARGET))?;
+        let mut module =
+            PoWModule::new(blockchain, DEFAULT_TEST_THREADS, DEFAULT_TEST_DIFFICULTY_TARGET)?;
 
         let output = Command::new("./script/research/pow/gen_wide_data.py").output().unwrap();
         let reader = Cursor::new(output.stdout);
@@ -429,7 +417,8 @@ mod tests {
         // Default setup
         let sled_db = sled::Config::new().temporary(true).open()?;
         let blockchain = Blockchain::new(&sled_db)?;
-        let module = PoWModule::new(blockchain, None, Some(DEFAULT_TEST_DIFFICULTY_TARGET))?;
+        let module =
+            PoWModule::new(blockchain, DEFAULT_TEST_THREADS, DEFAULT_TEST_DIFFICULTY_TARGET)?;
         let (_, recvr) = smol::channel::bounded(1);
         let genesis_block = BlockInfo::default();
 

+ 6 - 2
src/validator/validation.rs

@@ -333,9 +333,13 @@ pub fn validate_pos_slot(
 /// A blockchain is considered valid, when every block is valid,
 /// based on validate_block checks.
 /// Be careful as this will try to load everything in memory.
-pub fn validate_blockchain(blockchain: &Blockchain, pow_target: Option<usize>) -> Result<()> {
+pub fn validate_blockchain(
+    blockchain: &Blockchain,
+    pow_threads: usize,
+    pow_target: usize,
+) -> Result<()> {
     // Generate a PoW module
-    let mut module = PoWModule::new(blockchain.clone(), None, pow_target)?;
+    let mut module = PoWModule::new(blockchain.clone(), pow_threads, pow_target)?;
     // We use block order store here so we have all blocks in order
     let blocks = blockchain.order.get_all()?;
     for (index, block) in blocks[1..].iter().enumerate() {

+ 5 - 4
tests/blockchain.rs

@@ -30,7 +30,8 @@ use darkfi_sdk::{
     pasta::{group::ff::Field, pallas},
 };
 
-const POW_TARGET: Option<usize> = Some(10);
+const POW_THREADS: usize = 1;
+const POW_TARGET: usize = 10;
 
 struct Node {
     blockchain: Blockchain,
@@ -40,7 +41,7 @@ struct Node {
 impl Node {
     fn new() -> Result<Self> {
         let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
-        let module = PoWModule::new(blockchain.clone(), None, POW_TARGET)?;
+        let module = PoWModule::new(blockchain.clone(), POW_THREADS, POW_TARGET)?;
         Ok(Self { blockchain, module })
     }
 }
@@ -63,8 +64,8 @@ impl Harness {
     }
 
     fn validate_chains(&self) -> Result<()> {
-        validate_blockchain(&self.alice.blockchain, POW_TARGET)?;
-        validate_blockchain(&self.bob.blockchain, POW_TARGET)?;
+        validate_blockchain(&self.alice.blockchain, POW_THREADS, POW_TARGET)?;
+        validate_blockchain(&self.bob.blockchain, POW_THREADS, POW_TARGET)?;
 
         assert_eq!(self.alice.blockchain.len(), self.bob.blockchain.len());