Skip to content

Commit 708b916

Browse files
committed
chore(chain): simplify keychains_to_descriptor_ids field
Also rename `descriptor_ids_to_keychain_set` to `descriptor_ids_to_keychains` and update it's documentation.
1 parent 2f059a1 commit 708b916

File tree

1 file changed

+83
-48
lines changed

1 file changed

+83
-48
lines changed

crates/chain/src/keychain/txout_index.rs

Lines changed: 83 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,16 @@ const DEFAULT_LOOKAHEAD: u32 = 25;
207207
#[derive(Clone, Debug)]
208208
pub struct KeychainTxOutIndex<K> {
209209
inner: SpkTxOutIndex<(DescriptorId, u32)>,
210-
// keychain -> (descriptor, descriptor id) map
211-
keychains_to_descriptors: BTreeMap<K, (DescriptorId, Descriptor<DescriptorPublicKey>)>,
212-
// descriptor id -> keychain set
213-
// Because different keychains can have the same descriptor, we rank keychains by `Ord` so that
214-
// that the first keychain variant (according to `Ord`) has the highest rank. When associated
215-
// data (such as spks, outpoints) are returned with a keychain, we return the highest-ranked
216-
// keychain with it.
217-
descriptor_ids_to_keychain_set: HashMap<DescriptorId, BTreeSet<K>>,
210+
// keychain -> descriptor_id map
211+
keychains_to_descriptor_ids: BTreeMap<K, DescriptorId>,
212+
// descriptor_id -> keychain set
213+
// This is a reverse map of `keychains_to_descriptors`. Although there is only one descriptor
214+
// per keychain, different keychains can refer to the same descriptor, therefore we have a set
215+
// of keychains per descriptor. When associated data (such as spks, outpoints) are returned with
216+
// a keychain, we return it with the highest-ranked keychain with it. We rank keychains by
217+
// `Ord`, therefore the keychain set is a `BTreeSet`. The earliest keychain variant (according
218+
// to `Ord`) has precedence.
219+
descriptor_ids_to_keychains: HashMap<DescriptorId, BTreeSet<K>>,
218220
// descriptor_id -> descriptor map
219221
// This is a "monotone" map, meaning that its size keeps growing, i.e., we never delete
220222
// descriptors from it. This is useful for revealing spks for descriptors that don't have
@@ -289,8 +291,8 @@ impl<K> KeychainTxOutIndex<K> {
289291
pub fn new(lookahead: u32) -> Self {
290292
Self {
291293
inner: SpkTxOutIndex::default(),
292-
keychains_to_descriptors: BTreeMap::new(),
293-
descriptor_ids_to_keychain_set: HashMap::new(),
294+
keychains_to_descriptor_ids: BTreeMap::new(),
295+
descriptor_ids_to_keychains: HashMap::new(),
294296
descriptor_ids_to_descriptors: BTreeMap::new(),
295297
last_revealed: BTreeMap::new(),
296298
lookahead,
@@ -302,7 +304,7 @@ impl<K> KeychainTxOutIndex<K> {
302304
impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
303305
/// Get the highest-ranked keychain that is currently associated with the given `desc_id`.
304306
fn keychain_of_desc_id(&self, desc_id: &DescriptorId) -> Option<&K> {
305-
let keychains = self.descriptor_ids_to_keychain_set.get(desc_id)?;
307+
let keychains = self.descriptor_ids_to_keychains.get(desc_id)?;
306308
keychains.iter().next()
307309
}
308310

@@ -362,7 +364,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
362364
///
363365
/// This calls [`SpkTxOutIndex::spk_at_index`] internally.
364366
pub fn spk_at_index(&self, keychain: K, index: u32) -> Option<&Script> {
365-
let descriptor_id = self.keychains_to_descriptors.get(&keychain)?.0;
367+
let descriptor_id = *self.keychains_to_descriptor_ids.get(&keychain)?;
366368
self.inner.spk_at_index(&(descriptor_id, index))
367369
}
368370

@@ -382,7 +384,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
382384
///
383385
/// This calls [`SpkTxOutIndex::is_used`] internally.
384386
pub fn is_used(&self, keychain: K, index: u32) -> bool {
385-
let descriptor_id = self.keychains_to_descriptors.get(&keychain).map(|k| k.0);
387+
let descriptor_id = self.keychains_to_descriptor_ids.get(&keychain).copied();
386388
match descriptor_id {
387389
Some(descriptor_id) => self.inner.is_used(&(descriptor_id, index)),
388390
None => false,
@@ -406,7 +408,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
406408
///
407409
/// [`unmark_used`]: Self::unmark_used
408410
pub fn mark_used(&mut self, keychain: K, index: u32) -> bool {
409-
let descriptor_id = self.keychains_to_descriptors.get(&keychain).map(|k| k.0);
411+
let descriptor_id = self.keychains_to_descriptor_ids.get(&keychain).copied();
410412
match descriptor_id {
411413
Some(descriptor_id) => self.inner.mark_used(&(descriptor_id, index)),
412414
None => false,
@@ -423,7 +425,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
423425
///
424426
/// [`mark_used`]: Self::mark_used
425427
pub fn unmark_used(&mut self, keychain: K, index: u32) -> bool {
426-
let descriptor_id = self.keychains_to_descriptors.get(&keychain).map(|k| k.0);
428+
let descriptor_id = self.keychains_to_descriptor_ids.get(&keychain).copied();
427429
match descriptor_id {
428430
Some(descriptor_id) => self.inner.unmark_used(&(descriptor_id, index)),
429431
None => false,
@@ -462,9 +464,13 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
462464
&self,
463465
) -> impl DoubleEndedIterator<Item = (&K, &Descriptor<DescriptorPublicKey>)> + ExactSizeIterator + '_
464466
{
465-
self.keychains_to_descriptors
466-
.iter()
467-
.map(|(k, (_, d))| (k, d))
467+
self.keychains_to_descriptor_ids.iter().map(|(k, desc_id)| {
468+
let descriptor = self
469+
.descriptor_ids_to_descriptors
470+
.get(desc_id)
471+
.expect("descriptor id cannot be associated with keychain without descriptor");
472+
(k, descriptor)
473+
})
468474
}
469475

470476
/// Insert a descriptor with a keychain associated to it.
@@ -483,11 +489,11 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
483489
let mut changeset = super::ChangeSet::<K>::default();
484490
let desc_id = descriptor.descriptor_id();
485491

486-
let old_desc = self
487-
.keychains_to_descriptors
488-
.insert(keychain.clone(), (desc_id, descriptor.clone()));
492+
let old_desc_id = self
493+
.keychains_to_descriptor_ids
494+
.insert(keychain.clone(), desc_id);
489495

490-
if let Some((old_desc_id, _)) = old_desc {
496+
if let Some(old_desc_id) = old_desc_id {
491497
// nothing needs to be done if caller reinsterted the same descriptor under the same
492498
// keychain
493499
if old_desc_id == desc_id {
@@ -497,14 +503,14 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
497503
// is designed to track one descriptor per keychain (however different keychains can
498504
// share the same descriptor)
499505
let _is_keychain_removed = self
500-
.descriptor_ids_to_keychain_set
506+
.descriptor_ids_to_keychains
501507
.get_mut(&old_desc_id)
502508
.expect("we must have already inserted this descriptor")
503509
.remove(&keychain);
504510
debug_assert!(_is_keychain_removed);
505511
}
506512

507-
self.descriptor_ids_to_keychain_set
513+
self.descriptor_ids_to_keychains
508514
.entry(desc_id)
509515
.or_default()
510516
.insert(keychain.clone());
@@ -521,7 +527,13 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
521527
/// Gets the descriptor associated with the keychain. Returns `None` if the keychain doesn't
522528
/// have a descriptor associated with it.
523529
pub fn get_descriptor(&self, keychain: &K) -> Option<&Descriptor<DescriptorPublicKey>> {
524-
self.keychains_to_descriptors.get(keychain).map(|(_, d)| d)
530+
self.keychains_to_descriptor_ids
531+
.get(keychain)
532+
.map(|desc_id| {
533+
self.descriptor_ids_to_descriptors
534+
.get(desc_id)
535+
.expect("descriptor id cannot be associated with keychain without descriptor")
536+
})
525537
}
526538

527539
/// Get the lookahead setting.
@@ -549,8 +561,13 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
549561
}
550562

551563
fn replenish_lookahead(&mut self, keychain: &K, lookahead: u32) {
552-
let descriptor_opt = self.keychains_to_descriptors.get(keychain).cloned();
553-
if let Some((descriptor_id, descriptor)) = descriptor_opt {
564+
let descriptor_id = self.keychains_to_descriptor_ids.get(keychain).copied();
565+
if let Some(descriptor_id) = descriptor_id {
566+
let descriptor = self
567+
.descriptor_ids_to_descriptors
568+
.get(&descriptor_id)
569+
.expect("descriptor id cannot be associated with keychain without descriptor");
570+
554571
let next_store_index = self.next_store_index(descriptor_id);
555572
let next_reveal_index = self.last_revealed.get(&descriptor_id).map_or(0, |v| *v + 1);
556573

@@ -580,17 +597,29 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
580597
&self,
581598
keychain: &K,
582599
) -> Option<SpkIterator<Descriptor<DescriptorPublicKey>>> {
583-
let descriptor = self.keychains_to_descriptors.get(keychain)?.1.clone();
584-
Some(SpkIterator::new(descriptor))
600+
let desc_id = self.keychains_to_descriptor_ids.get(keychain)?;
601+
let desc = self
602+
.descriptor_ids_to_descriptors
603+
.get(desc_id)
604+
.cloned()
605+
.expect("descriptor id cannot be associated with keychain without descriptor");
606+
Some(SpkIterator::new(desc))
585607
}
586608

587609
/// Get unbounded spk iterators for all keychains.
588610
pub fn all_unbounded_spk_iters(
589611
&self,
590612
) -> BTreeMap<K, SpkIterator<Descriptor<DescriptorPublicKey>>> {
591-
self.keychains_to_descriptors
613+
self.keychains_to_descriptor_ids
592614
.iter()
593-
.map(|(k, (_, descriptor))| (k.clone(), SpkIterator::new(descriptor.clone())))
615+
.map(|(k, desc_id)| {
616+
let desc = self
617+
.descriptor_ids_to_descriptors
618+
.get(desc_id)
619+
.cloned()
620+
.expect("descriptor id cannot be associated with keychain without descriptor");
621+
(k.clone(), SpkIterator::new(desc))
622+
})
594623
.collect()
595624
}
596625

@@ -599,9 +628,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
599628
&self,
600629
range: impl RangeBounds<K>,
601630
) -> impl DoubleEndedIterator<Item = (&K, u32, &Script)> + Clone {
602-
self.keychains_to_descriptors
631+
self.keychains_to_descriptor_ids
603632
.range(range)
604-
.flat_map(|(_, (descriptor_id, _))| {
633+
.flat_map(|(_, descriptor_id)| {
605634
let start = Bound::Included((*descriptor_id, u32::MIN));
606635
let end = match self.last_revealed.get(descriptor_id) {
607636
Some(last_revealed) => Bound::Included((*descriptor_id, *last_revealed)),
@@ -633,10 +662,12 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
633662

634663
/// Iterate over revealed, but unused, spks of all keychains.
635664
pub fn unused_spks(&self) -> impl DoubleEndedIterator<Item = (K, u32, &Script)> + Clone {
636-
self.keychains_to_descriptors.keys().flat_map(|keychain| {
637-
self.unused_keychain_spks(keychain)
638-
.map(|(i, spk)| (keychain.clone(), i, spk))
639-
})
665+
self.keychains_to_descriptor_ids
666+
.keys()
667+
.flat_map(|keychain| {
668+
self.unused_keychain_spks(keychain)
669+
.map(|(i, spk)| (keychain.clone(), i, spk))
670+
})
640671
}
641672

642673
/// Iterate over revealed, but unused, spks of the given `keychain`.
@@ -646,9 +677,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
646677
keychain: &K,
647678
) -> impl DoubleEndedIterator<Item = (u32, &Script)> + Clone {
648679
let desc_id = self
649-
.keychains_to_descriptors
680+
.keychains_to_descriptor_ids
650681
.get(keychain)
651-
.map(|(desc_id, _)| *desc_id)
682+
.cloned()
652683
// We use a dummy desc id if we can't find the real one in our map. In this way,
653684
// if this method was to be called with a non-existent keychain, we would return an
654685
// empty iterator
@@ -672,7 +703,11 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
672703
///
673704
/// Returns None if the provided `keychain` doesn't exist.
674705
pub fn next_index(&self, keychain: &K) -> Option<(u32, bool)> {
675-
let (descriptor_id, descriptor) = self.keychains_to_descriptors.get(keychain)?;
706+
let descriptor_id = self.keychains_to_descriptor_ids.get(keychain)?;
707+
let descriptor = self
708+
.descriptor_ids_to_descriptors
709+
.get(descriptor_id)
710+
.expect("descriptor id cannot be associated with keychain without descriptor");
676711
let last_index = self.last_revealed.get(descriptor_id).cloned();
677712

678713
// we can only get the next index if the wildcard exists.
@@ -709,8 +744,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
709744
/// Get the last derivation index revealed for `keychain`. Returns None if the keychain doesn't
710745
/// exist, or if the keychain doesn't have any revealed scripts.
711746
pub fn last_revealed_index(&self, keychain: &K) -> Option<u32> {
712-
let descriptor_id = self.keychains_to_descriptors.get(keychain)?.0;
713-
self.last_revealed.get(&descriptor_id).cloned()
747+
let descriptor_id = self.keychains_to_descriptor_ids.get(keychain)?;
748+
self.last_revealed.get(descriptor_id).cloned()
714749
}
715750

716751
/// Convenience method to call [`Self::reveal_to_target`] on multiple keychains.
@@ -816,8 +851,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
816851
SpkIterator<Descriptor<DescriptorPublicKey>>,
817852
super::ChangeSet<K>,
818853
)> {
819-
let descriptor_id = self.keychains_to_descriptors.get(keychain)?.0;
820-
self.reveal_to_target_with_id(descriptor_id, target_index)
854+
let descriptor_id = self.keychains_to_descriptor_ids.get(keychain)?;
855+
self.reveal_to_target_with_id(*descriptor_id, target_index)
821856
}
822857

823858
/// Attempts to reveal the next script pubkey for `keychain`.
@@ -836,7 +871,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
836871
&mut self,
837872
keychain: &K,
838873
) -> Option<((u32, &Script), super::ChangeSet<K>)> {
839-
let descriptor_id = self.keychains_to_descriptors.get(keychain)?.0;
874+
let descriptor_id = self.keychains_to_descriptor_ids.get(keychain).cloned()?;
840875
let (next_index, _) = self.next_index(keychain).expect("We know keychain exists");
841876
let changeset = self
842877
.reveal_to_target(keychain, next_index)
@@ -908,9 +943,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
908943
bound: impl RangeBounds<K>,
909944
) -> impl RangeBounds<(DescriptorId, u32)> {
910945
let get_desc_id = |keychain| {
911-
self.keychains_to_descriptors
946+
self.keychains_to_descriptor_ids
912947
.get(keychain)
913-
.map(|(desc_id, _)| *desc_id)
948+
.copied()
914949
.unwrap_or_else(|| DescriptorId::from_byte_array([0; 32]))
915950
};
916951
let start = match bound.start_bound() {
@@ -936,7 +971,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
936971
/// Returns the highest derivation index of each keychain that [`KeychainTxOutIndex`] has found
937972
/// a [`TxOut`] with it's script pubkey.
938973
pub fn last_used_indices(&self) -> BTreeMap<K, u32> {
939-
self.keychains_to_descriptors
974+
self.keychains_to_descriptor_ids
940975
.iter()
941976
.filter_map(|(keychain, _)| {
942977
self.last_used_index(keychain)

0 commit comments

Comments
 (0)