binius_examples/circuits/
hashsign.rs1use anyhow::Result;
8use binius_circuits::hash_based_sig::{
9 MESSAGE_LEN, Message,
10 aggregate::{MultiSigWires, circuit_xmss_multisig},
11 xmss::generate_signature,
12};
13use binius_frontend::{CircuitBuilder, WitnessFiller};
14use clap::Args;
15use rand::{Rng, SeedableRng, rngs::StdRng};
16
17use crate::ExampleCircuit;
18
19const SEED: u64 = 42;
21
22pub struct HashBasedSigExample {
23 num_signers: usize,
24 wires: MultiSigWires,
25}
26
27#[derive(Args, Debug, Clone)]
28pub struct Params {
29 #[arg(short = 'n', long, default_value_t = 3)]
31 pub num_signers: usize,
32}
33
34#[derive(Args, Debug, Clone)]
35pub struct Instance {}
36
37impl ExampleCircuit for HashBasedSigExample {
38 type Params = Params;
39 type Instance = Instance;
40
41 fn build(params: Params, builder: &mut CircuitBuilder) -> Result<Self> {
42 if params.num_signers == 0 {
43 anyhow::bail!("num_signers must be positive");
44 }
45
46 let wires = MultiSigWires::new(builder, params.num_signers);
47 circuit_xmss_multisig(builder, &wires);
48
49 Ok(Self {
50 num_signers: params.num_signers,
51 wires,
52 })
53 }
54
55 fn populate_witness(&self, _instance: Instance, w: &mut WitnessFiller<'_>) -> Result<()> {
56 let mut rng = StdRng::seed_from_u64(SEED);
57
58 let mut message: Message = [0u8; MESSAGE_LEN];
59 rng.fill_bytes(&mut message);
60 let mut epoch_bytes = [0u8; 4];
61 rng.fill_bytes(&mut epoch_bytes);
62 let epoch = u32::from_le_bytes(epoch_bytes);
63
64 let signatures = (0..self.num_signers)
66 .map(|_| generate_signature(&mut rng, &message, epoch))
67 .collect::<Vec<_>>();
68
69 self.wires.populate(w, &message, epoch, &signatures);
70 Ok(())
71 }
72
73 fn param_summary(params: &Self::Params) -> Option<String> {
74 Some(format!("{}s", params.num_signers))
75 }
76}