1#[doc(hidden)]
15#[macro_export]
16macro_rules! impl_top_level_sh {
17 ( 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 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 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 ( { { $( $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 ( { $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 ( { $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 ( $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 ( 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_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 $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 ( @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 ( @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 ( @v , $( $tail:tt )* ) => ({
637 $crate::fragment_internal!( @v $( $tail )* )
638 });
639 ( @v ) => ({
640 vec![]
641 });
642
643 ( @t $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
656 ($crate::fragment!( $op ( $( $args )* ) ), $crate::fragment_internal!( @t $( $tail )* ))
657 });
658 ( @t $modif:tt : $( $tail:tt )* ) => ({
660 let (first, tail) = $crate::fragment_internal!( @t $( $tail )* );
661 ($crate::apply_modifier!($modif:first), tail)
662 });
663 ( @t , $( $tail:tt )* ) => ({
665 $crate::fragment_internal!( @t $( $tail )* )
666 });
667 ( @t ) => ({});
668
669 ( $( $tokens:tt )* ) => ({
671 $crate::fragment!($( $tokens )*)
672 });
673}
674
675#[macro_export]
683macro_rules! fragment {
684 ( $modif:tt : $( $tail:tt )* ) => ({
686 let op = $crate::fragment!( $( $tail )* );
687 $crate::apply_modifier!($modif:op)
688 });
689
690 ( 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`")) });
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 ( $( $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 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 #[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 #[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 #[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 #[test]
1174 fn test_script_context_validation() {
1175 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 }
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}