Skip to content

Commit bac2f77

Browse files
committed
Add tr() descriptors to the descriptor!() macro
1 parent 73c101f commit bac2f77

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

Diff for: src/descriptor/dsl.rs

+97
Original file line numberDiff line numberDiff line change
@@ -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]
78110
macro_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]
233321
macro_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

Comments
 (0)