1 // Bitcoin Hashes Library
2 // Written in 2018 by
3 //   Andrew Poelstra <apoelstra@wpsoftware.net>
4 //
5 // To the extent possible under law, the author(s) have dedicated all
6 // copyright and related and neighboring rights to this software to
7 // the public domain worldwide. This software is distributed without
8 // any warranty.
9 //
10 // You should have received a copy of the CC0 Public Domain Dedication
11 // along with this software.
12 // If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13 //
14 
15 /// Circular left-shift a 32-bit word
16 macro_rules! circular_lshift32 (
17     ($shift:expr, $w:expr) => (($w << $shift) | ($w >> (32 - $shift)))
18 );
19 
20 /// Circular left-shift a 64-bit word
21 macro_rules! circular_lshift64 (
22     ($shift:expr, $w:expr) => (($w << $shift) | ($w >> (64 - $shift)))
23 );
24 
25 #[macro_export]
26 /// Adds hexadecimal formatting implementation of a trait `$imp` to a given type `$ty`
27 macro_rules! hex_fmt_impl(
28     ($imp:ident, $ty:ident) => (
29         hex_fmt_impl!($imp, $ty, );
30     );
31     ($imp:ident, $ty:ident, $($gen:ident: $gent:ident),*) => (
32         impl<$($gen: $gent),*> $crate::_export::_core::fmt::$imp for $ty<$($gen),*> {
33             fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
34                 use $crate::hex::{format_hex, format_hex_reverse};
35                 if $ty::<$($gen),*>::DISPLAY_BACKWARD {
36                     format_hex_reverse(&self.0, f)
37                 } else {
38                     format_hex(&self.0, f)
39                 }
40             }
41         }
42     )
43 );
44 
45 /// Adds `core::ops::Index` trait implementation to a given type `$ty`
46 #[macro_export]
47 macro_rules! index_impl(
48     ($ty:ident) => (
49         index_impl!($ty, );
50     );
51     ($ty:ident, $($gen:ident: $gent:ident),*) => (
52         impl<$($gen: $gent),*> $crate::_export::_core::ops::Index<usize> for $ty<$($gen),*> {
53             type Output = u8;
54             fn index(&self, index: usize) -> &u8 {
55                 &self.0[index]
56             }
57         }
58 
59         impl<$($gen: $gent),*> $crate::_export::_core::ops::Index<$crate::_export::_core::ops::Range<usize>> for $ty<$($gen),*> {
60             type Output = [u8];
61             fn index(&self, index: $crate::_export::_core::ops::Range<usize>) -> &[u8] {
62                 &self.0[index]
63             }
64         }
65 
66         impl<$($gen: $gent),*> $crate::_export::_core::ops::Index<$crate::_export::_core::ops::RangeFrom<usize>> for $ty<$($gen),*> {
67             type Output = [u8];
68             fn index(&self, index: $crate::_export::_core::ops::RangeFrom<usize>) -> &[u8] {
69                 &self.0[index]
70             }
71         }
72 
73         impl<$($gen: $gent),*> $crate::_export::_core::ops::Index<$crate::_export::_core::ops::RangeTo<usize>> for $ty<$($gen),*> {
74             type Output = [u8];
75             fn index(&self, index: $crate::_export::_core::ops::RangeTo<usize>) -> &[u8] {
76                 &self.0[index]
77             }
78         }
79 
80         impl<$($gen: $gent),*> $crate::_export::_core::ops::Index<$crate::_export::_core::ops::RangeFull> for $ty<$($gen),*> {
81             type Output = [u8];
82             fn index(&self, index: $crate::_export::_core::ops::RangeFull) -> &[u8] {
83                 &self.0[index]
84             }
85         }
86     )
87 );
88 
89 /// Adds slicing traits implementations to a given type `$ty`
90 #[macro_export]
91 macro_rules! borrow_slice_impl(
92     ($ty:ident) => (
93         borrow_slice_impl!($ty, );
94     );
95     ($ty:ident, $($gen:ident: $gent:ident),*) => (
96         impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*>  {
97             fn borrow(&self) -> &[u8] {
98                 &self[..]
99             }
100         }
101 
102         impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*>  {
103             fn as_ref(&self) -> &[u8] {
104                 &self[..]
105             }
106         }
107 
108         impl<$($gen: $gent),*> $crate::_export::_core::ops::Deref for $ty<$($gen),*> {
109             type Target = [u8];
110 
111             fn deref(&self) -> &Self::Target {
112                 &self.0
113             }
114         }
115     )
116 );
117 
118 macro_rules! engine_input_impl(
119     () => (
120         #[cfg(not(fuzzing))]
121         fn input(&mut self, mut inp: &[u8]) {
122             while !inp.is_empty() {
123                 let buf_idx = self.length % <Self as EngineTrait>::BLOCK_SIZE;
124                 let rem_len = <Self as EngineTrait>::BLOCK_SIZE - buf_idx;
125                 let write_len = cmp::min(rem_len, inp.len());
126 
127                 self.buffer[buf_idx..buf_idx + write_len]
128                     .copy_from_slice(&inp[..write_len]);
129                 self.length += write_len;
130                 if self.length % <Self as EngineTrait>::BLOCK_SIZE == 0 {
131                     self.process_block();
132                 }
133                 inp = &inp[write_len..];
134             }
135         }
136 
137         #[cfg(fuzzing)]
138         fn input(&mut self, inp: &[u8]) {
139             for c in inp {
140                 self.buffer[0] ^= *c;
141             }
142             self.length += inp.len();
143         }
144     )
145 );
146 
147 
148 
149 macro_rules! define_slice_to_be {
150     ($name: ident, $type: ty) => {
151         #[inline]
152         pub fn $name(slice: &[u8]) -> $type {
153             assert_eq!(slice.len(), ::core::mem::size_of::<$type>());
154             let mut res = 0;
155             for i in 0..::core::mem::size_of::<$type>() {
156                 res |= (slice[i] as $type) << (::core::mem::size_of::<$type>() - i - 1)*8;
157             }
158             res
159         }
160     }
161 }
162 macro_rules! define_slice_to_le {
163     ($name: ident, $type: ty) => {
164         #[inline]
165         pub fn $name(slice: &[u8]) -> $type {
166             assert_eq!(slice.len(), ::core::mem::size_of::<$type>());
167             let mut res = 0;
168             for i in 0..::core::mem::size_of::<$type>() {
169                 res |= (slice[i] as $type) << i*8;
170             }
171             res
172         }
173     }
174 }
175 macro_rules! define_be_to_array {
176     ($name: ident, $type: ty, $byte_len: expr) => {
177         #[inline]
178         pub fn $name(val: $type) -> [u8; $byte_len] {
179             assert_eq!(::core::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22
180             let mut res = [0; $byte_len];
181             for i in 0..$byte_len {
182                 res[i] = ((val >> ($byte_len - i - 1)*8) & 0xff) as u8;
183             }
184             res
185         }
186     }
187 }
188 macro_rules! define_le_to_array {
189     ($name: ident, $type: ty, $byte_len: expr) => {
190         #[inline]
191         pub fn $name(val: $type) -> [u8; $byte_len] {
192             assert_eq!(::core::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22
193             let mut res = [0; $byte_len];
194             for i in 0..$byte_len {
195                 res[i] = ((val >> i*8) & 0xff) as u8;
196             }
197             res
198         }
199     }
200 }
201 
202 define_slice_to_be!(slice_to_u32_be, u32);
203 define_slice_to_be!(slice_to_u64_be, u64);
204 define_be_to_array!(u32_to_array_be, u32, 4);
205 define_be_to_array!(u64_to_array_be, u64, 8);
206 
207 define_slice_to_le!(slice_to_u32_le, u32);
208 define_slice_to_le!(slice_to_u64_le, u64);
209 define_le_to_array!(u32_to_array_le, u32, 4);
210 define_le_to_array!(u64_to_array_le, u64, 8);
211 
212 /// Create a new newtype around a [Hash] type.
213 #[macro_export]
214 macro_rules! hash_newtype {
215     ($newtype:ident, $hash:ty, $len:expr, $docs:meta) => {
216         hash_newtype!($newtype, $hash, $len, $docs, <$hash as $crate::Hash>::DISPLAY_BACKWARD);
217     };
218     ($newtype:ident, $hash:ty, $len:expr, $docs:meta, $reverse:expr) => {
219         #[$docs]
220         #[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
221         #[repr(transparent)]
222         pub struct $newtype($hash);
223 
224         hex_fmt_impl!(Debug, $newtype);
225         hex_fmt_impl!(Display, $newtype);
226         hex_fmt_impl!(LowerHex, $newtype);
227         index_impl!($newtype);
228         serde_impl!($newtype, $len);
229         borrow_slice_impl!($newtype);
230 
231         impl $newtype {
232             /// Create this type from the inner hash type.
233             pub fn from_hash(inner: $hash) -> $newtype {
234                 $newtype(inner)
235             }
236 
237             /// Convert this type into the inner hash type.
238             pub fn as_hash(&self) -> $hash {
239                 // Hashes implement Copy so don't need into_hash.
240                 self.0
241             }
242         }
243 
244         impl $crate::_export::_core::convert::From<$hash> for $newtype {
245             fn from(inner: $hash) -> $newtype {
246                 // Due to rust 1.22 we have to use this instead of simple `Self(inner)`
247                 Self { 0: inner }
248             }
249         }
250 
251         impl $crate::_export::_core::convert::From<$newtype> for $hash {
252             fn from(hashtype: $newtype) -> $hash {
253                 hashtype.0
254             }
255         }
256 
257         impl $crate::Hash for $newtype {
258             type Engine = <$hash as $crate::Hash>::Engine;
259             type Inner = <$hash as $crate::Hash>::Inner;
260 
261             const LEN: usize = <$hash as $crate::Hash>::LEN;
262             const DISPLAY_BACKWARD: bool = $reverse;
263 
264             fn engine() -> Self::Engine {
265                 <$hash as $crate::Hash>::engine()
266             }
267 
268             fn from_engine(e: Self::Engine) -> Self {
269                 Self::from(<$hash as $crate::Hash>::from_engine(e))
270             }
271 
272             #[inline]
273             fn from_slice(sl: &[u8]) -> Result<$newtype, $crate::Error> {
274                 Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?))
275             }
276 
277             #[inline]
278             fn from_inner(inner: Self::Inner) -> Self {
279                 $newtype(<$hash as $crate::Hash>::from_inner(inner))
280             }
281 
282             #[inline]
283             fn into_inner(self) -> Self::Inner {
284                 self.0.into_inner()
285             }
286 
287             #[inline]
288             fn as_inner(&self) -> &Self::Inner {
289                 self.0.as_inner()
290             }
291         }
292 
293         impl $crate::_export::_core::str::FromStr for $newtype {
294             type Err = $crate::hex::Error;
295             fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
296                 $crate::hex::FromHex::from_hex(s)
297             }
298         }
299     };
300 }
301 
302 #[cfg(feature = "schemars")]
303 pub mod json_hex_string {
304     use schemars::schema::{Schema, SchemaObject};
305     use schemars::{gen::SchemaGenerator, JsonSchema};
306     macro_rules! define_custom_hex {
307         ($name:ident, $len:expr) => {
308             pub fn $name(gen: &mut SchemaGenerator) -> Schema {
309                 let mut schema: SchemaObject = <String>::json_schema(gen).into();
310                 schema.string = Some(Box::new(schemars::schema::StringValidation {
311                     max_length: Some($len * 2),
312                     min_length: Some($len * 2),
313                     pattern: Some("[0-9a-fA-F]+".to_owned()),
314                 }));
315                 schema.into()
316             }
317         };
318     }
319     define_custom_hex!(len_8, 8);
320     define_custom_hex!(len_20, 20);
321     define_custom_hex!(len_32, 32);
322     define_custom_hex!(len_64, 64);
323 }
324 
325 #[cfg(test)]
326 mod test {
327     use Hash;
328     use sha256;
329     use super::*;
330 
331     #[test]
borrow_slice_impl_to_vec()332     fn borrow_slice_impl_to_vec() {
333         // Test that the borrow_slice_impl macro gives to_vec.
334         let hash = sha256::Hash::hash(&[3, 50]);
335         assert_eq!(hash.to_vec().len(), sha256::Hash::LEN);
336     }
337 
338     #[test]
endianness_test()339     fn endianness_test() {
340         assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef);
341         assert_eq!(slice_to_u64_be(&[0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef]), 0x1badcafedeadbeef);
342         assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]);
343         assert_eq!(u64_to_array_be(0x1badcafedeadbeef), [0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef]);
344 
345         assert_eq!(slice_to_u32_le(&[0xef, 0xbe, 0xad, 0xde]), 0xdeadbeef);
346         assert_eq!(slice_to_u64_le(&[0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]), 0x1badcafedeadbeef);
347         assert_eq!(u32_to_array_le(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]);
348         assert_eq!(u64_to_array_le(0x1badcafedeadbeef), [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]);
349     }
350 }
351