Skip to main content

filecoin_hashers/
types.rs

1use std::fmt::Debug;
2use std::hash::Hash as StdHash;
3
4#[cfg(feature = "poseidon")]
5pub use crate::poseidon_types::*;
6
7use bellperson::{
8    gadgets::{boolean::Boolean, num::AllocatedNum},
9    ConstraintSystem, SynthesisError,
10};
11use blstrs::Scalar as Fr;
12use ff::PrimeField;
13use merkletree::{
14    hash::{Algorithm as LightAlgorithm, Hashable as LightHashable},
15    merkle::Element,
16};
17use rand::RngCore;
18use serde::{de::DeserializeOwned, Serialize};
19
20pub trait Domain:
21    Ord
22    + Copy
23    + Clone
24    + AsRef<[u8]>
25    + Default
26    + Debug
27    + Eq
28    + Send
29    + Sync
30    + From<Fr>
31    + From<<Fr as PrimeField>::Repr>
32    + Into<Fr>
33    + Serialize
34    + DeserializeOwned
35    + Element
36    + StdHash
37{
38    #[allow(clippy::wrong_self_convention)]
39    fn into_bytes(&self) -> Vec<u8>;
40    fn try_from_bytes(raw: &[u8]) -> anyhow::Result<Self>;
41    /// Write itself into the given slice, LittleEndian bytes.
42    fn write_bytes(&self, _: &mut [u8]) -> anyhow::Result<()>;
43
44    fn random<R: RngCore>(rng: &mut R) -> Self;
45}
46
47pub trait HashFunction<T: Domain>: Clone + Debug + Send + Sync + LightAlgorithm<T> {
48    fn hash(data: &[u8]) -> T;
49    fn hash2(a: &T, b: &T) -> T;
50    fn hash_md(input: &[T]) -> T {
51        // Default to binary.
52        assert!(input.len() > 1, "hash_md needs more than one element.");
53        input
54            .iter()
55            .skip(1)
56            .fold(input[0], |acc, elt| Self::hash2(&acc, elt))
57    }
58
59    fn hash_leaf(data: &dyn LightHashable<Self>) -> T {
60        let mut a = Self::default();
61        data.hash(&mut a);
62        let item_hash = a.hash();
63        a.leaf(item_hash)
64    }
65
66    fn hash_single_node(data: &dyn LightHashable<Self>) -> T {
67        let mut a = Self::default();
68        data.hash(&mut a);
69        a.hash()
70    }
71
72    fn hash_leaf_circuit<CS: ConstraintSystem<Fr>>(
73        mut cs: CS,
74        left: &AllocatedNum<Fr>,
75        right: &AllocatedNum<Fr>,
76        height: usize,
77    ) -> Result<AllocatedNum<Fr>, SynthesisError> {
78        let left_bits = left.to_bits_le(cs.namespace(|| "left num into bits"))?;
79        let right_bits = right.to_bits_le(cs.namespace(|| "right num into bits"))?;
80
81        Self::hash_leaf_bits_circuit(cs, &left_bits, &right_bits, height)
82    }
83
84    fn hash_multi_leaf_circuit<Arity: 'static + PoseidonArity, CS: ConstraintSystem<Fr>>(
85        cs: CS,
86        leaves: &[AllocatedNum<Fr>],
87        height: usize,
88    ) -> Result<AllocatedNum<Fr>, SynthesisError>;
89
90    fn hash_md_circuit<CS: ConstraintSystem<Fr>>(
91        _cs: &mut CS,
92        _elements: &[AllocatedNum<Fr>],
93    ) -> Result<AllocatedNum<Fr>, SynthesisError> {
94        unimplemented!();
95    }
96
97    fn hash_leaf_bits_circuit<CS: ConstraintSystem<Fr>>(
98        _cs: CS,
99        _left: &[Boolean],
100        _right: &[Boolean],
101        _height: usize,
102    ) -> Result<AllocatedNum<Fr>, SynthesisError> {
103        unimplemented!();
104    }
105
106    fn hash_circuit<CS: ConstraintSystem<Fr>>(
107        cs: CS,
108        bits: &[Boolean],
109    ) -> Result<AllocatedNum<Fr>, SynthesisError>;
110
111    fn hash2_circuit<CS>(
112        cs: CS,
113        a: &AllocatedNum<Fr>,
114        b: &AllocatedNum<Fr>,
115    ) -> Result<AllocatedNum<Fr>, SynthesisError>
116    where
117        CS: ConstraintSystem<Fr>;
118}
119
120pub trait Hasher: Clone + Debug + Eq + Default + Send + Sync {
121    type Domain: Domain + LightHashable<Self::Function> + AsRef<Self::Domain>;
122    type Function: HashFunction<Self::Domain>;
123
124    fn name() -> String;
125}