@@ -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,59 @@ 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+ /// An error when parsing an extended key.
498+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
499+ pub enum XKeyParseError {
500+ Bip32 ( bip32:: Error ) ,
501+ Bip388 ( WalletPolicyError ) ,
502+ }
503+
504+ #[ cfg( feature = "std" ) ]
505+ impl error:: Error for XKeyParseError {
506+ fn source ( & self ) -> Option < & ( dyn error:: Error + ' static ) > {
507+ match self {
508+ Self :: Bip32 ( err) => Some ( err) ,
509+ Self :: Bip388 ( err) => Some ( err) ,
510+ }
511+ }
512+ }
513+
514+ impl fmt:: Display for XKeyParseError {
515+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
516+ match self {
517+ Self :: Bip32 ( err) => err. fmt ( f) ,
518+ Self :: Bip388 ( err) => err. fmt ( f) ,
519+ }
520+ }
521+ }
522+
523+ impl From < bip32:: Error > for XKeyParseError {
524+ fn from ( err : bip32:: Error ) -> Self { Self :: Bip32 ( err) }
525+ }
526+
490527impl fmt:: Display for DescriptorPublicKey {
491528 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
492529 match * self {
@@ -502,22 +539,14 @@ impl fmt::Display for DescriptorPublicKey {
502539 maybe_fmt_master_id ( f, & xpub. origin ) ?;
503540 xpub. xkey . fmt ( f) ?;
504541 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- }
542+ xpub. wildcard . fmt ( f) ?;
510543 Ok ( ( ) )
511544 }
512545 Self :: MultiXPub ( ref xpub) => {
513546 maybe_fmt_master_id ( f, & xpub. origin ) ?;
514547 xpub. xkey . fmt ( f) ?;
515548 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- }
549+ xpub. wildcard . fmt ( f) ?;
521550 Ok ( ( ) )
522551 }
523552 }
@@ -610,7 +639,10 @@ fn fmt_derivation_path(f: &mut fmt::Formatter, path: &bip32::DerivationPath) ->
610639/// Writes multiple derivation paths to the formatter, no leading 'm'.
611640/// NOTE: we assume paths only differ at a single index, as prescribed by BIP389.
612641/// Will panic if the list of paths is empty.
613- fn fmt_derivation_paths ( f : & mut fmt:: Formatter , paths : & [ bip32:: DerivationPath ] ) -> fmt:: Result {
642+ pub ( crate ) fn fmt_derivation_paths < W : fmt:: Write > (
643+ f : & mut W ,
644+ paths : & [ bip32:: DerivationPath ] ,
645+ ) -> fmt:: Result {
614646 for ( i, child) in paths[ 0 ] . into_iter ( ) . enumerate ( ) {
615647 if paths. len ( ) > 1 && child != & paths[ 1 ] [ i] {
616648 write ! ( f, "/<" ) ?;
@@ -642,7 +674,7 @@ impl FromStr for DescriptorPublicKey {
642674 let ( key_part, origin) = parse_key_origin ( s) ?;
643675
644676 if key_part. contains ( "pub" ) {
645- let ( xpub, derivation_paths, wildcard) = parse_xkey_deriv ( parse_bip32_xpub , key_part) ?;
677+ let ( xpub, derivation_paths, wildcard) = parse_xkey_deriv ( key_part) ?;
646678 if derivation_paths. len ( ) > 1 {
647679 Ok ( DescriptorPublicKey :: MultiXPub ( DescriptorMultiXKey {
648680 origin,
@@ -795,6 +827,38 @@ impl DescriptorPublicKey {
795827 }
796828 }
797829
830+ /// Derivation path without the origin prefix.
831+ ///
832+ /// For wildcard keys this will return the path up to the wildcard, so you
833+ /// can get full paths by appending one additional derivation step, according
834+ /// to the wildcard type (hardened or normal).
835+ ///
836+ /// For multipath extended keys, this returns `None`.
837+ pub fn derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
838+ match * self {
839+ DescriptorPublicKey :: XPub ( ref xpub) => Some ( xpub. derivation_path . clone ( ) ) ,
840+ DescriptorPublicKey :: Single ( _) => Some ( bip32:: DerivationPath :: from ( vec ! [ ] ) ) ,
841+ DescriptorPublicKey :: MultiXPub ( _) => None ,
842+ }
843+ }
844+
845+ /// Returns a vector of derivation paths without the origin prefix.
846+ ///
847+ /// For wildcard keys this will return the path up to the wildcard, so you
848+ /// can get full paths by appending one additional derivation step, according
849+ /// to the wildcard type (hardened or normal).
850+ pub fn derivation_paths ( & self ) -> Vec < bip32:: DerivationPath > {
851+ match & self {
852+ DescriptorPublicKey :: XPub ( xpub) => {
853+ vec ! [ xpub. derivation_path. clone( ) ]
854+ }
855+ DescriptorPublicKey :: Single ( _) => {
856+ vec ! [ bip32:: DerivationPath :: from( vec![ ] ) ]
857+ }
858+ DescriptorPublicKey :: MultiXPub ( xpub) => xpub. derivation_paths . paths ( ) . clone ( ) ,
859+ }
860+ }
861+
798862 /// Whether or not the key has a wildcard
799863 pub fn has_wildcard ( & self ) -> bool {
800864 match * self {
@@ -804,7 +868,16 @@ impl DescriptorPublicKey {
804868 }
805869 }
806870
807- /// Whether or not the key has a wildcard
871+ /// Return a Wildcard if key is a XKey
872+ pub fn wildcard ( & self ) -> Option < Wildcard > {
873+ match * self {
874+ DescriptorPublicKey :: Single ( ..) => None ,
875+ DescriptorPublicKey :: XPub ( ref xpub) => Some ( xpub. wildcard ) ,
876+ DescriptorPublicKey :: MultiXPub ( ref xpub) => Some ( xpub. wildcard ) ,
877+ }
878+ }
879+
880+ /// Whether or not the key has a hardened step in path
808881 pub fn has_hardened_step ( & self ) -> bool {
809882 let paths = match self {
810883 DescriptorPublicKey :: Single ( ..) => & [ ] ,
@@ -925,8 +998,7 @@ impl FromStr for DescriptorSecretKey {
925998 . map_err ( DescriptorKeyParseError :: WifPrivateKey ) ?;
926999 Ok ( DescriptorSecretKey :: Single ( SinglePriv { key : sk, origin } ) )
9271000 } else {
928- let ( xpriv, derivation_paths, wildcard) =
929- parse_xkey_deriv ( parse_bip32_xpriv, key_part) ?;
1001+ let ( xpriv, derivation_paths, wildcard) = parse_xkey_deriv ( key_part) ?;
9301002 if derivation_paths. len ( ) > 1 {
9311003 Ok ( DescriptorSecretKey :: MultiXPrv ( DescriptorMultiXKey {
9321004 origin,
@@ -1009,26 +1081,22 @@ fn parse_key_origin(s: &str) -> Result<(&str, Option<bip32::KeySource>), Descrip
10091081 }
10101082}
10111083
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 > ,
1084+ pub ( crate ) fn parse_xkey_deriv < Key , E > (
10221085 key_deriv : & str ,
1023- ) -> Result < ( Key , Vec < bip32:: DerivationPath > , Wildcard ) , DescriptorKeyParseError > {
1086+ ) -> Result < ( Key , Vec < bip32:: DerivationPath > , Wildcard ) , DescriptorKeyParseError >
1087+ where
1088+ Key : FromStr < Err = E > ,
1089+ E : Into < XKeyParseError > ,
1090+ {
10241091 let mut key_deriv = key_deriv. split ( '/' ) ;
10251092 let xkey_str = key_deriv
10261093 . next ( )
10271094 . ok_or ( DescriptorKeyParseError :: MalformedKeyData (
10281095 MalformedKeyDataKind :: NoKeyAfterOrigin ,
10291096 ) ) ?;
10301097
1031- let xkey = parse_xkey_fn ( xkey_str) ?;
1098+ let xkey =
1099+ Key :: from_str ( xkey_str) . map_err ( |e| DescriptorKeyParseError :: XKeyParseError ( e. into ( ) ) ) ?;
10321100
10331101 let mut wildcard = Wildcard :: None ;
10341102 let mut multipath = false ;
@@ -1097,7 +1165,7 @@ fn parse_xkey_deriv<Key>(
10971165 // step all the vectors of indexes contain a single element. If it did though, one of the
10981166 // vectors contains more than one element.
10991167 // Now transform this list of vectors of steps into distinct derivation paths.
1100- . try_fold ( Vec :: new ( ) , |mut paths, index_list| {
1168+ . try_fold ( Vec :: new ( ) , |mut paths, index_list| -> Result < _ , DescriptorKeyParseError > {
11011169 let mut index_list = index_list?. into_iter ( ) ;
11021170 let first_index = index_list
11031171 . next ( )
0 commit comments