Skip to content
Open
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
7 changes: 5 additions & 2 deletions crates/bitcoind_rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ workspace = true

[dependencies]
bitcoin = { version = "0.32.0", default-features = false }
bitcoincore-rpc = { version = "0.19.0" }
bdk_bitcoind_client = { version = "0.1.0", default-features = false }
bdk_core = { path = "../core", version = "0.6.1", default-features = false }

[dev-dependencies]
Expand All @@ -26,9 +26,12 @@ bdk_testenv = { path = "../testenv" }
bdk_chain = { path = "../chain" }

[features]
default = ["std"]
default = ["std", "bitcoind_28_0"]
std = ["bitcoin/std", "bdk_core/std"]
serde = ["bitcoin/serde", "bdk_core/serde"]
bitcoind_28_0 = ["bdk_bitcoind_client/28_0"]
bitcoind_29_0 = ["bdk_bitcoind_client/29_0"]
bitcoind_30_0 = ["bdk_bitcoind_client/30_0"]

[[example]]
name = "filter_iter"
Expand Down
6 changes: 4 additions & 2 deletions crates/bitcoind_rpc/examples/filter_iter.rs
Copy link
Copy Markdown
Collaborator

@ValuedMammal ValuedMammal May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get this error when running the filter_iter example, don't know if it's something about my OS. I noticed during the transition from bitcoincore_rpc to bdk_bitcoind_client using bitreq. FWIW I don't have the same problem with SimpleHttpTransport because it can create a fresh tcp socket on the fly.

Matched block 205061
Matched block 208441
Error: JSON-RPC error: transport error: bitreq: Can't assign requested address (os error 49)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have noticed this randomly when running tests. Sometimes it passes, other times it fails.

Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ fn main() -> anyhow::Result<()> {
// Configure RPC client
let url = std::env::var("RPC_URL").context("must set RPC_URL")?;
let cookie = std::env::var("RPC_COOKIE").context("must set RPC_COOKIE")?;
let rpc_client =
bitcoincore_rpc::Client::new(&url, bitcoincore_rpc::Auth::CookieFile(cookie.into()))?;
let rpc_client = bdk_bitcoind_client::Client::with_auth(
&url,
bdk_bitcoind_client::Auth::CookieFile(cookie.into()),
)?;

// Initialize `FilterIter`
let mut spks = vec![];
Expand Down
39 changes: 15 additions & 24 deletions crates/bitcoind_rpc/src/bip158.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
//! [0]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki
//! [1]: https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki

use bdk_bitcoind_client;
use bdk_bitcoind_client::corepc_types::model::GetBlockHeaderVerbose;
use bdk_core::bitcoin;
use bdk_core::CheckPoint;
use bitcoin::BlockHash;
use bitcoin::{bip158::BlockFilter, Block, ScriptBuf};
use bitcoincore_rpc;
use bitcoincore_rpc::{json::GetBlockHeaderResult, RpcApi};

/// Type that returns Bitcoin blocks by matching a list of script pubkeys (SPKs) against a
/// [`bip158::BlockFilter`](bitcoin::bip158::BlockFilter).
///
/// * `FilterIter` talks to bitcoind via JSON-RPC interface, which is handled by the
/// [`bitcoincore_rpc::Client`].
/// [`bdk_bitcoind_client::Client`].
/// * Collect the script pubkeys (SPKs) you want to watch. These will usually correspond to wallet
/// addresses that have been handed out for receiving payments.
/// * Construct `FilterIter` with the RPC client, SPKs, and [`CheckPoint`]. The checkpoint tip
Expand All @@ -31,19 +31,19 @@ use bitcoincore_rpc::{json::GetBlockHeaderResult, RpcApi};
#[derive(Debug)]
pub struct FilterIter<'a> {
/// RPC client
client: &'a bitcoincore_rpc::Client,
client: &'a bdk_bitcoind_client::Client,
/// SPK inventory
spks: Vec<ScriptBuf>,
/// checkpoint
cp: CheckPoint<BlockHash>,
/// Header info, contains the prev and next hashes for each header.
header: Option<GetBlockHeaderResult>,
header: Option<GetBlockHeaderVerbose>,
}

impl<'a> FilterIter<'a> {
/// Construct [`FilterIter`] with checkpoint, RPC client and SPKs.
pub fn new(
client: &'a bitcoincore_rpc::Client,
client: &'a bdk_bitcoind_client::Client,
cp: CheckPoint,
spks: impl IntoIterator<Item = ScriptBuf>,
) -> Self {
Expand All @@ -58,10 +58,10 @@ impl<'a> FilterIter<'a> {
/// Return the agreement header with the remote node.
///
/// Error if no agreement header is found.
fn find_base(&self) -> Result<GetBlockHeaderResult, Error> {
fn find_base(&self) -> Result<GetBlockHeaderVerbose, Error> {
for cp in self.cp.iter() {
match self.client.get_block_header_info(&cp.hash()) {
Err(e) if is_not_found(&e) => continue,
match self.client.get_block_header_verbose(&cp.hash()) {
Err(e) if e.is_not_found_error() => continue,
Ok(header) if header.confirmations <= 0 => continue,
Ok(header) => return Ok(header),
Err(e) => return Err(Error::Rpc(e)),
Expand Down Expand Up @@ -111,20 +111,20 @@ impl Iterator for FilterIter<'_> {
None => return Ok(None),
};

let mut next_header = self.client.get_block_header_info(&next_hash)?;
let mut next_header = self.client.get_block_header_verbose(&next_hash)?;

// In case of a reorg, rewind by fetching headers of previous hashes until we find
// one with enough confirmations.
while next_header.confirmations < 0 {
let prev_hash = next_header
.previous_block_hash
.ok_or(Error::ReorgDepthExceeded)?;
let prev_header = self.client.get_block_header_info(&prev_hash)?;
let prev_header = self.client.get_block_header_verbose(&prev_hash)?;
next_header = prev_header;
}

next_hash = next_header.hash;
let next_height: u32 = next_header.height.try_into()?;
let next_height: u32 = next_header.height;

cp = cp.insert(next_height, next_hash);

Expand Down Expand Up @@ -153,7 +153,7 @@ impl Iterator for FilterIter<'_> {
#[derive(Debug)]
pub enum Error {
/// RPC error
Rpc(bitcoincore_rpc::Error),
Rpc(bdk_bitcoind_client::Error),
/// `bitcoin::bip158` error
Bip158(bitcoin::bip158::Error),
/// Max reorg depth exceeded.
Expand All @@ -175,8 +175,8 @@ impl core::fmt::Display for Error {

impl core::error::Error for Error {}

impl From<bitcoincore_rpc::Error> for Error {
fn from(e: bitcoincore_rpc::Error) -> Self {
impl From<bdk_bitcoind_client::Error> for Error {
fn from(e: bdk_bitcoind_client::Error) -> Self {
Self::Rpc(e)
}
}
Expand All @@ -186,12 +186,3 @@ impl From<core::num::TryFromIntError> for Error {
Self::TryFromInt(e)
}
}

/// Whether the RPC error is a "not found" error (code: `-5`).
fn is_not_found(e: &bitcoincore_rpc::Error) -> bool {
matches!(
e,
bitcoincore_rpc::Error::JsonRpc(bitcoincore_rpc::jsonrpc::Error::Rpc(e))
if e.code == -5
)
}
Loading
Loading