From 4d2442c37f5c1bd822795271a79676d1ffbe7916 Mon Sep 17 00:00:00 2001 From: LLFourn Date: Thu, 6 Jun 2024 13:12:38 +1000 Subject: [PATCH] chore(chain): misc docs and insert_descriptor fixes --- crates/chain/src/keychain/txout_index.rs | 47 +++++-------------- crates/chain/src/spk_iter.rs | 8 +++- crates/chain/tests/test_indexed_tx_graph.rs | 5 +- .../chain/tests/test_keychain_txout_index.rs | 18 +++++-- example-crates/example_cli/src/lib.rs | 4 +- 5 files changed, 36 insertions(+), 46 deletions(-) diff --git a/crates/chain/src/keychain/txout_index.rs b/crates/chain/src/keychain/txout_index.rs index f4f736a40..846b6c248 100644 --- a/crates/chain/src/keychain/txout_index.rs +++ b/crates/chain/src/keychain/txout_index.rs @@ -95,7 +95,8 @@ impl Default for ChangeSet { } } -const DEFAULT_LOOKAHEAD: u32 = 25; +/// The default lookahead for a [`KeychainTxOutIndex`] +pub const DEFAULT_LOOKAHEAD: u32 = 25; /// [`KeychainTxOutIndex`] controls how script pubkeys are revealed for multiple keychains, and /// indexes [`TxOut`]s with them. @@ -121,15 +122,17 @@ const DEFAULT_LOOKAHEAD: u32 = 25; /// above the last revealed index. These additionally-derived script pubkeys are called the /// lookahead. /// -/// The [`KeychainTxOutIndex`] is constructed with the `lookahead` and cannot be altered. The -/// default `lookahead` count is 1000. Use [`new`] to set a custom `lookahead`. +/// The [`KeychainTxOutIndex`] is constructed with the `lookahead` and cannot be altered. See +/// [`DEFAULT_LOOKAHEAD`] for the value used in the `Default` implementation. Use [`new`] to set a +/// custom `lookahead`. /// /// # Unbounded script pubkey iterator /// /// For script-pubkey-based chain sources (such as Electrum/Esplora), an initial scan is best done /// by iterating though derived script pubkeys one by one and requesting transaction histories for /// each script pubkey. We will stop after x-number of script pubkeys have empty histories. An -/// unbounded script pubkey iterator is useful to pass to such a chain source. +/// unbounded script pubkey iterator is useful to pass to such a chain source because it doesn't +/// require holding a reference to the index. /// /// Call [`unbounded_spk_iter`] to get an unbounded script pubkey iterator for a given keychain. /// Call [`all_unbounded_spk_iters`] to get unbounded script pubkey iterators for all keychains. @@ -162,42 +165,14 @@ const DEFAULT_LOOKAHEAD: u32 = 25; /// # let (external_descriptor,_) = Descriptor::::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap(); /// # let (internal_descriptor,_) = Descriptor::::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap(); /// # let (descriptor_42, _) = Descriptor::::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/2/*)").unwrap(); -/// let _ = txout_index.insert_descriptor(MyKeychain::External, external_descriptor); -/// let _ = txout_index.insert_descriptor(MyKeychain::Internal, internal_descriptor); -/// let _ = txout_index.insert_descriptor(MyKeychain::MyAppUser { user_id: 42 }, descriptor_42); +/// let _ = txout_index.insert_descriptor(MyKeychain::External, external_descriptor)?; +/// let _ = txout_index.insert_descriptor(MyKeychain::Internal, internal_descriptor)?; +/// let _ = txout_index.insert_descriptor(MyKeychain::MyAppUser { user_id: 42 }, descriptor_42)?; /// /// let new_spk_for_user = txout_index.reveal_next_spk(&MyKeychain::MyAppUser{ user_id: 42 }); +/// # Ok::<_, bdk_chain::keychain::InsertDescriptorError<_>>(()) /// ``` /// -/// # Non-recommend keychain to descriptor assignments -/// -/// A keychain (`K`) is used to identify a descriptor. However, the following keychain to descriptor -/// arrangements result in behavior that is harder to reason about and is not recommended. -/// -/// ## Multiple keychains identifying the same descriptor -/// -/// Although a single keychain variant can only identify a single descriptor, multiple keychain -/// variants can identify the same descriptor. -/// -/// If multiple keychains identify the same descriptor: -/// 1. Methods that take in a keychain (such as [`reveal_next_spk`]) will work normally when any -/// keychain (that identifies that descriptor) is passed in. -/// 2. Methods that return data which associates with a descriptor (such as [`outpoints`], -/// [`txouts`], [`unused_spks`], etc.) the method will return the highest-ranked keychain variant -/// that identifies the descriptor. Rank is determined by the [`Ord`] implementation of the keychain -/// type. -/// -/// This arrangement is not recommended since some methods will return a single keychain variant -/// even though multiple keychain variants identify the same descriptor. -/// -/// ## Reassigning the descriptor of a single keychain -/// -/// Descriptors added to [`KeychainTxOutIndex`] are never removed. However, a keychain that -/// identifies a descriptor can be reassigned to identify a different descriptor. This may result in -/// a situation where a descriptor has no associated keychain(s), and relevant [`TxOut`]s, -/// [`OutPoint`]s and [`Script`]s (of that descriptor) will not be return by [`KeychainTxOutIndex`]. -/// Therefore, reassigning the descriptor of a single keychain is not recommended. -/// /// [`Ord`]: core::cmp::Ord /// [`SpkTxOutIndex`]: crate::spk_txout_index::SpkTxOutIndex /// [`Descriptor`]: crate::miniscript::Descriptor diff --git a/crates/chain/src/spk_iter.rs b/crates/chain/src/spk_iter.rs index d3a372794..91c271c7a 100644 --- a/crates/chain/src/spk_iter.rs +++ b/crates/chain/src/spk_iter.rs @@ -158,8 +158,12 @@ mod test { let (external_descriptor,_) = Descriptor::::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap(); let (internal_descriptor,_) = Descriptor::::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap(); - let _ = txout_index.insert_descriptor(TestKeychain::External, external_descriptor.clone()); - let _ = txout_index.insert_descriptor(TestKeychain::Internal, internal_descriptor.clone()); + let _ = txout_index + .insert_descriptor(TestKeychain::External, external_descriptor.clone()) + .unwrap(); + let _ = txout_index + .insert_descriptor(TestKeychain::Internal, internal_descriptor.clone()) + .unwrap(); (txout_index, external_descriptor, internal_descriptor) } diff --git a/crates/chain/tests/test_indexed_tx_graph.rs b/crates/chain/tests/test_indexed_tx_graph.rs index f386f0cfd..4266e184a 100644 --- a/crates/chain/tests/test_indexed_tx_graph.rs +++ b/crates/chain/tests/test_indexed_tx_graph.rs @@ -34,7 +34,10 @@ fn insert_relevant_txs() { let mut graph = IndexedTxGraph::>::new( KeychainTxOutIndex::new(10), ); - let _ = graph.index.insert_descriptor((), descriptor.clone()); + let _ = graph + .index + .insert_descriptor((), descriptor.clone()) + .unwrap(); let tx_a = Transaction { output: vec![ diff --git a/crates/chain/tests/test_keychain_txout_index.rs b/crates/chain/tests/test_keychain_txout_index.rs index b2bdba5ab..c5fd974cb 100644 --- a/crates/chain/tests/test_keychain_txout_index.rs +++ b/crates/chain/tests/test_keychain_txout_index.rs @@ -34,8 +34,12 @@ fn init_txout_index( ) -> bdk_chain::keychain::KeychainTxOutIndex { let mut txout_index = bdk_chain::keychain::KeychainTxOutIndex::::new(lookahead); - let _ = txout_index.insert_descriptor(TestKeychain::External, external_descriptor); - let _ = txout_index.insert_descriptor(TestKeychain::Internal, internal_descriptor); + let _ = txout_index + .insert_descriptor(TestKeychain::External, external_descriptor) + .unwrap(); + let _ = txout_index + .insert_descriptor(TestKeychain::Internal, internal_descriptor) + .unwrap(); txout_index } @@ -458,7 +462,9 @@ fn test_non_wildcard_derivations() { .unwrap() .script_pubkey(); - let _ = txout_index.insert_descriptor(TestKeychain::External, no_wildcard_descriptor.clone()); + let _ = txout_index + .insert_descriptor(TestKeychain::External, no_wildcard_descriptor.clone()) + .unwrap(); // given: // - `txout_index` with no stored scripts @@ -702,7 +708,9 @@ fn applying_changesets_one_by_one_vs_aggregate_must_have_same_result() { fn assigning_same_descriptor_to_multiple_keychains_should_error() { let desc = parse_descriptor(DESCRIPTORS[0]); let mut indexer = KeychainTxOutIndex::::new(0); - let _ = indexer.insert_descriptor(TestKeychain::Internal, desc.clone()); + let _ = indexer + .insert_descriptor(TestKeychain::Internal, desc.clone()) + .unwrap(); assert!(indexer .insert_descriptor(TestKeychain::External, desc) .is_err()) @@ -726,7 +734,7 @@ fn when_querying_over_a_range_of_keychains_the_utxos_should_show_up() { for (i, descriptor) in DESCRIPTORS.iter().enumerate() { let descriptor = parse_descriptor(descriptor); - let _ = indexer.insert_descriptor(i, descriptor.clone()); + let _ = indexer.insert_descriptor(i, descriptor.clone()).unwrap(); if i != 4 { // skip one in the middle to see if uncovers any bugs indexer.reveal_next_spk(&i); diff --git a/example-crates/example_cli/src/lib.rs b/example-crates/example_cli/src/lib.rs index 5355f556a..993bde416 100644 --- a/example-crates/example_cli/src/lib.rs +++ b/example-crates/example_cli/src/lib.rs @@ -709,7 +709,7 @@ where // them in the index here. However, the keymap is not stored in the database. let (descriptor, mut keymap) = Descriptor::::parse_descriptor(&secp, &args.descriptor)?; - let _ = index.insert_descriptor(Keychain::External, descriptor); + let _ = index.insert_descriptor(Keychain::External, descriptor)?; if let Some((internal_descriptor, internal_keymap)) = args .change_descriptor @@ -718,7 +718,7 @@ where .transpose()? { keymap.extend(internal_keymap); - let _ = index.insert_descriptor(Keychain::Internal, internal_descriptor); + let _ = index.insert_descriptor(Keychain::Internal, internal_descriptor)?; } let mut db_backend = match Store::::open_or_create_new(db_magic, &args.db_path) {