Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: validate and wait for bitcoind block height responses #340

Merged
merged 2 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 2 additions & 25 deletions components/ordhook-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::config::file::ConfigFile;
use crate::config::generator::generate_config;
use clap::{Parser, Subcommand};
use hiro_system_kit;
use ordhook::chainhook_sdk::bitcoincore_rpc::{Auth, Client, RpcApi};
use ordhook::chainhook_sdk::chainhooks::types::{
BitcoinChainhookSpecification, HttpHook, InscriptionFeedData, OrdinalsMetaProtocol,
};
Expand Down Expand Up @@ -35,6 +34,7 @@ use ordhook::download::download_ordinals_dataset_if_required;
use ordhook::scan::bitcoin::scan_bitcoin_chainstate_via_rpc_using_predicate;
use ordhook::service::observers::initialize_observers_db;
use ordhook::service::{start_observer_forwarding, Service};
use ordhook::utils::bitcoind::bitcoind_get_block_height;
use ordhook::{hex, initialize_db};
use reqwest::Client as HttpClient;
use std::collections::HashSet;
Expand Down Expand Up @@ -553,7 +553,7 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
ctx.expect_logger(),
"Checking {}...", config.network.bitcoind_rpc_url
);
let tip = check_bitcoind_connection(&config).await?;
let tip = bitcoind_get_block_height(&config, ctx);
if let Some(highest_desired) = block_range.pop_back() {
if tip < highest_desired {
error!(ctx.expect_logger(), "Unable to scan desired block range: underlying bitcoind synchronized until block #{} ", tip);
Expand Down Expand Up @@ -1035,29 +1035,6 @@ pub fn build_predicate_from_cli(
Ok(predicate)
}

pub async fn check_bitcoind_connection(config: &Config) -> Result<u64, String> {
let auth = Auth::UserPass(
config.network.bitcoind_rpc_username.clone(),
config.network.bitcoind_rpc_password.clone(),
);

let bitcoin_rpc = match Client::new(&config.network.bitcoind_rpc_url, auth) {
Ok(con) => con,
Err(message) => {
return Err(format!("unable to connect to bitcoind: {}", message));
}
};

let end_block = match bitcoin_rpc.get_blockchain_info() {
Ok(result) => result.blocks,
Err(e) => {
return Err(format!("unable to connect to bitcoind: {}", e));
}
};

Ok(end_block)
}

fn parse_blocks_heights_spec(
blocks_interval: &Option<String>,
blocks: &Option<String>,
Expand Down
30 changes: 3 additions & 27 deletions components/ordhook-core/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ use std::hash::BuildHasherDefault;
use std::ops::Div;
use std::path::PathBuf;

use chainhook_sdk::{
bitcoincore_rpc::{Auth, Client, RpcApi},
utils::Context,
};
use chainhook_sdk::utils::Context;

use crate::{
config::{Config, LogConfig, MetaProtocolsConfig, ResourcesConfig},
db::{find_pinned_block_bytes_at_block_height, open_ordhook_db_conn_rocks_db_loop},
db::{find_pinned_block_bytes_at_block_height, open_ordhook_db_conn_rocks_db_loop}, utils::bitcoind::bitcoind_get_block_height,
};

use crate::db::{
Expand Down Expand Up @@ -144,18 +141,6 @@ pub fn should_sync_ordhook_db(
config: &Config,
ctx: &Context,
) -> Result<Option<(u64, u64, usize)>, String> {
let auth = Auth::UserPass(
config.network.bitcoind_rpc_username.clone(),
config.network.bitcoind_rpc_password.clone(),
);

let bitcoin_rpc = match Client::new(&config.network.bitcoind_rpc_url, auth) {
Ok(con) => con,
Err(message) => {
return Err(format!("Bitcoin RPC error: {}", message.to_string()));
}
};

let blocks_db = open_ordhook_db_conn_rocks_db_loop(
true,
&config.expected_cache_path(),
Expand Down Expand Up @@ -186,17 +171,8 @@ pub fn should_sync_ordhook_db(
}
};

let end_block = match bitcoin_rpc.get_blockchain_info() {
Ok(result) => result.blocks,
Err(e) => {
return Err(format!(
"unable to retrieve Bitcoin chain tip ({})",
e.to_string()
));
}
};

// TODO: Gracefully handle Regtest, Testnet and Signet
let end_block = bitcoind_get_block_height(config, ctx);
let (mut end_block, speed) = if start_block < 200_000 {
(end_block.min(200_000), 10_000)
} else if start_block < 550_000 {
Expand Down
3 changes: 1 addition & 2 deletions components/ordhook-core/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ use chainhook_sdk::{
};

use crate::{
config::Config,
core::{
meta_protocols::brc20::db::{delete_activity_in_block_range, open_readwrite_brc20_db_conn},
meta_protocols::brc20::db::delete_activity_in_block_range,
protocol::inscription_parsing::{
get_inscriptions_revealed_in_block, get_inscriptions_transferred_in_block,
},
Expand Down
46 changes: 10 additions & 36 deletions components/ordhook-core/src/scan/bitcoin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::config::Config;
use crate::core::meta_protocols::brc20::brc20_activation_height;
use crate::core::meta_protocols::brc20::db::open_readonly_brc20_db_conn;
use crate::core::protocol::inscription_parsing::{
get_inscriptions_revealed_in_block, get_inscriptions_transferred_in_block,
Expand All @@ -11,8 +10,7 @@ use crate::download::download_ordinals_dataset_if_required;
use crate::service::observers::{
open_readwrite_observers_db_conn_or_panic, update_observer_progress,
};
use chainhook_sdk::bitcoincore_rpc::RpcApi;
use chainhook_sdk::bitcoincore_rpc::{Auth, Client};
use crate::utils::bitcoind::bitcoind_get_block_height;
use chainhook_sdk::chainhooks::bitcoin::{
evaluate_bitcoin_chainhooks_on_chain_event, handle_bitcoin_hook_action,
BitcoinChainhookOccurrence, BitcoinTriggerChainhook,
Expand All @@ -37,18 +35,6 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
ctx: &Context,
) -> Result<(), String> {
let _ = download_ordinals_dataset_if_required(config, ctx).await;

let auth = Auth::UserPass(
config.network.bitcoind_rpc_username.clone(),
config.network.bitcoind_rpc_password.clone(),
);

let bitcoin_rpc = match Client::new(&config.network.bitcoind_rpc_url, auth) {
Ok(con) => con,
Err(message) => {
return Err(format!("Bitcoin RPC error: {}", message.to_string()));
}
};
let mut floating_end_block = false;

let block_heights_to_scan_res = if let Some(ref blocks) = predicate_spec.blocks {
Expand All @@ -65,15 +51,7 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
};
let (end_block, update_end_block) = match predicate_spec.end_block {
Some(end_block) => (end_block, false),
None => match bitcoin_rpc.get_blockchain_info() {
Ok(result) => (result.blocks, true),
Err(e) => {
return Err(format!(
"unable to retrieve Bitcoin chain tip ({})",
e.to_string()
));
}
},
None => (bitcoind_get_block_height(config, ctx), true),
};
floating_end_block = update_end_block;
BlockHeights::BlockRange(start_block, end_block).get_sorted_entries()
Expand Down Expand Up @@ -195,20 +173,16 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
)
}
if block_heights_to_scan.is_empty() && floating_end_block {
let new_tip = match bitcoin_rpc.get_blockchain_info() {
Ok(result) => match predicate_spec.end_block {
Some(end_block) => {
if end_block > result.blocks {
result.blocks
} else {
end_block
}
let bitcoind_chain_tip = bitcoind_get_block_height(config, ctx);
let new_tip = match predicate_spec.end_block {
Some(end_block) => {
if end_block > bitcoind_chain_tip {
bitcoind_chain_tip
} else {
end_block
}
None => result.blocks,
},
Err(_e) => {
continue;
}
None => bitcoind_chain_tip,
};

for entry in (current_block_height + 1)..new_tip {
Expand Down
41 changes: 41 additions & 0 deletions components/ordhook-core/src/utils/bitcoind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use chainhook_sdk::{bitcoincore_rpc::{Auth, Client, RpcApi}, utils::Context};

use crate::{config::Config, try_error};

fn bitcoind_get_client(config: &Config, ctx: &Context) -> Client {
loop {
let auth = Auth::UserPass(
config.network.bitcoind_rpc_username.clone(),
config.network.bitcoind_rpc_password.clone(),
);
match Client::new(&config.network.bitcoind_rpc_url, auth) {
Ok(con) => {
return con;
}
Err(e) => {
try_error!(ctx, "bitcoind unable to get client: {}", e.to_string());
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
}
}

/// Retrieves the block height from bitcoind.
pub fn bitcoind_get_block_height(config: &Config, ctx: &Context) -> u64 {
let bitcoin_rpc = bitcoind_get_client(config, ctx);
loop {
match bitcoin_rpc.get_blockchain_info() {
Ok(result) => {
return result.blocks;
}
Err(e) => {
try_error!(
ctx,
"bitcoind unable to get block height: {}",
e.to_string()
);
std::thread::sleep(std::time::Duration::from_secs(1));
}
};
}
}
39 changes: 39 additions & 0 deletions components/ordhook-core/src/utils/logger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#[macro_export]
macro_rules! try_info {
($a:expr, $tag:expr, $($args:tt)*) => {
$a.try_log(|l| info!(l, $tag, $($args)*));
};
($a:expr, $tag:expr) => {
$a.try_log(|l| info!(l, $tag));
};
}

#[macro_export]
macro_rules! try_debug {
($a:expr, $tag:expr, $($args:tt)*) => {
$a.try_log(|l| debug!(l, $tag, $($args)*));
};
($a:expr, $tag:expr) => {
$a.try_log(|l| debug!(l, $tag));
};
}

#[macro_export]
macro_rules! try_warn {
($a:expr, $tag:expr, $($args:tt)*) => {
$a.try_log(|l| warn!(l, $tag, $($args)*));
};
($a:expr, $tag:expr) => {
$a.try_log(|l| warn!(l, $tag));
};
}

#[macro_export]
macro_rules! try_error {
($a:expr, $tag:expr, $($args:tt)*) => {
$a.try_log(|l| error!(l, $tag, $($args)*));
};
($a:expr, $tag:expr) => {
$a.try_log(|l| error!(l, $tag));
};
}
3 changes: 3 additions & 0 deletions components/ordhook-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
pub mod bitcoind;
pub mod logger;

use std::{
fs,
io::{Read, Write},
Expand Down
Loading