essential_hash/
lib.rs

1//! A minimal crate containing Essential's [`hash`] function and associated pre-hash
2//! generic serialization implementation [`serialize`] based on [`postcard`].
3
4#![deny(missing_docs)]
5#![deny(unsafe_code)]
6
7use essential_types::{convert::bytes_from_word, ContentAddress, Hash, Word};
8use serde::Serialize;
9use sha2::Digest;
10
11mod address_impl;
12pub mod contract_addr;
13pub mod solution_set_addr;
14
15/// Standardized trait for creating content addresses for
16/// types using the correct constructors.
17pub trait Address {
18    /// Produce the content address for self.
19    fn content_address(&self) -> ContentAddress;
20}
21
22/// Serialize data for hashing using postcard.
23///
24/// This serialization format is standardized across essential crates.
25/// Attempting to hash data serialized with any other serialization
26/// implementation will almost certainly result in a different hash.
27pub fn serialize<T: Serialize>(t: &T) -> Vec<u8> {
28    postcard::to_allocvec(t).expect("`postcard`'s `Serializer` implementation should never fail")
29}
30
31/// Hash data using SHA-256.
32///
33/// Internally, this first serializes the given type using [`serialize`] then
34/// hashes the resulting slice of bytes using the `Sha256` digest.
35pub fn hash<T: Serialize>(t: &T) -> Hash {
36    let data = serialize(t);
37    let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
38    hasher.update(&data);
39    hasher.finalize().into()
40}
41
42/// Shorthand for hashing the given value in order to produce its content address.
43///
44/// Commonly useful for solutions, predicates and contracts.
45pub fn content_addr<T: Address>(t: &T) -> ContentAddress {
46    t.content_address()
47}
48
49/// Hash words in the same way that `Crypto::Sha256` does.
50pub fn hash_words(words: &[Word]) -> Hash {
51    let data = words
52        .iter()
53        .copied()
54        .flat_map(bytes_from_word)
55        .collect::<Vec<_>>();
56    let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
57    hasher.update(&data);
58    hasher.finalize().into()
59}
60
61/// Hash bytes without serializing them.
62pub fn hash_bytes(bytes: &[u8]) -> Hash {
63    let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
64    hasher.update(bytes);
65    hasher.finalize().into()
66}
67
68/// Hash bytes without serializing them.
69pub fn hash_bytes_iter<'i>(iter: impl IntoIterator<Item = &'i [u8]>) -> Hash {
70    let mut hasher = <sha2::Sha256 as sha2::Digest>::new();
71    for bytes in iter {
72        hasher.update(bytes);
73    }
74    hasher.finalize().into()
75}