Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for inserting anchor without tx #961

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/chain/tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[allow(unused_macros)]
macro_rules! h {
($index:literal) => {{
($index:expr) => {{
bitcoin::hashes::Hash::hash($index.as_bytes())
}};
}
Expand Down
89 changes: 87 additions & 2 deletions crates/chain/tests/test_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mod common;
use bdk_chain::{
collections::*,
local_chain::LocalChain,
tx_graph::{Additions, TxGraph},
Append, BlockId, ChainPosition, ConfirmationHeightAnchor,
tx_graph::{Additions, TxGraph, TxNode},
Append, BlockId, ChainPosition, ConfirmationHeightAnchor, ObservedAs,
};
use bitcoin::{
hashes::Hash, BlockHash, OutPoint, PackedLockTime, Script, Transaction, TxIn, TxOut, Txid,
Expand Down Expand Up @@ -822,3 +822,88 @@ 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::<ConfirmationHeightAnchor>::default();
let mut graph_recovered = graph.clone();
let txs = (0..5).map(common::new_tx).collect::<Vec<_>>();
let anchors = (0..5)
.map(|i| ConfirmationHeightAnchor {
anchor_block: BlockId {
height: i,
hash: BlockHash::from_hash(h!(&i.to_string())),
},
confirmation_height: i,
})
.collect::<Vec<_>>();
let anchors_with_txs = BTreeSet::from([
(anchors[0], txs[0].clone()),
(anchors[1], txs[1].clone()),
(anchors[2], txs[2].clone()),
]);
let anchors_with_txids = &anchors_with_txs
.iter()
.map(|(anchor, tx)| (*anchor, tx.txid()))
.collect::<BTreeSet<_>>();

let mut anchor_additions = Additions::default();
for (anchor, tx) in &anchors_with_txs {
let additions = graph.insert_anchor(tx.txid(), *anchor);
anchor_additions.append(additions);
}

// Additions should only include the Anchor for the Tx-Block 0, 1 and 2
assert_eq!(
anchor_additions,
Additions {
anchors: anchors_with_txids.clone(),
..Default::default()
}
);

// Graph should be recoverable from additions
graph_recovered.apply_additions(anchor_additions);
assert_eq!(graph, graph_recovered);

// Check whether Anchors 0, 1 and 2 are part of TxGraph
assert_eq!(graph.all_anchors(), anchors_with_txids);

// Insert transactions into graph and check the returned addition
let mut tx_additions = Additions::default();
for tx in &txs {
let additions = graph.insert_tx(tx.clone());
assert_eq!(
additions,
Additions {
tx: BTreeSet::from([tx.clone()]),
..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 2 should have an Anchor
for (anchor, tx) in &anchors_with_txs {
assert_eq!(
graph.get_tx_node(tx.txid()).unwrap(),
TxNode {
txid: tx.txid(),
tx,
anchors: &BTreeSet::from([*anchor]),
last_seen_unconfirmed: 0
}
);
}

// Transactions 3 and 4 should not have an Anchor
for tx in txs.iter().take(5).skip(3) {
assert!(graph.get_tx_node(tx.txid()).unwrap().anchors.is_empty());
}
}