Skip to content

Commit 45573ea

Browse files
committed
Merge #1897: test for excluded bounds in outputs_in_range
ad79267 test for excluded bounds in outputs_in_range (aagbotemi) Pull request description: <!-- You can erase any parts of this template not applicable to your Pull Request. --> ### Description This PR covers a wide range on tests for excluded bounds and the `SpkTxOutIndex::outputs_in_range`. This PR fixes bitcoindevkit/bdk_wallet#58 <!-- Describe the purpose of this PR, what's being adding and/or fixed --> ### Notes to the reviewers <!-- In this section you can include notes directed to the reviewers, like explaining why some parts of the PR were done in a specific way --> ### Changelog notice <!-- Notice the release manager should include in the release tag message changelog --> <!-- See https://keepachangelog.com/en/1.0.0/ for examples --> ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [ ] I've added tests for the new feature * [ ] I've added docs for the new feature #### Bugfixes: * [ ] This pull request breaks the existing API * [ ] I've added tests to reproduce the issue which are now passing * [x] I'm linking the issue being fixed by this PR ACKs for top commit: ValuedMammal: ACK ad79267 oleonardolima: utACK ad79267 Tree-SHA512: 268e48ce6e7ffb0ed62d0124869caf1fbcff65d787a1a6566a5521408a8b9659a9f25cba5523802e805ac24bfa7809fff51e49c6be59cef6b6ecf4a29ffb9b0a
2 parents 1039d3c + ad79267 commit 45573ea

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

crates/chain/tests/test_spk_txout_index.rs

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use bdk_chain::{spk_txout::SpkTxOutIndex, Indexer};
22
use bitcoin::{
33
absolute, transaction, Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxIn, TxOut,
44
};
5+
use core::ops::Bound;
56

