@@ -327,6 +327,27 @@ impl DescriptorMultiXKey<bip32::Xpriv> {
327
327
}
328
328
}
329
329
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
+
330
351
/// Kinds of malformed key data
331
352
#[ derive( Debug , PartialEq , Clone ) ]
332
353
#[ non_exhaustive]
@@ -346,29 +367,25 @@ pub enum MalformedKeyDataKind {
346
367
NoKeyAfterOrigin ,
347
368
NoMasterFingerprintFound ,
348
369
UnclosedSquareBracket ,
349
- WildcardAsDerivedDescriptorKey ,
350
370
}
351
371
352
372
impl fmt:: Display for MalformedKeyDataKind {
353
373
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
354
- use MalformedKeyDataKind :: * ;
355
-
356
374
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 '['" ,
372
389
} ;
373
390
374
391
f. write_str ( err)
@@ -403,6 +420,8 @@ pub enum DescriptorKeyParseError {
403
420
/// The underlying parse error
404
421
err : bitcoin:: hex:: HexToArrayError ,
405
422
} ,
423
+ /// Attempt to construct a [`DefiniteDescriptorKey`] from an ambiguous key.
424
+ NonDefiniteKey ( NonDefiniteKeyError ) ,
406
425
/// Error while parsing a simple public key.
407
426
FullPublicKey ( bitcoin:: key:: ParsePublicKeyError ) ,
408
427
/// Error while parsing a WIF private key.
@@ -414,72 +433,56 @@ pub enum DescriptorKeyParseError {
414
433
impl fmt:: Display for DescriptorKeyParseError {
415
434
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
416
435
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}" )
431
440
}
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}" )
446
446
}
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) ,
447
451
}
448
452
}
449
453
}
450
454
451
455
#[ cfg( feature = "std" ) ]
452
456
impl error:: Error for DescriptorKeyParseError {
453
457
fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
454
- use DescriptorKeyParseError :: * ;
455
-
456
458
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 ,
467
470
}
468
471
}
469
472
}
470
473
471
474
impl fmt:: Display for DescriptorPublicKey {
472
475
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
473
476
match * self {
474
- DescriptorPublicKey :: Single ( ref pk) => {
477
+ Self :: Single ( ref pk) => {
475
478
maybe_fmt_master_id ( f, & pk. origin ) ?;
476
479
match pk. key {
477
480
SinglePubKey :: FullKey ( full_key) => full_key. fmt ( f) ,
478
481
SinglePubKey :: XOnly ( x_only_key) => x_only_key. fmt ( f) ,
479
482
} ?;
480
483
Ok ( ( ) )
481
484
}
482
- DescriptorPublicKey :: XPub ( ref xpub) => {
485
+ Self :: XPub ( ref xpub) => {
483
486
maybe_fmt_master_id ( f, & xpub. origin ) ?;
484
487
xpub. xkey . fmt ( f) ?;
485
488
fmt_derivation_path ( f, & xpub. derivation_path ) ?;
@@ -490,7 +493,7 @@ impl fmt::Display for DescriptorPublicKey {
490
493
}
491
494
Ok ( ( ) )
492
495
}
493
- DescriptorPublicKey :: MultiXPub ( ref xpub) => {
496
+ Self :: MultiXPub ( ref xpub) => {
494
497
maybe_fmt_master_id ( f, & xpub. origin ) ?;
495
498
xpub. xkey . fmt ( f) ?;
496
499
fmt_derivation_paths ( f, xpub. derivation_paths . paths ( ) ) ?;
@@ -694,19 +697,17 @@ pub enum ConversionError {
694
697
impl fmt:: Display for ConversionError {
695
698
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
696
699
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" ,
699
702
} )
700
703
}
701
704
}
702
705
703
706
#[ cfg( feature = "std" ) ]
704
707
impl error:: Error for ConversionError {
705
708
fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
706
- use self :: ConversionError :: * ;
707
-
708
709
match self {
709
- HardenedChild | MultiKey => None ,
710
+ Self :: HardenedChild | Self :: MultiKey => None ,
710
711
}
711
712
}
712
713
}
@@ -1272,11 +1273,13 @@ impl DefiniteDescriptorKey {
1272
1273
/// Construct an instance from a descriptor key and a derivation index
1273
1274
///
1274
1275
/// 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 > {
1276
1277
if key. has_wildcard ( ) {
1277
- None
1278
+ Err ( NonDefiniteKeyError :: Wildcard )
1279
+ } else if key. is_multipath ( ) {
1280
+ Err ( NonDefiniteKeyError :: Multipath )
1278
1281
} else {
1279
- Some ( Self ( key) )
1282
+ Ok ( Self ( key) )
1280
1283
}
1281
1284
}
1282
1285
@@ -1305,10 +1308,8 @@ impl FromStr for DefiniteDescriptorKey {
1305
1308
type Err = DescriptorKeyParseError ;
1306
1309
1307
1310
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 )
1312
1313
}
1313
1314
}
1314
1315
@@ -1384,7 +1385,9 @@ mod test {
1384
1385
use super :: {
1385
1386
DescriptorMultiXKey , DescriptorPublicKey , DescriptorSecretKey , MiniscriptKey , Wildcard ,
1386
1387
} ;
1388
+ use crate :: descriptor:: key:: NonDefiniteKeyError ;
1387
1389
use crate :: prelude:: * ;
1390
+ use crate :: DefiniteDescriptorKey ;
1388
1391
1389
1392
#[ test]
1390
1393
fn parse_descriptor_key_errors ( ) {
@@ -1399,14 +1402,14 @@ mod test {
1399
1402
let desc = "[NonHexor]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*" ;
1400
1403
assert_eq ! (
1401
1404
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"
1403
1406
) ;
1404
1407
1405
1408
// And ones with invalid xpubs..
1406
1409
let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*" ;
1407
1410
assert_eq ! (
1408
1411
DescriptorPublicKey :: from_str( desc) . unwrap_err( ) . to_string( ) ,
1409
- "error while parsing BIP32 Xpub: base58 encoding error"
1412
+ "base58 encoding error"
1410
1413
) ;
1411
1414
1412
1415
// ..or invalid raw keys
@@ -1446,22 +1449,19 @@ mod test {
1446
1449
DescriptorSecretKey :: from_str( secret_key)
1447
1450
. unwrap_err( )
1448
1451
. 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]"
1450
1453
) ;
1451
1454
1452
1455
// And ones with invalid fingerprints
1453
1456
let desc = "[NonHexor]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/*" ;
1454
1457
assert_eq ! (
1455
1458
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"
1457
1460
) ;
1458
1461
1459
1462
// ..or invalid raw keys
1460
1463
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" ) ;
1465
1465
}
1466
1466
1467
1467
#[ test]
@@ -1767,4 +1767,23 @@ mod test {
1767
1767
let public_key = DescriptorPublicKey :: from_str ( desc) . unwrap ( ) ;
1768
1768
assert_tokens ( & public_key, & [ Token :: String ( desc) ] ) ;
1769
1769
}
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
+ }
1770
1789
}
0 commit comments