Skip to main content

binius_examples/circuits/
blake2s.rs

1// Copyright 2026 The Binius Developers
2// Copyright 2025 Irreducible Inc.
3
4use anyhow::Result;
5use binius_circuits::blake2s::Blake2s;
6use binius_frontend::{CircuitBuilder, WitnessFiller};
7use blake2::{Blake2s256, Digest};
8
9use super::utils::{self, HasherInstance, HasherMode, HasherParams};
10use crate::ExampleCircuit;
11
12/// Blake2s circuit example demonstrating the Blake2s hash function implementation
13pub struct Blake2sExample {
14	blake2s_gadget: Blake2s,
15	mode: HasherMode,
16}
17
18impl ExampleCircuit for Blake2sExample {
19	type Params = HasherParams;
20	type Instance = HasherInstance;
21
22	fn build(params: HasherParams, builder: &mut CircuitBuilder) -> Result<Self> {
23		// TODO: pass `supports_variable = true` and wire up a variable-length Blake2s gadget here
24		// once one exists in binius-circuits. Until then `--max-message-len` is rejected.
25		let mode = utils::resolve_hasher_mode(&params, "Blake2s", false)?;
26		let HasherMode::Fixed { len_bytes } = mode else {
27			unreachable!("Blake2s only supports the fixed-length gadget")
28		};
29
30		// Build the fixed-length Blake2s gadget for exactly this message length.
31		let blake2s_gadget = Blake2s::new_witness(builder, len_bytes);
32
33		Ok(Self {
34			blake2s_gadget,
35			mode,
36		})
37	}
38
39	fn populate_witness(&self, instance: HasherInstance, w: &mut WitnessFiller<'_>) -> Result<()> {
40		let message = utils::resolve_hasher_message(&self.mode, &instance)?;
41
42		// Compute digest using reference implementation
43		let mut hasher = Blake2s256::new();
44		hasher.update(&message);
45		let digest: [u8; 32] = hasher.finalize().into();
46
47		// Populate witness values (Blake2s doesn't use len_bytes)
48		self.blake2s_gadget.populate_message(w, &message);
49		self.blake2s_gadget.populate_digest(w, &digest);
50
51		Ok(())
52	}
53
54	fn param_summary(params: &Self::Params) -> Option<String> {
55		utils::hasher_param_summary(params)
56	}
57}