1use core::marker::PhantomData;
4
5use ark_ff::{Field, PrimeField};
6use ark_std::{borrow::Borrow, string::ToString, vec::Vec};
7use jf_crhf::CRHF;
8use nimue::{
9 hash::sponge::{DuplexSponge, Sponge},
10 DuplexHash, Unit,
11};
12
13use crate::{sponge::Poseidon2Sponge, Poseidon2Error};
14
15#[derive(Clone)]
22pub struct FixedLenPoseidon2Hash<F, S, const INPUT_SIZE: usize, const OUTPUT_SIZE: usize>
23where
24 F: PrimeField + Unit,
25 S: Sponge<U = F> + Poseidon2Sponge,
26{
27 _field: PhantomData<F>,
28 _sponge: PhantomData<S>,
29}
30
31impl<F, S, const IN: usize, const OUT: usize> CRHF for FixedLenPoseidon2Hash<F, S, IN, OUT>
32where
33 F: PrimeField + Unit,
34 S: Sponge<U = F> + Poseidon2Sponge,
35{
36 type Input = [F]; type Output = [F; OUT];
38 type Error = Poseidon2Error;
39
40 fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> {
41 let input = input.borrow();
42 if input.len() > IN {
43 return Err(Poseidon2Error::ParamErr("hash input too long".to_string()));
44 }
45
46 let mut padded = Vec::from(input);
47 zero_padding(&mut padded, IN);
48
49 let mut sponge = DuplexSponge::<S>::default();
50 sponge.absorb_unchecked(&padded);
51 let mut output = [F::default(); OUT];
52 sponge.squeeze_unchecked(&mut output);
53 Ok(output)
54 }
55}
56
57#[derive(Debug, Clone)]
60pub struct VariableLenPoseidon2Hash<F, S, const OUTPUT_SIZE: usize>
61where
62 F: PrimeField + Unit,
63 S: Sponge<U = F>,
64{
65 _field: PhantomData<F>,
66 _sponge: PhantomData<S>,
67}
68
69impl<F, S, const OUT: usize> CRHF for VariableLenPoseidon2Hash<F, S, OUT>
70where
71 F: PrimeField + Unit,
72 S: Sponge<U = F>,
73{
74 type Input = [F];
75 type Output = [F; OUT];
76 type Error = Poseidon2Error;
77
78 fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> {
79 let mut padded = Vec::from(input.borrow());
80 bit_padding(&mut padded, S::R);
81
82 let mut sponge = DuplexSponge::<S>::default();
83 sponge.absorb_unchecked(&padded);
84 let mut output = [F::default(); OUT];
85 sponge.squeeze_unchecked(&mut output);
86 Ok(output)
87 }
88}
89
90#[inline(always)]
92fn zero_padding<F: Field>(data: &mut Vec<F>, multiple: usize) {
93 data.resize(data.len().next_multiple_of(multiple), F::zero());
94}
95
96#[inline(always)]
99fn bit_padding<F: Field>(data: &mut Vec<F>, multiple: usize) {
100 data.push(F::one());
101 zero_padding(data, multiple);
102}