use alloc::vec::Vec;
use dusk_plonk::prelude::{Composer, Witness};
use dusk_safe::Sponge;
use super::io_pattern;
use crate::Domain;
use crate::hades::GadgetPermutation;
pub struct HashGadget<'a> {
domain: Domain,
input: Vec<&'a [Witness]>,
output_len: usize,
}
impl<'a> HashGadget<'a> {
pub fn new(domain: Domain) -> Self {
Self {
domain,
input: Vec::new(),
output_len: 1,
}
}
pub fn output_len(&mut self, output_len: usize) {
if self.domain == Domain::Other && output_len > 0 {
self.output_len = output_len;
}
}
pub fn update(&mut self, input: &'a [Witness]) {
self.input.push(input);
}
pub fn finalize(&self, composer: &mut Composer) -> Vec<Witness> {
let mut sponge = Sponge::start(
GadgetPermutation::new(composer),
io_pattern(self.domain, &self.input, self.output_len)
.expect("io-pattern should be valid"),
self.domain.into(),
)
.expect("at this point the io-pattern is valid");
for input in self.input.iter() {
sponge
.absorb(input.len(), input)
.expect("at this point the io-pattern is valid");
}
sponge
.squeeze(self.output_len)
.expect("at this point the io-pattern is valid");
sponge
.finish()
.expect("at this point the io-pattern is valid")
}
pub fn finalize_truncated(&self, composer: &mut Composer) -> Vec<Witness> {
let bls_output = self.finalize(composer);
bls_output
.iter()
.map(|bls| composer.append_logic_xor::<125>(*bls, Composer::ZERO))
.collect()
}
pub fn digest(
composer: &mut Composer,
domain: Domain,
input: &'a [Witness],
) -> Vec<Witness> {
let mut hash = Self::new(domain);
hash.update(input);
hash.finalize(composer)
}
pub fn digest_truncated(
composer: &mut Composer,
domain: Domain,
input: &'a [Witness],
) -> Vec<Witness> {
let mut hash = Self::new(domain);
hash.update(input);
hash.finalize_truncated(composer)
}
}