1#![warn(missing_docs)]
7pub use hash_generated::Hash256;
8use serde::{Deserialize, Serialize};
9use sha3::{Digest, Sha3_256};
10use std::fmt::Display;
11use std::ops::Add;
12use std::{
13 convert::{TryFrom, TryInto},
14 fmt,
15};
16pub use traits::{Hashable, Hashed};
17
18#[cfg(feature = "rust-embed")]
19use rust_embed::RustEmbed;
21
22#[cfg(feature = "rust-embed")]
23#[derive(RustEmbed)]
24#[folder = "src/flatbuffer"]
25pub struct FbSchema;
27
28#[allow(unused_imports, dead_code, missing_docs)]
31#[allow(clippy::all)]
32mod hash_generated;
33
34#[macro_export]
57macro_rules! calc_hash {
58 ( $( $x:expr ),* ) => {
59 {
60 let mut temp_hasher = $crate::Hasher::new();
61 $(
62 temp_hasher.update($x);
63 )*
64 temp_hasher.finalize()
65 }
66 };
67}
68
69pub fn b16_display<T: AsRef<[u8]>>(input: T) -> String {
76 let out = base16::encode_lower(&input);
77 out.chars().take(8).collect()
78}
79
80pub struct Hasher(Sha3_256);
84
85impl Default for Hasher {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl Hasher {
92 pub fn new() -> Self {
94 Hasher(Sha3_256::new())
95 }
96
97 pub fn update<T: AsRef<[u8]>>(&mut self, data: &T) {
99 self.0.update(data.as_ref());
100 }
101
102 pub fn reset(&mut self) {
104 self.0.reset();
105 }
106
107 pub fn finalize(self) -> Hash256 {
109 self.0.finalize().into()
110 }
111}
112
113enum Base16HashSerializer {}
115
116impl Base16HashSerializer {
117 pub fn serialize<S, Input>(bytes: Input, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: serde::Serializer,
120 Input: AsRef<[u8]>,
121 {
122 if serializer.is_human_readable() {
123 serializer.serialize_str(&base16::encode_lower(&bytes))
124 } else {
125 serializer.serialize_bytes(bytes.as_ref())
126 }
127 }
128
129 pub fn deserialize<'de, D, Output>(deserializer: D) -> Result<Output, D::Error>
130 where
131 D: serde::Deserializer<'de>,
132 Output: From<[u8; 32]>,
133 {
134 struct Base16Visitor;
135
136 impl<'de> serde::de::Visitor<'de> for Base16Visitor {
137 type Value = [u8; 32];
138
139 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
140 write!(formatter, "Expecting base16 ASCII text or byte array")
141 }
142
143 fn visit_str<E>(self, v: &str) -> ::std::result::Result<Self::Value, E>
144 where
145 E: serde::de::Error,
146 {
147 let mut output = [0u8; 32];
148 base16::decode_slice(v, &mut output).map_err(serde::de::Error::custom)?;
149 Ok(output)
150 }
151
152 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
153 where
154 E: serde::de::Error,
155 {
156 let output: [u8; 32] = v.try_into().map_err(serde::de::Error::custom)?;
157 Ok(output)
158 }
159 }
160
161 if deserializer.is_human_readable() {
162 deserializer
163 .deserialize_str(Base16Visitor)
164 .map(|vec| Output::from(vec))
165 } else {
166 deserializer
167 .deserialize_bytes(Base16Visitor)
168 .map(Into::into)
169 }
170 }
171}
172
173impl Hash256 {
174 pub fn digest<T: AsRef<[u8]>>(bytes: &T) -> Self {
182 let buf = Sha3_256::digest(bytes.as_ref());
183 Self(buf.into())
184 }
185
186 pub fn digest_w_x00<T: AsRef<[u8]>>(bytes: &T) -> Self {
193 let mut hasher = Hasher::new();
194 hasher.update(b"\x00");
195 hasher.update(bytes);
196 hasher.finalize()
197 }
198
199 pub fn digest_w_x01<T: AsRef<[u8]>>(bytes: &T) -> Self {
206 let mut hasher = Hasher::new();
207 hasher.update(b"\x01");
208 hasher.update(bytes);
209 hasher.finalize()
210 }
211
212 pub fn zero() -> Self {
216 Hash256([0u8; 32])
217 }
218
219 pub fn empty() -> Self {
234 Hash256::digest(b"")
235 }
236
237 pub fn sum(h1: &Hash256, h2: &Hash256) -> Hash256 {
258 let mut hasher = Hasher::new();
259 hasher.update(h1);
260 hasher.update(h2);
261 hasher.finalize()
262 }
263
264 pub fn to_u64(&self) -> u64 {
269 let mut out: u64 = 0u64;
270 for i in 0..32 {
271 out = out
272 .overflowing_add(
273 (self.0.as_slice()[i] as u64)
274 .overflowing_shl(8u32 * (i as u32))
275 .0,
276 )
277 .0;
278 }
279 out
280 }
281
282 pub fn into_vec(self) -> Vec<u8> {
284 self.into()
285 }
286
287 pub fn into_slice(self) -> [u8; 32] {
289 self.into()
290 }
291}
292
293impl Add for Hash256 {
294 type Output = Hash256;
295
296 fn add(self, rhs: Self) -> Self::Output {
297 Hash256::sum(&self, &rhs)
298 }
299}
300
301impl From<Hash256> for u64 {
302 fn from(hash: Hash256) -> Self {
303 hash.to_u64()
304 }
305}
306
307impl From<sha3::digest::Output<Sha3_256>> for Hash256 {
308 fn from(hash: sha3::digest::Output<Sha3_256>) -> Self {
309 Hash256(hash.into())
310 }
311}
312
313#[derive(Debug)]
319pub struct InvalidSliceLength(pub usize);
320
321impl Display for InvalidSliceLength {
322 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323 write!(
324 f,
325 "failed to decode hash - invalid slice length. Expected 32bytes, got {}",
326 self.0
327 )
328 }
329}
330
331impl std::error::Error for InvalidSliceLength {}
332
333impl From<[u8; 32]> for Hash256 {
334 fn from(slice: [u8; 32]) -> Self {
335 Hash256(slice)
336 }
337}
338
339impl From<&[u8; 32]> for Hash256 {
340 fn from(slice: &[u8; 32]) -> Self {
341 Hash256(*slice)
342 }
343}
344
345impl From<Hash256> for [u8; 32] {
346 fn from(h: Hash256) -> Self {
347 h.0
348 }
349}
350
351impl TryFrom<&[u8]> for Hash256 {
352 type Error = InvalidSliceLength;
353
354 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
355 if value.len() != 32 {
356 return Err(InvalidSliceLength(value.len()));
357 }
358 let mut buf = [0; 32];
359 buf.copy_from_slice(value);
360 Ok(Hash256(buf))
361 }
362}
363
364impl TryFrom<Vec<u8>> for Hash256 {
365 type Error = InvalidSliceLength;
366
367 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
368 value.as_slice().try_into()
369 }
370}
371
372impl TryFrom<&Vec<u8>> for Hash256 {
373 type Error = InvalidSliceLength;
374
375 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
376 value.as_slice().try_into()
377 }
378}
379
380impl From<Hash256> for Vec<u8> {
381 fn from(h: Hash256) -> Self {
382 h.0.to_vec()
383 }
384}
385
386impl fmt::Display for Hash256 {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 write!(f, "{}", &b16_display(self.0))
389 }
390}
391
392impl From<Hash256> for String {
393 fn from(h: Hash256) -> Self {
394 base16::encode_lower(&h.0)
395 }
396}
397
398impl AsRef<[u8; 32]> for Hash256 {
399 fn as_ref(&self) -> &[u8; 32] {
400 &self.0
401 }
402}
403
404impl PartialOrd for Hash256 {
406 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
407 Some(self.cmp(other))
408 }
409}
410
411impl Ord for Hash256 {
412 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
413 self.0.cmp(&other.0)
414 }
415}
416
417impl Eq for Hash256 {}
418
419impl AsRef<[u8]> for Hash256 {
420 fn as_ref(&self) -> &[u8] {
421 self.0.as_ref()
422 }
423}
424
425impl Serialize for Hash256 {
426 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
427 where
428 S: serde::Serializer,
429 {
430 Base16HashSerializer::serialize(self.0, serializer)
431 }
432}
433
434impl<'de> Deserialize<'de> for Hash256 {
435 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
436 where
437 D: serde::Deserializer<'de>,
438 {
439 Base16HashSerializer::deserialize(deserializer)
440 }
441}
442
443impl std::hash::Hash for Hash256 {
444 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
445 self.0.hash(state);
446 }
447}
448
449pub mod traits {
451 use super::Hash256;
452
453 pub trait Hashed {
460 fn hash(&self) -> &Hash256;
462 }
463
464 pub trait Hashable {
472 fn calc_hash(&self) -> Hash256;
474 }
475
476 impl<T: Hashed> Hashable for T {
478 fn calc_hash(&self) -> Hash256 {
479 *self.hash()
480 }
481 }
482
483 impl Hashed for Hash256 {
485 fn hash(&self) -> &Hash256 {
486 self
487 }
488 }
489}
490
491#[cfg(test)]
492mod tests {
493 use super::traits::*;
494 use super::*;
495
496 #[test]
497 fn hash_sum_matches() {
498 let h1 = Sha3_256::digest("hash-1".as_bytes()).to_vec();
499 let h2 = Sha3_256::digest("hash-2".as_bytes()).to_vec();
500 let mut concat = Vec::new();
502 for byte in h1.iter() {
503 concat.push(*byte);
504 }
505 for byte in h2.iter() {
506 concat.push(*byte);
507 }
508 let res_hash = Sha3_256::digest(concat.as_slice());
509 println!("{:?}", res_hash);
510 let mut hasher = Sha3_256::new();
512 hasher.update(h1);
513 hasher.update(h2);
514 let res_update = hasher.finalize();
515 println!("{:?}", res_update);
516 assert_eq!(res_hash, res_update);
517 }
518
519 #[test]
520 fn hash_comparable() {
521 let h1 = Sha3_256::digest("hash-1".as_bytes()).to_vec();
522 let h2 = Sha3_256::digest("hash-2".as_bytes()).to_vec();
523 assert_ne!(h1 < h2, h2 < h1);
524 assert_ne!(h1 == h2, h2 < h1);
525 assert_eq!(h1, h1);
526 assert_eq!(h1 == h1, h2 == h2);
527 }
528
529 #[test]
530 fn zero_hash() {
531 assert_eq!(
532 base16::encode_lower(&Hash256::zero()),
533 "0000000000000000000000000000000000000000000000000000000000000000"
534 );
535 assert_eq!(Hash256::zero().0, [0u8; 32]);
536 }
537
538 #[test]
539 fn empty_hash() {
540 assert_eq!(Hash256::empty(), Hash256::digest(b""));
541 let hasher = Hasher::new();
542 assert_eq!(Hash256::empty(), hasher.finalize());
543 }
544
545 #[test]
546 fn hash_addition() {
547 let h1 = Hash256::zero() + Hash256::empty();
548 let h2 = Hash256::sum(&Hash256::zero(), &Hash256::empty());
549 let h3 = Hash256::empty() + Hash256::zero();
550 let h4 = Hash256::sum(&Hash256::empty(), &Hash256::zero());
551 assert_eq!(h1, h2);
552 assert_eq!(h3, h4);
553 assert_ne!(h1, h3);
554 assert_ne!(h2, h4);
555 let mut hasher = Hasher::new();
556 hasher.update(&Hash256::zero());
557 hasher.update(&Hash256::empty());
558 assert_eq!(h1, hasher.finalize());
559 }
560
561 #[test]
562 fn default_hash() {
563 assert_eq!(Hash256::zero(), Hash256::default());
564 }
565
566 #[test]
567 fn digest_x00() {
568 let msg = "random-message";
569 let h1 = Hash256::digest_w_x00(&msg);
570 let mut hasher = Hasher::new();
571 hasher.update(b"\x00");
572 hasher.update(&msg);
573 let h2 = hasher.finalize();
574 assert_eq!(h1, h2);
575 }
576
577 #[test]
578 fn digest_x01() {
579 let msg = "random-message";
580 let h1 = Hash256::digest_w_x01(&msg);
581 let mut hasher = Hasher::new();
582 hasher.update(b"\x01");
583 hasher.update(&msg);
584 let h2 = hasher.finalize();
585 assert_eq!(h1, h2);
586 }
587
588 #[test]
589 fn generic_array_equals_slice() {
590 let slice = [5u8; 32];
591 let hash = Hash256::from(slice);
592 assert_eq!(Hash256::digest(&hash), Hash256::digest(&slice));
593 }
594
595 #[test]
596 fn calc_hash_macro() {
597 let h = calc_hash!(
598 &Hash256::zero(),
599 &Hash256::empty(),
600 b"\x01",
601 &"foo",
602 &[1u8, 2u8, 3u8]
603 );
604 let mut hasher = Hasher::new();
605 hasher.update(&Hash256::zero());
606 hasher.update(&Hash256::empty());
607 hasher.update(b"\x01");
608 hasher.update(&"foo");
609 hasher.update(&[1u8, 2u8, 3u8]);
610 assert_eq!(h, hasher.finalize());
611 }
612
613 #[test]
614 fn hash_ordering() {
615 let mut original = Vec::new();
616 for i in 0..100u32 {
617 original.push(calc_hash!(&i.to_be_bytes()));
618 }
619 let mut fb_type: Vec<Hash256> = original.to_vec();
620
621 original.sort_unstable();
623 fb_type.sort_unstable();
624
625 let transformed_back: Vec<Hash256> = fb_type.into_iter().collect();
626 assert_eq!(original, transformed_back);
627 }
628
629 #[test]
630 fn b16_encode_decode() {
631 let hash = Hash256::empty();
632 let encoded = base16::encode_lower(&hash);
633 let decoded = base16::decode(&encoded).unwrap();
634 let reconstructed = Hash256::try_from(&decoded).unwrap();
635 assert_eq!(hash, reconstructed);
636 }
637
638 #[test]
639 fn reset_hasher() {
640 let mut hasher = Hasher::default();
641 hasher.update(&Hash256::zero());
642 hasher.update(&Hash256::zero());
643 hasher.reset();
644 let hash = hasher.finalize();
645 assert_eq!(hash, Hash256::empty());
646 }
647
648 #[test]
649 fn to_u64() {
650 let hash = Hash256::empty();
651 let res = 1025330622980758127;
652 assert_eq!(hash.to_u64(), res);
653 let into: u64 = hash.into();
654 assert_eq!(into, res);
655 }
656
657 #[test]
658 fn from_and_into_slice() {
659 let hash = Hash256::empty();
660 let slice = hash.into_slice();
661 let reconstructed = Hash256::from(&slice);
662 assert_eq!(reconstructed, Hash256::empty());
663 let other = Hash256::from(reconstructed.as_ref());
664 assert_eq!(reconstructed, other);
665 }
666
667 #[test]
668 fn from_and_into_vec() -> Result<(), Box<dyn std::error::Error>> {
669 let hash = Hash256::empty();
670 let mut vec = hash.into_vec();
671 let reconstructed = Hash256::try_from(&vec)?;
672 assert_eq!(reconstructed, Hash256::empty());
673
674 let reconstructed = Hash256::try_from(vec.as_slice())?;
675 assert_eq!(reconstructed, Hash256::empty());
676
677 vec.pop();
678 let fail = Hash256::try_from(&vec);
679 assert!(fail.is_err());
680 let fail = Hash256::try_from(vec![]);
681 assert!(fail.is_err());
682 Ok(())
683 }
684
685 #[test]
686 fn hashed() {
687 let hash = Hash256::empty();
688 assert_eq!(*hash.hash(), hash);
689 }
690
691 #[test]
692 fn display() {
693 assert_eq!(Hash256::empty().to_string(), "a7ffc6f8");
694 assert_eq!(Hash256::zero().to_string(), "00000000");
695 let hash = Hash256::empty();
696 let full_string: String = hash.into();
697 assert_ne!(
698 hash.to_string(),
699 full_string,
700 "Hash's display method should not display full length string"
701 );
702 }
703
704 #[test]
705 fn serialize_hash() {
706 let hash = Hash256::digest(b"hash");
707 let out = serde_json::to_string(&hash).unwrap();
708 assert_eq!(
709 out,
710 "\"d7333e98f53ddf1de70dd986f6a73f0c0d92f928458873b0d2a8a09ac22c191a\""
711 );
712 }
713
714 #[test]
715 fn deserialize_hash() {
716 let json: Hash256 = serde_json::from_str(
717 "\"d7333e98f53ddf1de70dd986f6a73f0c0d92f928458873b0d2a8a09ac22c191a\"",
718 )
719 .unwrap();
720 let hash = Hash256::digest(b"hash");
721 assert_eq!(json, hash);
722 }
723
724 #[test]
725 fn debug_output() {
726 let hash = Hash256::digest(b"hash");
727 let dbg = format!("{hash:?}");
728 assert_eq!(dbg, "Hash256 { bytes: [215, 51, 62, 152, 245, 61, 223, 29, 231, 13, 217, 134, 246, 167, 63, 12, 13, 146, 249, 40, 69, 136, 115, 176, 210, 168, 160, 154, 194, 44, 25, 26] }");
729 }
730
731 #[test]
732 fn fb_generated_interfaces() {
733 let bytes = [42u8; 32];
734 let mut hash = Hash256::new(&bytes);
735 assert_eq!(hash.0, bytes);
736
737 for v in hash.bytes().iter() {
738 assert_eq!(v, 42);
739 }
740
741 let other = [1u8; 32];
742 hash.set_bytes(&other);
743 assert_eq!(hash.0, other);
744 }
745}