diff --git a/src/descriptor/dsl.rs b/src/descriptor/dsl.rs
index 4296b4d9..34081ab1 100644
--- a/src/descriptor/dsl.rs
+++ b/src/descriptor/dsl.rs
@@ -577,6 +577,23 @@ impl From<(A, (B, (C, ())))> for TupleThree {
}
}
+#[doc(hidden)]
+#[macro_export]
+macro_rules! group_multi_keys {
+ ( $( $key:expr ),+ ) => {{
+ use $crate::keys::IntoDescriptorKey;
+
+ let keys = vec![
+ $(
+ $key.into_descriptor_key(),
+ )*
+ ];
+
+ keys.into_iter().collect::, _>>()
+ .map_err($crate::descriptor::DescriptorError::Key)
+ }};
+}
+
#[doc(hidden)]
#[macro_export]
macro_rules! fragment_internal {
@@ -737,21 +754,22 @@ macro_rules! fragment {
.and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
});
( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
- $crate::keys::make_multi($thresh, $keys)
- });
- ( multi ( $thresh:expr $(, $key:expr )+ ) ) => ({
- use $crate::keys::IntoDescriptorKey;
let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
- let keys = vec![
- $(
- $key.into_descriptor_key(),
- )*
- ];
+ $crate::keys::make_multi($thresh, $crate::miniscript::Terminal::Multi, $keys, &secp)
+ });
+ ( multi ( $thresh:expr $(, $key:expr )+ ) ) => ({
+ $crate::group_multi_keys!( $( $key ),* )
+ .and_then(|keys| $crate::fragment!( multi_vec ( $thresh, keys ) ))
+ });
+ ( multi_a_vec ( $thresh:expr, $keys:expr ) ) => ({
+ let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
- keys.into_iter().collect::, _>>()
- .map_err($crate::descriptor::DescriptorError::Key)
- .and_then(|keys| $crate::keys::make_multi($thresh, keys, &secp))
+ $crate::keys::make_multi($thresh, $crate::miniscript::Terminal::MultiA, $keys, &secp)
+ });
+ ( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => ({
+ $crate::group_multi_keys!( $( $key ),* )
+ .and_then(|keys| $crate::fragment!( multi_a_vec ( $thresh, keys ) ))
});
// `sortedmulti()` is handled separately
diff --git a/src/keys/mod.rs b/src/keys/mod.rs
index 320cca1f..20ff5818 100644
--- a/src/keys/mod.rs
+++ b/src/keys/mod.rs
@@ -792,13 +792,18 @@ pub fn make_pkh, Ctx: ScriptContext>(
// Used internally by `bdk::fragment!` to build `multi()` fragments
#[doc(hidden)]
-pub fn make_multi, Ctx: ScriptContext>(
+pub fn make_multi<
+ Pk: IntoDescriptorKey,
+ Ctx: ScriptContext,
+ V: Fn(usize, Vec) -> Terminal,
+>(
thresh: usize,
+ variant: V,
pks: Vec,
secp: &SecpCtx,
) -> Result<(Miniscript, KeyMap, ValidNetworks), DescriptorError> {
let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
- let minisc = Miniscript::from_ast(Terminal::Multi(thresh, pks))?;
+ let minisc = Miniscript::from_ast(variant(thresh, pks))?;
minisc.check_miniscript()?;