diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index d8a8af51..539ff308 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -751,12 +751,10 @@ impl BitcoinD { pub fn sync_progress(&self) -> SyncProgress { // TODO: don't harass lianad, be smarter like in revaultd. let chain_info = self.block_chain_info(); - let percentage = roundup_progress( - chain_info - .get("verificationprogress") - .and_then(Json::as_f64) - .expect("No valid 'verificationprogress' in getblockchaininfo response?"), - ); + let percentage = chain_info + .get("verificationprogress") + .and_then(Json::as_f64) + .expect("No valid 'verificationprogress' in getblockchaininfo response?"); let headers = chain_info .get("headers") .and_then(Json::as_u64) @@ -1140,13 +1138,39 @@ impl BitcoinD { #[derive(Debug, Clone, Copy)] pub struct SyncProgress { /// Chain verification progress as a percentage between 0 and 1. - pub percentage: f64, + percentage: f64, /// Headers count for the best known tip. pub headers: u64, /// Number of blocks validated toward the best known tip. pub blocks: u64, } +impl SyncProgress { + pub fn new(percentage: f64, headers: u64, blocks: u64) -> Self { + Self { + percentage, + headers, + blocks, + } + } + + /// Get the verification progress, roundup up to to three decimal places. This will not return + /// 1.0 (ie 100% verification progress) until the verification is complete. + pub fn rounded_up_progress(&self) -> f64 { + let progress = roundup_progress(self.percentage); + if progress == 1.0 && self.blocks != self.headers { + // Don't return a 100% progress until we are actually done syncing. + 0.999 + } else { + progress + } + } + + pub fn is_complete(&self) -> bool { + self.rounded_up_progress() == 1.0 + } +} + /// An entry in the 'listdescriptors' result. #[derive(Debug, Clone)] pub struct ListDescEntry { diff --git a/src/bitcoin/poller/looper.rs b/src/bitcoin/poller/looper.rs index e01bffde..9f3fe4b2 100644 --- a/src/bitcoin/poller/looper.rs +++ b/src/bitcoin/poller/looper.rs @@ -1,5 +1,5 @@ use crate::{ - bitcoin::{BitcoinInterface, BlockChainTip, SyncProgress, UTxO}, + bitcoin::{BitcoinInterface, BlockChainTip, UTxO}, database::{Coin, DatabaseConnection, DatabaseInterface}, descriptors, }; @@ -356,16 +356,12 @@ pub fn looper( // Don't poll until the Bitcoin backend is fully synced. if !synced { - let SyncProgress { - percentage, - headers, - blocks, - } = bit.sync_progress(); + let progress = bit.sync_progress(); log::info!( "Block chain synchronization progress: {:.2}%", - percentage * 100.0 + progress.rounded_up_progress() * 100.0 ); - synced = headers == blocks; + synced = progress.is_complete(); if !synced { continue; } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 6f48c350..0bdf09e8 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -263,7 +263,7 @@ impl DaemonControl { version: VERSION.to_string(), network: self.config.bitcoin_config.network, block_height, - sync: self.bitcoin.sync_progress().percentage, + sync: self.bitcoin.sync_progress().rounded_up_progress(), descriptors: GetInfoDescriptors { main: self.config.main_descriptor.clone(), }, diff --git a/src/testutils.rs b/src/testutils.rs index 0d795637..c9b44f13 100644 --- a/src/testutils.rs +++ b/src/testutils.rs @@ -43,11 +43,7 @@ impl BitcoinInterface for DummyBitcoind { } fn sync_progress(&self) -> SyncProgress { - SyncProgress { - percentage: 1.0, - headers: 1_000, - blocks: 1_000, - } + SyncProgress::new(1.0, 1_000, 1_000) } fn chain_tip(&self) -> BlockChainTip {