use alloc::vec::Vec;
use super::{MODULUS, N, Nonce, Polynomial, Poseidon2, ZERO, math::FalconFelt};
use crate::{Felt, Word};
pub fn hash_to_point_poseidon2(message: Word, nonce: &Nonce) -> Polynomial<FalconFelt> {
let mut state = [ZERO; Poseidon2::STATE_WIDTH];
let nonce_elements = nonce.to_elements();
for (&n, s) in nonce_elements.iter().zip(state[Poseidon2::RATE_RANGE].iter_mut()) {
*s = n;
}
Poseidon2::apply_permutation(&mut state);
for (&m, s) in message.iter().zip(state[Poseidon2::RATE_RANGE].iter_mut()) {
*s = m;
}
let mut coefficients: Vec<FalconFelt> = Vec::with_capacity(N);
for _ in 0..64 {
Poseidon2::apply_permutation(&mut state);
state[Poseidon2::RATE_RANGE]
.iter()
.for_each(|value| coefficients.push(felt_to_falcon_felt(*value)));
}
Polynomial::new(coefficients)
}
#[cfg(test)]
pub fn hash_to_point_shake256(message: &[u8], nonce: &Nonce) -> Polynomial<FalconFelt> {
use sha3::{
Shake256,
digest::{ExtendableOutput, Update, XofReader},
};
let mut data = vec![];
data.extend_from_slice(&nonce.as_bytes());
data.extend_from_slice(message);
const K: u32 = (1u32 << 16) / MODULUS as u32;
let mut hasher = Shake256::default();
hasher.update(&data);
let mut reader = hasher.finalize_xof();
let mut coefficients: Vec<FalconFelt> = Vec::with_capacity(N);
while coefficients.len() != N {
let mut randomness = [0u8; 2];
reader.read(&mut randomness);
let t = ((randomness[0] as u32) << 8) | (randomness[1] as u32);
if t < K * MODULUS as u32 {
coefficients.push(u32_to_falcon_felt(t));
}
}
Polynomial { coefficients }
}
fn felt_to_falcon_felt(value: Felt) -> FalconFelt {
FalconFelt::new((value.as_canonical_u64() % MODULUS as u64) as i16)
}
#[cfg(test)]
fn u32_to_falcon_felt(value: u32) -> FalconFelt {
FalconFelt::new((value % MODULUS as u32) as i16)
}