From 0536bd59ca54c513f1aca2f7a22b24f67f65b531 Mon Sep 17 00:00:00 2001 From: remix Date: Mon, 15 May 2023 11:43:16 +0200 Subject: [PATCH] Adds test inserting anchor without tx Test inserting anchors without the corresponding transaction and testing the recoverability of the transaction graph Partially fixes "More tests for IndexedTxGraph and TxGraph #958" https://github.com/bitcoindevkit/bdk/issues/958 --- crates/chain/tests/common/mod.rs | 2 +- crates/chain/tests/test_tx_graph.rs | 92 +++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/crates/chain/tests/common/mod.rs b/crates/chain/tests/common/mod.rs index 7d7288bdf..560f66fee 100644 --- a/crates/chain/tests/common/mod.rs +++ b/crates/chain/tests/common/mod.rs @@ -1,6 +1,6 @@ #[allow(unused_macros)] macro_rules! h { - ($index:literal) => {{ + ($index:expr) => {{ bitcoin::hashes::Hash::hash($index.as_bytes()) }}; } diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index 2b8456119..07f522715 100644 --- a/crates/chain/tests/test_tx_graph.rs +++ b/crates/chain/tests/test_tx_graph.rs @@ -822,3 +822,95 @@ fn test_additions_last_seen_append() { ); } } + +/// Inserting anchors without the corresponding transaction +/// and testing the recoverability of the transaction graph +#[test] +fn test_inserting_anchor_without_tx() { + let mut graph = TxGraph::::default(); + let mut graph_recovered = graph.clone(); + let txs = (0..5).map(common::new_tx).collect::>(); + let chain: LocalChain = (0..5) + .map(|i| (i, h!(i.to_string()))) + .collect::>() + .into(); + let anchors = (0..5) + .map(|i| ConfirmationHeightAnchor { + anchor_block: BlockId { + height: i, + hash: *chain.blocks().get(&i).unwrap(), + }, + confirmation_height: 0, + }) + .collect::>(); + + let mut anchor_additions = Additions::default(); + for i in 0..3 { + let additions = graph.insert_anchor(txs[i].txid(), anchors[i]); + anchor_additions.append(additions); + } + + // Additions should only include the Anchor for the Tx-Block 0, 1 and 2 + assert_eq!( + anchor_additions, + Additions { + tx: Default::default(), + txout: Default::default(), + anchors: BTreeSet::from([ + (anchors[0], txs[0].txid()), + (anchors[1], txs[1].txid()), + (anchors[2], txs[2].txid()), + ]), + last_seen: Default::default(), + } + ); + + // graph should be recoverable from additions + graph_recovered.apply_additions(anchor_additions); + assert_eq!(graph, graph_recovered); + + // Check whether Anchors are part of TxGraph + for i in 0..3 { + assert!(graph.all_anchors().contains(&(anchors[i], txs[i].txid()))); + } + + let mut tx_additions = Additions::default(); + for tx in &txs[1..] { + let additions = graph.insert_tx(tx.clone()); + assert_eq!( + additions, + Additions { + tx: BTreeSet::from([tx.clone()]), + txout: Default::default(), + anchors: BTreeSet::default(), + last_seen: Default::default(), + } + ); + tx_additions.append(additions); + } + + // graph should be recoverable from additions + graph_recovered.apply_additions(tx_additions); + assert_eq!(graph, graph_recovered); + + // Transactions 0, 1 and 3 should have an Anchor + for i in 0..3 { + assert_eq!( + graph + .get_chain_position(&chain, chain.tip().unwrap(), txs[i].txid()) + .unwrap(), + ObservedAs::Confirmed(&anchors[i]) + ); + } + + // Transactions 4 and 5 should not have an Anchor + for tx in txs.iter().take(5).skip(4) { + assert_eq!( + graph + .try_get_chain_position(&chain, chain.tip().unwrap(), tx.txid()) + .unwrap() + .unwrap(), + ObservedAs::Unconfirmed(0) + ); + } +}