}};
}
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_top_level_tr {
+ ( $internal_key:expr, $tap_tree:expr ) => {{
+ use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, Tr};
+ use $crate::miniscript::Tap;
+
+ #[allow(unused_imports)]
+ use $crate::keys::{DescriptorKey, IntoDescriptorKey};
+ let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+ $internal_key
+ .into_descriptor_key()
+ .and_then(|key: DescriptorKey<Tap>| key.extract(&secp))
+ .map_err($crate::descriptor::DescriptorError::Key)
+ .and_then(|(pk, mut key_map, mut valid_networks)| {
+ let tap_tree = $tap_tree.map(|(tap_tree, tree_keymap, tree_networks)| {
+ key_map.extend(tree_keymap.into_iter());
+ valid_networks = $crate::keys::merge_networks(&valid_networks, &tree_networks);
+
+ tap_tree
+ });
+
+ Ok((
+ Descriptor::<DescriptorPublicKey>::Tr(Tr::new(pk, tap_tree)?),
+ key_map,
+ valid_networks,
+ ))
+ })
+ }};
+}
+
#[doc(hidden)]
#[macro_export]
macro_rules! impl_leaf_opcode {
}
+#[doc(hidden)]
+#[macro_export]
+macro_rules! parse_tap_tree {
+ ( @merge $tree_a:expr, $tree_b:expr) => {{
+ use std::sync::Arc;
+ use $crate::miniscript::descriptor::TapTree;
+
+ $tree_a
+ .and_then(|tree_a| Ok((tree_a, $tree_b?)))
+ .and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| {
+ a_keymap.extend(b_keymap.into_iter());
+ Ok((TapTree::Tree(Arc::new(a_tree), Arc::new(b_tree)), a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
+ })
+
+ }};
+
+ // Two sub-trees
+ ( { { $( $tree_a:tt )* }, { $( $tree_b:tt )* } } ) => {{
+ let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
+ let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
+
+ $crate::parse_tap_tree!(@merge tree_a, tree_b)
+ }};
+
+ // One leaf and a sub-tree
+ ( { $op_a:ident ( $( $minisc_a:tt )* ), { $( $tree_b:tt )* } } ) => {{
+ let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
+ let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
+
+ $crate::parse_tap_tree!(@merge tree_a, tree_b)
+ }};
+ ( { { $( $tree_a:tt )* }, $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
+ let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
+ let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
+
+ $crate::parse_tap_tree!(@merge tree_a, tree_b)
+ }};
+
+ // Two leaves
+ ( { $op_a:ident ( $( $minisc_a:tt )* ), $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
+ let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
+ let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
+
+ $crate::parse_tap_tree!(@merge tree_a, tree_b)
+ }};
+
+ // Single leaf
+ ( $op:ident ( $( $minisc:tt )* ) ) => {{
+ use std::sync::Arc;
+ use $crate::miniscript::descriptor::TapTree;
+
+ $crate::fragment!( $op ( $( $minisc )* ) )
+ .map(|(a_minisc, a_keymap, a_networks)| (TapTree::Leaf(Arc::new(a_minisc)), a_keymap, a_networks))
+ }};
+}
+
#[doc(hidden)]
#[macro_export]
macro_rules! apply_modifier {
( wsh ( $( $minisc:tt )* ) ) => ({
$crate::impl_top_level_sh!(Wsh, new, new_sortedmulti, Segwitv0, $( $minisc )*)
});
+
+ ( tr ( $internal_key:expr ) ) => ({
+ $crate::impl_top_level_tr!($internal_key, None)
+ });
+ ( tr ( $internal_key:expr, $( $taptree:tt )* ) ) => ({
+ let tap_tree = $crate::parse_tap_tree!( $( $taptree )* );
+ tap_tree
+ .and_then(|tap_tree| $crate::impl_top_level_tr!($internal_key, Some(tap_tree)))
+ });
}
#[doc(hidden)]