darkfid: optional bootstrap timestamp added

This commit is contained in:
skoupidi
2024-06-19 17:35:52 +03:00
parent 934d8f1a42
commit 79f9cd24c5
12 changed files with 100 additions and 19 deletions

View File

@@ -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

View File

@@ -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<String>,
#[structopt(long)]
/// Optional bootstrap timestamp
pub bootstrap: Option<u64>,
/// P2P network settings
#[structopt(flatten)]
pub net: SettingsOpt,
@@ -236,6 +240,12 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> 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<smol::Executor<'static>>) -> 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 {

View File

@@ -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<Darkfid>,
/// Auxiliary structure representing node consesus init task configuration
pub struct ConsensusInitTaskConfig {
skip_sync: bool,
checkpoint_height: Option<u32>,
checkpoint: Option<String>,
miner: bool,
recipient: Option<String>,
bootstrap: u64,
}
impl ConsensusInitTaskConfig {
pub fn new(
skip_sync: bool,
checkpoint_height: Option<u32>,
checkpoint: Option<String>,
miner: bool,
recipient: Option<String>,
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<Darkfid>,
config: ConsensusInitTaskConfig,
ex: Arc<smol::Executor<'static>>,
) -> 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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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