@@ -22,8 +22,14 @@ use bitcoin::hashes::hex::FromHex;
2222use bitcoin:: hashes:: { hash160, ripemd160, sha256, sha256d} ;
2323#[ cfg( feature = "compiler" ) ]
2424use {
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 ,
2733 std:: sync:: Arc ,
2834} ;
2935
@@ -127,18 +133,101 @@ impl fmt::Display for PolicyError {
127133}
128134
129135impl < 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+
130176 /// Single-Node compilation
131177 #[ cfg( feature = "compiler" ) ]
132178 fn compile_leaf_taptree ( & self ) -> Result < TapTree < Pk > , Error > {
133179 let compilation = self . compile :: < Tap > ( ) . unwrap ( ) ;
134180 Ok ( TapTree :: Leaf ( Arc :: new ( compilation) ) )
135181 }
136182
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
138227 #[ cfg( feature = "compiler" ) ]
139228 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 ( ) ?) ) ?;
142231 Ok ( tree)
143232 }
144233
@@ -240,6 +329,30 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
240329 }
241330 }
242331
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+
243356 /// Get all keys in the policy
244357 pub fn keys ( & self ) -> Vec < & Pk > {
245358 match * self {
0 commit comments