@@ -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
+ pub origin : Option < ( bip32:: Fingerprint , bip32:: DerivationPath ) > ,
87
+ pub key : bitcoin:: PublicKey ,
88
+ }
89
+
84
90
#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
85
91
pub struct DescriptorXPub {
86
92
pub 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,6 +154,7 @@ 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
159
return Err ( DescriptorKeyParseError (
139
160
"Key too short (<66 char), doesn't match any format" ,
@@ -148,8 +169,11 @@ impl FromStr for DescriptorPublicKey {
148
169
}
149
170
}
150
171
172
+ let mut parts = s[ 1 ..] . split ( ']' ) ;
173
+
174
+ // They may specify an origin
175
+ let mut origin = None ;
151
176
if s. chars ( ) . next ( ) . unwrap ( ) == '[' {
152
- let mut parts = s[ 1 ..] . split ( ']' ) ;
153
177
let mut raw_origin = parts
154
178
. next ( )
155
179
. ok_or ( DescriptorKeyParseError ( "Unclosed '['" ) ) ?
@@ -174,30 +198,33 @@ impl FromStr for DescriptorPublicKey {
174
198
. map_err ( |_| {
175
199
DescriptorKeyParseError ( "Error while parsing master derivation path" )
176
200
} ) ?;
201
+ origin = Some ( ( parent_fingerprint, origin_path) ) ;
202
+ }
177
203
178
- let key_deriv = parts
204
+ let key_part = if origin == None {
205
+ Ok ( s)
206
+ } else {
207
+ parts
179
208
. next ( )
180
- . ok_or ( DescriptorKeyParseError ( "No key after origin." ) ) ?;
209
+ . ok_or ( DescriptorKeyParseError ( "No key after origin." ) )
210
+ } ?;
181
211
182
- let ( xpub, derivation_path, is_wildcard) = Self :: parse_xpub_deriv ( key_deriv) ?;
212
+ // To support testnet as well
213
+ if key_part. contains ( "pub" ) {
214
+ let ( xpub, derivation_path, is_wildcard) = Self :: parse_xpub_deriv ( key_part) ?;
183
215
184
216
Ok ( DescriptorPublicKey :: XPub ( DescriptorXPub {
185
- origin : Some ( ( parent_fingerprint , origin_path ) ) ,
217
+ origin,
186
218
xpub,
187
219
derivation_path,
188
220
is_wildcard,
189
221
} ) )
190
- } else if s. starts_with ( "02" ) || s. starts_with ( "03" ) || s. starts_with ( "04" ) {
191
- let pk = bitcoin:: PublicKey :: from_str ( s)
192
- . map_err ( |_| DescriptorKeyParseError ( "Error while parsing simple public key" ) ) ?;
193
- Ok ( DescriptorPublicKey :: PubKey ( pk) )
194
222
} else {
195
- let ( xpub, derivation_path, is_wildcard) = Self :: parse_xpub_deriv ( s) ?;
196
- Ok ( DescriptorPublicKey :: XPub ( DescriptorXPub {
197
- origin : None ,
198
- xpub,
199
- derivation_path,
200
- is_wildcard,
223
+ let key = bitcoin:: PublicKey :: from_str ( key_part)
224
+ . map_err ( |_| DescriptorKeyParseError ( "Error while parsing simple public key" ) ) ?;
225
+ Ok ( DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
226
+ key,
227
+ origin,
201
228
} ) )
202
229
}
203
230
}
@@ -253,7 +280,7 @@ impl DescriptorPublicKey {
253
280
debug_assert ! ( child_number. is_normal( ) ) ;
254
281
255
282
match self {
256
- DescriptorPublicKey :: PubKey ( _) => self ,
283
+ DescriptorPublicKey :: SinglePub ( _) => self ,
257
284
DescriptorPublicKey :: XPub ( xpub) => {
258
285
if xpub. is_wildcard {
259
286
DescriptorPublicKey :: XPub ( DescriptorXPub {
@@ -282,7 +309,7 @@ impl MiniscriptKey for DescriptorPublicKey {
282
309
impl ToPublicKey for DescriptorPublicKey {
283
310
fn to_public_key ( & self ) -> bitcoin:: PublicKey {
284
311
match * self {
285
- DescriptorPublicKey :: PubKey ( ref pk ) => * pk ,
312
+ DescriptorPublicKey :: SinglePub ( ref spub ) => spub . key . to_public_key ( ) ,
286
313
DescriptorPublicKey :: XPub ( ref xpub) => {
287
314
let ctx = secp256k1:: Secp256k1 :: verification_only ( ) ;
288
315
xpub. xpub
@@ -803,7 +830,7 @@ mod tests {
803
830
use bitcoin:: hashes:: { hash160, sha256} ;
804
831
use bitcoin:: util:: bip32;
805
832
use bitcoin:: { self , secp256k1, PublicKey } ;
806
- use descriptor:: { DescriptorPublicKey , DescriptorXPub } ;
833
+ use descriptor:: { DescriptorPublicKey , DescriptorSinglePub , DescriptorXPub } ;
807
834
use miniscript:: satisfy:: BitcoinSig ;
808
835
use std:: collections:: HashMap ;
809
836
use std:: str:: FromStr ;
@@ -1369,37 +1396,52 @@ mod tests {
1369
1396
1370
1397
// Raw (compressed) pubkey
1371
1398
let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
1372
- let expected = DescriptorPublicKey :: PubKey (
1373
- bitcoin:: PublicKey :: from_str (
1399
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1400
+ key : bitcoin:: PublicKey :: from_str (
1374
1401
"03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ,
1375
1402
)
1376
1403
. unwrap ( ) ,
1377
- ) ;
1404
+ origin : None ,
1405
+ } ) ;
1378
1406
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1379
1407
assert_eq ! ( format!( "{}" , expected) , key) ;
1380
1408
1381
1409
// Raw (uncompressed) pubkey
1382
1410
let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ;
1383
- let expected = DescriptorPublicKey :: PubKey (
1384
- bitcoin:: PublicKey :: from_str (
1411
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1412
+ key : bitcoin:: PublicKey :: from_str (
1385
1413
"04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ,
1386
1414
)
1387
1415
. unwrap ( ) ,
1388
- ) ;
1416
+ origin : None ,
1417
+ } ) ;
1389
1418
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1390
1419
assert_eq ! ( format!( "{}" , expected) , key) ;
1420
+
1421
+ // Raw pubkey with origin
1422
+ let desc =
1423
+ "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ;
1424
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1425
+ key : bitcoin:: PublicKey :: from_str (
1426
+ "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ,
1427
+ )
1428
+ . unwrap ( ) ,
1429
+ origin : Some ( (
1430
+ bip32:: Fingerprint :: from ( & [ 0x78 , 0x41 , 0x2e , 0x3a ] [ ..] ) ,
1431
+ ( & [
1432
+ bip32:: ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ,
1433
+ bip32:: ChildNumber :: from_normal_idx ( 42 ) . unwrap ( ) ,
1434
+ bip32:: ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ,
1435
+ ] [ ..] )
1436
+ . into ( ) ,
1437
+ ) ) ,
1438
+ } ) ;
1439
+ assert_eq ! ( expected, desc. parse( ) . expect( "Parsing desc" ) ) ;
1440
+ assert_eq ! ( format!( "{}" , expected) , desc) ;
1391
1441
}
1392
1442
1393
1443
#[ test]
1394
1444
fn parse_descriptor_key_errors ( ) {
1395
- // origin is only supported for xpubs
1396
- let desc =
1397
- "[78412e3a/0'/0'/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ;
1398
- assert_eq ! (
1399
- DescriptorPublicKey :: from_str( desc) ,
1400
- Err ( DescriptorKeyParseError ( "Error while parsing xpub." ) )
1401
- ) ;
1402
-
1403
1445
// We refuse creating descriptors which claim to be able to derive hardened childs
1404
1446
let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42'/*" ;
1405
1447
assert_eq ! (
@@ -1436,12 +1478,30 @@ mod tests {
1436
1478
) )
1437
1479
) ;
1438
1480
1439
- // And ones with invalid xpubs
1481
+ // And ones with invalid xpubs..
1440
1482
let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*" ;
1441
1483
assert_eq ! (
1442
1484
DescriptorPublicKey :: from_str( desc) ,
1443
1485
Err ( DescriptorKeyParseError ( "Error while parsing xpub." ) )
1444
1486
) ;
1487
+
1488
+ // ..or invalid raw keys
1489
+ let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*" ;
1490
+ assert_eq ! (
1491
+ DescriptorPublicKey :: from_str( desc) ,
1492
+ Err ( DescriptorKeyParseError (
1493
+ "Error while parsing simple public key"
1494
+ ) )
1495
+ ) ;
1496
+
1497
+ // ..or invalid separators
1498
+ let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
1499
+ assert_eq ! (
1500
+ DescriptorPublicKey :: from_str( desc) ,
1501
+ Err ( DescriptorKeyParseError (
1502
+ "Error while parsing simple public key"
1503
+ ) )
1504
+ ) ;
1445
1505
}
1446
1506
1447
1507
#[ test]
0 commit comments