diff --git a/crates/chain/Cargo.toml b/crates/chain/Cargo.toml index 9085b5ec8..cfdaa1cab 100644 --- a/crates/chain/Cargo.toml +++ b/crates/chain/Cargo.toml @@ -28,6 +28,8 @@ serde_json = { version = "1", optional = true } [dev-dependencies] rand = "0.8" proptest = "1.2.0" +bdk_testenv = { path = "../testenv", default-features = false } + [features] default = ["std", "miniscript"] diff --git a/crates/chain/tests/common/mod.rs b/crates/chain/tests/common/mod.rs index 3fad37f93..cb3ee66f3 100644 --- a/crates/chain/tests/common/mod.rs +++ b/crates/chain/tests/common/mod.rs @@ -3,87 +3,3 @@ mod tx_template; #[allow(unused_imports)] pub use tx_template::*; - -#[allow(unused_macros)] -macro_rules! block_id { - ($height:expr, $hash:literal) => {{ - bdk_chain::BlockId { - height: $height, - hash: bitcoin::hashes::Hash::hash($hash.as_bytes()), - } - }}; -} - -#[allow(unused_macros)] -macro_rules! h { - ($index:literal) => {{ - bitcoin::hashes::Hash::hash($index.as_bytes()) - }}; -} - -#[allow(unused_macros)] -macro_rules! local_chain { - [ $(($height:expr, $block_hash:expr)), * ] => {{ - #[allow(unused_mut)] - bdk_chain::local_chain::LocalChain::from_blocks([$(($height, $block_hash).into()),*].into_iter().collect()) - .expect("chain must have genesis block") - }}; -} - -#[allow(unused_macros)] -macro_rules! chain_update { - [ $(($height:expr, $hash:expr)), * ] => {{ - #[allow(unused_mut)] - bdk_chain::local_chain::LocalChain::from_blocks([$(($height, $hash).into()),*].into_iter().collect()) - .expect("chain must have genesis block") - .tip() - }}; -} - -#[allow(unused_macros)] -macro_rules! changeset { - (checkpoints: $($tail:tt)*) => { changeset!(index: TxHeight, checkpoints: $($tail)*) }; - ( - index: $ind:ty, - checkpoints: [ $(( $height:expr, $cp_to:expr )),* ] - $(,txids: [ $(( $txid:expr, $tx_to:expr )),* ])? - ) => {{ - use bdk_chain::collections::BTreeMap; - - #[allow(unused_mut)] - bdk_chain::sparse_chain::ChangeSet::<$ind> { - checkpoints: { - let mut changes = BTreeMap::default(); - $(changes.insert($height, $cp_to);)* - changes - }, - txids: { - let mut changes = BTreeMap::default(); - $($(changes.insert($txid, $tx_to.map(|h: TxHeight| h.into()));)*)? - changes - } - } - }}; -} - -#[allow(unused)] -pub fn new_tx(lt: u32) -> bitcoin::Transaction { - bitcoin::Transaction { - version: bitcoin::transaction::Version::non_standard(0x00), - lock_time: bitcoin::absolute::LockTime::from_consensus(lt), - input: vec![], - output: vec![], - } -} - -#[allow(unused)] -pub const DESCRIPTORS: [&str; 7] = [ - "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)", - "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)", - "wpkh([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/0/*)", - "tr(tprv8ZgxMBicQKsPd3krDUsBAmtnRsK3rb8u5yi1zhQgMhF1tR8MW7xfE4rnrbbsrbPR52e7rKapu6ztw1jXveJSCGHEriUGZV7mCe88duLp5pj/86'/1'/0'/0/*)", - "tr(tprv8ZgxMBicQKsPd3krDUsBAmtnRsK3rb8u5yi1zhQgMhF1tR8MW7xfE4rnrbbsrbPR52e7rKapu6ztw1jXveJSCGHEriUGZV7mCe88duLp5pj/86'/1'/0'/1/*)", - "wpkh(xprv9s21ZrQH143K4EXURwMHuLS469fFzZyXk7UUpdKfQwhoHcAiYTakpe8pMU2RiEdvrU9McyuE7YDoKcXkoAwEGoK53WBDnKKv2zZbb9BzttX/1/0/*)", - // non-wildcard - "wpkh([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/0)", -]; diff --git a/crates/chain/tests/common/tx_template.rs b/crates/chain/tests/common/tx_template.rs index c7ce392e5..6ece64cbb 100644 --- a/crates/chain/tests/common/tx_template.rs +++ b/crates/chain/tests/common/tx_template.rs @@ -1,5 +1,6 @@ #![cfg(feature = "miniscript")] +use bdk_testenv::utils::DESCRIPTORS; use rand::distributions::{Alphanumeric, DistString}; use std::collections::HashMap; @@ -55,7 +56,7 @@ pub fn init_graph<'a, A: Anchor + Clone + 'a>( tx_templates: impl IntoIterator>, ) -> (TxGraph, SpkTxOutIndex, HashMap<&'a str, Txid>) { let (descriptor, _) = - Descriptor::parse_descriptor(&Secp256k1::signing_only(), super::DESCRIPTORS[2]).unwrap(); + Descriptor::parse_descriptor(&Secp256k1::signing_only(), DESCRIPTORS[2]).unwrap(); let mut graph = TxGraph::::default(); let mut spk_index = SpkTxOutIndex::default(); (0..10).for_each(|index| { diff --git a/crates/chain/tests/test_indexed_tx_graph.rs b/crates/chain/tests/test_indexed_tx_graph.rs index 1fbbcd0df..a8d17ca91 100644 --- a/crates/chain/tests/test_indexed_tx_graph.rs +++ b/crates/chain/tests/test_indexed_tx_graph.rs @@ -5,13 +5,16 @@ mod common; use std::{collections::BTreeSet, sync::Arc}; -use crate::common::DESCRIPTORS; use bdk_chain::{ indexed_tx_graph::{self, IndexedTxGraph}, indexer::keychain_txout::KeychainTxOutIndex, local_chain::LocalChain, tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt, }; +use bdk_testenv::{ + block_id, hash, + utils::{new_tx, DESCRIPTORS}, +}; use bitcoin::{secp256k1::Secp256k1, Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut}; use miniscript::Descriptor; @@ -49,7 +52,7 @@ fn insert_relevant_txs() { script_pubkey: spk_1, }, ], - ..common::new_tx(0) + ..new_tx(0) }; let tx_b = Transaction { @@ -57,7 +60,7 @@ fn insert_relevant_txs() { previous_output: OutPoint::new(tx_a.compute_txid(), 0), ..Default::default() }], - ..common::new_tx(1) + ..new_tx(1) }; let tx_c = Transaction { @@ -65,7 +68,7 @@ fn insert_relevant_txs() { previous_output: OutPoint::new(tx_a.compute_txid(), 1), ..Default::default() }], - ..common::new_tx(2) + ..new_tx(2) }; let txs = [tx_c, tx_b, tx_a]; @@ -126,15 +129,16 @@ fn insert_relevant_txs() { #[test] fn test_list_owned_txouts() { // Create Local chains - let local_chain = LocalChain::from_blocks((0..150).map(|i| (i as u32, h!("random"))).collect()) - .expect("must have genesis hash"); + let local_chain = + LocalChain::from_blocks((0..150).map(|i| (i as u32, hash!("random"))).collect()) + .expect("must have genesis hash"); // Initiate IndexedTxGraph let (desc_1, _) = - Descriptor::parse_descriptor(&Secp256k1::signing_only(), common::DESCRIPTORS[2]).unwrap(); + Descriptor::parse_descriptor(&Secp256k1::signing_only(), DESCRIPTORS[2]).unwrap(); let (desc_2, _) = - Descriptor::parse_descriptor(&Secp256k1::signing_only(), common::DESCRIPTORS[3]).unwrap(); + Descriptor::parse_descriptor(&Secp256k1::signing_only(), DESCRIPTORS[3]).unwrap(); let mut graph = IndexedTxGraph::>::new( KeychainTxOutIndex::new(10), @@ -187,7 +191,7 @@ fn test_list_owned_txouts() { value: Amount::from_sat(70000), script_pubkey: trusted_spks[0].to_owned(), }], - ..common::new_tx(0) + ..new_tx(0) }; // tx2 is an incoming transaction received at untrusted keychain at block 1. @@ -196,7 +200,7 @@ fn test_list_owned_txouts() { value: Amount::from_sat(30000), script_pubkey: untrusted_spks[0].to_owned(), }], - ..common::new_tx(0) + ..new_tx(0) }; // tx3 spends tx2 and gives a change back in trusted keychain. Confirmed at Block 2. @@ -209,7 +213,7 @@ fn test_list_owned_txouts() { value: Amount::from_sat(10000), script_pubkey: trusted_spks[1].to_owned(), }], - ..common::new_tx(0) + ..new_tx(0) }; // tx4 is an external transaction receiving at untrusted keychain, unconfirmed. @@ -218,7 +222,7 @@ fn test_list_owned_txouts() { value: Amount::from_sat(20000), script_pubkey: untrusted_spks[1].to_owned(), }], - ..common::new_tx(0) + ..new_tx(0) }; // tx5 is an external transaction receiving at trusted keychain, unconfirmed. @@ -227,11 +231,11 @@ fn test_list_owned_txouts() { value: Amount::from_sat(15000), script_pubkey: trusted_spks[2].to_owned(), }], - ..common::new_tx(0) + ..new_tx(0) }; // tx6 is an unrelated transaction confirmed at 3. - let tx6 = common::new_tx(0); + let tx6 = new_tx(0); // Insert transactions into graph with respective anchors // Insert unconfirmed txs with a last_seen timestamp @@ -597,7 +601,7 @@ fn test_get_chain_position() { value: Amount::ONE_BTC, script_pubkey: spk.clone(), }], - ..common::new_tx(0) + ..new_tx(0) }, anchor: None, last_seen: None, @@ -610,7 +614,7 @@ fn test_get_chain_position() { value: Amount::ONE_BTC, script_pubkey: spk.clone(), }], - ..common::new_tx(1) + ..new_tx(1) }, anchor: None, last_seen: Some(2), @@ -623,7 +627,7 @@ fn test_get_chain_position() { value: Amount::ONE_BTC, script_pubkey: spk.clone(), }], - ..common::new_tx(2) + ..new_tx(2) }, anchor: Some(blocks[1]), last_seen: None, @@ -636,7 +640,7 @@ fn test_get_chain_position() { value: Amount::ONE_BTC, script_pubkey: spk.clone(), }], - ..common::new_tx(3) + ..new_tx(3) }, anchor: Some(block_id!(2, "B'")), last_seen: Some(2), @@ -649,7 +653,7 @@ fn test_get_chain_position() { value: Amount::ONE_BTC, script_pubkey: spk.clone(), }], - ..common::new_tx(4) + ..new_tx(4) }, anchor: Some(block_id!(2, "B'")), last_seen: None, diff --git a/crates/chain/tests/test_keychain_txout_index.rs b/crates/chain/tests/test_keychain_txout_index.rs index 267ee2e99..9d80d5460 100644 --- a/crates/chain/tests/test_keychain_txout_index.rs +++ b/crates/chain/tests/test_keychain_txout_index.rs @@ -1,18 +1,17 @@ #![cfg(feature = "miniscript")] -#[macro_use] -mod common; use bdk_chain::{ collections::BTreeMap, indexer::keychain_txout::{ChangeSet, KeychainTxOutIndex}, DescriptorExt, DescriptorId, Indexer, Merge, }; - +use bdk_testenv::{ + hash, + utils::{new_tx, DESCRIPTORS}, +}; use bitcoin::{secp256k1::Secp256k1, Amount, OutPoint, ScriptBuf, Transaction, TxOut}; use miniscript::{Descriptor, DescriptorPublicKey}; -use crate::common::DESCRIPTORS; - #[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] enum TestKeychain { External, @@ -253,7 +252,7 @@ fn test_lookahead() { value: Amount::from_sat(10_000), }, ], - ..common::new_tx(external_index) + ..new_tx(external_index) }; assert_eq!(txout_index.index_tx(&tx), ChangeSet::default()); assert_eq!( @@ -305,7 +304,7 @@ fn test_scan_with_lookahead() { .collect(); for (&spk_i, spk) in &spks { - let op = OutPoint::new(h!("fake tx"), spk_i); + let op = OutPoint::new(hash!("fake tx"), spk_i); let txout = TxOut { script_pubkey: spk.clone(), value: Amount::ZERO, @@ -331,7 +330,7 @@ fn test_scan_with_lookahead() { .at_derivation_index(41) .unwrap() .script_pubkey(); - let op = OutPoint::new(h!("fake tx"), 41); + let op = OutPoint::new(hash!("fake tx"), 41); let txout = TxOut { script_pubkey: spk_41, value: Amount::ZERO, @@ -656,7 +655,7 @@ fn reassigning_keychain_to_a_new_descriptor_should_error() { #[test] fn when_querying_over_a_range_of_keychains_the_utxos_should_show_up() { let mut indexer = KeychainTxOutIndex::::new(0); - let mut tx = common::new_tx(0); + let mut tx = new_tx(0); for (i, descriptor) in DESCRIPTORS.iter().enumerate() { let descriptor = parse_descriptor(descriptor); diff --git a/crates/chain/tests/test_local_chain.rs b/crates/chain/tests/test_local_chain.rs index 29686564d..e8515c868 100644 --- a/crates/chain/tests/test_local_chain.rs +++ b/crates/chain/tests/test_local_chain.rs @@ -9,12 +9,10 @@ use bdk_chain::{ }, BlockId, }; +use bdk_testenv::{chain_update, hash, local_chain}; use bitcoin::{block::Header, hashes::Hash, BlockHash}; use proptest::prelude::*; -#[macro_use] -mod common; - #[derive(Debug)] struct TestLocalChain<'a> { name: &'static str, @@ -78,45 +76,45 @@ fn update_local_chain() { [ TestLocalChain { name: "add first tip", - chain: local_chain![(0, h!("A"))], - update: chain_update![(0, h!("A"))], + chain: local_chain![(0, hash!("A"))], + update: chain_update![(0, hash!("A"))], exp: ExpectedResult::Ok { changeset: &[], - init_changeset: &[(0, Some(h!("A")))], + init_changeset: &[(0, Some(hash!("A")))], }, }, TestLocalChain { name: "add second tip", - chain: local_chain![(0, h!("A"))], - update: chain_update![(0, h!("A")), (1, h!("B"))], + chain: local_chain![(0, hash!("A"))], + update: chain_update![(0, hash!("A")), (1, hash!("B"))], exp: ExpectedResult::Ok { - changeset: &[(1, Some(h!("B")))], - init_changeset: &[(0, Some(h!("A"))), (1, Some(h!("B")))], + changeset: &[(1, Some(hash!("B")))], + init_changeset: &[(0, Some(hash!("A"))), (1, Some(hash!("B")))], }, }, TestLocalChain { name: "two disjoint chains cannot merge", - chain: local_chain![(0, h!("_")), (1, h!("A"))], - update: chain_update![(0, h!("_")), (2, h!("B"))], + chain: local_chain![(0, hash!("_")), (1, hash!("A"))], + update: chain_update![(0, hash!("_")), (2, hash!("B"))], exp: ExpectedResult::Err(CannotConnectError { try_include_height: 1, }), }, TestLocalChain { name: "two disjoint chains cannot merge (existing chain longer)", - chain: local_chain![(0, h!("_")), (2, h!("A"))], - update: chain_update![(0, h!("_")), (1, h!("B"))], + chain: local_chain![(0, hash!("_")), (2, hash!("A"))], + update: chain_update![(0, hash!("_")), (1, hash!("B"))], exp: ExpectedResult::Err(CannotConnectError { try_include_height: 2, }), }, TestLocalChain { name: "duplicate chains should merge", - chain: local_chain![(0, h!("A"))], - update: chain_update![(0, h!("A"))], + chain: local_chain![(0, hash!("A"))], + update: chain_update![(0, hash!("A"))], exp: ExpectedResult::Ok { changeset: &[], - init_changeset: &[(0, Some(h!("A")))], + init_changeset: &[(0, Some(hash!("A")))], }, }, // Introduce an older checkpoint (B) @@ -125,11 +123,11 @@ fn update_local_chain() { // update | _ B C TestLocalChain { name: "can introduce older checkpoint", - chain: local_chain![(0, h!("_")), (2, h!("C")), (3, h!("D"))], - update: chain_update![(0, h!("_")), (1, h!("B")), (2, h!("C"))], + chain: local_chain![(0, hash!("_")), (2, hash!("C")), (3, hash!("D"))], + update: chain_update![(0, hash!("_")), (1, hash!("B")), (2, hash!("C"))], exp: ExpectedResult::Ok { - changeset: &[(1, Some(h!("B")))], - init_changeset: &[(0, Some(h!("_"))), (1, Some(h!("B"))), (2, Some(h!("C"))), (3, Some(h!("D")))], + changeset: &[(1, Some(hash!("B")))], + init_changeset: &[(0, Some(hash!("_"))), (1, Some(hash!("B"))), (2, Some(hash!("C"))), (3, Some(hash!("D")))], }, }, // Introduce an older checkpoint (A) that is not directly behind PoA @@ -138,11 +136,11 @@ fn update_local_chain() { // update | _ A C TestLocalChain { name: "can introduce older checkpoint 2", - chain: local_chain![(0, h!("_")), (3, h!("B")), (4, h!("C"))], - update: chain_update![(0, h!("_")), (2, h!("A")), (4, h!("C"))], + chain: local_chain![(0, hash!("_")), (3, hash!("B")), (4, hash!("C"))], + update: chain_update![(0, hash!("_")), (2, hash!("A")), (4, hash!("C"))], exp: ExpectedResult::Ok { - changeset: &[(2, Some(h!("A")))], - init_changeset: &[(0, Some(h!("_"))), (2, Some(h!("A"))), (3, Some(h!("B"))), (4, Some(h!("C")))], + changeset: &[(2, Some(hash!("A")))], + init_changeset: &[(0, Some(hash!("_"))), (2, Some(hash!("A"))), (3, Some(hash!("B"))), (4, Some(hash!("C")))], } }, // Introduce an older checkpoint (B) that is not the oldest checkpoint @@ -151,11 +149,11 @@ fn update_local_chain() { // update | _ B C TestLocalChain { name: "can introduce older checkpoint 3", - chain: local_chain![(0, h!("_")), (1, h!("A")), (3, h!("C"))], - update: chain_update![(0, h!("_")), (2, h!("B")), (3, h!("C"))], + chain: local_chain![(0, hash!("_")), (1, hash!("A")), (3, hash!("C"))], + update: chain_update![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], exp: ExpectedResult::Ok { - changeset: &[(2, Some(h!("B")))], - init_changeset: &[(0, Some(h!("_"))), (1, Some(h!("A"))), (2, Some(h!("B"))), (3, Some(h!("C")))], + changeset: &[(2, Some(hash!("B")))], + init_changeset: &[(0, Some(hash!("_"))), (1, Some(hash!("A"))), (2, Some(hash!("B"))), (3, Some(hash!("C")))], } }, // Introduce two older checkpoints below the PoA @@ -164,20 +162,20 @@ fn update_local_chain() { // update | _ A B C TestLocalChain { name: "introduce two older checkpoints below PoA", - chain: local_chain![(0, h!("_")), (3, h!("C"))], - update: chain_update![(0, h!("_")), (1, h!("A")), (2, h!("B")), (3, h!("C"))], + chain: local_chain![(0, hash!("_")), (3, hash!("C"))], + update: chain_update![(0, hash!("_")), (1, hash!("A")), (2, hash!("B")), (3, hash!("C"))], exp: ExpectedResult::Ok { - changeset: &[(1, Some(h!("A"))), (2, Some(h!("B")))], - init_changeset: &[(0, Some(h!("_"))), (1, Some(h!("A"))), (2, Some(h!("B"))), (3, Some(h!("C")))], + changeset: &[(1, Some(hash!("A"))), (2, Some(hash!("B")))], + init_changeset: &[(0, Some(hash!("_"))), (1, Some(hash!("A"))), (2, Some(hash!("B"))), (3, Some(hash!("C")))], }, }, TestLocalChain { name: "fix blockhash before agreement point", - chain: local_chain![(0, h!("im-wrong")), (1, h!("we-agree"))], - update: chain_update![(0, h!("fix")), (1, h!("we-agree"))], + chain: local_chain![(0, hash!("im-wrong")), (1, hash!("we-agree"))], + update: chain_update![(0, hash!("fix")), (1, hash!("we-agree"))], exp: ExpectedResult::Ok { - changeset: &[(0, Some(h!("fix")))], - init_changeset: &[(0, Some(h!("fix"))), (1, Some(h!("we-agree")))], + changeset: &[(0, Some(hash!("fix")))], + init_changeset: &[(0, Some(hash!("fix"))), (1, Some(hash!("we-agree")))], }, }, // B and C are in both chain and update @@ -187,16 +185,16 @@ fn update_local_chain() { // This should succeed with the point of agreement being C and A should be added in addition. TestLocalChain { name: "two points of agreement", - chain: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C"))], - update: chain_update![(0, h!("_")), (1, h!("A")), (2, h!("B")), (3, h!("C")), (4, h!("D"))], + chain: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], + update: chain_update![(0, hash!("_")), (1, hash!("A")), (2, hash!("B")), (3, hash!("C")), (4, hash!("D"))], exp: ExpectedResult::Ok { - changeset: &[(1, Some(h!("A"))), (4, Some(h!("D")))], + changeset: &[(1, Some(hash!("A"))), (4, Some(hash!("D")))], init_changeset: &[ - (0, Some(h!("_"))), - (1, Some(h!("A"))), - (2, Some(h!("B"))), - (3, Some(h!("C"))), - (4, Some(h!("D"))), + (0, Some(hash!("_"))), + (1, Some(hash!("A"))), + (2, Some(hash!("B"))), + (3, Some(hash!("C"))), + (4, Some(hash!("D"))), ], }, }, @@ -207,8 +205,8 @@ fn update_local_chain() { // This should fail as we cannot figure out whether C & D are on the same chain TestLocalChain { name: "update and chain does not connect", - chain: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C"))], - update: chain_update![(0, h!("_")), (1, h!("A")), (2, h!("B")), (4, h!("D"))], + chain: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], + update: chain_update![(0, hash!("_")), (1, hash!("A")), (2, hash!("B")), (4, hash!("D"))], exp: ExpectedResult::Err(CannotConnectError { try_include_height: 3, }), @@ -220,20 +218,20 @@ fn update_local_chain() { // This should succeed and invalidate B,C and E with point of agreement being A. TestLocalChain { name: "transitive invalidation applies to checkpoints higher than invalidation", - chain: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C")), (5, h!("E"))], - update: chain_update![(0, h!("_")), (2, h!("B'")), (3, h!("C'")), (4, h!("D"))], + chain: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C")), (5, hash!("E"))], + update: chain_update![(0, hash!("_")), (2, hash!("B'")), (3, hash!("C'")), (4, hash!("D"))], exp: ExpectedResult::Ok { changeset: &[ - (2, Some(h!("B'"))), - (3, Some(h!("C'"))), - (4, Some(h!("D"))), + (2, Some(hash!("B'"))), + (3, Some(hash!("C'"))), + (4, Some(hash!("D"))), (5, None), ], init_changeset: &[ - (0, Some(h!("_"))), - (2, Some(h!("B'"))), - (3, Some(h!("C'"))), - (4, Some(h!("D"))), + (0, Some(hash!("_"))), + (2, Some(hash!("B'"))), + (3, Some(hash!("C'"))), + (4, Some(hash!("D"))), ], }, }, @@ -244,20 +242,20 @@ fn update_local_chain() { // This should succeed and invalidate B, C and E with no point of agreement TestLocalChain { name: "transitive invalidation applies to checkpoints higher than invalidation no point of agreement", - chain: local_chain![(0, h!("_")), (1, h!("B")), (2, h!("C")), (4, h!("E"))], - update: chain_update![(0, h!("_")), (1, h!("B'")), (2, h!("C'")), (3, h!("D"))], + chain: local_chain![(0, hash!("_")), (1, hash!("B")), (2, hash!("C")), (4, hash!("E"))], + update: chain_update![(0, hash!("_")), (1, hash!("B'")), (2, hash!("C'")), (3, hash!("D"))], exp: ExpectedResult::Ok { changeset: &[ - (1, Some(h!("B'"))), - (2, Some(h!("C'"))), - (3, Some(h!("D"))), + (1, Some(hash!("B'"))), + (2, Some(hash!("C'"))), + (3, Some(hash!("D"))), (4, None) ], init_changeset: &[ - (0, Some(h!("_"))), - (1, Some(h!("B'"))), - (2, Some(h!("C'"))), - (3, Some(h!("D"))), + (0, Some(hash!("_"))), + (1, Some(hash!("B'"))), + (2, Some(hash!("C'"))), + (3, Some(hash!("D"))), ], }, }, @@ -269,8 +267,8 @@ fn update_local_chain() { // A was invalid. TestLocalChain { name: "invalidation but no connection", - chain: local_chain![(0, h!("_")), (1, h!("A")), (2, h!("B")), (3, h!("C")), (5, h!("E"))], - update: chain_update![(0, h!("_")), (2, h!("B'")), (3, h!("C'")), (4, h!("D"))], + chain: local_chain![(0, hash!("_")), (1, hash!("A")), (2, hash!("B")), (3, hash!("C")), (5, hash!("E"))], + update: chain_update![(0, hash!("_")), (2, hash!("B'")), (3, hash!("C'")), (4, hash!("D"))], exp: ExpectedResult::Err(CannotConnectError { try_include_height: 1 }), }, // Introduce blocks between two points of agreement @@ -279,20 +277,20 @@ fn update_local_chain() { // update | A C E F TestLocalChain { name: "introduce blocks between two points of agreement", - chain: local_chain![(0, h!("A")), (1, h!("B")), (3, h!("D")), (4, h!("E"))], - update: chain_update![(0, h!("A")), (2, h!("C")), (4, h!("E")), (5, h!("F"))], + chain: local_chain![(0, hash!("A")), (1, hash!("B")), (3, hash!("D")), (4, hash!("E"))], + update: chain_update![(0, hash!("A")), (2, hash!("C")), (4, hash!("E")), (5, hash!("F"))], exp: ExpectedResult::Ok { changeset: &[ - (2, Some(h!("C"))), - (5, Some(h!("F"))), + (2, Some(hash!("C"))), + (5, Some(hash!("F"))), ], init_changeset: &[ - (0, Some(h!("A"))), - (1, Some(h!("B"))), - (2, Some(h!("C"))), - (3, Some(h!("D"))), - (4, Some(h!("E"))), - (5, Some(h!("F"))), + (0, Some(hash!("A"))), + (1, Some(hash!("B"))), + (2, Some(hash!("C"))), + (3, Some(hash!("D"))), + (4, Some(hash!("E"))), + (5, Some(hash!("F"))), ], }, }, @@ -302,18 +300,18 @@ fn update_local_chain() { // update | A C D' TestLocalChain { name: "allow update that is shorter than original chain", - chain: local_chain![(0, h!("_")), (2, h!("C")), (3, h!("D")), (4, h!("E")), (5, h!("F"))], - update: chain_update![(0, h!("_")), (2, h!("C")), (3, h!("D'"))], + chain: local_chain![(0, hash!("_")), (2, hash!("C")), (3, hash!("D")), (4, hash!("E")), (5, hash!("F"))], + update: chain_update![(0, hash!("_")), (2, hash!("C")), (3, hash!("D'"))], exp: ExpectedResult::Ok { changeset: &[ - (3, Some(h!("D'"))), + (3, Some(hash!("D'"))), (4, None), (5, None), ], init_changeset: &[ - (0, Some(h!("_"))), - (2, Some(h!("C"))), - (3, Some(h!("D'"))), + (0, Some(hash!("_"))), + (2, Some(hash!("C"))), + (3, Some(hash!("D'"))), ], }, }, @@ -333,38 +331,38 @@ fn local_chain_insert_block() { let test_cases = [ TestCase { - original: local_chain![(0, h!("_"))], - insert: (5, h!("block5")), - expected_result: Ok([(5, Some(h!("block5")))].into()), - expected_final: local_chain![(0, h!("_")), (5, h!("block5"))], + original: local_chain![(0, hash!("_"))], + insert: (5, hash!("block5")), + expected_result: Ok([(5, Some(hash!("block5")))].into()), + expected_final: local_chain![(0, hash!("_")), (5, hash!("block5"))], }, TestCase { - original: local_chain![(0, h!("_")), (3, h!("A"))], - insert: (4, h!("B")), - expected_result: Ok([(4, Some(h!("B")))].into()), - expected_final: local_chain![(0, h!("_")), (3, h!("A")), (4, h!("B"))], + original: local_chain![(0, hash!("_")), (3, hash!("A"))], + insert: (4, hash!("B")), + expected_result: Ok([(4, Some(hash!("B")))].into()), + expected_final: local_chain![(0, hash!("_")), (3, hash!("A")), (4, hash!("B"))], }, TestCase { - original: local_chain![(0, h!("_")), (4, h!("B"))], - insert: (3, h!("A")), - expected_result: Ok([(3, Some(h!("A")))].into()), - expected_final: local_chain![(0, h!("_")), (3, h!("A")), (4, h!("B"))], + original: local_chain![(0, hash!("_")), (4, hash!("B"))], + insert: (3, hash!("A")), + expected_result: Ok([(3, Some(hash!("A")))].into()), + expected_final: local_chain![(0, hash!("_")), (3, hash!("A")), (4, hash!("B"))], }, TestCase { - original: local_chain![(0, h!("_")), (2, h!("K"))], - insert: (2, h!("K")), + original: local_chain![(0, hash!("_")), (2, hash!("K"))], + insert: (2, hash!("K")), expected_result: Ok([].into()), - expected_final: local_chain![(0, h!("_")), (2, h!("K"))], + expected_final: local_chain![(0, hash!("_")), (2, hash!("K"))], }, TestCase { - original: local_chain![(0, h!("_")), (2, h!("K"))], - insert: (2, h!("J")), + original: local_chain![(0, hash!("_")), (2, hash!("K"))], + insert: (2, hash!("J")), expected_result: Err(AlterCheckPointError { height: 2, - original_hash: h!("K"), - update_hash: Some(h!("J")), + original_hash: hash!("K"), + update_hash: Some(hash!("J")), }), - expected_final: local_chain![(0, h!("_")), (2, h!("K"))], + expected_final: local_chain![(0, hash!("_")), (2, hash!("K"))], }, ]; @@ -393,45 +391,50 @@ fn local_chain_disconnect_from() { let test_cases = [ TestCase { name: "try_replace_genesis_should_fail", - original: local_chain![(0, h!("_"))], - disconnect_from: (0, h!("_")), + original: local_chain![(0, hash!("_"))], + disconnect_from: (0, hash!("_")), exp_result: Err(MissingGenesisError), - exp_final: local_chain![(0, h!("_"))], + exp_final: local_chain![(0, hash!("_"))], }, TestCase { name: "try_replace_genesis_should_fail_2", - original: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C"))], - disconnect_from: (0, h!("_")), + original: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], + disconnect_from: (0, hash!("_")), exp_result: Err(MissingGenesisError), - exp_final: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C"))], + exp_final: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], }, TestCase { name: "from_does_not_exist", - original: local_chain![(0, h!("_")), (3, h!("C"))], - disconnect_from: (2, h!("B")), + original: local_chain![(0, hash!("_")), (3, hash!("C"))], + disconnect_from: (2, hash!("B")), exp_result: Ok(ChangeSet::default()), - exp_final: local_chain![(0, h!("_")), (3, h!("C"))], + exp_final: local_chain![(0, hash!("_")), (3, hash!("C"))], }, TestCase { name: "from_has_different_blockhash", - original: local_chain![(0, h!("_")), (2, h!("B"))], - disconnect_from: (2, h!("not_B")), + original: local_chain![(0, hash!("_")), (2, hash!("B"))], + disconnect_from: (2, hash!("not_B")), exp_result: Ok(ChangeSet::default()), - exp_final: local_chain![(0, h!("_")), (2, h!("B"))], + exp_final: local_chain![(0, hash!("_")), (2, hash!("B"))], }, TestCase { name: "disconnect_one", - original: local_chain![(0, h!("_")), (2, h!("B"))], - disconnect_from: (2, h!("B")), + original: local_chain![(0, hash!("_")), (2, hash!("B"))], + disconnect_from: (2, hash!("B")), exp_result: Ok(ChangeSet::from_iter([(2, None)])), - exp_final: local_chain![(0, h!("_"))], + exp_final: local_chain![(0, hash!("_"))], }, TestCase { name: "disconnect_three", - original: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C")), (4, h!("D"))], - disconnect_from: (2, h!("B")), + original: local_chain![ + (0, hash!("_")), + (2, hash!("B")), + (3, hash!("C")), + (4, hash!("D")) + ], + disconnect_from: (2, hash!("B")), exp_result: Ok(ChangeSet::from_iter([(2, None), (3, None), (4, None)])), - exp_final: local_chain![(0, h!("_"))], + exp_final: local_chain![(0, hash!("_"))], }, ]; @@ -462,18 +465,18 @@ fn checkpoint_from_block_ids() { let test_cases = [ TestCase { name: "in_order", - blocks: &[(0, h!("A")), (1, h!("B")), (3, h!("D"))], + blocks: &[(0, hash!("A")), (1, hash!("B")), (3, hash!("D"))], exp_result: Ok(()), }, TestCase { name: "with_duplicates", - blocks: &[(1, h!("B")), (2, h!("C")), (2, h!("C'"))], - exp_result: Err(Some((2, h!("C")))), + blocks: &[(1, hash!("B")), (2, hash!("C")), (2, hash!("C'"))], + exp_result: Err(Some((2, hash!("C")))), }, TestCase { name: "not_in_order", - blocks: &[(1, h!("B")), (3, h!("D")), (2, h!("C"))], - exp_result: Err(Some((3, h!("D")))), + blocks: &[(1, hash!("B")), (3, hash!("D")), (2, hash!("C"))], + exp_result: Err(Some((3, hash!("D")))), }, TestCase { name: "empty", @@ -482,7 +485,7 @@ fn checkpoint_from_block_ids() { }, TestCase { name: "single", - blocks: &[(21, h!("million"))], + blocks: &[(21, hash!("million"))], exp_result: Ok(()), }, ]; @@ -543,11 +546,11 @@ fn checkpoint_query() { let test_cases = [ TestCase { - chain: local_chain![(0, h!("_")), (1, h!("A"))], + chain: local_chain![(0, hash!("_")), (1, hash!("A"))], query_range: (0, 2), }, TestCase { - chain: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C"))], + chain: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], query_range: (0, 3), }, ]; @@ -592,38 +595,48 @@ fn checkpoint_insert() { let test_cases = [ TestCase { name: "insert_above_tip", - chain: &[(1, h!("a")), (2, h!("b"))], - to_insert: (4, h!("d")), - exp_final_chain: &[(1, h!("a")), (2, h!("b")), (4, h!("d"))], + chain: &[(1, hash!("a")), (2, hash!("b"))], + to_insert: (4, hash!("d")), + exp_final_chain: &[(1, hash!("a")), (2, hash!("b")), (4, hash!("d"))], }, TestCase { name: "insert_already_exists_expect_no_change", - chain: &[(1, h!("a")), (2, h!("b")), (3, h!("c"))], - to_insert: (2, h!("b")), - exp_final_chain: &[(1, h!("a")), (2, h!("b")), (3, h!("c"))], + chain: &[(1, hash!("a")), (2, hash!("b")), (3, hash!("c"))], + to_insert: (2, hash!("b")), + exp_final_chain: &[(1, hash!("a")), (2, hash!("b")), (3, hash!("c"))], }, TestCase { name: "insert_in_middle", - chain: &[(2, h!("b")), (4, h!("d")), (5, h!("e"))], - to_insert: (3, h!("c")), - exp_final_chain: &[(2, h!("b")), (3, h!("c")), (4, h!("d")), (5, h!("e"))], + chain: &[(2, hash!("b")), (4, hash!("d")), (5, hash!("e"))], + to_insert: (3, hash!("c")), + exp_final_chain: &[ + (2, hash!("b")), + (3, hash!("c")), + (4, hash!("d")), + (5, hash!("e")), + ], }, TestCase { name: "replace_one", - chain: &[(3, h!("c")), (4, h!("d")), (5, h!("e"))], - to_insert: (5, h!("E")), - exp_final_chain: &[(3, h!("c")), (4, h!("d")), (5, h!("E"))], + chain: &[(3, hash!("c")), (4, hash!("d")), (5, hash!("e"))], + to_insert: (5, hash!("E")), + exp_final_chain: &[(3, hash!("c")), (4, hash!("d")), (5, hash!("E"))], }, TestCase { name: "insert_conflict_should_evict", - chain: &[(3, h!("c")), (4, h!("d")), (5, h!("e")), (6, h!("f"))], - to_insert: (4, h!("D")), - exp_final_chain: &[(3, h!("c")), (4, h!("D"))], + chain: &[ + (3, hash!("c")), + (4, hash!("d")), + (5, hash!("e")), + (6, hash!("f")), + ], + to_insert: (4, hash!("D")), + exp_final_chain: &[(3, hash!("c")), (4, hash!("D"))], }, ]; fn genesis_block() -> impl Iterator { - core::iter::once((0, h!("_"))).map(BlockId::from) + core::iter::once((0, hash!("_"))).map(BlockId::from) } for t in test_cases.into_iter() { @@ -669,13 +682,13 @@ fn local_chain_apply_header_connected_to() { let test_cases = [ { - let header = header_from_prev_blockhash(h!("_")); + let header = header_from_prev_blockhash(hash!("_")); let hash = header.block_hash(); let height = 1; let connected_to = BlockId { height, hash }; TestCase { name: "connected_to_self_header_applied_to_self", - chain: local_chain![(0, h!("_")), (height, hash)], + chain: local_chain![(0, hash!("_")), (height, hash)], header, height, connected_to, @@ -683,7 +696,7 @@ fn local_chain_apply_header_connected_to() { } }, { - let prev_hash = h!("A"); + let prev_hash = hash!("A"); let prev_height = 1; let header = header_from_prev_blockhash(prev_hash); let hash = header.block_hash(); @@ -694,7 +707,7 @@ fn local_chain_apply_header_connected_to() { }; TestCase { name: "connected_to_prev_header_applied_to_self", - chain: local_chain![(0, h!("_")), (prev_height, prev_hash)], + chain: local_chain![(0, hash!("_")), (prev_height, prev_hash)], header, height, connected_to, @@ -716,34 +729,34 @@ fn local_chain_apply_header_connected_to() { } }, { - let header = header_from_prev_blockhash(h!("Z")); + let header = header_from_prev_blockhash(hash!("Z")); let height = 10; let hash = header.block_hash(); let prev_height = height - 1; let prev_hash = header.prev_blockhash; TestCase { name: "connect_at_connected_to", - chain: local_chain![(0, h!("_")), (2, h!("B")), (3, h!("C"))], + chain: local_chain![(0, hash!("_")), (2, hash!("B")), (3, hash!("C"))], header, height: 10, connected_to: BlockId { height: 3, - hash: h!("C"), + hash: hash!("C"), }, exp_result: Ok(vec![(prev_height, Some(prev_hash)), (height, Some(hash))]), } }, { - let prev_hash = h!("A"); + let prev_hash = hash!("A"); let prev_height = 1; let header = header_from_prev_blockhash(prev_hash); let connected_to = BlockId { height: prev_height, - hash: h!("not_prev_hash"), + hash: hash!("not_prev_hash"), }; TestCase { name: "inconsistent_prev_hash", - chain: local_chain![(0, h!("_")), (prev_height, h!("not_prev_hash"))], + chain: local_chain![(0, hash!("_")), (prev_height, hash!("not_prev_hash"))], header, height: prev_height + 1, connected_to, @@ -751,17 +764,17 @@ fn local_chain_apply_header_connected_to() { } }, { - let prev_hash = h!("A"); + let prev_hash = hash!("A"); let prev_height = 1; let header = header_from_prev_blockhash(prev_hash); let height = prev_height + 1; let connected_to = BlockId { height, - hash: h!("not_current_hash"), + hash: hash!("not_current_hash"), }; TestCase { name: "inconsistent_current_block", - chain: local_chain![(0, h!("_")), (height, h!("not_current_hash"))], + chain: local_chain![(0, hash!("_")), (height, hash!("not_current_hash"))], header, height, connected_to, @@ -769,15 +782,15 @@ fn local_chain_apply_header_connected_to() { } }, { - let header = header_from_prev_blockhash(h!("B")); + let header = header_from_prev_blockhash(hash!("B")); let height = 3; let connected_to = BlockId { height: 4, - hash: h!("D"), + hash: hash!("D"), }; TestCase { name: "connected_to_is_greater", - chain: local_chain![(0, h!("_")), (2, h!("B"))], + chain: local_chain![(0, hash!("_")), (2, hash!("B"))], header, height, connected_to, diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index a49c9e5f5..08be91c7a 100644 --- a/crates/chain/tests/test_tx_graph.rs +++ b/crates/chain/tests/test_tx_graph.rs @@ -9,6 +9,7 @@ use bdk_chain::{ tx_graph::{ChangeSet, TxGraph}, Anchor, ChainOracle, ChainPosition, Merge, }; +use bdk_testenv::{block_id, hash, utils::new_tx}; use bitcoin::{ absolute, hashes::Hash, transaction, Amount, BlockHash, OutPoint, ScriptBuf, SignedAmount, Transaction, TxIn, TxOut, Txid, @@ -24,14 +25,14 @@ fn insert_txouts() { // 2 (Outpoint, TxOut) tuples that denotes original data in the graph, as partial transactions. let original_ops = [ ( - OutPoint::new(h!("tx1"), 1), + OutPoint::new(hash!("tx1"), 1), TxOut { value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new(), }, ), ( - OutPoint::new(h!("tx1"), 2), + OutPoint::new(hash!("tx1"), 2), TxOut { value: Amount::from_sat(20_000), script_pubkey: ScriptBuf::new(), @@ -41,7 +42,7 @@ fn insert_txouts() { // Another (OutPoint, TxOut) tuple to be used as update as partial transaction. let update_ops = [( - OutPoint::new(h!("tx2"), 0), + OutPoint::new(hash!("tx2"), 0), TxOut { value: Amount::from_sat(20_000), script_pubkey: ScriptBuf::new(), @@ -65,7 +66,7 @@ fn insert_txouts() { // Conf anchor used to mark the full transaction as confirmed. let conf_anchor = BlockId { height: 100, - hash: h!("random blockhash"), + hash: hash!("random blockhash"), }; // Unconfirmed seen_at timestamp to mark the partial transactions as unconfirmed. @@ -114,7 +115,7 @@ fn insert_txouts() { txs: [Arc::new(update_tx.clone())].into(), txouts: update_ops.clone().into(), anchors: [(conf_anchor, update_tx.compute_txid()),].into(), - last_seen: [(h!("tx2"), 1000000)].into() + last_seen: [(hash!("tx2"), 1000000)].into() } ); @@ -126,7 +127,7 @@ fn insert_txouts() { // Check TxOuts are fetched correctly from the graph. assert_eq!( - graph.tx_outputs(h!("tx1")).expect("should exists"), + graph.tx_outputs(hash!("tx1")).expect("should exists"), [ ( 1u32, @@ -167,7 +168,7 @@ fn insert_txouts() { txs: [Arc::new(update_tx.clone())].into(), txouts: update_ops.into_iter().chain(original_ops).collect(), anchors: [(conf_anchor, update_tx.compute_txid()),].into(), - last_seen: [(h!("tx2"), 1000000)].into() + last_seen: [(hash!("tx2"), 1000000)].into() } ); } @@ -361,7 +362,7 @@ fn test_calculate_fee() { let intxout1 = ( OutPoint { - txid: h!("dangling output"), + txid: hash!("dangling output"), vout: 0, }, TxOut { @@ -415,7 +416,7 @@ fn test_calculate_fee() { // If we have an unknown outpoint, fee should return CalculateFeeError::MissingTxOut. let outpoint = OutPoint { - txid: h!("unknown_txid"), + txid: hash!("unknown_txid"), vout: 0, }; tx.input.push(TxIn { @@ -470,11 +471,11 @@ fn test_walk_ancestors() { let tx_a0 = Transaction { input: vec![TxIn { - previous_output: OutPoint::new(h!("op0"), 0), + previous_output: OutPoint::new(hash!("op0"), 0), ..TxIn::default() }], output: vec![TxOut::NULL, TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_b0 spends tx_a0 @@ -484,7 +485,7 @@ fn test_walk_ancestors() { ..TxIn::default() }], output: vec![TxOut::NULL, TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_b1 spends tx_a0 @@ -494,16 +495,16 @@ fn test_walk_ancestors() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; let tx_b2 = Transaction { input: vec![TxIn { - previous_output: OutPoint::new(h!("op1"), 0), + previous_output: OutPoint::new(hash!("op1"), 0), ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_c0 spends tx_b0 @@ -513,7 +514,7 @@ fn test_walk_ancestors() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_c1 spends tx_b0 @@ -523,7 +524,7 @@ fn test_walk_ancestors() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_c2 spends tx_b1 and tx_b2 @@ -539,16 +540,16 @@ fn test_walk_ancestors() { }, ], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; let tx_c3 = Transaction { input: vec![TxIn { - previous_output: OutPoint::new(h!("op2"), 0), + previous_output: OutPoint::new(hash!("op2"), 0), ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_d0 spends tx_c1 @@ -558,7 +559,7 @@ fn test_walk_ancestors() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_d1 spends tx_c2 and tx_c3 @@ -574,7 +575,7 @@ fn test_walk_ancestors() { }, ], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_e0 spends tx_d1 @@ -584,7 +585,7 @@ fn test_walk_ancestors() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; let mut graph = TxGraph::::new([ @@ -658,7 +659,7 @@ fn test_walk_ancestors() { #[test] fn test_conflicting_descendants() { - let previous_output = OutPoint::new(h!("op"), 2); + let previous_output = OutPoint::new(hash!("op"), 2); // tx_a spends previous_output let tx_a = Transaction { @@ -667,7 +668,7 @@ fn test_conflicting_descendants() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; // tx_a2 spends previous_output and conflicts with tx_a @@ -677,7 +678,7 @@ fn test_conflicting_descendants() { ..TxIn::default() }], output: vec![TxOut::NULL, TxOut::NULL], - ..common::new_tx(1) + ..new_tx(1) }; // tx_b spends tx_a @@ -687,7 +688,7 @@ fn test_conflicting_descendants() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(2) + ..new_tx(2) }; let txid_a = tx_a.compute_txid(); @@ -709,7 +710,7 @@ fn test_conflicting_descendants() { fn test_descendants_no_repeat() { let tx_a = Transaction { output: vec![TxOut::NULL, TxOut::NULL, TxOut::NULL], - ..common::new_tx(0) + ..new_tx(0) }; let txs_b = (0..3) @@ -719,7 +720,7 @@ fn test_descendants_no_repeat() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(1) + ..new_tx(1) }) .collect::>(); @@ -730,7 +731,7 @@ fn test_descendants_no_repeat() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(2) + ..new_tx(2) }) .collect::>(); @@ -746,7 +747,7 @@ fn test_descendants_no_repeat() { }, ], output: vec![TxOut::NULL], - ..common::new_tx(3) + ..new_tx(3) }; let tx_e = Transaction { @@ -755,17 +756,17 @@ fn test_descendants_no_repeat() { ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(4) + ..new_tx(4) }; let txs_not_connected = (10..20) .map(|v| Transaction { input: vec![TxIn { - previous_output: OutPoint::new(h!("tx_does_not_exist"), v), + previous_output: OutPoint::new(hash!("tx_does_not_exist"), v), ..TxIn::default() }], output: vec![TxOut::NULL], - ..common::new_tx(v) + ..new_tx(v) }) .collect::>(); @@ -819,7 +820,7 @@ fn test_chain_spends() { script_pubkey: ScriptBuf::new(), }, ], - ..common::new_tx(0) + ..new_tx(0) }; // The first confirmed transaction spends vout: 0. And is confirmed at block 98. @@ -838,7 +839,7 @@ fn test_chain_spends() { script_pubkey: ScriptBuf::new(), }, ], - ..common::new_tx(0) + ..new_tx(0) }; // The second transactions spends vout:1, and is unconfirmed. @@ -857,7 +858,7 @@ fn test_chain_spends() { script_pubkey: ScriptBuf::new(), }, ], - ..common::new_tx(0) + ..new_tx(0) }; let mut graph = TxGraph::::default(); @@ -929,7 +930,7 @@ fn test_chain_spends() { previous_output: OutPoint::new(tx_0.compute_txid(), 0), ..Default::default() }], - ..common::new_tx(0) + ..new_tx(0) }; let _ = graph.insert_tx(tx_1_conflict.clone()); @@ -944,7 +945,7 @@ fn test_chain_spends() { previous_output: OutPoint::new(tx_0.compute_txid(), 1), ..Default::default() }], - ..common::new_tx(0) + ..new_tx(0) }; // Insert in graph and mark it as seen. @@ -983,7 +984,7 @@ fn test_chain_spends() { /// Ensure that `last_seen` values only increase during [`Merge::merge`]. #[test] fn test_changeset_last_seen_merge() { - let txid: Txid = h!("test txid"); + let txid: Txid = hash!("test txid"); let test_cases: &[(Option, Option)] = &[ (Some(5), Some(6)), @@ -1026,7 +1027,7 @@ fn transactions_inserted_into_tx_graph_are_not_canonical_until_they_have_an_anch assert_eq!(unseen_txs.len(), 2); // chain - let blocks: BTreeMap = [(0, h!("g")), (1, h!("A")), (2, h!("B"))] + let blocks: BTreeMap = [(0, hash!("g")), (1, hash!("A")), (2, hash!("B"))] .into_iter() .collect(); let chain = LocalChain::from_blocks(blocks).unwrap(); @@ -1181,9 +1182,9 @@ fn tx_graph_update_conversion() { TxUpdate { txs: vec![make_tx(0).into(), make_tx(1).into()], txouts: [ - (OutPoint::new(h!("a"), 0), make_txout(0)), - (OutPoint::new(h!("a"), 1), make_txout(1)), - (OutPoint::new(h!("b"), 0), make_txout(2)), + (OutPoint::new(hash!("a"), 0), make_txout(0)), + (OutPoint::new(hash!("a"), 1), make_txout(1)), + (OutPoint::new(hash!("b"), 0), make_txout(2)), ] .into(), ..Default::default() @@ -1194,14 +1195,14 @@ fn tx_graph_update_conversion() { TxUpdate { txs: vec![make_tx(0).into(), make_tx(1).into()], txouts: [ - (OutPoint::new(h!("a"), 0), make_txout(0)), - (OutPoint::new(h!("a"), 1), make_txout(1)), - (OutPoint::new(h!("b"), 0), make_txout(2)), + (OutPoint::new(hash!("a"), 0), make_txout(0)), + (OutPoint::new(hash!("a"), 1), make_txout(1)), + (OutPoint::new(hash!("b"), 0), make_txout(2)), ] .into(), anchors: [ - (ConfirmationBlockTime::default(), h!("a")), - (ConfirmationBlockTime::default(), h!("b")), + (ConfirmationBlockTime::default(), hash!("a")), + (ConfirmationBlockTime::default(), hash!("b")), ] .into(), ..Default::default() @@ -1212,17 +1213,17 @@ fn tx_graph_update_conversion() { TxUpdate { txs: vec![make_tx(0).into(), make_tx(1).into()], txouts: [ - (OutPoint::new(h!("a"), 0), make_txout(0)), - (OutPoint::new(h!("a"), 1), make_txout(1)), - (OutPoint::new(h!("d"), 0), make_txout(2)), + (OutPoint::new(hash!("a"), 0), make_txout(0)), + (OutPoint::new(hash!("a"), 1), make_txout(1)), + (OutPoint::new(hash!("d"), 0), make_txout(2)), ] .into(), anchors: [ - (ConfirmationBlockTime::default(), h!("a")), - (ConfirmationBlockTime::default(), h!("b")), + (ConfirmationBlockTime::default(), hash!("a")), + (ConfirmationBlockTime::default(), hash!("b")), ] .into(), - seen_ats: [(h!("c"), 12346)].into_iter().collect(), + seen_ats: [(hash!("c"), 12346)].into_iter().collect(), }, ), ]; diff --git a/crates/chain/tests/test_tx_graph_conflicts.rs b/crates/chain/tests/test_tx_graph_conflicts.rs index 45370b676..1f54c4b82 100644 --- a/crates/chain/tests/test_tx_graph_conflicts.rs +++ b/crates/chain/tests/test_tx_graph_conflicts.rs @@ -3,11 +3,11 @@ #[macro_use] mod common; -use std::collections::{BTreeSet, HashSet}; - use bdk_chain::{Balance, BlockId}; +use bdk_testenv::{block_id, hash, local_chain}; use bitcoin::{Amount, OutPoint, ScriptBuf}; use common::*; +use std::collections::{BTreeSet, HashSet}; #[allow(dead_code)] struct Scenario<'a> { @@ -33,13 +33,13 @@ struct Scenario<'a> { fn test_tx_conflict_handling() { // Create Local chains let local_chain = local_chain!( - (0, h!("A")), - (1, h!("B")), - (2, h!("C")), - (3, h!("D")), - (4, h!("E")), - (5, h!("F")), - (6, h!("G")) + (0, hash!("A")), + (1, hash!("B")), + (2, hash!("C")), + (3, hash!("D")), + (4, hash!("E")), + (5, hash!("F")), + (6, hash!("G")) ); let chain_tip = local_chain.tip().block_id(); diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index c218bf164..50417f4a9 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -22,3 +22,4 @@ serde = ["dep:serde", "bitcoin/serde", "hashbrown?/serde"] [dev-dependencies] bdk_chain = { path = "../chain" } +bdk_testenv = { path = "../testenv", default-features = false } diff --git a/crates/core/tests/common.rs b/crates/core/tests/common.rs deleted file mode 100644 index 347a90bf6..000000000 --- a/crates/core/tests/common.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[allow(unused_macros)] -macro_rules! block_id { - ($height:expr, $hash:literal) => {{ - bdk_chain::BlockId { - height: $height, - hash: bitcoin::hashes::Hash::hash($hash.as_bytes()), - } - }}; -} diff --git a/crates/core/tests/test_checkpoint.rs b/crates/core/tests/test_checkpoint.rs index 705f1c474..2ec96c153 100644 --- a/crates/core/tests/test_checkpoint.rs +++ b/crates/core/tests/test_checkpoint.rs @@ -1,7 +1,5 @@ -#[macro_use] -mod common; - use bdk_core::CheckPoint; +use bdk_testenv::block_id; /// Inserting a block that already exists in the checkpoint chain must always succeed. #[test] diff --git a/crates/testenv/src/lib.rs b/crates/testenv/src/lib.rs index 6d169bdce..abf4cac43 100644 --- a/crates/testenv/src/lib.rs +++ b/crates/testenv/src/lib.rs @@ -1,3 +1,5 @@ +pub mod utils; + use bdk_chain::{ bitcoin::{ address::NetworkChecked, block::Header, hash_types::TxMerkleNode, hashes::Hash, diff --git a/crates/testenv/src/utils.rs b/crates/testenv/src/utils.rs new file mode 100644 index 000000000..93ca1f217 --- /dev/null +++ b/crates/testenv/src/utils.rs @@ -0,0 +1,90 @@ +use bdk_chain::bitcoin; + +#[allow(unused_macros)] +#[macro_export] +macro_rules! block_id { + ($height:expr, $hash:literal) => {{ + bdk_chain::BlockId { + height: $height, + hash: bitcoin::hashes::Hash::hash($hash.as_bytes()), + } + }}; +} + +#[allow(unused_macros)] +#[macro_export] +macro_rules! hash { + ($index:literal) => {{ + bitcoin::hashes::Hash::hash($index.as_bytes()) + }}; +} + +#[allow(unused_macros)] +#[macro_export] +macro_rules! local_chain { + [ $(($height:expr, $hash:expr)), * ] => {{ + #[allow(unused_mut)] + bdk_chain::local_chain::LocalChain::from_blocks([$(($height, $hash).into()),*].into_iter().collect()) + .expect("chain must have genesis block") + }}; +} + +#[allow(unused_macros)] +#[macro_export] +macro_rules! chain_update { + [ $(($height:expr, $hash:expr)), * ] => {{ + #[allow(unused_mut)] + bdk_chain::local_chain::LocalChain::from_blocks([$(($height, $hash).into()),*].into_iter().collect()) + .expect("chain must have genesis block") + .tip() + }}; +} + +#[allow(unused_macros)] +#[macro_export] +macro_rules! changeset { + (checkpoints: $($tail:tt)*) => { changeset!(index: TxHeight, checkpoints: $($tail)*) }; + ( + index: $ind:ty, + checkpoints: [ $(( $height:expr, $cp_to:expr )),* ] + $(,txids: [ $(( $txid:expr, $tx_to:expr )),* ])? + ) => {{ + use bdk_chain::collections::BTreeMap; + + #[allow(unused_mut)] + bdk_chain::sparse_chain::ChangeSet::<$ind> { + checkpoints: { + let mut changes = BTreeMap::default(); + $(changes.insert($height, $cp_to);)* + changes + }, + txids: { + let mut changes = BTreeMap::default(); + $($(changes.insert($txid, $tx_to.map(|h: TxHeight| h.into()));)*)? + changes + } + } + }}; +} + +#[allow(unused)] +pub fn new_tx(lt: u32) -> bitcoin::Transaction { + bitcoin::Transaction { + version: bitcoin::transaction::Version::non_standard(0x00), + lock_time: bitcoin::absolute::LockTime::from_consensus(lt), + input: vec![], + output: vec![], + } +} + +#[allow(unused)] +pub const DESCRIPTORS: [&str; 7] = [ + "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)", + "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)", + "wpkh([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/0/*)", + "tr(tprv8ZgxMBicQKsPd3krDUsBAmtnRsK3rb8u5yi1zhQgMhF1tR8MW7xfE4rnrbbsrbPR52e7rKapu6ztw1jXveJSCGHEriUGZV7mCe88duLp5pj/86'/1'/0'/0/*)", + "tr(tprv8ZgxMBicQKsPd3krDUsBAmtnRsK3rb8u5yi1zhQgMhF1tR8MW7xfE4rnrbbsrbPR52e7rKapu6ztw1jXveJSCGHEriUGZV7mCe88duLp5pj/86'/1'/0'/1/*)", + "wpkh(xprv9s21ZrQH143K4EXURwMHuLS469fFzZyXk7UUpdKfQwhoHcAiYTakpe8pMU2RiEdvrU9McyuE7YDoKcXkoAwEGoK53WBDnKKv2zZbb9BzttX/1/0/*)", + // non-wildcard + "wpkh([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/0)", +];