@@ -22,8 +22,14 @@ use bitcoin::hashes::hex::FromHex;
22
22
use bitcoin:: hashes:: { hash160, ripemd160, sha256, sha256d} ;
23
23
#[ cfg( feature = "compiler" ) ]
24
24
use {
25
- crate :: descriptor:: TapTree , crate :: miniscript:: ScriptContext , crate :: policy:: compiler,
26
- crate :: policy:: compiler:: CompilerError , crate :: Descriptor , crate :: Miniscript , crate :: Tap ,
25
+ crate :: descriptor:: TapTree ,
26
+ crate :: miniscript:: ScriptContext ,
27
+ crate :: policy:: compiler:: CompilerError ,
28
+ crate :: policy:: { compiler, Concrete , Liftable , Semantic } ,
29
+ crate :: Descriptor ,
30
+ crate :: Miniscript ,
31
+ crate :: Tap ,
32
+ std:: collections:: HashMap ,
27
33
std:: sync:: Arc ,
28
34
} ;
29
35
@@ -127,18 +133,101 @@ impl fmt::Display for PolicyError {
127
133
}
128
134
129
135
impl < Pk : MiniscriptKey > Policy < Pk > {
136
+ /// Flatten the [`Policy`] tree structure into a Vector of tuple `(leaf script, leaf probability)`
137
+ /// with leaf probabilities corresponding to odds for sub-branch in the policy.
138
+ /// We calculate the probability of selecting the sub-branch at every level and calculate the
139
+ /// leaf probabilities as the probability of traversing through required branches to reach the
140
+ /// leaf node, i.e. multiplication of the respective probabilities.
141
+ ///
142
+ /// For example, the policy tree: OR
143
+ /// / \
144
+ /// 2 1 odds
145
+ /// / \
146
+ /// A OR
147
+ /// / \
148
+ /// 3 1 odds
149
+ /// / \
150
+ /// B C
151
+ ///
152
+ /// gives the vector [(2/3, A), (1/3 * 3/4, B), (1/3 * 1/4, C)].
153
+ #[ cfg( feature = "compiler" ) ]
154
+ fn to_tapleaf_prob_vec ( & self , prob : f64 ) -> Vec < ( f64 , Policy < Pk > ) > {
155
+ match * self {
156
+ Policy :: Or ( ref subs) => {
157
+ let total_odds: usize = subs. iter ( ) . map ( |( ref k, _) | k) . sum ( ) ;
158
+ subs. iter ( )
159
+ . map ( |( k, ref policy) | {
160
+ policy. to_tapleaf_prob_vec ( prob * * k as f64 / total_odds as f64 )
161
+ } )
162
+ . flatten ( )
163
+ . collect :: < Vec < _ > > ( )
164
+ }
165
+ Policy :: Threshold ( k, ref subs) if k == 1 => {
166
+ let total_odds = subs. len ( ) ;
167
+ subs. iter ( )
168
+ . map ( |policy| policy. to_tapleaf_prob_vec ( prob / total_odds as f64 ) )
169
+ . flatten ( )
170
+ . collect :: < Vec < _ > > ( )
171
+ }
172
+ ref x => vec ! [ ( prob, x. clone( ) ) ] ,
173
+ }
174
+ }
175
+
130
176
/// Single-Node compilation
131
177
#[ cfg( feature = "compiler" ) ]
132
178
fn compile_leaf_taptree ( & self ) -> Result < TapTree < Pk > , Error > {
133
179
let compilation = self . compile :: < Tap > ( ) . unwrap ( ) ;
134
180
Ok ( TapTree :: Leaf ( Arc :: new ( compilation) ) )
135
181
}
136
182
137
- /// Compile a [`Policy`] into a single-leaf [`TapTree`]
183
+ /// Extract the Taproot internal_key from policy tree.
184
+ #[ cfg( feature = "compiler" ) ]
185
+ fn extract_key ( self , unspendable_key : Option < Pk > ) -> Result < ( Pk , Policy < Pk > ) , Error > {
186
+ let mut internal_key: Option < Pk > = None ;
187
+ {
188
+ let mut prob = 0. ;
189
+ let semantic_policy = self . lift ( ) ?;
190
+ let concrete_keys = self . keys ( ) ;
191
+ let key_prob_map: HashMap < _ , _ > = self
192
+ . to_tapleaf_prob_vec ( 1.0 )
193
+ . into_iter ( )
194
+ . filter ( |( _, ref pol) | match * pol {
195
+ Concrete :: Key ( ..) => true ,
196
+ _ => false ,
197
+ } )
198
+ . map ( |( prob, key) | ( key, prob) )
199
+ . collect ( ) ;
200
+
201
+ for key in concrete_keys. into_iter ( ) {
202
+ if semantic_policy
203
+ . clone ( )
204
+ . satisfy_constraint ( & Semantic :: KeyHash ( key. to_pubkeyhash ( ) ) , true )
205
+ == Semantic :: Trivial
206
+ {
207
+ match key_prob_map. get ( & Concrete :: Key ( key. clone ( ) ) ) {
208
+ Some ( val) => {
209
+ if * val > prob {
210
+ prob = * val;
211
+ internal_key = Some ( key. clone ( ) ) ;
212
+ }
213
+ }
214
+ None => return Err ( errstr ( "Key should have existed in the HashMap!" ) ) ,
215
+ }
216
+ }
217
+ }
218
+ }
219
+ match ( internal_key, unspendable_key) {
220
+ ( Some ( ref key) , _) => Ok ( ( key. clone ( ) , self . translate_unsatisfiable_pk ( & key) ) ) ,
221
+ ( _, Some ( key) ) => Ok ( ( key, self ) ) ,
222
+ _ => Err ( errstr ( "No viable internal key found." ) ) ,
223
+ }
224
+ }
225
+
226
+ /// Compile the [`Tr`] descriptor into optimized [`TapTree`] implementation
138
227
#[ cfg( feature = "compiler" ) ]
139
228
pub fn compile_tr ( & self , unspendable_key : Option < Pk > ) -> Result < Descriptor < Pk > , Error > {
140
- let internal_key = unspendable_key . ok_or ( errstr ( "No internal key found" ) ) ?;
141
- let tree = Descriptor :: new_tr ( internal_key, Some ( self . compile_leaf_taptree ( ) ?) ) ?;
229
+ let ( internal_key, policy ) = self . clone ( ) . extract_key ( unspendable_key ) ?;
230
+ let tree = Descriptor :: new_tr ( internal_key, Some ( policy . compile_leaf_taptree ( ) ?) ) ?;
142
231
Ok ( tree)
143
232
}
144
233
@@ -240,6 +329,30 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
240
329
}
241
330
}
242
331
332
+ /// Translate `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting TapKey
333
+ pub fn translate_unsatisfiable_pk ( self , key : & Pk ) -> Policy < Pk > {
334
+ match self {
335
+ Policy :: Key ( ref k) if k. clone ( ) == * key => Policy :: Unsatisfiable ,
336
+ Policy :: And ( subs) => Policy :: And (
337
+ subs. into_iter ( )
338
+ . map ( |sub| sub. translate_unsatisfiable_pk ( key) )
339
+ . collect :: < Vec < _ > > ( ) ,
340
+ ) ,
341
+ Policy :: Or ( subs) => Policy :: Or (
342
+ subs. into_iter ( )
343
+ . map ( |( k, sub) | ( k, sub. translate_unsatisfiable_pk ( key) ) )
344
+ . collect :: < Vec < _ > > ( ) ,
345
+ ) ,
346
+ Policy :: Threshold ( k, subs) => Policy :: Threshold (
347
+ k,
348
+ subs. into_iter ( )
349
+ . map ( |sub| sub. translate_unsatisfiable_pk ( key) )
350
+ . collect :: < Vec < _ > > ( ) ,
351
+ ) ,
352
+ x => x,
353
+ }
354
+ }
355
+
243
356
/// Get all keys in the policy
244
357
pub fn keys ( & self ) -> Vec < & Pk > {
245
358
match * self {
0 commit comments