@@ -27,7 +27,9 @@ use std::fmt;
27
27
use std:: str:: { self , FromStr } ;
28
28
29
29
use bitcoin:: blockdata:: { opcodes, script} ;
30
+ use bitcoin:: hashes:: hash160;
30
31
use bitcoin:: hashes:: hex:: FromHex ;
32
+ use bitcoin:: secp256k1;
31
33
use bitcoin:: util:: bip32;
32
34
use bitcoin:: { self , Script } ;
33
35
@@ -73,13 +75,13 @@ pub enum Descriptor<Pk: MiniscriptKey> {
73
75
ShWsh ( Miniscript < Pk , Segwitv0 > ) ,
74
76
}
75
77
76
- #[ derive( Debug , Eq , PartialEq ) ]
78
+ #[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
77
79
pub enum DescriptorPublicKey {
78
80
PukKey ( bitcoin:: PublicKey ) ,
79
81
XPub ( DescriptorXPub ) ,
80
82
}
81
83
82
- #[ derive( Debug , Eq , PartialEq ) ]
84
+ #[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
83
85
pub struct DescriptorXPub {
84
86
origin : Option < ( bip32:: Fingerprint , bip32:: DerivationPath ) > ,
85
87
xpub : bip32:: ExtendedPubKey ,
@@ -90,6 +92,38 @@ pub struct DescriptorXPub {
90
92
#[ derive( Debug , PartialEq ) ]
91
93
pub struct DescriptorKeyParseError ( & ' static str ) ;
92
94
95
+ impl fmt:: Display for DescriptorPublicKey {
96
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
97
+ match * self {
98
+ DescriptorPublicKey :: PukKey ( ref pk) => pk. fmt ( f) ,
99
+ DescriptorPublicKey :: XPub ( ref xpub) => {
100
+ if let Some ( ( ref master_id, ref master_deriv) ) = xpub. origin {
101
+ fmt:: Formatter :: write_str ( f, "[" ) ?;
102
+ for byte in master_id. into_bytes ( ) . iter ( ) {
103
+ write ! ( f, "{:02x}" , byte) ?;
104
+ }
105
+ fmt_derivation_path ( f, master_deriv) ?;
106
+ fmt:: Formatter :: write_str ( f, "]" ) ?;
107
+ }
108
+ xpub. xpub . fmt ( f) ?;
109
+ fmt_derivation_path ( f, & xpub. derivation_path ) ?;
110
+ if xpub. is_wildcard {
111
+ write ! ( f, "/*" ) ?;
112
+ }
113
+ Ok ( ( ) )
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ /// Writes a derivation path to the formatter, no leading 'm'
120
+ fn fmt_derivation_path ( f : & mut fmt:: Formatter , path : & bip32:: DerivationPath ) -> fmt:: Result {
121
+ for child in path {
122
+ write ! ( f, "/{}" , child) ?;
123
+ }
124
+ Ok ( ( ) )
125
+ }
126
+
93
127
impl FromStr for DescriptorPublicKey {
94
128
type Err = DescriptorKeyParseError ;
95
129
@@ -193,6 +227,24 @@ impl DescriptorPublicKey {
193
227
}
194
228
}
195
229
230
+ impl MiniscriptKey for DescriptorPublicKey {
231
+ type Hash = hash160:: Hash ;
232
+
233
+ fn to_pubkeyhash ( & self ) -> Self :: Hash {
234
+ match * self {
235
+ DescriptorPublicKey :: PukKey ( ref pk) => pk. to_pubkeyhash ( ) ,
236
+ DescriptorPublicKey :: XPub ( ref xpub) => {
237
+ let ctx = secp256k1:: Secp256k1 :: verification_only ( ) ;
238
+ xpub. xpub
239
+ . derive_pub ( & ctx, & xpub. derivation_path )
240
+ . expect ( "Won't fail, only normal derivations" )
241
+ . public_key
242
+ . to_pubkeyhash ( )
243
+ }
244
+ }
245
+ }
246
+ }
247
+
196
248
impl < Pk : MiniscriptKey > Descriptor < Pk > {
197
249
/// Convert a descriptor using abstract keys to one using specific keys
198
250
/// This will panic if translatefpk returns an uncompressed key when
@@ -1225,6 +1277,7 @@ mod tests {
1225
1277
is_wildcard : true ,
1226
1278
} ) ;
1227
1279
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1280
+ assert_eq ! ( format!( "{}" , expected) , key) ;
1228
1281
1229
1282
// Without origin
1230
1283
let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1" ;
@@ -1235,6 +1288,7 @@ mod tests {
1235
1288
is_wildcard : false ,
1236
1289
} ) ;
1237
1290
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1291
+ assert_eq ! ( format!( "{}" , expected) , key) ;
1238
1292
1239
1293
// Without derivation path
1240
1294
let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL" ;
@@ -1245,6 +1299,7 @@ mod tests {
1245
1299
is_wildcard : false ,
1246
1300
} ) ;
1247
1301
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1302
+ assert_eq ! ( format!( "{}" , expected) , key) ;
1248
1303
1249
1304
// Raw (compressed) pubkey
1250
1305
let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" ;
@@ -1255,6 +1310,7 @@ mod tests {
1255
1310
. unwrap ( ) ,
1256
1311
) ;
1257
1312
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1313
+ assert_eq ! ( format!( "{}" , expected) , key) ;
1258
1314
1259
1315
// Raw (uncompressed) pubkey
1260
1316
let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a" ;
@@ -1265,6 +1321,7 @@ mod tests {
1265
1321
. unwrap ( ) ,
1266
1322
) ;
1267
1323
assert_eq ! ( expected, key. parse( ) . unwrap( ) ) ;
1324
+ assert_eq ! ( format!( "{}" , expected) , key) ;
1268
1325
}
1269
1326
1270
1327
#[ test]
0 commit comments