@@ -215,23 +215,32 @@ impl<'a> miniscript::Translator<String, bitcoin::PublicKey, Error>
215
215
216
216
/// See `ParsedPolicy`.
217
217
#[ derive( Debug ) ]
218
- pub struct Wsh {
219
- miniscript_expr : miniscript:: Miniscript < String , miniscript:: Segwitv0 > ,
218
+ pub struct Wsh < T : miniscript:: MiniscriptKey > {
219
+ miniscript_expr : miniscript:: Miniscript < T , miniscript:: Segwitv0 > ,
220
+ }
221
+
222
+ impl Wsh < bitcoin:: PublicKey > {
223
+ /// Return the witness script of this concrete wsh() descriptor.
224
+ pub fn witness_script ( & self ) -> Vec < u8 > {
225
+ self . miniscript_expr . encode ( ) . as_bytes ( ) . to_vec ( )
226
+ }
220
227
}
221
228
222
229
/// See `ParsedPolicy`.
223
230
#[ derive( Debug ) ]
224
- pub enum Descriptor {
231
+ pub enum Descriptor < T : miniscript :: MiniscriptKey > {
225
232
// `wsh(...)` policies
226
- Wsh ( Wsh ) ,
233
+ Wsh ( Wsh < T > ) ,
227
234
// `tr(...)` Taproot etc. in the future.
228
235
}
229
236
230
237
/// Result of `parse()`.
231
238
#[ derive( Debug ) ]
232
239
pub struct ParsedPolicy < ' a > {
233
240
policy : & ' a Policy ,
234
- pub descriptor : Descriptor ,
241
+ // String for pubkeys so we can parse and process the placeholder wallet policy keys like
242
+ // `@0/**` etc.
243
+ pub descriptor : Descriptor < String > ,
235
244
}
236
245
237
246
impl < ' a > ParsedPolicy < ' a > {
@@ -294,43 +303,52 @@ impl<'a> ParsedPolicy<'a> {
294
303
Ok ( ( ) )
295
304
}
296
305
297
- /// Derive the witness script of the policy derived at a receive or change path.
298
- /// If is_change is false, the witness script for the receive address is derived.
299
- /// If is_change is true, the witness script for the change address is derived.
306
+ /// Derive the descriptor of the policy at a receive or change path.
307
+ /// This turns key placeholders into actual pubkeys.
308
+ /// If is_change is false, the descriptor for the receive address is derived.
309
+ /// If is_change is true, the descriptor for the change address is derived.
300
310
/// Example: wsh(and_v(v:pk(@0/**),pk(@1/<20;21>/*))) derived using `is_change=false, address_index=5` derives
301
311
/// wsh(and_v(v:pk(@0/0/5),pk(@1/20/5))).
302
312
/// The same derived using `is_change=true` derives: wsh(and_v(v:pk(@0/1/5),pk(@1/21/5)))
303
- pub fn witness_script ( & self , is_change : bool , address_index : u32 ) -> Result < Vec < u8 > , Error > {
313
+ pub fn derive (
314
+ & self ,
315
+ is_change : bool ,
316
+ address_index : u32 ,
317
+ ) -> Result < Descriptor < bitcoin:: PublicKey > , Error > {
318
+ let mut translator = WalletPolicyPkTranslator {
319
+ keys : self . policy . keys . as_ref ( ) ,
320
+ is_change,
321
+ address_index,
322
+ } ;
304
323
match & self . descriptor {
305
324
Descriptor :: Wsh ( Wsh { miniscript_expr } ) => {
306
- let mut translator = WalletPolicyPkTranslator {
307
- keys : self . policy . keys . as_ref ( ) ,
308
- is_change,
309
- address_index,
310
- } ;
311
325
let miniscript_expr = match miniscript_expr. translate_pk ( & mut translator) {
312
326
Ok ( m) => m,
313
327
Err ( miniscript:: TranslateErr :: TranslatorErr ( e) ) => return Err ( e) ,
314
328
Err ( miniscript:: TranslateErr :: OuterError ( _) ) => return Err ( Error :: Generic ) ,
315
329
} ;
316
- Ok ( miniscript_expr . encode ( ) . as_bytes ( ) . to_vec ( ) )
330
+ Ok ( Descriptor :: Wsh ( Wsh { miniscript_expr } ) )
317
331
}
318
332
}
319
333
}
320
334
321
- /// Derive the witness script of the policy derived at the given full keypath.
335
+ /// Derive the descriptor of the policy derived at the given full keypath.
336
+ /// This turns key placeholders into actual pubkeys.
322
337
/// Example: wsh(and_v(v:pk(@0/<10;11>/*),pk(@1/<20;21>/*))) with our key [fp/48'/1'/0'/3']xpub...]
323
338
/// derived using keypath m/48'/1'/0'/3'/11/5 derives:
324
339
/// wsh(and_v(v:pk(@0/11/5),pk(@1/21/5))).
325
- pub fn witness_script_at_keypath ( & self , keypath : & [ u32 ] ) -> Result < Vec < u8 > , Error > {
340
+ pub fn derive_at_keypath (
341
+ & self ,
342
+ keypath : & [ u32 ] ,
343
+ ) -> Result < Descriptor < bitcoin:: PublicKey > , Error > {
326
344
match & self . descriptor {
327
345
Descriptor :: Wsh ( Wsh { miniscript_expr } ) => {
328
346
let ( is_change, address_index) = get_change_and_address_index (
329
347
miniscript_expr. iter_pk ( ) ,
330
348
& self . policy . keys ,
331
349
keypath,
332
350
) ?;
333
- self . witness_script ( is_change, address_index)
351
+ self . derive ( is_change, address_index)
334
352
}
335
353
}
336
354
}
@@ -899,7 +917,7 @@ mod tests {
899
917
}
900
918
901
919
#[ test]
902
- fn test_witness_script ( ) {
920
+ fn test_wsh_witness_script ( ) {
903
921
mock_unlocked_using_mnemonic (
904
922
"sudden tenant fault inject concert weather maid people chunk youth stumble grit" ,
905
923
"" ,
@@ -913,20 +931,22 @@ mod tests {
913
931
let address_index = 5 ;
914
932
915
933
let witness_script = |pol : & str , keys : & [ pb:: KeyOriginInfo ] , is_change : bool | {
916
- hex:: encode (
917
- parse ( & make_policy ( pol, keys) )
918
- . unwrap ( )
919
- . witness_script ( is_change, address_index)
920
- . unwrap ( ) ,
921
- )
934
+ let derived = parse ( & make_policy ( pol, keys) )
935
+ . unwrap ( )
936
+ . derive ( is_change, address_index)
937
+ . unwrap ( ) ;
938
+ match derived {
939
+ Descriptor :: Wsh ( wsh) => hex:: encode ( wsh. witness_script ( ) ) ,
940
+ }
922
941
} ;
923
942
let witness_script_at_keypath = |pol : & str , keys : & [ pb:: KeyOriginInfo ] , keypath : & [ u32 ] | {
924
- hex:: encode (
925
- parse ( & make_policy ( pol, keys) )
926
- . unwrap ( )
927
- . witness_script_at_keypath ( keypath)
928
- . unwrap ( ) ,
929
- )
943
+ let derived = parse ( & make_policy ( pol, keys) )
944
+ . unwrap ( )
945
+ . derive_at_keypath ( keypath)
946
+ . unwrap ( ) ;
947
+ match derived {
948
+ Descriptor :: Wsh ( wsh) => hex:: encode ( wsh. witness_script ( ) ) ,
949
+ }
930
950
} ;
931
951
932
952
// pk(key) => <key> OP_CHECKSIG
0 commit comments