Skip to main content

borderless_hash/
lib.rs

1//! Provides the hash implementation for all borderless-primitives.
2//!
3//! This library contains the implementation of the [`Hash256`], that is used throughout the entire borderless stack.
4//! Internally, it uses the sha-3 hash function to digest binary data and actually generate the hash.
5//!
6#![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")]
19// Required to embed primitives .fbs into external repositories
20use rust_embed::RustEmbed;
21
22#[cfg(feature = "rust-embed")]
23#[derive(RustEmbed)]
24#[folder = "src/flatbuffer"]
25/// Embedded schema accessor used at build time to expose schema content to external repositories
26pub struct FbSchema;
27
28// NOTE: The code generation creates a lot of artifacts,
29// which result in a lot of warnings.
30#[allow(unused_imports, dead_code, missing_docs)]
31#[allow(clippy::all)]
32mod hash_generated;
33
34/// Easy way to feed an arbitrary amount of data into the [`Hasher`] and retrieving its result.
35///
36/// # Examples
37/// ```
38/// # #[macro_use] extern crate borderless_hash;
39/// # fn main() {
40/// let hash = calc_hash!(b"hash", b"over", b"some", b"amount", b"of", b"data");
41/// # }
42/// ```
43///
44/// Which is equivalent to:
45/// ```
46/// # use borderless_hash::Hasher;
47/// let mut hasher = Hasher::new();
48/// hasher.update(b"hash");
49/// hasher.update(b"over");
50/// hasher.update(b"some");
51/// hasher.update(b"amount");
52/// hasher.update(b"of");
53/// hasher.update(b"data");
54/// let hash = hasher.finalize();
55/// ```
56#[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
69/// Applies the hexadecimal-encoding scheme to some data but only returns the first eight characters.
70///
71/// Can be used to print a hash to console.
72///
73/// Note: The output of this function cannot be decoded again,
74/// since we remove a relevant portion of the information!
75pub fn b16_display<T: AsRef<[u8]>>(input: T) -> String {
76    let out = base16::encode_lower(&input);
77    out.chars().take(8).collect()
78}
79
80/// Hasher that produces the [`Hash256`] as an output.
81///
82/// Thin wrapper around the [`Sha3_256`] type.
83pub struct Hasher(Sha3_256);
84
85impl Default for Hasher {
86    fn default() -> Self {
87        Self::new()
88    }
89}
90
91impl Hasher {
92    /// Creates a new `Hasher` instance.
93    pub fn new() -> Self {
94        Hasher(Sha3_256::new())
95    }
96
97    /// Process data, updating the internal state.
98    pub fn update<T: AsRef<[u8]>>(&mut self, data: &T) {
99        self.0.update(data.as_ref());
100    }
101
102    /// Reset hasher instance to its initial state.
103    pub fn reset(&mut self) {
104        self.0.reset();
105    }
106
107    /// Retrieve result and consume hasher instance.
108    pub fn finalize(self) -> Hash256 {
109        self.0.finalize().into()
110    }
111}
112
113// Helper for serde to force base16 encoding when serializing Hash256
114enum 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    /// Creates a new hash from a byte representation of some data.
175    ///
176    /// ```
177    /// # use borderless_hash::Hash256;
178    /// let data = "This is some data that can be hashed !";
179    /// let hash = Hash256::digest(&data);
180    /// ```
181    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    /// Creates a new hash from a byte representation of some data.
187    ///
188    /// A special byte `\x00` is fed into the hasher, before the data is added.
189    /// Can be used for merkle hash trees that conform to [`RFC6962`].
190    ///
191    /// [`RFC6962`]: https://www.rfc-editor.org/rfc/rfc6962#section-2.1
192    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    /// Creates a new hash from a byte representation of some data.
200    ///
201    /// A special byte `\x01` is fed into the hasher, before the data is added.
202    /// Can be used for merkle hash trees that conform to [`RFC6962`].
203    ///
204    /// [`RFC6962`]: https://www.rfc-editor.org/rfc/rfc6962#section-2.1
205    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    /// Creates a `Hash256`, where all bits are set to `0`.
213    ///
214    /// This is mostly used for testing, where we want to create hashes without some data.
215    pub fn zero() -> Self {
216        Hash256([0u8; 32])
217    }
218
219    /// Creates a new hash without any data.
220    ///
221    /// This returns the initial state of the hasher, without updating it with data.
222    /// The following variants all create the same output hash:
223    /// ```
224    /// # use borderless_hash::{Hash256, Hasher};
225    /// let hash = Hash256::empty();
226    /// let h2 = Hash256::digest(b"");
227    /// let mut hasher = Hasher::new();
228    /// let h3 = hasher.finalize();
229    ///
230    /// assert_eq!(hash, h2);
231    /// assert_eq!(hash, h3);
232    /// ```
233    pub fn empty() -> Self {
234        Hash256::digest(b"")
235    }
236
237    /// Constructs a new hash from two other hashes.
238    ///
239    /// Note: The sum of two hashes is not commutative, so the order of the hashes matter:
240    /// ```
241    /// # use borderless_hash::Hash256;
242    /// let h1 = Hash256::empty();
243    /// let h2 = Hash256::zero();
244    ///
245    /// assert_ne!(Hash256::sum(&h1, &h2), Hash256::sum(&h2, &h1));
246    /// ```
247    ///
248    /// Alternatively you can use the `+` operator directly, since the `Hash256` implements `Add`:
249    /// ```
250    /// # use borderless_hash::Hash256;
251    /// let h1 = Hash256::empty();
252    /// let h2 = Hash256::zero();
253    /// let sum = Hash256::sum(&h1, &h2);
254    ///
255    /// assert_eq!(h1 + h2, sum);
256    /// ```
257    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    /// Converts the hash to an u64 value.
265    ///
266    /// The `Hash256` can also be used to generate random values (which are equally distributed,
267    /// due to the cryptographic properties of the underlying hash-function).
268    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    /// Consumes the hash and returns the underlying byte-slice as a vector
283    pub fn into_vec(self) -> Vec<u8> {
284        self.into()
285    }
286
287    /// Consumes the hash and returns the underlying byte-slice
288    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/// Error that indicates an invalid slice length.
314///
315/// The `Hash256` can only be build from `[u8; 32]`,
316/// so if we try to create it from a slice of unknown size `&[u8]`,
317/// the operation may fail and return this error.
318#[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
404// Implement some traits for Sha256
405impl 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
449/// Simple traits that are based on the [`Hash256`] type
450pub mod traits {
451    use super::Hash256;
452
453    /// The `Hashed` trait indicates, that the hash over some data was already calculated and saved.
454    ///
455    /// Datatypes that internally save their hash can implement this, so that the hash does not need to be re-calculated
456    /// everytime we ask for it.
457    /// Note: All types that implement `Hashed` automatically implement `Hashable`,
458    /// since they can always return a copy of the internally saved hash.
459    pub trait Hashed {
460        /// Returns a reference to the pre-calculated hash of the datatype.
461        fn hash(&self) -> &Hash256;
462    }
463
464    // TODO: Maybe rename this to something like "id_hash" ? As this is not the raw hash of the binary data... idk
465    /// The `Hashable` trait indicates, that we can generate a [`Hash256`] from this type.
466    ///
467    /// Note: In general, we can calculate a `Hash256` from anything that implements `AsRef<[u8]>`,
468    /// but in our scenario not all items have a hash that is identical to their binary representation.
469    /// This trait is here to fix this issue, as implementers can define a complete custom method of
470    /// how the object-hash should be calculated.
471    pub trait Hashable {
472        /// Calculates and returns the hash of the datatype
473        fn calc_hash(&self) -> Hash256;
474    }
475
476    // All Types that implement 'Hashed' automatically implement 'Hashable'
477    impl<T: Hashed> Hashable for T {
478        fn calc_hash(&self) -> Hash256 {
479            *self.hash()
480        }
481    }
482
483    // Since the hash itself holds a hash...
484    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        // Calculate hash by concatenation
501        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        // Calculate hash using hasher update
511        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        // Sort this
622        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}