1
1
use std:: convert:: { TryFrom , TryInto } ;
2
2
use std:: { fmt, sync:: Arc } ;
3
3
4
+ use bitcoin:: ScriptBuf ;
4
5
use miniscript:: descriptor:: { DescriptorType , ShInner , WshInner } ;
5
6
use miniscript:: { ScriptContext , Threshold } ;
6
7
7
8
use crate :: runtime:: scope:: { Mutable , ScopeRef } ;
8
9
use crate :: runtime:: { Array , Error , Evaluate , ExprRepr , FieldAccess , Result , Value } ;
9
10
use crate :: stdlib:: { btc:: WshScript , taproot:: tap_scripts_to_val} ;
10
- use crate :: util:: { DescriptorExt , DescriptorSecretKeyExt , MiniscriptExt } ;
11
+ use crate :: util:: { DeriveExt , DescriptorExt , DescriptorSecretKeyExt , MiniscriptExt } ;
11
12
use crate :: { ast, DescriptorDpk as Descriptor , MiniscriptDpk as Miniscript , PolicyDpk as Policy } ;
12
13
13
14
pub use crate :: runtime:: AndOr ;
@@ -245,7 +246,8 @@ pub mod fns {
245
246
}
246
247
}
247
248
248
- // Descriptor fields accessors
249
+ // Field accessors
250
+
249
251
impl FieldAccess for Descriptor {
250
252
fn get_field ( self , field : & Value ) -> Option < Value > {
251
253
Some ( match field. as_str ( ) ? {
@@ -258,8 +260,9 @@ impl FieldAccess for Descriptor {
258
260
"is_definite" => ( !self . has_wildcard ( ) && !self . is_multipath ( ) ) . into ( ) ,
259
261
260
262
// Only available for definite descriptors (non-multi-path and no underived wildcards)
261
- "script_pubkey" | "scriptPubKey" => self . to_script_pubkey ( ) . ok ( ) ?. into ( ) ,
262
- "explicit_script" | "explicitScript" => self . to_explicit_script ( ) . ok ( ) ?. into ( ) ,
263
+ "script_pubkey" => self . to_script_pubkey ( ) . ok ( ) ?. into ( ) ,
264
+ // Only available for definite non-taproot descriptors
265
+ "explicit_script" => self . to_explicit_script ( ) . ok ( ) ?. into ( ) ,
263
266
// Only available for definite segwit descriptors
264
267
"witness_program" => self . witness_program ( ) . ok ( ) ??. into ( ) ,
265
268
@@ -278,6 +281,30 @@ impl FieldAccess for Descriptor {
278
281
}
279
282
}
280
283
284
+ impl FieldAccess for Policy {
285
+ fn get_field ( self , field : & Value ) -> Option < Value > {
286
+ fn compile < Ctx : miniscript:: ScriptContext > ( policy : & Policy ) -> Result < ScriptBuf > {
287
+ Ok ( policy. compile :: < Ctx > ( ) ?. derive_keys ( ) ?. encode ( ) )
288
+ }
289
+ Some ( match field. as_str ( ) ? {
290
+ "keys" => self . keys ( ) . into_iter ( ) . cloned ( ) . collect ( ) ,
291
+ "is_valid" => self . is_valid ( ) . is_ok ( ) . into ( ) ,
292
+ "is_safe" => self . is_safe_nonmalleable ( ) . 0 . into ( ) ,
293
+ "is_nonmalleable" => self . is_safe_nonmalleable ( ) . 1 . into ( ) ,
294
+ "is_wildcard" => self . has_wildcards ( ) . into ( ) ,
295
+ "is_definite" => ( !self . has_wildcards ( ) ) . into ( ) ,
296
+
297
+ // Script compilation fields are only available for Policies that are `$p->is_valid && $p->is_safe && $p->is_nonmalleable && $p->is_definite`
298
+ // You can use the tapscript()/segwitv0() functions to get a more useful exception instead of a 'field not found'
299
+ "tapscript" => compile :: < miniscript:: Tap > ( & self ) . ok ( ) ?. into ( ) ,
300
+ "segwitv0" => compile :: < miniscript:: Segwitv0 > ( & self ) . ok ( ) ?. into ( ) ,
301
+ _ => {
302
+ return None ;
303
+ }
304
+ } )
305
+ }
306
+ }
307
+
281
308
fn into_policies ( values : Vec < Value > ) -> Result < Vec < Arc < Policy > > > {
282
309
values
283
310
. into_iter ( )
@@ -314,10 +341,7 @@ impl TryFrom<Value> for Policy {
314
341
// PubKeys are coerced into a pk() policy
315
342
Value :: PubKey ( pubkey) => Ok ( Policy :: Key ( pubkey) ) ,
316
343
// SecKeys are coerced into a PubKey, then to a pk()
317
- Value :: SecKey ( seckey) => {
318
- let pubkey = seckey. to_public_ ( ) ?;
319
- Ok ( Policy :: Key ( pubkey) )
320
- }
344
+ Value :: SecKey ( seckey) => Ok ( Policy :: Key ( seckey. to_public_ ( ) ?) ) ,
321
345
v => Err ( Error :: NotPolicyLike ( v. into ( ) ) ) ,
322
346
}
323
347
}
0 commit comments