use super::matrix::matrix_vector_product;
use super::sbox::sbox;
use crate::{
circuit::sponge::circuit_generic_hash_num,
traits::{HashFamily, HashParams},
DomainStrategy,
};
use franklin_crypto::bellman::plonk::better_better_cs::cs::ConstraintSystem;
use crate::rescue::params::RescueParams;
use franklin_crypto::bellman::SynthesisError;
use franklin_crypto::{bellman::Engine, plonk::circuit::allocated_num::Num, plonk::circuit::linear_combination::LinearCombination};
pub fn circuit_rescue_hash<E: Engine, CS: ConstraintSystem<E>, const L: usize>(cs: &mut CS, input: &[Num<E>; L], domain_strategy: Option<DomainStrategy>) -> Result<[Num<E>; 2], SynthesisError> {
const WIDTH: usize = 3;
const RATE: usize = 2;
let params = RescueParams::<E, RATE, WIDTH>::default();
circuit_generic_hash_num(cs, input, ¶ms, domain_strategy)
}
pub(crate) fn circuit_rescue_round_function<E: Engine, CS: ConstraintSystem<E>, P: HashParams<E, RATE, WIDTH>, const RATE: usize, const WIDTH: usize>(
cs: &mut CS,
params: &P,
state: &mut [LinearCombination<E>; WIDTH],
) -> Result<(), SynthesisError> {
assert_eq!(params.hash_family(), HashFamily::Rescue, "Incorrect hash family!");
state.iter_mut().zip(params.constants_of_round(0).iter()).for_each(|(s, c)| s.add_assign_constant(*c));
for round in 0..2 * params.number_of_full_rounds() {
if round & 1 == 0 {
sbox(cs, params.alpha_inv(), state, None, params.custom_gate())?;
} else {
sbox(cs, params.alpha(), state, None, params.custom_gate())?;
}
matrix_vector_product(¶ms.mds_matrix(), state)?;
for (s, c) in state.iter_mut().zip(params.constants_of_round(round + 1).iter().cloned()) {
s.add_assign_constant(c);
}
}
Ok(())
}