diff --git a/src/descriptor/descriptor_impl.rs b/src/descriptor/descriptor_impl.rs
new file mode 100644
index 000000000..35d600d6c
--- /dev/null
+++ b/src/descriptor/descriptor_impl.rs
@@ -0,0 +1,452 @@
+//! Module of specialized impl blocks for certain MiniscriptKeys.
+//! Contains common APIs for specific types of keys like `DescriptorPublicKey`,
+//! `DefinitePublicKey` and more.
+
+use core::convert::Infallible;
+use core::ops::Range;
+use core::str::{self, FromStr};
+
+use bitcoin::hashes::{hash160, ripemd160, sha256};
+use bitcoin::{secp256k1, Script};
+
+use super::ConversionError;
+use crate::descriptor::DescriptorSecretKey;
+use crate::prelude::*;
+use crate::{
+    hash256, DefiniteDescriptorKey, Descriptor, DescriptorPublicKey, Error, ForEachKey,
+    MsDescriptor, MsDescriptorXPubOnly, TranslatePk, Translator, XPubOnly,
+};
+
+/// Alias type for a map of public key to secret key
+///
+/// This map is returned whenever a descriptor that contains secrets is parsed using
+/// [`Descriptor::parse_descriptor`], since the descriptor will always only contain
+/// public keys. This map allows looking up the corresponding secret key given a
+/// public key from the descriptor.
+pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey>;
+
+impl MsDescriptorXPubOnly {
+    /// Whether or not the descriptor has any wildcards i.e. `/*`.
+    pub fn has_wildcard(&self) -> bool {
+        self.for_any_key(|key| key.has_wildcard())
+    }
+
+    /// Replaces all wildcards (i.e. `/*`) in the descriptor with a particular derivation index,
+    /// turning it into a *definite* descriptor.
+    ///
+    /// # Errors
+    /// - If index ≥ 2^31
+    pub fn at_derivation_index(
+        &self,
+        index: u32,
+    ) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
+        struct Derivator(u32);
+
+        impl Translator<XPubOnly, DefiniteDescriptorKey, ConversionError> for Derivator {
+            fn pk(&mut self, pk: &XPubOnly) -> Result<DefiniteDescriptorKey, ConversionError> {
+                pk.clone().at_derivation_index(self.0)
+            }
+
+            translate_hash_clone!(XPubOnly, XPubOnly, ConversionError);
+        }
+
+        self.translate_pk(&mut Derivator(index))
+            .map_err(|e| e.expect_translator_err("No Context errors while translating"))
+    }
+
+    /// Same as [`Descriptor<DescriptorPublicKey>::derived_descriptor`], but for
+    /// descriptors with Extended keys only(xpubs only).
+    pub fn derived_descriptor<C: secp256k1::Verification>(
+        &self,
+        secp: &secp256k1::Secp256k1<C>,
+        index: u32,
+    ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
+        self.at_derivation_index(index)?.derived_descriptor(secp)
+    }
+
+    /// Returns the ms descriptor of this [`MsDescriptorXPubOnly`].
+    pub fn ms_descriptor(&self) -> MsDescriptor {
+        struct MsDescriptorTranslator;
+
+        impl Translator<XPubOnly, DescriptorPublicKey, Infallible> for MsDescriptorTranslator {
+            fn pk(&mut self, pk: &XPubOnly) -> Result<DescriptorPublicKey, Infallible> {
+                Ok(DescriptorPublicKey::XPub(pk.clone()))
+            }
+
+            translate_hash_clone!(XPubOnly, XPubOnly, Infallible);
+        }
+
+        let res = self
+            .translate_pk(&mut MsDescriptorTranslator)
+            .map_err(|e| e.expect_translator_err("No Context errors while translating"));
+        // Indirect way to unwrap the infallible error type
+        match res {
+            Ok(desc) => desc,
+            Err(e) => match e {},
+        }
+    }
+
+    /// Constructs a new [`MsDescriptorXPubOnly`] from a [`MsDescriptor`].
+    ///
+    /// # Returns None if:
+    ///
+    /// - If the descriptor contains any non-xpub keys.
+    pub fn from_ms_descriptor(desc: &MsDescriptor) -> Option<Self> {
+        struct XOnlyKeyTranslator;
+
+        impl Translator<DescriptorPublicKey, XPubOnly, ()> for XOnlyKeyTranslator {
+            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<XPubOnly, ()> {
+                if let DescriptorPublicKey::XPub(xpub) = pk {
+                    Ok(xpub.clone())
+                } else {
+                    Err(())
+                }
+            }
+
+            translate_hash_clone!(DescriptorPublicKey, XPubOnly, ());
+        }
+
+        desc.translate_pk(&mut XOnlyKeyTranslator)
+            .map_err(|e| e.expect_translator_err("No Context errors while translating"))
+            .ok()
+    }
+}
+
+impl Descriptor<DescriptorPublicKey> {
+    /// Whether or not the descriptor has any wildcards
+    #[deprecated(note = "use has_wildcards instead")]
+    pub fn is_deriveable(&self) -> bool {
+        self.has_wildcard()
+    }
+
+    /// Whether or not the descriptor has any wildcards i.e. `/*`.
+    pub fn has_wildcard(&self) -> bool {
+        self.for_any_key(|key| key.has_wildcard())
+    }
+
+    /// Replaces all wildcards (i.e. `/*`) in the descriptor with a particular derivation index,
+    /// turning it into a *definite* descriptor.
+    ///
+    /// # Errors
+    /// - If index ≥ 2^31
+    pub fn at_derivation_index(
+        &self,
+        index: u32,
+    ) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
+        struct Derivator(u32);
+
+        impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ConversionError> for Derivator {
+            fn pk(
+                &mut self,
+                pk: &DescriptorPublicKey,
+            ) -> Result<DefiniteDescriptorKey, ConversionError> {
+                pk.clone().at_derivation_index(self.0)
+            }
+
+            translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, ConversionError);
+        }
+        self.translate_pk(&mut Derivator(index))
+            .map_err(|e| e.expect_translator_err("No Context errors while translating"))
+    }
+
+    #[deprecated(note = "use at_derivation_index instead")]
+    /// Deprecated name for [`Self::at_derivation_index`].
+    pub fn derive(&self, index: u32) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
+        self.at_derivation_index(index)
+    }
+
+    /// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or
+    /// otherwise converting them. All [`bitcoin::secp256k1::XOnlyPublicKey`]s are converted to by adding a
+    /// default(0x02) y-coordinate.
+    ///
+    /// This is a shorthand for:
+    ///
+    /// ```
+    /// # use miniscript::{Descriptor, DescriptorPublicKey, bitcoin::secp256k1::Secp256k1};
+    /// # use core::str::FromStr;
+    /// # let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
+    ///     .expect("Valid ranged descriptor");
+    /// # let index = 42;
+    /// # let secp = Secp256k1::verification_only();
+    /// let derived_descriptor = descriptor.at_derivation_index(index).unwrap().derived_descriptor(&secp).unwrap();
+    /// # assert_eq!(descriptor.derived_descriptor(&secp, index).unwrap(), derived_descriptor);
+    /// ```
+    ///
+    /// and is only here really here for backwards compatbility.
+    /// See [`at_derivation_index`] and `[derived_descriptor`] for more documentation.
+    ///
+    /// [`at_derivation_index`]: Self::at_derivation_index
+    /// [`derived_descriptor`]: crate::DerivedDescriptor::derived_descriptor
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if hardened derivation is attempted.
+    pub fn derived_descriptor<C: secp256k1::Verification>(
+        &self,
+        secp: &secp256k1::Secp256k1<C>,
+        index: u32,
+    ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
+        self.at_derivation_index(index)?.derived_descriptor(secp)
+    }
+
+    /// Parse a descriptor that may contain secret keys
+    ///
+    /// Internally turns every secret key found into the corresponding public key and then returns a
+    /// a descriptor that only contains public keys and a map to lookup the secret key given a public key.
+    pub fn parse_descriptor<C: secp256k1::Signing>(
+        secp: &secp256k1::Secp256k1<C>,
+        s: &str,
+    ) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), Error> {
+        fn parse_key<C: secp256k1::Signing>(
+            s: &str,
+            key_map: &mut KeyMap,
+            secp: &secp256k1::Secp256k1<C>,
+        ) -> Result<DescriptorPublicKey, Error> {
+            let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
+                Ok(sk) => (
+                    sk.to_public(secp)
+                        .map_err(|e| Error::Unexpected(e.to_string()))?,
+                    Some(sk),
+                ),
+                Err(_) => (
+                    DescriptorPublicKey::from_str(s)
+                        .map_err(|e| Error::Unexpected(e.to_string()))?,
+                    None,
+                ),
+            };
+
+            if let Some(secret_key) = secret_key {
+                key_map.insert(public_key.clone(), secret_key);
+            }
+
+            Ok(public_key)
+        }
+
+        let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
+
+        struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
+
+        impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
+            for KeyMapWrapper<'a, C>
+        {
+            fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
+                parse_key(pk, &mut self.0, self.1)
+            }
+
+            fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
+                let hash =
+                    sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
+                Ok(hash)
+            }
+
+            fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
+                let hash = hash256::Hash::from_str(hash256)
+                    .map_err(|e| Error::Unexpected(e.to_string()))?;
+                Ok(hash)
+            }
+
+            fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Error> {
+                let hash = ripemd160::Hash::from_str(ripemd160)
+                    .map_err(|e| Error::Unexpected(e.to_string()))?;
+                Ok(hash)
+            }
+
+            fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Error> {
+                let hash = hash160::Hash::from_str(hash160)
+                    .map_err(|e| Error::Unexpected(e.to_string()))?;
+                Ok(hash)
+            }
+        }
+
+        let descriptor = Descriptor::<String>::from_str(s)?;
+        let descriptor = descriptor.translate_pk(&mut keymap_pk).map_err(|e| {
+            Error::Unexpected(
+                e.expect_translator_err("No Outer context errors")
+                    .to_string(),
+            )
+        })?;
+
+        Ok((descriptor, keymap_pk.0))
+    }
+
+    /// Serialize a descriptor to string with its secret keys
+    pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
+        struct KeyMapLookUp<'a>(&'a KeyMap);
+
+        impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
+            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
+                key_to_string(pk, self.0)
+            }
+
+            fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
+                Ok(sha256.to_string())
+            }
+
+            fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
+                Ok(hash256.to_string())
+            }
+
+            fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
+                Ok(ripemd160.to_string())
+            }
+
+            fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
+                Ok(hash160.to_string())
+            }
+        }
+
+        fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
+            Ok(match key_map.get(pk) {
+                Some(secret) => secret.to_string(),
+                None => pk.to_string(),
+            })
+        }
+
+        let descriptor = self
+            .translate_pk(&mut KeyMapLookUp(key_map))
+            .expect("Translation to string cannot fail");
+
+        descriptor.to_string()
+    }
+
+    /// Utility method for deriving the descriptor at each index in a range to find one matching
+    /// `script_pubkey`.
+    ///
+    /// If it finds a match then it returns the index it was derived at and the concrete
+    /// descriptor at that index. If the descriptor is non-derivable then it will simply check the
+    /// script pubkey against the descriptor and return it if it matches (in this case the index
+    /// returned will be meaningless).
+    pub fn find_derivation_index_for_spk<C: secp256k1::Verification>(
+        &self,
+        secp: &secp256k1::Secp256k1<C>,
+        script_pubkey: &Script,
+        range: Range<u32>,
+    ) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey>)>, ConversionError> {
+        let range = if self.has_wildcard() { range } else { 0..1 };
+
+        for i in range {
+            let concrete = self.derived_descriptor(secp, i)?;
+            if &concrete.script_pubkey() == script_pubkey {
+                return Ok(Some((i, concrete)));
+            }
+        }
+
+        Ok(None)
+    }
+
+    /// Whether this descriptor contains a key that has multiple derivation paths.
+    pub fn is_multipath(&self) -> bool {
+        self.for_any_key(DescriptorPublicKey::is_multipath)
+    }
+
+    /// Get as many descriptors as different paths in this descriptor.
+    ///
+    /// For multipath descriptors it will return as many descriptors as there is
+    /// "parallel" paths. For regular descriptors it will just return itself.
+    #[allow(clippy::blocks_in_if_conditions)]
+    pub fn into_single_descriptors(self) -> Result<Vec<Descriptor<DescriptorPublicKey>>, Error> {
+        // All single-path descriptors contained in this descriptor.
+        let mut descriptors = Vec::new();
+        // We (ab)use `for_any_key` to gather the number of separate descriptors.
+        if !self.for_any_key(|key| {
+            // All multipath keys must have the same number of indexes at the "multi-index"
+            // step. So we can return early if we already populated the vector.
+            if !descriptors.is_empty() {
+                return true;
+            }
+
+            match key {
+                DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
+                DescriptorPublicKey::MultiXPub(xpub) => {
+                    for _ in 0..xpub.derivation_paths.paths().len() {
+                        descriptors.push(self.clone());
+                    }
+                    true
+                }
+            }
+        }) {
+            // If there is no multipath key, return early.
+            return Ok(vec![self]);
+        }
+        assert!(!descriptors.is_empty());
+
+        // Now, transform the multipath key of each descriptor into a single-key using each index.
+        struct IndexChoser(usize);
+        impl Translator<DescriptorPublicKey, DescriptorPublicKey, Error> for IndexChoser {
+            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DescriptorPublicKey, Error> {
+                match pk {
+                    DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => {
+                        Ok(pk.clone())
+                    }
+                    DescriptorPublicKey::MultiXPub(_) => pk
+                        .clone()
+                        .into_single_keys()
+                        .get(self.0)
+                        .cloned()
+                        .ok_or(Error::MultipathDescLenMismatch),
+                }
+            }
+            translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, Error);
+        }
+
+        for (i, desc) in descriptors.iter_mut().enumerate() {
+            let mut index_choser = IndexChoser(i);
+            *desc = desc
+                .translate_pk(&mut index_choser)
+                .map_err(|e| e.expect_translator_err("No Context errors possible"))?;
+        }
+
+        Ok(descriptors)
+    }
+}
+
+impl Descriptor<DefiniteDescriptorKey> {
+    /// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or
+    /// otherwise converting them. All [`bitcoin::secp256k1::XOnlyPublicKey`]s are converted to by adding a
+    /// default(0x02) y-coordinate.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
+    /// use miniscript::bitcoin::secp256k1;
+    /// use std::str::FromStr;
+    ///
+    /// // test from bip 86
+    /// let secp = secp256k1::Secp256k1::verification_only();
+    /// let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
+    ///     .expect("Valid ranged descriptor");
+    /// let result = descriptor.at_derivation_index(0).unwrap().derived_descriptor(&secp).expect("Non-hardened derivation");
+    /// assert_eq!(result.to_string(), "tr(03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115)#6qm9h8ym");
+    /// ```
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if hardened derivation is attempted.
+    pub fn derived_descriptor<C: secp256k1::Verification>(
+        &self,
+        secp: &secp256k1::Secp256k1<C>,
+    ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
+        struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
+
+        impl<'a, C: secp256k1::Verification>
+            Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
+            for Derivator<'a, C>
+        {
+            fn pk(
+                &mut self,
+                pk: &DefiniteDescriptorKey,
+            ) -> Result<bitcoin::PublicKey, ConversionError> {
+                pk.derive_public_key(self.0)
+            }
+
+            translate_hash_clone!(DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError);
+        }
+
+        let derived = self.translate_pk(&mut Derivator(secp));
+        match derived {
+            Ok(derived) => Ok(derived),
+            Err(e) => Err(e.expect_translator_err("No Context errors when deriving keys")),
+        }
+    }
+}
diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs
index 83308e0dc..424e28b8c 100644
--- a/src/descriptor/key.rs
+++ b/src/descriptor/key.rs
@@ -294,17 +294,7 @@ impl fmt::Display for DescriptorPublicKey {
                 }?;
                 Ok(())
             }
