mirror of
https://github.com/arnaucube/circom-compat.git
synced 2026-01-28 22:46:40 +01:00
The motivation to do so, is so we can use the witness generation with other curves that don't have pairings (and hence the Pairing trait implemented).
100 lines
2.8 KiB
Rust
100 lines
2.8 KiB
Rust
use ark_ff::PrimeField;
|
|
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<F: PrimeField> {
|
|
pub cfg: CircomConfig<F>,
|
|
pub inputs: HashMap<String, Vec<BigInt>>,
|
|
}
|
|
|
|
// Add utils for creating this from files / directly from bytes
|
|
#[derive(Clone, Debug)]
|
|
pub struct CircomConfig<F: PrimeField> {
|
|
pub r1cs: R1CS<F>,
|
|
pub wtns: WitnessCalculator,
|
|
pub sanity_check: bool,
|
|
}
|
|
|
|
impl<F: PrimeField> CircomConfig<F> {
|
|
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<F: PrimeField> CircomBuilder<F> {
|
|
/// Instantiates a new builder using the provided WitnessGenerator and R1CS files
|
|
/// for your circuit
|
|
pub fn new(cfg: CircomConfig<F>) -> 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<F> {
|
|
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<F>> {
|
|
let mut circom = self.setup();
|
|
|
|
// calculate the witness
|
|
let witness = self
|
|
.cfg
|
|
.wtns
|
|
.calculate_witness_element::<F, _>(self.inputs, self.cfg.sanity_check)?;
|
|
circom.witness = Some(witness);
|
|
|
|
// sanity check
|
|
debug_assert!({
|
|
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
|
|
let cs = ConstraintSystem::<F>::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)
|
|
}
|
|
}
|