binius_examples/circuits/
blake3_compress.rs1use anyhow::Result;
4use binius_circuits::blake3::blake3_compress_2x;
5use binius_core::word::Word;
6use binius_frontend::{CircuitBuilder, Wire, WitnessFiller};
7use clap::Args;
8use rand::prelude::*;
9
10use super::utils::DEFAULT_RANDOM_SEED;
11use crate::ExampleCircuit;
12
13const DEFAULT_NUM_COMPRESSIONS: usize = 16;
15
16pub struct Blake3CompressExample {
19 initial_cv: [Wire; 8],
20 pairs: Vec<PairInputs>,
21}
22
23struct PairInputs {
24 block: [Wire; 16],
25 counter_lo: Wire,
26 counter_hi: Wire,
27 block_len: Wire,
28 flags: Wire,
29}
30
31#[derive(Debug, Clone, Args)]
32pub struct Params {
33 #[arg(long)]
37 pub num_compressions: Option<usize>,
38}
39
40#[derive(Debug, Clone, Args)]
41pub struct Instance {
42 #[arg(long)]
44 pub seed: Option<u64>,
45}
46
47impl ExampleCircuit for Blake3CompressExample {
48 type Params = Params;
49 type Instance = Instance;
50
51 fn build(params: Params, builder: &mut CircuitBuilder) -> Result<Self> {
52 let num_compressions = params.num_compressions.unwrap_or(DEFAULT_NUM_COMPRESSIONS);
53 let n_pairs = num_compressions.div_ceil(2);
54
55 let initial_cv: [Wire; 8] = std::array::from_fn(|_| builder.add_witness());
56 let mut cv = initial_cv;
57 let mut pairs = Vec::with_capacity(n_pairs);
58
59 for _ in 0..n_pairs {
60 let block: [Wire; 16] = std::array::from_fn(|_| builder.add_witness());
61 let counter_lo = builder.add_witness();
62 let counter_hi = builder.add_witness();
63 let block_len = builder.add_witness();
64 let flags = builder.add_witness();
65
66 cv = blake3_compress_2x(builder, cv, block, counter_lo, counter_hi, block_len, flags);
67
68 pairs.push(PairInputs {
69 block,
70 counter_lo,
71 counter_hi,
72 block_len,
73 flags,
74 });
75 }
76
77 Ok(Self { initial_cv, pairs })
78 }
79
80 fn populate_witness(&self, instance: Instance, w: &mut WitnessFiller<'_>) -> Result<()> {
81 let mut rng = StdRng::seed_from_u64(instance.seed.unwrap_or(DEFAULT_RANDOM_SEED));
82 let mut next = || Word(rng.next_u64());
83
84 for wire in self.initial_cv {
85 w[wire] = next();
86 }
87 for pair in &self.pairs {
88 for b in pair.block {
89 w[b] = next();
90 }
91 w[pair.counter_lo] = next();
92 w[pair.counter_hi] = next();
93 w[pair.block_len] = next();
94 w[pair.flags] = next();
95 }
96
97 Ok(())
98 }
99
100 fn param_summary(params: &Self::Params) -> Option<String> {
101 Some(format!("{}c", params.num_compressions.unwrap_or(DEFAULT_NUM_COMPRESSIONS)))
102 }
103}