From 4984d5a62fa74f0fbeb88bd27e5fc9ab3f4ed76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Tue, 5 Mar 2024 15:35:16 +0800 Subject: [PATCH] test(chain): introduce tests for changing descriptors --- .../chain/tests/test_keychain_txout_index.rs | 76 +++++++++++++++++-- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/crates/chain/tests/test_keychain_txout_index.rs b/crates/chain/tests/test_keychain_txout_index.rs index 93722e4137..17d6bf3695 100644 --- a/crates/chain/tests/test_keychain_txout_index.rs +++ b/crates/chain/tests/test_keychain_txout_index.rs @@ -5,7 +5,7 @@ mod common; use bdk_chain::{ collections::BTreeMap, indexed_tx_graph::Indexer, - keychain::{self, ChangeSet, DescriptorId, KeychainTxOutIndex}, + keychain::{self, DescriptorId, KeychainTxOutIndex}, Append, DescriptorExt, }; @@ -76,11 +76,11 @@ fn append_keychain_derivation_indices() { rhs_di.insert(descriptor_ids[1], 5); // value more than lhs desc 1 lhs_di.insert(descriptor_ids[3], 4); // key doesn't exist in lhs - let mut lhs = ChangeSet { + let mut lhs = keychain::ChangeSet { keychains_added: BTreeMap::<(), _>::new(), last_revealed: lhs_di, }; - let rhs = ChangeSet { + let rhs = keychain::ChangeSet { keychains_added: BTreeMap::<(), _>::new(), last_revealed: rhs_di, }; @@ -111,7 +111,7 @@ fn test_insert_different_desc_same_keychain() { ] ); - let changeset = ChangeSet { + let changeset = keychain::ChangeSet { keychains_added: [(TestKeychain::External, internal_descriptor.clone())].into(), last_revealed: [].into(), }; @@ -125,7 +125,7 @@ fn test_insert_different_desc_same_keychain() { ] ); - let changeset = ChangeSet { + let changeset = keychain::ChangeSet { keychains_added: [(TestKeychain::Internal, external_descriptor.clone())].into(), last_revealed: [].into(), }; @@ -158,7 +158,7 @@ fn test_set_all_derivation_indices() { .into(); assert_eq!( txout_index.reveal_to_target_multi(&derive_to).1, - ChangeSet { + keychain::ChangeSet { keychains_added: BTreeMap::new(), last_revealed: last_revealed.clone() } @@ -531,3 +531,67 @@ fn test_non_wildcard_derivations() { 1, ); } + +/// `::index_txout` should still index txouts with spks derived from descriptors without keychains. +/// This includes properly refilling the lookahead for said descriptors. +#[test] +fn index_txout_after_changing_descriptor_under_keychain() { + let secp = bdk_chain::bitcoin::secp256k1::Secp256k1::signing_only(); + let (desc_a, _) = Descriptor::::parse_descriptor(&secp, DESCRIPTORS[0]) + .expect("descriptor 0 must be valid"); + let (desc_b, _) = Descriptor::::parse_descriptor(&secp, DESCRIPTORS[1]) + .expect("descriptor 1 must be valid"); + let desc_id_a = desc_a.descriptor_id(); + + let mut txout_index = bdk_chain::keychain::KeychainTxOutIndex::<()>::new(10); + + // Introduce `desc_a` under keychain `()` and replace the descriptor. + let _ = txout_index.insert_descriptor(desc_a.clone(), ()); + let _ = txout_index.insert_descriptor(desc_b.clone(), ()); + + // Loop through spks in intervals of `lookahead` to create outputs with. We should always be + // able to index these outputs if `lookahead` is respected. + let spk_indices = [9, 19, 29, 39]; + for i in spk_indices { + let spk_at_index = desc_a + .at_derivation_index(i) + .expect("must derive") + .script_pubkey(); + let index_changeset = txout_index.index_txout( + // Use spk derivation index as vout as we just want an unique outpoint. + OutPoint::new(h!("mock_tx"), i as _), + &TxOut { + value: 10_000, + script_pubkey: spk_at_index, + }, + ); + assert_eq!( + index_changeset, + bdk_chain::keychain::ChangeSet { + keychains_added: BTreeMap::default(), + last_revealed: [(desc_id_a, i as u32)].into(), + }, + "must always increase last active if impl respects lookahead" + ); + } +} + +#[test] +fn insert_descriptor_no_change() { + let secp = Secp256k1::signing_only(); + let (desc, _) = + Descriptor::::parse_descriptor(&secp, DESCRIPTORS[0]).unwrap(); + let mut txout_index = KeychainTxOutIndex::<()>::default(); + assert_eq!( + txout_index.insert_descriptor(desc.clone(), ()), + keychain::ChangeSet { + keychains_added: [((), desc.clone())].into(), + last_revealed: Default::default() + }, + ); + assert_eq!( + txout_index.insert_descriptor(desc.clone(), ()), + keychain::ChangeSet::default(), + "inserting the same descriptor for keychain should return an empty changeset", + ); +}