@@ -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 {
@@ -281,7 +308,7 @@ impl MiniscriptKey for DescriptorPublicKey {
281
308
impl ToPublicKey for DescriptorPublicKey {
282
309
fn to_public_key ( & self ) -> bitcoin:: PublicKey {
283
310
match * self {
284
- DescriptorPublicKey :: PubKey ( ref pk ) => * pk ,
311
+ DescriptorPublicKey :: SinglePub ( ref spub ) => spub . key . to_public_key ( ) ,
285
312
DescriptorPublicKey :: XPub ( ref xpub) => {
286
313
let ctx = secp256k1:: Secp256k1 :: verification_only ( ) ;
287
314
xpub. xpub
@@ -812,7 +839,7 @@ mod tests {
812
839
use bitcoin:: hashes:: { hash160, sha256} ;
813
840
use bitcoin:: util:: bip32;
814
841
use bitcoin:: { self , secp256k1, PublicKey } ;
815
- use descriptor:: { DescriptorPublicKey , DescriptorXPub } ;
842
+ use descriptor:: { DescriptorPublicKey , DescriptorSinglePub , DescriptorXPub } ;
816
843
use miniscript:: satisfy:: BitcoinSig ;
817
844
use std:: collections:: HashMap ;
818
845
use std:: str:: FromStr ;
@@ -1378,37 +1405,52 @@ mod tests {
1378
1405
1379
1406
// Raw (compressed) pubkey
1380
1407
let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
1381
- let expected = DescriptorPublicKey :: PubKey (
1382
- bitcoin:: PublicKey :: from_str (
1408
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1409
+ key : bitcoin:: PublicKey :: from_str (
1383
1410
"03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ,
1384
1411
)
1385
1412
. unwrap ( ) ,
1386
- ) ;
1413
+ origin : None ,
1414
+ } ) ;
1387
1415
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1388
1416
assert_eq ! ( format!( "{}" , expected) , key) ;
1389
1417
1390
1418
// Raw (uncompressed) pubkey
1391
1419
let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ;
1392
- let expected = DescriptorPublicKey :: PubKey (
1393
- bitcoin:: PublicKey :: from_str (
1420
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1421
+ key : bitcoin:: PublicKey :: from_str (
1394
1422
"04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ,
1395
1423
)
1396
1424
. unwrap ( ) ,
1397
- ) ;
1425
+ origin : None ,
1426
+ } ) ;
1398
1427
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1399
1428
assert_eq ! ( format!( "{}" , expected) , key) ;
1429
+
1430
+ // Raw pubkey with origin
1431
+ let desc =
1432
+ "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ;
1433
+ let expected = DescriptorPublicKey :: SinglePub ( DescriptorSinglePub {
1434
+ key : bitcoin:: PublicKey :: from_str (
1435
+ "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ,
1436
+ )
1437
+ . unwrap ( ) ,
1438
+ origin : Some ( (
1439
+ bip32:: Fingerprint :: from ( & [ 0x78 , 0x41 , 0x2e , 0x3a ] [ ..] ) ,
1440
+ ( & [
1441
+ bip32:: ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ,
1442
+ bip32:: ChildNumber :: from_normal_idx ( 42 ) . unwrap ( ) ,
1443
+ bip32:: ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ,
1444
+ ] [ ..] )
1445
+ . into ( ) ,
1446
+ ) ) ,
1447
+ } ) ;
1448
+ assert_eq ! ( expected, desc. parse( ) . expect( "Parsing desc" ) ) ;
1449
+ assert_eq ! ( format!( "{}" , expected) , desc) ;
1400
1450
}
1401
1451
1402
1452
#[ test]
1403
1453
fn parse_descriptor_key_errors ( ) {
1404
- // origin is only supported for xpubs
1405
- let desc =
1406
- "[78412e3a/0'/0'/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8" ;
1407
- assert_eq ! (
1408
- DescriptorPublicKey :: from_str( desc) ,
1409
- Err ( DescriptorKeyParseError ( "Error while parsing xpub." ) )
1410
- ) ;
1411
-
1412
1454
// We refuse creating descriptors which claim to be able to derive hardened childs
1413
1455
let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42'/*" ;
1414
1456
assert_eq ! (
@@ -1445,12 +1487,30 @@ mod tests {
1445
1487
) )
1446
1488
) ;
1447
1489
1448
- // And ones with invalid xpubs
1490
+ // And ones with invalid xpubs..
1449
1491
let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*" ;
1450
1492
assert_eq ! (
1451
1493
DescriptorPublicKey :: from_str( desc) ,
1452
1494
Err ( DescriptorKeyParseError ( "Error while parsing xpub." ) )
1453
1495
) ;
1496
+
1497
+ // ..or invalid raw keys
1498
+ let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*" ;
1499
+ assert_eq ! (
1500
+ DescriptorPublicKey :: from_str( desc) ,
1501
+ Err ( DescriptorKeyParseError (
1502
+ "Error while parsing simple public key"
1503
+ ) )
1504
+ ) ;
1505
+
1506
+ // ..or invalid separators
1507
+ let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
1508
+ assert_eq ! (
1509
+ DescriptorPublicKey :: from_str( desc) ,
1510
+ Err ( DescriptorKeyParseError (
1511
+ "Error while parsing simple public key"
1512
+ ) )
1513
+ ) ;
1454
1514
}
1455
1515
1456
1516
#[ test]
0 commit comments