bdk_wallet/descriptor/
dsl.rs

1// Bitcoin Dev Kit
2// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3//
4// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5//
6// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9// You may not use this file except in accordance with one or both of these
10// licenses.
11
12//! Descriptors DSL
13
14#[doc(hidden)]
15#[macro_export]
16macro_rules! impl_top_level_sh {
17    // disallow `sortedmulti` in `bare()`
18    ( Bare, new, new, Legacy, sortedmulti $( $inner:tt )* ) => {
19        compile_error!("`bare()` descriptors can't contain any `sortedmulti()` operands");
20    };
21    ( Bare, new, new, Legacy, sortedmulti_vec $( $inner:tt )* ) => {
22        compile_error!("`bare()` descriptors can't contain any `sortedmulti_vec()` operands");
23    };
24
25    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti $( $inner:tt )* ) => {{
26        use core::marker::PhantomData;
27
28        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
29        use $crate::miniscript::$ctx;
30
31        let build_desc = |k, pks| {
32            Ok((Descriptor::<DescriptorPublicKey>::$inner_struct($inner_struct::$sortedmulti_constructor(k, pks)?), PhantomData::<$ctx>))
33        };
34
35        $crate::impl_sortedmulti!(build_desc, sortedmulti $( $inner )*)
36    }};
37    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti_vec $( $inner:tt )* ) => {{
38        use core::marker::PhantomData;
39
40        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
41        use $crate::miniscript::$ctx;
42
43        let build_desc = |k, pks| {
44            Ok((Descriptor::<DescriptorPublicKey>::$inner_struct($inner_struct::$sortedmulti_constructor(k, pks)?), PhantomData::<$ctx>))
45        };
46
47        $crate::impl_sortedmulti!(build_desc, sortedmulti_vec $( $inner )*)
48    }};
49
50    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, $( $minisc:tt )* ) => {{
51        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
52
53        $crate::fragment!($( $minisc )*)
54            .and_then(|(minisc, keymap, networks)| Ok(($inner_struct::$constructor(minisc)?, keymap, networks)))
55            .and_then(|(inner, key_map, valid_networks)| Ok((Descriptor::<DescriptorPublicKey>::$inner_struct(inner), key_map, valid_networks)))
56    }};
57}
58
59#[doc(hidden)]
60#[macro_export]
61macro_rules! impl_top_level_pk {
62    ( $inner_type:ident, $ctx:ty, $key:expr ) => {{
63        use $crate::miniscript::descriptor::$inner_type;
64
65        #[allow(unused_imports)]
66        use $crate::keys::{DescriptorKey, IntoDescriptorKey};
67        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
68
69        $key.into_descriptor_key()
70            .and_then(|key: DescriptorKey<$ctx>| key.extract(&secp))
71            .map_err($crate::descriptor::DescriptorError::Key)
72            .map(|(pk, key_map, valid_networks)| ($inner_type::new(pk), key_map, valid_networks))
73    }};
74}
75
76#[doc(hidden)]
77#[macro_export]
78macro_rules! impl_top_level_tr {
79    ( $internal_key:expr, $tap_tree:expr ) => {{
80        use $crate::miniscript::descriptor::{
81            Descriptor, DescriptorPublicKey, KeyMap, TapTree, Tr,
82        };
83        use $crate::miniscript::Tap;
84
85        #[allow(unused_imports)]
86        use $crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
87
88        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
89
90        $internal_key
91            .into_descriptor_key()
92            .and_then(|key: DescriptorKey<Tap>| key.extract(&secp))
93            .map_err($crate::descriptor::DescriptorError::Key)
94            .and_then(|(pk, mut key_map, mut valid_networks)| {
95                let tap_tree = $tap_tree.map(
96                    |(tap_tree, tree_keymap, tree_networks): (
97                        TapTree<DescriptorPublicKey>,
98                        KeyMap,
99                        ValidNetworks,
100                    )| {
101                        key_map.extend(tree_keymap.into_iter());
102                        valid_networks =
103                            $crate::keys::merge_networks(&valid_networks, &tree_networks);
104
105                        tap_tree
106                    },
107                );
108
109                Ok((
110                    Descriptor::<DescriptorPublicKey>::Tr(Tr::new(pk, tap_tree)?),
111                    key_map,
112                    valid_networks,
113                ))
114            })
115    }};
116}
117
118#[doc(hidden)]
119#[macro_export]
120macro_rules! impl_leaf_opcode {
121    ( $terminal_variant:ident ) => {{
122        use $crate::descriptor::CheckMiniscript;
123
124        $crate::miniscript::Miniscript::from_ast(
125            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant,
126        )
127        .map_err($crate::descriptor::DescriptorError::Miniscript)
128        .and_then(|minisc| {
129            minisc.check_miniscript()?;
130            Ok(minisc)
131        })
132        .map(|minisc| {
133            (
134                minisc,
135                $crate::miniscript::descriptor::KeyMap::default(),
136                $crate::keys::any_network(),
137            )
138        })
139    }};
140}
141
142#[doc(hidden)]
143#[macro_export]
144macro_rules! impl_leaf_opcode_value {
145    ( $terminal_variant:ident, $value:expr ) => {{
146        use $crate::descriptor::CheckMiniscript;
147
148        $crate::miniscript::Miniscript::from_ast(
149            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($value),
150        )
151        .map_err($crate::descriptor::DescriptorError::Miniscript)
152        .and_then(|minisc| {
153            minisc.check_miniscript()?;
154            Ok(minisc)
155        })
156        .map(|minisc| {
157            (
158                minisc,
159                $crate::miniscript::descriptor::KeyMap::default(),
160                $crate::keys::any_network(),
161            )
162        })
163    }};
164}
165
166#[doc(hidden)]
167#[macro_export]
168macro_rules! impl_leaf_opcode_value_two {
169    ( $terminal_variant:ident, $one:expr, $two:expr ) => {{
170        use $crate::descriptor::CheckMiniscript;
171
172        $crate::miniscript::Miniscript::from_ast(
173            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($one, $two),
174        )
175        .map_err($crate::descriptor::DescriptorError::Miniscript)
176        .and_then(|minisc| {
177            minisc.check_miniscript()?;
178            Ok(minisc)
179        })
180        .map(|minisc| {
181            (
182                minisc,
183                $crate::miniscript::descriptor::KeyMap::default(),
184                $crate::keys::any_network(),
185            )
186        })
187    }};
188}
189
190#[doc(hidden)]
191#[macro_export]
192macro_rules! impl_node_opcode_two {
193    ( $terminal_variant:ident, $( $inner:tt )* ) => ({
194        use $crate::descriptor::CheckMiniscript;
195
196        let inner = $crate::fragment_internal!( @t $( $inner )* );
197        let (a, b) = $crate::descriptor::dsl::TupleTwo::from(inner).flattened();
198
199        a
200            .and_then(|a| Ok((a, b?)))
201            .and_then(|((a_minisc, mut a_keymap, a_networks), (b_minisc, b_keymap, b_networks))| {
202                // join key_maps
203                a_keymap.extend(b_keymap.into_iter());
204
205                let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
206                    $crate::alloc::sync::Arc::new(a_minisc),
207                    $crate::alloc::sync::Arc::new(b_minisc),
208                ))?;
209
210                minisc.check_miniscript()?;
211
212                Ok((minisc, a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
213            })
214    });
215}
216
217#[doc(hidden)]
218#[macro_export]
219macro_rules! impl_node_opcode_three {
220    ( $terminal_variant:ident, $( $inner:tt )* ) => ({
221        use $crate::descriptor::CheckMiniscript;
222
223        let inner = $crate::fragment_internal!( @t $( $inner )* );
224        let (a, b, c) = $crate::descriptor::dsl::TupleThree::from(inner).flattened();
225
226        a
227            .and_then(|a| Ok((a, b?, c?)))
228            .and_then(|((a_minisc, mut a_keymap, a_networks), (b_minisc, b_keymap, b_networks), (c_minisc, c_keymap, c_networks))| {
229                // join key_maps
230                a_keymap.extend(b_keymap.into_iter());
231                a_keymap.extend(c_keymap.into_iter());
232
233                let networks = $crate::keys::merge_networks(&a_networks, &b_networks);
234                let networks = $crate::keys::merge_networks(&networks, &c_networks);
235
236                let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
237                    $crate::alloc::sync::Arc::new(a_minisc),
238                    $crate::alloc::sync::Arc::new(b_minisc),
239                    $crate::alloc::sync::Arc::new(c_minisc),
240                ))?;
241
242                minisc.check_miniscript()?;
243
244                Ok((minisc, a_keymap, networks))
245            })
246    });
247}
248
249#[doc(hidden)]
250#[macro_export]
251macro_rules! impl_sortedmulti {
252    ( $build_desc:expr, sortedmulti_vec ( $thresh:expr, $keys:expr ) ) => ({
253        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
254        $crate::keys::make_sortedmulti($thresh, $keys, $build_desc, &secp)
255    });
256    ( $build_desc:expr, sortedmulti ( $thresh:expr $(, $key:expr )+ ) ) => ({
257        use $crate::keys::IntoDescriptorKey;
258        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
259
260        let keys = vec![
261            $(
262                $key.into_descriptor_key(),
263            )*
264        ];
265
266        keys.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
267            .map_err($crate::descriptor::DescriptorError::Key)
268            .and_then(|keys| $crate::keys::make_sortedmulti($thresh, keys, $build_desc, &secp))
269    });
270
271}
272
273#[doc(hidden)]
274#[macro_export]
275macro_rules! parse_tap_tree {
276    ( @merge $tree_a:expr, $tree_b:expr) => {{
277        use $crate::miniscript::descriptor::TapTree;
278
279        $tree_a
280            .and_then(|tree_a| Ok((tree_a, $tree_b?)))
281            .and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| {
282                a_keymap.extend(b_keymap.into_iter());
283                Ok((TapTree::combine(a_tree, b_tree), a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
284            })
285
286    }};
287
288    // Two sub-trees
289    ( { { $( $tree_a:tt )* }, { $( $tree_b:tt )* } } ) => {{
290        let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
291        let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
292
293        $crate::parse_tap_tree!(@merge tree_a, tree_b)
294    }};
295
296    // One leaf and a sub-tree
297    ( { $op_a:ident ( $( $minisc_a:tt )* ), { $( $tree_b:tt )* } } ) => {{
298        let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
299        let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
300
301        $crate::parse_tap_tree!(@merge tree_a, tree_b)
302    }};
303    ( { { $( $tree_a:tt )* }, $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
304        let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
305        let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
306
307        $crate::parse_tap_tree!(@merge tree_a, tree_b)
308    }};
309
310    // Two leaves
311    ( { $op_a:ident ( $( $minisc_a:tt )* ), $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
312        let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
313        let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
314
315        $crate::parse_tap_tree!(@merge tree_a, tree_b)
316    }};
317
318    // Single leaf
319    ( $op:ident ( $( $minisc:tt )* ) ) => {{
320        use $crate::alloc::sync::Arc;
321        use $crate::miniscript::descriptor::TapTree;
322
323        $crate::fragment!( $op ( $( $minisc )* ) )
324            .map(|(a_minisc, a_keymap, a_networks)| (TapTree::Leaf(Arc::new(a_minisc)), a_keymap, a_networks))
325    }};
326}
327
328#[doc(hidden)]
329#[macro_export]
330macro_rules! apply_modifier {
331    ( $terminal_variant:ident, $inner:expr ) => {{
332        use $crate::descriptor::CheckMiniscript;
333
334        $inner
335            .map_err(|e| -> $crate::descriptor::DescriptorError { e.into() })
336            .and_then(|(minisc, keymap, networks)| {
337                let minisc = $crate::miniscript::Miniscript::from_ast(
338                    $crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
339                        $crate::alloc::sync::Arc::new(minisc),
340                    ),
341                )?;
342
343                minisc.check_miniscript()?;
344
345                Ok((minisc, keymap, networks))
346            })
347    }};
348
349    ( a: $inner:expr ) => {{
350        $crate::apply_modifier!(Alt, $inner)
351    }};
352    ( s: $inner:expr ) => {{
353        $crate::apply_modifier!(Swap, $inner)
354    }};
355    ( c: $inner:expr ) => {{
356        $crate::apply_modifier!(Check, $inner)
357    }};
358    ( d: $inner:expr ) => {{
359        $crate::apply_modifier!(DupIf, $inner)
360    }};
361    ( v: $inner:expr ) => {{
362        $crate::apply_modifier!(Verify, $inner)
363    }};
364    ( j: $inner:expr ) => {{
365        $crate::apply_modifier!(NonZero, $inner)
366    }};
367    ( n: $inner:expr ) => {{
368        $crate::apply_modifier!(ZeroNotEqual, $inner)
369    }};
370
371    // Modifiers expanded to other operators
372    ( t: $inner:expr ) => {{
373        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
374            $crate::impl_leaf_opcode_value_two!(
375                AndV,
376                $crate::alloc::sync::Arc::new(a_minisc),
377                $crate::alloc::sync::Arc::new($crate::fragment!(true).unwrap().0)
378            )
379            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
380        })
381    }};
382    ( l: $inner:expr ) => {{
383        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
384            $crate::impl_leaf_opcode_value_two!(
385                OrI,
386                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0),
387                $crate::alloc::sync::Arc::new(a_minisc)
388            )
389            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
390        })
391    }};
392    ( u: $inner:expr ) => {{
393        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
394            $crate::impl_leaf_opcode_value_two!(
395                OrI,
396                $crate::alloc::sync::Arc::new(a_minisc),
397                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0)
398            )
399            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
400        })
401    }};
402}
403
404/// Macro to write full descriptors with code
405///
406/// This macro expands to a `Result` of
407/// [`DescriptorTemplateOut`](super::template::DescriptorTemplateOut) and
408/// [`DescriptorError`](crate::descriptor::DescriptorError)
409///
410/// The syntax is very similar to the normal descriptor syntax, with the exception that modifiers
411/// cannot be grouped together. For instance, a descriptor fragment like `sdv:older(144)` has to be
412/// broken up to `s:d:v:older(144)`.
413///
414/// The `pk()`, `pk_k()` and `pk_h()` operands can take as argument any type that implements
415/// [`IntoDescriptorKey`]. This means that keys can also be written inline as strings, but in that
416/// case they must be wrapped in quotes, which is another difference compared to the standard
417/// descriptor syntax.
418///
419/// [`IntoDescriptorKey`]: crate::keys::IntoDescriptorKey
420///
421/// ## Example
422///
423/// Signature plus timelock descriptor:
424///
425/// ```
426/// # use std::str::FromStr;
427/// let (my_descriptor, my_keys_map, networks) = bdk_wallet::descriptor!(sh(wsh(and_v(v:pk("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"),older(50)))))?;
428/// # Ok::<(), Box<dyn std::error::Error>>(())
429/// ```
430///
431/// -------
432///
433/// 2-of-3 that becomes a 1-of-3 after a timelock has expired. Both `descriptor_a` and
434/// `descriptor_b` are equivalent: the first syntax is more suitable for a fixed number of items
435/// known at compile time, while the other accepts a [`Vec`] of items, which makes it more suitable
436/// for writing dynamic descriptors.
437///
438/// They both produce the descriptor: `wsh(thresh(2,pk(...),s:pk(...),sndv:older(...)))`
439///
440/// ```
441/// # use std::str::FromStr;
442/// let my_key_1 = bitcoin::PublicKey::from_str(
443///     "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
444/// )?;
445/// let my_key_2 =
446///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
447/// let my_timelock = 50;
448///
449/// let (descriptor_a, key_map_a, networks) = bdk_wallet::descriptor! {
450///     wsh (
451///         thresh(2, pk(my_key_1), s:pk(my_key_2), s:n:d:v:older(my_timelock))
452///     )
453/// }?;
454///
455/// #[rustfmt::skip]
456/// let b_items = vec![
457///     bdk_wallet::fragment!(pk(my_key_1))?,
458///     bdk_wallet::fragment!(s:pk(my_key_2))?,
459///     bdk_wallet::fragment!(s:n:d:v:older(my_timelock))?,
460/// ];
461/// let (descriptor_b, mut key_map_b, networks) =
462///     bdk_wallet::descriptor!(wsh(thresh_vec(2, b_items)))?;
463///
464/// assert_eq!(descriptor_a, descriptor_b);
465/// assert_eq!(key_map_a.len(), key_map_b.len());
466/// # Ok::<(), Box<dyn std::error::Error>>(())
467/// ```
468///
469/// ------
470///
471/// Simple 2-of-2 multi-signature, equivalent to: `wsh(multi(2, ...))`
472///
473/// ```
474/// # use std::str::FromStr;
475/// let my_key_1 = bitcoin::PublicKey::from_str(
476///     "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
477/// )?;
478/// let my_key_2 =
479///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
480///
481/// let (descriptor, key_map, networks) = bdk_wallet::descriptor! {
482///     wsh (
483///         multi(2, my_key_1, my_key_2)
484///     )
485/// }?;
486/// # Ok::<(), Box<dyn std::error::Error>>(())
487/// ```
488///
489/// ------
490///
491/// Native-Segwit single-sig, equivalent to: `wpkh(...)`
492///
493/// ```
494/// let my_key =
495///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
496///
497/// let (descriptor, key_map, networks) = bdk_wallet::descriptor!(wpkh(my_key))?;
498/// # Ok::<(), Box<dyn std::error::Error>>(())
499/// ```
500///
501/// [`Vec`]: alloc::vec::Vec
502#[macro_export]
503macro_rules! descriptor {
504    ( bare ( $( $minisc:tt )* ) ) => ({
505        $crate::impl_top_level_sh!(Bare, new, new, Legacy, $( $minisc )*)
506    });
507    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => ({
508        $crate::descriptor!(shwsh ($( $minisc )*))
509    });
510    ( shwsh ( $( $minisc:tt )* ) ) => ({
511        $crate::impl_top_level_sh!(Sh, new_wsh, new_wsh_sortedmulti, Segwitv0, $( $minisc )*)
512    });
513    ( pk ( $key:expr ) ) => ({
514        // `pk()` is actually implemented as `bare(pk())`
515        $crate::descriptor!( bare ( pk ( $key ) ) )
516    });
517    ( pkh ( $key:expr ) ) => ({
518        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
519
520        $crate::impl_top_level_pk!(Pkh, $crate::miniscript::Legacy, $key)
521            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
522            .map(|(a, b, c)| (Descriptor::<DescriptorPublicKey>::Pkh(a), b, c))
523    });
524    ( wpkh ( $key:expr ) ) => ({
525        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
526
527        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
528            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
529            .map(|(a, b, c)| (Descriptor::<DescriptorPublicKey>::Wpkh(a), b, c))
530    });
531    ( sh ( wpkh ( $key:expr ) ) ) => ({
532        $crate::descriptor!(shwpkh ( $key ))
533    });
534    ( shwpkh ( $key:expr ) ) => ({
535        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, Sh};
536
537        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
538            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
539            .and_then(|(a, b, c)| Ok((Descriptor::<DescriptorPublicKey>::Sh(Sh::new_wpkh(a.into_inner())?), b, c)))
540    });
541    ( sh ( $( $minisc:tt )* ) ) => ({
542        $crate::impl_top_level_sh!(Sh, new, new_sortedmulti, Legacy, $( $minisc )*)
543    });
544    ( wsh ( $( $minisc:tt )* ) ) => ({
545        $crate::impl_top_level_sh!(Wsh, new, new_sortedmulti, Segwitv0, $( $minisc )*)
546    });
547
548    ( tr ( $internal_key:expr ) ) => ({
549        $crate::impl_top_level_tr!($internal_key, None)
550    });
551    ( tr ( $internal_key:expr, $( $taptree:tt )* ) ) => ({
552        let tap_tree = $crate::parse_tap_tree!( $( $taptree )* );
553        tap_tree
554            .and_then(|tap_tree| $crate::impl_top_level_tr!($internal_key, Some(tap_tree)))
555    });
556}
557
558#[doc(hidden)]
559pub struct TupleTwo<A, B> {
560    pub a: A,
561    pub b: B,
562}
563
564impl<A, B> TupleTwo<A, B> {
565    pub fn flattened(self) -> (A, B) {
566        (self.a, self.b)
567    }
568}
569
570impl<A, B> From<(A, (B, ()))> for TupleTwo<A, B> {
571    fn from((a, (b, _)): (A, (B, ()))) -> Self {
572        TupleTwo { a, b }
573    }
574}
575
576#[doc(hidden)]
577pub struct TupleThree<A, B, C> {
578    pub a: A,
579    pub b: B,
580    pub c: C,
581}
582
583impl<A, B, C> TupleThree<A, B, C> {
584    pub fn flattened(self) -> (A, B, C) {
585        (self.a, self.b, self.c)
586    }
587}
588
589impl<A, B, C> From<(A, (B, (C, ())))> for TupleThree<A, B, C> {
590    fn from((a, (b, (c, _))): (A, (B, (C, ())))) -> Self {
591        TupleThree { a, b, c }
592    }
593}
594
595#[doc(hidden)]
596#[macro_export]
597macro_rules! group_multi_keys {
598    ( $( $key:expr ),+ ) => {{
599        use $crate::keys::IntoDescriptorKey;
600
601        let keys = vec![
602            $(
603                $key.into_descriptor_key(),
604            )*
605        ];
606
607        keys.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
608            .map_err($crate::descriptor::DescriptorError::Key)
609    }};
610}
611
612#[doc(hidden)]
613#[macro_export]
614macro_rules! fragment_internal {
615    // The @v prefix is used to parse a sequence of operands and return them in a vector. This is
616    // used by operands that take a variable number of arguments, like `thresh()` and `multi()`.
617    ( @v $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
618        let mut v = vec![$crate::fragment!( $op ( $( $args )* ) )];
619        v.append(&mut $crate::fragment_internal!( @v $( $tail )* ));
620
621        v
622    });
623    // Match modifiers
624    ( @v $modif:tt : $( $tail:tt )* ) => ({
625        let mut v = $crate::fragment_internal!( @v $( $tail )* );
626        let first = v.drain(..1).next().unwrap();
627
628        let first = $crate::apply_modifier!($modif:first);
629
630        let mut v_final = vec![first];
631        v_final.append(&mut v);
632
633        v_final
634    });
635    // Remove commas between operands
636    ( @v , $( $tail:tt )* ) => ({
637        $crate::fragment_internal!( @v $( $tail )* )
638    });
639    ( @v ) => ({
640        vec![]
641    });
642
643    // The @t prefix is used to parse a sequence of operands and return them in a tuple. This
644    // allows checking at compile-time the number of arguments passed to an operand. For this
645    // reason it's used by `and_*()`, `or_*()`, etc.
646    //
647    // Unfortunately, due to the fact that concatenating tuples is pretty hard, the final result
648    // adds in the first spot the parsed operand and in the second spot the result of parsing
649    // all the following ones. For two operands the type then corresponds to: (X, (X, ())). For
650    // three operands it's (X, (X, (X, ()))), etc.
651    //
652    // To check that the right number of arguments has been passed we can "cast" those tuples to
653    // more convenient structures like `TupleTwo`. If the conversion succeeds, the right number of
654    // args was passed. Otherwise the compilation fails entirely.
655    ( @t $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
656        ($crate::fragment!( $op ( $( $args )* ) ), $crate::fragment_internal!( @t $( $tail )* ))
657    });
658    // Match modifiers
659    ( @t $modif:tt : $( $tail:tt )* ) => ({
660        let (first, tail) = $crate::fragment_internal!( @t $( $tail )* );
661        ($crate::apply_modifier!($modif:first), tail)
662    });
663    // Remove commas between operands
664    ( @t , $( $tail:tt )* ) => ({
665        $crate::fragment_internal!( @t $( $tail )* )
666    });
667    ( @t ) => ({});
668
669    // Fallback to calling `fragment!()`
670    ( $( $tokens:tt )* ) => ({
671        $crate::fragment!($( $tokens )*)
672    });
673}
674
675/// Macro to write descriptor fragments with code
676///
677/// This macro will be expanded to an object of type `Result<(Miniscript<DescriptorPublicKey, _>,
678/// KeyMap, ValidNetworks), DescriptorError>`. It allows writing fragments of larger descriptors
679/// that can be pieced together using `fragment!(thresh_vec(m, ...))`.
680///
681/// The syntax to write macro fragment is the same as documented for the [`descriptor`] macro.
682#[macro_export]
683macro_rules! fragment {
684    // Modifiers
685    ( $modif:tt : $( $tail:tt )* ) => ({
686        let op = $crate::fragment!( $( $tail )* );
687        $crate::apply_modifier!($modif:op)
688    });
689
690    // Miniscript
691    ( true ) => ({
692        $crate::impl_leaf_opcode!(True)
693    });
694    ( false ) => ({
695        $crate::impl_leaf_opcode!(False)
696    });
697    ( pk_k ( $key:expr ) ) => ({
698        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
699        $crate::keys::make_pk($key, &secp)
700    });
701    ( pk ( $key:expr ) ) => ({
702        $crate::fragment!(c:pk_k ( $key ))
703    });
704    ( pk_h ( $key:expr ) ) => ({
705        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
706        $crate::keys::make_pkh($key, &secp)
707    });
708    ( after ( $value:expr ) ) => ({
709        $crate::impl_leaf_opcode_value!(After, $crate::miniscript::AbsLockTime::from_consensus($value).expect("valid `AbsLockTime`"))
710    });
711    ( older ( $value:expr ) ) => ({
712        $crate::impl_leaf_opcode_value!(Older, $crate::miniscript::RelLockTime::from_consensus($value).expect("valid `RelLockTime`")) // TODO!!
713    });
714    ( sha256 ( $hash:expr ) ) => ({
715        $crate::impl_leaf_opcode_value!(Sha256, $hash)
716    });
717    ( hash256 ( $hash:expr ) ) => ({
718        $crate::impl_leaf_opcode_value!(Hash256, $hash)
719    });
720    ( ripemd160 ( $hash:expr ) ) => ({
721        $crate::impl_leaf_opcode_value!(Ripemd160, $hash)
722    });
723    ( hash160 ( $hash:expr ) ) => ({
724        $crate::impl_leaf_opcode_value!(Hash160, $hash)
725    });
726    ( and_v ( $( $inner:tt )* ) ) => ({
727        $crate::impl_node_opcode_two!(AndV, $( $inner )*)
728    });
729    ( and_b ( $( $inner:tt )* ) ) => ({
730        $crate::impl_node_opcode_two!(AndB, $( $inner )*)
731    });
732    ( and_or ( $( $inner:tt )* ) ) => ({
733        $crate::impl_node_opcode_three!(AndOr, $( $inner )*)
734    });
735    ( andor ( $( $inner:tt )* ) ) => ({
736        $crate::impl_node_opcode_three!(AndOr, $( $inner )*)
737    });
738    ( or_b ( $( $inner:tt )* ) ) => ({
739        $crate::impl_node_opcode_two!(OrB, $( $inner )*)
740    });
741    ( or_d ( $( $inner:tt )* ) ) => ({
742        $crate::impl_node_opcode_two!(OrD, $( $inner )*)
743    });
744    ( or_c ( $( $inner:tt )* ) ) => ({
745        $crate::impl_node_opcode_two!(OrC, $( $inner )*)
746    });
747    ( or_i ( $( $inner:tt )* ) ) => ({
748        $crate::impl_node_opcode_two!(OrI, $( $inner )*)
749    });
750    ( thresh_vec ( $thresh:expr, $items:expr ) ) => ({
751        use $crate::miniscript::descriptor::KeyMap;
752
753        let (items, key_maps_networks): ($crate::alloc::vec::Vec<_>, $crate::alloc::vec::Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
754        let items = items.into_iter().map($crate::alloc::sync::Arc::new).collect();
755
756        let (key_maps, valid_networks) = key_maps_networks.into_iter().fold((KeyMap::default(), $crate::keys::any_network()), |(mut keys_acc, net_acc), (key, net)| {
757            keys_acc.extend(key.into_iter());
758            let net_acc = $crate::keys::merge_networks(&net_acc, &net);
759
760            (keys_acc, net_acc)
761        });
762
763        let thresh = $crate::miniscript::Threshold::new($thresh, items).expect("valid threshold and pks collection");
764        $crate::impl_leaf_opcode_value!(Thresh, thresh)
765            .map(|(minisc, _, _)| (minisc, key_maps, valid_networks))
766    });
767    ( thresh ( $thresh:expr, $( $inner:tt )* ) ) => ({
768        let items = $crate::fragment_internal!( @v $( $inner )* );
769
770        items.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
771            .and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
772    });
773    ( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
774        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
775
776        let fun = |k, pks| {
777            let thresh = $crate::miniscript::Threshold::new(k, pks).expect("valid threshold and pks collection");
778            $crate::miniscript::Terminal::Multi(thresh)
779        };
780
781        $crate::keys::make_multi($thresh, fun, $keys, &secp)
782    });
783    ( multi ( $thresh:expr $(, $key:expr )+ ) ) => ({
784        $crate::group_multi_keys!( $( $key ),* )
785            .and_then(|keys| $crate::fragment!( multi_vec ( $thresh, keys ) ))
786    });
787    ( multi_a_vec ( $thresh:expr, $keys:expr ) ) => ({
788        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
789
790        let fun = |k, pks| {
791            let thresh = $crate::miniscript::Threshold::new(k, pks).expect("valid threshold and pks collection");
792            $crate::miniscript::Terminal::MultiA(thresh)
793        };
794
795        $crate::keys::make_multi($thresh, fun, $keys, &secp)
796    });
797    ( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => ({
798        $crate::group_multi_keys!( $( $key ),* )
799            .and_then(|keys| $crate::fragment!( multi_a_vec ( $thresh, keys ) ))
800    });
801
802    // `sortedmulti()` is handled separately
803    ( sortedmulti ( $( $inner:tt )* ) ) => ({
804        compile_error!("`sortedmulti` can only be used as the root operand of a descriptor");
805    });
806    ( sortedmulti_vec ( $( $inner:tt )* ) ) => ({
807        compile_error!("`sortedmulti_vec` can only be used as the root operand of a descriptor");
808    });
809}
810
811#[cfg(test)]
812mod test {
813    use alloc::string::ToString;
814    use bitcoin::secp256k1::Secp256k1;
815    use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
816    use miniscript::{Descriptor, Legacy, Segwitv0};
817
818    use core::str::FromStr;
819
820    use crate::descriptor::{DescriptorError, DescriptorMeta};
821    use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
822    use bitcoin::bip32;
823    use bitcoin::Network::{Bitcoin, Regtest, Signet, Testnet, Testnet4};
824    use bitcoin::PrivateKey;
825
826    // test the descriptor!() macro
827
828    // verify descriptor generates expected script(s) (if bare or pk) or address(es)
829    fn check(
830        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
831        is_witness: bool,
832        is_fixed: bool,
833        expected: &[&str],
834    ) {
835        let (desc, _key_map, _networks) = desc.unwrap();
836        assert_eq!(desc.is_witness(), is_witness);
837        assert_eq!(!desc.has_wildcard(), is_fixed);
838        for i in 0..expected.len() {
839            let child_desc = desc
840                .at_derivation_index(i as u32)
841                .expect("i is not hardened");
842            let address = child_desc.address(Regtest);
843            if let Ok(address) = address {
844                assert_eq!(address.to_string(), *expected.get(i).unwrap());
845            } else {
846                let script = child_desc.script_pubkey();
847                assert_eq!(script.to_hex_string(), *expected.get(i).unwrap());
848            }
849        }
850    }
851
852    // - at least one of each "type" of operator; i.e. one modifier, one leaf_opcode, one
853    //   leaf_opcode_value, etc.
854    // - mixing up key types that implement IntoDescriptorKey in multi() or thresh()
855
856    // expected script for pk and bare manually created
857    // expected addresses created with `bitcoin-cli getdescriptorinfo` (for hash) and `bitcoin-cli
858    // deriveaddresses`
859
860    #[test]
861    fn test_fixed_legacy_descriptors() {
862        let pubkey1 = bitcoin::PublicKey::from_str(
863            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
864        )
865        .unwrap();
866        let pubkey2 = bitcoin::PublicKey::from_str(
867            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
868        )
869        .unwrap();
870
871        check(
872            descriptor!(bare(multi(1,pubkey1,pubkey2))),
873            false,
874            true,
875            &["512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af52ae"],
876        );
877        check(
878            descriptor!(pk(pubkey1)),
879            false,
880            true,
881            &["2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"],
882        );
883        check(
884            descriptor!(pkh(pubkey1)),
885            false,
886            true,
887            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
888        );
889        check(
890            descriptor!(sh(multi(1, pubkey1, pubkey2))),
891            false,
892            true,
893            &["2MymURoV1bzuMnWMGiXzyomDkeuxXY7Suey"],
894        );
895    }
896
897    #[test]
898    fn test_fixed_segwitv0_descriptors() {
899        let pubkey1 = bitcoin::PublicKey::from_str(
900            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
901        )
902        .unwrap();
903        let pubkey2 = bitcoin::PublicKey::from_str(
904            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
905        )
906        .unwrap();
907
908        check(
909            descriptor!(wpkh(pubkey1)),
910            true,
911            true,
912            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
913        );
914        check(
915            descriptor!(sh(wpkh(pubkey1))),
916            true,
917            true,
918            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
919        );
920        check(
921            descriptor!(wsh(multi(1, pubkey1, pubkey2))),
922            true,
923            true,
924            &["bcrt1qgw8jvv2hsrvjfa6q66rk6har7d32lrqm5unnf5cl63q9phxfvgps5fyfqe"],
925        );
926        check(
927            descriptor!(sh(wsh(multi(1, pubkey1, pubkey2)))),
928            true,
929            true,
930            &["2NCidRJysy7apkmE6JF5mLLaJFkrN3Ub9iy"],
931        );
932    }
933
934    #[test]
935    fn test_fixed_threeop_descriptors() {
936        let redeem_key = bitcoin::PublicKey::from_str(
937            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
938        )
939        .unwrap();
940        let move_key = bitcoin::PublicKey::from_str(
941            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
942        )
943        .unwrap();
944
945        check(
946            descriptor!(sh(wsh(and_or(pk(redeem_key), older(1000), pk(move_key))))),
947            true,
948            true,
949            &["2MypGwr5eQWAWWJtiJgUEToVxc4zuokjQRe"],
950        );
951    }
952
953    #[test]
954    fn test_bip32_legacy_descriptors() {
955        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
956
957        let path = bip32::DerivationPath::from_str("m/0").unwrap();
958        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
959        check(
960            descriptor!(pk(desc_key)),
961            false,
962            false,
963            &[
964                "2102363ad03c10024e1b597a5b01b9982807fb638e00b06f3b2d4a89707de3b93c37ac",
965                "2102063a21fd780df370ed2fc8c4b86aa5ea642630609c203009df631feb7b480dd2ac",
966                "2102ba2685ad1fa5891cb100f1656b2ce3801822ccb9bac0336734a6f8c1b93ebbc0ac",
967            ],
968        );
969
970        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
971        check(
972            descriptor!(pkh(desc_key)),
973            false,
974            false,
975            &[
976                "muvBdsVpJxpFuTHMKA47htJPdCvdt4F9DP",
977                "mxQSHK7DL2t1DN3xFxov1janCoXSSkrSPj",
978                "mfz43r15GiWo4nizmyzMNubsnkDpByFFAn",
979            ],
980        );
981
982        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
983        let desc_key1 = (xprv, path).into_descriptor_key().unwrap();
984        let desc_key2 = (xprv, path2).into_descriptor_key().unwrap();
985
986        check(
987            descriptor!(sh(multi(1, desc_key1, desc_key2))),
988            false,
989            false,
990            &[
991                "2MtMDXsfwefZkEEhVViEPidvcKRUtJamJJ8",
992                "2MwAUZ1NYyWjhVvGTethFL6n7nZhS8WE6At",
993                "2MuT6Bj66HLwZd7s4SoD8XbK4GwriKEA6Gr",
994            ],
995        );
996    }
997
998    #[test]
999    fn test_bip32_segwitv0_descriptors() {
1000        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
1001
1002        let path = bip32::DerivationPath::from_str("m/0").unwrap();
1003        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
1004        check(
1005            descriptor!(wpkh(desc_key)),
1006            true,
1007            false,
1008            &[
1009                "bcrt1qnhm8w9fhc8cxzgqsmqdf9fyjccyvc0gltnymu0",
1010                "bcrt1qhylfd55rn75w9fj06zspctad5w4hz33rf0ttad",
1011                "bcrt1qq5sq3a6k9av9d8cne0k9wcldy4nqey5yt6889r",
1012            ],
1013        );
1014
1015        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
1016        check(
1017            descriptor!(sh(wpkh(desc_key))),
1018            true,
1019            false,
1020            &[
1021                "2MxvjQCaLqZ5QxZ7XotZDQ63hZw3NPss763",
1022                "2NDUoevN4QMzhvHDMGhKuiT2fN9HXbFRMwn",
1023                "2NF4BEAY2jF1Fu8vqfN3NVKoFtom77pUxrx",
1024            ],
1025        );
1026
1027        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
1028        let desc_key1 = (xprv, path.clone()).into_descriptor_key().unwrap();
1029        let desc_key2 = (xprv, path2.clone()).into_descriptor_key().unwrap();
1030        check(
1031            descriptor!(wsh(multi(1, desc_key1, desc_key2))),
1032            true,
1033            false,
1034            &[
1035                "bcrt1qfxv8mxmlv5sz8q2mnuyaqdfe9jr4vvmx0csjhn092p6f4qfygfkq2hng49",
1036                "bcrt1qerj85g243e6jlcdxpmn9spk0gefcwvu7nw7ee059d5ydzpdhkm2qwfkf5k",
1037                "bcrt1qxkl2qss3k58q9ktc8e89pwr4gnptfpw4hju4xstxcjc0hkcae3jstluty7",
1038            ],
1039        );
1040
1041        let desc_key1 = (xprv, path).into_descriptor_key().unwrap();
1042        let desc_key2 = (xprv, path2).into_descriptor_key().unwrap();
1043        check(
1044            descriptor!(sh(wsh(multi(1, desc_key1, desc_key2)))),
1045            true,
1046            false,
1047            &[
1048                "2NFCtXvx9q4ci2kvKub17iSTgvRXGctCGhz",
1049                "2NB2PrFPv5NxWCpygas8tPrGJG2ZFgeuwJw",
1050                "2N79ZAGo5cMi5Jt7Wo9L5YmF5GkEw7sjWdC",
1051            ],
1052        );
1053    }
1054
1055    #[test]
1056    fn test_dsl_sortedmulti() {
1057        let key_1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
1058        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
1059
1060        let key_2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
1061        let path_2 = bip32::DerivationPath::from_str("m/1").unwrap();
1062
1063        let desc_key1 = (key_1, path_1);
1064        let desc_key2 = (key_2, path_2);
1065
1066        check(
1067            descriptor!(sh(sortedmulti(1, desc_key1.clone(), desc_key2.clone()))),
1068            false,
1069            false,
1070            &[
1071                "2MsxzPEJDBzpGffJXPaDpfXZAUNnZhaMh2N",
1072                "2My3x3DLPK3UbGWGpxrXr1RnbD8MNC4FpgS",
1073                "2NByEuiQT7YLqHCTNxL5KwYjvtuCYcXNBSC",
1074                "2N1TGbP81kj2VUKTSWgrwxoMfuWjvfUdyu7",
1075                "2N3Bomq2fpAcLRNfZnD3bCWK9quan28CxCR",
1076                "2N9nrZaEzEFDqEAU9RPvDnXGT6AVwBDKAQb",
1077            ],
1078        );
1079
1080        check(
1081            descriptor!(sh(wsh(sortedmulti(
1082                1,
1083                desc_key1.clone(),
1084                desc_key2.clone()
1085            )))),
1086            true,
1087            false,
1088            &[
1089                "2NCogc5YyM4N6ruv1hUa7WLMW1BPeCK7N9B",
1090                "2N6mkSAKi1V2oaBXby7XHdvBMKEDRQcFpNe",
1091                "2NFmTSttm9v6bXeoWaBvpMcgfPQcZhNn3Eh",
1092                "2Mvib87RBPUHXNEpX5S5Kv1qqrhBfgBGsJM",
1093                "2MtMv5mcK2EjcLsH8Txpx2JxLLzHr4ttczL",
1094                "2MsWCB56rb4T6yPv8QudZGHERTwNgesE4f6",
1095            ],
1096        );
1097
1098        check(
1099            descriptor!(wsh(sortedmulti_vec(1, vec![desc_key1, desc_key2]))),
1100            true,
1101            false,
1102            &[
1103                "bcrt1qcvq0lg8q7a47ytrd7zk5y7uls7mulrenjgvflwylpppgwf8029es4vhpnj",
1104                "bcrt1q80yn8sdt6l7pjvkz25lglyaqctlmsq9ugk80rmxt8yu0npdsj97sc7l4de",
1105                "bcrt1qrvf6024v9s50qhffe3t2fr2q9ckdhx2g6jz32chm2pp24ymgtr5qfrdmct",
1106                "bcrt1q6srfmra0ynypym35c7jvsxt2u4yrugeajq95kg2ps7lk6h2gaunsq9lzxn",
1107                "bcrt1qhl8rrzzcdpu7tcup3lcg7tge52sqvwy5fcv4k78v6kxtwmqf3v6qpvyjza",
1108                "bcrt1ql2elz9mhm9ll27ddpewhxs732xyl2fk2kpkqz9gdyh33wgcun4vstrd49k",
1109            ],
1110        );
1111    }
1112
1113    // - verify the valid_networks returned is correctly computed based on the keys present in the
1114    //   descriptor
1115    #[test]
1116    fn test_valid_networks() {
1117        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
1118        let path = bip32::DerivationPath::from_str("m/0").unwrap();
1119        let desc_key = (xprv, path).into_descriptor_key().unwrap();
1120
1121        let (_desc, _key_map, valid_networks) = descriptor!(pkh(desc_key)).unwrap();
1122        assert_eq!(
1123            valid_networks,
1124            [Testnet, Testnet4, Regtest, Signet]
1125                .iter()
1126                .cloned()
1127                .collect()
1128        );
1129
1130        let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap();
1131        let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
1132        let desc_key = (xprv, path).into_descriptor_key().unwrap();
1133
1134        let (_desc, _key_map, valid_networks) = descriptor!(wpkh(desc_key)).unwrap();
1135        assert_eq!(valid_networks, [Bitcoin].iter().cloned().collect());
1136    }
1137
1138    // - verify the key_maps are correctly merged together
1139    #[test]
1140    fn test_key_maps_merged() {
1141        let secp = Secp256k1::new();
1142
1143        let xprv1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
1144        let path1 = bip32::DerivationPath::from_str("m/0").unwrap();
1145        let desc_key1 = (xprv1, path1.clone()).into_descriptor_key().unwrap();
1146
1147        let xprv2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
1148        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
1149        let desc_key2 = (xprv2, path2.clone()).into_descriptor_key().unwrap();
1150
1151        let xprv3 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap();
1152        let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
1153        let desc_key3 = (xprv3, path3.clone()).into_descriptor_key().unwrap();
1154
1155        let (_desc, key_map, _valid_networks) =
1156            descriptor!(sh(wsh(multi(2, desc_key1, desc_key2, desc_key3)))).unwrap();
1157        assert_eq!(key_map.len(), 3);
1158
1159        let desc_key1: DescriptorKey<Segwitv0> = (xprv1, path1).into_descriptor_key().unwrap();
1160        let desc_key2: DescriptorKey<Segwitv0> = (xprv2, path2).into_descriptor_key().unwrap();
1161        let desc_key3: DescriptorKey<Segwitv0> = (xprv3, path3).into_descriptor_key().unwrap();
1162
1163        let (key1, _key_map, _valid_networks) = desc_key1.extract(&secp).unwrap();
1164        let (key2, _key_map, _valid_networks) = desc_key2.extract(&secp).unwrap();
1165        let (key3, _key_map, _valid_networks) = desc_key3.extract(&secp).unwrap();
1166        assert_eq!(key_map.get(&key1).unwrap().to_string(), "tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/0/*");
1167        assert_eq!(key_map.get(&key2).unwrap().to_string(), "tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF/2147483647'/0/*");
1168        assert_eq!(key_map.get(&key3).unwrap().to_string(), "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf/10/20/30/40/*");
1169    }
1170
1171    // - verify the ScriptContext is correctly validated (i.e. passing a type that only impl
1172    //   IntoDescriptorKey<Segwitv0> to a pkh() descriptor should throw a compilation error
1173    #[test]
1174    fn test_script_context_validation() {
1175        // this compiles
1176        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
1177        let path = bip32::DerivationPath::from_str("m/0").unwrap();
1178        let desc_key: DescriptorKey<Legacy> = (xprv, path).into_descriptor_key().unwrap();
1179
1180        let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
1181        assert_eq!(desc.to_string(), "pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)#yrnz9pp2");
1182
1183        // as expected this does not compile due to invalid context
1184        //let desc_key:DescriptorKey<Segwitv0> = (xprv,
1185        // path.clone()).into_descriptor_key().unwrap(); let (desc, _key_map,
1186        // _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
1187    }
1188
1189    #[test]
1190    fn test_dsl_modifiers() {
1191        let private_key =
1192            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
1193        let (descriptor, _, _) =
1194            descriptor!(wsh(thresh(2,n:d:v:older(1),s:pk(private_key),s:pk(private_key)))).unwrap();
1195
1196        assert_eq!(descriptor.to_string(), "wsh(thresh(2,ndv:older(1),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)))#zzk3ux8g")
1197    }
1198
1199    #[test]
1200    #[should_panic(expected = "Miniscript(ContextError(UncompressedKeysNotAllowed))")]
1201    fn test_dsl_miniscript_checks() {
1202        let mut uncompressed_pk =
1203            PrivateKey::from_wif("L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6").unwrap();
1204        uncompressed_pk.compressed = false;
1205
1206        descriptor!(wsh(v: pk(uncompressed_pk))).unwrap();
1207    }
1208
1209    #[test]
1210    fn test_dsl_tr_only_key() {
1211        let private_key =
1212            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
1213        let (descriptor, _, _) = descriptor!(tr(private_key)).unwrap();
1214
1215        assert_eq!(
1216            descriptor.to_string(),
1217            "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)#heq9m95v"
1218        )
1219    }
1220
1221    #[test]
1222    fn test_dsl_tr_simple_tree() {
1223        let private_key =
1224            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
1225        let (descriptor, _, _) =
1226            descriptor!(tr(private_key, { pk(private_key), pk(private_key) })).unwrap();
1227
1228        assert_eq!(descriptor.to_string(), "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c,{pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)})#xy5fjw6d")
1229    }
1230
1231    #[test]
1232    fn test_dsl_tr_single_leaf() {
1233        let private_key =
1234            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
1235        let (descriptor, _, _) = descriptor!(tr(private_key, pk(private_key))).unwrap();
1236
1237        assert_eq!(descriptor.to_string(), "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c,pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c))#lzl2vmc7")
1238    }
1239}