@@ -77,10 +77,16 @@ pub enum Descriptor<Pk: MiniscriptKey> {
77
77
78
78
#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
79
79
pub enum DescriptorPublicKey {
80
- PubKey ( bitcoin :: PublicKey ) ,
80
+ SinglePub ( DescriptorSinglePub ) ,
81
81
XPub ( DescriptorXPub ) ,
82
82
}
83
83
84
+ #[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
85
+ pub struct DescriptorSinglePub {
86
+ origin : Option < ( bip32:: Fingerprint , bip32:: DerivationPath ) > ,
87
+ key : bitcoin:: PublicKey ,
88
+ }
89
+
84
90
#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
85
91
pub struct DescriptorXPub {
86
92
origin : Option < ( bip32:: Fingerprint , bip32:: DerivationPath ) > ,
@@ -101,16 +107,13 @@ impl fmt::Display for DescriptorKeyParseError {
101
107
impl fmt:: Display for DescriptorPublicKey {
102
108
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
103
109
match * self {
104
- DescriptorPublicKey :: PubKey ( ref pk) => pk. fmt ( f) ,
110
+ DescriptorPublicKey :: SinglePub ( ref pk) => {
111
+ maybe_fmt_master_id ( f, & pk. origin ) ?;
112
+ pk. key . fmt ( f) ?;
113
+ Ok ( ( ) )
114
+ }
105
115
DescriptorPublicKey :: XPub ( ref xpub) => {
106
- if let Some ( ( ref master_id, ref master_deriv) ) = xpub. origin {
107
- fmt:: Formatter :: write_str ( f, "[" ) ?;
108
- for byte in master_id. into_bytes ( ) . iter ( ) {
109
- write ! ( f, "{:02x}" , byte) ?;
110
- }
111
- fmt_derivation_path ( f, master_deriv) ?;
112
- fmt:: Formatter :: write_str ( f, "]" ) ?;
113
- }
116
+ maybe_fmt_master_id ( f, & xpub. origin ) ?;
114
117
xpub. xpub . fmt ( f) ?;
115
118
fmt_derivation_path ( f, & xpub. derivation_path ) ?;
116
119
if xpub. is_wildcard {
@@ -122,6 +125,23 @@ impl fmt::Display for DescriptorPublicKey {
122
125
}
123
126
}
124
127
128
+ /// Writes the fingerprint of the origin, if there is one.
129
+ fn maybe_fmt_master_id (
130
+ f : & mut fmt:: Formatter ,
131
+ origin : & Option < ( bip32:: Fingerprint , bip32:: DerivationPath ) > ,
132
+ ) -> fmt:: Result {
133
+ if let Some ( ( ref master_id, ref master_deriv) ) = * origin {
134
+ fmt:: Formatter :: write_str ( f, "[" ) ?;
135
+ for byte in master_id. into_bytes ( ) . iter ( ) {
136
+ write ! ( f, "{:02x}" , byte) ?;
137
+ }
138
+ fmt_derivation_path ( f, master_deriv) ?;
139
+ fmt:: Formatter :: write_str ( f, "]" ) ?;
140
+ }
141
+
142
+ Ok ( ( ) )
143
+ }
144
+
125
145
/// Writes a derivation path to the formatter, no leading 'm'
126
146
fn fmt_derivation_path ( f : & mut fmt:: Formatter , path : & bip32:: DerivationPath ) -> fmt:: Result {
127
147
for child in path {
@@ -134,12 +154,18 @@ impl FromStr for DescriptorPublicKey {
134
154
type Err = DescriptorKeyParseError ;
135
155
136
156
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
157
+ // A "raw" public key without any origin is the least we accept.
137
158
if s. len ( ) < 66 {
138
- Err ( DescriptorKeyParseError (
159
+ return Err ( DescriptorKeyParseError (
139
160
"Key too short (<66 char), doesn't match any format" ,
140
- ) )
141
- } else if s. chars ( ) . next ( ) . unwrap ( ) == '[' {
142
- let mut parts = s[ 1 ..] . split ( ']' ) ;
161
+ ) ) ;
162
+ }
163
+
164
+ let mut parts = s[ 1 ..] . split ( ']' ) ;
165
+
166
+ // They may specify an origin
167
+ let mut origin = None ;
168
+ if s. chars ( ) . next ( ) . unwrap ( ) == '[' {
143
169
let mut raw_origin = parts
144
170
. next ( )
145
171
. ok_or ( DescriptorKeyParseError ( "Unclosed '['" ) ) ?
@@ -164,30 +190,33 @@ impl FromStr for DescriptorPublicKey {
164
190
. map_err ( |_| {
165
191
DescriptorKeyParseError ( "Error while parsing master derivation path" )
166
192
} ) ?;
193
+ origin = Some ( ( parent_fingerprint, origin_path) ) ;
194
+ }
167
195
168
- let key_deriv = parts
196
+ let key_part = if origin == None {
197
+ Ok ( s)
198
+ } else {
199
+ parts
169
200
. next ( )
170
- . ok_or ( DescriptorKeyParseError ( "No key after origin." ) ) ?;
201
+ . ok_or ( DescriptorKeyParseError ( "No key after origin." ) )
202
+ } ?;
171
203
172
- let ( xpub, derivation_path, is_wildcard) = Self :: parse_xpub_deriv ( key_deriv) ?;
204
+ // To support testnet as well
205
+ if key_part. contains ( "pub" ) {
206
+ let ( xpub, derivation_path, is_wildcard) = Self :: parse_xpub_deriv ( key_part) ?;
173
207
174
208
Ok ( DescriptorPublicKey :: XPub ( DescriptorXPub {
175
- origin : Some ( ( parent_fingerprint , origin_path ) ) ,
209
+ origin,
176
210
xpub,
177
211
derivation_path,
178
212
is_wildcard,
179
213
} ) )
180
- } else if s. starts_with ( "02" ) || s. starts_with ( "03" ) || s. starts_with ( "04" ) {
181
- let pk = bitcoin:: PublicKey :: from_str ( s)
182
- . map_err ( |_| DescriptorKeyParseError ( "Error while parsing simple public key" ) ) ?;
183
- Ok ( DescriptorPublicKey :: PubKey ( pk) )
184
214
} else {
185
- let ( xpub, derivation_path, is_wildcard) = Self :: parse_xpub_deriv ( s) ?;
186
- Ok ( DescriptorPublicKey :: XPub ( DescriptorXPub {
187
- origin : None ,
188
- xpub,
189
- derivation_path,
190
- is_wildcard,
215
+ let key = bitcoin:: PublicKey :: from_str ( key_part)
216
+ . map_err ( |_| DescriptorKeyParseError ( "Error while parsing simple public key" ) ) ?;
217
+ Ok ( DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
218
+ key,
219
+ origin,
191
220
} ) )
192
221
}
193
222
}
@@ -239,7 +268,7 @@ impl DescriptorPublicKey {
239
268
assert ! ( path. into_iter( ) . all( |c| c. is_normal( ) ) ) ;
240
269
241
270
match self {
242
- DescriptorPublicKey :: PubKey ( _) => self ,
271
+ DescriptorPublicKey :: SinglePub ( _) => self ,
243
272
DescriptorPublicKey :: XPub ( xpub) => {
244
273
if xpub. is_wildcard {
245
274
DescriptorPublicKey :: XPub ( DescriptorXPub {
@@ -272,7 +301,7 @@ impl MiniscriptKey for DescriptorPublicKey {
272
301
impl ToPublicKey for DescriptorPublicKey {
273
302
fn to_public_key ( & self ) -> bitcoin:: PublicKey {
274
303
match * self {
275
- DescriptorPublicKey :: PubKey ( ref pk ) => * pk ,
304
+ DescriptorPublicKey :: SinglePub ( ref spub ) => spub . key . to_public_key ( ) ,
276
305
DescriptorPublicKey :: XPub ( ref xpub) => {
277
306
let ctx = secp256k1:: Secp256k1 :: verification_only ( ) ;
278
307
xpub. xpub
@@ -793,7 +822,7 @@ mod tests {
793
822
use bitcoin:: hashes:: { hash160, sha256} ;
794
823
use bitcoin:: util:: bip32;
795
824
use bitcoin:: { self , secp256k1, PublicKey } ;
796
- use descriptor:: { DescriptorPublicKey , DescriptorXPub } ;
825
+ use descriptor:: { DescriptorPublicKey , DescriptorSinglePub , DescriptorXPub } ;
797
826
use miniscript:: satisfy:: BitcoinSig ;
798
827
use std:: collections:: HashMap ;
799
828
use std:: str:: FromStr ;
@@ -1359,37 +1388,52 @@ mod tests {
1359
1388
1360
1389
// Raw (compressed) pubkey
1361
1390
let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
1362
- let expected = DescriptorPublicKey :: PubKey (
1363
- bitcoin:: PublicKey :: from_str (
1391
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1392
+ key : bitcoin:: PublicKey :: from_str (
1364
1393
"03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ,
1365
1394
)
1366
1395
. unwrap ( ) ,
1367
- ) ;
1396
+ origin : None ,
1397
+ } ) ;
1368
1398
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1369
1399
assert_eq ! ( format!( "{}" , expected) , key) ;
1370
1400
1371
1401
// Raw (uncompressed) pubkey
1372
1402
let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ;
1373
- let expected = DescriptorPublicKey :: PubKey (
1374
- bitcoin:: PublicKey :: from_str (
1403
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1404
+ key : bitcoin:: PublicKey :: from_str (
1375
1405
"04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ,
1376
1406
)
1377
1407
. unwrap ( ) ,
1378
- ) ;
1408
+ origin : None ,
1409
+ } ) ;
1379
1410
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1380
1411
assert_eq ! ( format!( "{}" , expected) , key) ;
1412
+
1413
+ // Raw pubkey with origin
1414
+ let desc =
1415
+ "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ;
1416
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1417
+ key : bitcoin:: PublicKey :: from_str (
1418
+ "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ,
1419
+ )
1420
+ . unwrap ( ) ,
1421
+ origin : Some ( (
1422
+ bip32:: Fingerprint :: from ( & [ 0x78 , 0x41 , 0x2e , 0x3a ] [ ..] ) ,
1423
+ ( & [
1424
+ bip32:: ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ,
1425
+ bip32:: ChildNumber :: from_normal_idx ( 42 ) . unwrap ( ) ,
1426
+ bip32:: ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ,
1427
+ ] [ ..] )
1428
+ . into ( ) ,
1429
+ ) ) ,
1430
+ } ) ;
1431
+ assert_eq ! ( expected, desc. parse( ) . expect( "Parsing desc" ) ) ;
1432
+ assert_eq ! ( format!( "{}" , expected) , desc) ;
1381
1433
}
1382
1434
1383
1435
#[ test]
1384
1436
fn parse_descriptor_key_errors ( ) {
1385
- // origin is only supported for xpubs
1386
- let desc =
1387
- "[78412e3a/0'/0'/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ;
1388
- assert_eq ! (
1389
- DescriptorPublicKey :: from_str( desc) ,
1390
- Err ( DescriptorKeyParseError ( "Error while parsing xpub." ) )
1391
- ) ;
1392
-
1393
1437
// We refuse creating descriptors which claim to be able to derive hardened childs
1394
1438
let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42'/*" ;
1395
1439
assert_eq ! (
@@ -1417,12 +1461,30 @@ mod tests {
1417
1461
) )
1418
1462
) ;
1419
1463
1420
- // And ones with invalid xpubs
1464
+ // And ones with invalid xpubs..
1421
1465
let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*" ;
1422
1466
assert_eq ! (
1423
1467
DescriptorPublicKey :: from_str( desc) ,
1424
1468
Err ( DescriptorKeyParseError ( "Error while parsing xpub." ) )
1425
1469
) ;
1470
+
1471
+ // ..or invalid raw keys
1472
+ let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*" ;
1473
+ assert_eq ! (
1474
+ DescriptorPublicKey :: from_str( desc) ,
1475
+ Err ( DescriptorKeyParseError (
1476
+ "Error while parsing simple public key"
1477
+ ) )
1478
+ ) ;
1479
+
1480
+ // ..or invalid separators
1481
+ let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
1482
+ assert_eq ! (
1483
+ DescriptorPublicKey :: from_str( desc) ,
1484
+ Err ( DescriptorKeyParseError (
1485
+ "Error while parsing simple public key"
1486
+ ) )
1487
+ ) ;
1426
1488
}
1427
1489
1428
1490
#[ test]
0 commit comments