filecoin_hashers/
types.rs1use 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 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 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}