2
2
//! indexes [`TxOut`]s with them.
3
3
4
4
use crate :: {
5
+ alloc:: boxed:: Box ,
5
6
collections:: * ,
6
7
miniscript:: { Descriptor , DescriptorPublicKey } ,
7
8
spk_client:: { FullScanRequestBuilder , SyncRequestBuilder } ,
@@ -10,7 +11,9 @@ use crate::{
10
11
DescriptorExt , DescriptorId , Indexed , Indexer , KeychainIndexed , SpkIterator ,
11
12
} ;
12
13
use alloc:: { borrow:: ToOwned , vec:: Vec } ;
13
- use bitcoin:: { Amount , OutPoint , ScriptBuf , SignedAmount , Transaction , TxOut , Txid } ;
14
+ use bitcoin:: {
15
+ key:: Secp256k1 , Amount , OutPoint , ScriptBuf , SignedAmount , Transaction , TxOut , Txid ,
16
+ } ;
14
17
use core:: {
15
18
fmt:: Debug ,
16
19
ops:: { Bound , RangeBounds } ,
@@ -128,6 +131,8 @@ pub struct KeychainTxOutIndex<K> {
128
131
descriptors : HashMap < DescriptorId , Descriptor < DescriptorPublicKey > > ,
129
132
last_revealed : HashMap < DescriptorId , u32 > ,
130
133
lookahead : u32 ,
134
+
135
+ spk_cache : BTreeMap < DescriptorId , HashMap < u32 , ScriptBuf > > ,
131
136
}
132
137
133
138
impl < K > Default for KeychainTxOutIndex < K > {
@@ -155,7 +160,12 @@ impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
155
160
if self . last_revealed . get ( did) < Some ( & index) {
156
161
self . last_revealed . insert ( * did, index) ;
157
162
changeset. last_revealed . insert ( * did, index) ;
158
- self . replenish_inner_index ( * did, & keychain, self . lookahead ) ;
163
+ self . replenish_inner_index (
164
+ * did,
165
+ & keychain,
166
+ self . lookahead ,
167
+ changeset. spk_cache . entry ( * did) . or_default ( ) ,
168
+ ) ;
159
169
}
160
170
}
161
171
changeset
@@ -173,6 +183,16 @@ impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
173
183
fn initial_changeset ( & self ) -> Self :: ChangeSet {
174
184
ChangeSet {
175
185
last_revealed : self . last_revealed . clone ( ) . into_iter ( ) . collect ( ) ,
186
+ spk_cache : self
187
+ . spk_cache
188
+ . iter ( )
189
+ . map ( |( desc, spks) | {
190
+ (
191
+ * desc,
192
+ spks. iter ( ) . map ( |( i, spk) | ( * i, spk. clone ( ) ) ) . collect ( ) ,
193
+ )
194
+ } )
195
+ . collect ( ) ,
176
196
}
177
197
}
178
198
@@ -204,6 +224,7 @@ impl<K> KeychainTxOutIndex<K> {
204
224
descriptor_id_to_keychain : Default :: default ( ) ,
205
225
last_revealed : Default :: default ( ) ,
206
226
lookahead,
227
+ spk_cache : Default :: default ( ) ,
207
228
}
208
229
}
209
230
@@ -365,23 +386,30 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
365
386
& mut self ,
366
387
keychain : K ,
367
388
descriptor : Descriptor < DescriptorPublicKey > ,
368
- ) -> Result < bool , InsertDescriptorError < K > > {
389
+ ) -> Result < ( bool , ChangeSet ) , InsertDescriptorError < K > > {
390
+ let mut changeset = ChangeSet :: default ( ) ;
391
+
369
392
let did = descriptor. descriptor_id ( ) ;
370
393
if !self . keychain_to_descriptor_id . contains_key ( & keychain)
371
394
&& !self . descriptor_id_to_keychain . contains_key ( & did)
372
395
{
373
396
self . descriptors . insert ( did, descriptor. clone ( ) ) ;
374
397
self . keychain_to_descriptor_id . insert ( keychain. clone ( ) , did) ;
375
398
self . descriptor_id_to_keychain . insert ( did, keychain. clone ( ) ) ;
376
- self . replenish_inner_index ( did, & keychain, self . lookahead ) ;
377
- return Ok ( true ) ;
399
+ self . replenish_inner_index (
400
+ did,
401
+ & keychain,
402
+ self . lookahead ,
403
+ changeset. spk_cache . entry ( did) . or_default ( ) ,
404
+ ) ;
405
+ return Ok ( ( true , changeset) ) ;
378
406
}
379
407
380
408
if let Some ( existing_desc_id) = self . keychain_to_descriptor_id . get ( & keychain) {
381
409
let descriptor = self . descriptors . get ( existing_desc_id) . expect ( "invariant" ) ;
382
410
if * existing_desc_id != did {
383
411
return Err ( InsertDescriptorError :: KeychainAlreadyAssigned {
384
- existing_assignment : descriptor. clone ( ) ,
412
+ existing_assignment : Box :: new ( descriptor. clone ( ) ) ,
385
413
keychain,
386
414
} ) ;
387
415
}
@@ -393,12 +421,12 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
393
421
if * existing_keychain != keychain {
394
422
return Err ( InsertDescriptorError :: DescriptorAlreadyAssigned {
395
423
existing_assignment : existing_keychain. clone ( ) ,
396
- descriptor,
424
+ descriptor : Box :: new ( descriptor ) ,
397
425
} ) ;
398
426
}
399
427
}
400
428
401
- Ok ( false )
429
+ Ok ( ( false , changeset ) )
402
430
}
403
431
404
432
/// Gets the descriptor associated with the keychain. Returns `None` if the keychain doesn't
@@ -420,47 +448,100 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
420
448
/// Store lookahead scripts until `target_index` (inclusive).
421
449
///
422
450
/// This does not change the global `lookahead` setting.
423
- pub fn lookahead_to_target ( & mut self , keychain : K , target_index : u32 ) {
451
+ pub fn lookahead_to_target (
452
+ & mut self ,
453
+ keychain : K ,
454
+ target_index : u32 ,
455
+ derived_spks : & mut impl Extend < Indexed < ScriptBuf > > ,
456
+ ) {
424
457
if let Some ( ( next_index, _) ) = self . next_index ( keychain. clone ( ) ) {
425
458
let temp_lookahead = ( target_index + 1 )
426
459
. checked_sub ( next_index)
427
460
. filter ( |& index| index > 0 ) ;
428
461
429
462
if let Some ( temp_lookahead) = temp_lookahead {
430
- self . replenish_inner_index_keychain ( keychain, temp_lookahead) ;
463
+ self . replenish_inner_index_keychain ( keychain, temp_lookahead, derived_spks ) ;
431
464
}
432
465
}
433
466
}
434
467
435
- fn replenish_inner_index_did ( & mut self , did : DescriptorId , lookahead : u32 ) {
468
+ fn replenish_inner_index_did (
469
+ & mut self ,
470
+ did : DescriptorId ,
471
+ lookahead : u32 ,
472
+ derived_spks : & mut impl Extend < Indexed < ScriptBuf > > ,
473
+ ) {
436
474
if let Some ( keychain) = self . descriptor_id_to_keychain . get ( & did) . cloned ( ) {
437
- self . replenish_inner_index ( did, & keychain, lookahead) ;
475
+ self . replenish_inner_index ( did, & keychain, lookahead, derived_spks ) ;
438
476
}
439
477
}
440
478
441
- fn replenish_inner_index_keychain ( & mut self , keychain : K , lookahead : u32 ) {
479
+ fn replenish_inner_index_keychain (
480
+ & mut self ,
481
+ keychain : K ,
482
+ lookahead : u32 ,
483
+ derived_spks : & mut impl Extend < Indexed < ScriptBuf > > ,
484
+ ) {
442
485
if let Some ( did) = self . keychain_to_descriptor_id . get ( & keychain) {
443
- self . replenish_inner_index ( * did, & keychain, lookahead) ;
486
+ self . replenish_inner_index ( * did, & keychain, lookahead, derived_spks ) ;
444
487
}
445
488
}
446
489
447
490
/// Syncs the state of the inner spk index after changes to a keychain
448
- fn replenish_inner_index ( & mut self , did : DescriptorId , keychain : & K , lookahead : u32 ) {
491
+ fn replenish_inner_index (
492
+ & mut self ,
493
+ did : DescriptorId ,
494
+ keychain : & K ,
495
+ lookahead : u32 ,
496
+ derived_spks : & mut impl Extend < Indexed < ScriptBuf > > ,
497
+ ) {
449
498
let descriptor = self . descriptors . get ( & did) . expect ( "invariant" ) ;
450
- let next_store_index = self
499
+
500
+ let mut next_index = self
451
501
. inner
452
502
. all_spks ( )
453
503
. range ( & ( keychain. clone ( ) , u32:: MIN ) ..=& ( keychain. clone ( ) , u32:: MAX ) )
454
504
. last ( )
455
505
. map_or ( 0 , |( ( _, index) , _) | * index + 1 ) ;
456
- let next_reveal_index = self . last_revealed . get ( & did) . map_or ( 0 , |v| * v + 1 ) ;
457
- for ( new_index, new_spk) in
458
- SpkIterator :: new_with_range ( descriptor, next_store_index..next_reveal_index + lookahead)
459
- {
506
+
507
+ // Exclusive: index to stop at.
508
+ let stop_index = if descriptor. has_wildcard ( ) {
509
+ let next_reveal_index = self . last_revealed . get ( & did) . map_or ( 0 , |v| * v + 1 ) ;
510
+ ( next_reveal_index + lookahead) . min ( BIP32_MAX_INDEX )
511
+ } else {
512
+ 1
513
+ } ;
514
+
515
+ let cached_spk_iter = core:: iter:: from_fn ( {
516
+ let secp = Secp256k1 :: verification_only ( ) ;
517
+ let _desc = & descriptor;
518
+ let spk_cache = self . spk_cache . entry ( did) . or_default ( ) ;
519
+ let _i = & mut next_index;
520
+ move || -> Option < Indexed < ScriptBuf > > {
521
+ if * _i >= stop_index {
522
+ return None ;
523
+ }
524
+ let spk_i = * _i;
525
+ * _i = spk_i. saturating_add ( 1 ) ;
526
+
527
+ if let Some ( spk) = spk_cache. get ( _i) {
528
+ return Some ( ( spk_i, spk. clone ( ) ) ) ;
529
+ }
530
+ let spk = _desc
531
+ . derived_descriptor ( & secp, spk_i)
532
+ . expect ( "The descriptor cannot have hardened derivation" )
533
+ . script_pubkey ( ) ;
534
+ derived_spks. extend ( core:: iter:: once ( ( spk_i, spk. clone ( ) ) ) ) ;
535
+ spk_cache. insert ( spk_i, spk. clone ( ) ) ;
536
+ Some ( ( spk_i, spk. clone ( ) ) )
537
+ }
538
+ } ) ;
539
+
540
+ for ( new_index, new_spk) in cached_spk_iter {
460
541
let _inserted = self
461
542
. inner
462
543
. insert_spk ( ( keychain. clone ( ) , new_index) , new_spk) ;
463
- debug_assert ! ( _inserted, "replenish lookahead: must not have existing spk: keychain={:?}, lookahead={}, next_store_index ={}, next_reveal_index={} " , keychain, lookahead, next_store_index , next_reveal_index ) ;
544
+ debug_assert ! ( _inserted, "replenish lookahead: must not have existing spk: keychain={:?}, lookahead={}, next_index ={}" , keychain, lookahead, next_index ) ;
464
545
}
465
546
}
466
547
@@ -693,7 +774,12 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
693
774
let did = self . keychain_to_descriptor_id . get ( & keychain) ?;
694
775
self . last_revealed . insert ( * did, next_index) ;
695
776
changeset. last_revealed . insert ( * did, next_index) ;
696
- self . replenish_inner_index ( * did, & keychain, self . lookahead ) ;
777
+ self . replenish_inner_index (
778
+ * did,
779
+ & keychain,
780
+ self . lookahead ,
781
+ changeset. spk_cache . entry ( * did) . or_default ( ) ,
782
+ ) ;
697
783
}
698
784
let script = self
699
785
. inner
@@ -779,10 +865,13 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
779
865
780
866
/// Applies the `ChangeSet<K>` to the [`KeychainTxOutIndex<K>`]
781
867
pub fn apply_changeset ( & mut self , changeset : ChangeSet ) {
782
- for ( & desc_id , & index) in & changeset. last_revealed {
783
- let v = self . last_revealed . entry ( desc_id ) . or_default ( ) ;
868
+ for ( did , index) in changeset. last_revealed {
869
+ let v = self . last_revealed . entry ( did ) . or_default ( ) ;
784
870
* v = index. max ( * v) ;
785
- self . replenish_inner_index_did ( desc_id, self . lookahead ) ;
871
+ self . replenish_inner_index_did ( did, self . lookahead , & mut Vec :: new ( ) ) ;
872
+ }
873
+ for ( did, spks) in changeset. spk_cache {
874
+ self . spk_cache . entry ( did) . or_default ( ) . extend ( spks) ;
786
875
}
787
876
}
788
877
}
@@ -793,7 +882,7 @@ pub enum InsertDescriptorError<K> {
793
882
/// The descriptor has already been assigned to a keychain so you can't assign it to another
794
883
DescriptorAlreadyAssigned {
795
884
/// The descriptor you have attempted to reassign
796
- descriptor : Descriptor < DescriptorPublicKey > ,
885
+ descriptor : Box < Descriptor < DescriptorPublicKey > > ,
797
886
/// The keychain that the descriptor is already assigned to
798
887
existing_assignment : K ,
799
888
} ,
@@ -802,7 +891,7 @@ pub enum InsertDescriptorError<K> {
802
891
/// The keychain that you have attempted to reassign
803
892
keychain : K ,
804
893
/// The descriptor that the keychain is already assigned to
805
- existing_assignment : Descriptor < DescriptorPublicKey > ,
894
+ existing_assignment : Box < Descriptor < DescriptorPublicKey > > ,
806
895
} ,
807
896
}
808
897
@@ -852,6 +941,10 @@ impl<K: core::fmt::Debug> std::error::Error for InsertDescriptorError<K> {}
852
941
pub struct ChangeSet {
853
942
/// Contains for each descriptor_id the last revealed index of derivation
854
943
pub last_revealed : BTreeMap < DescriptorId , u32 > ,
944
+
945
+ /// Spk cache.
946
+ #[ cfg_attr( feature = "serde" , serde( default ) ) ]
947
+ pub spk_cache : BTreeMap < DescriptorId , BTreeMap < u32 , ScriptBuf > > ,
855
948
}
856
949
857
950
impl Merge for ChangeSet {
@@ -872,11 +965,15 @@ impl Merge for ChangeSet {
872
965
}
873
966
}
874
967
}
968
+
969
+ for ( did, spks) in other. spk_cache {
970
+ self . spk_cache . entry ( did) . or_default ( ) . extend ( spks) ;
971
+ }
875
972
}
876
973
877
974
/// Returns whether the changeset are empty.
878
975
fn is_empty ( & self ) -> bool {
879
- self . last_revealed . is_empty ( )
976
+ self . last_revealed . is_empty ( ) && self . spk_cache . is_empty ( )
880
977
}
881
978
}
882
979
0 commit comments