ark_circom/circom/
builder.rs1use ark_ff::PrimeField;
2use num_bigint::BigInt;
3use std::{collections::HashMap, fs::File, io::BufReader, path::Path};
4use wasmer::Store;
5
6use super::{CircomCircuit, R1CS};
7
8use crate::{
9 circom::R1CSFile,
10 witness::{Wasm, WitnessCalculator},
11};
12use color_eyre::Result;
13
14#[derive(Debug)]
15pub struct CircomBuilder<F: PrimeField> {
16 pub cfg: CircomConfig<F>,
17 pub inputs: HashMap<String, Vec<BigInt>>,
18}
19
20#[derive(Debug)]
22pub struct CircomConfig<F: PrimeField> {
23 pub r1cs: R1CS<F>,
24 pub wtns: WitnessCalculator,
25 pub store: Store,
26 pub sanity_check: bool,
27}
28
29impl<F: PrimeField> CircomConfig<F> {
30 pub fn new(wtns: impl AsRef<Path>, r1cs: impl AsRef<Path>) -> Result<Self> {
31 let mut store = Store::default();
32 let wtns = WitnessCalculator::new(&mut store, wtns).unwrap();
33 let reader = BufReader::new(File::open(r1cs)?);
34 let r1cs = R1CSFile::new(reader)?.into();
35 Ok(Self {
36 wtns,
37 r1cs,
38 store,
39 sanity_check: false,
40 })
41 }
42
43 pub fn new_from_wasm(wasm: Wasm, r1cs: impl AsRef<Path>) -> Result<Self> {
44 let mut store = Store::default();
45 let wtns = WitnessCalculator::new_from_wasm(&mut store, wasm).unwrap();
46 let reader = File::open(r1cs)?;
47 let r1cs = R1CSFile::new(reader)?.into();
48 Ok(Self {
49 wtns,
50 r1cs,
51 store,
52 sanity_check: false,
53 })
54 }
55}
56
57impl<F: PrimeField> CircomBuilder<F> {
58 pub fn new(cfg: CircomConfig<F>) -> Self {
61 Self {
62 cfg,
63 inputs: HashMap::new(),
64 }
65 }
66
67 pub fn push_input<T: Into<BigInt>>(&mut self, name: impl ToString, val: T) {
69 let values = self.inputs.entry(name.to_string()).or_default();
70 values.push(val.into());
71 }
72
73 pub fn setup(&self) -> CircomCircuit<F> {
76 let mut circom = CircomCircuit {
77 r1cs: self.cfg.r1cs.clone(),
78 witness: None,
79 };
80
81 circom.r1cs.wire_mapping = None;
83
84 circom
85 }
86
87 pub fn build(mut self) -> Result<CircomCircuit<F>> {
90 let mut circom = self.setup();
91
92 let witness = self.cfg.wtns.calculate_witness_element::<F, _>(
94 &mut self.cfg.store,
95 self.inputs,
96 self.cfg.sanity_check,
97 )?;
98 circom.witness = Some(witness);
99
100 debug_assert!({
102 use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
103 let cs = ConstraintSystem::<F>::new_ref();
104 circom.clone().generate_constraints(cs.clone()).unwrap();
105 let is_satisfied = cs.is_satisfied().unwrap();
106 if !is_satisfied {
107 println!(
108 "Unsatisfied constraint: {:?}",
109 cs.which_is_unsatisfied().unwrap()
110 );
111 }
112
113 is_satisfied
114 });
115
116 Ok(circom)
117 }
118}