1use crate::{Permutation, RescueError, RescueParameter, RescueSponge, RescueVector, CRHF_RATE};
10use ark_std::{borrow::Borrow, marker::PhantomData, string::ToString, vec, vec::Vec};
11use jf_crhf::CRHF;
12use jf_utils::pad_with_zeros;
13use spongefish::duplex_sponge::DuplexSpongeInterface;
14
15#[derive(Clone)]
17pub struct RescueCRHF<F: RescueParameter> {
18 sponge: RescueSponge<F, CRHF_RATE>,
19}
20
21impl<F: RescueParameter> RescueCRHF<F> {
22 pub fn sponge_with_bit_padding(input: &[F], num_outputs: usize) -> Vec<F> {
32 let mut padded = input.to_vec();
33 padded.push(F::one());
34 pad_with_zeros(&mut padded, CRHF_RATE);
35 Self::sponge_no_padding(padded.as_slice(), num_outputs)
36 .expect("Bug in JF Primitives : bad padding of input for sponge construction")
37 }
38
39 pub fn sponge_with_zero_padding(input: &[F], num_outputs: usize) -> Vec<F> {
45 let mut padded = input.to_vec();
46 pad_with_zeros(&mut padded, CRHF_RATE);
47 Self::sponge_no_padding(padded.as_slice(), num_outputs)
48 .expect("Bug in JF Primitives : bad padding of input for sponge construction")
49 }
50
51 pub fn sponge_no_padding(input: &[F], num_output: usize) -> Result<Vec<F>, RescueError> {
55 if input.len() % CRHF_RATE != 0 {
56 return Err(RescueError::ParameterError(
57 "Rescue sponge Error : input to sponge hashing function is not multiple of RATE."
58 .to_string(),
59 ));
60 }
61 let mut r = Self {
63 sponge: RescueSponge::default(),
64 };
65 r.sponge.absorb_unchecked(&input);
66
67 let mut output = vec![F::default(); num_output];
69 r.sponge.squeeze_unchecked(&mut output);
70 Ok(output)
71 }
72}
73
74#[derive(Debug, Clone)]
75pub struct FixedLengthRescueCRHF<
78 F: RescueParameter,
79 const INPUT_LEN: usize,
80 const OUTPUT_LEN: usize,
81>(PhantomData<F>);
82
83impl<F: RescueParameter, const INPUT_LEN: usize, const OUTPUT_LEN: usize> CRHF
84 for FixedLengthRescueCRHF<F, INPUT_LEN, OUTPUT_LEN>
85{
86 type Input = [F; INPUT_LEN];
87 type Output = [F; OUTPUT_LEN];
88 type Error = RescueError;
89
90 fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> {
95 let mut output = [F::zero(); OUTPUT_LEN];
96
97 let res = match INPUT_LEN % CRHF_RATE {
98 0 => RescueCRHF::<F>::sponge_no_padding(input.borrow(), OUTPUT_LEN)?,
99 _ => RescueCRHF::<F>::sponge_with_zero_padding(input.borrow(), OUTPUT_LEN),
100 };
101 if res.len() != OUTPUT_LEN {
102 return Err(RescueError::ParameterError(
103 "Unexpected rescue sponge return length".to_string(),
104 ));
105 }
106
107 output.copy_from_slice(&res[..]);
108 Ok(output)
109 }
110}
111
112#[derive(Debug, Clone)]
113pub struct VariableLengthRescueCRHF<F: RescueParameter, const OUTPUT_LEN: usize>(PhantomData<F>);
115
116impl<F: RescueParameter, const OUTPUT_LEN: usize> CRHF for VariableLengthRescueCRHF<F, OUTPUT_LEN> {
117 type Input = Vec<F>;
118 type Output = [F; OUTPUT_LEN];
119 type Error = RescueError;
120
121 fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> {
127 let mut output = [F::zero(); OUTPUT_LEN];
128 let res = RescueCRHF::<F>::sponge_with_bit_padding(input.borrow(), OUTPUT_LEN);
129 if res.len() != OUTPUT_LEN {
130 return Err(RescueError::ParameterError(
131 "Unexpected rescue sponge return length".to_string(),
132 ));
133 }
134 output.copy_from_slice(&res[..]);
135 Ok(output)
136 }
137}