-use crate::{
- alloc::{string::ToString, vec::Vec},
- miniscript::{Descriptor, DescriptorPublicKey},
-};
+use crate::miniscript::{Descriptor, DescriptorPublicKey};
use bitcoin::hashes::{hash_newtype, sha256, Hash};
hash_newtype! {
- /// Represents the ID of a descriptor, defined as the sha256 hash of
- /// the descriptor string, checksum excluded.
+ /// Represents the unique ID of a descriptor.
///
/// This is useful for having a fixed-length unique representation of a descriptor,
/// in particular, we use it to persist application state changes related to the
/// Panics if the descriptor wildcard is hardened.
fn dust_value(&self) -> u64;
- /// Returns the descriptor id, calculated as the sha256 of the descriptor, checksum not
- /// included.
+ /// Returns the descriptor ID, calculated as the sha256 hash of the spk derived from the
+ /// descriptor at index 0.
fn descriptor_id(&self) -> DescriptorId;
}
}
fn descriptor_id(&self) -> DescriptorId {
- let desc = self.to_string();
- let desc_without_checksum = desc.split('#').next().expect("Must be here");
- let descriptor_bytes = <Vec<u8>>::from(desc_without_checksum.as_bytes());
- DescriptorId(sha256::Hash::hash(&descriptor_bytes))
+ let spk = self.at_derivation_index(0).unwrap().script_pubkey();
+ DescriptorId(sha256::Hash::hash(spk.as_bytes()))
}
}
///
/// keychain <-> descriptor is a one-to-one mapping that cannot be changed. Attempting to do so
/// will return a [`InsertDescriptorError<K>`].
+ ///
+ /// `[KeychainTxOutIndex]` will prevent you from inserting two descriptors which derive the same
+ /// script pubkey at index 0, but it's up to you to ensure that descriptors don't collide at
+ /// other indices. If they do nothing catastrophic happens at the `KeychainTxOutIndex` level
+ /// (one keychain just becomes the defacto owner of that spk arbitrarily) but this may have
+ /// subtle implications up the application stack like one UTXO being missing from one keychain
+ /// because it has been assigned to another which produces the same script pubkey.
pub fn insert_descriptor(
&mut self,
keychain: K,
/// [`ChangeSet`]s (see [`take_staged`]). Also see individual functions and example for instructions
/// on when [`Wallet`] state needs to be persisted.
///
+/// The `Wallet` descriptor (external) and change descriptor (internal) must not derive the same
+/// script pubkeys. See [`KeychainTxOutIndex::insert_descriptor()`] for more details.
+///
/// [`signer`]: crate::signer
/// [`take_staged`]: Wallet::take_staged
#[derive(Debug)]