@@ -12,6 +12,7 @@ use bitcoin::key::{PublicKey, XOnlyPublicKey};
1212use bitcoin:: secp256k1:: { Secp256k1 , Signing , Verification } ;
1313use bitcoin:: NetworkKind ;
1414
15+ use super :: WalletPolicyError ;
1516use crate :: prelude:: * ;
1617#[ cfg( feature = "serde" ) ]
1718use crate :: serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
@@ -201,6 +202,16 @@ pub enum Wildcard {
201202 Hardened ,
202203}
203204
205+ impl fmt:: Display for Wildcard {
206+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
207+ match self {
208+ Wildcard :: None => write ! ( f, "" ) ,
209+ Wildcard :: Unhardened => write ! ( f, "/*" ) ,
210+ Wildcard :: Hardened => write ! ( f, "/*h" ) ,
211+ }
212+ }
213+ }
214+
204215impl SinglePriv {
205216 /// Returns the public key of this key.
206217 fn to_public < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> SinglePub {
@@ -412,16 +423,12 @@ impl fmt::Display for MalformedKeyDataKind {
412423#[ derive( Debug , PartialEq , Eq , Clone ) ]
413424#[ non_exhaustive]
414425pub enum DescriptorKeyParseError {
415- /// Error while parsing a BIP32 extended private key
416- Bip32Xpriv ( bip32:: Error ) ,
417- /// Error while parsing a BIP32 extended public key
418- Bip32Xpub ( bip32:: Error ) ,
419426 /// Error while parsing a derivation index
420427 DerivationIndexError {
421428 /// The invalid index
422429 index : String ,
423430 /// The underlying parse error
424- err : bitcoin :: bip32:: Error ,
431+ err : bip32:: Error ,
425432 } ,
426433 /// Error deriving the hardened private key.
427434 DeriveHardenedKey ( bip32:: Error ) ,
@@ -444,13 +451,13 @@ pub enum DescriptorKeyParseError {
444451 WifPrivateKey ( bitcoin:: key:: FromWifError ) ,
445452 /// Error while parsing an X-only public key (Secp256k1 error).
446453 XonlyPublicKey ( bitcoin:: secp256k1:: Error ) ,
454+ /// XKey parsing error
455+ XKeyParseError ( XKeyParseError ) ,
447456}
448457
449458impl fmt:: Display for DescriptorKeyParseError {
450459 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
451460 match self {
452- Self :: Bip32Xpriv ( err) => err. fmt ( f) ,
453- Self :: Bip32Xpub ( err) => err. fmt ( f) ,
454461 Self :: DerivationIndexError { index, err } => {
455462 write ! ( f, "at derivation index '{index}': {err}" )
456463 }
@@ -464,29 +471,53 @@ impl fmt::Display for DescriptorKeyParseError {
464471 Self :: FullPublicKey ( err) => err. fmt ( f) ,
465472 Self :: WifPrivateKey ( err) => err. fmt ( f) ,
466473 Self :: XonlyPublicKey ( err) => err. fmt ( f) ,
474+ Self :: XKeyParseError ( err) => err. fmt ( f) ,
467475 }
468476 }
469477}
470478
471479#[ cfg( feature = "std" ) ]
472480impl error:: Error for DescriptorKeyParseError {
473- fn source ( & self ) -> Option < & ( dyn std :: error:: Error + ' static ) > {
481+ fn source ( & self ) -> Option < & ( dyn error:: Error + ' static ) > {
474482 match self {
475- Self :: Bip32Xpriv ( err)
476- | Self :: Bip32Xpub ( err)
477- | Self :: DerivationIndexError { err, .. }
483+ Self :: DerivationIndexError { err, .. }
478484 | Self :: DeriveHardenedKey ( err)
479485 | Self :: MasterDerivationPath ( err) => Some ( err) ,
480486 Self :: MasterFingerprint { err, .. } => Some ( err) ,
481487 Self :: NonDefiniteKey ( err) => Some ( err) ,
482488 Self :: FullPublicKey ( err) => Some ( err) ,
483489 Self :: WifPrivateKey ( err) => Some ( err) ,
484490 Self :: XonlyPublicKey ( err) => Some ( err) ,
491+ Self :: XKeyParseError ( err) => Some ( err) ,
485492 Self :: MalformedKeyData ( _) => None ,
486493 }
487494 }
488495}
489496
497+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
498+ pub enum XKeyParseError {
499+ Bip32 ( bip32:: Error ) ,
500+ Bip388 ( WalletPolicyError ) ,
501+ }
502+
503+ #[ cfg( feature = "std" ) ]
504+ impl error:: Error for XKeyParseError {
505+ fn source ( & self ) -> Option < & ( dyn error:: Error + ' static ) > { None }
506+ }
507+
508+ impl fmt:: Display for XKeyParseError {
509+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
510+ match self {
511+ XKeyParseError :: Bip32 ( err) => err. fmt ( f) ,
512+ XKeyParseError :: Bip388 ( err) => err. fmt ( f) ,
513+ }
514+ }
515+ }
516+
517+ impl From < bip32:: Error > for XKeyParseError {
518+ fn from ( err : bip32:: Error ) -> Self { Self :: Bip32 ( err) }
519+ }
520+
490521impl fmt:: Display for DescriptorPublicKey {
491522 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
492523 match * self {
@@ -502,22 +533,14 @@ impl fmt::Display for DescriptorPublicKey {
502533 maybe_fmt_master_id ( f, & xpub. origin ) ?;
503534 xpub. xkey . fmt ( f) ?;
504535 fmt_derivation_path ( f, & xpub. derivation_path ) ?;
505- match xpub. wildcard {
506- Wildcard :: None => { }
507- Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
508- Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
509- }
536+ xpub. wildcard . fmt ( f) ?;
510537 Ok ( ( ) )
511538 }
512539 Self :: MultiXPub ( ref xpub) => {
513540 maybe_fmt_master_id ( f, & xpub. origin ) ?;
514541 xpub. xkey . fmt ( f) ?;
515542 fmt_derivation_paths ( f, xpub. derivation_paths . paths ( ) ) ?;
516- match xpub. wildcard {
517- Wildcard :: None => { }
518- Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
519- Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
520- }
543+ xpub. wildcard . fmt ( f) ?;
521544 Ok ( ( ) )
522545 }
523546 }
@@ -610,7 +633,10 @@ fn fmt_derivation_path(f: &mut fmt::Formatter, path: &bip32::DerivationPath) ->
610633/// Writes multiple derivation paths to the formatter, no leading 'm'.
611634/// NOTE: we assume paths only differ at a single index, as prescribed by BIP389.
612635/// Will panic if the list of paths is empty.
613- fn fmt_derivation_paths ( f : & mut fmt:: Formatter , paths : & [ bip32:: DerivationPath ] ) -> fmt:: Result {
636+ pub ( crate ) fn fmt_derivation_paths < W : fmt:: Write > (
637+ f : & mut W ,
638+ paths : & [ bip32:: DerivationPath ] ,
639+ ) -> fmt:: Result {
614640 for ( i, child) in paths[ 0 ] . into_iter ( ) . enumerate ( ) {
615641 if paths. len ( ) > 1 && child != & paths[ 1 ] [ i] {
616642 write ! ( f, "/<" ) ?;
@@ -642,7 +668,7 @@ impl FromStr for DescriptorPublicKey {
642668 let ( key_part, origin) = parse_key_origin ( s) ?;
643669
644670 if key_part. contains ( "pub" ) {
645- let ( xpub, derivation_paths, wildcard) = parse_xkey_deriv ( parse_bip32_xpub , key_part) ?;
671+ let ( xpub, derivation_paths, wildcard) = parse_xkey_deriv ( key_part) ?;
646672 if derivation_paths. len ( ) > 1 {
647673 Ok ( DescriptorPublicKey :: MultiXPub ( DescriptorMultiXKey {
648674 origin,
@@ -795,6 +821,38 @@ impl DescriptorPublicKey {
795821 }
796822 }
797823
824+ /// Derivation path without the origin prefix.
825+ ///
826+ /// For wildcard keys this will return the path up to the wildcard, so you
827+ /// can get full paths by appending one additional derivation step, according
828+ /// to the wildcard type (hardened or normal).
829+ ///
830+ /// For multipath extended keys, this returns `None`.
831+ pub fn derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
832+ match * self {
833+ DescriptorPublicKey :: XPub ( ref xpub) => Some ( xpub. derivation_path . clone ( ) ) ,
834+ DescriptorPublicKey :: Single ( _) => Some ( bip32:: DerivationPath :: from ( vec ! [ ] ) ) ,
835+ DescriptorPublicKey :: MultiXPub ( _) => None ,
836+ }
837+ }
838+
839+ /// Returns a vector of derivation paths without the origin prefix.
840+ ///
841+ /// For wildcard keys this will return the path up to the wildcard, so you
842+ /// can get full paths by appending one additional derivation step, according
843+ /// to the wildcard type (hardened or normal).
844+ pub fn derivation_paths ( & self ) -> Vec < bip32:: DerivationPath > {
845+ match & self {
846+ DescriptorPublicKey :: XPub ( xpub) => {
847+ vec ! [ xpub. derivation_path. clone( ) ]
848+ }
849+ DescriptorPublicKey :: Single ( _) => {
850+ vec ! [ bip32:: DerivationPath :: from( vec![ ] ) ]
851+ }
852+ DescriptorPublicKey :: MultiXPub ( xpub) => xpub. derivation_paths . paths ( ) . clone ( ) ,
853+ }
854+ }
855+
798856 /// Whether or not the key has a wildcard
799857 pub fn has_wildcard ( & self ) -> bool {
800858 match * self {
@@ -804,7 +862,16 @@ impl DescriptorPublicKey {
804862 }
805863 }
806864
807- /// Whether or not the key has a wildcard
865+ /// Return a Wildcard if key is a XKey
866+ pub fn wildcard ( & self ) -> Option < Wildcard > {
867+ match * self {
868+ DescriptorPublicKey :: Single ( ..) => None ,
869+ DescriptorPublicKey :: XPub ( ref xpub) => Some ( xpub. wildcard ) ,
870+ DescriptorPublicKey :: MultiXPub ( ref xpub) => Some ( xpub. wildcard ) ,
871+ }
872+ }
873+
874+ /// Whether or not the key has a hardened step in path
808875 pub fn has_hardened_step ( & self ) -> bool {
809876 let paths = match self {
810877 DescriptorPublicKey :: Single ( ..) => & [ ] ,
@@ -925,8 +992,7 @@ impl FromStr for DescriptorSecretKey {
925992 . map_err ( DescriptorKeyParseError :: WifPrivateKey ) ?;
926993 Ok ( DescriptorSecretKey :: Single ( SinglePriv { key : sk, origin } ) )
927994 } else {
928- let ( xpriv, derivation_paths, wildcard) =
929- parse_xkey_deriv ( parse_bip32_xpriv, key_part) ?;
995+ let ( xpriv, derivation_paths, wildcard) = parse_xkey_deriv ( key_part) ?;
930996 if derivation_paths. len ( ) > 1 {
931997 Ok ( DescriptorSecretKey :: MultiXPrv ( DescriptorMultiXKey {
932998 origin,
@@ -1009,26 +1075,22 @@ fn parse_key_origin(s: &str) -> Result<(&str, Option<bip32::KeySource>), Descrip
10091075 }
10101076}
10111077
1012- fn parse_bip32_xpub ( xkey_str : & str ) -> Result < bip32:: Xpub , DescriptorKeyParseError > {
1013- bip32:: Xpub :: from_str ( xkey_str) . map_err ( DescriptorKeyParseError :: Bip32Xpub )
1014- }
1015-
1016- fn parse_bip32_xpriv ( xkey_str : & str ) -> Result < bip32:: Xpriv , DescriptorKeyParseError > {
1017- bip32:: Xpriv :: from_str ( xkey_str) . map_err ( DescriptorKeyParseError :: Bip32Xpriv )
1018- }
1019-
1020- fn parse_xkey_deriv < Key > (
1021- parse_xkey_fn : impl Fn ( & str ) -> Result < Key , DescriptorKeyParseError > ,
1078+ pub ( crate ) fn parse_xkey_deriv < Key , E > (
10221079 key_deriv : & str ,
1023- ) -> Result < ( Key , Vec < bip32:: DerivationPath > , Wildcard ) , DescriptorKeyParseError > {
1080+ ) -> Result < ( Key , Vec < bip32:: DerivationPath > , Wildcard ) , DescriptorKeyParseError >
1081+ where
1082+ Key : FromStr < Err = E > ,
1083+ E : Into < XKeyParseError > ,
1084+ {
10241085 let mut key_deriv = key_deriv. split ( '/' ) ;
10251086 let xkey_str = key_deriv
10261087 . next ( )
10271088 . ok_or ( DescriptorKeyParseError :: MalformedKeyData (
10281089 MalformedKeyDataKind :: NoKeyAfterOrigin ,
10291090 ) ) ?;
10301091
1031- let xkey = parse_xkey_fn ( xkey_str) ?;
1092+ let xkey =
1093+ Key :: from_str ( xkey_str) . map_err ( |e| DescriptorKeyParseError :: XKeyParseError ( e. into ( ) ) ) ?;
10321094
10331095 let mut wildcard = Wildcard :: None ;
10341096 let mut multipath = false ;
@@ -1097,7 +1159,7 @@ fn parse_xkey_deriv<Key>(
10971159 // step all the vectors of indexes contain a single element. If it did though, one of the
10981160 // vectors contains more than one element.
10991161 // Now transform this list of vectors of steps into distinct derivation paths.
1100- . try_fold ( Vec :: new ( ) , |mut paths, index_list| {
1162+ . try_fold ( Vec :: new ( ) , |mut paths, index_list| -> Result < _ , DescriptorKeyParseError > {
11011163 let mut index_list = index_list?. into_iter ( ) ;
11021164 let first_index = index_list
11031165 . next ( )
0 commit comments