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