light_hasher/hash_chain.rs
1use crate::{Hasher, HasherError, Poseidon};
2
3/// Creates a hash chain from an array of [u8;32] arrays.
4///
5/// # Parameters
6/// - `inputs`: An array of [u8;32] arrays to be hashed.
7///
8/// # Returns
9/// - `Result<[u8; 32], HasherError>`: The resulting hash chain or an error.
10pub fn create_hash_chain_from_array<const T: usize>(
11 inputs: [[u8; 32]; T],
12) -> Result<[u8; 32], HasherError> {
13 create_hash_chain_from_slice(&inputs)
14}
15
16/// Creates a hash chain from a slice of [u8;32] arrays.
17///
18/// # Parameters
19/// - `inputs`: A slice of [u8;32] array to be hashed.
20///
21/// # Returns
22/// - `Result<[u8; 32], HasherError>`: The resulting hash chain or an error.
23pub fn create_hash_chain_from_slice(inputs: &[[u8; 32]]) -> Result<[u8; 32], HasherError> {
24 if inputs.is_empty() {
25 return Ok([0u8; 32]);
26 }
27 let mut hash_chain = inputs[0];
28 for input in inputs.iter().skip(1) {
29 hash_chain = Poseidon::hashv(&[&hash_chain, input])?;
30 }
31 Ok(hash_chain)
32}
33
34/// Creates a two inputs hash chain from two slices of [u8;32] arrays.
35/// The two slices must have the same length.
36/// Hashes are hashed in pairs, with the first hash from
37/// the first slice and the second hash from the second slice.
38/// H(i) = H(H(i-1), hashes_first[i], hashes_second[i])
39///
40/// # Parameters
41/// - `hashes_first`: A slice of [u8;32] arrays to be hashed first.
42/// - `hashes_second`: A slice of [u8;32] arrays to be hashed second.
43///
44/// # Returns
45/// - `Result<[u8; 32], HasherError>`: The resulting hash chain or an error.
46pub fn create_two_inputs_hash_chain(
47 hashes_first: &[[u8; 32]],
48 hashes_second: &[[u8; 32]],
49) -> Result<[u8; 32], HasherError> {
50 let first_len = hashes_first.len();
51 if first_len != hashes_second.len() {
52 return Err(HasherError::InvalidInputLength(
53 first_len,
54 hashes_second.len(),
55 ));
56 }
57 if hashes_first.is_empty() {
58 return Ok([0u8; 32]);
59 }
60 let mut hash_chain = Poseidon::hashv(&[&hashes_first[0], &hashes_second[0]])?;
61
62 if first_len == 1 {
63 return Ok(hash_chain);
64 }
65
66 for i in 1..first_len {
67 hash_chain = Poseidon::hashv(&[&hash_chain, &hashes_first[i], &hashes_second[i]])?;
68 }
69 Ok(hash_chain)
70}