From 594db648808a627998271abcad32e91642d2d9d1 Mon Sep 17 00:00:00 2001 From: Leonardo Lima Date: Fri, 21 Mar 2025 12:03:36 -0300 Subject: [PATCH 1/4] deps(bdk_testenv): bump `electrsd` to `0.34.0` --- crates/testenv/Cargo.toml | 4 +- crates/testenv/src/lib.rs | 107 +++++++++++++++++++------------------- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/crates/testenv/Cargo.toml b/crates/testenv/Cargo.toml index 2a707fe32..ec9a9bd32 100644 --- a/crates/testenv/Cargo.toml +++ b/crates/testenv/Cargo.toml @@ -17,14 +17,14 @@ workspace = true [dependencies] bdk_chain = { path = "../chain", version = "0.23.1", default-features = false } -electrsd = { version = "0.28.0", features = [ "legacy" ], default-features = false } +electrsd = { version = "0.35.0", features = [ "legacy" ], default-features = false } [dev-dependencies] bdk_testenv = { path = "." } [features] default = ["std", "download"] -download = ["electrsd/bitcoind_25_0", "electrsd/esplora_a33e97e1"] +download = ["electrsd/corepc-node_28_1", "electrsd/esplora_a33e97e1"] std = ["bdk_chain/std"] serde = ["bdk_chain/serde"] diff --git a/crates/testenv/src/lib.rs b/crates/testenv/src/lib.rs index 7572fbf4b..e78421225 100644 --- a/crates/testenv/src/lib.rs +++ b/crates/testenv/src/lib.rs @@ -5,21 +5,17 @@ pub mod utils; use bdk_chain::{ bitcoin::{ address::NetworkChecked, block::Header, hash_types::TxMerkleNode, hashes::Hash, - secp256k1::rand::random, transaction, Address, Amount, Block, BlockHash, CompactTarget, - ScriptBuf, ScriptHash, Transaction, TxIn, TxOut, Txid, + secp256k1::rand::random, transaction, Address, Amount, Block, BlockHash, ScriptBuf, + ScriptHash, Transaction, TxIn, TxOut, Txid, }, local_chain::CheckPoint, }; -use bitcoincore_rpc::{ - bitcoincore_rpc_json::{GetBlockTemplateModes, GetBlockTemplateRules}, - RpcApi, -}; -use electrsd::bitcoind::anyhow::Context; +use electrsd::corepc_node::{anyhow::Context, TemplateRequest, TemplateRules}; pub use electrsd; -pub use electrsd::bitcoind; -pub use electrsd::bitcoind::anyhow; -pub use electrsd::bitcoind::bitcoincore_rpc; +pub use electrsd::corepc_client; +pub use electrsd::corepc_node; +pub use electrsd::corepc_node::anyhow; pub use electrsd::electrum_client; use electrsd::electrum_client::ElectrumApi; use std::time::Duration; @@ -27,7 +23,7 @@ use std::time::Duration; /// Struct for running a regtest environment with a single `bitcoind` node with an `electrs` /// instance connected to it. pub struct TestEnv { - pub bitcoind: electrsd::bitcoind::BitcoinD, + pub bitcoind: electrsd::corepc_node::Node, pub electrsd: electrsd::ElectrsD, } @@ -35,7 +31,7 @@ pub struct TestEnv { #[derive(Debug)] pub struct Config<'a> { /// [`bitcoind::Conf`] - pub bitcoind: bitcoind::Conf<'a>, + pub bitcoind: corepc_node::Conf<'a>, /// [`electrsd::Conf`] pub electrsd: electrsd::Conf<'a>, } @@ -45,7 +41,7 @@ impl Default for Config<'_> { /// which is required for testing `bdk_esplora`. fn default() -> Self { Self { - bitcoind: bitcoind::Conf::default(), + bitcoind: corepc_node::Conf::default(), electrsd: { let mut conf = electrsd::Conf::default(); conf.http_enabled = true; @@ -65,11 +61,11 @@ impl TestEnv { pub fn new_with_config(config: Config) -> anyhow::Result { let bitcoind_exe = match std::env::var("BITCOIND_EXE") { Ok(path) => path, - Err(_) => bitcoind::downloaded_exe_path().context( + Err(_) => corepc_node::downloaded_exe_path().context( "you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature", )?, }; - let bitcoind = bitcoind::BitcoinD::with_conf(bitcoind_exe, &config.bitcoind)?; + let bitcoind = corepc_node::Node::with_conf(bitcoind_exe, &config.bitcoind)?; let electrs_exe = match std::env::var("ELECTRS_EXE") { Ok(path) => path, @@ -87,7 +83,7 @@ impl TestEnv { } /// Exposes the [`RpcApi`] calls from [`bitcoincore_rpc`]. - pub fn rpc_client(&self) -> &impl RpcApi { + pub fn rpc_client(&self) -> &corepc_node::Client { &self.bitcoind.client } @@ -118,26 +114,27 @@ impl TestEnv { ) -> anyhow::Result> { let coinbase_address = match address { Some(address) => address, - None => self - .bitcoind - .client - .get_new_address(None, None)? - .assume_checked(), + None => self.bitcoind.client.new_address()?, }; let block_hashes = self .bitcoind .client - .generate_to_address(count as _, &coinbase_address)?; + .generate_to_address(count as _, &coinbase_address)? + .into_model()? + .0; Ok(block_hashes) } /// Mine a block that is guaranteed to be empty even with transactions in the mempool. pub fn mine_empty_block(&self) -> anyhow::Result<(usize, BlockHash)> { - let bt = self.bitcoind.client.get_block_template( - GetBlockTemplateModes::Template, - &[GetBlockTemplateRules::SegWit], - &[], - )?; + let request = TemplateRequest { + rules: vec![TemplateRules::Segwit], + }; + let bt = self + .bitcoind + .client + .get_block_template(&request)? + .into_model()?; let txdata = vec![Transaction { version: transaction::Version::ONE, @@ -146,7 +143,7 @@ impl TestEnv { previous_output: bdk_chain::bitcoin::OutPoint::default(), script_sig: ScriptBuf::builder() .push_int(bt.height as _) - // randomn number so that re-mining creates unique block + // random number so that re-mining creates unique block .push_int(random()) .into_script(), sequence: bdk_chain::bitcoin::Sequence::default(), @@ -158,19 +155,16 @@ impl TestEnv { }], }]; - let bits: [u8; 4] = bt - .bits - .clone() - .try_into() - .expect("rpc provided us with invalid bits"); - let mut block = Block { header: Header { - version: bdk_chain::bitcoin::block::Version::default(), + version: bt.version, prev_blockhash: bt.previous_block_hash, merkle_root: TxMerkleNode::all_zeros(), - time: Ord::max(bt.min_time, std::time::UNIX_EPOCH.elapsed()?.as_secs()) as u32, - bits: CompactTarget::from_consensus(u32::from_be_bytes(bits)), + time: Ord::max( + bt.min_time, + std::time::UNIX_EPOCH.elapsed()?.as_secs() as u32, + ), + bits: bt.bits, nonce: 0, }, txdata, @@ -186,6 +180,7 @@ impl TestEnv { } self.bitcoind.client.submit_block(&block)?; + Ok((bt.height as usize, block.block_hash())) } @@ -238,18 +233,16 @@ impl TestEnv { /// Invalidate a number of blocks of a given size `count`. pub fn invalidate_blocks(&self, count: usize) -> anyhow::Result<()> { - let mut hash = self.bitcoind.client.get_best_block_hash()?; + let mut hash = self.bitcoind.client.get_best_block_hash()?.block_hash()?; for _ in 0..count { - let prev_hash = self - .bitcoind - .client - .get_block_info(&hash)? - .previousblockhash; - self.bitcoind.client.invalidate_block(&hash)?; - match prev_hash { - Some(prev_hash) => hash = prev_hash, - None => break, - } + let prev_hash = self.bitcoind.client.get_block(hash)?.header.prev_blockhash; + self.bitcoind.client.invalidate_block(hash)?; + hash = prev_hash + // TODO: (@leonardo) It requires a double check if there is any side-effect with this + // break removal. match prev_hash { + // Some(prev_hash) => hash = prev_hash, + // None => break, + // } } Ok(()) } @@ -290,7 +283,8 @@ impl TestEnv { let txid = self .bitcoind .client - .send_to_address(address, amount, None, None, None, None, None, None)?; + .send_to_address(address, amount)? + .txid()?; Ok(txid) } @@ -301,14 +295,19 @@ impl TestEnv { .client .get_block_hash(height as u64) .ok() - .map(|hash| (height, hash)) + .map(|get_block_hash| { + let hash = get_block_hash + .block_hash() + .expect("should `successfully convert to `BlockHash` from `GetBlockHash`"); + (height, hash) + }) })) .expect("must craft tip") } /// Get the genesis hash of the blockchain. pub fn genesis_hash(&self) -> anyhow::Result { - let hash = self.bitcoind.client.get_block_hash(0)?; + let hash = self.bitcoind.client.get_block_hash(0)?.into_model()?.0; Ok(hash) } } @@ -318,7 +317,7 @@ impl TestEnv { mod test { use crate::TestEnv; use core::time::Duration; - use electrsd::bitcoind::{anyhow::Result, bitcoincore_rpc::RpcApi}; + use electrsd::corepc_node::anyhow::Result; /// This checks that reorgs initiated by `bitcoind` is detected by our `electrsd` instance. #[test] @@ -328,7 +327,7 @@ mod test { // Mine some blocks. env.mine_blocks(101, None)?; env.wait_until_electrum_sees_block(Duration::from_secs(6))?; - let height = env.bitcoind.client.get_block_count()?; + let height = env.bitcoind.client.get_block_count()?.into_model().0; let blocks = (0..=height) .map(|i| env.bitcoind.client.get_block_hash(i)) .collect::, _>>()?; @@ -336,7 +335,7 @@ mod test { // Perform reorg on six blocks. env.reorg(6)?; env.wait_until_electrum_sees_block(Duration::from_secs(6))?; - let reorged_height = env.bitcoind.client.get_block_count()?; + let reorged_height = env.bitcoind.client.get_block_count()?.into_model().0; let reorged_blocks = (0..=height) .map(|i| env.bitcoind.client.get_block_hash(i)) .collect::, _>>()?; From 9453d331ace6ca6c800a1ac6fe6f480bba9e2e37 Mon Sep 17 00:00:00 2001 From: valued mammal Date: Fri, 21 Nov 2025 19:36:58 -0500 Subject: [PATCH 2/4] tests(bdk_bitcoind_rpc): add/use new `ClientExit` - add `ClientExt` trait to it's own common module. - update the `bdk_bitcoind_rpc` lib.rs tests to use `ClientExt`. - update the `bdk_bitcoind_rpc` test_emitter.rs tests to use `ClientExt`. - update the `bdk_bitcoind_rpc` test_filter_iter.rs tests to use `ClientExt`. --- crates/bitcoind_rpc/src/lib.rs | 13 ++- crates/bitcoind_rpc/tests/common/mod.rs | 20 ++++ crates/bitcoind_rpc/tests/test_emitter.rs | 109 +++++++++++------- crates/bitcoind_rpc/tests/test_filter_iter.rs | 27 +++-- 4 files changed, 114 insertions(+), 55 deletions(-) create mode 100644 crates/bitcoind_rpc/tests/common/mod.rs diff --git a/crates/bitcoind_rpc/src/lib.rs b/crates/bitcoind_rpc/src/lib.rs index 30fc556be..901a6b516 100644 --- a/crates/bitcoind_rpc/src/lib.rs +++ b/crates/bitcoind_rpc/src/lib.rs @@ -399,7 +399,7 @@ impl BitcoindRpcErrorExt for bitcoincore_rpc::Error { #[cfg(test)] #[cfg_attr(coverage_nightly, coverage(off))] mod test { - use crate::{bitcoincore_rpc::RpcApi, Emitter, NO_EXPECTED_MEMPOOL_TXS}; + use crate::{Emitter, NO_EXPECTED_MEMPOOL_TXS}; use bdk_chain::local_chain::LocalChain; use bdk_testenv::{anyhow, TestEnv}; use bitcoin::{hashes::Hash, Address, Amount, ScriptBuf, Txid, WScriptHash}; @@ -408,10 +408,17 @@ mod test { #[test] fn test_expected_mempool_txids_accumulate_and_remove() -> anyhow::Result<()> { let env = TestEnv::new()?; - let chain = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?).0; + let (chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let chain_tip = chain.tip(); + + // TODO: (@oleonardolima) We should use the `ClientExt` trait instead. + let mut bitcoincore_rpc_client = bitcoincore_rpc::Client::new( + &env.bitcoind.rpc_url(), + bitcoincore_rpc::Auth::CookieFile(env.bitcoind.workdir().join("regtest/.cookie")), + )?; + let mut emitter = Emitter::new( - env.rpc_client(), + &mut bitcoincore_rpc_client, chain_tip.clone(), 1, NO_EXPECTED_MEMPOOL_TXS, diff --git a/crates/bitcoind_rpc/tests/common/mod.rs b/crates/bitcoind_rpc/tests/common/mod.rs new file mode 100644 index 000000000..bbd914cca --- /dev/null +++ b/crates/bitcoind_rpc/tests/common/mod.rs @@ -0,0 +1,20 @@ +use bdk_testenv::anyhow; +use bdk_testenv::TestEnv; + +/// This trait is used for testing. It allows creating a new [`bitcoincore_rpc::Client`] connected +/// to the instance of bitcoind running in the test environment. This way the `TestEnv` and the +/// `Emitter` aren't required to share the same client. In the future when we no longer depend on +/// `bitcoincore-rpc`, this can be updated to return the production client that is used by BDK. +pub trait ClientExt { + /// Creates a new [`bitcoincore_rpc::Client`] connected to the current node instance. + fn get_rpc_client(&self) -> anyhow::Result; +} + +impl ClientExt for TestEnv { + fn get_rpc_client(&self) -> anyhow::Result { + Ok(bitcoincore_rpc::Client::new( + &self.bitcoind.rpc_url(), + bitcoincore_rpc::Auth::CookieFile(self.bitcoind.params.cookie_file.clone()), + )?) + } +} diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index 6453037e6..679b6155a 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -11,6 +11,10 @@ use bdk_testenv::{anyhow, TestEnv}; use bitcoin::{hashes::Hash, Block, Network, OutPoint, ScriptBuf, WScriptHash}; use bitcoincore_rpc::RpcApi; +use crate::common::ClientExt; + +mod common; + /// Ensure that blocks are emitted in order even after reorg. /// /// 1. Mine 101 blocks. @@ -20,10 +24,12 @@ use bitcoincore_rpc::RpcApi; #[test] pub fn test_sync_local_chain() -> anyhow::Result<()> { let env = TestEnv::new()?; - let network_tip = env.rpc_client().get_block_count()?; - let (mut local_chain, _) = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?); + let network_tip = env.rpc_client().get_block_count()?.into_model().0; + let (mut local_chain, _) = LocalChain::from_genesis(env.genesis_hash()?); + + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; let mut emitter = Emitter::new( - env.rpc_client(), + &mut bitcoincore_rpc_client, local_chain.tip(), 0, NO_EXPECTED_MEMPOOL_TXS, @@ -34,7 +40,11 @@ pub fn test_sync_local_chain() -> anyhow::Result<()> { // returning block hashes. let exp_hashes = { let mut hashes = (0..=network_tip) - .map(|height| env.rpc_client().get_block_hash(height)) + .map(|height| { + ClientExt::get_rpc_client(&env) + .unwrap() + .get_block_hash(height) + }) .collect::, _>>()?; hashes.extend(env.mine_blocks(101 - network_tip as usize, None)?); hashes @@ -137,22 +147,21 @@ pub fn test_sync_local_chain() -> anyhow::Result<()> { fn test_into_tx_graph() -> anyhow::Result<()> { let env = TestEnv::new()?; - let addr_0 = env - .rpc_client() + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; + + let addr_0 = bitcoincore_rpc_client .get_new_address(None, None)? .assume_checked(); - let addr_1 = env - .rpc_client() + let addr_1 = bitcoincore_rpc_client .get_new_address(None, None)? .assume_checked(); - let addr_2 = env - .rpc_client() + let addr_2 = bitcoincore_rpc_client .get_new_address(None, None)? .assume_checked(); env.mine_blocks(101, None)?; - let (mut chain, _) = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?); + let (mut chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let mut indexed_tx_graph = IndexedTxGraph::::new({ let mut index = SpkTxOutIndex::::default(); index.insert_spk(0, addr_0.script_pubkey()); @@ -161,7 +170,12 @@ fn test_into_tx_graph() -> anyhow::Result<()> { index }); - let emitter = &mut Emitter::new(env.rpc_client(), chain.tip(), 0, NO_EXPECTED_MEMPOOL_TXS); + let emitter = &mut Emitter::new( + &mut bitcoincore_rpc_client, + chain.tip(), + 0, + NO_EXPECTED_MEMPOOL_TXS, + ); while let Some(emission) = emitter.next_block()? { let height = emission.block_height(); @@ -174,7 +188,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> { let exp_txids = { let mut txids = BTreeSet::new(); for _ in 0..3 { - txids.insert(env.rpc_client().send_to_address( + txids.insert(ClientExt::get_rpc_client(&env)?.send_to_address( &addr_0, Amount::from_sat(10_000), None, @@ -210,7 +224,9 @@ fn test_into_tx_graph() -> anyhow::Result<()> { // mine a block that confirms the 3 txs let exp_block_hash = env.mine_blocks(1, None)?[0]; - let exp_block_height = env.rpc_client().get_block_info(&exp_block_hash)?.height as u32; + let exp_block_height = ClientExt::get_rpc_client(&env)? + .get_block_info(&exp_block_hash)? + .height as u32; let exp_anchors = exp_txids .iter() .map({ @@ -250,9 +266,11 @@ fn ensure_block_emitted_after_reorg_is_at_reorg_height() -> anyhow::Result<()> { const CHAIN_TIP_HEIGHT: usize = 110; let env = TestEnv::new()?; + + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; let mut emitter = Emitter::new( - env.rpc_client(), - CheckPoint::new(0, env.rpc_client().get_block_hash(0)?), + &mut bitcoincore_rpc_client, + CheckPoint::new(0, env.genesis_hash()?), EMITTER_START_HEIGHT as _, NO_EXPECTED_MEMPOOL_TXS, ); @@ -325,23 +343,24 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { const SEND_AMOUNT: Amount = Amount::from_sat(10_000); let env = TestEnv::new()?; + + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; let mut emitter = Emitter::new( - env.rpc_client(), - CheckPoint::new(0, env.rpc_client().get_block_hash(0)?), + &mut bitcoincore_rpc_client, + CheckPoint::new(0, env.genesis_hash()?), 0, NO_EXPECTED_MEMPOOL_TXS, ); // setup addresses - let addr_to_mine = env - .rpc_client() + let addr_to_mine = ClientExt::get_rpc_client(&env)? .get_new_address(None, None)? .assume_checked(); let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros()); let addr_to_track = Address::from_script(&spk_to_track, Network::Regtest)?; // setup receiver - let (mut recv_chain, _) = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?); + let (mut recv_chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let mut recv_graph = IndexedTxGraph::::new({ let mut recv_index = SpkTxOutIndex::default(); recv_index.insert_spk((), spk_to_track.clone()); @@ -356,8 +375,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { let txid = env.send(&addr_to_track, SEND_AMOUNT)?; // lock outputs that send to `addr_to_track` - let outpoints_to_lock = env - .rpc_client() + let outpoints_to_lock = ClientExt::get_rpc_client(&env)? .get_transaction(&txid, None)? .transaction()? .output @@ -366,7 +384,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { .filter(|(_, txo)| txo.script_pubkey == spk_to_track) .map(|(vout, _)| OutPoint::new(txid, vout as _)) .collect::>(); - env.rpc_client().lock_unspent(&outpoints_to_lock)?; + ClientExt::get_rpc_client(&env)?.lock_unspent(&outpoints_to_lock)?; let _ = env.mine_blocks(1, None)?; } @@ -413,16 +431,16 @@ fn mempool_avoids_re_emission() -> anyhow::Result<()> { const MEMPOOL_TX_COUNT: usize = 2; let env = TestEnv::new()?; + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; let mut emitter = Emitter::new( - env.rpc_client(), - CheckPoint::new(0, env.rpc_client().get_block_hash(0)?), + &mut bitcoincore_rpc_client, + CheckPoint::new(0, env.genesis_hash()?), 0, NO_EXPECTED_MEMPOOL_TXS, ); // mine blocks and sync up emitter - let addr = env - .rpc_client() + let addr = ClientExt::get_rpc_client(&env)? .get_new_address(None, None)? .assume_checked(); env.mine_blocks(BLOCKS_TO_MINE, Some(addr.clone()))?; @@ -482,10 +500,11 @@ fn no_agreement_point() -> anyhow::Result<()> { let env = TestEnv::new()?; + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; // start height is 99 let mut emitter = Emitter::new( - env.rpc_client(), - CheckPoint::new(0, env.rpc_client().get_block_hash(0)?), + &mut bitcoincore_rpc_client, + CheckPoint::new(0, env.genesis_hash()?), (PREMINE_COUNT - 2) as u32, NO_EXPECTED_MEMPOOL_TXS, ); @@ -507,12 +526,12 @@ fn no_agreement_point() -> anyhow::Result<()> { let block_hash_100a = block_header_100a.block_hash(); // get hash for block 101a - let block_hash_101a = env.rpc_client().get_block_hash(101)?; + let block_hash_101a = ClientExt::get_rpc_client(&env)?.get_block_hash(101)?; // invalidate blocks 99a, 100a, 101a - env.rpc_client().invalidate_block(&block_hash_99a)?; - env.rpc_client().invalidate_block(&block_hash_100a)?; - env.rpc_client().invalidate_block(&block_hash_101a)?; + ClientExt::get_rpc_client(&env)?.invalidate_block(&block_hash_99a)?; + ClientExt::get_rpc_client(&env)?.invalidate_block(&block_hash_100a)?; + ClientExt::get_rpc_client(&env)?.invalidate_block(&block_hash_101a)?; // mine new blocks 99b, 100b, 101b env.mine_blocks(3, None)?; @@ -570,12 +589,17 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> { &Address::from_script(&spk, Network::Regtest)?, Amount::ONE_BTC, )?; - let tx_1 = env - .rpc_client() + let tx_1 = ClientExt::get_rpc_client(&env)? .get_transaction(&txid_1, None)? .transaction()?; - let mut emitter = Emitter::new(env.rpc_client(), chain.tip(), 1, core::iter::once(tx_1)); + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; + let mut emitter = Emitter::new( + &mut bitcoincore_rpc_client, + chain.tip(), + 1, + core::iter::once(tx_1), + ); while let Some(emission) = emitter.next_block()? { let height = emission.block_height(); chain.apply_header(&emission.block.header, height)?; @@ -591,7 +615,7 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> { // Double spend tx1. // Get `prevout` from core. - let core = env.rpc_client(); + let core = ClientExt::get_rpc_client(&env)?; let tx1 = &core.get_raw_transaction(&txid_1, None)?; let txin = &tx1.input[0]; let op = txin.previous_output; @@ -648,14 +672,15 @@ fn detect_new_mempool_txs() -> anyhow::Result<()> { let env = TestEnv::new()?; env.mine_blocks(101, None)?; - let addr = env - .rpc_client() + let mut bitcoincore_rpc_client = ClientExt::get_rpc_client(&env)?; + + let addr = bitcoincore_rpc_client .get_new_address(None, None)? .require_network(Network::Regtest)?; let mut emitter = Emitter::new( - env.rpc_client(), - CheckPoint::new(0, env.rpc_client().get_block_hash(0)?), + &mut bitcoincore_rpc_client, + CheckPoint::new(0, env.genesis_hash()?), 0, NO_EXPECTED_MEMPOOL_TXS, ); diff --git a/crates/bitcoind_rpc/tests/test_filter_iter.rs b/crates/bitcoind_rpc/tests/test_filter_iter.rs index eafe8250b..e45e53311 100644 --- a/crates/bitcoind_rpc/tests/test_filter_iter.rs +++ b/crates/bitcoind_rpc/tests/test_filter_iter.rs @@ -1,11 +1,15 @@ use bdk_bitcoind_rpc::bip158::{Error, FilterIter}; use bdk_core::CheckPoint; -use bdk_testenv::{anyhow, bitcoind, TestEnv}; +use bdk_testenv::{anyhow, corepc_node, TestEnv}; use bitcoin::{Address, Amount, Network, ScriptBuf}; use bitcoincore_rpc::RpcApi; +use crate::common::ClientExt; + +mod common; + fn testenv() -> anyhow::Result { - let mut conf = bitcoind::Conf::default(); + let mut conf = corepc_node::Conf::default(); conf.args.push("-blockfilterindex=1"); conf.args.push("-peerblockfilters=1"); TestEnv::new_with_config(bdk_testenv::Config { @@ -17,13 +21,12 @@ fn testenv() -> anyhow::Result { #[test] fn filter_iter_matches_blocks() -> anyhow::Result<()> { let env = testenv()?; - let addr = env - .rpc_client() + let addr = ClientExt::get_rpc_client(&env)? .get_new_address(None, None)? .assume_checked(); let _ = env.mine_blocks(100, Some(addr.clone()))?; - assert_eq!(env.rpc_client().get_block_count()?, 101); + assert_eq!(ClientExt::get_rpc_client(&env)?.get_block_count()?, 101); // Send tx to external address to confirm at height = 102 let _txid = env.send( @@ -38,7 +41,8 @@ fn filter_iter_matches_blocks() -> anyhow::Result<()> { let genesis_hash = env.genesis_hash()?; let cp = CheckPoint::new(0, genesis_hash); - let iter = FilterIter::new(&env.bitcoind.client, cp, [addr.script_pubkey()]); + let client = ClientExt::get_rpc_client(&env)?; + let iter = FilterIter::new(&client, cp, [addr.script_pubkey()]); for res in iter { let event = res?; @@ -60,7 +64,8 @@ fn filter_iter_error_wrong_network() -> anyhow::Result<()> { // Try to initialize FilterIter with a CP on the wrong network let cp = CheckPoint::new(0, bitcoin::hashes::Hash::hash(b"wrong-hash")); - let mut iter = FilterIter::new(&env.bitcoind.client, cp, [ScriptBuf::new()]); + let client = ClientExt::get_rpc_client(&env)?; + let mut iter = FilterIter::new(&client, cp, [ScriptBuf::new()]); assert!(matches!(iter.next(), Some(Err(Error::ReorgDepthExceeded)))); Ok(()) @@ -72,7 +77,7 @@ fn filter_iter_detects_reorgs() -> anyhow::Result<()> { const MINE_TO: u32 = 16; let env = testenv()?; - let rpc = env.rpc_client(); + let rpc = ClientExt::get_rpc_client(&env)?; while rpc.get_block_count()? < MINE_TO as u64 { let _ = env.mine_blocks(1, None)?; } @@ -81,7 +86,8 @@ fn filter_iter_detects_reorgs() -> anyhow::Result<()> { let cp = CheckPoint::new(0, genesis_hash); let spk = ScriptBuf::from_hex("0014446906a6560d8ad760db3156706e72e171f3a2aa")?; - let mut iter = FilterIter::new(&env.bitcoind.client, cp, [spk]); + let client = ClientExt::get_rpc_client(&env)?; + let mut iter = FilterIter::new(&client, cp, [spk]); // Process events to height (MINE_TO - 1) loop { @@ -131,7 +137,8 @@ fn event_checkpoint_connects_to_local_chain() -> anyhow::Result<()> { .collect(); // Construct iter - let mut iter = FilterIter::new(&env.bitcoind.client, cp, vec![ScriptBuf::new()]); + let client = ClientExt::get_rpc_client(&env)?; + let mut iter = FilterIter::new(&client, cp, vec![ScriptBuf::new()]); // Now reorg 3 blocks (14, 15, 16) let new_hashes: BTreeMap = (14..=16).zip(env.reorg(3)?).collect(); From 25e00ad12d702e5b98a9c19b0eb71577ef330695 Mon Sep 17 00:00:00 2001 From: Leonardo Lima Date: Thu, 27 Nov 2025 17:09:20 -0300 Subject: [PATCH 3/4] fix(tests): on `bdk_chain` --- crates/bitcoind_rpc/src/lib.rs | 2 +- crates/chain/tests/test_indexed_tx_graph.rs | 93 ++++++++++++++------- 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/crates/bitcoind_rpc/src/lib.rs b/crates/bitcoind_rpc/src/lib.rs index 901a6b516..031d156ea 100644 --- a/crates/bitcoind_rpc/src/lib.rs +++ b/crates/bitcoind_rpc/src/lib.rs @@ -414,7 +414,7 @@ mod test { // TODO: (@oleonardolima) We should use the `ClientExt` trait instead. let mut bitcoincore_rpc_client = bitcoincore_rpc::Client::new( &env.bitcoind.rpc_url(), - bitcoincore_rpc::Auth::CookieFile(env.bitcoind.workdir().join("regtest/.cookie")), + bitcoincore_rpc::Auth::CookieFile(env.bitcoind.params.cookie_file.clone()), )?; let mut emitter = Emitter::new( diff --git a/crates/chain/tests/test_indexed_tx_graph.rs b/crates/chain/tests/test_indexed_tx_graph.rs index 7a2f8ea60..6989e4ee1 100644 --- a/crates/chain/tests/test_indexed_tx_graph.rs +++ b/crates/chain/tests/test_indexed_tx_graph.rs @@ -3,10 +3,7 @@ #[macro_use] mod common; -use std::{ - collections::{BTreeSet, HashMap}, - sync::Arc, -}; +use std::{collections::BTreeSet, str::FromStr, sync::Arc}; use bdk_chain::{ indexed_tx_graph::{self, IndexedTxGraph}, @@ -18,8 +15,9 @@ use bdk_chain::{ }; use bdk_testenv::{ anyhow::{self}, - bitcoincore_rpc::{json::CreateRawTransactionInput, RpcApi}, - block_id, hash, + block_id, + corepc_node::{Input, Output}, + hash, utils::{new_tx, DESCRIPTORS}, TestEnv, }; @@ -67,6 +65,7 @@ fn relevant_conflicts() -> anyhow::Result<()> { let sender_addr = client .get_new_address(None, None)? + .address()? .require_network(Network::Regtest)?; let recv_spk = gen_spk(); @@ -78,31 +77,39 @@ fn relevant_conflicts() -> anyhow::Result<()> { env.mine_blocks(1, Some(sender_addr.clone()))?; env.mine_blocks(101, None)?; + // TODO: (@oleonardolima) remove unwraps let tx_input = client - .list_unspent(None, None, None, None, None)? + .list_unspent()? + .0 .into_iter() .take(1) - .map(|r| CreateRawTransactionInput { - txid: r.txid, - vout: r.vout, + .map(|r| Input { + txid: Txid::from_str(&r.txid).unwrap(), + vout: r.vout as u64, sequence: None, }) .collect::>(); let tx_send = { - let outputs = - HashMap::from([(recv_addr.to_string(), Amount::from_btc(49.999_99)?)]); - let tx = client.create_raw_transaction(&tx_input, &outputs, None, Some(true))?; + let outputs = [Output::new(recv_addr, Amount::from_btc(49.999_99)?)]; + let tx = client + .create_raw_transaction(&tx_input, &outputs)? + .into_model()? + .0; client - .sign_raw_transaction_with_wallet(&tx, None, None)? - .transaction()? + .sign_raw_transaction_with_wallet(&tx)? + .into_model()? + .tx }; let tx_cancel = { - let outputs = - HashMap::from([(sender_addr.to_string(), Amount::from_btc(49.999_98)?)]); - let tx = client.create_raw_transaction(&tx_input, &outputs, None, Some(true))?; + let outputs = [Output::new(sender_addr, Amount::from_btc(49.999_98)?)]; + let tx = client + .create_raw_transaction(&tx_input, &outputs)? + .into_model()? + .0; client - .sign_raw_transaction_with_wallet(&tx, None, None)? - .transaction()? + .sign_raw_transaction_with_wallet(&tx)? + .into_model()? + .tx }; Ok(Self { @@ -118,31 +125,53 @@ fn relevant_conflicts() -> anyhow::Result<()> { /// Scans through all transactions in the blockchain + mempool. fn sync(&mut self) -> anyhow::Result<()> { let client = self.env.rpc_client(); - for height in 0..=client.get_block_count()? { - let hash = client.get_block_hash(height)?; - let block = client.get_block(&hash)?; + for height in 0..=client.get_block_count()?.into_model().0 { + let hash = client.get_block_hash(height)?.block_hash()?; + let block = client.get_block(hash)?; let _ = self.graph.apply_block_relevant(&block, height as _); } - let _ = self.graph.batch_insert_relevant_unconfirmed( - client - .get_raw_mempool()? - .into_iter() - .map(|txid| client.get_raw_transaction(&txid, None).map(|tx| (tx, 0))) - .collect::, _>>()?, - ); + + let mempool_txids = client.get_raw_mempool()?.into_model()?.0; + let unconfirmed_txs = mempool_txids + .iter() + .map(|txid| { + client + .get_raw_transaction(*txid) + .unwrap() + .into_model() + .unwrap() + }) + .map(|get_raw_transaction| (get_raw_transaction.0, 0)) + .collect::>(); + // let unconfirmed_txs = mempool_txids + // .iter() + // // .map(|txid| -> Result<_, _> { client.get_raw_transaction(*txid)?.into_model() + // })? .map( + // |txid| -> Result< + // GetRawTransaction, + // bdk_testenv::corepc_client::client_sync::Error, + // > { client.get_raw_transaction(*txid) }, + // ) + // .collect::>>() + // .map(|get_raw_tx| get_raw_tx.into_model()) + // .map(|tx| (tx.0, 0)) + // .collect::>(); + let _ = self + .graph + .batch_insert_relevant_unconfirmed(unconfirmed_txs); Ok(()) } /// Broadcast the original sending transaction. fn broadcast_send(&self) -> anyhow::Result { let client = self.env.rpc_client(); - Ok(client.send_raw_transaction(&self.tx_send)?) + Ok(client.send_raw_transaction(&self.tx_send)?.txid()?) } /// Broadcast the cancellation transaction. fn broadcast_cancel(&self) -> anyhow::Result { let client = self.env.rpc_client(); - Ok(client.send_raw_transaction(&self.tx_cancel)?) + Ok(client.send_raw_transaction(&self.tx_cancel)?.txid()?) } } From a83a8fe856d5f1df46f3958998d96ab5956e480e Mon Sep 17 00:00:00 2001 From: Leonardo Lima Date: Fri, 21 Mar 2025 20:46:30 -0300 Subject: [PATCH 4/4] fix(tests): on bdk_esplora, bdk_electrum --- crates/electrum/benches/test_sync.rs | 12 +- crates/electrum/src/bdk_electrum_client.rs | 5 +- crates/electrum/tests/test_electrum.rs | 243 ++++++++++----------- crates/esplora/src/async_ext.rs | 16 +- crates/esplora/src/blocking_ext.rs | 22 +- crates/esplora/tests/async_ext.rs | 132 ++++++----- crates/esplora/tests/blocking_ext.rs | 138 ++++++------ 7 files changed, 280 insertions(+), 288 deletions(-) diff --git a/crates/electrum/benches/test_sync.rs b/crates/electrum/benches/test_sync.rs index 12ecf06aa..39dd10d9a 100644 --- a/crates/electrum/benches/test_sync.rs +++ b/crates/electrum/benches/test_sync.rs @@ -10,7 +10,7 @@ use bdk_core::{ CheckPoint, }; use bdk_electrum::BdkElectrumClient; -use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv}; +use bdk_testenv::{anyhow, TestEnv}; use criterion::{criterion_group, criterion_main, Criterion}; use electrum_client::ElectrumApi; use std::{collections::BTreeSet, time::Duration}; @@ -77,7 +77,15 @@ pub fn test_sync_performance(c: &mut Criterion) { ); // Setup receiver. - let genesis_cp = CheckPoint::new(0, env.bitcoind.client.get_block_hash(0).unwrap()); + let genesis_cp = CheckPoint::new( + 0, + env.bitcoind + .client + .get_block_hash(0) + .unwrap() + .block_hash() + .unwrap(), + ); { let electrum_client = diff --git a/crates/electrum/src/bdk_electrum_client.rs b/crates/electrum/src/bdk_electrum_client.rs index 05b501871..25da3998a 100644 --- a/crates/electrum/src/bdk_electrum_client.rs +++ b/crates/electrum/src/bdk_electrum_client.rs @@ -702,7 +702,7 @@ mod test { use bdk_chain::bitcoin::{constants, Network, OutPoint, ScriptBuf, Transaction, TxIn}; use bdk_chain::CheckPoint; use bdk_core::{collections::BTreeMap, spk_client::SyncRequest}; - use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, utils::new_tx, TestEnv}; + use bdk_testenv::{anyhow, utils::new_tx, TestEnv}; use core::time::Duration; use electrum_client::Error as ElectrumError; use std::sync::Arc; @@ -786,13 +786,14 @@ mod test { let addr = env .rpc_client() .get_new_address(None, None)? + .address()? .assume_checked(); let txid = env.send(&addr, Amount::from_sat(50_000))?; // Mine block that confirms transaction. env.mine_blocks(1, None)?; env.wait_until_electrum_sees_block(Duration::from_secs(6))?; - let height: u32 = env.rpc_client().get_block_count()? as u32; + let height: u32 = env.rpc_client().get_block_count()?.into_model().0 as u32; // Add the pre-reorg block that the tx is confirmed in to the header cache. let header = electrum_client.inner.block_header(height as usize)?; diff --git a/crates/electrum/tests/test_electrum.rs b/crates/electrum/tests/test_electrum.rs index 07979866e..ecda4fa86 100644 --- a/crates/electrum/tests/test_electrum.rs +++ b/crates/electrum/tests/test_electrum.rs @@ -8,17 +8,17 @@ use bdk_chain::{ }; use bdk_core::bitcoin::{ key::{Secp256k1, UntweakedPublicKey}, - Network, + Denomination, Txid, }; use bdk_electrum::BdkElectrumClient; use bdk_testenv::{ anyhow, - bitcoincore_rpc::{json::CreateRawTransactionInput, RawTx, RpcApi}, + corepc_node::{Input, Output}, TestEnv, }; use core::time::Duration; use electrum_client::ElectrumApi; -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeSet, HashSet}; use std::str::FromStr; // Batch size for `sync_with_electrum`. @@ -89,7 +89,7 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { let client = BdkElectrumClient::new(electrum_client); let mut graph = IndexedTxGraph::::new(SpkTxOutIndex::<()>::default()); - let (chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (chain, _) = LocalChain::from_genesis(env.genesis_hash()?); // Get receiving address. let receiver_spk = get_test_spk(); @@ -100,48 +100,57 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { // Select a UTXO to use as an input for constructing our test transactions. let selected_utxo = rpc_client - .list_unspent(None, None, None, Some(false), None)? + .list_unspent()? + .0 .into_iter() // Find a block reward tx. - .find(|utxo| utxo.amount == Amount::from_int_btc(50)) - .expect("Must find a block reward UTXO"); + .find(|utxo| utxo.amount == Amount::from_int_btc(50).to_btc()) + .expect("Must find a block reward UTXO") + .into_model()?; // Derive the sender's address from the selected UTXO. - let sender_spk = selected_utxo.script_pub_key.clone(); + let sender_spk = selected_utxo.script_pubkey.clone(); let sender_addr = Address::from_script(&sender_spk, bdk_chain::bitcoin::Network::Regtest) .expect("Failed to derive address from UTXO"); // Setup the common inputs used by both `send_tx` and `undo_send_tx`. - let inputs = [CreateRawTransactionInput { + let inputs = [Input { txid: selected_utxo.txid, - vout: selected_utxo.vout, + vout: selected_utxo.vout as u64, sequence: None, }]; // Create and sign the `send_tx` that sends funds to the receiver address. - let send_tx_outputs = HashMap::from([( - receiver_addr.to_string(), - selected_utxo.amount - SEND_TX_FEE, - )]); - let send_tx = rpc_client.create_raw_transaction(&inputs, &send_tx_outputs, None, Some(true))?; + let send_tx_outputs = [Output::new( + receiver_addr, + selected_utxo.amount.to_unsigned()? - SEND_TX_FEE, + )]; let send_tx = rpc_client - .sign_raw_transaction_with_wallet(send_tx.raw_hex(), None, None)? - .transaction()?; + .create_raw_transaction(&inputs, &send_tx_outputs)? + .into_model()? + .0; + let send_tx = rpc_client + .sign_raw_transaction_with_wallet(&send_tx)? + .into_model()? + .tx; // Create and sign the `undo_send_tx` transaction. This redirects funds back to the sender // address. - let undo_send_outputs = HashMap::from([( - sender_addr.to_string(), - selected_utxo.amount - UNDO_SEND_TX_FEE, - )]); - let undo_send_tx = - rpc_client.create_raw_transaction(&inputs, &undo_send_outputs, None, Some(true))?; + let undo_send_outputs = [Output::new( + sender_addr, + selected_utxo.amount.to_unsigned()? - UNDO_SEND_TX_FEE, + )]; let undo_send_tx = rpc_client - .sign_raw_transaction_with_wallet(undo_send_tx.raw_hex(), None, None)? - .transaction()?; + .create_raw_transaction(&inputs, &undo_send_outputs)? + .into_model()? + .0; + let undo_send_tx = rpc_client + .sign_raw_transaction_with_wallet(&undo_send_tx)? + .into_model()? + .tx; // Sync after broadcasting the `send_tx`. Ensure that we detect and receive the `send_tx`. - let send_txid = env.rpc_client().send_raw_transaction(send_tx.raw_hex())?; + let send_txid = env.rpc_client().send_raw_transaction(&send_tx)?.txid()?; env.wait_until_electrum_sees_txid(send_txid, Duration::from_secs(6))?; let sync_request = SyncRequest::builder() .chain_tip(chain.tip()) @@ -170,7 +179,8 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { // mempool. let undo_send_txid = env .rpc_client() - .send_raw_transaction(undo_send_tx.raw_hex())?; + .send_raw_transaction(&undo_send_tx)? + .txid()?; env.wait_until_electrum_sees_txid(undo_send_txid, Duration::from_secs(6))?; let sync_request = SyncRequest::builder() .chain_tip(chain.tip()) @@ -206,9 +216,7 @@ pub fn chained_mempool_tx_sync() -> anyhow::Result<()> { let rpc_client = env.rpc_client(); let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str())?; - let tracked_addr = rpc_client - .get_new_address(None, None)? - .require_network(Network::Regtest)?; + let tracked_addr = rpc_client.new_address()?; env.mine_blocks(100, None)?; @@ -217,32 +225,37 @@ pub fn chained_mempool_tx_sync() -> anyhow::Result<()> { // Create second unconfirmed tx that spends the first. let utxo = rpc_client - .list_unspent(None, Some(0), None, Some(true), None)? + .list_unspent()? + .0 .into_iter() - .find(|utxo| utxo.script_pub_key == tracked_addr.script_pubkey()) - .expect("must find the newly created utxo"); - let tx_that_spends_unconfirmed = rpc_client.create_raw_transaction( - &[CreateRawTransactionInput { - txid: utxo.txid, - vout: utxo.vout, - sequence: None, - }], - &[( - tracked_addr.to_string(), - utxo.amount - Amount::from_sat(1000), - )] - .into(), - None, - None, - )?; - let signed_tx = rpc_client - .sign_raw_transaction_with_wallet(tx_that_spends_unconfirmed.raw_hex(), None, None)? + .find(|utxo| utxo.script_pubkey == tracked_addr.script_pubkey().to_string()) + .expect("must find the newly created utxo") + .into_model()?; + let tx_that_spends_unconfirmed = rpc_client + .create_raw_transaction( + &[Input { + txid: utxo.txid, + vout: utxo.vout as u64, + sequence: None, + }], + &[Output::new( + tracked_addr.clone(), + utxo.amount.to_unsigned()? - Amount::from_sat(1000), + )], + )? .transaction()?; - let txid2 = rpc_client.send_raw_transaction(signed_tx.raw_hex())?; + let signed_tx = rpc_client + .sign_raw_transaction_with_wallet(&tx_that_spends_unconfirmed)? + .into_model()? + .tx; + + let txid2 = rpc_client.send_raw_transaction(&signed_tx)?.txid()?; env.wait_until_electrum_sees_txid(signed_tx.compute_txid(), Duration::from_secs(6))?; - let spk_history = electrum_client.script_get_history(&tracked_addr.script_pubkey())?; + let spk = tracked_addr.clone().script_pubkey(); + let script = spk.as_script(); + let spk_history = electrum_client.script_get_history(script)?; assert!( spk_history.into_iter().any(|tx_res| tx_res.height < 0), "must find tx with negative height" @@ -280,26 +293,16 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { ]; let _block_hashes = env.mine_blocks(101, None)?; - let txid1 = env.bitcoind.client.send_to_address( - &receive_address1, - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; - let txid2 = env.bitcoind.client.send_to_address( - &receive_address0, - Amount::from_sat(20000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid1 = env + .bitcoind + .client + .send_to_address(&receive_address1, Amount::from_sat(10000))? + .txid()?; + let txid2 = env + .bitcoind + .client + .send_to_address(&receive_address0, Amount::from_sat(20000))? + .txid()?; env.mine_blocks(1, None)?; env.wait_until_electrum_sees_block(Duration::from_secs(6))?; @@ -346,7 +349,8 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let tx_fee = env .bitcoind .client - .get_transaction(&tx.compute_txid(), None) + .get_transaction(tx.compute_txid())? + .into_model() .expect("Tx must exist") .fee .expect("Fee must exist") @@ -402,16 +406,11 @@ pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> { .collect(); // Then receive coins on the 4th address. - let txid_4th_addr = env.bitcoind.client.send_to_address( - &addresses[3], - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid_4th_addr = env + .bitcoind + .client + .send_to_address(&addresses[3], Amount::from_sat(10000))? + .txid()?; env.mine_blocks(1, None)?; env.wait_until_electrum_sees_block(Duration::from_secs(6))?; @@ -446,16 +445,11 @@ pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> { assert_eq!(full_scan_update.last_active_indices[&0], 3); // Now receive a coin on the last address. - let txid_last_addr = env.bitcoind.client.send_to_address( - &addresses[addresses.len() - 1], - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid_last_addr = env + .bitcoind + .client + .send_to_address(&addresses[addresses.len() - 1], Amount::from_sat(10000))? + .txid()?; env.mine_blocks(1, None)?; env.wait_until_electrum_sees_block(Duration::from_secs(6))?; @@ -507,16 +501,12 @@ fn test_sync() -> anyhow::Result<()> { let client = BdkElectrumClient::new(electrum_client); // Setup addresses. - let addr_to_mine = env - .bitcoind - .client - .get_new_address(None, None)? - .assume_checked(); + let addr_to_mine = env.bitcoind.client.new_address()?; let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros()); let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?; // Setup receiver. - let (mut recv_chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (mut recv_chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let mut recv_graph = IndexedTxGraph::::new({ let mut recv_index = SpkTxOutIndex::default(); recv_index.insert_spk((), spk_to_track.clone()); @@ -619,7 +609,8 @@ fn test_sync() -> anyhow::Result<()> { let tx_fee = env .bitcoind .client - .get_transaction(&tx.txid, None) + .get_transaction(tx.txid)? + .into_model() .expect("Tx must exist") .fee .expect("Fee must exist") @@ -650,16 +641,12 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { let client = BdkElectrumClient::new(electrum_client); // Setup addresses. - let addr_to_mine = env - .bitcoind - .client - .get_new_address(None, None)? - .assume_checked(); + let addr_to_mine = env.bitcoind.client.new_address()?; let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros()); let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?; // Setup receiver. - let (mut recv_chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (mut recv_chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let mut recv_graph = IndexedTxGraph::::new({ let mut recv_index = SpkTxOutIndex::default(); recv_index.insert_spk((), spk_to_track.clone()); @@ -745,7 +732,7 @@ fn test_sync_with_coinbase() -> anyhow::Result<()> { let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?; // Setup receiver. - let (mut recv_chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (mut recv_chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let mut recv_graph = IndexedTxGraph::::new({ let mut recv_index = SpkTxOutIndex::default(); recv_index.insert_spk((), spk_to_track.clone()); @@ -780,7 +767,7 @@ fn test_check_fee_calculation() -> anyhow::Result<()> { let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?; // Setup receiver. - let (mut recv_chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (mut recv_chain, _) = LocalChain::from_genesis(env.genesis_hash()?); let mut recv_graph = IndexedTxGraph::::new({ let mut recv_index = SpkTxOutIndex::default(); recv_index.insert_spk((), spk_to_track.clone()); @@ -792,42 +779,35 @@ fn test_check_fee_calculation() -> anyhow::Result<()> { // Send a preliminary tx such that the new utxo in Core's wallet // becomes the input of the next tx - let new_addr = env - .rpc_client() - .get_new_address(None, None)? - .assume_checked(); + let new_addr = env.rpc_client().new_address()?; let prev_amt = SEND_AMOUNT + FEE_AMOUNT; env.send(&new_addr, prev_amt)?; - let prev_block_hash = env.mine_blocks(1, None)?.into_iter().next(); + let _prev_block_hash = env.mine_blocks(1, None)?.into_iter().next(); let txid = env.send(&addr_to_track, SEND_AMOUNT)?; // Mine a block to confirm sent tx. - let block_hash = env.mine_blocks(1, None)?.into_iter().next(); + let _block_hash = env.mine_blocks(1, None)?.into_iter().next(); // Look at the tx we just sent, it should have 1 input and 1 output - let tx = env - .rpc_client() - .get_raw_transaction_info(&txid, block_hash.as_ref())?; - assert_eq!(tx.vin.len(), 1); - assert_eq!(tx.vout.len(), 1); - let vin = &tx.vin[0]; - let prev_txid = vin.txid.unwrap(); - let vout = vin.vout.unwrap(); + let tx = env.rpc_client().get_raw_transaction_verbose(txid)?; + assert_eq!(tx.inputs.len(), 1); + assert_eq!(tx.outputs.len(), 1); + let vin = &tx.inputs[0]; + let prev_txid = Txid::from_str(&vin.txid)?; + let vout = vin.vout; let outpoint = bdk_chain::bitcoin::OutPoint::new(prev_txid, vout); // Get the txout of the previous tx - let prev_tx = env - .rpc_client() - .get_raw_transaction_info(&prev_txid, prev_block_hash.as_ref())?; + let prev_tx = env.rpc_client().get_raw_transaction_verbose(prev_txid)?; let txout = prev_tx - .vout + .outputs .iter() - .find(|txout| txout.value == prev_amt) + .find(|txout| txout.value == prev_amt.to_btc()) .unwrap(); - let script_pubkey = ScriptBuf::from_bytes(txout.script_pub_key.hex.to_vec()); + let script_pubkey = ScriptBuf::from_hex(&txout.script_pubkey.hex)?; let txout = bdk_chain::bitcoin::TxOut { - value: txout.value, + value: Amount::from_float_in(txout.value, Denomination::Bitcoin)?, script_pubkey, }; @@ -872,12 +852,13 @@ fn test_check_fee_calculation() -> anyhow::Result<()> { let tx_fee = env .bitcoind .client - .get_transaction(&tx.txid, None) + .get_transaction(tx.txid) .expect("Tx must exist") .fee + .map(|fee| Amount::from_float_in(fee.abs(), Denomination::BTC)) .expect("Fee must exist") - .abs() - .to_sat() as u64; + .expect("Amount parsing should succeed") + .to_sat(); // Check that the calculated fee matches the fee from the transaction data. assert_eq!(fee, Amount::from_sat(tx_fee)); // 1650sat diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index c9cb17c1e..d504a4723 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -560,7 +560,7 @@ mod test { BlockId, }; use bdk_core::{bitcoin, ConfirmationBlockTime}; - use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv}; + use bdk_testenv::{anyhow, TestEnv}; use esplora_client::Builder; use crate::async_ext::{chain_update, fetch_latest_blocks}; @@ -577,7 +577,7 @@ mod test { let env = TestEnv::new()?; let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap()); let client = Builder::new(base_url.as_str()).build_async()?; - let initial_height = env.rpc_client().get_block_count()? as u32; + let initial_height = env.rpc_client().get_block_count()?.into_model().0 as u32; let mine_to = 16; let _ = env.mine_blocks((mine_to - initial_height) as usize, None)?; @@ -673,7 +673,11 @@ mod test { ConfirmationBlockTime { block_id: BlockId { height, - hash: env.bitcoind.client.get_block_hash(height as _)?, + hash: env + .bitcoind + .client + .get_block_hash(height as _)? + .block_hash()?, }, confirmation_time: height as _, }, @@ -713,7 +717,11 @@ mod test { ConfirmationBlockTime { block_id: BlockId { height, - hash: env.bitcoind.client.get_block_hash(height as _)?, + hash: env + .bitcoind + .client + .get_block_hash(height as _)? + .block_hash()?, }, confirmation_time: height as _, }, diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index 5f8ab531c..9413c14af 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -518,7 +518,7 @@ mod test { use bdk_chain::local_chain::LocalChain; use bdk_chain::BlockId; use bdk_core::ConfirmationBlockTime; - use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv}; + use bdk_testenv::{anyhow, TestEnv}; use esplora_client::{BlockHash, Builder}; use std::collections::{BTreeMap, BTreeSet}; use std::time::Duration; @@ -543,7 +543,7 @@ mod test { let env = TestEnv::new()?; let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap()); let client = Builder::new(base_url.as_str()).build_blocking(); - let initial_height = env.rpc_client().get_block_count()? as u32; + let initial_height = env.rpc_client().get_block_count()?.into_model().0 as u32; let mine_to = 16; let _ = env.mine_blocks((mine_to - initial_height) as usize, None)?; @@ -639,7 +639,11 @@ mod test { ConfirmationBlockTime { block_id: BlockId { height, - hash: env.bitcoind.client.get_block_hash(height as _)?, + hash: env + .bitcoind + .client + .get_block_hash(height as _)? + .block_hash()?, }, confirmation_time: height as _, }, @@ -678,7 +682,11 @@ mod test { ConfirmationBlockTime { block_id: BlockId { height, - hash: env.bitcoind.client.get_block_hash(height as _)?, + hash: env + .bitcoind + .client + .get_block_hash(height as _)? + .block_hash()?, }, confirmation_time: height as _, }, @@ -741,10 +749,10 @@ mod test { let env = TestEnv::new()?; let blocks = { let bitcoind_client = &env.bitcoind.client; - assert_eq!(bitcoind_client.get_block_count()?, 1); + assert_eq!(bitcoind_client.get_block_count()?.0, 1); [ - (0, bitcoind_client.get_block_hash(0)?), - (1, bitcoind_client.get_block_hash(1)?), + (0, bitcoind_client.get_block_hash(0)?.block_hash()?), + (1, bitcoind_client.get_block_hash(1)?.block_hash()?), ] .into_iter() .chain((2..).zip(env.mine_blocks((TIP_HEIGHT - 1) as usize, None)?)) diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index 3c628c20d..209e5b788 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -4,11 +4,10 @@ use bdk_chain::spk_client::{FullScanRequest, SyncRequest}; use bdk_chain::spk_txout::SpkTxOutIndex; use bdk_chain::{ConfirmationBlockTime, IndexedTxGraph, TxGraph}; use bdk_esplora::EsploraAsyncExt; -use bdk_testenv::bitcoincore_rpc::json::CreateRawTransactionInput; -use bdk_testenv::bitcoincore_rpc::RawTx; -use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv}; +use bdk_testenv::corepc_node::{Input, Output}; +use bdk_testenv::{anyhow, TestEnv}; use esplora_client::{self, Builder}; -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeSet, HashSet}; use std::str::FromStr; use std::thread::sleep; use std::time::Duration; @@ -30,7 +29,7 @@ pub async fn detect_receive_tx_cancel() -> anyhow::Result<()> { let client = Builder::new(base_url.as_str()).build_async()?; let mut graph = IndexedTxGraph::::new(SpkTxOutIndex::<()>::default()); - let (chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (chain, _) = LocalChain::from_genesis(env.genesis_hash()?); // Get receiving address. let receiver_spk = common::get_test_spk(); @@ -41,48 +40,61 @@ pub async fn detect_receive_tx_cancel() -> anyhow::Result<()> { // Select a UTXO to use as an input for constructing our test transactions. let selected_utxo = rpc_client - .list_unspent(None, None, None, Some(false), None)? + .list_unspent()? + .0 .into_iter() // Find a block reward tx. - .find(|utxo| utxo.amount == Amount::from_int_btc(50)) - .expect("Must find a block reward UTXO"); + .find(|utxo| utxo.amount == Amount::from_int_btc(50).to_btc()) + .expect("Must find a block reward UTXO") + .into_model()?; // Derive the sender's address from the selected UTXO. - let sender_spk = selected_utxo.script_pub_key.clone(); + let sender_spk = selected_utxo.script_pubkey.clone(); let sender_addr = Address::from_script(&sender_spk, bdk_chain::bitcoin::Network::Regtest) .expect("Failed to derive address from UTXO"); // Setup the common inputs used by both `send_tx` and `undo_send_tx`. - let inputs = [CreateRawTransactionInput { + let inputs = [Input { txid: selected_utxo.txid, - vout: selected_utxo.vout, + vout: selected_utxo.vout as u64, sequence: None, }]; // Create and sign the `send_tx` that sends funds to the receiver address. - let send_tx_outputs = HashMap::from([( - receiver_addr.to_string(), - selected_utxo.amount - SEND_TX_FEE, - )]); - let send_tx = rpc_client.create_raw_transaction(&inputs, &send_tx_outputs, None, Some(true))?; + let address = receiver_addr; + let value = selected_utxo.amount.to_unsigned()? - SEND_TX_FEE; + let send_tx_outputs = Output::new(address, value); + + let send_tx = rpc_client + .create_raw_transaction(&inputs, &[send_tx_outputs])? + .into_model()? + .0; let send_tx = rpc_client - .sign_raw_transaction_with_wallet(send_tx.raw_hex(), None, None)? - .transaction()?; + .sign_raw_transaction_with_wallet(&send_tx)? + .into_model()? + .tx; // Create and sign the `undo_send_tx` transaction. This redirects funds back to the sender // address. - let undo_send_outputs = HashMap::from([( - sender_addr.to_string(), - selected_utxo.amount - UNDO_SEND_TX_FEE, - )]); - let undo_send_tx = - rpc_client.create_raw_transaction(&inputs, &undo_send_outputs, None, Some(true))?; + let undo_send_outputs = [Output::new( + sender_addr, + selected_utxo.amount.to_unsigned()? - UNDO_SEND_TX_FEE, + )]; let undo_send_tx = rpc_client - .sign_raw_transaction_with_wallet(undo_send_tx.raw_hex(), None, None)? - .transaction()?; + .create_raw_transaction(&inputs, &undo_send_outputs)? + .into_model()? + .0; + let undo_send_tx = rpc_client + .sign_raw_transaction_with_wallet(&undo_send_tx)? + .into_model()? + .tx; // Sync after broadcasting the `send_tx`. Ensure that we detect and receive the `send_tx`. - let send_txid = env.rpc_client().send_raw_transaction(send_tx.raw_hex())?; + let send_txid = env + .rpc_client() + .send_raw_transaction(&send_tx)? + .into_model()? + .0; env.wait_until_electrum_sees_txid(send_txid, Duration::from_secs(6))?; let sync_request = SyncRequest::builder() .chain_tip(chain.tip()) @@ -111,7 +123,8 @@ pub async fn detect_receive_tx_cancel() -> anyhow::Result<()> { // mempool. let undo_send_txid = env .rpc_client() - .send_raw_transaction(undo_send_tx.raw_hex())?; + .send_raw_transaction(&undo_send_tx)? + .txid()?; env.wait_until_electrum_sees_txid(undo_send_txid, Duration::from_secs(6))?; let sync_request = SyncRequest::builder() .chain_tip(chain.tip()) @@ -155,26 +168,16 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { ]; let _block_hashes = env.mine_blocks(101, None)?; - let txid1 = env.bitcoind.client.send_to_address( - &receive_address1, - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; - let txid2 = env.bitcoind.client.send_to_address( - &receive_address0, - Amount::from_sat(20000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid1 = env + .bitcoind + .client + .send_to_address(&receive_address1, Amount::from_sat(10000))? + .txid()?; + let txid2 = env + .bitcoind + .client + .send_to_address(&receive_address0, Amount::from_sat(20000))? + .txid()?; let _block_hashes = env.mine_blocks(1, None)?; while client.get_height().await.unwrap() < 102 { sleep(Duration::from_millis(10)) @@ -223,8 +226,9 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let tx_fee = env .bitcoind .client - .get_transaction(&tx.compute_txid(), None) + .get_transaction(tx.compute_txid()) .expect("Tx must exist") + .into_model()? .fee .expect("Fee must exist") .abs() @@ -279,16 +283,11 @@ pub async fn test_async_update_tx_graph_stop_gap() -> anyhow::Result<()> { .collect(); // Then receive coins on the 4th address. - let txid_4th_addr = env.bitcoind.client.send_to_address( - &addresses[3], - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid_4th_addr = env + .bitcoind + .client + .send_to_address(&addresses[3], Amount::from_sat(10000))? + .txid()?; let _block_hashes = env.mine_blocks(1, None)?; while client.get_height().await.unwrap() < 103 { sleep(Duration::from_millis(10)) @@ -325,16 +324,11 @@ pub async fn test_async_update_tx_graph_stop_gap() -> anyhow::Result<()> { assert_eq!(full_scan_update.last_active_indices[&0], 3); // Now receive a coin on the last address. - let txid_last_addr = env.bitcoind.client.send_to_address( - &addresses[addresses.len() - 1], - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid_last_addr = env + .bitcoind + .client + .send_to_address(&addresses[addresses.len() - 1], Amount::from_sat(10000))? + .txid()?; let _block_hashes = env.mine_blocks(1, None)?; while client.get_height().await.unwrap() < 104 { sleep(Duration::from_millis(10)) diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index 4d5683e8b..76ed28fbb 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -4,11 +4,10 @@ use bdk_chain::spk_client::{FullScanRequest, SyncRequest}; use bdk_chain::spk_txout::SpkTxOutIndex; use bdk_chain::{ConfirmationBlockTime, IndexedTxGraph, TxGraph}; use bdk_esplora::EsploraExt; -use bdk_testenv::bitcoincore_rpc::json::CreateRawTransactionInput; -use bdk_testenv::bitcoincore_rpc::RawTx; -use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv}; +use bdk_testenv::corepc_node::{Input, Output}; +use bdk_testenv::{anyhow, TestEnv}; use esplora_client::{self, Builder}; -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeSet, HashSet}; use std::str::FromStr; use std::thread::sleep; use std::time::Duration; @@ -30,7 +29,7 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { let client = Builder::new(base_url.as_str()).build_blocking(); let mut graph = IndexedTxGraph::::new(SpkTxOutIndex::<()>::default()); - let (chain, _) = LocalChain::from_genesis(env.bitcoind.client.get_block_hash(0)?); + let (chain, _) = LocalChain::from_genesis(env.genesis_hash()?); // Get receiving address. let receiver_spk = common::get_test_spk(); @@ -41,48 +40,58 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { // Select a UTXO to use as an input for constructing our test transactions. let selected_utxo = rpc_client - .list_unspent(None, None, None, Some(false), None)? + .list_unspent()? + .0 .into_iter() // Find a block reward tx. - .find(|utxo| utxo.amount == Amount::from_int_btc(50)) - .expect("Must find a block reward UTXO"); + .find(|utxo| utxo.amount == Amount::from_int_btc(50).to_btc()) + .expect("Must find a block reward UTXO") + .into_model()?; // Derive the sender's address from the selected UTXO. - let sender_spk = selected_utxo.script_pub_key.clone(); + let sender_spk = selected_utxo.script_pubkey.clone(); let sender_addr = Address::from_script(&sender_spk, bdk_chain::bitcoin::Network::Regtest) .expect("Failed to derive address from UTXO"); // Setup the common inputs used by both `send_tx` and `undo_send_tx`. - let inputs = [CreateRawTransactionInput { + let inputs = [Input { txid: selected_utxo.txid, - vout: selected_utxo.vout, + vout: selected_utxo.vout as u64, sequence: None, }]; // Create and sign the `send_tx` that sends funds to the receiver address. - let send_tx_outputs = HashMap::from([( - receiver_addr.to_string(), - selected_utxo.amount - SEND_TX_FEE, - )]); - let send_tx = rpc_client.create_raw_transaction(&inputs, &send_tx_outputs, None, Some(true))?; + let send_tx_outputs = [Output::new( + receiver_addr, + selected_utxo.amount.to_unsigned()? - SEND_TX_FEE, + )]; + + let send_tx = rpc_client + .create_raw_transaction(&inputs, &send_tx_outputs)? + .into_model()? + .0; let send_tx = rpc_client - .sign_raw_transaction_with_wallet(send_tx.raw_hex(), None, None)? - .transaction()?; + .sign_raw_transaction_with_wallet(&send_tx)? + .into_model()? + .tx; // Create and sign the `undo_send_tx` transaction. This redirects funds back to the sender // address. - let undo_send_outputs = HashMap::from([( - sender_addr.to_string(), - selected_utxo.amount - UNDO_SEND_TX_FEE, - )]); - let undo_send_tx = - rpc_client.create_raw_transaction(&inputs, &undo_send_outputs, None, Some(true))?; + let undo_send_outputs = [Output::new( + sender_addr, + selected_utxo.amount.to_unsigned()? - UNDO_SEND_TX_FEE, + )]; let undo_send_tx = rpc_client - .sign_raw_transaction_with_wallet(undo_send_tx.raw_hex(), None, None)? - .transaction()?; + .create_raw_transaction(&inputs, &undo_send_outputs)? + .into_model()? + .0; + let undo_send_tx = rpc_client + .sign_raw_transaction_with_wallet(&undo_send_tx)? + .into_model()? + .tx; // Sync after broadcasting the `send_tx`. Ensure that we detect and receive the `send_tx`. - let send_txid = env.rpc_client().send_raw_transaction(send_tx.raw_hex())?; + let send_txid = env.rpc_client().send_raw_transaction(&send_tx)?.txid()?; env.wait_until_electrum_sees_txid(send_txid, Duration::from_secs(6))?; let sync_request = SyncRequest::builder() .chain_tip(chain.tip()) @@ -111,7 +120,8 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { // mempool. let undo_send_txid = env .rpc_client() - .send_raw_transaction(undo_send_tx.raw_hex())?; + .send_raw_transaction(&undo_send_tx)? + .txid()?; env.wait_until_electrum_sees_txid(undo_send_txid, Duration::from_secs(6))?; let sync_request = SyncRequest::builder() .chain_tip(chain.tip()) @@ -156,26 +166,16 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { ]; let _block_hashes = env.mine_blocks(101, None)?; - let txid1 = env.bitcoind.client.send_to_address( - &receive_address1, - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; - let txid2 = env.bitcoind.client.send_to_address( - &receive_address0, - Amount::from_sat(20000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid1 = env + .bitcoind + .client + .send_to_address(&receive_address1, Amount::from_sat(10000))? + .txid()?; + let txid2 = env + .bitcoind + .client + .send_to_address(&receive_address0, Amount::from_sat(20000))? + .txid()?; let _block_hashes = env.mine_blocks(1, None)?; while client.get_height().unwrap() < 102 { sleep(Duration::from_millis(10)) @@ -224,16 +224,17 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let tx_fee = env .bitcoind .client - .get_transaction(&tx.compute_txid(), None) + .get_transaction(tx.compute_txid()) .expect("Tx must exist") .fee .expect("Fee must exist") - .abs() - .to_unsigned() - .expect("valid `Amount`"); + .abs(); // Check that the calculated fee matches the fee from the transaction data. - assert_eq!(fee, tx_fee); + assert_eq!( + fee, + Amount::from_float_in(tx_fee, bdk_core::bitcoin::Denomination::Bitcoin)? + ); } assert_eq!( @@ -280,16 +281,12 @@ pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> { .collect(); // Then receive coins on the 4th address. - let txid_4th_addr = env.bitcoind.client.send_to_address( - &addresses[3], - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid_4th_addr = env + .bitcoind + .client + .send_to_address(&addresses[3], Amount::from_sat(10000))? + .into_model()? + .txid; let _block_hashes = env.mine_blocks(1, None)?; while client.get_height().unwrap() < 103 { sleep(Duration::from_millis(10)) @@ -326,16 +323,11 @@ pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> { assert_eq!(full_scan_update.last_active_indices[&0], 3); // Now receive a coin on the last address. - let txid_last_addr = env.bitcoind.client.send_to_address( - &addresses[addresses.len() - 1], - Amount::from_sat(10000), - None, - None, - None, - None, - Some(1), - None, - )?; + let txid_last_addr = env + .bitcoind + .client + .send_to_address(&addresses[addresses.len() - 1], Amount::from_sat(10000))? + .txid()?; let _block_hashes = env.mine_blocks(1, None)?; while client.get_height().unwrap() < 104 { sleep(Duration::from_millis(10))