@@ -5,12 +5,13 @@ use crate::{
55 spk_iter:: BIP32_MAX_INDEX ,
66 SpkIterator , SpkTxOutIndex ,
77} ;
8- use alloc:: vec:: Vec ;
98use bitcoin:: { OutPoint , Script , TxOut } ;
109use core:: { fmt:: Debug , ops:: Deref } ;
1110
1211use crate :: Append ;
1312
13+ const DEFAULT_LOOKAHEAD : u32 = 1_000 ;
14+
1415/// A convenient wrapper around [`SpkTxOutIndex`] that relates script pubkeys to miniscript public
1516/// [`Descriptor`]s.
1617///
@@ -46,7 +47,7 @@ use crate::Append;
4647/// # let secp = bdk_chain::bitcoin::secp256k1::Secp256k1::signing_only();
4748/// # let (external_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
4849/// # let (internal_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap();
49- /// # let descriptor_for_user_42 = external_descriptor.clone ();
50+ /// # let ( descriptor_for_user_42, _) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/2/*)").unwrap ();
5051/// txout_index.add_keychain(MyKeychain::External, external_descriptor);
5152/// txout_index.add_keychain(MyKeychain::Internal, internal_descriptor);
5253/// txout_index.add_keychain(MyKeychain::MyAppUser { user_id: 42 }, descriptor_for_user_42);
@@ -65,17 +66,12 @@ pub struct KeychainTxOutIndex<K> {
6566 // last revealed indexes
6667 last_revealed : BTreeMap < K , u32 > ,
6768 // lookahead settings for each keychain
68- lookahead : BTreeMap < K , u32 > ,
69+ lookahead : u32 ,
6970}
7071
7172impl < K > Default for KeychainTxOutIndex < K > {
7273 fn default ( ) -> Self {
73- Self {
74- inner : SpkTxOutIndex :: default ( ) ,
75- keychains : BTreeMap :: default ( ) ,
76- last_revealed : BTreeMap :: default ( ) ,
77- lookahead : BTreeMap :: default ( ) ,
78- }
74+ Self :: new ( DEFAULT_LOOKAHEAD )
7975 }
8076}
8177
@@ -118,6 +114,24 @@ impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
118114 }
119115}
120116
117+ impl < K > KeychainTxOutIndex < K > {
118+ /// Construct a [`KeychainTxOutIndex`] with the given `lookahead`.
119+ ///
120+ /// The lookahead is the number of scripts to cache ahead of the last revealed script index.
121+ /// This is useful to find outputs you own when processing block data that lie beyond the last
122+ /// revealed index. In certain situations, such as when performing an initial scan of the
123+ /// blockchain during wallet import, it may be uncertain or unknown what the last revealed index
124+ /// is.
125+ pub fn new ( lookahead : u32 ) -> Self {
126+ Self {
127+ inner : SpkTxOutIndex :: default ( ) ,
128+ keychains : BTreeMap :: new ( ) ,
129+ last_revealed : BTreeMap :: new ( ) ,
130+ lookahead,
131+ }
132+ }
133+ }
134+
121135impl < K : Clone + Ord + Debug > KeychainTxOutIndex < K > {
122136 /// Return a reference to the internal [`SpkTxOutIndex`].
123137 pub fn inner ( & self ) -> & SpkTxOutIndex < ( K , u32 ) > {
@@ -145,54 +159,22 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
145159 pub fn add_keychain ( & mut self , keychain : K , descriptor : Descriptor < DescriptorPublicKey > ) {
146160 let old_descriptor = & * self
147161 . keychains
148- . entry ( keychain)
162+ . entry ( keychain. clone ( ) )
149163 . or_insert_with ( || descriptor. clone ( ) ) ;
150164 assert_eq ! (
151165 & descriptor, old_descriptor,
152166 "keychain already contains a different descriptor"
153167 ) ;
168+ self . replenish_lookahead ( & keychain, self . lookahead ) ;
154169 }
155170
156- /// Return the lookahead setting for each keychain .
171+ /// Get the lookahead setting.
157172 ///
158- /// Refer to [`set_lookahead `] for a deeper explanation of the `lookahead`.
173+ /// Refer to [`new `] for more information on the `lookahead`.
159174 ///
160- /// [`set_lookahead`]: Self::set_lookahead
161- pub fn lookaheads ( & self ) -> & BTreeMap < K , u32 > {
162- & self . lookahead
163- }
164-
165- /// Convenience method to call [`set_lookahead`] for all keychains.
166- ///
167- /// [`set_lookahead`]: Self::set_lookahead
168- pub fn set_lookahead_for_all ( & mut self , lookahead : u32 ) {
169- for keychain in & self . keychains . keys ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) {
170- self . set_lookahead ( keychain, lookahead) ;
171- }
172- }
173-
174- /// Set the lookahead count for `keychain`.
175- ///
176- /// The lookahead is the number of scripts to cache ahead of the last revealed script index. This
177- /// is useful to find outputs you own when processing block data that lie beyond the last revealed
178- /// index. In certain situations, such as when performing an initial scan of the blockchain during
179- /// wallet import, it may be uncertain or unknown what the last revealed index is.
180- ///
181- /// # Panics
182- ///
183- /// This will panic if the `keychain` does not exist.
184- pub fn set_lookahead ( & mut self , keychain : & K , lookahead : u32 ) {
185- self . lookahead . insert ( keychain. clone ( ) , lookahead) ;
186- self . replenish_lookahead ( keychain) ;
187- }
188-
189- /// Convenience method to call [`lookahead_to_target`] for multiple keychains.
190- ///
191- /// [`lookahead_to_target`]: Self::lookahead_to_target
192- pub fn lookahead_to_target_multi ( & mut self , target_indexes : BTreeMap < K , u32 > ) {
193- for ( keychain, target_index) in target_indexes {
194- self . lookahead_to_target ( & keychain, target_index)
195- }
175+ /// [`new`]: Self::new
176+ pub fn lookahead ( & self ) -> u32 {
177+ self . lookahead
196178 }
197179
198180 /// Store lookahead scripts until `target_index`.
@@ -201,22 +183,14 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
201183 pub fn lookahead_to_target ( & mut self , keychain : & K , target_index : u32 ) {
202184 let next_index = self . next_store_index ( keychain) ;
203185 if let Some ( temp_lookahead) = target_index. checked_sub ( next_index) . filter ( |& v| v > 0 ) {
204- let old_lookahead = self . lookahead . insert ( keychain. clone ( ) , temp_lookahead) ;
205- self . replenish_lookahead ( keychain) ;
206-
207- // revert
208- match old_lookahead {
209- Some ( lookahead) => self . lookahead . insert ( keychain. clone ( ) , lookahead) ,
210- None => self . lookahead . remove ( keychain) ,
211- } ;
186+ self . replenish_lookahead ( keychain, temp_lookahead) ;
212187 }
213188 }
214189
215- fn replenish_lookahead ( & mut self , keychain : & K ) {
190+ fn replenish_lookahead ( & mut self , keychain : & K , lookahead : u32 ) {
216191 let descriptor = self . keychains . get ( keychain) . expect ( "keychain must exist" ) ;
217192 let next_store_index = self . next_store_index ( keychain) ;
218193 let next_reveal_index = self . last_revealed . get ( keychain) . map_or ( 0 , |v| * v + 1 ) ;
219- let lookahead = self . lookahead . get ( keychain) . map_or ( 0 , |v| * v) ;
220194
221195 for ( new_index, new_spk) in
222196 SpkIterator :: new_with_range ( descriptor, next_store_index..next_reveal_index + lookahead)
@@ -388,25 +362,21 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
388362
389363 let target_index = if has_wildcard { target_index } else { 0 } ;
390364 let next_reveal_index = self . last_revealed . get ( keychain) . map_or ( 0 , |v| * v + 1 ) ;
391- let lookahead = self . lookahead . get ( keychain) . map_or ( 0 , |v| * v) ;
392365
393- debug_assert_eq ! (
394- next_reveal_index + lookahead,
395- self . next_store_index( keychain)
396- ) ;
366+ debug_assert ! ( next_reveal_index + self . lookahead >= self . next_store_index( keychain) ) ;
397367
398368 // if we need to reveal new indices, the latest revealed index goes here
399369 let mut reveal_to_index = None ;
400370
401371 // if the target is not yet revealed, but is already stored (due to lookahead), we need to
402372 // set the `reveal_to_index` as target here (as the `for` loop below only updates
403373 // `reveal_to_index` for indexes that are NOT stored)
404- if next_reveal_index <= target_index && target_index < next_reveal_index + lookahead {
374+ if next_reveal_index <= target_index && target_index < next_reveal_index + self . lookahead {
405375 reveal_to_index = Some ( target_index) ;
406376 }
407377
408378 // we range over indexes that are not stored
409- let range = next_reveal_index + lookahead..=target_index + lookahead;
379+ let range = next_reveal_index + self . lookahead ..=target_index + self . lookahead ;
410380 for ( new_index, new_spk) in SpkIterator :: new_with_range ( descriptor, range) {
411381 let _inserted = self
412382 . inner
0 commit comments