#[cfg(not(feature = "std"))]
use alloc::vec;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
pub use qp_plonky2_core::hashing::{
compress, hash_n_to_hash_no_pad, hash_n_to_hash_no_pad_p2, hash_n_to_m_no_pad,
PlonkyPermutation,
};
use crate::field::extension::Extendable;
use crate::gates::poseidon2::SPONGE_RATE;
use crate::hash::hash_types::{HashOutTarget, RichField, NUM_HASH_OUT_ELTS};
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::config::AlgebraicHasher;
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn hash_or_noop<H: AlgebraicHasher<F>>(&mut self, inputs: Vec<Target>) -> HashOutTarget {
let zero = self.zero();
if inputs.len() <= NUM_HASH_OUT_ELTS {
HashOutTarget::from_partial(&inputs, zero)
} else {
self.hash_n_to_hash_no_pad::<H>(inputs)
}
}
pub fn hash_n_to_hash_no_pad<H: AlgebraicHasher<F>>(
&mut self,
inputs: Vec<Target>,
) -> HashOutTarget {
HashOutTarget::from_vec(self.hash_n_to_m_no_pad::<H>(inputs, NUM_HASH_OUT_ELTS))
}
pub fn hash_n_to_m_no_pad<H: AlgebraicHasher<F>>(
&mut self,
inputs: Vec<Target>,
num_outputs: usize,
) -> Vec<Target> {
let zero = self.zero();
let mut state = H::AlgebraicPermutation::new(core::iter::repeat(zero));
for input_chunk in inputs.chunks(H::AlgebraicPermutation::RATE) {
state.set_from_slice(input_chunk, 0);
state = self.permute::<H>(state);
}
let mut outputs = Vec::with_capacity(num_outputs);
loop {
for &s in state.squeeze() {
outputs.push(s);
if outputs.len() == num_outputs {
return outputs;
}
}
state = self.permute::<H>(state);
}
}
pub fn hash_n_to_hash_no_pad_p2<H: AlgebraicHasher<F>>(
&mut self,
inputs: Vec<Target>,
) -> HashOutTarget {
let zero = self.zero();
let one = self.one();
let mut st = H::AlgebraicPermutation::new(core::iter::repeat(zero));
if SPONGE_RATE == 0 {
return HashOutTarget::from_vec(vec![zero; NUM_HASH_OUT_ELTS]);
}
let mut idx = 0usize;
while idx < inputs.len() {
let remaining = inputs.len() - idx;
let take = remaining.min(SPONGE_RATE);
let mut blk = vec![zero; SPONGE_RATE];
for i in 0..take {
blk[i] = inputs[idx + i];
}
if idx + take == inputs.len() && take < SPONGE_RATE {
blk[take] = one;
}
for i in 0..SPONGE_RATE {
let sum = self.add(st.as_ref()[i], blk[i]);
st.set_elt(sum, i);
}
st = self.permute::<H>(st);
idx += take;
}
if inputs.len() % SPONGE_RATE == 0 {
let mut blk = vec![zero; SPONGE_RATE];
blk[0] = one;
for i in 0..SPONGE_RATE {
let sum = self.add(st.as_ref()[i], blk[i]);
st.set_elt(sum, i);
}
st = self.permute::<H>(st);
}
let outs = st.squeeze()[..NUM_HASH_OUT_ELTS].to_vec();
HashOutTarget::from_vec(outs)
}
}