@@ -735,50 +735,57 @@ impl FromStr for DescriptorPublicKey {
735735
736736 let ( key_part, origin) = parse_key_origin ( s) ?;
737737
738- if key_part. contains ( "pub" ) {
739- let ( xpub, derivation_paths, wildcard) = parse_xkey_deriv ( key_part) ?;
740- if derivation_paths. len ( ) > 1 {
741- Ok ( DescriptorPublicKey :: MultiXPub ( DescriptorMultiXKey {
742- origin,
743- xkey : xpub,
744- derivation_paths : DerivPaths :: new ( derivation_paths) . expect ( "Not empty" ) ,
745- wildcard,
746- } ) )
747- } else {
748- Ok ( DescriptorPublicKey :: XPub ( DescriptorXKey {
749- origin,
750- xkey : xpub,
751- derivation_path : derivation_paths. into_iter ( ) . next ( ) . unwrap_or_default ( ) ,
752- wildcard,
753- } ) )
738+ match key_part. get ( ..4 ) {
739+ Some ( "xprv" | "tprv" ) => {
740+ let prv = DescriptorSecretKey :: from_str ( s) ?;
741+ prv. to_public ( & Secp256k1 :: signing_only ( ) )
754742 }
755- } else {
756- let key = match key_part. len ( ) {
757- 64 => {
758- let x_only_key = XOnlyPublicKey :: from_str ( key_part)
759- . map_err ( DescriptorKeyParseError :: XonlyPublicKey ) ?;
760- SinglePubKey :: XOnly ( x_only_key)
743+ Some ( "xpub" | "tpub" ) => {
744+ let ( xpub, derivation_paths, wildcard) = parse_xkey_deriv ( key_part) ?;
745+ if derivation_paths. len ( ) > 1 {
746+ Ok ( DescriptorPublicKey :: MultiXPub ( DescriptorMultiXKey {
747+ origin,
748+ xkey : xpub,
749+ derivation_paths : DerivPaths :: new ( derivation_paths) . expect ( "Not empty" ) ,
750+ wildcard,
751+ } ) )
752+ } else {
753+ Ok ( DescriptorPublicKey :: XPub ( DescriptorXKey {
754+ origin,
755+ xkey : xpub,
756+ derivation_path : derivation_paths. into_iter ( ) . next ( ) . unwrap_or_default ( ) ,
757+ wildcard,
758+ } ) )
761759 }
762- 66 | 130 => {
763- if !( & key_part[ 0 ..2 ] == "02"
764- || & key_part[ 0 ..2 ] == "03"
765- || & key_part[ 0 ..2 ] == "04" )
766- {
760+ }
761+ _ => {
762+ let key = match key_part. len ( ) {
763+ 64 => {
764+ let x_only_key = XOnlyPublicKey :: from_str ( key_part)
765+ . map_err ( DescriptorKeyParseError :: XonlyPublicKey ) ?;
766+ SinglePubKey :: XOnly ( x_only_key)
767+ }
768+ 66 | 130 => {
769+ if !( & key_part[ 0 ..2 ] == "02"
770+ || & key_part[ 0 ..2 ] == "03"
771+ || & key_part[ 0 ..2 ] == "04" )
772+ {
773+ return Err ( DescriptorKeyParseError :: MalformedKeyData (
774+ MalformedKeyDataKind :: InvalidFullPublicKeyPrefix ,
775+ ) ) ;
776+ }
777+ let key = bitcoin:: PublicKey :: from_str ( key_part)
778+ . map_err ( DescriptorKeyParseError :: FullPublicKey ) ?;
779+ SinglePubKey :: FullKey ( key)
780+ }
781+ _ => {
767782 return Err ( DescriptorKeyParseError :: MalformedKeyData (
768- MalformedKeyDataKind :: InvalidFullPublicKeyPrefix ,
769- ) ) ;
783+ MalformedKeyDataKind :: InvalidPublicKeyLength ,
784+ ) )
770785 }
771- let key = bitcoin:: PublicKey :: from_str ( key_part)
772- . map_err ( DescriptorKeyParseError :: FullPublicKey ) ?;
773- SinglePubKey :: FullKey ( key)
774- }
775- _ => {
776- return Err ( DescriptorKeyParseError :: MalformedKeyData (
777- MalformedKeyDataKind :: InvalidPublicKeyLength ,
778- ) )
779- }
780- } ;
781- Ok ( DescriptorPublicKey :: Single ( SinglePub { key, origin } ) )
786+ } ;
787+ Ok ( DescriptorPublicKey :: Single ( SinglePub { key, origin } ) )
788+ }
782789 }
783790 }
784791}
@@ -1952,4 +1959,13 @@ mod test {
19521959 . unwrap ( ) ;
19531960 assert_eq ! ( single_key. xkey_network( ) , None ) ;
19541961 }
1962+
1963+ // https://github.com/bitcoinfuzz/bitcoinfuzz/issues/70
1964+ // https://github.com/rust-bitcoin/rust-miniscript/issues/785
1965+ #[ test]
1966+ fn can_parse_pk_from_xprv ( ) {
1967+ assert ! ( "pk(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/*)" . parse:: <crate :: Descriptor :: <DescriptorPublicKey >>( ) . is_ok( ) ) ;
1968+ // xprv containing "pub"
1969+ assert ! ( "pk(xprv9s21ZrQH143K3MByafknWupz9D5c3Wz3MrAZpC5KFxUuwwbefg6BVSWFwyUbEcqxGTpubCGtQyC3m3vm8rZkmN1TNoc7n6VdZBt5NeXdxwV/*)" . parse:: <crate :: Descriptor :: <DescriptorPublicKey >>( ) . is_ok( ) ) ;
1970+ }
19551971}
0 commit comments