@@ -327,6 +327,27 @@ impl DescriptorMultiXKey<bip32::Xpriv> {
327327 }
328328}
329329
330+ /// Kinds of malformed key data
331+ #[ derive( Debug , PartialEq , Clone ) ]
332+ #[ non_exhaustive]
333+ #[ allow( missing_docs) ]
334+ pub enum NonDefiniteKeyError {
335+ Wildcard ,
336+ Multipath ,
337+ }
338+
339+ impl fmt:: Display for NonDefiniteKeyError {
340+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
341+ match * self {
342+ Self :: Wildcard => f. write_str ( "key with a wildcard cannot be a DerivedDescriptorKey" ) ,
343+ Self :: Multipath => f. write_str ( "multipath key cannot be a DerivedDescriptorKey" ) ,
344+ }
345+ }
346+ }
347+
348+ #[ cfg( feature = "std" ) ]
349+ impl error:: Error for NonDefiniteKeyError { }
350+
330351/// Kinds of malformed key data
331352#[ derive( Debug , PartialEq , Clone ) ]
332353#[ non_exhaustive]
@@ -346,29 +367,25 @@ pub enum MalformedKeyDataKind {
346367 NoKeyAfterOrigin ,
347368 NoMasterFingerprintFound ,
348369 UnclosedSquareBracket ,
349- WildcardAsDerivedDescriptorKey ,
350370}
351371
352372impl fmt:: Display for MalformedKeyDataKind {
353373 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
354- use MalformedKeyDataKind :: * ;
355-
356374 let err = match self {
357- EmptyKey => "empty key" ,
358- EncounteredUnprintableCharacter => "encountered an unprintable character" ,
359- InvalidFullPublicKeyPrefix => "only full public keys with prefixes '02', '03' or '04' are allowed" ,
360- InvalidMasterFingerprintLength => "master fingerprint should be 8 characters long" ,
361- InvalidMultiIndexStep => "invalid multi index step in multipath descriptor" ,
362- InvalidMultiXKeyDerivation => "can't make a multi-xpriv with hardened derivation steps that are not shared among all paths into a public key" ,
363- InvalidPublicKeyLength => "public keys must be 64, 66 or 130 characters in size" ,
364- InvalidWildcardInDerivationPath => "'*' may only appear as last element in a derivation path" ,
365- KeyTooShort => "key too short" ,
366- MultipleFingerprintsInPublicKey => "multiple ']' in Descriptor Public Key" ,
367- MultipleDerivationPathIndexSteps => "'<' may only appear once in a derivation path" ,
368- NoKeyAfterOrigin => "no key after origin" ,
369- NoMasterFingerprintFound => "no master fingerprint found after '['" ,
370- UnclosedSquareBracket => "unclosed '['" ,
371- WildcardAsDerivedDescriptorKey => "cannot parse key with a wilcard as a DerivedDescriptorKey" ,
375+ Self :: EmptyKey => "empty key" ,
376+ Self :: EncounteredUnprintableCharacter => "encountered an unprintable character" ,
377+ Self :: InvalidFullPublicKeyPrefix => "only full public keys with prefixes '02', '03' or '04' are allowed" ,
378+ Self :: InvalidMasterFingerprintLength => "master fingerprint should be 8 characters long" ,
379+ Self :: InvalidMultiIndexStep => "invalid multi index step in multipath descriptor" ,
380+ Self :: InvalidMultiXKeyDerivation => "can't make a multi-xpriv with hardened derivation steps that are not shared among all paths into a public key" ,
381+ Self :: InvalidPublicKeyLength => "public keys must be 64, 66 or 130 characters in size" ,
382+ Self :: InvalidWildcardInDerivationPath => "'*' may only appear as last element in a derivation path" ,
383+ Self :: KeyTooShort => "key too short" ,
384+ Self :: MultipleFingerprintsInPublicKey => "multiple ']' in Descriptor Public Key" ,
385+ Self :: MultipleDerivationPathIndexSteps => "'<' may only appear once in a derivation path" ,
386+ Self :: NoKeyAfterOrigin => "no key after origin" ,
387+ Self :: NoMasterFingerprintFound => "no master fingerprint found after '['" ,
388+ Self :: UnclosedSquareBracket => "unclosed '['" ,
372389 } ;
373390
374391 f. write_str ( err)
@@ -403,6 +420,8 @@ pub enum DescriptorKeyParseError {
403420 /// The underlying parse error
404421 err : bitcoin:: hex:: HexToArrayError ,
405422 } ,
423+ /// Attempt to construct a [`DefiniteDescriptorKey`] from an ambiguous key.
424+ NonDefiniteKey ( NonDefiniteKeyError ) ,
406425 /// Error while parsing a simple public key.
407426 FullPublicKey ( bitcoin:: key:: ParsePublicKeyError ) ,
408427 /// Error while parsing a WIF private key.
@@ -414,72 +433,56 @@ pub enum DescriptorKeyParseError {
414433impl fmt:: Display for DescriptorKeyParseError {
415434 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
416435 match self {
417- DescriptorKeyParseError :: Bip32Xpriv ( err) => {
418- write ! ( f, "error while parsing BIP32 Xpriv: {err}" )
419- }
420- DescriptorKeyParseError :: Bip32Xpub ( err) => {
421- write ! ( f, "error while parsing BIP32 Xpub: {err}" )
422- }
423- DescriptorKeyParseError :: DerivationIndexError { index, err } => {
424- write ! ( f, "error while parsing derivation index '{index}': {err}" )
425- }
426- DescriptorKeyParseError :: DeriveHardenedKey ( err) => {
427- write ! ( f, "unable to derive the hardened steps: {err}" )
428- }
429- DescriptorKeyParseError :: MalformedKeyData ( err) => {
430- write ! ( f, "{err}" )
436+ Self :: Bip32Xpriv ( err) => err. fmt ( f) ,
437+ Self :: Bip32Xpub ( err) => err. fmt ( f) ,
438+ Self :: DerivationIndexError { index, err } => {
439+ write ! ( f, "at derivation index '{index}': {err}" )
431440 }
432- DescriptorKeyParseError :: MasterDerivationPath ( err) => {
433- write ! ( f, "error while parsing master derivation path: {err}" )
434- }
435- DescriptorKeyParseError :: MasterFingerprint { fingerprint, err } => {
436- write ! ( f, "error while parsing master fingerprint '{fingerprint}': {err}" )
437- }
438- DescriptorKeyParseError :: FullPublicKey ( err) => {
439- write ! ( f, "error while parsing full public key: {err}" )
440- }
441- DescriptorKeyParseError :: WifPrivateKey ( err) => {
442- write ! ( f, "error while parsing WIF private key: {err}" )
443- }
444- DescriptorKeyParseError :: XonlyPublicKey ( err) => {
445- write ! ( f, "error while parsing xonly public key: {err}" )
441+ Self :: DeriveHardenedKey ( err) => err. fmt ( f) ,
442+ Self :: MalformedKeyData ( err) => err. fmt ( f) ,
443+ Self :: MasterDerivationPath ( err) => err. fmt ( f) ,
444+ Self :: MasterFingerprint { fingerprint, err } => {
445+ write ! ( f, "on master fingerprint '{fingerprint}': {err}" )
446446 }
447+ Self :: NonDefiniteKey ( err) => err. fmt ( f) ,
448+ Self :: FullPublicKey ( err) => err. fmt ( f) ,
449+ Self :: WifPrivateKey ( err) => err. fmt ( f) ,
450+ Self :: XonlyPublicKey ( err) => err. fmt ( f) ,
447451 }
448452 }
449453}
450454
451455#[ cfg( feature = "std" ) ]
452456impl error:: Error for DescriptorKeyParseError {
453457 fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
454- use DescriptorKeyParseError :: * ;
455-
456458 match self {
457- Bip32Xpriv ( err)
458- | Bip32Xpub ( err)
459- | DerivationIndexError { err, .. }
460- | DeriveHardenedKey ( err)
461- | MasterDerivationPath ( err) => Some ( err) ,
462- MasterFingerprint { err, .. } => Some ( err) ,
463- FullPublicKey ( err) => Some ( err) ,
464- WifPrivateKey ( err) => Some ( err) ,
465- XonlyPublicKey ( err) => Some ( err) ,
466- MalformedKeyData ( _) => None ,
459+ Self :: Bip32Xpriv ( err)
460+ | Self :: Bip32Xpub ( err)
461+ | Self :: DerivationIndexError { err, .. }
462+ | Self :: DeriveHardenedKey ( err)
463+ | Self :: MasterDerivationPath ( err) => Some ( err) ,
464+ Self :: MasterFingerprint { err, .. } => Some ( err) ,
465+ Self :: NonDefiniteKey ( err) => Some ( err) ,
466+ Self :: FullPublicKey ( err) => Some ( err) ,
467+ Self :: WifPrivateKey ( err) => Some ( err) ,
468+ Self :: XonlyPublicKey ( err) => Some ( err) ,
469+ Self :: MalformedKeyData ( _) => None ,
467470 }
468471 }
469472}
470473
471474impl fmt:: Display for DescriptorPublicKey {
472475 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
473476 match * self {
474- DescriptorPublicKey :: Single ( ref pk) => {
477+ Self :: Single ( ref pk) => {
475478 maybe_fmt_master_id ( f, & pk. origin ) ?;
476479 match pk. key {
477480 SinglePubKey :: FullKey ( full_key) => full_key. fmt ( f) ,
478481 SinglePubKey :: XOnly ( x_only_key) => x_only_key. fmt ( f) ,
479482 } ?;
480483 Ok ( ( ) )
481484 }
482- DescriptorPublicKey :: XPub ( ref xpub) => {
485+ Self :: XPub ( ref xpub) => {
483486 maybe_fmt_master_id ( f, & xpub. origin ) ?;
484487 xpub. xkey . fmt ( f) ?;
485488 fmt_derivation_path ( f, & xpub. derivation_path ) ?;
@@ -490,7 +493,7 @@ impl fmt::Display for DescriptorPublicKey {
490493 }
491494 Ok ( ( ) )
492495 }
493- DescriptorPublicKey :: MultiXPub ( ref xpub) => {
496+ Self :: MultiXPub ( ref xpub) => {
494497 maybe_fmt_master_id ( f, & xpub. origin ) ?;
495498 xpub. xkey . fmt ( f) ?;
496499 fmt_derivation_paths ( f, xpub. derivation_paths . paths ( ) ) ?;
@@ -694,19 +697,17 @@ pub enum ConversionError {
694697impl fmt:: Display for ConversionError {
695698 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
696699 f. write_str ( match * self {
697- ConversionError :: HardenedChild => "hardened child step in bip32 path" ,
698- ConversionError :: MultiKey => "multiple existing keys" ,
700+ Self :: HardenedChild => "hardened child step in bip32 path" ,
701+ Self :: MultiKey => "multiple existing keys" ,
699702 } )
700703 }
701704}
702705
703706#[ cfg( feature = "std" ) ]
704707impl error:: Error for ConversionError {
705708 fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
706- use self :: ConversionError :: * ;
707-
708709 match self {
709- HardenedChild | MultiKey => None ,
710+ Self :: HardenedChild | Self :: MultiKey => None ,
710711 }
711712 }
712713}
@@ -1272,11 +1273,13 @@ impl DefiniteDescriptorKey {
12721273 /// Construct an instance from a descriptor key and a derivation index
12731274 ///
12741275 /// Returns `None` if the key contains a wildcard
1275- pub fn new ( key : DescriptorPublicKey ) -> Option < Self > {
1276+ pub fn new ( key : DescriptorPublicKey ) -> Result < Self , NonDefiniteKeyError > {
12761277 if key. has_wildcard ( ) {
1277- None
1278+ Err ( NonDefiniteKeyError :: Wildcard )
1279+ } else if key. is_multipath ( ) {
1280+ Err ( NonDefiniteKeyError :: Multipath )
12781281 } else {
1279- Some ( Self ( key) )
1282+ Ok ( Self ( key) )
12801283 }
12811284 }
12821285
@@ -1305,10 +1308,8 @@ impl FromStr for DefiniteDescriptorKey {
13051308 type Err = DescriptorKeyParseError ;
13061309
13071310 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
1308- let inner = DescriptorPublicKey :: from_str ( s) ?;
1309- DefiniteDescriptorKey :: new ( inner) . ok_or ( DescriptorKeyParseError :: MalformedKeyData (
1310- MalformedKeyDataKind :: WildcardAsDerivedDescriptorKey ,
1311- ) )
1311+ let d = DescriptorPublicKey :: from_str ( s) ?;
1312+ DefiniteDescriptorKey :: new ( d) . map_err ( DescriptorKeyParseError :: NonDefiniteKey )
13121313 }
13131314}
13141315
@@ -1384,7 +1385,9 @@ mod test {
13841385 use super :: {
13851386 DescriptorMultiXKey , DescriptorPublicKey , DescriptorSecretKey , MiniscriptKey , Wildcard ,
13861387 } ;
1388+ use crate :: descriptor:: key:: NonDefiniteKeyError ;
13871389 use crate :: prelude:: * ;
1390+ use crate :: DefiniteDescriptorKey ;
13881391
13891392 #[ test]
13901393 fn parse_descriptor_key_errors ( ) {
@@ -1399,14 +1402,14 @@ mod test {
13991402 let desc = "[NonHexor]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*" ;
14001403 assert_eq ! (
14011404 DescriptorPublicKey :: from_str( desc) . unwrap_err( ) . to_string( ) ,
1402- "error while parsing master fingerprint 'NonHexor': failed to parse hex digit"
1405+ "on master fingerprint 'NonHexor': failed to parse hex digit"
14031406 ) ;
14041407
14051408 // And ones with invalid xpubs..
14061409 let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*" ;
14071410 assert_eq ! (
14081411 DescriptorPublicKey :: from_str( desc) . unwrap_err( ) . to_string( ) ,
1409- "error while parsing BIP32 Xpub: base58 encoding error"
1412+ "base58 encoding error"
14101413 ) ;
14111414
14121415 // ..or invalid raw keys
@@ -1446,22 +1449,19 @@ mod test {
14461449 DescriptorSecretKey :: from_str( secret_key)
14471450 . unwrap_err( )
14481451 . to_string( ) ,
1449- "error while parsing BIP32 Xpriv: unknown version magic bytes: [4, 136, 178, 30]"
1452+ "unknown version magic bytes: [4, 136, 178, 30]"
14501453 ) ;
14511454
14521455 // And ones with invalid fingerprints
14531456 let desc = "[NonHexor]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/*" ;
14541457 assert_eq ! (
14551458 DescriptorSecretKey :: from_str( desc) . unwrap_err( ) . to_string( ) ,
1456- "error while parsing master fingerprint 'NonHexor': failed to parse hex digit"
1459+ "on master fingerprint 'NonHexor': failed to parse hex digit"
14571460 ) ;
14581461
14591462 // ..or invalid raw keys
14601463 let desc = "[78412e3a]L32jTfVLei6BYTPUpwpJSkrHx8iL9GZzeErVS8y4Y/1/*" ;
1461- assert_eq ! (
1462- DescriptorSecretKey :: from_str( desc) . unwrap_err( ) . to_string( ) ,
1463- "error while parsing WIF private key: invalid base58"
1464- ) ;
1464+ assert_eq ! ( DescriptorSecretKey :: from_str( desc) . unwrap_err( ) . to_string( ) , "invalid base58" ) ;
14651465 }
14661466
14671467 #[ test]
@@ -1767,4 +1767,23 @@ mod test {
17671767 let public_key = DescriptorPublicKey :: from_str ( desc) . unwrap ( ) ;
17681768 assert_tokens ( & public_key, & [ Token :: String ( desc) ] ) ;
17691769 }
1770+
1771+ #[ test]
1772+ fn definite_keys ( ) {
1773+ // basic xpub
1774+ let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
1775+ . parse :: < DescriptorPublicKey > ( )
1776+ . unwrap ( ) ;
1777+ assert ! ( matches!( DefiniteDescriptorKey :: new( desc) , Ok ( ..) ) ) ;
1778+ // xpub with wildcard
1779+ let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/*"
1780+ . parse :: < DescriptorPublicKey > ( )
1781+ . unwrap ( ) ;
1782+ assert ! ( matches!( DefiniteDescriptorKey :: new( desc) , Err ( NonDefiniteKeyError :: Wildcard ) ) ) ;
1783+ // multipath xpub
1784+ let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/<0;1>"
1785+ . parse :: < DescriptorPublicKey > ( )
1786+ . unwrap ( ) ;
1787+ assert ! ( matches!( DefiniteDescriptorKey :: new( desc) , Err ( NonDefiniteKeyError :: Multipath ) ) ) ;
1788+ }
17701789}
0 commit comments