diff --git a/src/circom/builder.rs b/src/circom/builder.rs index 670e22b..63fab22 100644 --- a/src/circom/builder.rs +++ b/src/circom/builder.rs @@ -1,4 +1,4 @@ -use ark_ec::pairing::Pairing; +use ark_ff::PrimeField; use std::{fs::File, path::Path}; use super::{CircomCircuit, R1CS}; @@ -10,20 +10,20 @@ use crate::{circom::R1CSFile, witness::WitnessCalculator}; use color_eyre::Result; #[derive(Clone, Debug)] -pub struct CircomBuilder { - pub cfg: CircomConfig, +pub struct CircomBuilder { + pub cfg: CircomConfig, pub inputs: HashMap>, } // Add utils for creating this from files / directly from bytes #[derive(Clone, Debug)] -pub struct CircomConfig { - pub r1cs: R1CS, +pub struct CircomConfig { + pub r1cs: R1CS, pub wtns: WitnessCalculator, pub sanity_check: bool, } -impl CircomConfig { +impl CircomConfig { pub fn new(wtns: impl AsRef, r1cs: impl AsRef) -> Result { let wtns = WitnessCalculator::new(wtns).unwrap(); let reader = File::open(r1cs)?; @@ -36,10 +36,10 @@ impl CircomConfig { } } -impl CircomBuilder { +impl CircomBuilder { /// Instantiates a new builder using the provided WitnessGenerator and R1CS files /// for your circuit - pub fn new(cfg: CircomConfig) -> Self { + pub fn new(cfg: CircomConfig) -> Self { Self { cfg, inputs: HashMap::new(), @@ -54,7 +54,7 @@ impl CircomBuilder { /// Generates an empty circom circuit with no witness set, to be used for /// generation of the trusted setup parameters - pub fn setup(&self) -> CircomCircuit { + pub fn setup(&self) -> CircomCircuit { let mut circom = CircomCircuit { r1cs: self.cfg.r1cs.clone(), witness: None, @@ -68,20 +68,20 @@ impl CircomBuilder { /// Creates the circuit populated with the witness corresponding to the previously /// provided inputs - pub fn build(mut self) -> Result> { + pub fn build(mut self) -> Result> { let mut circom = self.setup(); // calculate the witness let witness = self .cfg .wtns - .calculate_witness_element::(self.inputs, self.cfg.sanity_check)?; + .calculate_witness_element::(self.inputs, self.cfg.sanity_check)?; circom.witness = Some(witness); // sanity check debug_assert!({ use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem}; - let cs = ConstraintSystem::::new_ref(); + let cs = ConstraintSystem::::new_ref(); circom.clone().generate_constraints(cs.clone()).unwrap(); let is_satisfied = cs.is_satisfied().unwrap(); if !is_satisfied { diff --git a/src/circom/circuit.rs b/src/circom/circuit.rs index 12540e9..7895712 100644 --- a/src/circom/circuit.rs +++ b/src/circom/circuit.rs @@ -1,4 +1,4 @@ -use ark_ec::pairing::Pairing; +use ark_ff::PrimeField; use ark_relations::r1cs::{ ConstraintSynthesizer, ConstraintSystemRef, LinearCombination, SynthesisError, Variable, }; @@ -8,13 +8,13 @@ use super::R1CS; use color_eyre::Result; #[derive(Clone, Debug)] -pub struct CircomCircuit { - pub r1cs: R1CS, - pub witness: Option>, +pub struct CircomCircuit { + pub r1cs: R1CS, + pub witness: Option>, } -impl CircomCircuit { - pub fn get_public_inputs(&self) -> Option> { +impl CircomCircuit { + pub fn get_public_inputs(&self) -> Option> { match &self.witness { None => None, Some(w) => match &self.r1cs.wire_mapping { @@ -25,11 +25,8 @@ impl CircomCircuit { } } -impl ConstraintSynthesizer for CircomCircuit { - fn generate_constraints( - self, - cs: ConstraintSystemRef, - ) -> Result<(), SynthesisError> { +impl ConstraintSynthesizer for CircomCircuit { + fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { let witness = &self.witness; let wire_mapping = &self.r1cs.wire_mapping; @@ -37,7 +34,7 @@ impl ConstraintSynthesizer for CircomCircuit { for i in 1..self.r1cs.num_inputs { cs.new_input_variable(|| { Ok(match witness { - None => E::ScalarField::from(1u32), + None => F::from(1u32), Some(w) => match wire_mapping { Some(m) => w[m[i]], None => w[i], @@ -49,7 +46,7 @@ impl ConstraintSynthesizer for CircomCircuit { for i in 0..self.r1cs.num_aux { cs.new_witness_variable(|| { Ok(match witness { - None => E::ScalarField::from(1u32), + 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], @@ -65,12 +62,10 @@ impl ConstraintSynthesizer for CircomCircuit { Variable::Witness(index - self.r1cs.num_inputs) } }; - let make_lc = |lc_data: &[(usize, E::ScalarField)]| { + let make_lc = |lc_data: &[(usize, F)]| { lc_data.iter().fold( - LinearCombination::::zero(), - |lc: LinearCombination, (index, coeff)| { - lc + (*coeff, make_index(*index)) - }, + LinearCombination::::zero(), + |lc: LinearCombination, (index, coeff)| lc + (*coeff, make_index(*index)), ) }; @@ -90,12 +85,12 @@ impl ConstraintSynthesizer for CircomCircuit { mod tests { use super::*; use crate::{CircomBuilder, CircomConfig}; - use ark_bn254::{Bn254, Fr}; + use ark_bn254::Fr; use ark_relations::r1cs::ConstraintSystem; #[test] fn satisfied() { - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/mycircuit.wasm", "./test-vectors/mycircuit.r1cs", ) diff --git a/src/circom/mod.rs b/src/circom/mod.rs index 6ad7fd0..080eb2d 100644 --- a/src/circom/mod.rs +++ b/src/circom/mod.rs @@ -1,5 +1,3 @@ -use ark_ec::pairing::Pairing; - pub mod r1cs_reader; pub use r1cs_reader::{R1CSFile, R1CS}; @@ -12,5 +10,5 @@ pub use builder::{CircomBuilder, CircomConfig}; mod qap; pub use qap::CircomReduction; -pub type Constraints = (ConstraintVec, ConstraintVec, ConstraintVec); -pub type ConstraintVec = Vec<(usize, ::ScalarField)>; +pub type Constraints = (ConstraintVec, ConstraintVec, ConstraintVec); +pub type ConstraintVec = Vec<(usize, F)>; diff --git a/src/circom/r1cs_reader.rs b/src/circom/r1cs_reader.rs index b5db104..eb0ea43 100644 --- a/src/circom/r1cs_reader.rs +++ b/src/circom/r1cs_reader.rs @@ -4,8 +4,8 @@ use byteorder::{LittleEndian, ReadBytesExt}; use std::io::{Error, ErrorKind}; -use ark_ec::pairing::Pairing; -use ark_serialize::{CanonicalDeserialize, SerializationError, SerializationError::IoError}; +use ark_ff::PrimeField; +use ark_serialize::{SerializationError, SerializationError::IoError}; use ark_std::io::{Read, Seek, SeekFrom}; use std::collections::HashMap; @@ -15,16 +15,16 @@ type IoResult = Result; use super::{ConstraintVec, Constraints}; #[derive(Clone, Debug)] -pub struct R1CS { +pub struct R1CS { pub num_inputs: usize, pub num_aux: usize, pub num_variables: usize, - pub constraints: Vec>, + pub constraints: Vec>, pub wire_mapping: Option>, } -impl From> for R1CS { - fn from(file: R1CSFile) -> Self { +impl From> for R1CS { + fn from(file: R1CSFile) -> Self { let num_inputs = (1 + file.header.n_pub_in + file.header.n_pub_out) as usize; let num_variables = file.header.n_wires as usize; let num_aux = num_variables - num_inputs; @@ -38,20 +38,20 @@ impl From> for R1CS { } } -pub struct R1CSFile { +pub struct R1CSFile { pub version: u32, pub header: Header, - pub constraints: Vec>, + pub constraints: Vec>, pub wire_mapping: Vec, } -impl R1CSFile { +impl R1CSFile { /// reader must implement the Seek trait, for example with a Cursor /// /// ```rust,ignore /// let reader = BufReader::new(Cursor::new(&data[..])); /// ``` - pub fn new(mut reader: R) -> IoResult> { + pub fn new(mut reader: R) -> IoResult> { let mut magic = [0u8; 4]; reader.read_exact(&mut magic)?; if magic != [0x72, 0x31, 0x63, 0x73] { @@ -117,7 +117,7 @@ impl R1CSFile { reader.seek(SeekFrom::Start(*constraint_offset?))?; - let constraints = read_constraints::<&mut R, E>(&mut reader, &header)?; + let constraints = read_constraints::<&mut R, F>(&mut reader, &header)?; let wire2label_offset = sec_offsets.get(&wire2label_type).ok_or_else(|| { Error::new( @@ -177,15 +177,16 @@ impl Header { let mut prime_size = vec![0u8; field_size as usize]; reader.read_exact(&mut prime_size)?; - if prime_size - != hex::decode("010000f093f5e1439170b97948e833285d588181b64550b829a031e1724e6430") - .unwrap() - { - return Err(IoError(Error::new( - ErrorKind::InvalidData, - "This parser only supports bn256", - ))); - } + // TODO WIP + // if prime_size + // != hex::decode("010000f093f5e1439170b97948e833285d588181b64550b829a031e1724e6430") + // .unwrap() + // { + // return Err(IoError(Error::new( + // ErrorKind::InvalidData, + // "This parser only supports bn256", + // ))); + // } Ok(Header { field_size, @@ -200,29 +201,29 @@ impl Header { } } -fn read_constraint_vec(mut reader: R) -> IoResult> { +fn read_constraint_vec(mut reader: R) -> IoResult> { let n_vec = reader.read_u32::()? as usize; let mut vec = Vec::with_capacity(n_vec); for _ in 0..n_vec { vec.push(( reader.read_u32::()? as usize, - E::ScalarField::deserialize_uncompressed(&mut reader)?, + F::deserialize_uncompressed(&mut reader)?, )); } Ok(vec) } -fn read_constraints( +fn read_constraints( mut reader: R, header: &Header, -) -> IoResult>> { +) -> IoResult>> { // todo check section size let mut vec = Vec::with_capacity(header.n_constraints as usize); for _ in 0..header.n_constraints { vec.push(( - read_constraint_vec::<&mut R, E>(&mut reader)?, - read_constraint_vec::<&mut R, E>(&mut reader)?, - read_constraint_vec::<&mut R, E>(&mut reader)?, + read_constraint_vec::<&mut R, F>(&mut reader)?, + read_constraint_vec::<&mut R, F>(&mut reader)?, + read_constraint_vec::<&mut R, F>(&mut reader)?, )); } Ok(vec) @@ -251,7 +252,7 @@ fn read_map(mut reader: R, size: u64, header: &Header) -> IoResult::new(reader).unwrap(); + let file = R1CSFile::::new(reader).unwrap(); assert_eq!(file.version, 1); assert_eq!(file.header.field_size, 32); diff --git a/src/witness/witness_calculator.rs b/src/witness/witness_calculator.rs index 49582b9..a859394 100644 --- a/src/witness/witness_calculator.rs +++ b/src/witness/witness_calculator.rs @@ -1,4 +1,5 @@ use super::{fnv, CircomBase, SafeMemory, Wasm}; +use ark_ff::PrimeField; use color_eyre::Result; use num_bigint::BigInt; use num_traits::Zero; @@ -255,16 +256,15 @@ impl WitnessCalculator { } pub fn calculate_witness_element< - E: ark_ec::pairing::Pairing, + F: PrimeField, I: IntoIterator)>, >( &mut self, inputs: I, sanity_check: bool, - ) -> Result> { - use ark_ff::PrimeField; + ) -> Result> { let witness = self.calculate_witness(inputs, sanity_check)?; - let modulus = ::MODULUS; + let modulus = ::MODULUS; // convert it to field elements use num_traits::Signed; @@ -277,7 +277,7 @@ impl WitnessCalculator { } else { w.to_biguint().unwrap() }; - E::ScalarField::from(w) + F::from(w) }) .collect::>(); diff --git a/src/zkey.rs b/src/zkey.rs index 8dd6422..ab9c0f8 100644 --- a/src/zkey.rs +++ b/src/zkey.rs @@ -848,7 +848,7 @@ mod tests { let mut file = File::open(path).unwrap(); let (params, _matrices) = read_zkey(&mut file).unwrap(); // binfile.proving_key().unwrap(); - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/mycircuit.wasm", "./test-vectors/mycircuit.r1cs", ) @@ -895,7 +895,7 @@ mod tests { let s = ark_bn254::Fr::rand(rng); let full_assignment = wtns - .calculate_witness_element::(inputs, false) + .calculate_witness_element::(inputs, false) .unwrap(); let proof = Groth16::::create_proof_with_reduction_and_matrices( ¶ms, diff --git a/tests/groth16.rs b/tests/groth16.rs index 8b29ba3..a561a84 100644 --- a/tests/groth16.rs +++ b/tests/groth16.rs @@ -2,7 +2,7 @@ use ark_circom::{CircomBuilder, CircomConfig}; use ark_std::rand::thread_rng; use color_eyre::Result; -use ark_bn254::Bn254; +use ark_bn254::{Bn254, Fr}; use ark_crypto_primitives::snark::SNARK; use ark_groth16::Groth16; @@ -10,7 +10,7 @@ type GrothBn = Groth16; #[test] fn groth16_proof() -> Result<()> { - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/mycircuit.wasm", "./test-vectors/mycircuit.r1cs", )?; @@ -41,7 +41,7 @@ fn groth16_proof() -> Result<()> { #[test] fn groth16_proof_wrong_input() { - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/mycircuit.wasm", "./test-vectors/mycircuit.r1cs", ) @@ -63,7 +63,7 @@ fn groth16_proof_wrong_input() { #[test] #[cfg(feature = "circom-2")] fn groth16_proof_circom2() -> Result<()> { - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/circom2_multiplier2.wasm", "./test-vectors/circom2_multiplier2.r1cs", )?; @@ -95,7 +95,7 @@ fn groth16_proof_circom2() -> Result<()> { #[test] #[cfg(feature = "circom-2")] fn witness_generation_circom2() -> Result<()> { - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/circom2_multiplier2.wasm", "./test-vectors/circom2_multiplier2.r1cs", )?; diff --git a/tests/solidity.rs b/tests/solidity.rs index c183709..a805c3b 100644 --- a/tests/solidity.rs +++ b/tests/solidity.rs @@ -2,7 +2,7 @@ use ark_circom::{ethereum, CircomBuilder, CircomConfig}; use ark_std::rand::thread_rng; use color_eyre::Result; -use ark_bn254::Bn254; +use ark_bn254::{Bn254, Fr}; use ark_crypto_primitives::snark::SNARK; use ark_groth16::Groth16; @@ -16,7 +16,7 @@ use std::{convert::TryFrom, sync::Arc}; #[tokio::test] async fn solidity_verifier() -> Result<()> { - let cfg = CircomConfig::::new( + let cfg = CircomConfig::::new( "./test-vectors/mycircuit.wasm", "./test-vectors/mycircuit.r1cs", )?;