chore(chain): misc docs and insert_descriptor fixes
This commit is contained in:
parent
bc2a8be979
commit
4d2442c37f
@ -95,7 +95,8 @@ impl<K> Default for ChangeSet<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/// [`KeychainTxOutIndex`] controls how script pubkeys are revealed for multiple keychains, and
|
||||||
/// indexes [`TxOut`]s with them.
|
/// 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
|
/// above the last revealed index. These additionally-derived script pubkeys are called the
|
||||||
/// lookahead.
|
/// lookahead.
|
||||||
///
|
///
|
||||||
/// The [`KeychainTxOutIndex`] is constructed with the `lookahead` and cannot be altered. The
|
/// The [`KeychainTxOutIndex`] is constructed with the `lookahead` and cannot be altered. See
|
||||||
/// default `lookahead` count is 1000. Use [`new`] to set a custom `lookahead`.
|
/// [`DEFAULT_LOOKAHEAD`] for the value used in the `Default` implementation. Use [`new`] to set a
|
||||||
|
/// custom `lookahead`.
|
||||||
///
|
///
|
||||||
/// # Unbounded script pubkey iterator
|
/// # Unbounded script pubkey iterator
|
||||||
///
|
///
|
||||||
/// For script-pubkey-based chain sources (such as Electrum/Esplora), an initial scan is best done
|
/// 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
|
/// 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
|
/// 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 [`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.
|
/// 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::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
|
/// # let (external_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
|
||||||
/// # let (internal_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap();
|
/// # let (internal_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap();
|
||||||
/// # let (descriptor_42, _) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/2/*)").unwrap();
|
/// # let (descriptor_42, _) = Descriptor::<DescriptorPublicKey>::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::External, external_descriptor)?;
|
||||||
/// let _ = txout_index.insert_descriptor(MyKeychain::Internal, internal_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::MyAppUser { user_id: 42 }, descriptor_42)?;
|
||||||
///
|
///
|
||||||
/// let new_spk_for_user = txout_index.reveal_next_spk(&MyKeychain::MyAppUser{ user_id: 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
|
/// [`Ord`]: core::cmp::Ord
|
||||||
/// [`SpkTxOutIndex`]: crate::spk_txout_index::SpkTxOutIndex
|
/// [`SpkTxOutIndex`]: crate::spk_txout_index::SpkTxOutIndex
|
||||||
/// [`Descriptor`]: crate::miniscript::Descriptor
|
/// [`Descriptor`]: crate::miniscript::Descriptor
|
||||||
|
@ -158,8 +158,12 @@ mod test {
|
|||||||
let (external_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
|
let (external_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
|
||||||
let (internal_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap();
|
let (internal_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap();
|
||||||
|
|
||||||
let _ = txout_index.insert_descriptor(TestKeychain::External, external_descriptor.clone());
|
let _ = txout_index
|
||||||
let _ = txout_index.insert_descriptor(TestKeychain::Internal, internal_descriptor.clone());
|
.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)
|
(txout_index, external_descriptor, internal_descriptor)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,10 @@ fn insert_relevant_txs() {
|
|||||||
let mut graph = IndexedTxGraph::<ConfirmationHeightAnchor, KeychainTxOutIndex<()>>::new(
|
let mut graph = IndexedTxGraph::<ConfirmationHeightAnchor, KeychainTxOutIndex<()>>::new(
|
||||||
KeychainTxOutIndex::new(10),
|
KeychainTxOutIndex::new(10),
|
||||||
);
|
);
|
||||||
let _ = graph.index.insert_descriptor((), descriptor.clone());
|
let _ = graph
|
||||||
|
.index
|
||||||
|
.insert_descriptor((), descriptor.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let tx_a = Transaction {
|
let tx_a = Transaction {
|
||||||
output: vec![
|
output: vec![
|
||||||
|
@ -34,8 +34,12 @@ fn init_txout_index(
|
|||||||
) -> bdk_chain::keychain::KeychainTxOutIndex<TestKeychain> {
|
) -> bdk_chain::keychain::KeychainTxOutIndex<TestKeychain> {
|
||||||
let mut txout_index = bdk_chain::keychain::KeychainTxOutIndex::<TestKeychain>::new(lookahead);
|
let mut txout_index = bdk_chain::keychain::KeychainTxOutIndex::<TestKeychain>::new(lookahead);
|
||||||
|
|
||||||
let _ = txout_index.insert_descriptor(TestKeychain::External, external_descriptor);
|
let _ = txout_index
|
||||||
let _ = txout_index.insert_descriptor(TestKeychain::Internal, internal_descriptor);
|
.insert_descriptor(TestKeychain::External, external_descriptor)
|
||||||
|
.unwrap();
|
||||||
|
let _ = txout_index
|
||||||
|
.insert_descriptor(TestKeychain::Internal, internal_descriptor)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
txout_index
|
txout_index
|
||||||
}
|
}
|
||||||
@ -458,7 +462,9 @@ fn test_non_wildcard_derivations() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.script_pubkey();
|
.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:
|
// given:
|
||||||
// - `txout_index` with no stored scripts
|
// - `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() {
|
fn assigning_same_descriptor_to_multiple_keychains_should_error() {
|
||||||
let desc = parse_descriptor(DESCRIPTORS[0]);
|
let desc = parse_descriptor(DESCRIPTORS[0]);
|
||||||
let mut indexer = KeychainTxOutIndex::<TestKeychain>::new(0);
|
let mut indexer = KeychainTxOutIndex::<TestKeychain>::new(0);
|
||||||
let _ = indexer.insert_descriptor(TestKeychain::Internal, desc.clone());
|
let _ = indexer
|
||||||
|
.insert_descriptor(TestKeychain::Internal, desc.clone())
|
||||||
|
.unwrap();
|
||||||
assert!(indexer
|
assert!(indexer
|
||||||
.insert_descriptor(TestKeychain::External, desc)
|
.insert_descriptor(TestKeychain::External, desc)
|
||||||
.is_err())
|
.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() {
|
for (i, descriptor) in DESCRIPTORS.iter().enumerate() {
|
||||||
let descriptor = parse_descriptor(descriptor);
|
let descriptor = parse_descriptor(descriptor);
|
||||||
let _ = indexer.insert_descriptor(i, descriptor.clone());
|
let _ = indexer.insert_descriptor(i, descriptor.clone()).unwrap();
|
||||||
if i != 4 {
|
if i != 4 {
|
||||||
// skip one in the middle to see if uncovers any bugs
|
// skip one in the middle to see if uncovers any bugs
|
||||||
indexer.reveal_next_spk(&i);
|
indexer.reveal_next_spk(&i);
|
||||||
|
@ -709,7 +709,7 @@ where
|
|||||||
// them in the index here. However, the keymap is not stored in the database.
|
// them in the index here. However, the keymap is not stored in the database.
|
||||||
let (descriptor, mut keymap) =
|
let (descriptor, mut keymap) =
|
||||||
Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &args.descriptor)?;
|
Descriptor::<DescriptorPublicKey>::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
|
if let Some((internal_descriptor, internal_keymap)) = args
|
||||||
.change_descriptor
|
.change_descriptor
|
||||||
@ -718,7 +718,7 @@ where
|
|||||||
.transpose()?
|
.transpose()?
|
||||||
{
|
{
|
||||||
keymap.extend(internal_keymap);
|
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::<C>::open_or_create_new(db_magic, &args.db_path) {
|
let mut db_backend = match Store::<C>::open_or_create_new(db_magic, &args.db_path) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user