From: Leonardo Lima Date: Fri, 21 Mar 2025 23:46:30 +0000 (-0300) Subject: test(bdk_esplora,bdk_electrum): update to new `bdk_testenv` APIs X-Git-Url: http://internal-gitweb-vhost/%22https:/parse/scripts/database/-script/encode/struct.LocalUpdate.html?a=commitdiff_plain;h=cbad92eb69243dbe57d001556ffa31e21d223138;p=bdk test(bdk_esplora,bdk_electrum): update to new `bdk_testenv` APIs --- diff --git a/crates/electrum/benches/test_sync.rs b/crates/electrum/benches/test_sync.rs index 12ecf06a..39dd10d9 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 05b50187..25da3998 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 07979866..318708a1 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, }; 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,43 +216,47 @@ 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)?; // First unconfirmed tx. let txid1 = env.send(&tracked_addr, Amount::from_btc(1.0)?)?; - // Create second unconfirmed tx that spends the first. - let utxo = rpc_client - .list_unspent(None, Some(0), None, Some(true), None)? - .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)? + let raw_tx = rpc_client.get_raw_transaction(txid1)?.transaction()?; + let (vout, utxo) = raw_tx + .output + .iter() + .enumerate() + .find(|(_, utxo)| utxo.script_pubkey == tracked_addr.script_pubkey()) + .expect("must find the newly created UTXO"); + + let tx_that_spends_unconfirmed = rpc_client + .create_raw_transaction( + &[Input { + txid: raw_tx.compute_txid(), + vout: vout as u64, + sequence: None, + }], + &[Output::new( + tracked_addr.clone(), + utxo.value - 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 +294,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 +350,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 +407,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 +446,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 +502,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 +610,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 +642,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 +733,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 +768,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,44 +780,42 @@ 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() + .expect("should've successfully mined a block"); 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() + .expect("should've successfully mined a block"); // 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 outpoint = bdk_chain::bitcoin::OutPoint::new(prev_txid, vout); + let tx = env.rpc_client().get_transaction(txid)?.into_model()?.tx; + assert_eq!(tx.input.len(), 1); + assert_eq!(tx.output.len(), 1); + let outpoint = tx.input[0].previous_output; + let prev_txid = outpoint.txid; // Get the txout of the previous tx let prev_tx = env .rpc_client() - .get_raw_transaction_info(&prev_txid, prev_block_hash.as_ref())?; + .get_transaction(prev_txid)? + .into_model()? + .tx; let txout = prev_tx - .vout + .output .iter() .find(|txout| txout.value == prev_amt) - .unwrap(); - let script_pubkey = ScriptBuf::from_bytes(txout.script_pub_key.hex.to_vec()); - let txout = bdk_chain::bitcoin::TxOut { - value: txout.value, - script_pubkey, - }; + .expect("should've successfully found the existing `TxOut`"); // Sync up to tip. env.wait_until_electrum_sees_block(Duration::from_secs(6))?; @@ -846,7 +832,7 @@ fn test_check_fee_calculation() -> anyhow::Result<()> { .all_txouts() .find(|(_op, txout)| txout.value == prev_amt) .unwrap(); - assert_eq!(graph_txout, (outpoint, &txout)); + assert_eq!(graph_txout, (outpoint, txout)); // Check to see if tx is confirmed. assert_eq!( @@ -872,12 +858,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 c9cb17c1..d504a472 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 5f8ab531..9413c14a 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 3c628c20..209e5b78 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 4d5683e8..76ed28fb 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))