use crate::{CompressionFunction, HashFunction};
use crate::expression::Expression;
use crate::field::{Element, Field};
use crate::gadget_builder::GadgetBuilder;
use crate::lcg::LCG;
pub struct MerkleDamgard<F: Field, CF: CompressionFunction<F>> {
initial_value: Element<F>,
compress: CF,
}
impl<F: Field, CF: CompressionFunction<F>> MerkleDamgard<F, CF> {
pub fn new(initial_value: Element<F>, compress: CF) -> Self {
MerkleDamgard { initial_value, compress }
}
pub fn new_defaults(compress: CF) -> Self {
let initial_value = LCG::new().next_element();
Self::new(initial_value, compress)
}
}
impl<F: Field, C: CompressionFunction<F>> HashFunction<F> for MerkleDamgard<F, C> {
fn hash(&self, builder: &mut GadgetBuilder<F>, blocks: &[Expression<F>]) -> Expression<F> {
let mut current = Expression::from(&self.initial_value);
for block in blocks {
current = self.compress.compress(builder, ¤t, block);
}
self.compress.compress(builder, ¤t, &Expression::from(blocks.len()))
}
}
#[cfg(test)]
mod tests {
use crate::{CompressionFunction, HashFunction, MerkleDamgard};
use crate::expression::Expression;
use crate::field::{Element, Field};
use crate::gadget_builder::GadgetBuilder;
use crate::test_util::F7;
#[test]
fn merkle_damgard() {
struct TestCompress;
impl<F: Field> CompressionFunction<F> for TestCompress {
fn compress(
&self, _builder: &mut GadgetBuilder<F>, x: &Expression<F>, y: &Expression<F>,
) -> Expression<F> {
x * 2 + y * 3
}
}
let mut builder = GadgetBuilder::<F7>::new();
let x_wire = builder.wire();
let y_wire = builder.wire();
let x = Expression::from(x_wire);
let y = Expression::from(y_wire);
let blocks = &[x, y];
let md = MerkleDamgard::new(Element::from(2u8), TestCompress);
let hash = md.hash(&mut builder, blocks);
let gadget = builder.build();
let mut values = values!(x_wire => 3u8.into(), y_wire => 4u8.into());
assert!(gadget.execute(&mut values));
assert_eq!(Element::from(5u8), hash.evaluate(&values));
}
}