use super::*;
use crate::{
based,
belt::{montify, Belt},
};
pub fn assert_all_based(vecbelt: &[Belt]) {
vecbelt.iter().for_each(|b| based!(b.0));
}
pub fn tip5_calc_q_r(input_vec: &[Belt]) -> (usize, usize) {
let lent_input = input_vec.len();
let (q, r) = (lent_input / RATE, lent_input % RATE);
(q, r)
}
pub fn tip5_montify_vecbelt(input_vec: &mut [Belt]) {
for item in input_vec {
item.0 = montify(item.0);
}
}
pub fn tip5_calc_digest(sponge: &[u64; 16]) -> [u64; 5] {
let mut digest = [0; 5];
for i in 0..5 {
digest[i] = mont_reduction(sponge[i] as u128);
}
digest
}
pub fn create_init_sponge_variable() -> [u64; STATE_SIZE] {
[0u64; STATE_SIZE]
}
pub fn create_init_sponge_fixed() -> [u64; STATE_SIZE] {
let mut sponge = [0u64; STATE_SIZE];
for item in sponge.iter_mut().take(STATE_SIZE).skip(10) {
*item = 4294967295u64;
}
sponge
}
pub fn tip5_absorb_sponge<const PAD: bool>(sponge: &mut [u64; STATE_SIZE], input: &[Belt]) {
let l = input.len();
let r = l % RATE;
let (input, end) = input.as_chunks::<RATE>();
let input = input.iter().copied().chain(if PAD {
let mut r = [Belt(0); RATE];
let (a, b) = r.split_at_mut(end.len());
a.copy_from_slice(end);
let (a, b) = b.split_at_mut(1);
a[0] = Belt(1);
b.iter_mut().for_each(|v| *v = Belt(0));
Some(r)
} else {
debug_assert_eq!(r, 0);
None
});
for mut input_head in input {
tip5_montify_vecbelt(&mut input_head);
let input_head = input_head.map(|b| b.0);
sponge[..RATE].copy_from_slice(&input_head);
permute(sponge);
}
}
pub fn hash_varlen(input_vec: &[Belt]) -> [u64; 5] {
let mut sponge = create_init_sponge_variable();
assert_all_based(input_vec);
tip5_absorb_sponge::<true>(&mut sponge, input_vec);
tip5_calc_digest(&sponge)
}
pub fn hash_fixed(input_vec: &mut [Belt]) -> [u64; 5] {
let mut sponge = create_init_sponge_fixed();
assert_all_based(input_vec);
tip5_absorb_sponge::<false>(&mut sponge, input_vec);
tip5_calc_digest(&sponge)
}