Skip to content

Commit 0dc826d

Browse files
committed
test(chain): batch_insert_relevant inserts conflicting tx
1 parent eaa4688 commit 0dc826d

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

crates/chain/tests/test_indexed_tx_graph.rs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use bdk_chain::{
99
indexed_tx_graph::{self, IndexedTxGraph},
1010
indexer::keychain_txout::KeychainTxOutIndex,
1111
local_chain::LocalChain,
12-
tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt,
12+
tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt, Indexer,
1313
};
1414
use bdk_testenv::{
1515
block_id, hash,
@@ -99,6 +99,97 @@ fn insert_relevant_txs() {
9999
assert_eq!(graph.initial_changeset(), initial_changeset);
100100
}
101101

102+
/// Ensure that [`IndexedTxGraph::batch_insert_relevant`] adds transactions that are direct
103+
/// conflicts with transactions in our graph but are not directly relevant to it.
104+
///
105+
/// The graph contains three transactions (A, B, and conflicting_tx), with A and B being relevant
106+
/// because B spends from A. This test verifies that `conflicting_tx` is inserted into the graph
107+
/// solely because it is directly conflicting with B.
108+
#[test]
109+
fn insert_relevant_conflicting_txs() {
110+
use bdk_chain::indexer::keychain_txout;
111+
let (descriptor, _) = Descriptor::parse_descriptor(&Secp256k1::signing_only(), DESCRIPTORS[0])
112+
.expect("must be valid");
113+
let spk_0 = descriptor.at_derivation_index(0).unwrap().script_pubkey();
114+
let spk_1 = descriptor.at_derivation_index(9).unwrap().script_pubkey();
115+
116+
let mut graph = IndexedTxGraph::<ConfirmationBlockTime, KeychainTxOutIndex<()>>::new(
117+
KeychainTxOutIndex::new(10),
118+
);
119+
let _ = graph
120+
.index
121+
.insert_descriptor((), descriptor.clone())
122+
.unwrap();
123+
124+
let conflicting_prev_tx = Transaction {
125+
output: vec![TxOut {
126+
value: Amount::from_sat(10_000),
127+
script_pubkey: spk_0,
128+
}],
129+
..new_tx(0)
130+
};
131+
132+
let tx_a = Transaction {
133+
output: vec![TxOut {
134+
value: Amount::from_sat(10_000),
135+
script_pubkey: spk_1,
136+
}],
137+
..new_tx(1)
138+
};
139+
140+
let tx_b = Transaction {
141+
input: vec![
142+
TxIn {
143+
previous_output: OutPoint::new(conflicting_prev_tx.compute_txid(), 0),
144+
..Default::default()
145+
},
146+
TxIn {
147+
previous_output: OutPoint::new(tx_a.compute_txid(), 0),
148+
..Default::default()
149+
},
150+
],
151+
..new_tx(2)
152+
};
153+
154+
let conflicting_tx = Transaction {
155+
input: vec![TxIn {
156+
previous_output: OutPoint::new(conflicting_prev_tx.compute_txid(), 0),
157+
..Default::default()
158+
}],
159+
..new_tx(3)
160+
};
161+
162+
// We add only `tx_a`, `tx_b`, and `conflicting_tx` into the graph. `tx_a` and `tx_b` are
163+
// relevant to our graph, because `tx_b` spends from `tx_a`. `conflicting_tx` is not directly
164+
// relevant to our graph because it does not spend from `tx_a`. However, `tx_b` and
165+
// `conflicting_tx` conflict, because they both spend from the same output of
166+
// `conflicting_prev_tx`.
167+
let txs = [tx_a, tx_b, conflicting_tx.clone()];
168+
169+
let changeset = graph.batch_insert_relevant(txs.iter().cloned().map(|tx| (tx, None)));
170+
171+
// Confirm that `conflicting_tx` is added to `ChangeSet` only due to it being a conflicting
172+
// transaction, and not because it is directly relevant to our graph.
173+
assert!(!graph.index.is_tx_relevant(&conflicting_tx));
174+
assert!(graph
175+
.graph()
176+
.direct_conflicts(&conflicting_tx)
177+
.next()
178+
.is_some());
179+
180+
let expected_changeset = indexed_tx_graph::ChangeSet {
181+
tx_graph: tx_graph::ChangeSet::<ConfirmationBlockTime> {
182+
txs: txs.iter().cloned().map(Arc::new).collect(),
183+
..Default::default()
184+
},
185+
indexer: keychain_txout::ChangeSet {
186+
last_revealed: [(descriptor.descriptor_id(), 9_u32)].into(),
187+
},
188+
};
189+
190+
assert_eq!(changeset, expected_changeset);
191+
}
192+
102193
/// Ensure consistency IndexedTxGraph list_* and balance methods. These methods lists
103194
/// relevant txouts and utxos from the information fetched from a ChainOracle (here a LocalChain).
104195
///

0 commit comments

Comments
 (0)