bitcoin: make sure we are *completely* synced before starting up
When not in IBD but catching up to the latest tip, our rounding up of verificationprogress makes us start while bitcoind is still kind of far from being caught up. Make sure it doesn't happen by not returning until bitcoind validated all the blocks we've fetched the headers for.
This commit is contained in:
parent
03fe06fd1f
commit
f687145c1e
@ -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 {
|
||||
|
||||
@ -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<sync::Mutex<dyn BitcoinInterface + 'static>>
|
||||
self.lock().unwrap().genesis_block()
|
||||
}
|
||||
|
||||
fn sync_progress(&self) -> f64 {
|
||||
fn sync_progress(&self) -> SyncProgress {
|
||||
self.lock().unwrap().sync_progress()
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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(),
|
||||
},
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user