From 7ec10ad8c793200292eb4edaaf3162e5d21c629e Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Fri, 18 Jul 2025 08:50:49 +0000 Subject: [PATCH 1/3] feat: add optional `tracing` instrumentation --- crates/bitcoind_rpc/Cargo.toml | 2 + crates/bitcoind_rpc/src/lib.rs | 59 +++++++++- crates/electrum/Cargo.toml | 2 + crates/electrum/src/bdk_electrum_client.rs | 126 ++++++++++++++++++++- crates/esplora/Cargo.toml | 2 + crates/esplora/src/async_ext.rs | 35 ++++++ crates/esplora/src/blocking_ext.rs | 35 ++++++ 7 files changed, 258 insertions(+), 3 deletions(-) diff --git a/crates/bitcoind_rpc/Cargo.toml b/crates/bitcoind_rpc/Cargo.toml index bdece9800..0158f2f11 100644 --- a/crates/bitcoind_rpc/Cargo.toml +++ b/crates/bitcoind_rpc/Cargo.toml @@ -19,6 +19,7 @@ workspace = true bitcoin = { version = "0.32.0", default-features = false } bitcoincore-rpc = { version = "0.19.0" } bdk_core = { path = "../core", version = "0.6.1", default-features = false } +tracing = { version = "0.1", optional = true } [dev-dependencies] bdk_bitcoind_rpc = { path = "." } @@ -29,6 +30,7 @@ bdk_chain = { path = "../chain" } default = ["std"] std = ["bitcoin/std", "bdk_core/std"] serde = ["bitcoin/serde", "bdk_core/serde"] +tracing-logs = ["tracing"] [[example]] name = "filter_iter" diff --git a/crates/bitcoind_rpc/src/lib.rs b/crates/bitcoind_rpc/src/lib.rs index eb58018e9..de2d1c557 100644 --- a/crates/bitcoind_rpc/src/lib.rs +++ b/crates/bitcoind_rpc/src/lib.rs @@ -21,6 +21,9 @@ use bitcoin::{Block, BlockHash, Transaction, Txid}; use bitcoincore_rpc::{bitcoincore_rpc_json, RpcApi}; use core::ops::Deref; +#[cfg(feature = "tracing-logs")] +use tracing::trace; + pub mod bip158; pub use bitcoincore_rpc; @@ -124,6 +127,13 @@ where pub fn mempool_at(&mut self, sync_time: u64) -> Result { let client = &*self.client; + #[cfg(feature = "tracing-logs")] + trace!( + start_height = self.start_height, + sync_time = sync_time, + "enter mempool_at" + ); + let mut rpc_tip_height; let mut rpc_tip_hash; let mut rpc_mempool; @@ -164,6 +174,14 @@ where ..Default::default() }; + #[cfg(feature = "tracing-logs")] + trace!( + rpc_mempool_count = rpc_mempool_txids.len(), + rpc_height = rpc_tip_height, + rpc_block_hash = %rpc_tip_hash, + "fetched raw mempool" + ); + let at_tip = rpc_tip_height == self.last_cp.height() as u64 && rpc_tip_hash == self.last_cp.hash(); @@ -200,11 +218,23 @@ where /// Emit the next block height and block (if any). pub fn next_block(&mut self) -> Result>, bitcoincore_rpc::Error> { + #[cfg(feature = "tracing-logs")] + trace!( + last_block_height = self.last_block.as_ref().map(|r| r.height), + "enter next_block" + ); + if let Some((checkpoint, block)) = poll(self, move |hash, client| client.get_block(hash))? { // Stop tracking unconfirmed transactions that have been confirmed in this block. for tx in &block.txdata { self.mempool_snapshot.remove(&tx.compute_txid()); } + #[cfg(feature = "tracing-logs")] + trace!( + block_height = checkpoint.height(), + tx_count = block.txdata.len(), + "emit block" + ); return Ok(Some(BlockEvent { block, checkpoint })); } Ok(None) @@ -279,6 +309,13 @@ where C: Deref, C::Target: RpcApi, { + #[cfg(feature = "tracing-logs")] + trace!( + last_block_height = emitter.last_block.as_ref().map(|r| r.height), + start_height = emitter.start_height, + "enter poll_once" + ); + let client = &*emitter.client; if let Some(last_res) = &emitter.last_block { @@ -287,21 +324,35 @@ where let next_hash = client.get_block_hash(emitter.start_height as _)?; // make sure last emission is still in best chain if client.get_block_hash(last_res.height as _)? != last_res.hash { + #[cfg(feature = "tracing-logs")] + trace!("block not in best chain"); return Ok(PollResponse::BlockNotInBestChain); } next_hash } else { match last_res.nextblockhash { - None => return Ok(PollResponse::NoMoreBlocks), + None => { + #[cfg(feature = "tracing-logs")] + trace!("no more blocks"); + return Ok(PollResponse::NoMoreBlocks); + } Some(next_hash) => next_hash, } }; let res = client.get_block_info(&next_hash)?; if res.confirmations < 0 { + #[cfg(feature = "tracing-logs")] + trace!("block not in best chain"); return Ok(PollResponse::BlockNotInBestChain); } + #[cfg(feature = "tracing-logs")] + trace!( + height = res.height, + hash = %res.hash, + "agreement found" + ); return Ok(PollResponse::Block(res)); } @@ -321,6 +372,12 @@ where }; // agreement point found + #[cfg(feature = "tracing-logs")] + trace!( + "poll(): PollResponse::AgreementFound, height={}, hash={}", + res.height, + res.hash + ); return Ok(PollResponse::AgreementFound(res, cp)); } diff --git a/crates/electrum/Cargo.toml b/crates/electrum/Cargo.toml index 7ad0d6c3d..f4cce0d27 100644 --- a/crates/electrum/Cargo.toml +++ b/crates/electrum/Cargo.toml @@ -15,6 +15,7 @@ workspace = true [dependencies] bdk_core = { path = "../core", version = "0.6.1" } electrum-client = { version = "0.24.0", features = [ "proxy" ], default-features = false } +tracing = { version = "0.1", optional = true } [dev-dependencies] bdk_testenv = { path = "../testenv" } @@ -26,6 +27,7 @@ default = ["use-rustls"] use-rustls = ["electrum-client/use-rustls"] use-rustls-ring = ["electrum-client/use-rustls-ring"] use-openssl = ["electrum-client/use-openssl"] +tracing-logs = ["tracing"] [[test]] name = "test_electrum" diff --git a/crates/electrum/src/bdk_electrum_client.rs b/crates/electrum/src/bdk_electrum_client.rs index f5eee7a80..aa59255af 100644 --- a/crates/electrum/src/bdk_electrum_client.rs +++ b/crates/electrum/src/bdk_electrum_client.rs @@ -10,6 +10,9 @@ use electrum_client::{ElectrumApi, Error, HeaderNotification}; use std::convert::TryInto; use std::sync::{Arc, Mutex}; +#[cfg(feature = "tracing-logs")] +use tracing::{debug, trace, trace_span}; + /// We include a chain suffix of a certain length for the purpose of robustness. const CHAIN_SUFFIX_LENGTH: u32 = 8; @@ -72,11 +75,22 @@ impl BdkElectrumClient { let tx_cache = self.tx_cache.lock().unwrap(); if let Some(tx) = tx_cache.get(&txid) { + #[cfg(feature = "tracing-logs")] + trace!( + event = "tx_cache_hit", + txid = %txid, + ); return Ok(Arc::clone(tx)); } drop(tx_cache); + #[cfg(feature = "tracing-logs")] + trace!( + event = "tx_cache_miss", + txid = %txid, + ); + let tx = Arc::new(self.inner.transaction_get(&txid)?); self.tx_cache.lock().unwrap().insert(txid, Arc::clone(&tx)); @@ -121,6 +135,16 @@ impl BdkElectrumClient { let mut request: FullScanRequest = request.into(); let start_time = request.start_time(); + #[cfg(feature = "tracing-logs")] + let _span = trace_span!( + "bdk_electrum::full_scan", + event = "enter_full_scan", + stop_gap = stop_gap, + batch_size = batch_size, + fetch_prev = fetch_prev_txouts, + ) + .entered(); + let tip_and_latest_blocks = match request.chain_tip() { Some(chain_tip) => Some(fetch_tip_and_latest_blocks(&self.inner, chain_tip)?), None => None, @@ -204,6 +228,15 @@ impl BdkElectrumClient { let mut request: SyncRequest = request.into(); let start_time = request.start_time(); + #[cfg(feature = "tracing-logs")] + let _span = trace_span!( + "bdk_electrum::sync", + event = "enter_sync", + batch_size = batch_size, + fetch_prev = fetch_prev_txouts, + ) + .entered(); + let tip_and_latest_blocks = match request.chain_tip() { Some(chain_tip) => Some(fetch_tip_and_latest_blocks(&self.inner, chain_tip)?), None => None, @@ -283,10 +316,18 @@ impl BdkElectrumClient { let spks = (0..batch_size) .map_while(|_| spks_with_expected_txids.next()) .collect::>(); + #[cfg(feature = "tracing-logs")] + trace!(event = "script_history_batch", batch_size = spks.len(),); + if spks.is_empty() { + #[cfg(feature = "tracing-logs")] + trace!(event = "script_history_empty",); return Ok(last_active_index); } + #[cfg(feature = "tracing-logs")] + trace!(event = "spk_has_history",); + let spk_histories = self .inner .batch_script_get_history(spks.iter().map(|(_, s)| s.spk.as_script()))?; @@ -295,7 +336,15 @@ impl BdkElectrumClient { if spk_history.is_empty() { match unused_spk_count.checked_add(1) { Some(i) if i < stop_gap => unused_spk_count = i, - _ => return Ok(last_active_index), + _ => { + #[cfg(feature = "tracing-logs")] + trace!( + event = "gap_limit_reached", + unused_spk_count = unused_spk_count, + stop_gap = stop_gap, + ); + return Ok(last_active_index); + } }; } else { last_active_index = Some(spk_index); @@ -377,10 +426,21 @@ impl BdkElectrumClient { if !has_residing && res.tx_hash == outpoint.txid { has_residing = true; + #[cfg(feature = "tracing-logs")] + trace!( + event = "outpoint_reside", + outpoint = %outpoint, + ); tx_update.txs.push(Arc::clone(&tx)); match res.height.try_into() { // Returned heights 0 & -1 are reserved for unconfirmed txs. Ok(height) if height > 0 => { + #[cfg(feature = "tracing-logs")] + trace!( + event = "anchor_added_outpoint", + txid = %res.tx_hash, + height = height, + ); pending_anchors.push((res.tx_hash, height)); } _ => { @@ -396,13 +456,26 @@ impl BdkElectrumClient { .input .iter() .any(|txin| txin.previous_output == outpoint); - if !has_spending { + if has_spending { + #[cfg(feature = "tracing-logs")] + trace!( + event = "outpoint_spent", + outpoint = %outpoint, + spending_txid = %res.tx_hash, + ); + } else { continue; } tx_update.txs.push(Arc::clone(&res_tx)); match res.height.try_into() { // Returned heights 0 & -1 are reserved for unconfirmed txs. Ok(height) if height > 0 => { + #[cfg(feature = "tracing-logs")] + trace!( + event = "anchor_added_from_outpoint_resolution", + txid = %res.tx_hash, + height = height, + ); pending_anchors.push((res.tx_hash, height)); } _ => { @@ -437,9 +510,19 @@ impl BdkElectrumClient { .expect("tx must have an output") .clone(); txs.push((txid, tx)); + #[cfg(feature = "tracing-logs")] + trace!( + event = "fetched_tx_for_confirmation", + txid = %txid, + ); scripts.push(spk); } Err(electrum_client::Error::Protocol(_)) => { + #[cfg(feature = "tracing-logs")] + debug!( + event = "protocol_error", + txid = %txid, + ); continue; } Err(e) => return Err(e), @@ -457,6 +540,12 @@ impl BdkElectrumClient { match res.height.try_into() { // Returned heights 0 & -1 are reserved for unconfirmed txs. Ok(height) if height > 0 => { + #[cfg(feature = "tracing-logs")] + trace!( + event = "anchor_candidate_txid_history", + txid = %res.tx_hash, + height, + ); pending_anchors.push((tx.0, height)); } _ => { @@ -516,8 +605,20 @@ impl BdkElectrumClient { let h = height as u32; let hash = height_to_hash[&h]; if let Some(anchor) = anchor_cache.get(&(txid, hash)) { + #[cfg(feature = "tracing-logs")] + trace!( + event = "anchor_cache_hit", + txid = %txid, + height, + ); results.push((txid, *anchor)); } else { + #[cfg(feature = "tracing-logs")] + trace!( + event = "anchor_cache_miss", + txid = %txid, + height, + ); to_fetch.push((txid, height)); } } @@ -538,6 +639,12 @@ impl BdkElectrumClient { let mut valid = electrum_client::utils::validate_merkle_proof(&txid, &header.merkle_root, &proof); if !valid { + #[cfg(feature = "tracing-logs")] + debug!( + event = "merkle_validation_failed", + txid = %txid, + height, + ); header = self.inner.block_header(height)?; self.block_header_cache .lock() @@ -548,6 +655,14 @@ impl BdkElectrumClient { &header.merkle_root, &proof, ); + if valid { + #[cfg(feature = "tracing-logs")] + trace!( + event = "merkle_validated_retry", + txid = %txid, + height, + ); + } } // Build and cache the anchor if merkle proof is valid. @@ -564,6 +679,13 @@ impl BdkElectrumClient { .lock() .unwrap() .insert((txid, hash), anchor); + #[cfg(feature = "tracing-logs")] + trace!( + event = "anchor_inserted", + txid = %txid, + height , + hash = %hash, + ); results.push((txid, anchor)); } } diff --git a/crates/esplora/Cargo.toml b/crates/esplora/Cargo.toml index e4c553f77..6a176a1c1 100644 --- a/crates/esplora/Cargo.toml +++ b/crates/esplora/Cargo.toml @@ -19,6 +19,7 @@ bdk_core = { path = "../core", version = "0.6.1", default-features = false } esplora-client = { version = "0.12.1", default-features = false } async-trait = { version = "0.1.66", optional = true } futures = { version = "0.3.26", optional = true } +tracing = { version = "0.1", optional = true } [dev-dependencies] esplora-client = { version = "0.12.0" } @@ -38,6 +39,7 @@ blocking = ["esplora-client/blocking"] blocking-https = ["blocking", "esplora-client/blocking-https"] blocking-https-rustls = ["blocking", "esplora-client/blocking-https-rustls"] blocking-https-native = ["blocking", "esplora-client/blocking-https-native"] +tracing-logs = ["tracing"] [[test]] name = "blocking_ext" diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index c0e55ab50..16f796b47 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -12,6 +12,9 @@ use futures::{stream::FuturesOrdered, TryStreamExt}; use crate::{insert_anchor_or_seen_at_from_status, insert_prevouts}; +#[cfg(feature = "tracing-logs")] +use tracing::trace; + /// [`esplora_client::Error`] type Error = Box; @@ -68,6 +71,9 @@ where let start_time = request.start_time(); let keychains = request.keychains(); + #[cfg(feature = "tracing-logs")] + trace!(stop_gap, parallel_requests, "enter full_scan"); + let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { Some(fetch_latest_blocks(self).await?) @@ -119,6 +125,9 @@ where let mut request: SyncRequest = request.into(); let start_time = request.start_time(); + #[cfg(feature = "tracing-logs")] + trace!(parallel_requests, "enter sync"); + let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { Some(fetch_latest_blocks(self).await?) @@ -183,6 +192,9 @@ where async fn fetch_latest_blocks( client: &esplora_client::AsyncClient, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!("fetch_latest_blocks()"); + Ok(client .get_blocks(None) .await? @@ -199,6 +211,9 @@ async fn fetch_block( latest_blocks: &BTreeMap, height: u32, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!(height, "fetch_block()"); + if let Some(&hash) = latest_blocks.get(&height) { return Ok(Some(hash)); } @@ -230,6 +245,9 @@ async fn chain_update( local_tip: &CheckPoint, anchors: &BTreeSet<(ConfirmationBlockTime, Txid)>, ) -> Result { + #[cfg(feature = "tracing-logs")] + trace!("chain_update()"); + let mut point_of_agreement = None; let mut local_cp_hash = local_tip.hash(); let mut conflicts = vec![]; @@ -311,6 +329,14 @@ where I: Iterator> + Send, S: Sleeper + Clone + Send + Sync, { + #[cfg(feature = "tracing-logs")] + trace!( + start_time, + stop_gap, + parallel_requests, + "fetch_txs_with_keychain_spks" + ); + type TxsOfSpkIndex = (u32, Vec, HashSet); let mut update = TxUpdate::::default(); @@ -402,6 +428,9 @@ where I::IntoIter: Send, S: Sleeper + Clone + Send + Sync, { + #[cfg(feature = "tracing-logs")] + trace!(start_time, parallel_requests, "fetch_txs_with_spks"); + fetch_txs_with_keychain_spks( client, start_time, @@ -432,6 +461,9 @@ where I::IntoIter: Send, S: Sleeper + Clone + Send + Sync, { + #[cfg(feature = "tracing-logs")] + trace!(start_time, parallel_requests, "fetch_txs_with_txids"); + let mut update = TxUpdate::::default(); // Only fetch for non-inserted txs. let mut txids = txids @@ -484,6 +516,9 @@ where I::IntoIter: Send, S: Sleeper + Clone + Send + Sync, { + #[cfg(feature = "tracing-logs")] + trace!(start_time, parallel_requests, "fetch_txs_with_outpoints"); + let outpoints = outpoints.into_iter().collect::>(); let mut update = TxUpdate::::default(); diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index 5a52b7a09..30f8c66bb 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -11,6 +11,9 @@ use std::thread::JoinHandle; use crate::{insert_anchor_or_seen_at_from_status, insert_prevouts}; +#[cfg(feature = "tracing-logs")] +use tracing::trace; + /// [`esplora_client::Error`] pub type Error = Box; @@ -58,6 +61,9 @@ impl EsploraExt for esplora_client::BlockingClient { let mut request: FullScanRequest = request.into(); let start_time = request.start_time(); + #[cfg(feature = "tracing-logs")] + trace!(stop_gap, parallel_requests, "enter full_scan"); + let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { Some(fetch_latest_blocks(self)?) @@ -111,6 +117,9 @@ impl EsploraExt for esplora_client::BlockingClient { let mut request: SyncRequest = request.into(); let start_time = request.start_time(); + #[cfg(feature = "tracing-logs")] + trace!(parallel_requests, "enter sync"); + let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { Some(fetch_latest_blocks(self)?) @@ -169,6 +178,9 @@ impl EsploraExt for esplora_client::BlockingClient { fn fetch_latest_blocks( client: &esplora_client::BlockingClient, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!("fetch_latest_blocks()"); + Ok(client .get_blocks(None)? .into_iter() @@ -184,6 +196,9 @@ fn fetch_block( latest_blocks: &BTreeMap, height: u32, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!(height, "fetch_block()"); + if let Some(&hash) = latest_blocks.get(&height) { return Ok(Some(hash)); } @@ -215,6 +230,9 @@ fn chain_update( local_tip: &CheckPoint, anchors: &BTreeSet<(ConfirmationBlockTime, Txid)>, ) -> Result { + #[cfg(feature = "tracing-logs")] + trace!("chain_update()"); + let mut point_of_agreement = None; let mut local_cp_hash = local_tip.hash(); let mut conflicts = vec![]; @@ -279,6 +297,14 @@ fn fetch_txs_with_keychain_spks stop_gap: usize, parallel_requests: usize, ) -> Result<(TxUpdate, Option), Error> { + #[cfg(feature = "tracing-logs")] + trace!( + start_time, + stop_gap, + parallel_requests, + "fetch_txs_with_keychain_spks" + ); + type TxsOfSpkIndex = (u32, Vec, HashSet); let mut update = TxUpdate::::default(); @@ -366,6 +392,9 @@ fn fetch_txs_with_spks>( spks: I, parallel_requests: usize, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!(start_time, parallel_requests, "fetch_txs_with_spks"); + fetch_txs_with_keychain_spks( client, start_time, @@ -390,6 +419,9 @@ fn fetch_txs_with_txids>( txids: I, parallel_requests: usize, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!(start_time, parallel_requests, "fetch_txs_with_txids"); + let mut update = TxUpdate::::default(); // Only fetch for non-inserted txs. let mut txids = txids @@ -443,6 +475,9 @@ fn fetch_txs_with_outpoints>( outpoints: I, parallel_requests: usize, ) -> Result, Error> { + #[cfg(feature = "tracing-logs")] + trace!(start_time, parallel_requests, "fetch_txs_with_outpoints"); + let outpoints = outpoints.into_iter().collect::>(); let mut update = TxUpdate::::default(); From 301496315fea81cbdf3c17b10bddcc22914bf261 Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Tue, 5 Aug 2025 09:55:06 +0000 Subject: [PATCH 2/3] feat: introduce `bdk_common` crate with log macros --- Cargo.toml | 1 + crates/bitcoind_rpc/Cargo.toml | 4 +- crates/bitcoind_rpc/src/lib.rs | 37 +++----- crates/common/Cargo.toml | 17 ++++ crates/common/README.md | 11 +++ crates/common/src/lib.rs | 5 ++ crates/common/src/log.rs | 99 ++++++++++++++++++++++ crates/electrum/Cargo.toml | 4 +- crates/electrum/src/bdk_electrum_client.rs | 63 +++++--------- crates/electrum/src/lib.rs | 4 + crates/esplora/Cargo.toml | 4 +- crates/esplora/src/async_ext.rs | 30 ++----- crates/esplora/src/blocking_ext.rs | 30 ++----- crates/esplora/src/lib.rs | 4 + justfile | 4 + 15 files changed, 203 insertions(+), 114 deletions(-) create mode 100644 crates/common/Cargo.toml create mode 100644 crates/common/README.md create mode 100644 crates/common/src/lib.rs create mode 100644 crates/common/src/log.rs diff --git a/Cargo.toml b/Cargo.toml index d505c1a0a..966a66ac0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "crates/esplora", "crates/bitcoind_rpc", "crates/testenv", + "crates/common", "examples/example_cli", "examples/example_electrum", "examples/example_esplora", diff --git a/crates/bitcoind_rpc/Cargo.toml b/crates/bitcoind_rpc/Cargo.toml index 0158f2f11..3e6fd18be 100644 --- a/crates/bitcoind_rpc/Cargo.toml +++ b/crates/bitcoind_rpc/Cargo.toml @@ -19,7 +19,7 @@ workspace = true bitcoin = { version = "0.32.0", default-features = false } bitcoincore-rpc = { version = "0.19.0" } bdk_core = { path = "../core", version = "0.6.1", default-features = false } -tracing = { version = "0.1", optional = true } +bdk_common = { path = "../common" } [dev-dependencies] bdk_bitcoind_rpc = { path = "." } @@ -30,7 +30,7 @@ bdk_chain = { path = "../chain" } default = ["std"] std = ["bitcoin/std", "bdk_core/std"] serde = ["bitcoin/serde", "bdk_core/serde"] -tracing-logs = ["tracing"] +log = ["bdk_common/log"] [[example]] name = "filter_iter" diff --git a/crates/bitcoind_rpc/src/lib.rs b/crates/bitcoind_rpc/src/lib.rs index de2d1c557..a6e84c88d 100644 --- a/crates/bitcoind_rpc/src/lib.rs +++ b/crates/bitcoind_rpc/src/lib.rs @@ -14,6 +14,10 @@ #[macro_use] extern crate alloc; +#[allow(unused_imports)] +#[macro_use] +extern crate bdk_common; + use alloc::sync::Arc; use bdk_core::collections::{HashMap, HashSet}; use bdk_core::{BlockId, CheckPoint}; @@ -21,9 +25,6 @@ use bitcoin::{Block, BlockHash, Transaction, Txid}; use bitcoincore_rpc::{bitcoincore_rpc_json, RpcApi}; use core::ops::Deref; -#[cfg(feature = "tracing-logs")] -use tracing::trace; - pub mod bip158; pub use bitcoincore_rpc; @@ -127,8 +128,7 @@ where pub fn mempool_at(&mut self, sync_time: u64) -> Result { let client = &*self.client; - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( start_height = self.start_height, sync_time = sync_time, "enter mempool_at" @@ -174,8 +174,7 @@ where ..Default::default() }; - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( rpc_mempool_count = rpc_mempool_txids.len(), rpc_height = rpc_tip_height, rpc_block_hash = %rpc_tip_hash, @@ -218,8 +217,7 @@ where /// Emit the next block height and block (if any). pub fn next_block(&mut self) -> Result>, bitcoincore_rpc::Error> { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( last_block_height = self.last_block.as_ref().map(|r| r.height), "enter next_block" ); @@ -229,8 +227,7 @@ where for tx in &block.txdata { self.mempool_snapshot.remove(&tx.compute_txid()); } - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( block_height = checkpoint.height(), tx_count = block.txdata.len(), "emit block" @@ -309,8 +306,7 @@ where C: Deref, C::Target: RpcApi, { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( last_block_height = emitter.last_block.as_ref().map(|r| r.height), start_height = emitter.start_height, "enter poll_once" @@ -324,16 +320,14 @@ where let next_hash = client.get_block_hash(emitter.start_height as _)?; // make sure last emission is still in best chain if client.get_block_hash(last_res.height as _)? != last_res.hash { - #[cfg(feature = "tracing-logs")] - trace!("block not in best chain"); + log_trace!("block not in best chain"); return Ok(PollResponse::BlockNotInBestChain); } next_hash } else { match last_res.nextblockhash { None => { - #[cfg(feature = "tracing-logs")] - trace!("no more blocks"); + log_trace!("no more blocks"); return Ok(PollResponse::NoMoreBlocks); } Some(next_hash) => next_hash, @@ -342,13 +336,11 @@ where let res = client.get_block_info(&next_hash)?; if res.confirmations < 0 { - #[cfg(feature = "tracing-logs")] - trace!("block not in best chain"); + log_trace!("block not in best chain"); return Ok(PollResponse::BlockNotInBestChain); } - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( height = res.height, hash = %res.hash, "agreement found" @@ -372,8 +364,7 @@ where }; // agreement point found - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( "poll(): PollResponse::AgreementFound, height={}, hash={}", res.height, res.hash diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml new file mode 100644 index 000000000..9cced771e --- /dev/null +++ b/crates/common/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "bdk_common" +version = "0.1.0" +edition = "2021" +rust-version = "1.63" +homepage = "https://bitcoindevkit.org" +repository = "https://github.com/bitcoindevkit/bdk" +description = "Shared utilities and macros for BDK chain sources." +license = "MIT OR Apache-2.0" +readme = "README.md" +publish = false + +[dependencies] +tracing = { version = "0.1", optional = true } + +[features] +log = ["tracing"] diff --git a/crates/common/README.md b/crates/common/README.md new file mode 100644 index 000000000..4741dd769 --- /dev/null +++ b/crates/common/README.md @@ -0,0 +1,11 @@ +# BDK Common + +`bdk_common` is an **internal-only** crate providing zero-overhead, feature-gated logging macros for +all BDK chain-sync crates. Enabling the single `log` feature pulls in `tracing = "0.1"`. When it’s +off, the macros compile to no-ops and there’s no runtime or dependency impact. + +## Features + +- **`log`** (off by default) + – Re-exports `tracing` and enables logging. + – When disabled, `log_trace!`, `log_debug!`, `log_info!`, `log_warn!`, `log_error!`, and `log_span!` expand to nothing. diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs new file mode 100644 index 000000000..3ffd25cb0 --- /dev/null +++ b/crates/common/src/lib.rs @@ -0,0 +1,5 @@ +#[cfg(feature = "log")] +pub use tracing; + +#[macro_use] +mod log; diff --git a/crates/common/src/log.rs b/crates/common/src/log.rs new file mode 100644 index 000000000..433ce95ac --- /dev/null +++ b/crates/common/src/log.rs @@ -0,0 +1,99 @@ +/// Trace-level logging. Expands to `tracing::trace!()` when the `log` feature is enabled, +/// otherwise into a no-op. +#[cfg(feature = "log")] +#[macro_export] +macro_rules! log_trace { + ($($tt:tt)*) => { + $crate::tracing::trace!($($tt)*); + }; +} +#[cfg(not(feature = "log"))] +#[macro_export] +macro_rules! log_trace { + ($($tt:tt)*) => {}; +} + +/// Trace-level span. Expands to `tracing::trace_span!()` when the `log` feature is enabled, +/// otherwise to a dummy no-op span whose `.entered()` does nothing. +#[cfg(feature = "log")] +#[macro_export] +macro_rules! log_span { + ( $($tts:tt)* ) => { + $crate::tracing::trace_span!($($tts)*) + }; +} +#[cfg(not(feature = "log"))] +#[macro_export] +macro_rules! log_span { + ( $($tts:tt)* ) => {{ + struct NoopSpan; + impl NoopSpan { + #[allow(dead_code)] + pub fn entered(self) -> NoopEntered { + NoopEntered + } + } + struct NoopEntered; + NoopSpan + }}; +} + +/// Debug-level logging. Expands to `tracing::debug!()` when the `log` feature is enabled, +/// otherwise into a no-op. +#[cfg(feature = "log")] +#[macro_export] +macro_rules! log_debug { + ($($tt:tt)*) => { + $crate::tracing::debug!($($tt)*); + }; +} +#[cfg(not(feature = "log"))] +#[macro_export] +macro_rules! log_debug { + ($($tt:tt)*) => {}; +} + +/// Info-level logging. Expands to `tracing::info!()` when the `log` feature is enabled, +/// otherwise into a no-op. +#[cfg(feature = "log")] +#[macro_export] +macro_rules! log_info { + ($($tt:tt)*) => { + $crate::tracing::info!($($tt)*); + }; +} +#[cfg(not(feature = "log"))] +#[macro_export] +macro_rules! log_info { + ($($tt:tt)*) => {}; +} + +/// Warn-level logging. Expands to `tracing::warn!()` when the `log` feature is enabled, +/// otherwise into a no-op. +#[cfg(feature = "log")] +#[macro_export] +macro_rules! log_warn { + ($($tt:tt)*) => { + $crate::tracing::warn!($($tt)*); + }; +} +#[cfg(not(feature = "log"))] +#[macro_export] +macro_rules! log_warn { + ($($tt:tt)*) => {}; +} + +/// Error-level logging. Expands to `tracing::error!()` when the `log` feature is enabled, +/// otherwise into a no-op. +#[cfg(feature = "log")] +#[macro_export] +macro_rules! log_error { + ($($tt:tt)*) => { + $crate::tracing::error!($($tt)*); + }; +} +#[cfg(not(feature = "log"))] +#[macro_export] +macro_rules! log_error { + ($($tt:tt)*) => {}; +} diff --git a/crates/electrum/Cargo.toml b/crates/electrum/Cargo.toml index f4cce0d27..43c446c4f 100644 --- a/crates/electrum/Cargo.toml +++ b/crates/electrum/Cargo.toml @@ -14,8 +14,8 @@ workspace = true [dependencies] bdk_core = { path = "../core", version = "0.6.1" } +bdk_common = { path = "../common" } electrum-client = { version = "0.24.0", features = [ "proxy" ], default-features = false } -tracing = { version = "0.1", optional = true } [dev-dependencies] bdk_testenv = { path = "../testenv" } @@ -27,7 +27,7 @@ default = ["use-rustls"] use-rustls = ["electrum-client/use-rustls"] use-rustls-ring = ["electrum-client/use-rustls-ring"] use-openssl = ["electrum-client/use-openssl"] -tracing-logs = ["tracing"] +log = ["bdk_common/log"] [[test]] name = "test_electrum" diff --git a/crates/electrum/src/bdk_electrum_client.rs b/crates/electrum/src/bdk_electrum_client.rs index aa59255af..92e0ad059 100644 --- a/crates/electrum/src/bdk_electrum_client.rs +++ b/crates/electrum/src/bdk_electrum_client.rs @@ -10,9 +10,6 @@ use electrum_client::{ElectrumApi, Error, HeaderNotification}; use std::convert::TryInto; use std::sync::{Arc, Mutex}; -#[cfg(feature = "tracing-logs")] -use tracing::{debug, trace, trace_span}; - /// We include a chain suffix of a certain length for the purpose of robustness. const CHAIN_SUFFIX_LENGTH: u32 = 8; @@ -75,8 +72,7 @@ impl BdkElectrumClient { let tx_cache = self.tx_cache.lock().unwrap(); if let Some(tx) = tx_cache.get(&txid) { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "tx_cache_hit", txid = %txid, ); @@ -85,8 +81,7 @@ impl BdkElectrumClient { drop(tx_cache); - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "tx_cache_miss", txid = %txid, ); @@ -135,8 +130,7 @@ impl BdkElectrumClient { let mut request: FullScanRequest = request.into(); let start_time = request.start_time(); - #[cfg(feature = "tracing-logs")] - let _span = trace_span!( + let _span = log_span!( "bdk_electrum::full_scan", event = "enter_full_scan", stop_gap = stop_gap, @@ -228,8 +222,7 @@ impl BdkElectrumClient { let mut request: SyncRequest = request.into(); let start_time = request.start_time(); - #[cfg(feature = "tracing-logs")] - let _span = trace_span!( + let _span = log_span!( "bdk_electrum::sync", event = "enter_sync", batch_size = batch_size, @@ -316,17 +309,14 @@ impl BdkElectrumClient { let spks = (0..batch_size) .map_while(|_| spks_with_expected_txids.next()) .collect::>(); - #[cfg(feature = "tracing-logs")] - trace!(event = "script_history_batch", batch_size = spks.len(),); + log_trace!(event = "script_history_batch", batch_size = spks.len(),); if spks.is_empty() { - #[cfg(feature = "tracing-logs")] - trace!(event = "script_history_empty",); + log_trace!(event = "script_history_empty",); return Ok(last_active_index); } - #[cfg(feature = "tracing-logs")] - trace!(event = "spk_has_history",); + log_trace!(event = "spk_has_history",); let spk_histories = self .inner @@ -337,8 +327,7 @@ impl BdkElectrumClient { match unused_spk_count.checked_add(1) { Some(i) if i < stop_gap => unused_spk_count = i, _ => { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "gap_limit_reached", unused_spk_count = unused_spk_count, stop_gap = stop_gap, @@ -426,8 +415,7 @@ impl BdkElectrumClient { if !has_residing && res.tx_hash == outpoint.txid { has_residing = true; - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "outpoint_reside", outpoint = %outpoint, ); @@ -435,8 +423,7 @@ impl BdkElectrumClient { match res.height.try_into() { // Returned heights 0 & -1 are reserved for unconfirmed txs. Ok(height) if height > 0 => { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "anchor_added_outpoint", txid = %res.tx_hash, height = height, @@ -457,8 +444,7 @@ impl BdkElectrumClient { .iter() .any(|txin| txin.previous_output == outpoint); if has_spending { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "outpoint_spent", outpoint = %outpoint, spending_txid = %res.tx_hash, @@ -470,8 +456,7 @@ impl BdkElectrumClient { match res.height.try_into() { // Returned heights 0 & -1 are reserved for unconfirmed txs. Ok(height) if height > 0 => { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "anchor_added_from_outpoint_resolution", txid = %res.tx_hash, height = height, @@ -510,16 +495,14 @@ impl BdkElectrumClient { .expect("tx must have an output") .clone(); txs.push((txid, tx)); - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "fetched_tx_for_confirmation", txid = %txid, ); scripts.push(spk); } Err(electrum_client::Error::Protocol(_)) => { - #[cfg(feature = "tracing-logs")] - debug!( + log_debug!( event = "protocol_error", txid = %txid, ); @@ -540,8 +523,7 @@ impl BdkElectrumClient { match res.height.try_into() { // Returned heights 0 & -1 are reserved for unconfirmed txs. Ok(height) if height > 0 => { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "anchor_candidate_txid_history", txid = %res.tx_hash, height, @@ -605,16 +587,14 @@ impl BdkElectrumClient { let h = height as u32; let hash = height_to_hash[&h]; if let Some(anchor) = anchor_cache.get(&(txid, hash)) { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "anchor_cache_hit", txid = %txid, height, ); results.push((txid, *anchor)); } else { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "anchor_cache_miss", txid = %txid, height, @@ -639,8 +619,7 @@ impl BdkElectrumClient { let mut valid = electrum_client::utils::validate_merkle_proof(&txid, &header.merkle_root, &proof); if !valid { - #[cfg(feature = "tracing-logs")] - debug!( + log_debug!( event = "merkle_validation_failed", txid = %txid, height, @@ -656,8 +635,7 @@ impl BdkElectrumClient { &proof, ); if valid { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "merkle_validated_retry", txid = %txid, height, @@ -679,8 +657,7 @@ impl BdkElectrumClient { .lock() .unwrap() .insert((txid, hash), anchor); - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( event = "anchor_inserted", txid = %txid, height , diff --git a/crates/electrum/src/lib.rs b/crates/electrum/src/lib.rs index 9c1d9f452..96c6453a3 100644 --- a/crates/electrum/src/lib.rs +++ b/crates/electrum/src/lib.rs @@ -19,6 +19,10 @@ #![cfg_attr(coverage_nightly, feature(coverage_attribute))] #![warn(missing_docs)] +#[allow(unused_imports)] +#[macro_use] +extern crate bdk_common; + mod bdk_electrum_client; pub use bdk_electrum_client::*; diff --git a/crates/esplora/Cargo.toml b/crates/esplora/Cargo.toml index 6a176a1c1..d5e4bf259 100644 --- a/crates/esplora/Cargo.toml +++ b/crates/esplora/Cargo.toml @@ -16,10 +16,10 @@ workspace = true [dependencies] bdk_core = { path = "../core", version = "0.6.1", default-features = false } +bdk_common = { path = "../common" } esplora-client = { version = "0.12.1", default-features = false } async-trait = { version = "0.1.66", optional = true } futures = { version = "0.3.26", optional = true } -tracing = { version = "0.1", optional = true } [dev-dependencies] esplora-client = { version = "0.12.0" } @@ -39,7 +39,7 @@ blocking = ["esplora-client/blocking"] blocking-https = ["blocking", "esplora-client/blocking-https"] blocking-https-rustls = ["blocking", "esplora-client/blocking-https-rustls"] blocking-https-native = ["blocking", "esplora-client/blocking-https-native"] -tracing-logs = ["tracing"] +log = ["bdk_common/log"] [[test]] name = "blocking_ext" diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index 16f796b47..4a99064d7 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -12,9 +12,6 @@ use futures::{stream::FuturesOrdered, TryStreamExt}; use crate::{insert_anchor_or_seen_at_from_status, insert_prevouts}; -#[cfg(feature = "tracing-logs")] -use tracing::trace; - /// [`esplora_client::Error`] type Error = Box; @@ -71,8 +68,7 @@ where let start_time = request.start_time(); let keychains = request.keychains(); - #[cfg(feature = "tracing-logs")] - trace!(stop_gap, parallel_requests, "enter full_scan"); + log_trace!(stop_gap, parallel_requests, "enter full_scan"); let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { @@ -125,8 +121,7 @@ where let mut request: SyncRequest = request.into(); let start_time = request.start_time(); - #[cfg(feature = "tracing-logs")] - trace!(parallel_requests, "enter sync"); + log_trace!(parallel_requests, "enter sync"); let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { @@ -192,8 +187,7 @@ where async fn fetch_latest_blocks( client: &esplora_client::AsyncClient, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!("fetch_latest_blocks()"); + log_trace!("fetch_latest_blocks()"); Ok(client .get_blocks(None) @@ -211,8 +205,7 @@ async fn fetch_block( latest_blocks: &BTreeMap, height: u32, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!(height, "fetch_block()"); + log_trace!(height, "fetch_block()"); if let Some(&hash) = latest_blocks.get(&height) { return Ok(Some(hash)); @@ -245,8 +238,7 @@ async fn chain_update( local_tip: &CheckPoint, anchors: &BTreeSet<(ConfirmationBlockTime, Txid)>, ) -> Result { - #[cfg(feature = "tracing-logs")] - trace!("chain_update()"); + log_trace!("chain_update()"); let mut point_of_agreement = None; let mut local_cp_hash = local_tip.hash(); @@ -329,8 +321,7 @@ where I: Iterator> + Send, S: Sleeper + Clone + Send + Sync, { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( start_time, stop_gap, parallel_requests, @@ -428,8 +419,7 @@ where I::IntoIter: Send, S: Sleeper + Clone + Send + Sync, { - #[cfg(feature = "tracing-logs")] - trace!(start_time, parallel_requests, "fetch_txs_with_spks"); + log_trace!(start_time, parallel_requests, "fetch_txs_with_spks"); fetch_txs_with_keychain_spks( client, @@ -461,8 +451,7 @@ where I::IntoIter: Send, S: Sleeper + Clone + Send + Sync, { - #[cfg(feature = "tracing-logs")] - trace!(start_time, parallel_requests, "fetch_txs_with_txids"); + log_trace!(start_time, parallel_requests, "fetch_txs_with_txids"); let mut update = TxUpdate::::default(); // Only fetch for non-inserted txs. @@ -516,8 +505,7 @@ where I::IntoIter: Send, S: Sleeper + Clone + Send + Sync, { - #[cfg(feature = "tracing-logs")] - trace!(start_time, parallel_requests, "fetch_txs_with_outpoints"); + log_trace!(start_time, parallel_requests, "fetch_txs_with_outpoints"); let outpoints = outpoints.into_iter().collect::>(); let mut update = TxUpdate::::default(); diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index 30f8c66bb..aac39434a 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -11,9 +11,6 @@ use std::thread::JoinHandle; use crate::{insert_anchor_or_seen_at_from_status, insert_prevouts}; -#[cfg(feature = "tracing-logs")] -use tracing::trace; - /// [`esplora_client::Error`] pub type Error = Box; @@ -61,8 +58,7 @@ impl EsploraExt for esplora_client::BlockingClient { let mut request: FullScanRequest = request.into(); let start_time = request.start_time(); - #[cfg(feature = "tracing-logs")] - trace!(stop_gap, parallel_requests, "enter full_scan"); + log_trace!(stop_gap, parallel_requests, "enter full_scan"); let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { @@ -117,8 +113,7 @@ impl EsploraExt for esplora_client::BlockingClient { let mut request: SyncRequest = request.into(); let start_time = request.start_time(); - #[cfg(feature = "tracing-logs")] - trace!(parallel_requests, "enter sync"); + log_trace!(parallel_requests, "enter sync"); let chain_tip = request.chain_tip(); let latest_blocks = if chain_tip.is_some() { @@ -178,8 +173,7 @@ impl EsploraExt for esplora_client::BlockingClient { fn fetch_latest_blocks( client: &esplora_client::BlockingClient, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!("fetch_latest_blocks()"); + log_trace!("fetch_latest_blocks()"); Ok(client .get_blocks(None)? @@ -196,8 +190,7 @@ fn fetch_block( latest_blocks: &BTreeMap, height: u32, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!(height, "fetch_block()"); + log_trace!(height, "fetch_block()"); if let Some(&hash) = latest_blocks.get(&height) { return Ok(Some(hash)); @@ -230,8 +223,7 @@ fn chain_update( local_tip: &CheckPoint, anchors: &BTreeSet<(ConfirmationBlockTime, Txid)>, ) -> Result { - #[cfg(feature = "tracing-logs")] - trace!("chain_update()"); + log_trace!("chain_update()"); let mut point_of_agreement = None; let mut local_cp_hash = local_tip.hash(); @@ -297,8 +289,7 @@ fn fetch_txs_with_keychain_spks stop_gap: usize, parallel_requests: usize, ) -> Result<(TxUpdate, Option), Error> { - #[cfg(feature = "tracing-logs")] - trace!( + log_trace!( start_time, stop_gap, parallel_requests, @@ -392,8 +383,7 @@ fn fetch_txs_with_spks>( spks: I, parallel_requests: usize, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!(start_time, parallel_requests, "fetch_txs_with_spks"); + log_trace!(start_time, parallel_requests, "fetch_txs_with_spks"); fetch_txs_with_keychain_spks( client, @@ -419,8 +409,7 @@ fn fetch_txs_with_txids>( txids: I, parallel_requests: usize, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!(start_time, parallel_requests, "fetch_txs_with_txids"); + log_trace!(start_time, parallel_requests, "fetch_txs_with_txids"); let mut update = TxUpdate::::default(); // Only fetch for non-inserted txs. @@ -475,8 +464,7 @@ fn fetch_txs_with_outpoints>( outpoints: I, parallel_requests: usize, ) -> Result, Error> { - #[cfg(feature = "tracing-logs")] - trace!(start_time, parallel_requests, "fetch_txs_with_outpoints"); + log_trace!(start_time, parallel_requests, "fetch_txs_with_outpoints"); let outpoints = outpoints.into_iter().collect::>(); let mut update = TxUpdate::::default(); diff --git a/crates/esplora/src/lib.rs b/crates/esplora/src/lib.rs index 60b4f1eb3..1ccb14e49 100644 --- a/crates/esplora/src/lib.rs +++ b/crates/esplora/src/lib.rs @@ -27,6 +27,10 @@ use esplora_client::TxStatus; pub use esplora_client; +#[allow(unused_imports)] +#[macro_use] +extern crate bdk_common; + #[cfg(feature = "blocking")] mod blocking_ext; #[cfg(feature = "blocking")] diff --git a/justfile b/justfile index b5ca94d16..76a31e57f 100644 --- a/justfile +++ b/justfile @@ -33,6 +33,7 @@ test: @just _test-esplora @just _test-file_store @just _test-testenv + @just _test-common _test-bitcoind_rpc: cargo test -p bdk_bitcoind_rpc --all-features @@ -55,5 +56,8 @@ _test-file_store: _test-testenv: cargo test -p bdk_testenv --all-features +_test-common: + cargo test -p bdk_common --all-features + # Run pre-push suite: format, check, and test pre-push: fmt check test From f4c90328fa33e8faac34e08b8cf2a290eadd9d67 Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Tue, 5 Aug 2025 10:01:46 +0000 Subject: [PATCH 3/3] fix(ci): pin `tracing-attributes` for msrv --- ci/pin-msrv.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/pin-msrv.sh b/ci/pin-msrv.sh index 17253eed1..b076b75da 100755 --- a/ci/pin-msrv.sh +++ b/ci/pin-msrv.sh @@ -29,6 +29,7 @@ cargo update -p base64ct --precise "1.6.0" cargo update -p minreq --precise "2.13.2" cargo update -p tracing-core --precise "0.1.33" cargo update -p webpki-roots@1.0.2 --precise "1.0.1" +cargo update -p tracing-attributes --precise "0.1.28" cargo update -p rayon --precise "1.10.0" cargo update -p rayon-core --precise "1.12.1" cargo update -p socket2@0.6.0 --precise "0.5.10"