miniscript/pub_macros.rs
1// SPDX-License-Identifier: CC0-1.0
2
3//! Macros exported by the miniscript crate
4//!
5
6/// Macro for failing translation for other associated types.
7/// Handy for testing String -> concrete keys as we don't want to specify these
8/// functions repeatedly.
9///
10/// This macro is handy when dealing with scripts that are only contain keys.
11/// See also [`crate::translate_hash_clone`]
12/// ```rust
13/// use miniscript::{bitcoin::PublicKey, policy::concrete::Policy, Translator, hash256};
14/// use std::str::FromStr;
15/// use miniscript::translate_hash_fail;
16/// use std::collections::HashMap;
17/// use miniscript::bitcoin::hashes::{sha256, hash160, ripemd160};
18/// let alice_key = "0270cf3c71f65a3d93d285d9149fddeeb638f87a2d4d8cf16c525f71c417439777";
19/// let bob_key = "02f43b15c50a436f5335dbea8a64dd3b4e63e34c3b50c42598acb5f4f336b5d2fb";
20/// let placeholder_policy = Policy::<String>::from_str("and(pk(alice_key),pk(bob_key))").unwrap();
21///
22/// // Information to translator abstract String type keys to concrete bitcoin::PublicKey.
23/// // In practice, wallets would map from String key names to BIP32 keys
24/// struct StrPkTranslator {
25/// pk_map: HashMap<String, bitcoin::PublicKey>
26/// }
27///
28/// // If we also wanted to provide mapping of other associated types(sha256, older etc),
29/// // we would use the general Translator Trait.
30/// impl Translator<String, bitcoin::PublicKey, ()> for StrPkTranslator {
31/// // Provides the translation public keys P -> Q
32/// fn pk(&mut self, pk: &String) -> Result<bitcoin::PublicKey, ()> {
33/// self.pk_map.get(pk).copied().ok_or(()) // Dummy Err
34/// }
35///
36/// // Fail for hash types
37/// translate_hash_fail!(String, bitcoin::PublicKey, ());
38/// }
39///
40/// let mut pk_map = HashMap::new();
41/// pk_map.insert(String::from("alice_key"), bitcoin::PublicKey::from_str(alice_key).unwrap());
42/// pk_map.insert(String::from("bob_key"), bitcoin::PublicKey::from_str(bob_key).unwrap());
43/// let mut t = StrPkTranslator { pk_map: pk_map };
44/// ```
45#[macro_export]
46macro_rules! translate_hash_fail {
47 ($source: ty, $target:ty, $error_ty: ty) => {
48 fn sha256(
49 &mut self,
50 _sha256: &<$source as $crate::MiniscriptKey>::Sha256,
51 ) -> Result<<$target as $crate::MiniscriptKey>::Sha256, $error_ty> {
52 panic!("Called sha256 on translate_only_pk")
53 }
54
55 fn hash256(
56 &mut self,
57 _hash256: &<$source as $crate::MiniscriptKey>::Hash256,
58 ) -> Result<<$target as $crate::MiniscriptKey>::Hash256, $error_ty> {
59 panic!("Called hash256 on translate_only_pk")
60 }
61
62 fn hash160(
63 &mut self,
64 _hash160: &<$source as $crate::MiniscriptKey>::Hash160,
65 ) -> Result<<$target as $crate::MiniscriptKey>::Hash160, $error_ty> {
66 panic!("Called hash160 on translate_only_pk")
67 }
68
69 fn ripemd160(
70 &mut self,
71 _ripemd160: &<$source as $crate::MiniscriptKey>::Ripemd160,
72 ) -> Result<<$target as $crate::MiniscriptKey>::Ripemd160, $error_ty> {
73 panic!("Called ripemd160 on translate_only_pk")
74 }
75 };
76}
77
78/// Macro for translation of associated types where the associated type is the same
79/// Handy for Derived -> concrete keys where the associated types are the same.
80///
81/// Writing the complete translator trait is tedious. This macro is handy when
82/// we are not trying the associated types for hash160, ripemd160, hash256 and
83/// sha256.
84///
85/// See also [`crate::translate_hash_fail`]
86#[macro_export]
87macro_rules! translate_hash_clone {
88 ($source: ty, $target:ty, $error_ty: ty) => {
89 fn sha256(
90 &mut self,
91 sha256: &<$source as $crate::MiniscriptKey>::Sha256,
92 ) -> Result<<$target as $crate::MiniscriptKey>::Sha256, $error_ty> {
93 Ok((*sha256).into())
94 }
95
96 fn hash256(
97 &mut self,
98 hash256: &<$source as $crate::MiniscriptKey>::Hash256,
99 ) -> Result<<$target as $crate::MiniscriptKey>::Hash256, $error_ty> {
100 Ok((*hash256).into())
101 }
102
103 fn hash160(
104 &mut self,
105 hash160: &<$source as $crate::MiniscriptKey>::Hash160,
106 ) -> Result<<$target as $crate::MiniscriptKey>::Hash160, $error_ty> {
107 Ok((*hash160).into())
108 }
109
110 fn ripemd160(
111 &mut self,
112 ripemd160: &<$source as $crate::MiniscriptKey>::Ripemd160,
113 ) -> Result<<$target as $crate::MiniscriptKey>::Ripemd160, $error_ty> {
114 Ok((*ripemd160).into())
115 }
116 };
117}