From 79f9cd24c5a430acc8d7db0ebfc0233d01ccef7d Mon Sep 17 00:00:00 2001 From: skoupidi Date: Wed, 19 Jun 2024 17:35:52 +0300 Subject: [PATCH] darkfid: optional bootstrap timestamp added --- bin/darkfid/darkfid_config.toml | 9 +++ bin/darkfid/src/main.rs | 23 +++++-- bin/darkfid/src/task/consensus.rs | 60 ++++++++++++++----- .../localnet/darkfid-five-nodes/darkfid0.toml | 3 + .../localnet/darkfid-five-nodes/darkfid1.toml | 3 + .../localnet/darkfid-five-nodes/darkfid2.toml | 3 + .../localnet/darkfid-five-nodes/darkfid3.toml | 3 + .../localnet/darkfid-five-nodes/darkfid4.toml | 3 + .../localnet/darkfid-single-node/darkfid.toml | 3 + contrib/localnet/darkfid-small/darkfid0.toml | 3 + contrib/localnet/darkfid-small/darkfid1.toml | 3 + contrib/localnet/darkfid-small/darkfid2.toml | 3 + 12 files changed, 100 insertions(+), 19 deletions(-) diff --git a/bin/darkfid/darkfid_config.toml b/bin/darkfid/darkfid_config.toml index 260a71f1a..06792d883 100644 --- a/bin/darkfid/darkfid_config.toml +++ b/bin/darkfid/darkfid_config.toml @@ -52,6 +52,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections @@ -141,6 +144,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Testnet P2P network settings [network_config."testnet".net] # P2P accept addresses the instance listens on for inbound connections @@ -234,6 +240,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Mainnet P2P network settings [network_config."mainnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/bin/darkfid/src/main.rs b/bin/darkfid/src/main.rs index cc3df7e24..a6a81f86c 100644 --- a/bin/darkfid/src/main.rs +++ b/bin/darkfid/src/main.rs @@ -56,7 +56,7 @@ mod rpc_tx; /// Validator async tasks mod task; -use task::consensus_init_task; +use task::{consensus::ConsensusInitTaskConfig, consensus_init_task}; /// P2P net protocols mod proto; @@ -152,6 +152,10 @@ pub struct BlockchainNetwork { /// Optional sync checkpoint hash pub checkpoint: Option, + #[structopt(long)] + /// Optional bootstrap timestamp + pub bootstrap: Option, + /// P2P network settings #[structopt(flatten)] pub net: SettingsOpt, @@ -236,6 +240,12 @@ async fn realmain(args: Args, ex: Arc>) -> Result<()> { let bytes = base64::decode(genesis_block.trim()).unwrap(); let genesis_block: BlockInfo = deserialize_async(&bytes).await?; + // Compute the bootstrap timestamp + let bootstrap = match blockchain_config.bootstrap { + Some(b) => b, + None => genesis_block.header.timestamp.inner(), + }; + // Initialize or open sled database let db_path = expand_path(&blockchain_config.database)?; let sled_db = sled::open(&db_path)?; @@ -331,10 +341,13 @@ async fn realmain(args: Args, ex: Arc>) -> Result<()> { consensus_task.clone().start( consensus_init_task( darkfid.clone(), - blockchain_config.skip_sync, - blockchain_config.checkpoint_height, - blockchain_config.checkpoint, blockchain_config.miner, - blockchain_config.recipient, + ConsensusInitTaskConfig::new( + blockchain_config.skip_sync, + blockchain_config.checkpoint_height, + blockchain_config.checkpoint, blockchain_config.miner, + blockchain_config.recipient, + bootstrap, + ), ex.clone(), ), |res| async move { diff --git a/bin/darkfid/src/task/consensus.rs b/bin/darkfid/src/task/consensus.rs index 45a8c645a..0960ac7f7 100644 --- a/bin/darkfid/src/task/consensus.rs +++ b/bin/darkfid/src/task/consensus.rs @@ -19,7 +19,10 @@ use std::{str::FromStr, sync::Arc}; use darkfi::{ - blockchain::HeaderHash, rpc::util::JsonValue, system::StoppableTask, util::encoding::base64, + blockchain::HeaderHash, + rpc::util::JsonValue, + system::{sleep, StoppableTask}, + util::{encoding::base64, time::Timestamp}, Error, Result, }; use darkfi_sdk::crypto::PublicKey; @@ -31,29 +34,58 @@ use crate::{ Darkfid, }; -/// Sync the node consensus state and start the corresponding task, based on node type. -pub async fn consensus_init_task( - node: Arc, +/// Auxiliary structure representing node consesus init task configuration +pub struct ConsensusInitTaskConfig { skip_sync: bool, checkpoint_height: Option, checkpoint: Option, miner: bool, recipient: Option, + bootstrap: u64, +} + +impl ConsensusInitTaskConfig { + pub fn new( + skip_sync: bool, + checkpoint_height: Option, + checkpoint: Option, + miner: bool, + recipient: Option, + bootstrap: u64, + ) -> Self { + Self { skip_sync, checkpoint_height, checkpoint, miner, recipient, bootstrap } + } +} + +/// Sync the node consensus state and start the corresponding task, based on node type. +pub async fn consensus_init_task( + node: Arc, + config: ConsensusInitTaskConfig, ex: Arc>, ) -> Result<()> { + // Check if network is configured to start in the future. + // NOTE: Always configure the network to start in the future when bootstrapping + // or restarting it. + let current = Timestamp::current_time().inner(); + if current < config.bootstrap { + let diff = config.bootstrap - current; + info!(target: "darkfid::task::consensus_init_task", "Waiting for network bootstrap: {diff} seconds"); + sleep(diff).await; + } + // Generate a new fork to be able to extend info!(target: "darkfid::task::consensus_init_task", "Generating new empty fork..."); node.validator.consensus.generate_empty_fork().await?; // Sync blockchain - let checkpoint = if !skip_sync { + let checkpoint = if !config.skip_sync { // Parse configured checkpoint - if checkpoint_height.is_some() && checkpoint.is_none() { + if config.checkpoint_height.is_some() && config.checkpoint.is_none() { return Err(Error::ParseFailed("Blockchain configured checkpoint hash missing")) } - let checkpoint = if let Some(height) = checkpoint_height { - Some((height, HeaderHash::from_str(checkpoint.as_ref().unwrap())?)) + let checkpoint = if let Some(height) = config.checkpoint_height { + Some((height, HeaderHash::from_str(config.checkpoint.as_ref().unwrap())?)) } else { None }; @@ -66,11 +98,11 @@ pub async fn consensus_init_task( }; // Grab rewards recipient public key(address) if node is a miner - let recipient = if miner { - if recipient.is_none() { + let recipient = if config.miner { + if config.recipient.is_none() { return Err(Error::ParseFailed("Recipient address missing")) } - match PublicKey::from_str(recipient.as_ref().unwrap()) { + match PublicKey::from_str(config.recipient.as_ref().unwrap()) { Ok(address) => Some(address), Err(_) => return Err(Error::InvalidAddress), } @@ -80,8 +112,8 @@ pub async fn consensus_init_task( // Gracefully handle network disconnections loop { - let result = if miner { - miner_task(node.clone(), recipient.unwrap(), skip_sync, ex.clone()).await + let result = if config.miner { + miner_task(node.clone(), recipient.unwrap(), config.skip_sync, ex.clone()).await } else { replicator_task(node.clone(), ex.clone()).await }; @@ -91,7 +123,7 @@ pub async fn consensus_init_task( Err(Error::NetworkOperationFailed) => { // Sync node again *node.validator.synced.write().await = false; - if !skip_sync { + if !config.skip_sync { sync_task(&node, checkpoint).await?; } else { *node.validator.synced.write().await = true; diff --git a/contrib/localnet/darkfid-five-nodes/darkfid0.toml b/contrib/localnet/darkfid-five-nodes/darkfid0.toml index 62e07dab3..6a3a46380 100644 --- a/contrib/localnet/darkfid-five-nodes/darkfid0.toml +++ b/contrib/localnet/darkfid-five-nodes/darkfid0.toml @@ -46,6 +46,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-five-nodes/darkfid1.toml b/contrib/localnet/darkfid-five-nodes/darkfid1.toml index 8a43fd245..6549740b7 100644 --- a/contrib/localnet/darkfid-five-nodes/darkfid1.toml +++ b/contrib/localnet/darkfid-five-nodes/darkfid1.toml @@ -46,6 +46,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-five-nodes/darkfid2.toml b/contrib/localnet/darkfid-five-nodes/darkfid2.toml index 5a66d4d7f..623061026 100644 --- a/contrib/localnet/darkfid-five-nodes/darkfid2.toml +++ b/contrib/localnet/darkfid-five-nodes/darkfid2.toml @@ -46,6 +46,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-five-nodes/darkfid3.toml b/contrib/localnet/darkfid-five-nodes/darkfid3.toml index 1b35fafc9..19f214009 100644 --- a/contrib/localnet/darkfid-five-nodes/darkfid3.toml +++ b/contrib/localnet/darkfid-five-nodes/darkfid3.toml @@ -46,6 +46,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-five-nodes/darkfid4.toml b/contrib/localnet/darkfid-five-nodes/darkfid4.toml index 4978a30cf..451bde259 100644 --- a/contrib/localnet/darkfid-five-nodes/darkfid4.toml +++ b/contrib/localnet/darkfid-five-nodes/darkfid4.toml @@ -46,6 +46,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-single-node/darkfid.toml b/contrib/localnet/darkfid-single-node/darkfid.toml index a3122ae81..e0cd42400 100644 --- a/contrib/localnet/darkfid-single-node/darkfid.toml +++ b/contrib/localnet/darkfid-single-node/darkfid.toml @@ -49,6 +49,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1718807405 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-small/darkfid0.toml b/contrib/localnet/darkfid-small/darkfid0.toml index 052c01a1e..9cd80afb9 100644 --- a/contrib/localnet/darkfid-small/darkfid0.toml +++ b/contrib/localnet/darkfid-small/darkfid0.toml @@ -46,6 +46,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-small/darkfid1.toml b/contrib/localnet/darkfid-small/darkfid1.toml index 757c39946..159326493 100644 --- a/contrib/localnet/darkfid-small/darkfid1.toml +++ b/contrib/localnet/darkfid-small/darkfid1.toml @@ -54,6 +54,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections diff --git a/contrib/localnet/darkfid-small/darkfid2.toml b/contrib/localnet/darkfid-small/darkfid2.toml index 465d78446..3a14f1276 100644 --- a/contrib/localnet/darkfid-small/darkfid2.toml +++ b/contrib/localnet/darkfid-small/darkfid2.toml @@ -41,6 +41,9 @@ skip_fees = false # Optional sync checkpoint hash #checkpoint = "" +# Optional bootstrap timestamp +#bootstrap = 1712581283 + ## Localnet P2P network settings [network_config."localnet".net] # P2P accept addresses the instance listens on for inbound connections