67
#[test]
78
fn spk_txout_sent_and_received() {
@@ -122,3 +123,194 @@ fn unmark_used_does_not_result_in_invalid_representation() {
122123
assert!(!spk_index.unmark_used(&2));
123124
assert!(spk_index.unused_spks(..).collect::<Vec<_>>().is_empty());
124125
}
126+
127+
#[test]
128+
fn outputs_in_range_excluded_bounds() {
129+
let spk1 = ScriptBuf::from_hex("001404f1e52ce2bab3423c6a8c63b7cd730d8f12542c").unwrap();
130+
let spk2 = ScriptBuf::from_hex("00142b57404ae14f08c3a0c903feb2af7830605eb00f").unwrap();
131+
let spk3 = ScriptBuf::from_hex("0014afa973f4364b2772d35f7a13ed83eb0c3330cf9c").unwrap();
132+
let spk4 = ScriptBuf::from_hex("00140707d2493460cad9bb20f5f447a5a89d16d9e21c").unwrap();
133+
let spk5 = ScriptBuf::from_hex("0014a10d9257489e685dda030662390dc177852faf13").unwrap();
134+
135+
let mut spk_index = SpkTxOutIndex::default();
136+
spk_index.insert_spk(1, spk1.clone());
137+
spk_index.insert_spk(2, spk2.clone());
138+
spk_index.insert_spk(3, spk3.clone());
139+
spk_index.insert_spk(4, spk4.clone());
140+
spk_index.insert_spk(5, spk5.clone());
141+
142+
let tx1 = Transaction {
143+
version: transaction::Version::TWO,
144+
lock_time: absolute::LockTime::ZERO,
145+
input: vec![],
146+
output: vec![TxOut {
147+
value: Amount::from_sat(10_000),
148+
script_pubkey: spk1,
149+
}],
150+
};
151+
152+
let tx2 = Transaction {
153+
version: transaction::Version::TWO,
154+
lock_time: absolute::LockTime::ZERO,
155+
input: vec![],
156+
output: vec![TxOut {
157+
value: Amount::from_sat(20_000),
158+
script_pubkey: spk2,
159+
}],
160+
};
161+
162+
let tx3 = Transaction {
163+
version: transaction::Version::TWO,
164+
lock_time: absolute::LockTime::ZERO,
165+
input: vec![],
166+
output: vec![TxOut {
167+
value: Amount::from_sat(30_000),
168+
script_pubkey: spk3,
169+
}],
170+
};
171+
172+
let tx4 = Transaction {
173+
version: transaction::Version::TWO,
174+
lock_time: absolute::LockTime::ZERO,
175+
input: vec![],
176+
output: vec![TxOut {
177+
value: Amount::from_sat(40_000),
178+
script_pubkey: spk4,
179+
}],
180+
};
181+
182+
let tx5 = Transaction {
183+
version: transaction::Version::TWO,
184+
lock_time: absolute::LockTime::ZERO,
185+
input: vec![],
186+
output: vec![TxOut {
187+
value: Amount::from_sat(50_000),
188+
script_pubkey: spk5,
189+
}],
190+
};
191+
192+
spk_index.index_tx(&tx1);
193+
spk_index.index_tx(&tx2);
194+
spk_index.index_tx(&tx3);
195+
spk_index.index_tx(&tx4);
196+
spk_index.index_tx(&tx5);
197+
198+
let tx1_op = OutPoint {
199+
txid: tx1.compute_txid(),
200+
vout: 0,
201+
};
202+
let tx2_op = OutPoint {
203+
txid: tx2.compute_txid(),
204+
vout: 0,
205+
};
206+
let tx3_op = OutPoint {
207+
txid: tx3.compute_txid(),
208+
vout: 0,
209+
};
210+
let tx4_op = OutPoint {
211+
txid: tx4.compute_txid(),
212+
vout: 0,
213+
};
214+
215+
// Full range (unbounded)
216+
let all_outputs: Vec<_> = spk_index
217+
.outputs_in_range((Bound::Unbounded::<u32>, Bound::Unbounded::<u32>))
218+
.collect();
219+
assert_eq!(all_outputs.len(), 5);
220+
221+
// Included start, included end
222+
let outputs_one_to_four: Vec<_> = spk_index
223+
.outputs_in_range((Bound::Included(1u32), Bound::Included(4u32)))
224+
.collect();
225+
assert_eq!(outputs_one_to_four.len(), 4);
226+
assert!(outputs_one_to_four
227+
.iter()
228+
.any(|(i, op)| **i == 1 && *op == tx1_op));
229+
assert!(outputs_one_to_four
230+
.iter()
231+
.any(|(i, op)| **i == 4 && *op == tx4_op));
232+
assert!(!outputs_one_to_four.iter().any(|(i, _)| **i == 5));
233+
234+
// Included start, Excluded end
235+
let outputs_one_to_four_excl: Vec<_> = spk_index
236+
.outputs_in_range((Bound::Included(1u32), Bound::Excluded(4u32)))
237+
.collect();
238+
assert_eq!(outputs_one_to_four_excl.len(), 3);
239+
assert!(outputs_one_to_four_excl.iter().any(|(i, _)| **i == 1));
240+
assert!(outputs_one_to_four_excl
241+
.iter()
242+
.any(|(i, op)| **i == 3 && *op == tx3_op));
243+
assert!(!outputs_one_to_four_excl.iter().any(|(i, _)| **i == 4));
244+
245+
// Excluded start, Included end
246+
let outputs_one_excl_to_four: Vec<_> = spk_index
247+
.outputs_in_range((Bound::Excluded(1u32), Bound::Included(4u32)))
248+
.collect();
249+
assert_eq!(outputs_one_excl_to_four.len(), 3,);
250+
assert!(!outputs_one_excl_to_four.iter().any(|(i, _)| **i == 1));
251+
assert!(outputs_one_excl_to_four
252+
.iter()
253+
.any(|(i, op)| **i == 2 && *op == tx2_op));
254+
assert!(outputs_one_excl_to_four.iter().any(|(i, _)| **i == 4));
255+
256+
// Excluded start, Excluded end
257+
let outputs_one_excl_to_four_excl: Vec<_> = spk_index
258+
.outputs_in_range((Bound::Excluded(1u32), Bound::Excluded(4u32)))
259+
.collect();
260+
assert_eq!(outputs_one_excl_to_four_excl.len(), 2);
261+
assert!(!outputs_one_excl_to_four_excl.iter().any(|(i, _)| **i == 1));
262+
assert!(outputs_one_excl_to_four_excl.iter().any(|(i, _)| **i == 2));
263+
assert!(outputs_one_excl_to_four_excl.iter().any(|(i, _)| **i == 3));
264+
assert!(!outputs_one_excl_to_four_excl.iter().any(|(i, _)| **i == 4));
265+
266+
// Unbounded start, Included end
267+
let outputs_to_three: Vec<_> = spk_index
268+
.outputs_in_range((Bound::Unbounded::<u32>, Bound::Included(3u32)))
269+
.collect();
270+
assert_eq!(outputs_to_three.len(), 3,);
271+
assert!(outputs_to_three.iter().any(|(i, _)| **i == 1));
272+
assert!(outputs_to_three.iter().any(|(i, _)| **i == 3));
273+
assert!(!outputs_to_three.iter().any(|(i, _)| **i == 4));
274+
275+
// Unbounded start, excluded end
276+
let outputs_to_three_excl: Vec<_> = spk_index
277+
.outputs_in_range((Bound::Unbounded::<u32>, Bound::Excluded(3u32)))
278+
.collect();
279+
assert_eq!(outputs_to_three_excl.len(), 2,);
280+
assert!(outputs_to_three_excl.iter().any(|(i, _)| **i == 1));
281+
assert!(outputs_to_three_excl.iter().any(|(i, _)| **i == 2));
282+
assert!(!outputs_to_three_excl.iter().any(|(i, _)| **i == 3),);
283+
284+
// Included start, Unbounded end
285+
let outputs_to_three: Vec<_> = spk_index
286+
.outputs_in_range((Bound::Included(3u32), Bound::Unbounded::<u32>))
287+
.collect();
288+
assert_eq!(outputs_to_three.len(), 3,);
289+
assert!(outputs_to_three.iter().any(|(i, _)| **i == 3));
290+
assert!(outputs_to_three.iter().any(|(i, _)| **i == 5),);
291+
assert!(!outputs_to_three.iter().any(|(i, _)| **i == 2),);
292+
293+
// Excluded start, Unbounded end
294+
let outputs_to_three_excl: Vec<_> = spk_index
295+
.outputs_in_range((Bound::Excluded(3u32), Bound::Unbounded::<u32>))
296+
.collect();
297+
assert_eq!(outputs_to_three_excl.len(), 2,);
298+
assert!(!outputs_to_three_excl.iter().any(|(i, _)| **i == 3));
299+
assert!(outputs_to_three_excl.iter().any(|(i, _)| **i == 5),);
300+
assert!(outputs_to_three_excl.iter().any(|(i, _)| **i == 4));
301+
302+
// Single element range
303+
let output_at_three: Vec<_> = spk_index
304+
.outputs_in_range((Bound::Included(3u32), Bound::Included(3u32)))
305+
.collect();
306+
assert_eq!(output_at_three.len(), 1,);
307+
assert!(output_at_three.iter().any(|(i, _)| **i == 3));
308+
assert!(!output_at_three.iter().any(|(i, _)| **i == 4));
309+
assert!(!output_at_three.iter().any(|(i, _)| **i == 2));
310+
311+
// Empty range with excluded bound
312+
let outputs_empty: Vec<_> = spk_index
313+
.outputs_in_range((Bound::Included(3u32), Bound::Excluded(3u32)))
314+
.collect();
315+
assert_eq!(outputs_empty.len(), 0);
316+
}

0 commit comments

Comments
 (0)