diff --git a/src/sonic/S_poly.pdf b/src/sonic/S_poly.pdf new file mode 100644 index 0000000..a3d626e Binary files /dev/null and b/src/sonic/S_poly.pdf differ diff --git a/src/sonic/helped/adapted_verifier.rs b/src/sonic/helped/adapted_verifier.rs index 0a4b159..83bfa72 100644 --- a/src/sonic/helped/adapted_verifier.rs +++ b/src/sonic/helped/adapted_verifier.rs @@ -51,52 +51,3 @@ pub fn verify_aggregate + Clone, R: Rng>( } -// #[test] -// fn my_fun_circuit_test() { -// use pairing::ff::PrimeField; -// use pairing::bls12_381::{Bls12, Fr}; -// use super::*; -// use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination}; - -// struct MyCircuit; - -// impl Circuit for MyCircuit { -// fn synthesize>(&self, cs: &mut CS) -> Result<(), SynthesisError> { -// let (a, b, _) = cs.multiply(|| { -// Ok(( -// E::Fr::from_str("10").unwrap(), -// E::Fr::from_str("20").unwrap(), -// E::Fr::from_str("200").unwrap(), -// )) -// })?; - -// cs.enforce_zero(LinearCombination::from(a) + a - b); - -// //let multiplier = cs.alloc_input(|| Ok(E::Fr::from_str("20").unwrap()))?; - -// //cs.enforce_zero(LinearCombination::from(b) - multiplier); - -// Ok(()) -// } -// } - -// let srs = SRS::::new( -// 20, -// Fr::from_str("22222").unwrap(), -// Fr::from_str("33333333").unwrap(), -// ); -// let proof = create_proof_on_srs::(&MyCircuit, &srs).unwrap(); - -// use std::time::{Instant}; -// let start = Instant::now(); -// let mut batch = MultiVerifier::::new(MyCircuit, &srs).unwrap(); - -// for _ in 0..1 { -// batch.add_proof(&proof, &[/*Fr::from_str("20").unwrap()*/], |_, _| None); -// } - -// assert!(batch.check_all()); - -// let elapsed = start.elapsed(); -// println!("time to verify: {:?}", elapsed); -// } diff --git a/src/sonic/helped/poly.rs b/src/sonic/helped/poly.rs index 58b046e..e16325e 100644 --- a/src/sonic/helped/poly.rs +++ b/src/sonic/helped/poly.rs @@ -74,11 +74,11 @@ impl SxEval { let mut acc = E::Fr::zero(); - let mut tmp = x_inv; + let tmp = x_inv; acc.add_assign(&evaluate_at_consequitive_powers(& self.u[..], tmp, tmp)); - let mut tmp = x; + let tmp = x; acc.add_assign(&evaluate_at_consequitive_powers(& self.v[..], tmp, tmp)); - let mut tmp = x.pow(&[(self.v.len()+1) as u64]); + let tmp = x.pow(&[(self.v.len()+1) as u64]); acc.add_assign(&evaluate_at_consequitive_powers(& self.w[..], tmp, x)); // let mut tmp = x_inv; diff --git a/src/sonic/helped/prover.rs b/src/sonic/helped/prover.rs index 2624bfc..d6558bf 100644 --- a/src/sonic/helped/prover.rs +++ b/src/sonic/helped/prover.rs @@ -240,7 +240,6 @@ pub fn create_proof_on_srs, S: SynthesisDriver>( rx1.push(E::Fr::zero()); rx1.extend(wires.a); - let mut rxy = rx1.clone(); let y_inv = y.inverse().ok_or(SynthesisError::DivisionByZero)?; diff --git a/src/sonic/tests/sonics.rs b/src/sonic/tests/sonics.rs index 114a061..cbea80c 100644 --- a/src/sonic/tests/sonics.rs +++ b/src/sonic/tests/sonics.rs @@ -539,4 +539,102 @@ fn test_high_level_sonic_api() { println!("done in {:?}", start.elapsed()); } } +} + +#[test] +fn test_constraints_info() { + use pairing::bn256::{Bn256}; + use std::time::{Instant}; + use crate::sonic::unhelped::padding::{constraints_info}; + { + // This may not be cryptographically safe, use + // `OsRng` (for example) in production software. + let mut rng = &mut thread_rng(); + + // Generate the MiMC round constants + let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); + + let xl = rng.gen(); + let xr = rng.gen(); + let image = mimc::(xl, xr, &constants); + + // Create an instance of our circuit (with the + // witness) + let circuit = MiMCDemo { + xl: Some(xl), + xr: Some(xr), + constants: &constants + }; + + constraints_info::(circuit.clone()); + } +} + +#[test] +fn test_padding_using_mimc() { + use pairing::ff::{Field, PrimeField}; + use pairing::{Engine, CurveAffine, CurveProjective}; + use pairing::bls12_381::{Bls12, Fr}; + use std::time::{Instant}; + use crate::sonic::srs::SRS; + + let srs_x = Fr::from_str("23923").unwrap(); + let srs_alpha = Fr::from_str("23728792").unwrap(); + println!("making srs"); + let start = Instant::now(); + let srs = SRS::::dummy(830564, srs_x, srs_alpha); + println!("done in {:?}", start.elapsed()); + + { + // This may not be cryptographically safe, use + // `OsRng` (for example) in production software. + let rng = &mut thread_rng(); + + // Generate the MiMC round constants + let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); + let samples: usize = 100; + + let xl = rng.gen(); + let xr = rng.gen(); + let image = mimc::(xl, xr, &constants); + + // Create an instance of our circuit (with the + // witness) + let circuit = MiMCDemoNoInputs { + xl: Some(xl), + xr: Some(xr), + image: Some(image), + constants: &constants + }; + + use crate::sonic::cs::Basic; + use crate::sonic::sonic::AdaptorCircuit; + use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs}; + use crate::sonic::helped::{MultiVerifier, get_circuit_parameters}; + use crate::sonic::helped::helper::{create_aggregate_on_srs}; + use crate::sonic::unhelped::padding::Padding; + + let info = get_circuit_parameters::(circuit.clone()).expect("Must get circuit info"); + println!("{:?}", info); + + println!("creating proof"); + let start = Instant::now(); + let proof = create_proof_on_srs::(&AdaptorCircuit(circuit.clone()), &srs).unwrap(); + println!("done in {:?}", start.elapsed()); + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("K map = {:?}", verifier.get_k_map()); + println!("verifying 1 proof without advice"); + let start = Instant::now(); + { + for _ in 0..1 { + verifier.add_proof(&proof, &[], |_, _| None); + } + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + } } \ No newline at end of file diff --git a/src/sonic/unhelped/mod.rs b/src/sonic/unhelped/mod.rs index 7c54dec..4cece77 100644 --- a/src/sonic/unhelped/mod.rs +++ b/src/sonic/unhelped/mod.rs @@ -7,5 +7,6 @@ mod s2_proof; mod wellformed_argument; mod grand_product_argument; mod permutation_argument; +pub mod padding; pub use self::wellformed_argument::{WellformednessArgument, WellformednessProof}; \ No newline at end of file diff --git a/src/sonic/unhelped/padding.rs b/src/sonic/unhelped/padding.rs new file mode 100644 index 0000000..99229ff --- /dev/null +++ b/src/sonic/unhelped/padding.rs @@ -0,0 +1,686 @@ +use pairing::ff::{Field}; +use pairing::{Engine, CurveProjective}; +use std::marker::PhantomData; + +use crate::sonic::cs::{Backend}; +use crate::sonic::cs::{Coeff, Variable, LinearCombination}; +use crate::sonic::util::*; +use crate::sonic::util::*; +use crate::sonic::cs::{SynthesisDriver}; +use crate::Circuit as BellmanCircuit; +use crate::sonic::sonic::AdaptorCircuit; +use crate::sonic::cs::Circuit; +use crate::sonic::cs::ConstraintSystem; +use crate::sonic::cs::Nonassigning; +use crate::SynthesisError; + +/* +s_1(X, Y) = \sum\limits_{i=1}^N u_i(Y) X^{N + 1 - i} + + \sum\limits_{i=1}^N v_i(Y) X^{N + 1 + i} + + \sum\limits_{i=1}^N w_i(Y) X^{2N + 1 + i} + +where + + u_i(Y) = \sum\limits_{q=1}^Q Y^{q} u_{i,q} + v_i(Y) = \sum\limits_{q=1}^Q Y^{q} v_{i,q} + w_i(Y) = \sum\limits_{q=1}^Q Y^{q} w_{i,q} + +s_1(X, Y) = \sum\limits_{i=1}^(3N + 1) [u_{N + 1 - i}(Y), v_{i - N - 1}(Y), w_{i - 2N - 1}(Y)] X^{i} + +where [] means concatenation + +if we open up both sums a little it would look like + +// q = 1, +Y * ( X * u_{N, 1} + X^{N + 1} * v_{1, 1} + X^{2N + 1} * w{1, 1}) = Y * (k_0 * X + k_1 * X^{N + 1} + k_2 * X^{2N + 1}) +and for permutation where should exist another term over Y that would have the same structure, but with coefficients permuted, e.g. +Y^{p_1} * (k_1 * X + k_2 * X^{N + 1} + k_0 * X^{2N + 1}) and Y^{p_2} * (k_2 * X + k_0 * X^{N + 1} + k_1 * X^{2N + 1}) +that would result in a sum + + X * (k_0 * Y + k_1 * Y^{p_1} + k_2 * Y^{p_2}) ++ X^{N + 1} * (k_1 * Y + k_2 * Y^{p_1} + k_0 * Y^{p_2}) ++ X^{2N + 1} * (k_2 * Y + k_0 * Y^{p_1} + k_1 * Y^{p_2}) + +and permutations would look like + [k_0, k_1, k_2] + [1 , p_1, p_2] + + [k_0, k_1, k_2] + [p_2, 1 , p_1] + + [k_0, k_1, k_2] + [p_1, p_2, 1 ] + +that would naively mean that k_0 should appear in constraint number 1 for variable number 1 + constraint number p_1 for variable number N + 1 + constraint number p_2 for variable number 2N + 1 + +restructuring strategy: + +where u_{i, q} is a coefficient in a linear constraint for an A type variable number i +that corresponds to the qth multiplication gate + +to make s_1 representable as a permutation we first must synthesize all the normal constraints, +then make what would look like a cyclic shift + expansion + +- imagine that there were originally N variables +- variable A(i) in linear constraint number q had a coefficient of u{i, q} +- add a variable B(i+n) that would have a number + +*/ + +pub struct Debugging { + constraint_num: usize, + u: Vec, + v: Vec, + w: Vec, + _marker: std::marker::PhantomData +} + +impl<'a, E: Engine> Backend for &'a mut Debugging { + fn new_linear_constraint(&mut self) { + self.constraint_num += 1; + self.u.push("".to_string()); + self.v.push("".to_string()); + self.w.push("".to_string()); + } + + fn insert_coefficient(&mut self, var: Variable, coeff: Coeff) { + let one = E::Fr::one(); + let mut minus_one = one; + minus_one.negate(); + match var { + Variable::A(index) => { + let acc = &mut self.u[self.constraint_num - 1]; + match coeff { + Coeff::Zero => { }, + Coeff::One => { + acc.push_str(&format!(" + A{}", index)); + }, + Coeff::NegativeOne => { + acc.push_str(&format!(" - A{}", index)); + }, + Coeff::Full(val) => { + if val == one { + acc.push_str(&format!(" + A{}", index)); + } else if val == minus_one { + acc.push_str(&format!(" - A{}", index)); + } else { + acc.push_str(&format!(" + {}*A{}", val, index)); + } + } + } + } + Variable::B(index) => { + let acc = &mut self.v[self.constraint_num - 1]; + match coeff { + Coeff::Zero => { }, + Coeff::One => { + acc.push_str(&format!(" + B{}", index)); + }, + Coeff::NegativeOne => { + acc.push_str(&format!(" - B{}", index)); + }, + Coeff::Full(val) => { + if val == one { + acc.push_str(&format!(" + B{}", index)); + } else if val == minus_one { + acc.push_str(&format!(" - B{}", index)); + } else { + acc.push_str(&format!(" + {}*B{}", val, index)); + } + } + } + } + Variable::C(index) => { + let acc = &mut self.w[self.constraint_num - 1]; + match coeff { + Coeff::Zero => { }, + Coeff::One => { + acc.push_str(&format!(" + C{}", index)); + }, + Coeff::NegativeOne => { + acc.push_str(&format!(" - C{}", index)); + }, + Coeff::Full(val) => { + if val == one { + acc.push_str(&format!(" + C{}", index)); + } else if val == minus_one { + acc.push_str(&format!(" - C{}", index)); + } else { + acc.push_str(&format!(" + {}*C{}", val, index)); + } + } + } + } + }; + } +} + +pub struct Padding; + +impl SynthesisDriver for Padding { + fn synthesize, B: Backend>(backend: B, circuit: &C) -> Result<(), SynthesisError> { + struct Synthesizer> { + backend: B, + current_variable: Option, + _marker: PhantomData, + q: usize, + n: usize, + } + + impl>Synthesizer { + fn purge_current_var(&mut self) { + match self.current_variable.take() { + Some(index) => { + let var_a = Variable::A(index); + let var_b = Variable::B(index); + let var_c = Variable::C(index); + + let mut product = None; + + let value_a = self.backend.get_var(var_a); + + self.backend.set_var(var_b, || { + let value_b = E::Fr::one(); + product = Some(value_a.ok_or(SynthesisError::AssignmentMissing)?); + product.as_mut().map(|product| product.mul_assign(&value_b)); + + Ok(value_b) + }).expect("should exist by now"); + + self.backend.set_var(var_c, || { + product.ok_or(SynthesisError::AssignmentMissing) + }).expect("should exist by now"); + + self.current_variable = None; + }, + _ => {} + } + } + + fn alloc_one(&mut self) -> Variable { + self.n += 1; + let index = self.n; + assert_eq!(index, 1); + self.backend.new_multiplication_gate(); + + let var_a = Variable::A(1); + let var_b = Variable::B(1); + let var_c = Variable::C(1); + + self.backend.set_var(var_a, || { + Ok(E::Fr::one()) + }).expect("should exist by now"); + + self.backend.set_var(var_b, || { + Ok(E::Fr::one()) + }).expect("should exist by now"); + + self.backend.set_var(var_c, || { + Ok(E::Fr::one()) + }).expect("should exist by now"); + + self.q += 1; + self.backend.new_linear_constraint(); + self.backend.insert_coefficient(var_a, Coeff::One); + self.backend.insert_coefficient(var_b, Coeff::One); + self.backend.insert_coefficient(var_c, Coeff::NegativeOne); + self.backend.new_k_power(self.q); + + var_a + } + } + + impl> ConstraintSystem for Synthesizer { + const ONE: Variable = Variable::A(1); + + fn alloc(&mut self, value: F) -> Result + where + F: FnOnce() -> Result + { + match self.current_variable.take() { + Some(index) => { + let var_a = Variable::A(index); + let var_b = Variable::B(index); + let var_c = Variable::C(index); + + let mut product = None; + + let value_a = self.backend.get_var(var_a); + + self.backend.set_var(var_b, || { + let value_b = value()?; + product = Some(value_a.ok_or(SynthesisError::AssignmentMissing)?); + product.as_mut().map(|product| product.mul_assign(&value_b)); + + Ok(value_b) + })?; + + self.backend.set_var(var_c, || { + product.ok_or(SynthesisError::AssignmentMissing) + })?; + + self.current_variable = None; + + Ok(var_b) + }, + None => { + self.n += 1; + let index = self.n; + self.backend.new_multiplication_gate(); + + let var_a = Variable::A(index); + + self.backend.set_var(var_a, value)?; + + self.current_variable = Some(index); + + Ok(var_a) + } + } + } + + // TODO: allocate input without spawning extra constraints + fn alloc_input(&mut self, value: F) -> Result + where + F: FnOnce() -> Result + { + // self.purge_current_var(); + // self.n += 1; + // self.backend.new_multiplication_gate(); + + // let index = self.n; + + // let var = Variable::A::(index); + + // self.q += 1; + // self.backend.new_k_power(self.q); + // self.backend.self.backend.insert_coefficient(new_var, Coeff::One); + + // it's always going to be + let input_var = self.alloc(value)?; + + self.enforce_zero(LinearCombination::zero() + input_var); + self.backend.new_k_power(self.q-2); + self.backend.new_k_power(self.q-1); + self.backend.new_k_power(self.q); + + Ok(input_var) + } + + fn enforce_zero(&mut self, lc: LinearCombination) + { + self.q += 1; + self.backend.new_linear_constraint(); + + for (var, coeff) in lc.as_ref() { + self.backend.insert_coefficient(*var, *coeff); + } + + // now we need to "rotate" a linear constraint by allocating more dummy variables, so ensuring + // that if for some q (index of LC) there is a coefficient C in front of a variable A(i) (that will result in a term ~ C*Y^{q}*X^{i}) + // then there will be some other q' where there is a coefficient C in front of the variable B(i) + // (that will result in a term ~ C*Y^{q'}*X^{i+N}) and another q'' with C in front of C(i) + // (that will result in a term ~ C*Y^{q''}*X^{i+2N}), so S polynomial is indeed a permutation + + // allocate at max 1 variable to later work with whole gates directly + + self.purge_current_var(); + + use std::collections::HashMap; + + // A -> B, B -> C, C -> A + { + self.q += 1; + self.backend.new_linear_constraint(); + + let mut allocation_map = HashMap::with_capacity(lc.as_ref().len()); + let mut expected_new_index = self.n + 1; + + // determine size of the map + for (var, _) in lc.as_ref() { + match var { + Variable::A(index) => { + if allocation_map.get(index).is_none() && *index != 1 { + allocation_map.insert(*index, expected_new_index); + expected_new_index += 1; + println!("A{} -> B{}", index, expected_new_index); + } + }, + Variable::B(index) => { + if allocation_map.get(index).is_none() && *index != 2 { + allocation_map.insert(*index, expected_new_index); + expected_new_index += 1; + println!("B{} -> C{}", index, expected_new_index); + } + }, + Variable::C(index) => { + if allocation_map.get(index).is_none() && *index != 3 { + allocation_map.insert(*index, expected_new_index); + expected_new_index += 1; + println!("C{} -> A{}", index, expected_new_index); + } + } + } + } + + for _ in 0..allocation_map.len() { + self.backend.new_multiplication_gate(); + self.n += 1; + } + + for (index, new_index) in allocation_map.iter() { + let var_a = Variable::A(*new_index); + let var_b = Variable::B(*new_index); + let var_c = Variable::C(*new_index); + + // A -> B, B -> C, C -> A + let b_val = self.backend.get_var(Variable::A(*index)); + let c_val = self.backend.get_var(Variable::B(*index)); + let a_val = self.backend.get_var(Variable::C(*index)); + + self.backend.set_var(var_a, || { + let value = a_val.ok_or(SynthesisError::AssignmentMissing)?; + + Ok(value) + }).expect("should exist by now"); + + self.backend.set_var(var_b, || { + let value = b_val.ok_or(SynthesisError::AssignmentMissing)?; + + Ok(value) + }).expect("should exist by now"); + + self.backend.set_var(var_c, || { + let value = c_val.ok_or(SynthesisError::AssignmentMissing)?; + + Ok(value) + }).expect("should exist by now"); + + } + + // A -> B, B -> C, C -> A + for (var, coeff) in lc.as_ref() { + let new_var = match var { + Variable::A(index) => { + let var = if *index == 1 { + Variable::B(2) + } else { + let new_index = allocation_map.get(index).unwrap(); + Variable::B(*new_index) + }; + + var + }, + Variable::B(index) => { + let var = if *index == 2 { + Variable::C(3) + } else { + let new_index = allocation_map.get(index).unwrap(); + Variable::C(*new_index) + }; + + var + }, + Variable::C(index) => { + let var = if *index == 3 { + Variable::A(1) + } else { + let new_index = allocation_map.get(index).unwrap(); + Variable::A(*new_index) + }; + + var + } + }; + + self.backend.insert_coefficient(new_var, *coeff); + } + } + + // A -> C, B -> A, C -> B + { + self.q += 1; + self.backend.new_linear_constraint(); + + let mut allocation_map = HashMap::with_capacity(lc.as_ref().len()); + let mut expected_new_index = self.n + 1; + + // determine size of the map + for (var, _) in lc.as_ref() { + match var { + Variable::A(index) => { + if allocation_map.get(index).is_none() && *index != 1 { + allocation_map.insert(*index, expected_new_index); + expected_new_index += 1; + println!("A{} -> C{}", index, expected_new_index); + } + }, + Variable::B(index) => { + if allocation_map.get(index).is_none() && *index != 2 { + allocation_map.insert(*index, expected_new_index); + expected_new_index += 1; + println!("B{} -> A{}", index, expected_new_index); + } + }, + Variable::C(index) => { + if allocation_map.get(index).is_none() && *index != 3 { + allocation_map.insert(*index, expected_new_index); + expected_new_index += 1; + println!("C{} -> B{}", index, expected_new_index); + } + } + } + } + + for _ in 0..allocation_map.len() { + self.backend.new_multiplication_gate(); + self.n += 1; + } + + // A -> C, B -> A, C -> B + for (index, new_index) in allocation_map.iter() { + let var_a = Variable::A(*new_index); + let var_b = Variable::B(*new_index); + let var_c = Variable::C(*new_index); + + let b_val = self.backend.get_var(Variable::C(*index)); + let c_val = self.backend.get_var(Variable::A(*index)); + let a_val = self.backend.get_var(Variable::B(*index)); + + self.backend.set_var(var_a, || { + let value = a_val.ok_or(SynthesisError::AssignmentMissing)?; + + Ok(value) + }).expect("should exist by now"); + + self.backend.set_var(var_b, || { + let value = b_val.ok_or(SynthesisError::AssignmentMissing)?; + + Ok(value) + }).expect("should exist by now"); + + self.backend.set_var(var_c, || { + let value = c_val.ok_or(SynthesisError::AssignmentMissing)?; + + Ok(value) + }).expect("should exist by now"); + } + + // A -> C, B -> A, C -> B + for (var, coeff) in lc.as_ref() { + let new_var = match var { + Variable::A(index) => { + let var = if *index == 1 { + Variable::C(3) + } else { + let new_index = allocation_map.get(index).unwrap(); + Variable::C(*new_index) + }; + + var + }, + Variable::B(index) => { + let var = if *index == 2 { + Variable::A(1) + } else { + let new_index = allocation_map.get(index).unwrap(); + Variable::A(*new_index) + }; + + var + }, + Variable::C(index) => { + let var = if *index == 3 { + Variable::B(2) + } else { + let new_index = allocation_map.get(index).unwrap(); + Variable::B(*new_index) + }; + + var + } + }; + + self.backend.insert_coefficient(new_var, *coeff); + } + } + } + + fn multiply(&mut self, values: F) -> Result<(Variable, Variable, Variable), SynthesisError> + where + F: FnOnce() -> Result<(E::Fr, E::Fr, E::Fr), SynthesisError> + { + self.n += 1; + let index = self.n; + self.backend.new_multiplication_gate(); + + let a = Variable::A(index); + let b = Variable::B(index); + let c = Variable::C(index); + + let mut b_val = None; + let mut c_val = None; + + self.backend.set_var(a, || { + let (a, b, c) = values()?; + + b_val = Some(b); + c_val = Some(c); + + Ok(a) + })?; + + self.backend.set_var(b, || { + b_val.ok_or(SynthesisError::AssignmentMissing) + })?; + + self.backend.set_var(c, || { + c_val.ok_or(SynthesisError::AssignmentMissing) + })?; + + Ok((a, b, c)) + } + + fn get_value(&self, var: Variable) -> Result { + self.backend.get_var(var).ok_or(()) + } + } + + let mut tmp: Synthesizer = Synthesizer { + backend: backend, + current_variable: None, + _marker: PhantomData, + q: 0, + n: 0, + }; + + let one = tmp.alloc_input(|| Ok(E::Fr::one())).expect("should have no issues"); + + match (one, as ConstraintSystem>::ONE) { + (Variable::A(1), Variable::A(1)) => {}, + _ => panic!("one variable is incorrect") + } + + circuit.synthesize(&mut tmp)?; + + println!("Done synthesizing, N = {}, Q = {}", tmp.n, tmp.q); + + Ok(()) + } +} + +pub fn constraints_info + Clone>( + circuit: C, +) +{ + let adapted_circuit = AdaptorCircuit(circuit); + + create_constraints_info::<_, _, Nonassigning>(&adapted_circuit) +} + +pub fn constraints_padding_info + Clone>( + circuit: C, +) +{ + let adapted_circuit = AdaptorCircuit(circuit); + + create_constraints_info::<_, _, Padding>(&adapted_circuit) +} + +pub fn create_constraints_info, S: SynthesisDriver>( + circuit: &C, +) +{ + let mut backend = Debugging:: { + constraint_num: 0, + u: vec![], + v: vec![], + w: vec![], + _marker: std::marker::PhantomData + }; + + S::synthesize(&mut backend, circuit).unwrap(); + + + for (i, ((u, v), w)) in backend.u.iter() + .zip(backend.v.iter()) + .zip(backend.w.iter()) + .enumerate() + { + println!("Constraint {}: 0 = {}{}{}", i, u, v, w); + } +} + +#[test] +fn my_fun_circuit_test() { + use pairing::ff::PrimeField; + use pairing::bls12_381::{Bls12, Fr}; + + struct MyCircuit; + + impl Circuit for MyCircuit { + fn synthesize>(&self, cs: &mut CS) -> Result<(), SynthesisError> { + let (a, b, _) = cs.multiply(|| { + Ok(( + E::Fr::from_str("10").unwrap(), + E::Fr::from_str("20").unwrap(), + E::Fr::from_str("200").unwrap(), + )) + })?; + + cs.enforce_zero(LinearCombination::from(a) + a - b); + + let multiplier = cs.alloc_input(|| Ok(E::Fr::from_str("20").unwrap()))?; + + cs.enforce_zero(LinearCombination::from(b) - multiplier); + + Ok(()) + } + } + + create_constraints_info::(&MyCircuit); + println!("---------------"); + create_constraints_info::(&MyCircuit); +} \ No newline at end of file diff --git a/src/sonic/unhelped/permutation_argument.rs b/src/sonic/unhelped/permutation_argument.rs index 1813ae6..021e5a3 100644 --- a/src/sonic/unhelped/permutation_argument.rs +++ b/src/sonic/unhelped/permutation_argument.rs @@ -43,8 +43,6 @@ pub struct Proof { s_zy: E::Fr } - - fn permute(coeffs: &[F], permutation: & [usize]) -> Vec{ assert_eq!(coeffs.len(), permutation.len()); let mut result: Vec = vec![F::zero(); coeffs.len()]; diff --git a/src/sonic/util.rs b/src/sonic/util.rs index 16505a8..aa26854 100644 --- a/src/sonic/util.rs +++ b/src/sonic/util.rs @@ -123,12 +123,12 @@ pub fn polynomial_commitment_opening< ) -> E::G1Affine where I::IntoIter: DoubleEndedIterator + ExactSizeIterator, { - let poly = parallel_kate_divison::(polynomial_coefficients, point); + // let poly = parallel_kate_divison::(polynomial_coefficients, point); - // let poly = kate_divison( - // polynomial_coefficients, - // point, - // ); + let poly = kate_divison( + polynomial_coefficients, + point, + ); let negative_poly = poly[0..largest_negative_power].iter().rev(); let positive_poly = poly[largest_negative_power..].iter();