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