// Exclusive: index to stop at.
let stop_index = if descriptor.has_wildcard() {
let next_reveal_index = self.last_revealed.get(&did).map_or(0, |v| *v + 1);
- (next_reveal_index + lookahead).min(BIP32_MAX_INDEX)
+ next_reveal_index
+ .saturating_add(lookahead)
+ .min(BIP32_MAX_INDEX + 1)
} else {
1
};
)
);
}
+
+ /// Build an index with `last_revealed` (and the matching spk) at `last_revealed_index`.
+ fn indexer_with_last_revealed_at(last_revealed_index: u32) -> KeychainTxOutIndex<i32> {
+ let s = DESCRIPTORS[0];
+ let desc = Descriptor::parse_descriptor(&Secp256k1::new(), s)
+ .unwrap()
+ .0;
+ let mut index = KeychainTxOutIndex::new(0, false);
+ let did = desc.descriptor_id();
+ let _ = index.insert_descriptor(0i32, desc.clone());
+
+ let spk = desc
+ .at_derivation_index(last_revealed_index)
+ .unwrap()
+ .script_pubkey();
+ index.inner.insert_spk((0i32, last_revealed_index), spk);
+ index.last_revealed.insert(did, last_revealed_index);
+ index
+ }
+
+ #[test]
+ fn reveal_next_spk_and_next_unused_spk_return_last_script_when_saturated() {
+ let mut index = indexer_with_last_revealed_at(BIP32_MAX_INDEX);
+ let (i, changeset) = index.reveal_next_spk(0i32).unwrap();
+ assert_eq!(i.0, BIP32_MAX_INDEX);
+ assert!(changeset.is_empty());
+ assert!(index.mark_used(0i32, BIP32_MAX_INDEX));
+ let (i, changeset) = index.next_unused_spk(0i32).unwrap();
+ assert_eq!(i.0, BIP32_MAX_INDEX);
+ assert!(changeset.is_empty());
+ }
+
+ #[test]
+ fn reveal_to_target_with_target_at_bip32_max_index() {
+ let mut index = indexer_with_last_revealed_at(BIP32_MAX_INDEX - 1);
+ let (spks, _changeset) = index.reveal_to_target(0i32, BIP32_MAX_INDEX).unwrap();
+ assert_eq!(spks.len(), 1);
+ assert_eq!(spks[0].0, BIP32_MAX_INDEX);
+ }
+
+ #[test]
+ fn reveal_to_target_with_target_above_bip32_max_index() {
+ let mut index = indexer_with_last_revealed_at(BIP32_MAX_INDEX - 1);
+ let (spks, _changeset) = index.reveal_to_target(0i32, BIP32_MAX_INDEX + 5).unwrap();
+ assert_eq!(spks.len(), 1);
+ assert_eq!(spks[0].0, BIP32_MAX_INDEX);
+ }
}