-
Notifications
You must be signed in to change notification settings - Fork 122
/
Copy pathbuilder.rs
99 lines (83 loc) · 2.86 KB
/
builder.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use ark_ec::PairingEngine;
use std::{fs::File, path::Path};
use super::{CircomCircuit, R1CS};
use num_bigint::BigInt;
use std::collections::HashMap;
use crate::{circom::R1CSFile, witness::WitnessCalculator};
use color_eyre::Result;
#[derive(Clone, Debug)]
pub struct CircomBuilder<E: PairingEngine> {
pub cfg: CircomConfig<E>,
pub inputs: HashMap<String, Vec<BigInt>>,
}
// Add utils for creating this from files / directly from bytes
#[derive(Clone, Debug)]
pub struct CircomConfig<E: PairingEngine> {
pub r1cs: R1CS<E>,
pub wtns: WitnessCalculator,
pub sanity_check: bool,
}
impl<E: PairingEngine> CircomConfig<E> {
pub fn new(wtns: impl AsRef<Path>, r1cs: impl AsRef<Path>) -> Result<Self> {
let wtns = WitnessCalculator::new(wtns).unwrap();
let reader = File::open(r1cs)?;
let r1cs = R1CSFile::new(reader)?.into();
Ok(Self {
wtns,
r1cs,
sanity_check: false,
})
}
}
impl<E: PairingEngine> CircomBuilder<E> {
/// Instantiates a new builder using the provided WitnessGenerator and R1CS files
/// for your circuit
pub fn new(cfg: CircomConfig<E>) -> Self {
Self {
cfg,
inputs: HashMap::new(),
}
}
/// Pushes a Circom input at the specified name.
pub fn push_input<T: Into<BigInt>>(&mut self, name: impl ToString, val: T) {
let values = self.inputs.entry(name.to_string()).or_insert_with(Vec::new);
values.push(val.into());
}
/// Generates an empty circom circuit with no witness set, to be used for
/// generation of the trusted setup parameters
pub fn setup(&self) -> CircomCircuit<E> {
let mut circom = CircomCircuit {
r1cs: self.cfg.r1cs.clone(),
witness: None,
};
// Disable the wire mapping
circom.r1cs.wire_mapping = None;
circom
}
/// Creates the circuit populated with the witness corresponding to the previously
/// provided inputs
pub fn build(mut self) -> Result<CircomCircuit<E>> {
let mut circom = self.setup();
// calculate the witness
let witness = self
.cfg
.wtns
.calculate_witness_element::<E, _>(self.inputs, self.cfg.sanity_check)?;
circom.witness = Some(witness);
// sanity check
debug_assert!({
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
let cs = ConstraintSystem::<E::Fr>::new_ref();
circom.clone().generate_constraints(cs.clone()).unwrap();
let is_satisfied = cs.is_satisfied().unwrap();
if !is_satisfied {
println!(
"Unsatisfied constraint: {:?}",
cs.which_is_unsatisfied().unwrap()
);
}
is_satisfied
});
Ok(circom)
}
}