-            DescriptorPublicKey::XPub(ref xpub) => {
-                maybe_fmt_master_id(f, &xpub.origin)?;
-                xpub.xkey.fmt(f)?;
-                fmt_derivation_path(f, &xpub.derivation_path)?;
-                match xpub.wildcard {
-                    Wildcard::None => {}
-                    Wildcard::Unhardened => write!(f, "/*")?,
-                    Wildcard::Hardened => write!(f, "/*h")?,
-                }
-                Ok(())
-            }
+            DescriptorPublicKey::XPub(ref xpub) => xpub.fmt(f),
             DescriptorPublicKey::MultiXPub(ref xpub) => {
                 maybe_fmt_master_id(f, &xpub.origin)?;
                 xpub.xkey.fmt(f)?;
@@ -456,12 +446,7 @@ impl FromStr for DescriptorPublicKey {
                     wildcard,
                 }))
             } else {
-                Ok(DescriptorPublicKey::XPub(DescriptorXKey {
-                    origin,
-                    xkey: xpub,
-                    derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
-                    wildcard,
-                }))
+                DescriptorXKey::<bip32::ExtendedPubKey>::from_str(s).map(Self::XPub)
             }
         } else {
             let key = match key_part.len() {
@@ -525,17 +510,127 @@ impl error::Error for ConversionError {
     }
 }
 
+impl MiniscriptKey for DescriptorXKey<bip32::ExtendedPubKey> {
+    type Sha256 = sha256::Hash;
+    type Hash256 = hash256::Hash;
+    type Ripemd160 = ripemd160::Hash;
+    type Hash160 = hash160::Hash;
+
+    fn num_der_paths(&self) -> usize {
+        1
+    }
+}
+
+impl DescriptorXKey<bip32::ExtendedPubKey> {
+    /// The fingerprint of the master key associated with this key, `0x00000000` if none.
+    pub fn master_fingerprint(&self) -> bip32::Fingerprint {
+        if let Some((fingerprint, _)) = self.origin {
+            fingerprint
+        } else {
+            self.xkey.fingerprint()
+        }
+    }
+
+    /// Full path, from the master key
+    ///
+    /// For wildcard keys this will return the path up to the wildcard, so you
+    /// can get full paths by appending one additional derivation step, according
+    /// to the wildcard type (hardened or normal).
+    pub fn full_derivation_path(&self) -> bip32::DerivationPath {
+        let origin_path = if let Some((_, ref path)) = self.origin {
+            path.clone()
+        } else {
+            bip32::DerivationPath::from(vec![])
+        };
+        origin_path.extend(&self.derivation_path)
+    }
+
+    /// Whether or not the key has a wildcard
+    pub fn has_wildcard(&self) -> bool {
+        self.wildcard != Wildcard::None
+    }
+
+    /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
+    /// *definite* key (i.e. one where all the derivation paths are set).
+    ///
+    /// # Returns
+    ///
+    /// - If this key is not an xpub, returns `self`.
+    /// - If this key is an xpub but does not have a wildcard, returns `self`.
+    /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
+    ///
+    /// # Errors
+    ///
+    /// - If `index` is hardened.
+    pub fn at_derivation_index(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
+        let derivation_path = match self.wildcard {
+            Wildcard::None => self.derivation_path,
+            Wildcard::Unhardened => self.derivation_path.into_child(
+                bip32::ChildNumber::from_normal_idx(index)
+                    .ok()
+                    .ok_or(ConversionError::HardenedChild)?,
+            ),
+            Wildcard::Hardened => self.derivation_path.into_child(
+                bip32::ChildNumber::from_hardened_idx(index)
+                    .ok()
+                    .ok_or(ConversionError::HardenedChild)?,
+            ),
+        };
+        let definite = DescriptorPublicKey::XPub(DescriptorXKey {
+            origin: self.origin,
+            xkey: self.xkey,
+            derivation_path,
+            wildcard: Wildcard::None,
+        });
+
+        Ok(DefiniteDescriptorKey::new(definite)
+            .expect("The key should not contain any wildcards at this point"))
+    }
+}
+
+impl fmt::Display for DescriptorXKey<bip32::ExtendedPubKey> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        maybe_fmt_master_id(f, &self.origin)?;
+        self.xkey.fmt(f)?;
+        fmt_derivation_path(f, &self.derivation_path)?;
+        match self.wildcard {
+            Wildcard::None => {}
+            Wildcard::Unhardened => write!(f, "/*")?,
+            Wildcard::Hardened => write!(f, "/*h")?,
+        }
+        Ok(())
+    }
+}
+
+impl FromStr for DescriptorXKey<bip32::ExtendedPubKey> {
+    type Err = DescriptorKeyParseError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let (key_part, origin) = parse_key_origin(s)?;
+
+        let (xpub, derivation_paths, wildcard) =
+            parse_xkey_deriv::<bip32::ExtendedPubKey>(key_part)?;
+
+        if derivation_paths.len() > 1 {
+            return Err(DescriptorKeyParseError(
+                "Multiple derivation paths are not allowed for single extended keys",
+            ));
+        }
+
+        Ok(Self {
+            origin,
+            xkey: xpub,
+            derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
+            wildcard,
+        })
+    }
+}
+
 impl DescriptorPublicKey {
     /// The fingerprint of the master key associated with this key, `0x00000000` if none.
     pub fn master_fingerprint(&self) -> bip32::Fingerprint {
         match *self {
-            DescriptorPublicKey::XPub(ref xpub) => {
-                if let Some((fingerprint, _)) = xpub.origin {
-                    fingerprint
-                } else {
-                    xpub.xkey.fingerprint()
-                }
-            }
+            DescriptorPublicKey::XPub(ref xpub) => xpub.master_fingerprint(),
             DescriptorPublicKey::MultiXPub(ref xpub) => {
                 if let Some((fingerprint, _)) = xpub.origin {
                     fingerprint
@@ -573,14 +668,7 @@ impl DescriptorPublicKey {
     /// For multipath extended keys, this returns `None`.
     pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
         match *self {
-            DescriptorPublicKey::XPub(ref xpub) => {
-                let origin_path = if let Some((_, ref path)) = xpub.origin {
-                    path.clone()
-                } else {
-                    bip32::DerivationPath::from(vec![])
-                };
-                Some(origin_path.extend(&xpub.derivation_path))
-            }
+            DescriptorPublicKey::XPub(ref xpub) => Some(xpub.full_derivation_path()),
             DescriptorPublicKey::Single(ref single) => {
                 Some(if let Some((_, ref path)) = single.origin {
                     path.clone()
@@ -602,7 +690,7 @@ impl DescriptorPublicKey {
     pub fn has_wildcard(&self) -> bool {
         match *self {
             DescriptorPublicKey::Single(..) => false,
-            DescriptorPublicKey::XPub(ref xpub) => xpub.wildcard != Wildcard::None,
+            DescriptorPublicKey::XPub(ref xpub) => xpub.has_wildcard(),
             DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
         }
     }
@@ -628,27 +716,7 @@ impl DescriptorPublicKey {
     pub fn at_derivation_index(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
         let definite = match self {
             DescriptorPublicKey::Single(_) => self,
-            DescriptorPublicKey::XPub(xpub) => {
-                let derivation_path = match xpub.wildcard {
-                    Wildcard::None => xpub.derivation_path,
-                    Wildcard::Unhardened => xpub.derivation_path.into_child(
-                        bip32::ChildNumber::from_normal_idx(index)
-                            .ok()
-                            .ok_or(ConversionError::HardenedChild)?,
-                    ),
-                    Wildcard::Hardened => xpub.derivation_path.into_child(
-                        bip32::ChildNumber::from_hardened_idx(index)
-                            .ok()
-                            .ok_or(ConversionError::HardenedChild)?,
-                    ),
-                };
-                DescriptorPublicKey::XPub(DescriptorXKey {
-                    origin: xpub.origin,
-                    xkey: xpub.xkey,
-                    derivation_path,
-                    wildcard: Wildcard::None,
-                })
-            }
+            DescriptorPublicKey::XPub(xpub) => return xpub.at_derivation_index(index),
             DescriptorPublicKey::MultiXPub(_) => return Err(ConversionError::MultiKey),
         };
 
diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs
index 7551e1ad4..f19eb454b 100644
--- a/src/descriptor/mod.rs
+++ b/src/descriptor/mod.rs
@@ -12,29 +12,30 @@
 //!
 
 use core::fmt;
-use core::ops::Range;
-use core::str::{self, FromStr};
+use core::str::{self};
 
 use bitcoin::address::WitnessVersion;
-use bitcoin::hashes::{hash160, ripemd160, sha256};
-use bitcoin::{secp256k1, Address, Network, Script, ScriptBuf, TxIn, Witness};
+use bitcoin::{Address, Network, ScriptBuf, TxIn, Witness};
 use sync::Arc;
 
 use self::checksum::verify_checksum;
 use crate::miniscript::{Legacy, Miniscript, Segwitv0};
 use crate::prelude::*;
 use crate::{
-    expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, Satisfier,
-    ToPublicKey, TranslateErr, TranslatePk, Translator,
+    expression, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, Satisfier, ToPublicKey,
+    TranslateErr, TranslatePk, Translator,
 };
 
 mod bare;
+mod descriptor_impl;
 mod segwitv0;
 mod sh;
 mod sortedmulti;
 mod tr;
 
 // Descriptor Exports
+pub use descriptor_impl::KeyMap;
+
 pub use self::bare::{Bare, Pkh};
 pub use self::segwitv0::{Wpkh, Wsh, WshInner};
 pub use self::sh::{Sh, ShInner};
@@ -50,14 +51,6 @@ pub use self::key::{
     SinglePriv, SinglePub, SinglePubKey, Wildcard,
 };
 
-/// Alias type for a map of public key to secret key
-///
-/// This map is returned whenever a descriptor that contains secrets is parsed using
-/// [`Descriptor::parse_descriptor`], since the descriptor will always only contain
-/// public keys. This map allows looking up the corresponding secret key given a
-/// public key from the descriptor.
-pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey>;
-
 /// Script descriptor
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum Descriptor<Pk: MiniscriptKey> {
@@ -547,345 +540,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Descriptor<Pk> {
     }
 }
 
-impl Descriptor<DescriptorPublicKey> {
-    /// Whether or not the descriptor has any wildcards
-    #[deprecated(note = "use has_wildcards instead")]
-    pub fn is_deriveable(&self) -> bool {
-        self.has_wildcard()
-    }
-
-    /// Whether or not the descriptor has any wildcards i.e. `/*`.
-    pub fn has_wildcard(&self) -> bool {
-        self.for_any_key(|key| key.has_wildcard())
-    }
-
-    /// Replaces all wildcards (i.e. `/*`) in the descriptor with a particular derivation index,
-    /// turning it into a *definite* descriptor.
-    ///
-    /// # Errors
-    /// - If index ≥ 2^31
-    pub fn at_derivation_index(
-        &self,
-        index: u32,
-    ) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
-        struct Derivator(u32);
-
-        impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ConversionError> for Derivator {
-            fn pk(
-                &mut self,
-                pk: &DescriptorPublicKey,
-            ) -> Result<DefiniteDescriptorKey, ConversionError> {
-                pk.clone().at_derivation_index(self.0)
-            }
-
-            translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, ConversionError);
-        }
-        self.translate_pk(&mut Derivator(index))
-            .map_err(|e| e.expect_translator_err("No Context errors while translating"))
-    }
-
-    #[deprecated(note = "use at_derivation_index instead")]
-    /// Deprecated name for [`Self::at_derivation_index`].
-    pub fn derive(&self, index: u32) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
-        self.at_derivation_index(index)
-    }
-
-    /// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or
-    /// otherwise converting them. All [`bitcoin::secp256k1::XOnlyPublicKey`]s are converted to by adding a
-    /// default(0x02) y-coordinate.
-    ///
-    /// This is a shorthand for:
-    ///
-    /// ```
-    /// # use miniscript::{Descriptor, DescriptorPublicKey, bitcoin::secp256k1::Secp256k1};
-    /// # use core::str::FromStr;
-    /// # let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
-    ///     .expect("Valid ranged descriptor");
-    /// # let index = 42;
-    /// # let secp = Secp256k1::verification_only();
-    /// let derived_descriptor = descriptor.at_derivation_index(index).unwrap().derived_descriptor(&secp).unwrap();
-    /// # assert_eq!(descriptor.derived_descriptor(&secp, index).unwrap(), derived_descriptor);
-    /// ```
-    ///
-    /// and is only here really here for backwards compatbility.
-    /// See [`at_derivation_index`] and `[derived_descriptor`] for more documentation.
-    ///
-    /// [`at_derivation_index`]: Self::at_derivation_index
-    /// [`derived_descriptor`]: crate::DerivedDescriptor::derived_descriptor
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if hardened derivation is attempted.
-    pub fn derived_descriptor<C: secp256k1::Verification>(
-        &self,
-        secp: &secp256k1::Secp256k1<C>,
-        index: u32,
-    ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
-        self.at_derivation_index(index)?.derived_descriptor(secp)
-    }
-
-    /// Parse a descriptor that may contain secret keys
-    ///
-    /// Internally turns every secret key found into the corresponding public key and then returns a
-    /// a descriptor that only contains public keys and a map to lookup the secret key given a public key.
-    pub fn parse_descriptor<C: secp256k1::Signing>(
-        secp: &secp256k1::Secp256k1<C>,
-        s: &str,
-    ) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), Error> {
-        fn parse_key<C: secp256k1::Signing>(
-            s: &str,
-            key_map: &mut KeyMap,
-            secp: &secp256k1::Secp256k1<C>,
-        ) -> Result<DescriptorPublicKey, Error> {
-            let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
-                Ok(sk) => (
-                    sk.to_public(secp)
-                        .map_err(|e| Error::Unexpected(e.to_string()))?,
-                    Some(sk),
-                ),
-                Err(_) => (
-                    DescriptorPublicKey::from_str(s)
-                        .map_err(|e| Error::Unexpected(e.to_string()))?,
-                    None,
-                ),
-            };
-
-            if let Some(secret_key) = secret_key {
-                key_map.insert(public_key.clone(), secret_key);
-            }
-
-            Ok(public_key)
-        }
-
-        let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
-
-        struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
-
-        impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
-            for KeyMapWrapper<'a, C>
-        {
-            fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
-                parse_key(pk, &mut self.0, self.1)
-            }
-
-            fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
-                let hash =
-                    sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
-                Ok(hash)
-            }
-
-            fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
-                let hash = hash256::Hash::from_str(hash256)
-                    .map_err(|e| Error::Unexpected(e.to_string()))?;
-                Ok(hash)
-            }
-
-            fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Error> {
-                let hash = ripemd160::Hash::from_str(ripemd160)
-                    .map_err(|e| Error::Unexpected(e.to_string()))?;
-                Ok(hash)
-            }
-
-            fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Error> {
-                let hash = hash160::Hash::from_str(hash160)
-                    .map_err(|e| Error::Unexpected(e.to_string()))?;
-                Ok(hash)
-            }
-        }
-
-        let descriptor = Descriptor::<String>::from_str(s)?;
-        let descriptor = descriptor.translate_pk(&mut keymap_pk).map_err(|e| {
-            Error::Unexpected(
-                e.expect_translator_err("No Outer context errors")
-                    .to_string(),
-            )
-        })?;
-
-        Ok((descriptor, keymap_pk.0))
-    }
-
-    /// Serialize a descriptor to string with its secret keys
-    pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
-        struct KeyMapLookUp<'a>(&'a KeyMap);
-
-        impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
-            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
-                key_to_string(pk, self.0)
-            }
-
-            fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
-                Ok(sha256.to_string())
-            }
-
-            fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
-                Ok(hash256.to_string())
-            }
-
-            fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
-                Ok(ripemd160.to_string())
-            }
-
-            fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
-                Ok(hash160.to_string())
-            }
-        }
-
-        fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
-            Ok(match key_map.get(pk) {
-                Some(secret) => secret.to_string(),
-                None => pk.to_string(),
-            })
-        }
-
-        let descriptor = self
-            .translate_pk(&mut KeyMapLookUp(key_map))
-            .expect("Translation to string cannot fail");
-
-        descriptor.to_string()
-    }
-
-    /// Utility method for deriving the descriptor at each index in a range to find one matching
-    /// `script_pubkey`.
-    ///
-    /// If it finds a match then it returns the index it was derived at and the concrete
-    /// descriptor at that index. If the descriptor is non-derivable then it will simply check the
-    /// script pubkey against the descriptor and return it if it matches (in this case the index
-    /// returned will be meaningless).
-    pub fn find_derivation_index_for_spk<C: secp256k1::Verification>(
-        &self,
-        secp: &secp256k1::Secp256k1<C>,
-        script_pubkey: &Script,
-        range: Range<u32>,
-    ) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey>)>, ConversionError> {
-        let range = if self.has_wildcard() { range } else { 0..1 };
-
-        for i in range {
-            let concrete = self.derived_descriptor(secp, i)?;
-            if &concrete.script_pubkey() == script_pubkey {
-                return Ok(Some((i, concrete)));
-            }
-        }
-
-        Ok(None)
-    }
-
-    /// Whether this descriptor contains a key that has multiple derivation paths.
-    pub fn is_multipath(&self) -> bool {
-        self.for_any_key(DescriptorPublicKey::is_multipath)
-    }
-
-    /// Get as many descriptors as different paths in this descriptor.
-    ///
-    /// For multipath descriptors it will return as many descriptors as there is
-    /// "parallel" paths. For regular descriptors it will just return itself.
-    #[allow(clippy::blocks_in_if_conditions)]
-    pub fn into_single_descriptors(self) -> Result<Vec<Descriptor<DescriptorPublicKey>>, Error> {
-        // All single-path descriptors contained in this descriptor.
-        let mut descriptors = Vec::new();
-        // We (ab)use `for_any_key` to gather the number of separate descriptors.
-        if !self.for_any_key(|key| {
-            // All multipath keys must have the same number of indexes at the "multi-index"
-            // step. So we can return early if we already populated the vector.
-            if !descriptors.is_empty() {
-                return true;
-            }
-
-            match key {
-                DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
-                DescriptorPublicKey::MultiXPub(xpub) => {
-                    for _ in 0..xpub.derivation_paths.paths().len() {
-                        descriptors.push(self.clone());
-                    }
-                    true
-                }
-            }
-        }) {
-            // If there is no multipath key, return early.
-            return Ok(vec![self]);
-        }
-        assert!(!descriptors.is_empty());
-
-        // Now, transform the multipath key of each descriptor into a single-key using each index.
-        struct IndexChoser(usize);
-        impl Translator<DescriptorPublicKey, DescriptorPublicKey, Error> for IndexChoser {
-            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DescriptorPublicKey, Error> {
-                match pk {
-                    DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => {
-                        Ok(pk.clone())
-                    }
-                    DescriptorPublicKey::MultiXPub(_) => pk
-                        .clone()
-                        .into_single_keys()
-                        .get(self.0)
-                        .cloned()
-                        .ok_or(Error::MultipathDescLenMismatch),
-                }
-            }
-            translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, Error);
-        }
-
-        for (i, desc) in descriptors.iter_mut().enumerate() {
-            let mut index_choser = IndexChoser(i);
-            *desc = desc
-                .translate_pk(&mut index_choser)
-                .map_err(|e| e.expect_translator_err("No Context errors possible"))?;
-        }
-
-        Ok(descriptors)
-    }
-}
-
-impl Descriptor<DefiniteDescriptorKey> {
-    /// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or
-    /// otherwise converting them. All [`bitcoin::secp256k1::XOnlyPublicKey`]s are converted to by adding a
-    /// default(0x02) y-coordinate.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
-    /// use miniscript::bitcoin::secp256k1;
-    /// use std::str::FromStr;
-    ///
-    /// // test from bip 86
-    /// let secp = secp256k1::Secp256k1::verification_only();
-    /// let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
-    ///     .expect("Valid ranged descriptor");
-    /// let result = descriptor.at_derivation_index(0).unwrap().derived_descriptor(&secp).expect("Non-hardened derivation");
-    /// assert_eq!(result.to_string(), "tr(03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115)#6qm9h8ym");
-    /// ```
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if hardened derivation is attempted.
-    pub fn derived_descriptor<C: secp256k1::Verification>(
-        &self,
-        secp: &secp256k1::Secp256k1<C>,
-    ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
-        struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
-
-        impl<'a, C: secp256k1::Verification>
-            Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
-            for Derivator<'a, C>
-        {
-            fn pk(
-                &mut self,
-                pk: &DefiniteDescriptorKey,
-            ) -> Result<bitcoin::PublicKey, ConversionError> {
-                pk.derive_public_key(self.0)
-            }
-
-            translate_hash_clone!(DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError);
-        }
-
-        let derived = self.translate_pk(&mut Derivator(secp));
-        match derived {
-            Ok(derived) => Ok(derived),
-            Err(e) => Err(e.expect_translator_err("No Context errors when deriving keys")),
-        }
-    }
-}
-
 impl_from_tree!(
     Descriptor<Pk>,
     /// Parse an expression tree into a descriptor.
@@ -969,7 +623,9 @@ mod tests {
     use crate::descriptor::{DescriptorPublicKey, DescriptorXKey, SinglePub};
     #[cfg(feature = "compiler")]
     use crate::policy;
-    use crate::{hex_script, Descriptor, Error, Miniscript, Satisfier};
+    use crate::{
+        hex_script, Descriptor, Error, Miniscript, MsDescriptor, MsDescriptorXPubOnly, Satisfier,
+    };
 
     type StdDescriptor = Descriptor<PublicKey>;
     const TEST_PK: &str = "pk(020000000000000000000000000000000000000000000000000000000000000002)";
@@ -1690,6 +1346,39 @@ mod tests {
         assert_eq!(format!("{}", expected), desc);
     }
 
+    #[test]
+    fn test_extended_only_descriptor() {
+        fn _test_xpub_desc(raw_desc: &str, raw_addr_expected: &str) {
+            let secp = secp256k1::Secp256k1::verification_only();
+            let index = 5;
+
+            // Parse descriptor
+            let desc = MsDescriptor::from_str(raw_desc).unwrap();
+            let desc_xpub_only = MsDescriptorXPubOnly::from_str(raw_desc).unwrap();
+
+            // Same string formatting
+            assert_eq!(desc.to_string(), raw_desc);
+            assert_eq!(desc_xpub_only.to_string(), raw_desc);
+
+            // Same address
+            let addr_one = desc
+                .derived_descriptor(&secp, index)
+                .unwrap()
+                .address(bitcoin::Network::Bitcoin)
+                .unwrap();
+            let addr_two = desc_xpub_only
+                .derived_descriptor(&secp, index)
+                .unwrap()
+                .address(bitcoin::Network::Bitcoin)
+                .unwrap();
+            let addr_expected = bitcoin::Address::from_str(raw_addr_expected)
+                .unwrap()
+                .assume_checked();
+            assert_eq!(addr_one, addr_expected);
+            assert_eq!(addr_two, addr_expected);
+        }
+    }
+
     #[test]
     fn test_sortedmulti() {
         fn _test_sortedmulti(raw_desc_one: &str, raw_desc_two: &str, raw_addr_expected: &str) {
diff --git a/src/lib.rs b/src/lib.rs
index 7a51f1405..5db44244f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -118,6 +118,8 @@ mod macros;
 #[macro_use]
 mod pub_macros;
 
+use bitcoin::bip32;
+use descriptor::DescriptorXKey;
 use internals::hex::exts::DisplayHex;
 pub use pub_macros::*;
 
@@ -150,6 +152,23 @@ pub use crate::miniscript::satisfy::{Preimage32, Satisfier};
 pub use crate::miniscript::{hash256, Miniscript};
 use crate::prelude::*;
 
+/// Output descriptor supporting full capabilities of Miniscript as well as all BIPs
+/// from BIP380-386. This is the recommended descriptor type to use if you want to
+/// support all the features of Miniscript as well full descriptor support.
+pub type MsDescriptor = Descriptor<DescriptorPublicKey>;
+
+/// They key type that supports parsing only extended public keys.
+pub type XPubOnly = DescriptorXKey<bip32::ExtendedPubKey>;
+/// Output descriptor supporting all the features of Miniscript, but only supports
+/// extended public keys.
+///
+/// In particular, as of 0.11.0, this descriptor type does not support the following:
+///     - Multi-path descriptors
+///     - Single keys in descriptor without derivation paths
+///
+/// Wallet developers might want to use this descriptor type for ergonomic reasons
+/// if they are **only** interested in supporting extended public keys.
+pub type MsDescriptorXPubOnly = Descriptor<XPubOnly>;
 ///Public key trait which can be converted to Hash type
 pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
     /// Returns true if the pubkey is uncompressed. Defaults to `false`.