2020-09-16 14:32:55 +02:00
// Magical Bitcoin Library
// Written in 2020 by
// Alekos Filini <alekos.filini@gmail.com>
//
// Copyright (c) 2020 Magical Bitcoin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
2020-09-18 16:31:03 +02:00
//! Descriptors DSL
2020-09-16 14:32:55 +02:00
2020-09-18 16:31:03 +02:00
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_top_level_sh {
2020-11-17 23:40:31 +01:00
// disallow `sortedmulti` in `bare()`
2021-02-02 20:06:40 -05:00
( Bare , new , new , Legacy , sortedmulti $( $inner :tt ) * ) = > {
2020-12-16 16:10:22 +01:00
compile_error! ( " `bare()` descriptors can't contain any `sortedmulti()` operands " ) ;
2020-11-17 23:40:31 +01:00
} ;
2021-02-02 20:06:40 -05:00
( Bare , new , new , Legacy , sortedmulti_vec $( $inner :tt ) * ) = > {
2020-12-16 16:10:22 +01:00
compile_error! ( " `bare()` descriptors can't contain any `sortedmulti_vec()` operands " ) ;
2020-11-17 23:40:31 +01:00
} ;
2021-02-02 20:06:40 -05:00
( $inner_struct :ident , $constructor :ident , $sortedmulti_constructor :ident , $ctx :ident , sortedmulti $( $inner :tt ) * ) = > { {
use std ::marker ::PhantomData ;
use $crate ::miniscript ::descriptor ::{ $inner_struct , Descriptor , DescriptorPublicKey } ;
use $crate ::miniscript ::$ctx ;
let build_desc = | k , pks | {
Ok ( ( Descriptor ::< DescriptorPublicKey > ::$inner_struct ( $inner_struct ::$sortedmulti_constructor ( k , pks ) ? ) , PhantomData ::< $ctx > ) )
} ;
$crate ::impl_sortedmulti! ( build_desc , sortedmulti $( $inner ) * )
} } ;
( $inner_struct :ident , $constructor :ident , $sortedmulti_constructor :ident , $ctx :ident , sortedmulti_vec $( $inner :tt ) * ) = > { {
use std ::marker ::PhantomData ;
use $crate ::miniscript ::descriptor ::{ $inner_struct , Descriptor , DescriptorPublicKey } ;
use $crate ::miniscript ::$ctx ;
let build_desc = | k , pks | {
Ok ( ( Descriptor ::< DescriptorPublicKey > ::$inner_struct ( $inner_struct ::$sortedmulti_constructor ( k , pks ) ? ) , PhantomData ::< $ctx > ) )
} ;
$crate ::impl_sortedmulti! ( build_desc , sortedmulti_vec $( $inner ) * )
} } ;
( $inner_struct :ident , $constructor :ident , $sortedmulti_constructor :ident , $ctx :ident , $( $minisc :tt ) * ) = > { {
use $crate ::miniscript ::descriptor ::{ $inner_struct , Descriptor , DescriptorPublicKey } ;
2020-11-17 23:40:31 +01:00
2020-09-18 16:31:03 +02:00
$crate ::fragment! ( $( $minisc ) * )
2021-02-02 20:06:40 -05:00
. and_then ( | ( minisc , keymap , networks ) | Ok ( ( $inner_struct ::$constructor ( minisc ) ? , keymap , networks ) ) )
. and_then ( | ( inner , key_map , valid_networks ) | Ok ( ( Descriptor ::< DescriptorPublicKey > ::$inner_struct ( inner ) , key_map , valid_networks ) ) )
} } ;
2020-09-18 16:31:03 +02:00
}
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_top_level_pk {
2021-02-02 20:06:40 -05:00
( $inner_type :ident , $ctx :ty , $key :expr ) = > { {
use $crate ::miniscript ::descriptor ::$inner_type ;
2020-09-22 16:12:09 +02:00
#[ allow(unused_imports) ]
2020-09-19 12:08:30 +02:00
use $crate ::keys ::{ DescriptorKey , ToDescriptorKey } ;
2020-11-16 22:07:38 +01:00
let secp = $crate ::bitcoin ::secp256k1 ::Secp256k1 ::new ( ) ;
2020-09-19 12:08:30 +02:00
2021-02-11 11:00:48 -08:00
$key . into_descriptor_key ( )
2020-11-16 22:07:38 +01:00
. and_then ( | key : DescriptorKey < $ctx > | key . extract ( & secp ) )
2021-01-11 13:12:01 +01:00
. map_err ( $crate ::descriptor ::DescriptorError ::Key )
2021-02-02 20:06:40 -05:00
. map ( | ( pk , key_map , valid_networks ) | ( $inner_type ::new ( pk ) , key_map , valid_networks ) )
2020-09-18 16:31:03 +02:00
} } ;
}
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_leaf_opcode {
2021-01-11 13:12:01 +01:00
( $terminal_variant :ident ) = > { {
use $crate ::descriptor ::CheckMiniscript ;
2020-09-18 16:31:03 +02:00
$crate ::miniscript ::Miniscript ::from_ast (
$crate ::miniscript ::miniscript ::decode ::Terminal ::$terminal_variant ,
)
2021-01-11 13:12:01 +01:00
. map_err ( $crate ::descriptor ::DescriptorError ::Miniscript )
. and_then ( | minisc | {
minisc . check_minsicript ( ) ? ;
Ok ( minisc )
} )
2020-09-21 15:44:07 +02:00
. map ( | minisc | {
(
minisc ,
$crate ::miniscript ::descriptor ::KeyMap ::default ( ) ,
$crate ::keys ::any_network ( ) ,
)
} )
2021-01-11 13:12:01 +01:00
} } ;
2020-09-18 16:31:03 +02:00
}
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_leaf_opcode_value {
2021-01-11 13:12:01 +01:00
( $terminal_variant :ident , $value :expr ) = > { {
use $crate ::descriptor ::CheckMiniscript ;
2020-09-18 16:31:03 +02:00
$crate ::miniscript ::Miniscript ::from_ast (
$crate ::miniscript ::miniscript ::decode ::Terminal ::$terminal_variant ( $value ) ,
)
2021-01-11 13:12:01 +01:00
. map_err ( $crate ::descriptor ::DescriptorError ::Miniscript )
. and_then ( | minisc | {
minisc . check_minsicript ( ) ? ;
Ok ( minisc )
} )
2020-09-21 15:44:07 +02:00
. map ( | minisc | {
(
minisc ,
$crate ::miniscript ::descriptor ::KeyMap ::default ( ) ,
$crate ::keys ::any_network ( ) ,
)
} )
2021-01-11 13:12:01 +01:00
} } ;
2020-09-18 16:31:03 +02:00
}
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_leaf_opcode_value_two {
2021-01-11 13:12:01 +01:00
( $terminal_variant :ident , $one :expr , $two :expr ) = > { {
use $crate ::descriptor ::CheckMiniscript ;
2020-09-18 16:31:03 +02:00
$crate ::miniscript ::Miniscript ::from_ast (
$crate ::miniscript ::miniscript ::decode ::Terminal ::$terminal_variant ( $one , $two ) ,
)
2021-01-11 13:12:01 +01:00
. map_err ( $crate ::descriptor ::DescriptorError ::Miniscript )
. and_then ( | minisc | {
minisc . check_minsicript ( ) ? ;
Ok ( minisc )
} )
2020-09-21 15:44:07 +02:00
. map ( | minisc | {
(
minisc ,
$crate ::miniscript ::descriptor ::KeyMap ::default ( ) ,
$crate ::keys ::any_network ( ) ,
)
} )
2021-01-11 13:12:01 +01:00
} } ;
2020-09-18 16:31:03 +02:00
}
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_node_opcode_two {
2020-12-16 16:10:22 +01:00
( $terminal_variant :ident , $( $inner :tt ) * ) = > ( {
2021-01-11 13:12:01 +01:00
use $crate ::descriptor ::CheckMiniscript ;
2020-12-16 16:10:22 +01:00
let inner = $crate ::fragment_internal! ( @ t $( $inner ) * ) ;
let ( a , b ) = $crate ::descriptor ::dsl ::TupleTwo ::from ( inner ) . flattened ( ) ;
a
. and_then ( | a | Ok ( ( a , b ? ) ) )
2020-09-21 15:44:07 +02:00
. and_then ( | ( ( a_minisc , mut a_keymap , a_networks ) , ( b_minisc , b_keymap , b_networks ) ) | {
2020-09-18 16:31:03 +02:00
// join key_maps
a_keymap . extend ( b_keymap . into_iter ( ) ) ;
2021-01-11 13:12:01 +01:00
let minisc = $crate ::miniscript ::Miniscript ::from_ast ( $crate ::miniscript ::miniscript ::decode ::Terminal ::$terminal_variant (
2020-09-18 16:31:03 +02:00
std ::sync ::Arc ::new ( a_minisc ) ,
std ::sync ::Arc ::new ( b_minisc ) ,
2021-01-11 13:12:01 +01:00
) ) ? ;
minisc . check_minsicript ( ) ? ;
Ok ( ( minisc , a_keymap , $crate ::keys ::merge_networks ( & a_networks , & b_networks ) ) )
2020-09-18 16:31:03 +02:00
} )
2020-12-16 16:10:22 +01:00
} ) ;
2020-09-18 16:31:03 +02:00
}
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_node_opcode_three {
2020-12-16 16:10:22 +01:00
( $terminal_variant :ident , $( $inner :tt ) * ) = > {
2021-01-11 13:12:01 +01:00
use $crate ::descriptor ::CheckMiniscript ;
2020-12-16 16:10:22 +01:00
let inner = $crate ::fragment_internal! ( @ t $( $inner ) * ) ;
let ( a , b , c ) = $crate ::descriptor ::dsl ::TupleThree ::from ( inner ) . flattened ( ) ;
a
. and_then ( | a | Ok ( ( a , b ? , c ? ) ) )
2020-09-21 15:44:07 +02:00
. and_then ( | ( ( a_minisc , mut a_keymap , a_networks ) , ( b_minisc , b_keymap , b_networks ) , ( c_minisc , c_keymap , c_networks ) ) | {
2020-09-18 16:31:03 +02:00
// join key_maps
a_keymap . extend ( b_keymap . into_iter ( ) ) ;
a_keymap . extend ( c_keymap . into_iter ( ) ) ;
2020-09-21 15:44:07 +02:00
let networks = $crate ::keys ::merge_networks ( & a_networks , & b_networks ) ;
let networks = $crate ::keys ::merge_networks ( & networks , & c_networks ) ;
2021-01-11 13:12:01 +01:00
let minisc = $crate ::miniscript ::Miniscript ::from_ast ( $crate ::miniscript ::miniscript ::decode ::Terminal ::$terminal_variant (
2020-09-18 16:31:03 +02:00
std ::sync ::Arc ::new ( a_minisc ) ,
std ::sync ::Arc ::new ( b_minisc ) ,
std ::sync ::Arc ::new ( c_minisc ) ,
2021-01-11 13:12:01 +01:00
) ) ? ;
minisc . check_minsicript ( ) ? ;
Ok ( ( minisc , a_keymap , networks ) )
2020-09-18 16:31:03 +02:00
} )
} ;
}
2020-11-17 23:40:31 +01:00
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! impl_sortedmulti {
2021-02-02 20:06:40 -05:00
( $build_desc :expr , sortedmulti_vec ( $thresh :expr , $keys :expr ) ) = > ( {
2020-11-17 23:40:31 +01:00
let secp = $crate ::bitcoin ::secp256k1 ::Secp256k1 ::new ( ) ;
2021-02-02 20:06:40 -05:00
$crate ::keys ::make_sortedmulti ( $thresh , $keys , $build_desc , & secp )
2020-11-17 23:40:31 +01:00
} ) ;
2021-02-02 20:06:40 -05:00
( $build_desc :expr , sortedmulti ( $thresh :expr $(, $key :expr ) + ) ) = > ( {
2020-11-17 23:40:31 +01:00
use $crate ::keys ::ToDescriptorKey ;
let secp = $crate ::bitcoin ::secp256k1 ::Secp256k1 ::new ( ) ;
let mut keys = vec! [ ] ;
$(
2021-02-11 11:00:48 -08:00
keys . push ( $key . into_descriptor_key ( ) ) ;
2020-11-17 23:40:31 +01:00
) *
keys . into_iter ( ) . collect ::< Result < Vec < _ > , _ > > ( )
2021-01-11 13:12:01 +01:00
. map_err ( $crate ::descriptor ::DescriptorError ::Key )
2021-02-02 20:06:40 -05:00
. and_then ( | keys | $crate ::keys ::make_sortedmulti ( $thresh , keys , $build_desc , & secp ) )
2020-11-17 23:40:31 +01:00
} ) ;
}
2020-12-16 16:10:22 +01:00
#[ doc(hidden) ]
#[ macro_export ]
macro_rules ! apply_modifier {
( $terminal_variant :ident , $inner :expr ) = > { {
2021-01-11 13:12:01 +01:00
use $crate ::descriptor ::CheckMiniscript ;
2020-12-16 16:10:22 +01:00
$inner
2021-01-11 13:12:01 +01:00
. map_err ( | e | -> $crate ::descriptor ::DescriptorError { e . into ( ) } )
2020-12-16 16:10:22 +01:00
. and_then ( | ( minisc , keymap , networks ) | {
2021-01-11 13:12:01 +01:00
let minisc = $crate ::miniscript ::Miniscript ::from_ast (
$crate ::miniscript ::miniscript ::decode ::Terminal ::$terminal_variant (
std ::sync ::Arc ::new ( minisc ) ,
) ,
) ? ;
minisc . check_minsicript ( ) ? ;
Ok ( ( minisc , keymap , networks ) )
2020-12-16 16:10:22 +01:00
} )
} } ;
( a : $inner :expr ) = > { {
$crate ::apply_modifier! ( Alt , $inner )
} } ;
( s : $inner :expr ) = > { {
$crate ::apply_modifier! ( Swap , $inner )
} } ;
( c : $inner :expr ) = > { {
$crate ::apply_modifier! ( Check , $inner )
} } ;
( d : $inner :expr ) = > { {
$crate ::apply_modifier! ( DupIf , $inner )
} } ;
( v : $inner :expr ) = > { {
$crate ::apply_modifier! ( Verify , $inner )
} } ;
( j : $inner :expr ) = > { {
$crate ::apply_modifier! ( NonZero , $inner )
} } ;
( n : $inner :expr ) = > { {
$crate ::apply_modifier! ( ZeroNotEqual , $inner )
} } ;
// Modifiers expanded to other operators
( t : $inner :expr ) = > { {
$inner . and_then ( | ( a_minisc , a_keymap , a_networks ) | {
$crate ::impl_leaf_opcode_value_two! (
AndV ,
std ::sync ::Arc ::new ( a_minisc ) ,
std ::sync ::Arc ::new ( $crate ::fragment! ( true ) . unwrap ( ) . 0 )
)
. map ( | ( minisc , _ , _ ) | ( minisc , a_keymap , a_networks ) )
} )
} } ;
( l : $inner :expr ) = > { {
$inner . and_then ( | ( a_minisc , a_keymap , a_networks ) | {
$crate ::impl_leaf_opcode_value_two! (
OrI ,
std ::sync ::Arc ::new ( $crate ::fragment! ( false ) . unwrap ( ) . 0 ) ,
std ::sync ::Arc ::new ( a_minisc )
)
. map ( | ( minisc , _ , _ ) | ( minisc , a_keymap , a_networks ) )
} )
} } ;
( u : $inner :expr ) = > { {
$inner . and_then ( | ( a_minisc , a_keymap , a_networks ) | {
$crate ::impl_leaf_opcode_value_two! (
OrI ,
std ::sync ::Arc ::new ( a_minisc ) ,
std ::sync ::Arc ::new ( $crate ::fragment! ( false ) . unwrap ( ) . 0 )
)
. map ( | ( minisc , _ , _ ) | ( minisc , a_keymap , a_networks ) )
} )
} } ;
}
2020-09-18 16:31:03 +02:00
/// Macro to write full descriptors with code
2020-09-16 14:32:55 +02:00
///
2020-12-10 11:38:42 +01:00
/// This macro expands to a `Result` of
2021-01-11 13:12:01 +01:00
/// [`DescriptorTemplateOut`](super::template::DescriptorTemplateOut) and [`DescriptorError`](crate::descriptor::DescriptorError)
2020-09-16 14:32:55 +02:00
///
2020-12-16 16:10:22 +01:00
/// The syntax is very similar to the normal descriptor syntax, with the exception that modifiers
/// cannot be grouped together. For instance, a descriptor fragment like `sdv:older(144)` has to be
/// broken up to `s:d:v:older(144)`.
///
2020-12-16 19:01:16 +01:00
/// The `pk()`, `pk_k()` and `pk_h()` operands can take as argument any type that implements
/// [`ToDescriptorKey`]. This means that keys can also be written inline as strings, but in that
/// case they must be wrapped in quotes, which is another difference compared to the standard
/// descriptor syntax.
///
/// [`ToDescriptorKey`]: crate::keys::ToDescriptorKey
///
2020-09-16 14:32:55 +02:00
/// ## Example
///
2020-12-16 19:01:16 +01:00
/// Signature plus timelock descriptor:
2020-09-16 14:32:55 +02:00
///
/// ```
/// # use std::str::FromStr;
2020-12-16 19:01:16 +01:00
/// let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh(wsh(and_v(v:pk("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"),older(50)))))?;
2020-09-18 16:31:03 +02:00
/// # Ok::<(), Box<dyn std::error::Error>>(())
2020-09-16 14:32:55 +02:00
/// ```
///
2020-09-18 16:31:03 +02:00
/// -------
///
2020-09-16 14:32:55 +02:00
/// 2-of-3 that becomes a 1-of-3 after a timelock has expired. Both `descriptor_a` and `descriptor_b` are equivalent: the first
/// syntax is more suitable for a fixed number of items known at compile time, while the other accepts a
/// [`Vec`] of items, which makes it more suitable for writing dynamic descriptors.
///
/// They both produce the descriptor: `wsh(thresh(2,pk(...),s:pk(...),sdv:older(...)))`
///
/// ```
/// # use std::str::FromStr;
2021-01-11 13:12:01 +01:00
/// let my_key_1 = bitcoin::PublicKey::from_str(
/// "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
/// )?;
/// let my_key_2 =
/// bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
2020-09-16 14:32:55 +02:00
/// let my_timelock = 50;
///
2020-09-21 15:44:07 +02:00
/// let (descriptor_a, key_map_a, networks) = bdk::descriptor! {
2020-09-16 14:32:55 +02:00
/// wsh (
2020-12-16 16:10:22 +01:00
/// thresh(2, pk(my_key_1), s:pk(my_key_2), s:d:v:older(my_timelock))
2020-09-16 14:32:55 +02:00
/// )
2020-09-18 16:31:03 +02:00
/// }?;
2020-09-16 14:32:55 +02:00
///
2021-01-11 13:12:01 +01:00
/// #[rustfmt::skip]
2020-09-16 14:32:55 +02:00
/// let b_items = vec![
2020-12-16 16:10:22 +01:00
/// bdk::fragment!(pk(my_key_1))?,
/// bdk::fragment!(s:pk(my_key_2))?,
/// bdk::fragment!(s:d:v:older(my_timelock))?,
2020-09-16 14:32:55 +02:00
/// ];
2021-01-11 13:12:01 +01:00
/// let (descriptor_b, mut key_map_b, networks) = bdk::descriptor!(wsh(thresh_vec(2, b_items)))?;
2020-09-16 14:32:55 +02:00
///
/// assert_eq!(descriptor_a, descriptor_b);
2020-09-18 16:31:03 +02:00
/// assert_eq!(key_map_a.len(), key_map_b.len());
/// # Ok::<(), Box<dyn std::error::Error>>(())
2020-09-16 14:32:55 +02:00
/// ```
2020-09-18 17:26:58 +02:00
///
/// ------
///
/// Simple 2-of-2 multi-signature, equivalent to: `wsh(multi(2, ...))`
///
/// ```
/// # use std::str::FromStr;
2020-12-16 14:19:37 -08:00
/// let my_key_1 = bitcoin::PublicKey::from_str(
/// "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
/// )?;
/// let my_key_2 =
/// bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
2020-09-18 17:26:58 +02:00
///
2020-09-21 15:44:07 +02:00
/// let (descriptor, key_map, networks) = bdk::descriptor! {
2020-09-18 17:26:58 +02:00
/// wsh (
2020-12-16 16:10:22 +01:00
/// multi(2, my_key_1, my_key_2)
2020-09-18 17:26:58 +02:00
/// )
/// }?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
2020-09-19 12:08:30 +02:00
///
/// ------
///
/// Native-Segwit single-sig, equivalent to: `wpkh(...)`
///
/// ```
2020-12-16 14:19:37 -08:00
/// let my_key =
/// bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
2020-09-19 12:08:30 +02:00
///
2020-12-16 14:19:37 -08:00
/// let (descriptor, key_map, networks) = bdk::descriptor!(wpkh(my_key))?;
2020-09-19 12:08:30 +02:00
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
2020-09-16 14:32:55 +02:00
#[ macro_export ]
2020-09-18 16:31:03 +02:00
macro_rules ! descriptor {
2020-09-16 14:32:55 +02:00
( bare ( $( $minisc :tt ) * ) ) = > ( {
2021-02-02 20:06:40 -05:00
$crate ::impl_top_level_sh! ( Bare , new , new , Legacy , $( $minisc ) * )
2020-09-16 14:32:55 +02:00
} ) ;
( sh ( wsh ( $( $minisc :tt ) * ) ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::descriptor! ( shwsh ( $( $minisc ) * ) )
2020-09-16 14:32:55 +02:00
} ) ;
( shwsh ( $( $minisc :tt ) * ) ) = > ( {
2021-02-02 20:06:40 -05:00
$crate ::impl_top_level_sh! ( Sh , new_wsh , new_wsh_sortedmulti , Segwitv0 , $( $minisc ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( pk ( $key :expr ) ) = > ( {
2021-02-02 20:06:40 -05:00
// `pk()` is actually implemented as `bare(pk())`
$crate ::descriptor! ( bare ( pk ( $key ) ) )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( pkh ( $key :expr ) ) = > ( {
2021-02-02 20:06:40 -05:00
use $crate ::miniscript ::descriptor ::{ Descriptor , DescriptorPublicKey } ;
$crate ::impl_top_level_pk! ( Pkh , $crate ::miniscript ::Legacy , $key )
. map ( | ( a , b , c ) | ( Descriptor ::< DescriptorPublicKey > ::Pkh ( a ) , b , c ) )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( wpkh ( $key :expr ) ) = > ( {
2021-02-02 20:06:40 -05:00
use $crate ::miniscript ::descriptor ::{ Descriptor , DescriptorPublicKey } ;
2020-09-19 12:08:30 +02:00
$crate ::impl_top_level_pk! ( Wpkh , $crate ::miniscript ::Segwitv0 , $key )
2021-02-02 20:06:40 -05:00
. and_then ( | ( a , b , c ) | Ok ( ( a ? , b , c ) ) )
. map ( | ( a , b , c ) | ( Descriptor ::< DescriptorPublicKey > ::Wpkh ( a ) , b , c ) )
2020-09-16 14:32:55 +02:00
} ) ;
( sh ( wpkh ( $key :expr ) ) ) = > ( {
2020-09-22 16:12:09 +02:00
$crate ::descriptor! ( shwpkh ( $key ) )
2020-09-16 14:32:55 +02:00
} ) ;
( shwpkh ( $key :expr ) ) = > ( {
2021-02-02 20:06:40 -05:00
use $crate ::miniscript ::descriptor ::{ Descriptor , DescriptorPublicKey , Sh } ;
$crate ::impl_top_level_pk! ( Wpkh , $crate ::miniscript ::Segwitv0 , $key )
. and_then ( | ( a , b , c ) | Ok ( ( a ? , b , c ) ) )
. and_then ( | ( a , b , c ) | Ok ( ( Descriptor ::< DescriptorPublicKey > ::Sh ( Sh ::new_wpkh ( a . into_inner ( ) ) ? ) , b , c ) ) )
2020-09-16 14:32:55 +02:00
} ) ;
( sh ( $( $minisc :tt ) * ) ) = > ( {
2021-02-02 20:06:40 -05:00
$crate ::impl_top_level_sh! ( Sh , new , new_sortedmulti , Legacy , $( $minisc ) * )
2020-09-16 14:32:55 +02:00
} ) ;
( wsh ( $( $minisc :tt ) * ) ) = > ( {
2021-02-02 20:06:40 -05:00
$crate ::impl_top_level_sh! ( Wsh , new , new_sortedmulti , Segwitv0 , $( $minisc ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-09-18 16:31:03 +02:00
}
2020-09-16 14:32:55 +02:00
2020-12-16 16:10:22 +01:00
#[ doc(hidden) ]
pub struct TupleTwo < A , B > {
pub a : A ,
pub b : B ,
}
impl < A , B > TupleTwo < A , B > {
pub fn flattened ( self ) -> ( A , B ) {
( self . a , self . b )
}
}
impl < A , B > From < ( A , ( B , ( ) ) ) > for TupleTwo < A , B > {
fn from ( ( a , ( b , _ ) ) : ( A , ( B , ( ) ) ) ) -> Self {
TupleTwo { a , b }
}
}
#[ doc(hidden) ]
pub struct TupleThree < A , B , C > {
pub a : A ,
pub b : B ,
pub c : C ,
}
impl < A , B , C > TupleThree < A , B , C > {
pub fn flattened ( self ) -> ( A , B , C ) {
( self . a , self . b , self . c )
}
}
impl < A , B , C > From < ( A , ( B , ( C , ( ) ) ) ) > for TupleThree < A , B , C > {
fn from ( ( a , ( b , ( c , _ ) ) ) : ( A , ( B , ( C , ( ) ) ) ) ) -> Self {
TupleThree { a , b , c }
}
}
#[ doc(hidden) ]
2020-09-18 16:31:03 +02:00
#[ macro_export ]
2020-12-16 16:10:22 +01:00
macro_rules ! fragment_internal {
// The @v prefix is used to parse a sequence of operands and return them in a vector. This is
// used by operands that take a variable number of arguments, like `thresh()` and `multi()`.
( @ v $op :ident ( $( $args :tt ) * ) $( $tail :tt ) * ) = > ( {
let mut v = vec! [ $crate ::fragment! ( $op ( $( $args ) * ) ) ] ;
v . append ( & mut $crate ::fragment_internal! ( @ v $( $tail ) * ) ) ;
v
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
// Match modifiers
( @ v $modif :tt : $( $tail :tt ) * ) = > ( {
let mut v = $crate ::fragment_internal! ( @ v $( $tail ) * ) ;
let first = v . drain ( .. 1 ) . next ( ) . unwrap ( ) ;
let first = $crate ::apply_modifier! ( $modif :first ) ;
let mut v_final = vec! [ first ] ;
v_final . append ( & mut v ) ;
v_final
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
// Remove commas between operands
( @ v , $( $tail :tt ) * ) = > ( {
$crate ::fragment_internal! ( @ v $( $tail ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( @ v ) = > ( {
vec! [ ]
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
// The @t prefix is used to parse a sequence of operands and return them in a tuple. This
// allows checking at compile-time the number of arguments passed to an operand. For this
// reason it's used by `and_*()`, `or_*()`, etc.
//
// Unfortunately, due to the fact that concatenating tuples is pretty hard, the final result
// adds in the first spot the parsed operand and in the second spot the result of parsing
// all the following ones. For two operands the type then corresponds to: (X, (X, ())). For
// three operands it's (X, (X, (X, ()))), etc.
//
// To check that the right number of arguments has been passed we can "cast" those tuples to
// more convenient structures like `TupleTwo`. If the conversion succedes, the right number of
// args was passed. Otherwise the compilation fails entirely.
( @ t $op :ident ( $( $args :tt ) * ) $( $tail :tt ) * ) = > ( {
( $crate ::fragment! ( $op ( $( $args ) * ) ) , $crate ::fragment_internal! ( @ t $( $tail ) * ) )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
// Match modifiers
( @ t $modif :tt : $( $tail :tt ) * ) = > ( {
let ( first , tail ) = $crate ::fragment_internal! ( @ t $( $tail ) * ) ;
( $crate ::apply_modifier! ( $modif :first ) , tail )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
// Remove commas between operands
( @ t , $( $tail :tt ) * ) = > ( {
$crate ::fragment_internal! ( @ t $( $tail ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( @ t ) = > ( {
( )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
// Fallback to calling `fragment!()`
( $( $tokens :tt ) * ) = > ( {
$crate ::fragment! ( $( $tokens ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
}
/// Macro to write descriptor fragments with code
///
2021-01-11 13:12:01 +01:00
/// This macro will be expanded to an object of type `Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), DescriptorError>`. It allows writing
2020-12-16 16:10:22 +01:00
/// fragments of larger descriptors that can be pieced together using `fragment!(thresh_vec(m, ...))`.
///
/// The syntax to write macro fragment is the same as documented for the [`descriptor`] macro.
#[ macro_export ]
macro_rules ! fragment {
// Modifiers
( $modif :tt : $( $tail :tt ) * ) = > ( {
let op = $crate ::fragment! ( $( $tail ) * ) ;
$crate ::apply_modifier! ( $modif :op )
2020-09-16 14:32:55 +02:00
} ) ;
// Miniscript
( true ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode! ( True )
2020-09-16 14:32:55 +02:00
} ) ;
( false ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode! ( False )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( pk_k ( $key :expr ) ) = > ( {
2020-11-16 22:07:38 +01:00
let secp = $crate ::bitcoin ::secp256k1 ::Secp256k1 ::new ( ) ;
$crate ::keys ::make_pk ( $key , & secp )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( pk ( $key :expr ) ) = > ( {
$crate ::fragment! ( c :pk_k ( $key ) )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( pk_h ( $key_hash :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( PkH , $key_hash )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( after ( $value :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( After , $value )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( older ( $value :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( Older , $value )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( sha256 ( $hash :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( Sha256 , $hash )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( hash256 ( $hash :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( Hash256 , $hash )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( ripemd160 ( $hash :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( Ripemd160 , $hash )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( hash160 ( $hash :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
$crate ::impl_leaf_opcode_value! ( Hash160 , $hash )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( and_v ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_two! ( AndV , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( and_b ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_two! ( AndB , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( and_or ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_three! ( AndOr , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( or_b ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_two! ( OrB , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( or_d ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_two! ( OrD , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( or_c ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_two! ( OrC , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( or_i ( $( $inner :tt ) * ) ) = > ( {
$crate ::impl_node_opcode_two! ( OrI , $( $inner ) * )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( thresh_vec ( $thresh :expr , $items :expr ) ) = > ( {
2020-09-18 16:31:03 +02:00
use $crate ::miniscript ::descriptor ::KeyMap ;
2020-09-21 15:44:07 +02:00
let ( items , key_maps_networks ) : ( Vec < _ > , Vec < _ > ) = $items . into_iter ( ) . map ( | ( a , b , c ) | ( a , ( b , c ) ) ) . unzip ( ) ;
2020-09-18 16:31:03 +02:00
let items = items . into_iter ( ) . map ( std ::sync ::Arc ::new ) . collect ( ) ;
2020-09-21 15:44:07 +02:00
let ( key_maps , valid_networks ) = key_maps_networks . into_iter ( ) . fold ( ( KeyMap ::default ( ) , $crate ::keys ::any_network ( ) ) , | ( mut keys_acc , net_acc ) , ( key , net ) | {
keys_acc . extend ( key . into_iter ( ) ) ;
let net_acc = $crate ::keys ::merge_networks ( & net_acc , & net ) ;
( keys_acc , net_acc )
2020-09-18 16:31:03 +02:00
} ) ;
$crate ::impl_leaf_opcode_value_two! ( Thresh , $thresh , items )
2020-09-21 15:44:07 +02:00
. map ( | ( minisc , _ , _ ) | ( minisc , key_maps , valid_networks ) )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( thresh ( $thresh :expr , $( $inner :tt ) * ) ) = > ( {
let items = $crate ::fragment_internal! ( @ v $( $inner ) * ) ;
2020-09-16 14:32:55 +02:00
2020-09-18 16:31:03 +02:00
items . into_iter ( ) . collect ::< Result < Vec < _ > , _ > > ( )
2020-12-16 16:10:22 +01:00
. and_then ( | items | $crate ::fragment! ( thresh_vec ( $thresh , items ) ) )
2020-09-18 16:31:03 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( multi_vec ( $thresh :expr , $keys :expr ) ) = > ( {
2020-09-19 12:08:30 +02:00
$crate ::keys ::make_multi ( $thresh , $keys )
2020-09-16 14:32:55 +02:00
} ) ;
2020-12-16 16:10:22 +01:00
( multi ( $thresh :expr $(, $key :expr ) + ) ) = > ( {
2020-09-18 17:26:58 +02:00
use $crate ::keys ::ToDescriptorKey ;
2020-11-16 22:07:38 +01:00
let secp = $crate ::bitcoin ::secp256k1 ::Secp256k1 ::new ( ) ;
2020-09-18 17:26:58 +02:00
2020-09-18 16:31:03 +02:00
let mut keys = vec! [ ] ;
$(
2021-02-11 11:00:48 -08:00
keys . push ( $key . into_descriptor_key ( ) ) ;
2020-09-18 16:31:03 +02:00
) *
2020-09-18 17:26:58 +02:00
keys . into_iter ( ) . collect ::< Result < Vec < _ > , _ > > ( )
2021-01-11 13:12:01 +01:00
. map_err ( $crate ::descriptor ::DescriptorError ::Key )
2020-11-16 22:07:38 +01:00
. and_then ( | keys | $crate ::keys ::make_multi ( $thresh , keys , & secp ) )
2020-09-16 14:32:55 +02:00
} ) ;
2020-09-18 16:31:03 +02:00
2020-11-17 23:40:31 +01:00
// `sortedmulti()` is handled separately
2020-12-16 16:10:22 +01:00
( sortedmulti ( $( $inner :tt ) * ) ) = > ( {
2020-11-17 23:40:31 +01:00
compile_error! ( " `sortedmulti` can only be used as the root operand of a descriptor " ) ;
} ) ;
2020-12-16 16:10:22 +01:00
( sortedmulti_vec ( $( $inner :tt ) * ) ) = > ( {
2020-11-17 23:40:31 +01:00
compile_error! ( " `sortedmulti_vec` can only be used as the root operand of a descriptor " ) ;
} ) ;
2020-09-16 14:32:55 +02:00
}
2020-10-03 14:48:13 -07:00
2020-10-12 09:09:25 -07:00
#[ cfg(test) ]
mod test {
use bitcoin ::hashes ::hex ::ToHex ;
2020-11-16 22:07:38 +01:00
use bitcoin ::secp256k1 ::Secp256k1 ;
2021-02-02 20:06:40 -05:00
use miniscript ::descriptor ::{ DescriptorPublicKey , DescriptorTrait , KeyMap } ;
2020-10-12 09:09:25 -07:00
use miniscript ::{ Descriptor , Legacy , Segwitv0 } ;
use std ::str ::FromStr ;
2021-01-11 13:12:01 +01:00
use crate ::descriptor ::{ DescriptorError , DescriptorMeta } ;
use crate ::keys ::{ DescriptorKey , ToDescriptorKey , ValidNetworks } ;
2021-02-05 10:23:17 -05:00
use bitcoin ::network ::constants ::Network ::{ Bitcoin , Regtest , Signet , Testnet } ;
2020-10-12 09:09:25 -07:00
use bitcoin ::util ::bip32 ;
2020-12-16 16:10:22 +01:00
use bitcoin ::PrivateKey ;
2020-10-12 09:09:25 -07:00
2021-02-02 20:06:40 -05:00
use crate ::descriptor ::derived ::AsDerived ;
2020-10-12 09:09:25 -07:00
// test the descriptor!() macro
// verify descriptor generates expected script(s) (if bare or pk) or address(es)
fn check (
2021-01-11 13:12:01 +01:00
desc : Result < ( Descriptor < DescriptorPublicKey > , KeyMap , ValidNetworks ) , DescriptorError > ,
2020-10-12 09:09:25 -07:00
is_witness : bool ,
is_fixed : bool ,
expected : & [ & str ] ,
) {
2020-11-16 22:07:38 +01:00
let secp = Secp256k1 ::new ( ) ;
2020-10-12 09:09:25 -07:00
let ( desc , _key_map , _networks ) = desc . unwrap ( ) ;
assert_eq! ( desc . is_witness ( ) , is_witness ) ;
2021-02-02 20:06:40 -05:00
assert_eq! ( ! desc . is_deriveable ( ) , is_fixed ) ;
2020-10-12 09:09:25 -07:00
for i in 0 .. expected . len ( ) {
let index = i as u32 ;
2021-02-02 20:06:40 -05:00
let child_desc = if ! desc . is_deriveable ( ) {
desc . as_derived_fixed ( & secp )
2020-10-12 09:09:25 -07:00
} else {
2021-02-02 20:06:40 -05:00
desc . as_derived ( index , & secp )
2020-10-12 09:09:25 -07:00
} ;
2021-02-02 20:06:40 -05:00
let address = child_desc . address ( Regtest ) ;
if let Ok ( address ) = address {
2020-11-17 23:40:31 +01:00
assert_eq! ( address . to_string ( ) , * expected . get ( i ) . unwrap ( ) ) ;
2020-10-12 09:09:25 -07:00
} else {
2021-02-02 20:06:40 -05:00
let script = child_desc . script_pubkey ( ) ;
2020-10-12 09:09:25 -07:00
assert_eq! ( script . to_hex ( ) . as_str ( ) , * expected . get ( i ) . unwrap ( ) ) ;
}
}
}
// - at least one of each "type" of operator; ie. one modifier, one leaf_opcode, one leaf_opcode_value, etc.
// - mixing up key types that implement ToDescriptorKey in multi() or thresh()
// expected script for pk and bare manually created
// expected addresses created with `bitcoin-cli getdescriptorinfo` (for hash) and `bitcoin-cli deriveaddresses`
#[ test ]
fn test_fixed_legacy_descriptors ( ) {
let pubkey1 = bitcoin ::PublicKey ::from_str (
" 03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd " ,
)
. unwrap ( ) ;
let pubkey2 = bitcoin ::PublicKey ::from_str (
" 032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af " ,
)
. unwrap ( ) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( bare ( multi ( 1 , pubkey1 , pubkey2 ) ) ) ,
2020-10-12 09:09:25 -07:00
false ,
true ,
& [ " 512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af52ae " ] ,
) ;
check (
descriptor! ( pk ( pubkey1 ) ) ,
false ,
true ,
& [ " 2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac " ] ,
) ;
check (
descriptor! ( pkh ( pubkey1 ) ) ,
false ,
true ,
& [ " muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi " ] ,
) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( multi ( 1 , pubkey1 , pubkey2 ) ) ) ,
2020-10-12 09:09:25 -07:00
false ,
true ,
& [ " 2MymURoV1bzuMnWMGiXzyomDkeuxXY7Suey " ] ,
) ;
}
#[ test ]
fn test_fixed_segwitv0_descriptors ( ) {
let pubkey1 = bitcoin ::PublicKey ::from_str (
" 03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd " ,
)
. unwrap ( ) ;
let pubkey2 = bitcoin ::PublicKey ::from_str (
" 032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af " ,
)
. unwrap ( ) ;
check (
descriptor! ( wpkh ( pubkey1 ) ) ,
true ,
true ,
& [ " bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h " ] ,
) ;
check (
descriptor! ( sh ( wpkh ( pubkey1 ) ) ) ,
true ,
true ,
& [ " 2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb " ] ,
) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( wsh ( multi ( 1 , pubkey1 , pubkey2 ) ) ) ,
2020-10-12 09:09:25 -07:00
true ,
true ,
& [ " bcrt1qgw8jvv2hsrvjfa6q66rk6har7d32lrqm5unnf5cl63q9phxfvgps5fyfqe " ] ,
) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( wsh ( multi ( 1 , pubkey1 , pubkey2 ) ) ) ) ,
2020-10-12 09:09:25 -07:00
true ,
true ,
& [ " 2NCidRJysy7apkmE6JF5mLLaJFkrN3Ub9iy " ] ,
) ;
}
#[ test ]
fn test_bip32_legacy_descriptors ( ) {
let xprv = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy " ) . unwrap ( ) ;
let path = bip32 ::DerivationPath ::from_str ( " m/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
descriptor! ( pk ( desc_key ) ) ,
false ,
false ,
& [
" 2102363ad03c10024e1b597a5b01b9982807fb638e00b06f3b2d4a89707de3b93c37ac " ,
" 2102063a21fd780df370ed2fc8c4b86aa5ea642630609c203009df631feb7b480dd2ac " ,
" 2102ba2685ad1fa5891cb100f1656b2ce3801822ccb9bac0336734a6f8c1b93ebbc0ac " ,
] ,
) ;
2021-02-11 11:00:48 -08:00
let desc_key = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
descriptor! ( pkh ( desc_key ) ) ,
false ,
false ,
& [
" muvBdsVpJxpFuTHMKA47htJPdCvdt4F9DP " ,
" mxQSHK7DL2t1DN3xFxov1janCoXSSkrSPj " ,
" mfz43r15GiWo4nizmyzMNubsnkDpByFFAn " ,
] ,
) ;
let path2 = bip32 ::DerivationPath ::from_str ( " m/2147483647'/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key1 = ( xprv , path ) . into_descriptor_key ( ) . unwrap ( ) ;
let desc_key2 = ( xprv , path2 ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( multi ( 1 , desc_key1 , desc_key2 ) ) ) ,
2020-10-12 09:09:25 -07:00
false ,
false ,
& [
" 2MtMDXsfwefZkEEhVViEPidvcKRUtJamJJ8 " ,
" 2MwAUZ1NYyWjhVvGTethFL6n7nZhS8WE6At " ,
" 2MuT6Bj66HLwZd7s4SoD8XbK4GwriKEA6Gr " ,
] ,
) ;
}
#[ test ]
fn test_bip32_segwitv0_descriptors ( ) {
let xprv = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy " ) . unwrap ( ) ;
let path = bip32 ::DerivationPath ::from_str ( " m/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
descriptor! ( wpkh ( desc_key ) ) ,
true ,
false ,
& [
" bcrt1qnhm8w9fhc8cxzgqsmqdf9fyjccyvc0gltnymu0 " ,
" bcrt1qhylfd55rn75w9fj06zspctad5w4hz33rf0ttad " ,
" bcrt1qq5sq3a6k9av9d8cne0k9wcldy4nqey5yt6889r " ,
] ,
) ;
2021-02-11 11:00:48 -08:00
let desc_key = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
descriptor! ( sh ( wpkh ( desc_key ) ) ) ,
true ,
false ,
& [
" 2MxvjQCaLqZ5QxZ7XotZDQ63hZw3NPss763 " ,
" 2NDUoevN4QMzhvHDMGhKuiT2fN9HXbFRMwn " ,
" 2NF4BEAY2jF1Fu8vqfN3NVKoFtom77pUxrx " ,
] ,
) ;
let path2 = bip32 ::DerivationPath ::from_str ( " m/2147483647'/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key1 = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
let desc_key2 = ( xprv , path2 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
2020-12-16 16:10:22 +01:00
descriptor! ( wsh ( multi ( 1 , desc_key1 , desc_key2 ) ) ) ,
2020-10-12 09:09:25 -07:00
true ,
false ,
& [
" bcrt1qfxv8mxmlv5sz8q2mnuyaqdfe9jr4vvmx0csjhn092p6f4qfygfkq2hng49 " ,
" bcrt1qerj85g243e6jlcdxpmn9spk0gefcwvu7nw7ee059d5ydzpdhkm2qwfkf5k " ,
" bcrt1qxkl2qss3k58q9ktc8e89pwr4gnptfpw4hju4xstxcjc0hkcae3jstluty7 " ,
] ,
) ;
2021-02-11 11:00:48 -08:00
let desc_key1 = ( xprv , path ) . into_descriptor_key ( ) . unwrap ( ) ;
let desc_key2 = ( xprv , path2 ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
check (
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( wsh ( multi ( 1 , desc_key1 , desc_key2 ) ) ) ) ,
2020-10-12 09:09:25 -07:00
true ,
false ,
& [
" 2NFCtXvx9q4ci2kvKub17iSTgvRXGctCGhz " ,
" 2NB2PrFPv5NxWCpygas8tPrGJG2ZFgeuwJw " ,
" 2N79ZAGo5cMi5Jt7Wo9L5YmF5GkEw7sjWdC " ,
] ,
) ;
}
2020-11-17 23:40:31 +01:00
#[ test ]
fn test_dsl_sortedmulti ( ) {
let key_1 = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy " ) . unwrap ( ) ;
let path_1 = bip32 ::DerivationPath ::from_str ( " m/0 " ) . unwrap ( ) ;
let key_2 = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF " ) . unwrap ( ) ;
let path_2 = bip32 ::DerivationPath ::from_str ( " m/1 " ) . unwrap ( ) ;
let desc_key1 = ( key_1 , path_1 ) ;
let desc_key2 = ( key_2 , path_2 ) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( sortedmulti ( 1 , desc_key1 . clone ( ) , desc_key2 . clone ( ) ) ) ) ,
2020-11-17 23:40:31 +01:00
false ,
false ,
& [
" 2MsxzPEJDBzpGffJXPaDpfXZAUNnZhaMh2N " ,
" 2My3x3DLPK3UbGWGpxrXr1RnbD8MNC4FpgS " ,
" 2NByEuiQT7YLqHCTNxL5KwYjvtuCYcXNBSC " ,
" 2N1TGbP81kj2VUKTSWgrwxoMfuWjvfUdyu7 " ,
" 2N3Bomq2fpAcLRNfZnD3bCWK9quan28CxCR " ,
" 2N9nrZaEzEFDqEAU9RPvDnXGT6AVwBDKAQb " ,
] ,
) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( wsh ( sortedmulti (
1 ,
desc_key1 . clone ( ) ,
desc_key2 . clone ( )
) ) ) ) ,
2020-11-17 23:40:31 +01:00
true ,
false ,
& [
" 2NCogc5YyM4N6ruv1hUa7WLMW1BPeCK7N9B " ,
" 2N6mkSAKi1V2oaBXby7XHdvBMKEDRQcFpNe " ,
" 2NFmTSttm9v6bXeoWaBvpMcgfPQcZhNn3Eh " ,
" 2Mvib87RBPUHXNEpX5S5Kv1qqrhBfgBGsJM " ,
" 2MtMv5mcK2EjcLsH8Txpx2JxLLzHr4ttczL " ,
" 2MsWCB56rb4T6yPv8QudZGHERTwNgesE4f6 " ,
] ,
) ;
check (
2020-12-16 16:10:22 +01:00
descriptor! ( wsh ( sortedmulti_vec ( 1 , vec! [ desc_key1 , desc_key2 ] ) ) ) ,
2020-11-17 23:40:31 +01:00
true ,
false ,
& [
" bcrt1qcvq0lg8q7a47ytrd7zk5y7uls7mulrenjgvflwylpppgwf8029es4vhpnj " ,
" bcrt1q80yn8sdt6l7pjvkz25lglyaqctlmsq9ugk80rmxt8yu0npdsj97sc7l4de " ,
" bcrt1qrvf6024v9s50qhffe3t2fr2q9ckdhx2g6jz32chm2pp24ymgtr5qfrdmct " ,
" bcrt1q6srfmra0ynypym35c7jvsxt2u4yrugeajq95kg2ps7lk6h2gaunsq9lzxn " ,
" bcrt1qhl8rrzzcdpu7tcup3lcg7tge52sqvwy5fcv4k78v6kxtwmqf3v6qpvyjza " ,
" bcrt1ql2elz9mhm9ll27ddpewhxs732xyl2fk2kpkqz9gdyh33wgcun4vstrd49k " ,
] ,
) ;
}
2020-10-12 09:09:25 -07:00
// - verify the valid_networks returned is correctly computed based on the keys present in the descriptor
#[ test ]
fn test_valid_networks ( ) {
let xprv = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy " ) . unwrap ( ) ;
let path = bip32 ::DerivationPath ::from_str ( " m/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let ( _desc , _key_map , valid_networks ) = descriptor! ( pkh ( desc_key ) ) . unwrap ( ) ;
2021-02-05 10:23:17 -05:00
assert_eq! (
valid_networks ,
[ Testnet , Regtest , Signet ] . iter ( ) . cloned ( ) . collect ( )
) ;
2020-10-12 09:09:25 -07:00
let xprv = bip32 ::ExtendedPrivKey ::from_str ( " xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi " ) . unwrap ( ) ;
let path = bip32 ::DerivationPath ::from_str ( " m/10/20/30/40 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let ( _desc , _key_map , valid_networks ) = descriptor! ( wpkh ( desc_key ) ) . unwrap ( ) ;
assert_eq! ( valid_networks , [ Bitcoin ] . iter ( ) . cloned ( ) . collect ( ) ) ;
}
// - verify the key_maps are correctly merged together
#[ test ]
fn test_key_maps_merged ( ) {
2020-11-16 22:07:38 +01:00
let secp = Secp256k1 ::new ( ) ;
2020-10-12 09:09:25 -07:00
let xprv1 = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy " ) . unwrap ( ) ;
let path1 = bip32 ::DerivationPath ::from_str ( " m/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key1 = ( xprv1 , path1 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let xprv2 = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF " ) . unwrap ( ) ;
let path2 = bip32 ::DerivationPath ::from_str ( " m/2147483647'/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key2 = ( xprv2 , path2 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let xprv3 = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf " ) . unwrap ( ) ;
let path3 = bip32 ::DerivationPath ::from_str ( " m/10/20/30/40 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key3 = ( xprv3 , path3 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let ( _desc , key_map , _valid_networks ) =
2020-12-16 16:10:22 +01:00
descriptor! ( sh ( wsh ( multi ( 2 , desc_key1 , desc_key2 , desc_key3 ) ) ) ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
assert_eq! ( key_map . len ( ) , 3 ) ;
let desc_key1 : DescriptorKey < Segwitv0 > =
2021-02-11 11:00:48 -08:00
( xprv1 , path1 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let desc_key2 : DescriptorKey < Segwitv0 > =
2021-02-11 11:00:48 -08:00
( xprv2 , path2 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let desc_key3 : DescriptorKey < Segwitv0 > =
2021-02-11 11:00:48 -08:00
( xprv3 , path3 . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
2020-11-16 22:07:38 +01:00
let ( key1 , _key_map , _valid_networks ) = desc_key1 . extract ( & secp ) . unwrap ( ) ;
let ( key2 , _key_map , _valid_networks ) = desc_key2 . extract ( & secp ) . unwrap ( ) ;
let ( key3 , _key_map , _valid_networks ) = desc_key3 . extract ( & secp ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
assert_eq! ( key_map . get ( & key1 ) . unwrap ( ) . to_string ( ) , " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/0/* " ) ;
assert_eq! ( key_map . get ( & key2 ) . unwrap ( ) . to_string ( ) , " tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF/2147483647'/0/* " ) ;
assert_eq! ( key_map . get ( & key3 ) . unwrap ( ) . to_string ( ) , " tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf/10/20/30/40/* " ) ;
}
// - verify the ScriptContext is correctly validated (i.e. passing a type that only impl ToDescriptorKey<Segwitv0> to a pkh() descriptor should throw a compilation error
#[ test ]
fn test_script_context_validation ( ) {
// this compiles
let xprv = bip32 ::ExtendedPrivKey ::from_str ( " tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy " ) . unwrap ( ) ;
let path = bip32 ::DerivationPath ::from_str ( " m/0 " ) . unwrap ( ) ;
2021-02-11 11:00:48 -08:00
let desc_key : DescriptorKey < Legacy > = ( xprv , path . clone ( ) ) . into_descriptor_key ( ) . unwrap ( ) ;
2020-10-12 09:09:25 -07:00
let ( desc , _key_map , _valid_networks ) = descriptor! ( pkh ( desc_key ) ) . unwrap ( ) ;
2021-02-02 20:06:40 -05:00
assert_eq! ( desc . to_string ( ) , " pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)#yrnz9pp2 " ) ;
2020-10-12 09:09:25 -07:00
// as expected this does not compile due to invalid context
2021-02-11 11:00:48 -08:00
//let desc_key:DescriptorKey<Segwitv0> = (xprv, path.clone()).into_descriptor_key().unwrap();
2020-10-12 09:09:25 -07:00
//let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
}
2020-12-16 16:10:22 +01:00
#[ test ]
fn test_dsl_modifiers ( ) {
let private_key =
PrivateKey ::from_wif ( " cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR " ) . unwrap ( ) ;
let ( descriptor , _ , _ ) =
descriptor! ( wsh ( thresh ( 2 , d :v :older ( 1 ) , s :pk ( private_key ) , s :pk ( private_key ) ) ) ) . unwrap ( ) ;
2021-02-02 20:06:40 -05:00
assert_eq! ( descriptor . to_string ( ) , " wsh(thresh(2,dv:older(1),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)))#cfdcqs3s " )
2020-12-16 16:10:22 +01:00
}
2021-01-11 13:12:01 +01:00
2021-02-02 20:06:40 -05:00
#[ test ]
#[ should_panic(expected = " Miniscript(ContextError(CompressedOnly)) " ) ]
fn test_dsl_miniscript_checks ( ) {
let mut uncompressed_pk =
PrivateKey ::from_wif ( " L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6 " ) . unwrap ( ) ;
uncompressed_pk . compressed = false ;
descriptor! ( wsh ( v : pk ( uncompressed_pk ) ) ) . unwrap ( ) ;
}
2020-10-12 09:09:25 -07:00
}