Simplify reveal_to_target
logic
- Remove unnecessary check - Better comments - Better variable names - Add test for scanning txouts with lookahead
This commit is contained in:
parent
82f5d9c81e
commit
72b1e2a485
@ -63,7 +63,7 @@ pub struct KeychainTxOutIndex<K> {
|
|||||||
inner: SpkTxOutIndex<(K, u32)>,
|
inner: SpkTxOutIndex<(K, u32)>,
|
||||||
// descriptors of each keychain
|
// descriptors of each keychain
|
||||||
keychains: BTreeMap<K, Descriptor<DescriptorPublicKey>>,
|
keychains: BTreeMap<K, Descriptor<DescriptorPublicKey>>,
|
||||||
// last stored indexes
|
// last revealed indexes
|
||||||
last_revealed: BTreeMap<K, u32>,
|
last_revealed: BTreeMap<K, u32>,
|
||||||
// lookahead settings for each keychain
|
// lookahead settings for each keychain
|
||||||
lookahead: BTreeMap<K, u32>,
|
lookahead: BTreeMap<K, u32>,
|
||||||
@ -381,40 +381,39 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
let has_wildcard = descriptor.has_wildcard();
|
let has_wildcard = descriptor.has_wildcard();
|
||||||
|
|
||||||
let target_index = if has_wildcard { target_index } else { 0 };
|
let target_index = if has_wildcard { target_index } else { 0 };
|
||||||
let next_store_index = self.next_store_index(keychain);
|
|
||||||
let next_reveal_index = self.last_revealed.get(keychain).map_or(0, |v| *v + 1);
|
let next_reveal_index = self.last_revealed.get(keychain).map_or(0, |v| *v + 1);
|
||||||
let lookahead = self.lookahead.get(keychain).map_or(0, |v| *v);
|
let lookahead = self.lookahead.get(keychain).map_or(0, |v| *v);
|
||||||
|
|
||||||
// if we can reveal new indexes, the latest revealed index goes here
|
debug_assert_eq!(
|
||||||
let mut revealed_index = None;
|
next_reveal_index + lookahead,
|
||||||
|
self.next_store_index(keychain)
|
||||||
|
);
|
||||||
|
|
||||||
// if the target is already surpassed, we have nothing to reveal
|
// if we need to reveal new indices, the latest revealed index goes here
|
||||||
if next_reveal_index <= target_index
|
let mut reveal_to_index = None;
|
||||||
// if the target is already stored (due to lookahead), this can be our newly revealed index
|
|
||||||
&& target_index < next_reveal_index + lookahead
|
// if the target is not yet revealed, but is already stored (due to lookahead), we need to
|
||||||
{
|
// set the `reveal_to_index` as target here (as the `for` loop below only updates
|
||||||
revealed_index = Some(target_index);
|
// `reveal_to_index` for indexes that are NOT stored)
|
||||||
|
if next_reveal_index <= target_index && target_index < next_reveal_index + lookahead {
|
||||||
|
reveal_to_index = Some(target_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we range over indexes that are not stored
|
// we range over indexes that are not stored
|
||||||
let range = next_reveal_index + lookahead..=target_index + lookahead;
|
let range = next_reveal_index + lookahead..=target_index + lookahead;
|
||||||
|
|
||||||
for (new_index, new_spk) in range_descriptor_spks(Cow::Borrowed(descriptor), range) {
|
for (new_index, new_spk) in range_descriptor_spks(Cow::Borrowed(descriptor), range) {
|
||||||
// no need to store if already stored
|
let _inserted = self
|
||||||
if new_index >= next_store_index {
|
.inner
|
||||||
let _inserted = self
|
.insert_spk((keychain.clone(), new_index), new_spk);
|
||||||
.inner
|
debug_assert!(_inserted, "must not have existing spk",);
|
||||||
.insert_spk((keychain.clone(), new_index), new_spk);
|
|
||||||
debug_assert!(_inserted, "must not have existing spk",);
|
|
||||||
}
|
|
||||||
|
|
||||||
// everything after `target_index` is stored for lookahead only
|
// everything after `target_index` is stored for lookahead only
|
||||||
if new_index <= target_index {
|
if new_index <= target_index {
|
||||||
revealed_index = Some(new_index);
|
reveal_to_index = Some(new_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match revealed_index {
|
match reveal_to_index {
|
||||||
Some(index) => {
|
Some(index) => {
|
||||||
let _old_index = self.last_revealed.insert(keychain.clone(), index);
|
let _old_index = self.last_revealed.insert(keychain.clone(), index);
|
||||||
debug_assert!(_old_index < Some(index));
|
debug_assert!(_old_index < Some(index));
|
||||||
|
@ -7,7 +7,7 @@ use bdk_chain::{
|
|||||||
keychain::{DerivationAdditions, KeychainTxOutIndex},
|
keychain::{DerivationAdditions, KeychainTxOutIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bitcoin::{secp256k1::Secp256k1, Script, Transaction, TxOut};
|
use bitcoin::{secp256k1::Secp256k1, OutPoint, Script, Transaction, TxOut};
|
||||||
use miniscript::{Descriptor, DescriptorPublicKey};
|
use miniscript::{Descriptor, DescriptorPublicKey};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
|
#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
|
||||||
@ -210,13 +210,54 @@ fn test_lookahead() {
|
|||||||
last_internal_index as usize + 1,
|
last_internal_index as usize + 1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// when:
|
// when:
|
||||||
// - scanning txouts with spks above last stored index
|
// - scanning txouts with spks above last stored index
|
||||||
// expect:
|
// expect:
|
||||||
// - cached scripts count should increase as expected
|
// - last revealed index should increase as expected
|
||||||
// - last stored index should increase as expected
|
// - last used index should change as expected
|
||||||
// TODO!
|
#[test]
|
||||||
|
fn test_scan_with_lookahead() {
|
||||||
|
let (mut txout_index, external_desc, _) = init_txout_index();
|
||||||
|
txout_index.set_lookahead_for_all(10);
|
||||||
|
|
||||||
|
let spks: BTreeMap<u32, Script> = [0, 10, 20, 30]
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| (i, external_desc.at_derivation_index(i).script_pubkey()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (&spk_i, spk) in &spks {
|
||||||
|
let op = OutPoint::new(h!("fake tx"), spk_i);
|
||||||
|
let txout = TxOut {
|
||||||
|
script_pubkey: spk.clone(),
|
||||||
|
value: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let additions = txout_index.scan_txout(op, &txout);
|
||||||
|
assert_eq!(
|
||||||
|
additions.as_inner(),
|
||||||
|
&[(TestKeychain::External, spk_i)].into()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
txout_index.last_revealed_index(&TestKeychain::External),
|
||||||
|
Some(spk_i)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
txout_index.last_used_index(&TestKeychain::External),
|
||||||
|
Some(spk_i)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now try with index 41 (lookahead surpassed), we expect that the txout to not be indexed
|
||||||
|
let spk_41 = external_desc.at_derivation_index(41).script_pubkey();
|
||||||
|
let op = OutPoint::new(h!("fake tx"), 41);
|
||||||
|
let txout = TxOut {
|
||||||
|
script_pubkey: spk_41,
|
||||||
|
value: 0,
|
||||||
|
};
|
||||||
|
let additions = txout_index.scan_txout(op, &txout);
|
||||||
|
assert!(additions.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user