@@ -27,8 +27,14 @@ use miniscript::limits::{HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_TYPE_FLAG};
27
27
use miniscript:: types:: extra_props:: TimeLockInfo ;
28
28
#[ cfg( feature = "compiler" ) ]
29
29
use {
30
- descriptor:: TapTree , miniscript:: ScriptContext , policy:: compiler,
31
- policy:: compiler:: CompilerError , std:: sync:: Arc , Descriptor , Miniscript , Tap ,
30
+ descriptor:: TapTree ,
31
+ miniscript:: ScriptContext ,
32
+ policy:: compiler:: CompilerError ,
33
+ policy:: Concrete ,
34
+ policy:: { compiler, Liftable , Semantic } ,
35
+ std:: collections:: HashMap ,
36
+ std:: sync:: Arc ,
37
+ Descriptor , Miniscript , Tap ,
32
38
} ;
33
39
use { Error , ForEach , ForEachKey , MiniscriptKey } ;
34
40
@@ -126,7 +132,30 @@ impl fmt::Display for PolicyError {
126
132
}
127
133
128
134
impl < Pk : MiniscriptKey > Policy < Pk > {
129
- /// Single-Node compilation
135
+ /// Flatten the [`Policy`] tree structure into a Vector with corresponding leaf probability
136
+ #[ cfg( feature = "compiler" ) ]
137
+ fn to_tapleaf_prob_vec ( & self , prob : f64 ) -> Vec < ( f64 , Policy < Pk > ) > {
138
+ match * self {
139
+ Policy :: Or ( ref subs) => {
140
+ let total_odds: usize = subs. iter ( ) . map ( |( ref k, _) | k) . sum ( ) ;
141
+ subs. iter ( )
142
+ . map ( |( k, ref policy) | {
143
+ policy. to_tapleaf_prob_vec ( prob * * k as f64 / total_odds as f64 )
144
+ } )
145
+ . flatten ( )
146
+ . collect :: < Vec < _ > > ( )
147
+ }
148
+ Policy :: Threshold ( k, ref subs) if k == 1 => {
149
+ let total_odds = subs. len ( ) ;
150
+ subs. iter ( )
151
+ . map ( |policy| policy. to_tapleaf_prob_vec ( prob / total_odds as f64 ) )
152
+ . flatten ( )
153
+ . collect :: < Vec < _ > > ( )
154
+ }
155
+ ref x => vec ! [ ( prob, x. clone( ) ) ] ,
156
+ }
157
+ }
158
+
130
159
#[ cfg( feature = "compiler" ) ]
131
160
fn compile_leaf_taptree ( & self ) -> Result < TapTree < Pk > , Error > {
132
161
let compilation = self . compile :: < Tap > ( ) . unwrap ( ) ;
@@ -135,17 +164,51 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
135
164
136
165
/// Extract the Taproot internal_key from policy tree.
137
166
#[ cfg( feature = "compiler" ) ]
138
- fn extract_key ( & self , unspendable_key : Option < Pk > ) -> Result < ( Pk , & Policy < Pk > ) , Error > {
139
- match unspendable_key {
140
- Some ( key) => Ok ( ( key, self ) ) ,
141
- None => Err ( errstr ( "No internal key found" ) ) ,
167
+ fn extract_key ( self , unspendable_key : Option < Pk > ) -> Result < ( Pk , Policy < Pk > ) , Error > {
168
+ let mut internal_key: Option < Pk > = None ;
169
+ {
170
+ let mut prob = 0. ;
171
+ let semantic_policy = self . lift ( ) ?;
172
+ let concrete_keys = self . keys ( ) ;
173
+ let key_prob_map: HashMap < _ , _ > = self
174
+ . to_tapleaf_prob_vec ( 1.0 )
175
+ . into_iter ( )
176
+ . filter ( |( _, ref pol) | match * pol {
177
+ Concrete :: Key ( ..) => true ,
178
+ _ => false ,
179
+ } )
180
+ . map ( |( prob, key) | ( key, prob) )
181
+ . collect ( ) ;
182
+
183
+ for key in concrete_keys. into_iter ( ) {
184
+ if semantic_policy
185
+ . clone ( )
186
+ . satisfy_constraint ( & Semantic :: KeyHash ( key. to_pubkeyhash ( ) ) , true )
187
+ == Semantic :: Trivial
188
+ {
189
+ match key_prob_map. get ( & Concrete :: Key ( key. clone ( ) ) ) {
190
+ Some ( val) => {
191
+ if * val > prob {
192
+ prob = * val;
193
+ internal_key = Some ( key. clone ( ) ) ;
194
+ }
195
+ }
196
+ None => return Err ( errstr ( "Key should have existed in the HashMap!" ) ) ,
197
+ }
198
+ }
199
+ }
200
+ }
201
+ match ( internal_key, unspendable_key) {
202
+ ( Some ( ref key) , _) => Ok ( ( key. clone ( ) , self . translate_unsatisfiable_pk ( & key) ) ) ,
203
+ ( _, Some ( key) ) => Ok ( ( key, self ) ) ,
204
+ _ => Err ( errstr ( "No viable internal key found." ) ) ,
142
205
}
143
206
}
144
207
145
208
/// Compile the [`Tr`] descriptor into optimized [`TapTree`] implementation
146
209
#[ cfg( feature = "compiler" ) ]
147
210
pub fn compile_tr ( & self , unspendable_key : Option < Pk > ) -> Result < Descriptor < Pk > , Error > {
148
- let ( internal_key, policy) = self . extract_key ( unspendable_key) ?;
211
+ let ( internal_key, policy) = self . clone ( ) . extract_key ( unspendable_key) ?;
149
212
let tree = Descriptor :: new_tr ( internal_key, Some ( policy. compile_leaf_taptree ( ) ?) ) ?;
150
213
Ok ( tree)
151
214
}
@@ -250,6 +313,30 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
250
313
}
251
314
}
252
315
316
+ /// Translate `Semantic::Key(key)` to `Semantic::Unsatisfiable` when extracting TapKey
317
+ pub fn translate_unsatisfiable_pk ( self , key : & Pk ) -> Policy < Pk > {
318
+ match self {
319
+ Policy :: Key ( ref k) if k. clone ( ) == * key => Policy :: Unsatisfiable ,
320
+ Policy :: And ( subs) => Policy :: And (
321
+ subs. into_iter ( )
322
+ . map ( |sub| sub. translate_unsatisfiable_pk ( key) )
323
+ . collect :: < Vec < _ > > ( ) ,
324
+ ) ,
325
+ Policy :: Or ( subs) => Policy :: Or (
326
+ subs. into_iter ( )
327
+ . map ( |( k, sub) | ( k, sub. translate_unsatisfiable_pk ( key) ) )
328
+ . collect :: < Vec < _ > > ( ) ,
329
+ ) ,
330
+ Policy :: Threshold ( k, subs) => Policy :: Threshold (
331
+ k,
332
+ subs. into_iter ( )
333
+ . map ( |sub| sub. translate_unsatisfiable_pk ( key) )
334
+ . collect :: < Vec < _ > > ( ) ,
335
+ ) ,
336
+ x => x,
337
+ }
338
+ }
339
+
253
340
/// Get all keys in the policy
254
341
pub fn keys ( & self ) -> Vec < & Pk > {
255
342
match * self {
0 commit comments