@@ -73,6 +73,38 @@ macro_rules! impl_top_level_pk {
7373 } } ;
7474}
7575
76+ #[ doc( hidden) ]
77+ #[ macro_export]
78+ macro_rules! impl_top_level_tr {
79+ ( $internal_key: expr, $tap_tree: expr ) => { {
80+ use $crate:: miniscript:: descriptor:: { Descriptor , DescriptorPublicKey , Tr } ;
81+ use $crate:: miniscript:: Tap ;
82+
83+ #[ allow( unused_imports) ]
84+ use $crate:: keys:: { DescriptorKey , IntoDescriptorKey } ;
85+ let secp = $crate:: bitcoin:: secp256k1:: Secp256k1 :: new( ) ;
86+
87+ $internal_key
88+ . into_descriptor_key( )
89+ . and_then( |key: DescriptorKey <Tap >| key. extract( & secp) )
90+ . map_err( $crate:: descriptor:: DescriptorError :: Key )
91+ . and_then( |( pk, mut key_map, mut valid_networks) | {
92+ let tap_tree = $tap_tree. map( |( tap_tree, tree_keymap, tree_networks) | {
93+ key_map. extend( tree_keymap. into_iter( ) ) ;
94+ valid_networks = $crate:: keys:: merge_networks( & valid_networks, & tree_networks) ;
95+
96+ tap_tree
97+ } ) ;
98+
99+ Ok ( (
100+ Descriptor :: <DescriptorPublicKey >:: Tr ( Tr :: new( pk, tap_tree) ?) ,
101+ key_map,
102+ valid_networks,
103+ ) )
104+ } )
105+ } } ;
106+ }
107+
76108#[ doc( hidden) ]
77109#[ macro_export]
78110macro_rules! impl_leaf_opcode {
@@ -228,6 +260,62 @@ macro_rules! impl_sortedmulti {
228260
229261}
230262
263+ #[ doc( hidden) ]
264+ #[ macro_export]
265+ macro_rules! parse_tap_tree {
266+ ( @merge $tree_a: expr, $tree_b: expr) => { {
267+ use std:: sync:: Arc ;
268+ use $crate:: miniscript:: descriptor:: TapTree ;
269+
270+ $tree_a
271+ . and_then( |tree_a| Ok ( ( tree_a, $tree_b?) ) )
272+ . and_then( |( ( a_tree, mut a_keymap, a_networks) , ( b_tree, b_keymap, b_networks) ) | {
273+ a_keymap. extend( b_keymap. into_iter( ) ) ;
274+ Ok ( ( TapTree :: Tree ( Arc :: new( a_tree) , Arc :: new( b_tree) ) , a_keymap, $crate:: keys:: merge_networks( & a_networks, & b_networks) ) )
275+ } )
276+
277+ } } ;
278+
279+ // Two sub-trees
280+ ( { { $( $tree_a: tt ) * } , { $( $tree_b: tt ) * } } ) => { {
281+ let tree_a = $crate:: parse_tap_tree!( { $( $tree_a ) * } ) ;
282+ let tree_b = $crate:: parse_tap_tree!( { $( $tree_b ) * } ) ;
283+
284+ $crate:: parse_tap_tree!( @merge tree_a, tree_b)
285+ } } ;
286+
287+ // One leaf and a sub-tree
288+ ( { $op_a: ident ( $( $minisc_a: tt ) * ) , { $( $tree_b: tt ) * } } ) => { {
289+ let tree_a = $crate:: parse_tap_tree!( $op_a ( $( $minisc_a ) * ) ) ;
290+ let tree_b = $crate:: parse_tap_tree!( { $( $tree_b ) * } ) ;
291+
292+ $crate:: parse_tap_tree!( @merge tree_a, tree_b)
293+ } } ;
294+ ( { { $( $tree_a: tt ) * } , $op_b: ident ( $( $minisc_b: tt ) * ) } ) => { {
295+ let tree_a = $crate:: parse_tap_tree!( { $( $tree_a ) * } ) ;
296+ let tree_b = $crate:: parse_tap_tree!( $op_b ( $( $minisc_b ) * ) ) ;
297+
298+ $crate:: parse_tap_tree!( @merge tree_a, tree_b)
299+ } } ;
300+
301+ // Two leaves
302+ ( { $op_a: ident ( $( $minisc_a: tt ) * ) , $op_b: ident ( $( $minisc_b: tt ) * ) } ) => { {
303+ let tree_a = $crate:: parse_tap_tree!( $op_a ( $( $minisc_a ) * ) ) ;
304+ let tree_b = $crate:: parse_tap_tree!( $op_b ( $( $minisc_b ) * ) ) ;
305+
306+ $crate:: parse_tap_tree!( @merge tree_a, tree_b)
307+ } } ;
308+
309+ // Single leaf
310+ ( $op: ident ( $( $minisc: tt ) * ) ) => { {
311+ use std:: sync:: Arc ;
312+ use $crate:: miniscript:: descriptor:: TapTree ;
313+
314+ $crate:: fragment!( $op ( $( $minisc ) * ) )
315+ . map( |( a_minisc, a_keymap, a_networks) | ( TapTree :: Leaf ( Arc :: new( a_minisc) ) , a_keymap, a_networks) )
316+ } } ;
317+ }
318+
231319#[ doc( hidden) ]
232320#[ macro_export]
233321macro_rules! apply_modifier {
@@ -441,6 +529,15 @@ macro_rules! descriptor {
441529 ( wsh ( $( $minisc: tt ) * ) ) => ( {
442530 $crate:: impl_top_level_sh!( Wsh , new, new_sortedmulti, Segwitv0 , $( $minisc ) * )
443531 } ) ;
532+
533+ ( tr ( $internal_key: expr ) ) => ( {
534+ $crate:: impl_top_level_tr!( $internal_key, None )
535+ } ) ;
536+ ( tr ( $internal_key: expr, $( $taptree: tt ) * ) ) => ( {
537+ let tap_tree = $crate:: parse_tap_tree!( $( $taptree ) * ) ;
538+ tap_tree
539+ . and_then( |tap_tree| $crate:: impl_top_level_tr!( $internal_key, Some ( tap_tree) ) )
540+ } ) ;
444541}
445542
446543#[ doc( hidden) ]
0 commit comments