bitcoin_hashes/
util.rs

1// SPDX-License-Identifier: CC0-1.0
2
3#[macro_export]
4/// Adds hexadecimal formatting implementation of a trait `$imp` to a given type `$ty`.
5macro_rules! hex_fmt_impl(
6    ($reverse:expr, $ty:ident) => (
7        $crate::hex_fmt_impl!($reverse, $ty, );
8    );
9    ($reverse:expr, $ty:ident, $($gen:ident: $gent:ident),*) => (
10        impl<$($gen: $gent),*> $crate::_export::_core::fmt::LowerHex for $ty<$($gen),*> {
11            #[inline]
12            fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
13                if $reverse {
14                    $crate::_export::_core::fmt::LowerHex::fmt(&self.0.backward_hex(), f)
15                } else {
16                    $crate::_export::_core::fmt::LowerHex::fmt(&self.0.forward_hex(), f)
17                }
18            }
19        }
20
21        impl<$($gen: $gent),*> $crate::_export::_core::fmt::UpperHex for $ty<$($gen),*> {
22            #[inline]
23            fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
24                if $reverse {
25                    $crate::_export::_core::fmt::UpperHex::fmt(&self.0.backward_hex(), f)
26                } else {
27                    $crate::_export::_core::fmt::UpperHex::fmt(&self.0.forward_hex(), f)
28                }
29            }
30        }
31
32        impl<$($gen: $gent),*> $crate::_export::_core::fmt::Display for $ty<$($gen),*> {
33            #[inline]
34            fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
35                $crate::_export::_core::fmt::LowerHex::fmt(&self, f)
36            }
37        }
38
39        impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> {
40            #[inline]
41            fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
42                write!(f, "{:#}", self)
43            }
44        }
45    );
46);
47
48/// Adds slicing traits implementations to a given type `$ty`
49#[macro_export]
50macro_rules! borrow_slice_impl(
51    ($ty:ident) => (
52        $crate::borrow_slice_impl!($ty, );
53    );
54    ($ty:ident, $($gen:ident: $gent:ident),*) => (
55        impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*>  {
56            fn borrow(&self) -> &[u8] {
57                &self[..]
58            }
59        }
60
61        impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*>  {
62            fn as_ref(&self) -> &[u8] {
63                &self[..]
64            }
65        }
66    )
67);
68
69macro_rules! engine_input_impl(
70    () => (
71        #[cfg(not(hashes_fuzz))]
72        fn input(&mut self, mut inp: &[u8]) {
73            while !inp.is_empty() {
74                let buf_idx = self.length % <Self as crate::HashEngine>::BLOCK_SIZE;
75                let rem_len = <Self as crate::HashEngine>::BLOCK_SIZE - buf_idx;
76                let write_len = cmp::min(rem_len, inp.len());
77
78                self.buffer[buf_idx..buf_idx + write_len]
79                    .copy_from_slice(&inp[..write_len]);
80                self.length += write_len;
81                if self.length % <Self as crate::HashEngine>::BLOCK_SIZE == 0 {
82                    self.process_block();
83                }
84                inp = &inp[write_len..];
85            }
86        }
87
88        #[cfg(hashes_fuzz)]
89        fn input(&mut self, inp: &[u8]) {
90            for c in inp {
91                self.buffer[0] ^= *c;
92            }
93            self.length += inp.len();
94        }
95    )
96);
97
98/// Creates a new newtype around a [`Hash`] type.
99///
100/// The syntax is similar to the usual tuple struct syntax:
101///
102/// ```
103/// # use bitcoin_hashes::{hash_newtype, sha256};
104/// hash_newtype! {
105///     /// Hash of `Foo`.
106///     pub struct MyNewtype(pub sha256::Hash);
107/// }
108/// ```
109///
110/// You can use any valid visibility specifier in place of `pub` or you can omit either or both, if
111/// you want the type or its field to be private.
112///
113/// Whether the hash is reversed or not when displaying depends on the inner type. However you can
114/// override it like this:
115///
116/// ```
117/// # use bitcoin_hashes::{hash_newtype, sha256};
118/// hash_newtype! {
119///     #[hash_newtype(backward)]
120///     struct MyNewtype(sha256::Hash);
121/// }
122/// ```
123///
124/// This will display the hash backwards regardless of what the inner type does. Use `forward`
125/// instead of `backward` to force displaying forward.
126///
127/// You can add arbitrary doc comments or other attributes to the struct or it's field. Note that
128/// the macro already derives [`Copy`], [`Clone`], [`Eq`], [`PartialEq`],
129/// [`Hash`](core::hash::Hash), [`Ord`], [`PartialOrd`]. With the `serde` feature on, this also adds
130/// `Serialize` and `Deserialize` implementations.
131///
132/// You can also define multiple newtypes within one macro call:
133///
134/// ```
135/// # use bitcoin_hashes::{hash_newtype, sha256, hash160};
136///
137/// hash_newtype! {
138///     /// My custom type 1
139///     pub struct Newtype1(sha256::Hash);
140///
141///     /// My custom type 2
142///     struct Newtype2(hash160::Hash);
143/// }
144/// ```
145///
146/// Note: the macro is internally recursive. If you use too many attributes (> 256 tokens) you may
147/// hit recursion limit. If you have so many attributes for a good reason, just raising the limit
148/// should be OK. Note however that attribute-processing part has to use [TT muncher] which has
149/// quadratic complexity, so having many attributes may blow up compile time. This should be rare.
150///
151/// [TT muncher]: https://danielkeep.github.io/tlborm/book/pat-incremental-tt-munchers.html
152///
153// Ever heard of legendary comments warning developers to not touch the code? Yep, here's another
154// one. The following code is written the way it is for some specific reasons. If you think you can
155// simplify it, I suggest spending your time elsewhere.
156//
157// If you looks at the code carefully you might ask these questions:
158//
159// * Why are attributes using `tt` and not `meta`?!
160// * Why are the macros split like that?!
161// * Why use recursion instead of `$()*`?
162//
163// None of these are here by accident. For some reason unknown to me, if you accept an argument to
164// macro with any fragment specifier other than `tt` it will **not** match any of the rules
165// requiring a specific token. Yep, I tried it, I literally got error that `hash_newtype` doesn't
166// match `hash_newtype`. So all input attributes must be `tt`.
167//
168// Originally I wanted to define a bunch of macros that would filter-out hash_type attributes. Then
169// I remembered (by seeing compiler error) that calling macros is not allowed inside attributes.
170// And no, you can't bypass it by calling a helper macro and passing "output of another macro" into
171// it. The whole macro gets passed, not the resulting value. So we have to generate the entire
172// attributes. And you can't just place an attribute-producing macro above struct - they are
173// considered separate items. This is not C.
174//
175// Thus struct is generated in a separate macro together with attributes. And since the macro needs
176// attributes as the input and I didn't want to create confusion by using `#[]` syntax *after*
177// struct, I opted to use `{}` as a separator. Yes, a separator is required because an attribute
178// may be composed of multiple token trees - that's the point of "double repetition".
179#[macro_export]
180macro_rules! hash_newtype {
181    ($($(#[$($type_attrs:tt)*])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:tt])* $field_vis:vis $hash:path);)+) => {
182        $(
183        $($crate::hash_newtype_known_attrs!(#[ $($type_attrs)* ]);)*
184
185        $crate::hash_newtype_struct! {
186            $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
187
188            $({ $($type_attrs)* })*
189        }
190
191        $crate::hex_fmt_impl!(<$newtype as $crate::Hash>::DISPLAY_BACKWARD, $newtype);
192        $crate::serde_impl!($newtype, <$newtype as $crate::Hash>::LEN);
193        $crate::borrow_slice_impl!($newtype);
194
195        impl $newtype {
196            /// Creates this wrapper type from the inner hash type.
197            #[allow(unused)] // the user of macro may not need this
198            pub fn from_raw_hash(inner: $hash) -> $newtype {
199                $newtype(inner)
200            }
201
202            /// Returns the inner hash (sha256, sh256d etc.).
203            #[allow(unused)] // the user of macro may not need this
204            pub fn to_raw_hash(self) -> $hash {
205                self.0
206            }
207
208            /// Returns a reference to the inner hash (sha256, sh256d etc.).
209            #[allow(unused)] // the user of macro may not need this
210            pub fn as_raw_hash(&self) -> &$hash {
211                &self.0
212            }
213        }
214
215        impl $crate::_export::_core::convert::From<$hash> for $newtype {
216            fn from(inner: $hash) -> $newtype {
217                // Due to rust 1.22 we have to use this instead of simple `Self(inner)`
218                Self { 0: inner }
219            }
220        }
221
222        impl $crate::_export::_core::convert::From<$newtype> for $hash {
223            fn from(hashtype: $newtype) -> $hash {
224                hashtype.0
225            }
226        }
227
228        impl $crate::Hash for $newtype {
229            type Engine = <$hash as $crate::Hash>::Engine;
230            type Bytes = <$hash as $crate::Hash>::Bytes;
231
232            const LEN: usize = <$hash as $crate::Hash>::LEN;
233            const DISPLAY_BACKWARD: bool = $crate::hash_newtype_get_direction!($hash, $(#[$($type_attrs)*])*);
234
235            fn engine() -> Self::Engine {
236                <$hash as $crate::Hash>::engine()
237            }
238
239            fn from_engine(e: Self::Engine) -> Self {
240                Self::from(<$hash as $crate::Hash>::from_engine(e))
241            }
242
243            #[inline]
244            fn from_slice(sl: &[u8]) -> Result<$newtype, $crate::FromSliceError> {
245                Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?))
246            }
247
248            #[inline]
249            fn from_byte_array(bytes: Self::Bytes) -> Self {
250                $newtype(<$hash as $crate::Hash>::from_byte_array(bytes))
251            }
252
253            #[inline]
254            fn to_byte_array(self) -> Self::Bytes {
255                self.0.to_byte_array()
256            }
257
258            #[inline]
259            fn as_byte_array(&self) -> &Self::Bytes {
260                self.0.as_byte_array()
261            }
262
263            #[inline]
264            fn all_zeros() -> Self {
265                let zeros = <$hash>::all_zeros();
266                $newtype(zeros)
267            }
268        }
269
270        impl $crate::_export::_core::str::FromStr for $newtype {
271            type Err = $crate::hex::HexToArrayError;
272            fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
273                use $crate::hex::{FromHex, HexToBytesIter};
274                use $crate::Hash;
275
276                let inner: <$hash as Hash>::Bytes = if <Self as $crate::Hash>::DISPLAY_BACKWARD {
277                    FromHex::from_byte_iter(HexToBytesIter::new(s)?.rev())?
278                } else {
279                    FromHex::from_byte_iter(HexToBytesIter::new(s)?)?
280                };
281                Ok($newtype(<$hash>::from_byte_array(inner)))
282            }
283        }
284
285        impl $crate::_export::_core::convert::AsRef<[u8; <$hash as $crate::Hash>::LEN]> for $newtype {
286            fn as_ref(&self) -> &[u8; <$hash as $crate::Hash>::LEN] {
287                AsRef::<[u8; <$hash as $crate::Hash>::LEN]>::as_ref(&self.0)
288            }
289        }
290
291        impl<I: $crate::_export::_core::slice::SliceIndex<[u8]>> $crate::_export::_core::ops::Index<I> for $newtype {
292            type Output = I::Output;
293
294            #[inline]
295            fn index(&self, index: I) -> &Self::Output {
296                &self.0[index]
297            }
298        }
299        )+
300    };
301}
302
303// Generates the struct only (no impls)
304//
305// This is a separate macro to make it more readable and have a separate interface that allows for
306// two groups of type attributes: processed and not-yet-processed ones (think about it like
307// computation via recursion). The macro recursively matches unprocessed attributes, popping them
308// one at a time and either ignoring them (`hash_newtype`) or appending them to the list of
309// processed attributes to be added to the struct.
310//
311// Once the list of not-yet-processed attributes is empty the struct is generated with processed
312// attributes added.
313#[doc(hidden)]
314#[macro_export]
315macro_rules! hash_newtype_struct {
316    ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path);) => {
317        $(#[$other_attrs])*
318        #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
319        $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
320    };
321    ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path); { hash_newtype($($ignore:tt)*) } $($type_attrs:tt)*) => {
322        $crate::hash_newtype_struct! {
323            $(#[$other_attrs])*
324            $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
325
326            $($type_attrs)*
327        }
328    };
329    ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path); { $other_attr:meta } $($type_attrs:tt)*) => {
330        $crate::hash_newtype_struct! {
331            $(#[$other_attrs])*
332            #[$other_attr]
333            $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
334
335            $($type_attrs)*
336        }
337    };
338}
339
340// Extracts `hash_newtype(forward)` and `hash_newtype(backward)` attributes if any and turns them
341// into bool, defaulting to `DISPLAY_BACKWARD` of the wrapped type if the attribute is omitted.
342//
343// Once an appropriate attribute is found we pass the remaining ones into another macro to detect
344// duplicates/conflicts and report an error.
345//
346// FYI, no, we can't use a helper macro to first filter all `hash_newtype` attributes. We would be
347// attempting to match on macros instead. So we must write `hashe_newtype` in each branch.
348#[doc(hidden)]
349#[macro_export]
350macro_rules! hash_newtype_get_direction {
351    ($hash:ty, ) => { <$hash as $crate::Hash>::DISPLAY_BACKWARD };
352    ($hash:ty, #[hash_newtype(forward)] $($others:tt)*) => { { $crate::hash_newtype_forbid_direction!(forward, $($others)*); false } };
353    ($hash:ty, #[hash_newtype(backward)] $($others:tt)*) => { { $crate::hash_newtype_forbid_direction!(backward, $($others)*); true } };
354    ($hash:ty, #[$($ignore:tt)*]  $($others:tt)*) => { $crate::hash_newtype_get_direction!($hash, $($others)*) };
355}
356
357// Reports an error if any of the attributes is `hash_newtype($direction)`.
358//
359// This is used for detection of duplicates/conflicts, see the macro above.
360#[doc(hidden)]
361#[macro_export]
362macro_rules! hash_newtype_forbid_direction {
363    ($direction:ident, ) => {};
364    ($direction:ident, #[hash_newtype(forward)] $(others:tt)*) => {
365        compile_error!(concat!("Cannot set display direction to forward: ", stringify!($direction), " was already specified"));
366    };
367    ($direction:ident, #[hash_newtype(backward)] $(others:tt)*) => {
368        compile_error!(concat!("Cannot set display direction to backward: ", stringify!($direction), " was already specified"));
369    };
370    ($direction:ident, #[$($ignore:tt)*] $(#[$others:tt])*) => {
371        $crate::hash_newtype_forbid_direction!($direction, $(#[$others])*)
372    };
373}
374
375// Checks (at compile time) that all `hash_newtype` attributes are known.
376//
377// An unknown attribute could be a typo that could cause problems - e.g. wrong display direction if
378// it's missing. To prevent this, we call this macro above. The macro produces nothing unless an
379// unknown attribute is found in which case it produces `compile_error!`.
380#[doc(hidden)]
381#[macro_export]
382macro_rules! hash_newtype_known_attrs {
383    (#[hash_newtype(forward)]) => {};
384    (#[hash_newtype(backward)]) => {};
385    (#[hash_newtype($($unknown:tt)*)]) => { compile_error!(concat!("Unrecognized attribute ", stringify!($($unknown)*))); };
386    ($($ignore:tt)*) => {};
387}
388
389#[cfg(feature = "schemars")]
390pub mod json_hex_string {
391    use schemars::gen::SchemaGenerator;
392    use schemars::schema::{Schema, SchemaObject};
393    use schemars::JsonSchema;
394    macro_rules! define_custom_hex {
395        ($name:ident, $len:expr) => {
396            pub fn $name(gen: &mut SchemaGenerator) -> Schema {
397                let mut schema: SchemaObject = <String>::json_schema(gen).into();
398                schema.string = Some(Box::new(schemars::schema::StringValidation {
399                    max_length: Some($len * 2),
400                    min_length: Some($len * 2),
401                    pattern: Some("[0-9a-fA-F]+".to_owned()),
402                }));
403                schema.into()
404            }
405        };
406    }
407    define_custom_hex!(len_8, 8);
408    define_custom_hex!(len_20, 20);
409    define_custom_hex!(len_32, 32);
410    define_custom_hex!(len_64, 64);
411}
412
413#[cfg(test)]
414mod test {
415    use crate::{sha256, Hash};
416
417    #[test]
418    fn hash_as_ref_array() {
419        let hash = sha256::Hash::hash(&[3, 50]);
420        let r = AsRef::<[u8; 32]>::as_ref(&hash);
421        assert_eq!(r, hash.as_byte_array());
422    }
423
424    #[test]
425    fn hash_as_ref_slice() {
426        let hash = sha256::Hash::hash(&[3, 50]);
427        let r = AsRef::<[u8]>::as_ref(&hash);
428        assert_eq!(r, hash.as_byte_array());
429    }
430
431    #[test]
432    fn hash_borrow() {
433        use core::borrow::Borrow;
434
435        let hash = sha256::Hash::hash(&[3, 50]);
436        let borrowed: &[u8] = hash.borrow();
437        assert_eq!(borrowed, hash.as_byte_array());
438    }
439
440    hash_newtype! {
441        /// Test hash.
442        struct TestHash(crate::sha256d::Hash);
443    }
444
445    #[test]
446    fn display() {
447        let want = "0000000000000000000000000000000000000000000000000000000000000000";
448        let got = format!("{}", TestHash::all_zeros());
449        assert_eq!(got, want)
450    }
451
452    #[test]
453    fn display_alternate() {
454        let want = "0x0000000000000000000000000000000000000000000000000000000000000000";
455        let got = format!("{:#}", TestHash::all_zeros());
456        assert_eq!(got, want)
457    }
458
459    #[test]
460    fn lower_hex() {
461        let want = "0000000000000000000000000000000000000000000000000000000000000000";
462        let got = format!("{:x}", TestHash::all_zeros());
463        assert_eq!(got, want)
464    }
465
466    #[test]
467    fn lower_hex_alternate() {
468        let want = "0x0000000000000000000000000000000000000000000000000000000000000000";
469        let got = format!("{:#x}", TestHash::all_zeros());
470        assert_eq!(got, want)
471    }
472
473    #[test]
474    fn inner_hash_as_ref_array() {
475        let hash = TestHash::all_zeros();
476        let r = AsRef::<[u8; 32]>::as_ref(&hash);
477        assert_eq!(r, hash.as_byte_array());
478    }
479
480    #[test]
481    fn inner_hash_as_ref_slice() {
482        let hash = TestHash::all_zeros();
483        let r = AsRef::<[u8]>::as_ref(&hash);
484        assert_eq!(r, hash.as_byte_array());
485    }
486}