Skip to content

Commit d4b67bb

Browse files
authored
feat: wait for bitcoind to be at chain tip before starting service (#364)
* feat: wait for bitcoind to be at chain tip before starting service * fix: reset confirmations * chore: more logs
1 parent 21fcf46 commit d4b67bb

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

components/ordhook-core/src/service/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::db::{drop_block_data_from_all_dbs, open_all_dbs_rw};
3535
use crate::scan::bitcoin::process_block_with_predicates;
3636
use crate::service::observers::create_and_consolidate_chainhook_config_with_predicates;
3737
use crate::service::runloops::start_bitcoin_scan_runloop;
38+
use crate::utils::bitcoind::bitcoind_wait_for_chain_tip;
3839
use crate::utils::monitoring::{start_serving_prometheus_metrics, PrometheusMonitoring};
3940
use crate::{try_debug, try_error, try_info};
4041
use chainhook_sdk::chainhooks::bitcoin::BitcoinChainhookOccurrencePayload;
@@ -404,6 +405,7 @@ impl Service {
404405
}
405406

406407
pub async fn check_blocks_db_integrity(&mut self) -> Result<(), String> {
408+
bitcoind_wait_for_chain_tip(&self.config, &self.ctx);
407409
let (tip, missing_blocks) = {
408410
let blocks_db = open_blocks_db_with_retry(false, &self.config, &self.ctx);
409411

@@ -446,7 +448,10 @@ impl Service {
446448
&self,
447449
block_post_processor: Option<crossbeam_channel::Sender<BitcoinBlockData>>,
448450
) -> Result<(), String> {
449-
// 1: Catch up blocks DB so it is at the same height as the ordinals DB.
451+
// 0: Make sure bitcoind is synchronized.
452+
bitcoind_wait_for_chain_tip(&self.config, &self.ctx);
453+
454+
// 1: Catch up blocks DB so it is at least at the same height as the ordinals DB.
450455
if let Some((start_block, end_block)) = should_sync_rocks_db(&self.config, &self.ctx)? {
451456
let blocks_post_processor = start_block_archiving_processor(
452457
&self.config,
@@ -472,7 +477,8 @@ impl Service {
472477
.await?;
473478
}
474479

475-
// 2: Catch up ordinals DB until it reaches bitcoind block height. This will also advance blocks DB.
480+
// 2: Catch up ordinals DB until it reaches bitcoind block height. This will also advance blocks DB and BRC-20 DB if
481+
// enabled.
476482
let mut last_block_processed = 0;
477483
while let Some((start_block, end_block, speed)) =
478484
should_sync_ordhook_db(&self.config, &self.ctx)?
@@ -502,7 +508,6 @@ impl Service {
502508
&self.ctx,
503509
)
504510
.await?;
505-
506511
last_block_processed = end_block;
507512
}
508513

components/ordhook-core/src/utils/bitcoind.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
use std::{thread::sleep, time::Duration};
2+
13
use chainhook_sdk::{
24
bitcoincore_rpc::{Auth, Client, RpcApi},
35
utils::Context,
46
};
57

6-
use crate::{config::Config, try_error};
8+
use crate::{config::Config, try_error, try_info};
79

810
fn bitcoind_get_client(config: &Config, ctx: &Context) -> Client {
911
loop {
@@ -16,8 +18,8 @@ fn bitcoind_get_client(config: &Config, ctx: &Context) -> Client {
1618
return con;
1719
}
1820
Err(e) => {
19-
try_error!(ctx, "bitcoind unable to get client: {}", e.to_string());
20-
std::thread::sleep(std::time::Duration::from_secs(1));
21+
try_error!(ctx, "bitcoind: Unable to get client: {}", e.to_string());
22+
sleep(Duration::from_secs(1));
2123
}
2224
}
2325
}
@@ -34,11 +36,44 @@ pub fn bitcoind_get_block_height(config: &Config, ctx: &Context) -> u64 {
3436
Err(e) => {
3537
try_error!(
3638
ctx,
37-
"bitcoind unable to get block height: {}",
39+
"bitcoind: Unable to get block height: {}",
40+
e.to_string()
41+
);
42+
sleep(Duration::from_secs(1));
43+
}
44+
};
45+
}
46+
}
47+
48+
/// Checks if bitcoind is still synchronizing blocks and waits until it's finished if that is the case.
49+
pub fn bitcoind_wait_for_chain_tip(config: &Config, ctx: &Context) {
50+
let bitcoin_rpc = bitcoind_get_client(config, ctx);
51+
let mut confirmations = 0;
52+
loop {
53+
match bitcoin_rpc.get_blockchain_info() {
54+
Ok(result) => {
55+
if result.initial_block_download == false && result.blocks == result.headers {
56+
confirmations += 1;
57+
// Wait for 10 confirmations before declaring node is at chain tip, just in case it's still connecting to
58+
// peers.
59+
if confirmations == 10 {
60+
try_info!(ctx, "bitcoind: Chain tip reached");
61+
return;
62+
}
63+
try_info!(ctx, "bitcoind: Verifying chain tip");
64+
} else {
65+
confirmations = 0;
66+
try_info!(ctx, "bitcoind: Node has not reached chain tip, trying again");
67+
}
68+
}
69+
Err(e) => {
70+
try_error!(
71+
ctx,
72+
"bitcoind: Unable to check for chain tip: {}",
3873
e.to_string()
3974
);
40-
std::thread::sleep(std::time::Duration::from_secs(1));
4175
}
4276
};
77+
sleep(Duration::from_secs(1));
4378
}
4479
}

0 commit comments

Comments
 (0)