From a8b03b56e1818897c28b9fdc811ad65d48f2d06c Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 28 May 2024 12:30:59 +0200 Subject: [PATCH] Fix allocated public inputs indexes (#1) * fix: manage already allocated public inputs with a custom mapping * fix: initialize CircomCircuit with empty allocated public input variables * feat: add ability to choose to allocate inputs as witnesses or instances * chore: remove outdated comment * test: add relevant tests and asserts for generate_constraints * chore: add files used for tests * chore: replace assert_eq with match statement --- src/circom/builder.rs | 3 +- src/circom/circuit.rs | 281 ++++++++++++++++++++--- test-vectors/mycircuit2.circom | 15 ++ test-vectors/mycircuit2.r1cs | Bin 0 -> 528 bytes test-vectors/mycircuit2.sym | 6 + test-vectors/mycircuit2.wasm | Bin 0 -> 34377 bytes test-vectors/mycircuit2_constraints.json | 7 + 7 files changed, 275 insertions(+), 37 deletions(-) create mode 100644 test-vectors/mycircuit2.circom create mode 100644 test-vectors/mycircuit2.r1cs create mode 100644 test-vectors/mycircuit2.sym create mode 100644 test-vectors/mycircuit2.wasm create mode 100644 test-vectors/mycircuit2_constraints.json diff --git a/src/circom/builder.rs b/src/circom/builder.rs index 5608210..222f7c9 100644 --- a/src/circom/builder.rs +++ b/src/circom/builder.rs @@ -58,7 +58,8 @@ impl CircomBuilder { let mut circom = CircomCircuit { r1cs: self.cfg.r1cs.clone(), witness: None, - inputs_already_allocated: false, + public_inputs_indexes: vec![], + allocate_inputs_as_witnesses: false, }; // Disable the wire mapping diff --git a/src/circom/circuit.rs b/src/circom/circuit.rs index 17e5d9f..5469e55 100644 --- a/src/circom/circuit.rs +++ b/src/circom/circuit.rs @@ -1,17 +1,28 @@ +use std::{collections::HashMap, f32::consts::E}; + use ark_ff::PrimeField; use ark_relations::r1cs::{ - ConstraintSynthesizer, ConstraintSystemRef, LinearCombination, SynthesisError, Variable, + self, ConstraintSynthesizer, ConstraintSystemRef, LinearCombination, SynthesisError, Variable, }; -use super::R1CS; - use color_eyre::Result; +use super::R1CS; + +/// `self.public_inputs_indexes` stores already allocated public variables. We assume that: +/// 1. `self.public_inputs_indexes` is sorted in the same order as circom's r1cs public inputs +/// 2. the first element of `self.public_inputs_indexes` is the first element *after* the last non yet allocated public input +/// example: +/// if circom public values are [1, out1, out2, in1, in2] (where out and in denote public signals only) +/// and `self.public_inputs_indexes` is [Variable(2), Variable(3)] +/// then we will allocate Variable(1), Variable(out1), Variable(out2) and consider that +/// Variable(in1) and Variable(in2) are already allocated as Variable(2), Variable(3) #[derive(Clone, Debug)] pub struct CircomCircuit { pub r1cs: R1CS, pub witness: Option>, - pub inputs_already_allocated: bool, + pub public_inputs_indexes: Vec, + pub allocate_inputs_as_witnesses: bool, } impl CircomCircuit { @@ -31,58 +42,111 @@ impl ConstraintSynthesizer for CircomCircuit { let witness = &self.witness; let wire_mapping = &self.r1cs.wire_mapping; - // Start from 1 because Arkworks implicitly allocates One for the first input - if !self.inputs_already_allocated { - for i in 1..self.r1cs.num_inputs { - cs.new_input_variable(|| { - Ok(match witness { - None => F::from(1u32), - Some(w) => match wire_mapping { - Some(m) => w[m[i]], - None => w[i], - }, - }) - })?; - } + // Since our cs might already have allocated constraints, + // We store a mapping between circom's defined indexes and the newly obtained cs indexes + let mut circom_index_to_cs_index = HashMap::new(); + + // constant 1 at idx 0 is already allocated by arkworks + circom_index_to_cs_index.insert(0, Variable::One); + + // length pub inputs - constant 1 (already allocated by arkworks) - length already allocated pub inputs + let n_non_allocated_inputs = self.r1cs.num_inputs - 1 - self.public_inputs_indexes.len(); + + // allocate non-allocated inputs and update mapping + for circom_public_input_index in 1..=n_non_allocated_inputs { + let variable = match self.allocate_inputs_as_witnesses { + true => { + let witness_var = Variable::Witness(cs.num_witness_variables()); + cs.new_witness_variable(|| { + Ok(match witness { + None => F::from(1u32), + Some(w) => match wire_mapping { + Some(m) => w[m[circom_public_input_index]], + None => w[circom_public_input_index], + }, + }) + })?; + witness_var + } + false => { + let instance_var = Variable::Instance(cs.num_instance_variables()); + cs.new_input_variable(|| { + Ok(match witness { + None => F::from(1u32), + Some(w) => match wire_mapping { + Some(m) => w[m[circom_public_input_index]], + None => w[circom_public_input_index], + }, + }) + })?; + instance_var + } + }; + circom_index_to_cs_index.insert(circom_public_input_index, variable); + } + + // update mapping with already allocated public inputs + for circom_public_input_index in (n_non_allocated_inputs + 1)..self.r1cs.num_inputs { + let access_input_index = circom_public_input_index - n_non_allocated_inputs - 1; + circom_index_to_cs_index.insert( + circom_public_input_index, + self.public_inputs_indexes[access_input_index], + ); } + match ( + circom_index_to_cs_index.get(&0), + circom_index_to_cs_index.len(), + ) == (Some(&Variable::One), self.r1cs.num_inputs) + { + true => Ok(()), + false => Err(SynthesisError::Unsatisfiable), + }?; + for i in 0..self.r1cs.num_aux { + let circom_defined_r1cs_index = i + self.r1cs.num_inputs; + circom_index_to_cs_index.insert( + circom_defined_r1cs_index, + Variable::Witness(cs.num_witness_variables()), + ); cs.new_witness_variable(|| { Ok(match witness { None => F::from(1u32), Some(w) => match wire_mapping { Some(m) => w[m[i + self.r1cs.num_inputs]], - None => w[i + self.r1cs.num_inputs], + None => w[circom_defined_r1cs_index], }, }) })?; } let make_index = |index| { - if index < self.r1cs.num_inputs { - Variable::Instance(index) - } else { - Variable::Witness(index - self.r1cs.num_inputs) - } + let new_index = match circom_index_to_cs_index.get(&index) { + Some(i) => Ok(*i), + None => Err(SynthesisError::AssignmentMissing), + }; + Ok(new_index?) }; + let make_lc = |lc_data: &[(usize, F)]| { - lc_data.iter().fold( + lc_data.iter().try_fold( LinearCombination::::zero(), - |lc: LinearCombination, (index, coeff)| lc + (*coeff, make_index(*index)), + |lc: LinearCombination, (index, coeff)| { + let r1cs_index = make_index(*index); + match r1cs_index { + Ok(r1cs_index) => Ok(lc + (*coeff, r1cs_index)), + Err(e) => Err(e), + } + }, ) }; - let skip = if self.inputs_already_allocated { - self.r1cs.num_inputs - } else { - 0 - }; - for constraint in self.r1cs.constraints.iter().skip(skip) { - cs.enforce_constraint( - make_lc(&constraint.0), - make_lc(&constraint.1), - make_lc(&constraint.2), - )?; + for constraint in self.r1cs.constraints.iter() { + let a = make_lc(&constraint.0)?; + let b = make_lc(&constraint.1)?; + let c = make_lc(&constraint.2)?; + let res = cs.enforce_constraint(a, b, c); + res? } Ok(()) @@ -95,6 +159,7 @@ mod tests { use crate::{CircomBuilder, CircomConfig}; use ark_bn254::Fr; use ark_relations::r1cs::ConstraintSystem; + use num_bigint::BigInt; #[test] fn satisfied() { @@ -112,4 +177,148 @@ mod tests { circom.generate_constraints(cs.clone()).unwrap(); assert!(cs.is_satisfied().unwrap()); } + + #[test] + fn no_public_inputs_allocated() { + let mut cfg = CircomConfig::::new( + "./test-vectors/mycircuit2.wasm", + "./test-vectors/mycircuit2.r1cs", + ) + .unwrap(); + + let inputs = vec![ + ("a".to_string(), vec![BigInt::from(3)]), + ("b".to_string(), vec![BigInt::from(3)]), + ("c".to_string(), vec![BigInt::from(3)]), + ]; + + let witness = cfg.wtns.calculate_witness_element(inputs, true).unwrap(); + + // satisfy with inputs as instance variables + let mut circom = CircomCircuit { + r1cs: cfg.r1cs.clone(), + witness: Some(witness.clone()), + public_inputs_indexes: vec![], + allocate_inputs_as_witnesses: false, + }; + + let cs = ConstraintSystem::::new_ref(); + circom.clone().generate_constraints(cs.clone()).unwrap(); + assert_eq!(cs.num_witness_variables(), 2); + assert_eq!(cs.num_instance_variables(), 5); + assert!(cs.is_satisfied().unwrap()); + + // satisfy with inputs as witness variables + let cs = ConstraintSystem::::new_ref(); + circom.allocate_inputs_as_witnesses = true; + circom.generate_constraints(cs.clone()).unwrap(); + + assert_eq!(cs.num_witness_variables(), 6); + assert_eq!(cs.num_instance_variables(), 1); + assert!(cs.is_satisfied().unwrap()); + } + + #[test] + fn all_public_inputs_allocated() { + let mut cfg = CircomConfig::::new( + "./test-vectors/mycircuit2.wasm", + "./test-vectors/mycircuit2.r1cs", + ) + .unwrap(); + + let inputs = vec![ + ("a".to_string(), vec![BigInt::from(3)]), + ("b".to_string(), vec![BigInt::from(3)]), + ("c".to_string(), vec![BigInt::from(3)]), + ]; + + let witness = cfg.wtns.calculate_witness_element(inputs, true).unwrap(); + + // satisfy with inputs as instance variables + let mut circom = CircomCircuit { + r1cs: cfg.r1cs.clone(), + witness: Some(witness.clone()), + public_inputs_indexes: vec![], + allocate_inputs_as_witnesses: false, + }; + + let cs = ConstraintSystem::::new_ref(); + + // allocate all public input variables (except 1) as instance variables and push their indexes + for i in 1..cfg.r1cs.num_inputs { + circom + .public_inputs_indexes + .push(Variable::Instance(cs.num_instance_variables())); + cs.new_input_variable(|| Ok(witness[i])).unwrap(); + } + + circom.clone().generate_constraints(cs.clone()).unwrap(); + + assert_eq!(cs.num_witness_variables(), 2); + assert_eq!(cs.num_instance_variables(), 5); + assert!(cs.is_satisfied().unwrap()); + } + + #[test] + fn some_public_inputs_allocated() { + let mut cfg = CircomConfig::::new( + "./test-vectors/mycircuit2.wasm", + "./test-vectors/mycircuit2.r1cs", + ) + .unwrap(); + + let inputs = vec![ + ("a".to_string(), vec![BigInt::from(3)]), + ("b".to_string(), vec![BigInt::from(3)]), + ("c".to_string(), vec![BigInt::from(3)]), + ]; + + let witness = cfg.wtns.calculate_witness_element(inputs, true).unwrap(); + + // satisfy with inputs as instance variables + let mut circom = CircomCircuit { + r1cs: cfg.r1cs.clone(), + witness: Some(witness.clone()), + public_inputs_indexes: vec![], + allocate_inputs_as_witnesses: false, + }; + + let cs = ConstraintSystem::::new_ref(); + + // allocate all some input variables as instance variables and push their indexes + // recall that it should start with the first non-allocated public input + for i in 3..cfg.r1cs.num_inputs { + circom + .public_inputs_indexes + .push(Variable::Instance(cs.num_instance_variables())); + cs.new_input_variable(|| Ok(witness[i])).unwrap(); + } + + circom.clone().generate_constraints(cs.clone()).unwrap(); + + assert_eq!(cs.num_witness_variables(), 2); + assert_eq!(cs.num_instance_variables(), 5); + assert!(cs.is_satisfied().unwrap()); + + // re-init and now satisfy with inputs as witness variables + let mut circom = CircomCircuit { + r1cs: cfg.r1cs.clone(), + witness: Some(witness.clone()), + public_inputs_indexes: vec![], + allocate_inputs_as_witnesses: false, + }; + + let cs = ConstraintSystem::::new_ref(); + for i in 3..cfg.r1cs.num_inputs { + circom + .public_inputs_indexes + .push(Variable::Instance(cs.num_instance_variables())); + cs.new_input_variable(|| Ok(witness[i])).unwrap(); + } + circom.allocate_inputs_as_witnesses = true; + circom.generate_constraints(cs.clone()).unwrap(); + + assert_eq!(cs.num_witness_variables(), 4); + assert_eq!(cs.num_instance_variables(), 3); + } } diff --git a/test-vectors/mycircuit2.circom b/test-vectors/mycircuit2.circom new file mode 100644 index 0000000..4a18598 --- /dev/null +++ b/test-vectors/mycircuit2.circom @@ -0,0 +1,15 @@ +template Multiplier() { + signal input a; // 3 + signal input b; // 3 + signal input c; // 3 + signal temp; + signal output d; // 27 + signal output e; // 9 + + temp <== a*b; + d <== temp*c; + e <== b*c; +} + +component main{public [a, b]} = Multiplier(); + diff --git a/test-vectors/mycircuit2.r1cs b/test-vectors/mycircuit2.r1cs new file mode 100644 index 0000000000000000000000000000000000000000..34611b9db030fdfd6452459115270d38e732e74f GIT binary patch literal 528 zcmXRiOfF_*U|?VdVkRKY0C9i-CI)1FnEdsj^TdLkl^!pQHDV(g8@IUz?9g0b_^`+? z#Q>y^1*#rM;RGOcY!F$3<`Juo6=)vRxp?h`sv&4E$R9vJP#v-Mg2Iy+^Blm+7#I|Q yG|;Vh?Pmw70htTJAb)}QAOMO#5VinukO0*0VD%tjkQxwx`jr9X7Z8AkIRgOk=4Q44 literal 0 HcmV?d00001 diff --git a/test-vectors/mycircuit2.sym b/test-vectors/mycircuit2.sym new file mode 100644 index 0000000..10ee4df --- /dev/null +++ b/test-vectors/mycircuit2.sym @@ -0,0 +1,6 @@ +1,1,0,main.d +2,2,0,main.e +3,3,0,main.a +4,4,0,main.b +5,5,0,main.c +6,6,0,main.temp diff --git a/test-vectors/mycircuit2.wasm b/test-vectors/mycircuit2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5b6786fc2d1a251fcb78ac3d8ad53e95b3d6880c GIT binary patch literal 34377 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 Tu~?c(35=jRjrrxIC;a~bxIiEf literal 0 HcmV?d00001 diff --git a/test-vectors/mycircuit2_constraints.json b/test-vectors/mycircuit2_constraints.json new file mode 100644 index 0000000..c0b721d --- /dev/null +++ b/test-vectors/mycircuit2_constraints.json @@ -0,0 +1,7 @@ +{ +"constraints": [ +[{"3":"21888242871839275222246405745257275088548364400416034343698204186575808495616"},{"4":"1"},{"6":"21888242871839275222246405745257275088548364400416034343698204186575808495616"}], +[{"6":"21888242871839275222246405745257275088548364400416034343698204186575808495616"},{"5":"1"},{"1":"21888242871839275222246405745257275088548364400416034343698204186575808495616"}], +[{"4":"21888242871839275222246405745257275088548364400416034343698204186575808495616"},{"5":"1"},{"2":"21888242871839275222246405745257275088548364400416034343698204186575808495616"}] +] +} \ No newline at end of file