Skip to content

Commit c151d8f

Browse files
committed
fix(chain): KeychainTxOutIndex::lookahead_to_target
1 parent 50c549b commit c151d8f

File tree

2 files changed

+104
-4
lines changed

2 files changed

+104
-4
lines changed

crates/chain/src/keychain/txout_index.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,17 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
326326
self.lookahead
327327
}
328328

329-
/// Store lookahead scripts until `target_index`.
329+
/// Store lookahead scripts until `target_index` (inclusive).
330330
///
331-
/// This does not change the `lookahead` setting.
331+
/// This does not change the global `lookahead` setting.
332332
pub fn lookahead_to_target(&mut self, keychain: &K, target_index: u32) {
333-
let next_index = self.next_store_index(keychain);
334-
if let Some(temp_lookahead) = target_index.checked_sub(next_index).filter(|&v| v > 0) {
333+
let (next_index, _) = self.next_index(keychain);
334+
335+
let temp_lookahead = (target_index + 1)
336+
.checked_sub(next_index)
337+
.filter(|&index| index > 0);
338+
339+
if let Some(temp_lookahead) = temp_lookahead {
335340
self.replenish_lookahead(keychain, temp_lookahead);
336341
}
337342
}

crates/chain/tests/test_keychain_txout_index.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,98 @@ fn test_non_wildcard_derivations() {
386386
1,
387387
);
388388
}
389+
390+
/// Check that calling `lookahead_to_target` stores the expected spks.
391+
#[test]
392+
fn lookahead_to_target() {
393+
#[derive(Default)]
394+
struct TestCase {
395+
lookahead: u32, // Global lookahead value
396+
external_last_revealed: Option<u32>, // Last revealed index for external keychain
397+
internal_last_revealed: Option<u32>, // Last revealed index for internal keychain
398+
external_target: Option<u32>, // Call `lookahead_to_target(External, u32)`
399+
internal_target: Option<u32>, // Call `lookahead_to_target(Internal, u32)`
400+
}
401+
402+
let test_cases = &[
403+
TestCase {
404+
lookahead: 0,
405+
external_target: Some(100),
406+
..Default::default()
407+
},
408+
TestCase {
409+
lookahead: 10,
410+
internal_target: Some(99),
411+
..Default::default()
412+
},
413+
TestCase {
414+
lookahead: 100,
415+
internal_target: Some(9),
416+
external_target: Some(10),
417+
..Default::default()
418+
},
419+
TestCase {
420+
lookahead: 12,
421+
external_last_revealed: Some(2),
422+
internal_last_revealed: Some(2),
423+
internal_target: Some(15),
424+
external_target: Some(13),
425+
},
426+
TestCase {
427+
lookahead: 13,
428+
external_last_revealed: Some(100),
429+
internal_last_revealed: Some(21),
430+
internal_target: Some(120),
431+
external_target: Some(130),
432+
},
433+
];
434+
435+
for t in test_cases {
436+
let (mut index, _, _) = init_txout_index(t.lookahead);
437+
438+
if let Some(last_revealed) = t.external_last_revealed {
439+
let _ = index.reveal_to_target(&TestKeychain::External, last_revealed);
440+
}
441+
if let Some(last_revealed) = t.internal_last_revealed {
442+
let _ = index.reveal_to_target(&TestKeychain::Internal, last_revealed);
443+
}
444+
445+
let keychain_test_cases = [
446+
(
447+
TestKeychain::External,
448+
t.external_last_revealed,
449+
t.external_target,
450+
),
451+
(
452+
TestKeychain::Internal,
453+
t.internal_last_revealed,
454+
t.internal_target,
455+
),
456+
];
457+
for (keychain, last_revealed, target) in keychain_test_cases {
458+
if let Some(target) = target {
459+
let original_last_stored_index = match last_revealed {
460+
Some(last_revealed) => Some(last_revealed + t.lookahead),
461+
None => t.lookahead.checked_sub(1),
462+
};
463+
let exp_last_stored_index = match original_last_stored_index {
464+
Some(original_last_stored_index) => {
465+
Ord::max(target, original_last_stored_index)
466+
}
467+
None => target,
468+
};
469+
index.lookahead_to_target(&keychain, target);
470+
let keys = index
471+
.inner()
472+
.all_spks()
473+
.range((keychain.clone(), 0)..=(keychain.clone(), u32::MAX))
474+
.map(|(k, _)| k.clone())
475+
.collect::<Vec<_>>();
476+
let exp_keys = core::iter::repeat(keychain)
477+
.zip(0_u32..=exp_last_stored_index)
478+
.collect::<Vec<_>>();
479+
assert_eq!(keys, exp_keys);
480+
}
481+
}
482+
}
483+
}

0 commit comments

Comments
 (0)