From 12188f0c52d5ab141c1dcea194851ba01c04a57d Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Thu, 8 Sep 2022 18:32:57 +0200 Subject: [PATCH] descriptors: add more utilities to the derived descriptor type We'll need those to add them to PSBTs we create. --- src/descriptors.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/descriptors.rs b/src/descriptors.rs index d58e5dbe..eb258ff1 100644 --- a/src/descriptors.rs +++ b/src/descriptors.rs @@ -11,7 +11,7 @@ use miniscript::{ MiniscriptKey, ScriptContext, ToPublicKey, TranslatePk2, }; -use std::{error, fmt, io::Write, str, sync}; +use std::{collections::BTreeMap, error, fmt, io::Write, str, sync}; use serde::{Deserialize, Serialize}; @@ -374,12 +374,56 @@ impl InheritanceDescriptor { } } +/// Map of a raw public key to the xpub used to derive it and its derivation path +pub type Bip32Deriv = BTreeMap; + impl DerivedInheritanceDescriptor { pub fn address(&self, network: bitcoin::Network) -> bitcoin::Address { self.0 .address(network) .expect("A P2WSH always has an address") } + + pub fn script_pubkey(&self) -> bitcoin::Script { + self.0.script_pubkey() + } + + pub fn witness_script(&self) -> bitcoin::Script { + self.0.explicit_script() + } + + pub fn bip32_derivations(&self) -> Bip32Deriv { + let ms = match self.0 { + descriptor::Descriptor::Wsh(ref wsh) => match wsh.as_inner() { + descriptor::WshInner::Ms(ms) => ms, + descriptor::WshInner::SortedMulti(_) => { + unreachable!("None of our descriptors is a sorted multi") + } + }, + _ => unreachable!("All our descriptors are always P2WSH"), + }; + + // For DerivedPublicKey, Pk::Hash == Self. + ms.iter_pk_pkh() + .map(|pkpkh| match pkpkh { + PkPkh::PlainPubkey(pk) => pk, + PkPkh::HashedPubkey(pkh) => pkh, + }) + .map(|k| { + ( + k.key, + (k.origin.0, bip32::DerivationPath::from(&[k.origin.1][..])), + ) + }) + .collect() + } + + /// Get the maximum size in WU of a satisfaction for this descriptor. + pub fn max_sat_weight(&self) -> usize { + self.0 + .max_satisfaction_weight() + .expect("Cannot fail for P2WSH") + } } #[cfg(test)] @@ -426,6 +470,12 @@ mod tests { "bc1qvjzcg25nsxmfccct0txjvljxjwn68htkrw57jqmjhfzvhyd2z4msc74w65", der_desc.address(bitcoin::Network::Bitcoin).to_string() ); + + // Sanity check we can call the methods on the derived desc + der_desc.script_pubkey(); + der_desc.witness_script(); + assert!(!der_desc.bip32_derivations().is_empty()); + assert!(!der_desc.max_sat_weight() > 0); } #[test]