diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index 74f3ee56..d8a8af51 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -748,14 +748,28 @@ impl BitcoinD { self.make_node_request("getblockchaininfo", &[]) } - pub fn sync_progress(&self) -> f64 { + pub fn sync_progress(&self) -> SyncProgress { // TODO: don't harass lianad, be smarter like in revaultd. - roundup_progress( - self.block_chain_info() + 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 headers = chain_info + .get("headers") + .and_then(Json::as_u64) + .expect("No valid 'verificationprogress' in getblockchaininfo response?"); + let blocks = chain_info + .get("blocks") + .and_then(Json::as_u64) + .expect("No valid 'blocks' in getblockchaininfo response?"); + SyncProgress { + percentage, + headers, + blocks, + } } pub fn chain_tip(&self) -> BlockChainTip { @@ -1122,6 +1136,17 @@ impl BitcoinD { } } +/// Information about the block chain verification progress. +#[derive(Debug, Clone, Copy)] +pub struct SyncProgress { + /// Chain verification progress as a percentage between 0 and 1. + pub percentage: f64, + /// Headers count for the best known tip. + pub headers: u64, + /// Number of blocks validated toward the best known tip. + pub blocks: u64, +} + /// An entry in the 'listdescriptors' result. #[derive(Debug, Clone)] pub struct ListDescEntry { diff --git a/src/bitcoin/mod.rs b/src/bitcoin/mod.rs index b1d32fae..86bf5ccd 100644 --- a/src/bitcoin/mod.rs +++ b/src/bitcoin/mod.rs @@ -9,6 +9,7 @@ use crate::{ bitcoin::d::{BitcoindError, CachedTxGetter, LSBlockEntry}, descriptors, }; +pub use d::SyncProgress; use std::{fmt, sync}; @@ -42,8 +43,9 @@ pub trait BitcoinInterface: Send { fn genesis_block(&self) -> BlockChainTip; /// Get the progress of the block chain synchronization. - /// Returns a percentage between 0 and 1. - fn sync_progress(&self) -> f64; + /// Returns a rounded up percentage between 0 and 1. Use the `is_synced` method to be sure the + /// backend is completely synced to the best known tip. + fn sync_progress(&self) -> SyncProgress; /// Get the best block info. fn chain_tip(&self) -> BlockChainTip; @@ -117,7 +119,7 @@ impl BitcoinInterface for d::BitcoinD { BlockChainTip { hash, height } } - fn sync_progress(&self) -> f64 { + fn sync_progress(&self) -> SyncProgress { self.sync_progress() } @@ -333,7 +335,7 @@ impl BitcoinInterface for sync::Arc> self.lock().unwrap().genesis_block() } - fn sync_progress(&self) -> f64 { + fn sync_progress(&self) -> SyncProgress { self.lock().unwrap().sync_progress() } diff --git a/src/bitcoin/poller/looper.rs b/src/bitcoin/poller/looper.rs index b15684b3..e01bffde 100644 --- a/src/bitcoin/poller/looper.rs +++ b/src/bitcoin/poller/looper.rs @@ -1,5 +1,5 @@ use crate::{ - bitcoin::{BitcoinInterface, BlockChainTip, UTxO}, + bitcoin::{BitcoinInterface, BlockChainTip, SyncProgress, UTxO}, database::{Coin, DatabaseConnection, DatabaseInterface}, descriptors, }; @@ -356,12 +356,16 @@ pub fn looper( // Don't poll until the Bitcoin backend is fully synced. if !synced { - let sync_progress = bit.sync_progress(); + let SyncProgress { + percentage, + headers, + blocks, + } = bit.sync_progress(); log::info!( "Block chain synchronization progress: {:.2}%", - sync_progress * 100.0 + percentage * 100.0 ); - synced = sync_progress == 1.0; + synced = headers == blocks; if !synced { continue; } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index fb2c2b22..6f48c350 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(), + sync: self.bitcoin.sync_progress().percentage, descriptors: GetInfoDescriptors { main: self.config.main_descriptor.clone(), }, diff --git a/src/lib.rs b/src/lib.rs index 37a68284..5f58e04f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -671,7 +671,7 @@ mod tests { // Send them a response to 'getblockchaininfo' saying we are far from being synced fn complete_sync_check(server: &net::TcpListener) { let net_resp = [ - "HTTP/1.1 200\n\r\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"verificationprogress\":0.1}}\n".as_bytes(), + "HTTP/1.1 200\n\r\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"verificationprogress\":0.1,\"headers\":1000,\"blocks\":100}}\n".as_bytes(), ] .concat(); let (mut stream, _) = server.accept().unwrap(); diff --git a/src/testutils.rs b/src/testutils.rs index 3c7e3ea6..0d795637 100644 --- a/src/testutils.rs +++ b/src/testutils.rs @@ -1,5 +1,5 @@ use crate::{ - bitcoin::{BitcoinInterface, Block, BlockChainTip, UTxO}, + bitcoin::{BitcoinInterface, Block, BlockChainTip, SyncProgress, UTxO}, config::{BitcoinConfig, Config}, database::{BlockInfo, Coin, CoinStatus, DatabaseConnection, DatabaseInterface, LabelItem}, descriptors, DaemonHandle, @@ -42,8 +42,12 @@ impl BitcoinInterface for DummyBitcoind { BlockChainTip { hash, height: 0 } } - fn sync_progress(&self) -> f64 { - 1.0 + fn sync_progress(&self) -> SyncProgress { + SyncProgress { + percentage: 1.0, + headers: 1_000, + blocks: 1_000, + } } fn chain_tip(&self) -> BlockChainTip {