From 6674f62bd46a10353c018148f127ff45908b2416 Mon Sep 17 00:00:00 2001 From: rebenkoy Date: Wed, 22 Nov 2023 02:53:55 +0300 Subject: [PATCH 1/2] constructed circuit step --- src/circuit.rs | 93 +++-- src/gadgets/bits.rs | 1 - src/gadgets/ecmul.rs | 3 - src/gadgets/lookup.rs | 762 +++++++++++++++++------------------ src/gadgets/nonzero_check.rs | 2 +- src/gadgets/poseidon.rs | 3 +- src/gadgets/range.rs | 3 +- src/test.rs | 670 +++++++++++++++--------------- 8 files changed, 777 insertions(+), 760 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index b6751b5..a0c52ea 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,8 +1,8 @@ -use std::{rc::Rc, marker::PhantomData, iter::repeat_with}; +use std::{rc::{Rc, Weak}, marker::PhantomData, iter::repeat_with, cell::RefCell}; use elsa::map::FrozenMap; use ff::PrimeField; -use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}}; +use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub} }; use self::circuit_operations::CircuitOperation; @@ -74,11 +74,11 @@ impl InternalValue { pub ivar: usize, pub iext: usize, pub o: usize, - pub f: Rc Vec + 'closure>, + pub f: Rc Vec + 'closure>, } impl<'closure, F: PrimeField> Advice<'closure, F> { - pub fn new(ivar: usize, iext: usize, o: usize, f: impl Fn(&[F], &[F]) -> Vec + 'closure) -> Self { + pub fn new(ivar: usize, iext: usize, o: usize, f: impl Fn(&[F], &RunIndex) -> Vec + 'closure) -> Self { let f = Rc::new(f); Self { ivar, iext, o, f } @@ -104,10 +104,10 @@ pub mod circuit_operations { use std::rc::Rc; use ff::PrimeField; use crate::{constraint_system::Variable, gate::Gate, witness::CSWtns}; - use super::{ExternalValue, InternalValue}; + use super::{ExternalValue, RunIndex}; pub trait CircuitOperation<'a, F: PrimeField, G: Gate<'a, F>> { - fn execute(&self, witness: &mut CSWtns<'a, F, G>); + fn execute(&self, witness: &mut CSWtns<'a, F, G>, idx: &RunIndex); } pub struct AttachedAdvicePub<'advice, F: PrimeField> { @@ -123,7 +123,7 @@ pub mod circuit_operations { } impl<'advice, F: PrimeField, G: Gate<'advice, F>> CircuitOperation<'advice, F, G> for AttachedAdvicePub<'advice, F> { - fn execute(&self, witness: &mut CSWtns<'advice, F, G>) { + fn execute(&self, witness: &mut CSWtns<'advice, F, G>, idx: &RunIndex) { let aux: Vec<_> = self.aux.iter().map(|ev| witness.getext(*ev)).collect(); let output = (self.closure)(&aux); @@ -136,23 +136,21 @@ pub mod circuit_operations { pub struct AttachedAdvice<'advice, F: PrimeField> { input: Vec, - aux: Vec<&'advice InternalValue>, output: Vec, - closure: Rc Vec + 'advice>, + closure: Rc Vec + 'advice>, } impl<'advice, F: PrimeField> AttachedAdvice<'advice, F> { - pub fn new(input: Vec, aux: Vec<&'advice InternalValue>, output: Vec, closure: Rc Vec + 'advice>) -> Self { - Self { input, aux, output, closure } + pub fn new(input: Vec, output: Vec, closure: Rc Vec + 'advice>) -> Self { + Self { input, output, closure } } } impl<'advice, F: PrimeField, G: Gate<'advice, F>> CircuitOperation<'advice, F, G> for AttachedAdvice<'advice, F> { - fn execute(&self, witness: &mut CSWtns<'advice, F, G>) { + fn execute(&self, witness: &mut CSWtns<'advice, F, G>, idx: &RunIndex) { let input = witness.get_vars(&self.input); - let aux: Vec<_> = self.aux.iter().map(|ev| ev.get().expect("external values should be set before execution")).collect(); - let output = (self.closure)(&input, &aux); + let output = (self.closure)(&input, &idx); let value_set: Vec<_> = self.output.iter().cloned().zip(output).collect(); witness.set_vars(&value_set); @@ -172,7 +170,7 @@ pub mod circuit_operations { } impl<'closure, F: PrimeField, G: Gate<'closure, F>> CircuitOperation<'closure, F, G> for AttachedPolynomialAdvice<'closure, F> { - fn execute(&self, witness: &mut CSWtns<'closure, F, G>) { + fn execute(&self, witness: &mut CSWtns<'closure, F, G>, _: &RunIndex) { let input = witness.get_vars(&self.input); let output = (self.closure)(&input, &[]); @@ -216,7 +214,7 @@ where prep } - pub fn advice(&mut self, round: usize, advice: Advice<'circuit, F>, input: Vec, aux: Vec<&'circuit InternalValue>) -> Vec { + pub fn advice(&mut self, round: usize, advice: Advice<'circuit, F>, input: Vec) -> Vec { assert!(round < self.ops.len(), "The round is too large."); let op_index = self.ops[round].len(); @@ -226,10 +224,9 @@ where } assert!(input.len() == advice.ivar, "Incorrect amount of input vars at operation #{} (round {})", op_index, round); - assert!(aux.len() == advice.iext, "Incorrect amount of internal vals at operation #{} (round {})", op_index, round); let output = self.cs.alloc_in_round(round, Visibility::Private, advice.o); - let operation = Box::new(AttachedAdvice::new(input, aux, output.clone(), advice.f.clone())); + let operation = Box::new(AttachedAdvice::new(input, output.clone(), advice.f.clone())); self.ops[round].push(operation); output @@ -310,15 +307,10 @@ where self.advice_pub(round, adv, vec![pi])[0] } - pub fn finalize(self) -> SealedCircuit<'circuit, F, G> { - let cs = CSWtns::::new(&self.cs); - - let circuit = Rc::new(self); - - SealedCircuit { - cs, - circuit, - round_counter: 0, + pub fn finalize(self) -> ConstructedCircuit<'circuit, F, G> { + ConstructedCircuit { + circuit: self, + num_runs: RefCell::new(0), } } @@ -331,13 +323,43 @@ where } } -pub struct SealedCircuit<'circuit, F: PrimeField, G: Gate<'circuit, F> + From>>{ - circuit: Rc >, +pub struct RunIndex { + idx: usize, +} + +impl RunIndex { + fn new(idx: usize) -> Self { + Self { + idx, + } + } +} + +pub struct ConstructedCircuit<'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> { + circuit: Circuit<'circuit, F, G>, + num_runs: RefCell, +} + +impl<'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> ConstructedCircuit<'circuit, F, G> { + pub fn spawn<'constructed>(&'constructed self) -> CircuitRun<'constructed, 'circuit, F, G> { + *self.num_runs.borrow_mut() += 1; + CircuitRun { + constructed: &self, + cs: CSWtns::::new(&self.circuit.cs), + round_counter: 0, + run_idx: RunIndex::new(*self.num_runs.borrow() - 1), + } + } +} + +pub struct CircuitRun<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>>{ + constructed: &'constructed ConstructedCircuit<'circuit, F, G>, pub cs : CSWtns<'circuit, F, G>, round_counter : usize, + run_idx: RunIndex, } -impl<'circuit, F, G> SealedCircuit<'circuit, F, G> +impl<'constructed, 'circuit, F, G> CircuitRun<'constructed, 'circuit, F, G> where F: PrimeField, G: Gate<'circuit, F> + From>, @@ -347,8 +369,8 @@ where assert!(self.round_counter <= round, "Execution is already at round {}, tried to execute up to round {}", self.round_counter, round); while self.round_counter <= round { - for op in &self.circuit.ops[self.round_counter] { - op.execute(&mut self.cs); + for op in &self.constructed.circuit.ops[self.round_counter] { + op.execute(&mut self.cs, &self.run_idx); } self.round_counter += 1; } @@ -360,7 +382,7 @@ where pub fn valid_witness(&self) -> () { - for constr in self.circuit.cs.iter_constraints() { + for constr in self.constructed.circuit.cs.iter_constraints() { let input_values: Vec<_> = constr.inputs.iter().map(|&x| self.cs.getvar(x)).collect(); let result = constr.gate.exec(&input_values); @@ -369,6 +391,7 @@ where } pub fn iter_constraints(&self) -> impl Iterator> { - self.circuit.cs.iter_constraints() + self.constructed.circuit.cs.iter_constraints() } -} \ No newline at end of file +} + diff --git a/src/gadgets/bits.rs b/src/gadgets/bits.rs index f5beebe..8625898 100644 --- a/src/gadgets/bits.rs +++ b/src/gadgets/bits.rs @@ -43,7 +43,6 @@ pub fn bit_decomposition_gadget<'a, F: PrimeField+FieldUtils>(circuit: &mut Circ } ), vec![input], - vec![] ); let bitcheck_gate = Gatebb::new(2, 1, 1, Rc::new(|args, _| bitcheck::(args)), vec![]); diff --git a/src/gadgets/ecmul.rs b/src/gadgets/ecmul.rs index 0fd059c..0b7c8cf 100644 --- a/src/gadgets/ecmul.rs +++ b/src/gadgets/ecmul.rs @@ -193,7 +193,6 @@ pub fn ecadd_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt>( } ), vec![pt1.x, pt1.y, pt2.x, pt2.y], - vec![] ); let pt3 = EcAffinePoint::::new(circuit, tmp[0], tmp[1]); @@ -223,7 +222,6 @@ pub fn ecdouble_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt>( } ), vec![pt.x, pt.y], - vec![] ); let pt2 = EcAffinePoint::::new(circuit, tmp[0], tmp[1]); @@ -384,7 +382,6 @@ pub fn escalarmul_gadget_9<'a, F: PrimeField + FieldUtils, C: CurveExt>( round, adv, pts_limbs.clone(), - vec![] ); let (acc, rest) = advices.split_at(2*(num_limbs-1)); diff --git a/src/gadgets/lookup.rs b/src/gadgets/lookup.rs index 5cdb18a..465211a 100644 --- a/src/gadgets/lookup.rs +++ b/src/gadgets/lookup.rs @@ -131,7 +131,7 @@ pub fn invsum_gadget<'a, F: PrimeField+FieldUtils>( let mut args = vals.to_vec(); args.push(challenge); - let batches = circuit.advice(round, advice, args, vec![]); + let batches = circuit.advice(round, advice, args); for i in 0..l/rate { (chunk, vals) = vals.split_at(rate); invsum_flat_constrain(circuit, chunk, batches[i], challenge); @@ -182,7 +182,7 @@ pub fn fracsum_gadget<'a,'c, F: PrimeField+FieldUtils>( let args = nums.iter().map(|x|*x).chain(once(challenge)).collect(); - let batches = circuit.advice(round, advice, args, vec![]); + let batches = circuit.advice(round, advice, args); for i in 0..l/rate { (num_chunk, nums) = nums.split_at(rate); (den_chunk, dens) = dens.split_at(rate); @@ -262,7 +262,7 @@ impl<'c, F: PrimeField+FieldUtils> Lookup<'c, F> for StaticLookup { } ret.into_iter().map(|x|F::from(x)).collect() }); - let access_counts = circuit.advice(access_round, compute_accesses, vars.clone(), vec![]); + let access_counts = circuit.advice(access_round, compute_accesses, vars.clone()); // Allocate challenge. let challenge = input(circuit, challenge, challenge_round); @@ -273,405 +273,405 @@ impl<'c, F: PrimeField+FieldUtils> Lookup<'c, F> for StaticLookup { } } -#[cfg(test)] -mod test { - use super::*; - const TEST_LEN: usize = 12; - use ff::Field; - use halo2::halo2curves::bn256; - use itertools::Itertools; - use rand_core::OsRng; - - mod montgomery { - use super::*; - - #[test] - fn empty() { - type F = bn256::Fr; - assert_eq!(montgomery::(&[]), (F::ONE, vec![])); - } - - #[test] - fn one() { - type F = bn256::Fr; - let points = [F::random(OsRng)]; - assert_eq!(montgomery::(&points), (points[0], vec![F::ONE])); - } - - #[test] - fn random() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let (res_mul, res_partials) = montgomery::(&points); - assert_eq!(res_mul, points.iter().fold(F::ONE, |acc, n| acc * n)); - assert!(points.iter().zip_eq(res_partials).all(|(point, partial)| point * partial == res_mul)) - } - } +// #[cfg(test)] +// mod test { +// use super::*; +// const TEST_LEN: usize = 12; +// use ff::Field; +// use halo2::halo2curves::bn256; +// use itertools::Itertools; +// use rand_core::OsRng; + +// mod montgomery { +// use super::*; + +// #[test] +// fn empty() { +// type F = bn256::Fr; +// assert_eq!(montgomery::(&[]), (F::ONE, vec![])); +// } + +// #[test] +// fn one() { +// type F = bn256::Fr; +// let points = [F::random(OsRng)]; +// assert_eq!(montgomery::(&points), (points[0], vec![F::ONE])); +// } + +// #[test] +// fn random() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let (res_mul, res_partials) = montgomery::(&points); +// assert_eq!(res_mul, points.iter().fold(F::ONE, |acc, n| acc * n)); +// assert!(points.iter().zip_eq(res_partials).all(|(point, partial)| point * partial == res_mul)) +// } +// } - mod sum_of_fractions { - use super::*; - - mod invalid { - use super::*; - - #[test] - #[should_panic] - fn no_args() { - type F = bn256::Fr; - sum_of_fractions::(&[], 0); - } - - #[test] - #[should_panic] - fn small_k() { - type F = bn256::Fr; - sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 1); - } - - #[test] - #[should_panic] - fn big_k() { - type F = bn256::Fr; - sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 3); - } - } - - - #[test] - fn empty() { - type F = bn256::Fr; - let c = F::random(OsRng); - - assert_eq!(sum_of_fractions::(&[F::ZERO, c], 0), F::ZERO); - } - - #[test] - fn random_eq() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let c = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let sum = points.iter().map(|p| (p - c).invert().unwrap() * F::ONE).fold(F::ZERO, |acc, n| acc + n); - let mut inputs = vec![sum, c]; - inputs.extend(points.iter()); - assert_eq!(sum_of_fractions::(&inputs, indexes.len()), F::ZERO); - } - - #[test] - fn aware_constrain_random() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let c = F::random(OsRng); - let fake_sum = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let mut inputs = vec![fake_sum, c]; - inputs.extend(points.iter()); - let res = sum_of_fractions::(&inputs, indexes.len()); - let padded = points.iter().map(|p| (p - c)).collect_vec(); - let inverces = padded.iter().map(|p| p.invert().unwrap()).collect_vec(); - let real_sum = inverces.iter().fold(F::ZERO, |acc, n| acc + n); - let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); - let real_numerator = real_sum * real_denominator; - assert_eq!(fake_sum * real_denominator - real_numerator, res); - } - } - - mod sum_of_fractions_with_nums { - use super::*; - - mod invalid { - use super::*; - - #[test] - #[should_panic] - fn no_args() { - type F = bn256::Fr; - sum_of_fractions_with_nums::(&[], &[], 0); - } - - #[test] - #[should_panic] - fn small_k() { - type F = bn256::Fr; - sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE], 1); - } - - #[test] - #[should_panic] - fn big_k() { - type F = bn256::Fr; - sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE, F::ONE, F::ONE], 3); - } - } - - #[test] - fn empty() { - type F = bn256::Fr; - let c = F::random(OsRng); - - assert_eq!(sum_of_fractions_with_nums::(&[F::ZERO, c], &[], 0), F::ZERO); - } - - #[test] - fn random_eq() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let c = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - - let sum = points.iter().zip_eq(&numerators).map(|(p, n)| (p - c).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - - let mut inputs = vec![sum, c]; - inputs.extend(numerators.iter()); - assert_eq!(sum_of_fractions_with_nums::(&inputs, &points, indexes.len()), F::ZERO); - } - - #[test] - fn aware_constrain_random() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let c = F::random(OsRng); - let fake_sum = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let mut inputs = vec![fake_sum, c]; - inputs.extend(numerators.iter()); - let res = sum_of_fractions_with_nums::(&inputs, &points, indexes.len()); - let padded = points.iter().map(|p| (p - c)).collect_vec(); - let real_sum = padded.iter().zip_eq(&numerators).map(|(p, n)| p.invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); - let real_numerator = real_sum * real_denominator; - assert_eq!(fake_sum * real_denominator - real_numerator, res); - } - } - - mod invsum_flat_constrain { - use super::*; - - #[test] - fn random_eq() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; +// mod sum_of_fractions { +// use super::*; + +// mod invalid { +// use super::*; + +// #[test] +// #[should_panic] +// fn no_args() { +// type F = bn256::Fr; +// sum_of_fractions::(&[], 0); +// } + +// #[test] +// #[should_panic] +// fn small_k() { +// type F = bn256::Fr; +// sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 1); +// } + +// #[test] +// #[should_panic] +// fn big_k() { +// type F = bn256::Fr; +// sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 3); +// } +// } + + +// #[test] +// fn empty() { +// type F = bn256::Fr; +// let c = F::random(OsRng); + +// assert_eq!(sum_of_fractions::(&[F::ZERO, c], 0), F::ZERO); +// } + +// #[test] +// fn random_eq() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let c = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let sum = points.iter().map(|p| (p - c).invert().unwrap() * F::ONE).fold(F::ZERO, |acc, n| acc + n); +// let mut inputs = vec![sum, c]; +// inputs.extend(points.iter()); +// assert_eq!(sum_of_fractions::(&inputs, indexes.len()), F::ZERO); +// } + +// #[test] +// fn aware_constrain_random() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let c = F::random(OsRng); +// let fake_sum = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let mut inputs = vec![fake_sum, c]; +// inputs.extend(points.iter()); +// let res = sum_of_fractions::(&inputs, indexes.len()); +// let padded = points.iter().map(|p| (p - c)).collect_vec(); +// let inverces = padded.iter().map(|p| p.invert().unwrap()).collect_vec(); +// let real_sum = inverces.iter().fold(F::ZERO, |acc, n| acc + n); +// let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); +// let real_numerator = real_sum * real_denominator; +// assert_eq!(fake_sum * real_denominator - real_numerator, res); +// } +// } + +// mod sum_of_fractions_with_nums { +// use super::*; + +// mod invalid { +// use super::*; + +// #[test] +// #[should_panic] +// fn no_args() { +// type F = bn256::Fr; +// sum_of_fractions_with_nums::(&[], &[], 0); +// } + +// #[test] +// #[should_panic] +// fn small_k() { +// type F = bn256::Fr; +// sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE], 1); +// } + +// #[test] +// #[should_panic] +// fn big_k() { +// type F = bn256::Fr; +// sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE, F::ONE, F::ONE], 3); +// } +// } + +// #[test] +// fn empty() { +// type F = bn256::Fr; +// let c = F::random(OsRng); + +// assert_eq!(sum_of_fractions_with_nums::(&[F::ZERO, c], &[], 0), F::ZERO); +// } + +// #[test] +// fn random_eq() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let c = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + +// let sum = points.iter().zip_eq(&numerators).map(|(p, n)| (p - c).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); + +// let mut inputs = vec![sum, c]; +// inputs.extend(numerators.iter()); +// assert_eq!(sum_of_fractions_with_nums::(&inputs, &points, indexes.len()), F::ZERO); +// } + +// #[test] +// fn aware_constrain_random() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let c = F::random(OsRng); +// let fake_sum = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let mut inputs = vec![fake_sum, c]; +// inputs.extend(numerators.iter()); +// let res = sum_of_fractions_with_nums::(&inputs, &points, indexes.len()); +// let padded = points.iter().map(|p| (p - c)).collect_vec(); +// let real_sum = padded.iter().zip_eq(&numerators).map(|(p, n)| p.invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); +// let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); +// let real_numerator = real_sum * real_denominator; +// assert_eq!(fake_sum * real_denominator - real_numerator, res); +// } +// } + +// mod invsum_flat_constrain { +// use super::*; + +// #[test] +// fn random_eq() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; - let challenge = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); +// let challenge = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); - let mut circuit = Circuit::new(TEST_LEN + 1, 1); - let challenge_value = circuit.ext_val(1)[0]; - let points_values = circuit.ext_val(TEST_LEN); - let result_value = circuit.ext_val(1)[0]; +// let mut circuit = Circuit::new(TEST_LEN + 1, 1); +// let challenge_value = circuit.ext_val(1)[0]; +// let points_values = circuit.ext_val(TEST_LEN); +// let result_value = circuit.ext_val(1)[0]; - let challenge_variable = input(&mut circuit, challenge_value, 0); - let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); - let reslut_variable = input(&mut circuit, result_value, 0); +// let challenge_variable = input(&mut circuit, challenge_value, 0); +// let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); +// let reslut_variable = input(&mut circuit, result_value, 0); - invsum_flat_constrain(&mut circuit, &points_variables, reslut_variable, challenge_variable); - let mut instance = circuit.finalize(); +// invsum_flat_constrain(&mut circuit, &points_variables, reslut_variable, challenge_variable); +// let mut instance = circuit.finalize(); - instance.set_ext(challenge_value, challenge); - points_values.into_iter().zip_eq(points).map(|(val, point)| instance.set_ext(val, point)).last(); - instance.set_ext(result_value, result); +// instance.set_ext(challenge_value, challenge); +// points_values.into_iter().zip_eq(points).map(|(val, point)| instance.set_ext(val, point)).last(); +// instance.set_ext(result_value, result); - instance.execute(0); - instance.valid_witness(); +// instance.execute(0); +// instance.valid_witness(); - } - } +// } +// } - mod fracsum_flat_constrain { - use super::*; +// mod fracsum_flat_constrain { +// use super::*; - #[test] - fn random_eq() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; +// #[test] +// fn random_eq() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; - let challenge = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - - - let mut circuit = Circuit::new(TEST_LEN + 1, 1); - let challenge_value = circuit.ext_val(1)[0]; - let numerators_values = circuit.ext_val(TEST_LEN); - let result_value = circuit.ext_val(1)[0]; - - let challenge_variable = input(&mut circuit, challenge_value, 0); - let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); - let reslut_variable = input(&mut circuit, result_value, 0); - - fracsum_flat_constrain(&mut circuit, &numerator_variables, &points, reslut_variable, challenge_variable); - let mut instance = circuit.finalize(); - - instance.set_ext(challenge_value, challenge); - numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| instance.set_ext(val, point)).last(); - instance.set_ext(result_value, result); - - instance.execute(0); - instance.valid_witness(); - } - } - mod invsum_gadget{ - use super::*; - - #[test] - fn random_eq() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let rate = 3; - let challenge = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); +// let challenge = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); + + +// let mut circuit = Circuit::new(TEST_LEN + 1, 1); +// let challenge_value = circuit.ext_val(1)[0]; +// let numerators_values = circuit.ext_val(TEST_LEN); +// let result_value = circuit.ext_val(1)[0]; + +// let challenge_variable = input(&mut circuit, challenge_value, 0); +// let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); +// let reslut_variable = input(&mut circuit, result_value, 0); + +// fracsum_flat_constrain(&mut circuit, &numerator_variables, &points, reslut_variable, challenge_variable); +// let mut instance = circuit.finalize(); + +// instance.set_ext(challenge_value, challenge); +// numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| instance.set_ext(val, point)).last(); +// instance.set_ext(result_value, result); + +// instance.execute(0); +// instance.valid_witness(); +// } +// } +// mod invsum_gadget{ +// use super::*; + +// #[test] +// fn random_eq() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let rate = 3; +// let challenge = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); - let mut circuit = Circuit::new(10, 1); - let challenge_value = circuit.ext_val(1)[0]; - let points_values = circuit.ext_val(TEST_LEN); +// let mut circuit = Circuit::new(10, 1); +// let challenge_value = circuit.ext_val(1)[0]; +// let points_values = circuit.ext_val(TEST_LEN); - let challenge_variable = input(&mut circuit, challenge_value, 0); - let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); +// let challenge_variable = input(&mut circuit, challenge_value, 0); +// let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); - let result_variable = invsum_gadget(&mut circuit, &points_variables, challenge_variable, rate, 0); - let mut circuit = circuit.finalize(); +// let result_variable = invsum_gadget(&mut circuit, &points_variables, challenge_variable, rate, 0); +// let mut circuit = circuit.finalize(); - circuit.set_ext(challenge_value, challenge); - points_values.into_iter().zip_eq(points).map(|(val, point)| circuit.set_ext(val, point)).last(); +// circuit.set_ext(challenge_value, challenge); +// points_values.into_iter().zip_eq(points).map(|(val, point)| circuit.set_ext(val, point)).last(); - circuit.execute(0); - circuit.valid_witness(); +// circuit.execute(0); +// circuit.valid_witness(); - assert_eq!(result, circuit.cs.getvar(result_variable)); - } - } +// assert_eq!(result, circuit.cs.getvar(result_variable)); +// } +// } - mod fracsum_gadget { - use super::*; +// mod fracsum_gadget { +// use super::*; - #[test] - fn random_eq() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; +// #[test] +// fn random_eq() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; - let challenge = F::random(OsRng); - let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - - let mut circuit = Circuit::new(TEST_LEN + 1, 1); - let challenge_value = circuit.ext_val(1)[0]; - let numerators_values = circuit.ext_val(TEST_LEN); - - let challenge_variable = input(&mut circuit, challenge_value, 0); - let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); - - let result_variable = fracsum_gadget(&mut circuit, &numerator_variables, &points, challenge_variable, 3, 0); - let mut circuit = circuit.finalize(); - - circuit.set_ext(challenge_value, challenge); - numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| circuit.set_ext(val, point)).last(); - - circuit.execute(0); - circuit.valid_witness(); - assert_eq!(result, circuit.cs.getvar(result_variable)); - } - } - - mod range_lookup { - use super::*; - - use rand_core::RngCore; - - #[test] - fn random() { - type F = bn256::Fr; - let indexes = 0..TEST_LEN; - let range = 16; - - let table = (0..range).map(|_| F::random(OsRng)).collect_vec(); - let mut circuit = Circuit::new(range + 1, TEST_LEN + 1); - - let challenge_value = circuit.ext_val(1)[0]; - let test_values = circuit.ext_val(TEST_LEN); - let mut range_lookup = StaticLookup::new(challenge_value, &table); - - let test_variables = test_values.clone().into_iter().enumerate().map(|(i, v)| input(&mut circuit, v, i)).collect_vec(); - test_variables.into_iter().map(|variable| range_lookup.check(&mut circuit, variable)).last(); - range_lookup.finalize(&mut circuit, 0, TEST_LEN - 1, TEST_LEN, 2); - let mut circuit = circuit.finalize(); - - test_values.into_iter().map(|val| circuit.set_ext(val, table[(OsRng.next_u64() % range as u64) as usize])).last(); - for i in indexes { - circuit.execute(i); - } - let challenge = F::random(OsRng); - circuit.set_ext(challenge_value, challenge); - circuit.execute(TEST_LEN); - circuit.valid_witness(); - } - - mod invalid { - use super::*; - - #[test] - #[should_panic] - fn low_challendge_round() { - type F = bn256::Fr; - let range = 16; - let rounds = 3; +// let challenge = F::random(OsRng); +// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); +// let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); + +// let mut circuit = Circuit::new(TEST_LEN + 1, 1); +// let challenge_value = circuit.ext_val(1)[0]; +// let numerators_values = circuit.ext_val(TEST_LEN); + +// let challenge_variable = input(&mut circuit, challenge_value, 0); +// let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); + +// let result_variable = fracsum_gadget(&mut circuit, &numerator_variables, &points, challenge_variable, 3, 0); +// let mut circuit = circuit.finalize(); + +// circuit.set_ext(challenge_value, challenge); +// numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| circuit.set_ext(val, point)).last(); + +// circuit.execute(0); +// circuit.valid_witness(); +// assert_eq!(result, circuit.cs.getvar(result_variable)); +// } +// } + +// mod range_lookup { +// use super::*; + +// use rand_core::RngCore; + +// #[test] +// fn random() { +// type F = bn256::Fr; +// let indexes = 0..TEST_LEN; +// let range = 16; + +// let table = (0..range).map(|_| F::random(OsRng)).collect_vec(); +// let mut circuit = Circuit::new(range + 1, TEST_LEN + 1); + +// let challenge_value = circuit.ext_val(1)[0]; +// let test_values = circuit.ext_val(TEST_LEN); +// let mut range_lookup = StaticLookup::new(challenge_value, &table); + +// let test_variables = test_values.clone().into_iter().enumerate().map(|(i, v)| input(&mut circuit, v, i)).collect_vec(); +// test_variables.into_iter().map(|variable| range_lookup.check(&mut circuit, variable)).last(); +// range_lookup.finalize(&mut circuit, 0, TEST_LEN - 1, TEST_LEN, 2); +// let mut circuit = circuit.finalize(); + +// test_values.into_iter().map(|val| circuit.set_ext(val, table[(OsRng.next_u64() % range as u64) as usize])).last(); +// for i in indexes { +// circuit.execute(i); +// } +// let challenge = F::random(OsRng); +// circuit.set_ext(challenge_value, challenge); +// circuit.execute(TEST_LEN); +// circuit.valid_witness(); +// } + +// mod invalid { +// use super::*; + +// #[test] +// #[should_panic] +// fn low_challendge_round() { +// type F = bn256::Fr; +// let range = 16; +// let rounds = 3; - let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); - let mut circuit = Circuit::new(range + 1, rounds); - - let challenge_value: ExternalValue = circuit.ext_val(1)[0]; - let test_value = circuit.ext_val(1)[0]; - let mut range_lookup = StaticLookup::new(challenge_value, &table); - - let test_variable = input(&mut circuit, test_value, 0); - range_lookup.check(&mut circuit, test_variable); - range_lookup.finalize(&mut circuit, 1, 1, 1, 2); - } - - #[test] - #[should_panic] - fn high_value_round() { - type F = bn256::Fr; - let range = 16; - let rounds = 3; +// let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); +// let mut circuit = Circuit::new(range + 1, rounds); + +// let challenge_value: ExternalValue = circuit.ext_val(1)[0]; +// let test_value = circuit.ext_val(1)[0]; +// let mut range_lookup = StaticLookup::new(challenge_value, &table); + +// let test_variable = input(&mut circuit, test_value, 0); +// range_lookup.check(&mut circuit, test_variable); +// range_lookup.finalize(&mut circuit, 1, 1, 1, 2); +// } + +// #[test] +// #[should_panic] +// fn high_value_round() { +// type F = bn256::Fr; +// let range = 16; +// let rounds = 3; - let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); - let mut circuit = Circuit::new(range + 1, rounds); - - let challenge_value: ExternalValue = circuit.ext_val(1)[0]; - let test_value = circuit.ext_val(1)[0]; - let mut range_lookup = StaticLookup::new(challenge_value, &table); - - let test_variable = input(&mut circuit, test_value, 2); - range_lookup.check(&mut circuit, test_variable); - range_lookup.finalize(&mut circuit, 1, 1, 1, 2); - } - - #[test] - #[should_panic] - fn high_table_round() { - type F = bn256::Fr; - let range = 16; - let rounds = 3; +// let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); +// let mut circuit = Circuit::new(range + 1, rounds); + +// let challenge_value: ExternalValue = circuit.ext_val(1)[0]; +// let test_value = circuit.ext_val(1)[0]; +// let mut range_lookup = StaticLookup::new(challenge_value, &table); + +// let test_variable = input(&mut circuit, test_value, 2); +// range_lookup.check(&mut circuit, test_variable); +// range_lookup.finalize(&mut circuit, 1, 1, 1, 2); +// } + +// #[test] +// #[should_panic] +// fn high_table_round() { +// type F = bn256::Fr; +// let range = 16; +// let rounds = 3; - let mut circuit = Circuit::new(range + 1, rounds); +// let mut circuit = Circuit::new(range + 1, rounds); - let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); - - let challenge_value: ExternalValue = circuit.ext_val(1)[0]; - let test_value = circuit.ext_val(1)[0]; - let mut range_lookup = StaticLookup::new(challenge_value, &table); - - let test_variable = input(&mut circuit, test_value, 2); - range_lookup.check(&mut circuit, test_variable); - range_lookup.finalize(&mut circuit, 1, 0, 2, 2); - } - } - } -} \ No newline at end of file +// let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); + +// let challenge_value: ExternalValue = circuit.ext_val(1)[0]; +// let test_value = circuit.ext_val(1)[0]; +// let mut range_lookup = StaticLookup::new(challenge_value, &table); + +// let test_variable = input(&mut circuit, test_value, 2); +// range_lookup.check(&mut circuit, test_variable); +// range_lookup.finalize(&mut circuit, 1, 0, 2, 2); +// } +// } +// } +// } \ No newline at end of file diff --git a/src/gadgets/nonzero_check.rs b/src/gadgets/nonzero_check.rs index 29d7a32..c483d97 100644 --- a/src/gadgets/nonzero_check.rs +++ b/src/gadgets/nonzero_check.rs @@ -19,7 +19,7 @@ pub fn nonzero_gadget<'a, F: PrimeField + FieldUtils> (circuit: &mut Circuit<'a, let prod = prod_run_gadget(circuit, input.to_vec(), round, rate); let adv_invert = Advice::new(1, 0, 1, |arg: &[F], _| vec![arg[0].invert().unwrap()]); - let prod_inv = circuit.advice(round, adv_invert, vec![prod], vec![])[0]; + let prod_inv = circuit.advice(round, adv_invert, vec![prod])[0]; circuit.constrain_with( &vec![prod, prod_inv], diff --git a/src/gadgets/poseidon.rs b/src/gadgets/poseidon.rs index 6cb06df..536ac8e 100644 --- a/src/gadgets/poseidon.rs +++ b/src/gadgets/poseidon.rs @@ -132,10 +132,9 @@ pub fn poseidon_partial_rounds_gadget<'a>(circuit: &mut Circuit<'a, F, Gatebb<'a t, 0, n_rounds_p + t, - move |input_state: &[F], _: &[F]| poseidon_partial_rounds_advice(input_state, c, m, n_rounds_f, n_rounds_p, t) + move |input_state, _| poseidon_partial_rounds_advice(input_state, c, m, n_rounds_f, n_rounds_p, t) ), inp.clone(), - vec![], ); let (adv, out) = tmp.split_at(n_rounds_p); diff --git a/src/gadgets/range.rs b/src/gadgets/range.rs index cb7d260..ba73204 100644 --- a/src/gadgets/range.rs +++ b/src/gadgets/range.rs @@ -193,7 +193,7 @@ pub fn limb_decompose_gadget<'a, F: PrimeField+FieldUtils>( 1, 0, num_limbs, - move |args,_| { + move |args, _| { let x = args[0]; let limbs = limbs(x, base); assert!(limbs.len()<=num_limbs, "The value has too many limbs."); @@ -201,7 +201,6 @@ pub fn limb_decompose_gadget<'a, F: PrimeField+FieldUtils>( } ), vec![input], - vec![] ); diff --git a/src/test.rs b/src/test.rs index b1e22cb..de2cbce 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,435 +1,435 @@ -#[cfg(test)] -mod tests { - use std::rc::Rc; - - use crate::{ - gate::Gatebb, - constraint_system::{Variable, Visibility}, - circuit::{Circuit, PolyOp, Advice}, - gadgets::{ - poseidon::{ - poseidon_gadget_mixstrat, - poseidon_gadget_internal - }, - bits::bit_decomposition_gadget, - ecmul::{ - add_proj, - double_proj, - EcAffinePoint, - escalarmul_gadget_9 - }, - range::{ - rangecheck, - limb_decompose_gadget, - lagrange_choice, - lagrange_choice_batched, - VarSmall, - choice_gadget - }, - nonzero_check::nonzero_gadget, input::input - }, folding::poseidon::Poseidon - }; - use ff::{PrimeField, Field}; - use group::{Group, Curve}; - use halo2::halo2curves::{bn256, grumpkin, CurveAffine, CurveExt}; - use rand_core::OsRng; - use crate::utils::poly_utils::{check_poly, find_degree}; - use crate::utils::field_precomp::FieldUtils; - - type F = bn256::Fr; - type C = grumpkin::G1; - - type Fq = ::ScalarExt; - - // #[test] - - // fn test_cross_terms() { - - // for d in 2..10{ - // let f = Rc::new(|v: &[F]| vec![v[0].pow([2 as u64])]); - // let gate = Gatebb::new(2, 1, 1, f); - // let tmp = gate.cross_terms_adjust(&vec![F::ONE], &vec![F::ONE], d); - // println!("{:?}", tmp.iter().map(|v|v[0]).collect::>()); - // } - // } - - #[test] - - fn test_circuit_builder() { - let mut circuit = Circuit::>::new(2, 1); - let public_input_source = circuit.ext_val(1)[0]; - - let sq = PolyOp::new(2, 1, 1, |x, _| vec!(x[0]*x[0])); - let input = input(&mut circuit, public_input_source, 0); - let sq1 = circuit.apply(0, sq.clone(), vec![input]); - let _ = circuit.apply_pub(0, sq.clone(), sq1); - - let mut instance = circuit.finalize(); +// #[cfg(test)] +// mod tests { +// use std::rc::Rc; + +// use crate::{ +// gate::Gatebb, +// constraint_system::{Variable, Visibility}, +// circuit::{Circuit, PolyOp, Advice}, +// gadgets::{ +// poseidon::{ +// poseidon_gadget_mixstrat, +// poseidon_gadget_internal +// }, +// bits::bit_decomposition_gadget, +// ecmul::{ +// add_proj, +// double_proj, +// EcAffinePoint, +// escalarmul_gadget_9 +// }, +// range::{ +// rangecheck, +// limb_decompose_gadget, +// lagrange_choice, +// lagrange_choice_batched, +// VarSmall, +// choice_gadget +// }, +// nonzero_check::nonzero_gadget, input::input +// }, folding::poseidon::Poseidon +// }; +// use ff::{PrimeField, Field}; +// use group::{Group, Curve}; +// use halo2::halo2curves::{bn256, grumpkin, CurveAffine, CurveExt}; +// use rand_core::OsRng; +// use crate::utils::poly_utils::{check_poly, find_degree}; +// use crate::utils::field_precomp::FieldUtils; + +// type F = bn256::Fr; +// type C = grumpkin::G1; + +// type Fq = ::ScalarExt; + +// // #[test] + +// // fn test_cross_terms() { + +// // for d in 2..10{ +// // let f = Rc::new(|v: &[F]| vec![v[0].pow([2 as u64])]); +// // let gate = Gatebb::new(2, 1, 1, f); +// // let tmp = gate.cross_terms_adjust(&vec![F::ONE], &vec![F::ONE], d); +// // println!("{:?}", tmp.iter().map(|v|v[0]).collect::>()); +// // } +// // } + +// #[test] + +// fn test_circuit_builder() { +// let mut circuit = Circuit::>::new(2, 1); +// let public_input_source = circuit.ext_val(1)[0]; + +// let sq = PolyOp::new(2, 1, 1, |x, _| vec!(x[0]*x[0])); +// let input = input(&mut circuit, public_input_source, 0); +// let sq1 = circuit.apply(0, sq.clone(), vec![input]); +// let _ = circuit.apply_pub(0, sq.clone(), sq1); + +// let mut constructed = circuit.finalize(); - instance.set_ext(public_input_source, F::from(2)); +// instance.set_ext(public_input_source, F::from(2)); - instance.execute(0); +// instance.execute(0); - let var = Variable { visibility: Visibility::Public, round: 0, index: 2 }; - assert_eq!(F::from(16), instance.cs.getvar(var)); - } +// let var = Variable { visibility: Visibility::Public, round: 0, index: 2 }; +// assert_eq!(F::from(16), instance.cs.getvar(var)); +// } - #[test] +// #[test] - fn test_permutation_argument() { +// fn test_permutation_argument() { - let mut circuit = Circuit::new(2, 2); - let pi_ext = circuit.ext_val(5); - let challenge_ext = circuit.ext_val(1)[0]; - - let one = circuit.one(); +// let mut circuit = Circuit::new(2, 2); +// let pi_ext = circuit.ext_val(5); +// let challenge_ext = circuit.ext_val(1)[0]; + +// let one = circuit.one(); - let mut pi = vec![]; - for k in 0..5{ - pi.push( - input(&mut circuit, pi_ext[k], 0) - ); - } +// let mut pi = vec![]; +// for k in 0..5{ +// pi.push( +// input(&mut circuit, pi_ext[k], 0) +// ); +// } - let challenge = input(&mut circuit, challenge_ext, 1); +// let challenge = input(&mut circuit, challenge_ext, 1); - let division_advice = Advice::new(2, 0, 1, |ivar : &[F], _| { - let ch = ivar[0]; - let x = ivar[1]; - vec![(x-ch).invert().unwrap()] - }); +// let division_advice = Advice::new(2, 0, 1, |ivar : &[F], _| { +// let ch = ivar[0]; +// let x = ivar[1]; +// vec![(x-ch).invert().unwrap()] +// }); - let mut fractions = vec![]; - for k in 0..5 { - fractions.push( - circuit.advice(1, division_advice.clone(), vec![challenge, pi[k]], vec![])[0] - ); - } +// let mut fractions = vec![]; +// for k in 0..5 { +// fractions.push( +// circuit.advice(1, division_advice.clone(), vec![challenge, pi[k]])[0] +// ); +// } - let div_constr = Gatebb::::new( - 2, 4, 1, - Rc::new(|args, _|{ - let one = args[0]; - let ch = args[1]; - let x = args[2]; - let res = args[3]; - vec![one*one - res * (x-ch)] - }), - vec![], - ); +// let div_constr = Gatebb::::new( +// 2, 4, 1, +// Rc::new(|args, _|{ +// let one = args[0]; +// let ch = args[1]; +// let x = args[2]; +// let res = args[3]; +// vec![one*one - res * (x-ch)] +// }), +// vec![], +// ); - for k in 0..5 { - circuit.constrain(&[one, challenge, pi[k], fractions[k]], div_constr.clone()); - } +// for k in 0..5 { +// circuit.constrain(&[one, challenge, pi[k], fractions[k]], div_constr.clone()); +// } - let mut circuit = circuit.finalize(); +// let mut circuit = circuit.finalize(); - // construction phase ended - circuit.set_ext(pi_ext[0], F::from(2)); - circuit.set_ext(pi_ext[1], F::from(3)); - circuit.set_ext(pi_ext[2], F::from(4)); - circuit.set_ext(pi_ext[3], F::from(5)); - circuit.set_ext(pi_ext[4], F::from(6)); +// // construction phase ended +// circuit.set_ext(pi_ext[0], F::from(2)); +// circuit.set_ext(pi_ext[1], F::from(3)); +// circuit.set_ext(pi_ext[2], F::from(4)); +// circuit.set_ext(pi_ext[3], F::from(5)); +// circuit.set_ext(pi_ext[4], F::from(6)); - circuit.execute(0); +// circuit.execute(0); - circuit.set_ext(challenge_ext, F::random(OsRng)); +// circuit.set_ext(challenge_ext, F::random(OsRng)); - circuit.execute(1); +// circuit.execute(1); - circuit.valid_witness(); // test that constraints are satisfied - } +// circuit.valid_witness(); // test that constraints are satisfied +// } - #[test] - fn test_poseidon_gadget(){ - let cfg = Poseidon::new(); - let mut circuit = Circuit::new(25, 1); - let pi_ext = circuit.ext_val(1)[0]; - let pi = input(&mut circuit, pi_ext, 0); - let ret = poseidon_gadget_internal(&mut circuit, &cfg, 1, 0, vec![pi]); +// #[test] +// fn test_poseidon_gadget(){ +// let cfg = Poseidon::new(); +// let mut circuit = Circuit::new(25, 1); +// let pi_ext = circuit.ext_val(1)[0]; +// let pi = input(&mut circuit, pi_ext, 0); +// let ret = poseidon_gadget_internal(&mut circuit, &cfg, 1, 0, vec![pi]); - let mut circuit = circuit.finalize(); +// let mut circuit = circuit.finalize(); - circuit.set_ext(pi_ext, F::ONE); +// circuit.set_ext(pi_ext, F::ONE); - circuit.execute(0); - circuit.valid_witness(); +// circuit.execute(0); +// circuit.valid_witness(); - assert_eq!(circuit.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); - } +// assert_eq!(circuit.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); +// } - #[test] - fn test_poseidon_gadget_k_equals_two(){ - let cfg = Poseidon::new(); - let mut circuit = Circuit::new(25, 1); - let pi_ext = circuit.ext_val(1)[0]; - let pi = input(&mut circuit, pi_ext, 0); - let ret = poseidon_gadget_internal(&mut circuit, &cfg, 2, 0, vec![pi]); +// #[test] +// fn test_poseidon_gadget_k_equals_two(){ +// let cfg = Poseidon::new(); +// let mut circuit = Circuit::new(25, 1); +// let pi_ext = circuit.ext_val(1)[0]; +// let pi = input(&mut circuit, pi_ext, 0); +// let ret = poseidon_gadget_internal(&mut circuit, &cfg, 2, 0, vec![pi]); - let mut circuit = circuit.finalize(); +// let mut circuit = circuit.finalize(); - circuit.set_ext(pi_ext, F::ONE); +// circuit.set_ext(pi_ext, F::ONE); - circuit.execute(0); - circuit.valid_witness(); +// circuit.execute(0); +// circuit.valid_witness(); - assert_eq!(circuit.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); - } +// assert_eq!(circuit.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); +// } - #[test] - fn test_poseidon_gadget_mixstrat(){ - let cfg = Poseidon::new(); - let mut circuit = Circuit::new(25, 1); - let pi_ext = circuit.ext_val(1)[0]; - let pi = input(&mut circuit, pi_ext, 0); - let ret = poseidon_gadget_mixstrat(&mut circuit, &cfg, 0, vec![pi]); +// #[test] +// fn test_poseidon_gadget_mixstrat(){ +// let cfg = Poseidon::new(); +// let mut circuit = Circuit::new(25, 1); +// let pi_ext = circuit.ext_val(1)[0]; +// let pi = input(&mut circuit, pi_ext, 0); +// let ret = poseidon_gadget_mixstrat(&mut circuit, &cfg, 0, vec![pi]); - let mut circuit = circuit.finalize(); +// let mut circuit = circuit.finalize(); - circuit.set_ext(pi_ext, F::ONE); +// circuit.set_ext(pi_ext, F::ONE); - circuit.execute(0); - circuit.valid_witness(); +// circuit.execute(0); +// circuit.valid_witness(); - assert!(circuit.cs.getvar(ret) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); +// assert!(circuit.cs.getvar(ret) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); - assert!(cfg.hash(vec![F::ONE]) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); +// assert!(cfg.hash(vec![F::ONE]) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); - println!("{:?}", circuit.cs.getvar(ret).to_repr()); - } +// println!("{:?}", circuit.cs.getvar(ret).to_repr()); +// } - #[test] +// #[test] - fn test_bit_decomposition(){ - let mut circuit = Circuit::new(2, 1); - let pi_ext = circuit.ext_val(1)[0]; +// fn test_bit_decomposition(){ +// let mut circuit = Circuit::new(2, 1); +// let pi_ext = circuit.ext_val(1)[0]; - let pi = input(&mut circuit, pi_ext, 0); +// let pi = input(&mut circuit, pi_ext, 0); - let bits = bit_decomposition_gadget(&mut circuit, 0, 3, pi); +// let bits = bit_decomposition_gadget(&mut circuit, 0, 3, pi); - let mut circuit = circuit.finalize(); - circuit.set_ext(pi_ext, F::from(6)); - circuit.execute(0); +// let mut circuit = circuit.finalize(); +// circuit.set_ext(pi_ext, F::from(6)); +// circuit.execute(0); - circuit.valid_witness(); +// circuit.valid_witness(); - assert!(bits.len()==3); - assert!(circuit.cs.getvar(bits[0]) == F::ZERO); - assert!(circuit.cs.getvar(bits[1]) == F::ONE); - assert!(circuit.cs.getvar(bits[2]) == F::ONE); - } +// assert!(bits.len()==3); +// assert!(circuit.cs.getvar(bits[0]) == F::ZERO); +// assert!(circuit.cs.getvar(bits[1]) == F::ONE); +// assert!(circuit.cs.getvar(bits[2]) == F::ONE); +// } - #[test] +// #[test] - fn test_check_poly() { - let f = Rc::new(|x: &[F], _: &[F]|{vec![x[0].pow([5])]}); - check_poly(5, 1, 1, f, &[]).unwrap(); - } +// fn test_check_poly() { +// let f = Rc::new(|x: &[F], _: &[F]|{vec![x[0].pow([5])]}); +// check_poly(5, 1, 1, f, &[]).unwrap(); +// } - #[test] +// #[test] - fn test_scale(){ - let x = F::random(OsRng); - for y in 0..100 { - assert!(x.scale(y) == x*F::from(y)); - } - } +// fn test_scale(){ +// let x = F::random(OsRng); +// for y in 0..100 { +// assert!(x.scale(y) == x*F::from(y)); +// } +// } - #[test] +// #[test] - fn test_add() { - let pt1 = C::random(OsRng).to_affine(); - let pt2 = C::random(OsRng).to_affine(); +// fn test_add() { +// let pt1 = C::random(OsRng).to_affine(); +// let pt2 = C::random(OsRng).to_affine(); - let pt1_ = (pt1.x, pt1.y); - let pt2_ = (pt2.x, pt2.y); +// let pt1_ = (pt1.x, pt1.y); +// let pt2_ = (pt2.x, pt2.y); - let pt3_ = add_proj::(pt1_, pt2_); +// let pt3_ = add_proj::(pt1_, pt2_); - let r3_inv = pt3_.2.invert().unwrap(); - let pt3 = grumpkin::G1Affine::from_xy(pt3_.0*r3_inv, pt3_.1*r3_inv).unwrap(); - - assert!(Into::::into(pt3) == pt1+pt2); - } +// let r3_inv = pt3_.2.invert().unwrap(); +// let pt3 = grumpkin::G1Affine::from_xy(pt3_.0*r3_inv, pt3_.1*r3_inv).unwrap(); + +// assert!(Into::::into(pt3) == pt1+pt2); +// } - #[test] +// #[test] - fn test_double() { - let pt = C::random(OsRng).to_affine(); - let pt_ = (pt.x, pt.y); - let pt2_ = double_proj::(pt_); - let rinv = pt2_.2.invert().unwrap(); - let pt2 = grumpkin::G1Affine::from_xy(pt2_.0*rinv, pt2_.1*rinv).unwrap(); - assert!(Into::::into(pt2) == pt+pt); +// fn test_double() { +// let pt = C::random(OsRng).to_affine(); +// let pt_ = (pt.x, pt.y); +// let pt2_ = double_proj::(pt_); +// let rinv = pt2_.2.invert().unwrap(); +// let pt2 = grumpkin::G1Affine::from_xy(pt2_.0*rinv, pt2_.1*rinv).unwrap(); +// assert!(Into::::into(pt2) == pt+pt); - } +// } - #[test] +// #[test] - fn test_range_check() { - for range in 1..10 { - for i in 1..10 { - let x = F::from(i); - assert!(if i < range {rangecheck(x, range) == F::ZERO} else {rangecheck(x, range) != F::ZERO}); - } - } - } +// fn test_range_check() { +// for range in 1..10 { +// for i in 1..10 { +// let x = F::from(i); +// assert!(if i < range {rangecheck(x, range) == F::ZERO} else {rangecheck(x, range) != F::ZERO}); +// } +// } +// } - #[test] +// #[test] - fn test_limb_decompose_gadget() { +// fn test_limb_decompose_gadget() { - let mut circuit = Circuit::new(9, 1); - let pi_ext = circuit.ext_val(1)[0]; - let pi = input(&mut circuit, pi_ext, 0); +// let mut circuit = Circuit::new(9, 1); +// let pi_ext = circuit.ext_val(1)[0]; +// let pi = input(&mut circuit, pi_ext, 0); - let limbs = limb_decompose_gadget(&mut circuit, 9, 0, 2, pi); +// let limbs = limb_decompose_gadget(&mut circuit, 9, 0, 2, pi); - let mut circuit = circuit.finalize(); - circuit.set_ext(pi_ext, F::from(25)); - circuit.execute(0); +// let mut circuit = circuit.finalize(); +// circuit.set_ext(pi_ext, F::from(25)); +// circuit.execute(0); - circuit.valid_witness(); +// circuit.valid_witness(); - assert!(limbs.len()==2); - assert!(circuit.cs.getvar(limbs[0].var) == F::from(7)); - assert!(circuit.cs.getvar(limbs[1].var) == F::from(2)); +// assert!(limbs.len()==2); +// assert!(circuit.cs.getvar(limbs[0].var) == F::from(7)); +// assert!(circuit.cs.getvar(limbs[1].var) == F::from(2)); - } +// } - #[test] +// #[test] - fn test_lagrange_choice() -> () { - for n in 2..12 { - for t in 0..n { - assert!(find_degree(32, 1, 1, Rc::new(move |v: &[F], _| vec![lagrange_choice(v[0],t,n)]), &[]).unwrap() == (n-1) as usize); - for x in 0..n { - if x == t { - assert!(lagrange_choice(F::from(x), t, n) == F::ONE); - } else { - assert!(lagrange_choice(F::from(x), t, n) == F::ZERO); - } - } +// fn test_lagrange_choice() -> () { +// for n in 2..12 { +// for t in 0..n { +// assert!(find_degree(32, 1, 1, Rc::new(move |v: &[F], _| vec![lagrange_choice(v[0],t,n)]), &[]).unwrap() == (n-1) as usize); +// for x in 0..n { +// if x == t { +// assert!(lagrange_choice(F::from(x), t, n) == F::ONE); +// } else { +// assert!(lagrange_choice(F::from(x), t, n) == F::ZERO); +// } +// } - } - } - } +// } +// } +// } - #[test] +// #[test] - fn test_lagrange_batch() -> () { - for n in 2..12 { - assert!(find_degree(32, 1, n, Rc::new(move |v: &[F], _| lagrange_choice_batched(v[0], n as u64)), &[]).unwrap() == (n-1)); - for x in 0..n { - let v = lagrange_choice_batched(F::from(x as u64), n as u64); - for t in 0..n { - assert!(if t==x {v[t] == F::ONE} else {v[t] == F::ZERO}) - } - } - } - } +// fn test_lagrange_batch() -> () { +// for n in 2..12 { +// assert!(find_degree(32, 1, n, Rc::new(move |v: &[F], _| lagrange_choice_batched(v[0], n as u64)), &[]).unwrap() == (n-1)); +// for x in 0..n { +// let v = lagrange_choice_batched(F::from(x as u64), n as u64); +// for t in 0..n { +// assert!(if t==x {v[t] == F::ONE} else {v[t] == F::ZERO}) +// } +// } +// } +// } - #[test] +// #[test] - fn test_choice_gadget() -> () { - let mut circuit = Circuit::new(10, 1); +// fn test_choice_gadget() -> () { +// let mut circuit = Circuit::new(10, 1); - let mut pi_ext = vec![]; - let pi_id_ext = circuit.ext_val(1)[0]; - for _ in 0..9 { - pi_ext.push(circuit.ext_val(3)); - } +// let mut pi_ext = vec![]; +// let pi_id_ext = circuit.ext_val(1)[0]; +// for _ in 0..9 { +// pi_ext.push(circuit.ext_val(3)); +// } - let mut pi = vec![]; - for i in 0..9 { - pi.push(vec![]); - for j in 0..3 { - pi[i].push(input(&mut circuit, pi_ext[i][j], 0)); - } - } - let pi_id = input(&mut circuit, pi_id_ext, 0); +// let mut pi = vec![]; +// for i in 0..9 { +// pi.push(vec![]); +// for j in 0..3 { +// pi[i].push(input(&mut circuit, pi_ext[i][j], 0)); +// } +// } +// let pi_id = input(&mut circuit, pi_id_ext, 0); - let pi : Vec<_> = pi.iter().map(|x|x.as_ref()).collect(); - let chosen = choice_gadget(&mut circuit, &pi, VarSmall::new_unchecked(pi_id, 9), 0); +// let pi : Vec<_> = pi.iter().map(|x|x.as_ref()).collect(); +// let chosen = choice_gadget(&mut circuit, &pi, VarSmall::new_unchecked(pi_id, 9), 0); - let mut circuit = circuit.finalize(); - circuit.set_ext(pi_id_ext, F::from(5)); - for i in 0..9 { - for j in 0..3 { - circuit.set_ext(pi_ext[i][j], F::random(OsRng)); - } - } - circuit.execute(0); +// let mut circuit = circuit.finalize(); +// circuit.set_ext(pi_id_ext, F::from(5)); +// for i in 0..9 { +// for j in 0..3 { +// circuit.set_ext(pi_ext[i][j], F::random(OsRng)); +// } +// } +// circuit.execute(0); - circuit.valid_witness(); +// circuit.valid_witness(); - assert!(chosen.len() == 3); +// assert!(chosen.len() == 3); - for j in 0..3 { - assert!(circuit.cs.getvar(pi[5][j]) == circuit.cs.getvar(chosen[j])) - } - } +// for j in 0..3 { +// assert!(circuit.cs.getvar(pi[5][j]) == circuit.cs.getvar(chosen[j])) +// } +// } - #[test] - fn test_escalarmul_gadget()->(){ - let mut circuit = Circuit::new(10, 1); +// #[test] +// fn test_escalarmul_gadget()->(){ +// let mut circuit = Circuit::new(10, 1); - let pi_a_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); - let pi_b_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band - let pi_pt_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); - let pi_sc_ext = circuit.ext_val(1)[0]; +// let pi_a_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); +// let pi_b_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band +// let pi_pt_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); +// let pi_sc_ext = circuit.ext_val(1)[0]; - let x = input(&mut circuit, pi_a_ext.0, 0); - let y = input(&mut circuit, pi_a_ext.1, 0); - let a = EcAffinePoint::::new(&mut circuit, x, y); - let x = input(&mut circuit, pi_b_ext.0, 0); - let y = input(&mut circuit, pi_b_ext.1, 0); - let b = EcAffinePoint::::new(&mut circuit, x, y); - let x = input(&mut circuit, pi_pt_ext.0, 0); - let y = input(&mut circuit, pi_pt_ext.1, 0); - let pt = EcAffinePoint::::new(&mut circuit, x, y); - let sc = input(&mut circuit, pi_sc_ext, 0); +// let x = input(&mut circuit, pi_a_ext.0, 0); +// let y = input(&mut circuit, pi_a_ext.1, 0); +// let a = EcAffinePoint::::new(&mut circuit, x, y); +// let x = input(&mut circuit, pi_b_ext.0, 0); +// let y = input(&mut circuit, pi_b_ext.1, 0); +// let b = EcAffinePoint::::new(&mut circuit, x, y); +// let x = input(&mut circuit, pi_pt_ext.0, 0); +// let y = input(&mut circuit, pi_pt_ext.1, 0); +// let pt = EcAffinePoint::::new(&mut circuit, x, y); +// let sc = input(&mut circuit, pi_sc_ext, 0); - let mut nonzeros = vec![]; - let num_limbs = 81; +// let mut nonzeros = vec![]; +// let num_limbs = 81; - let scmul = escalarmul_gadget_9(&mut circuit, sc, pt, num_limbs, 0, a, b, &mut nonzeros); +// let scmul = escalarmul_gadget_9(&mut circuit, sc, pt, num_limbs, 0, a, b, &mut nonzeros); - nonzero_gadget(&mut circuit, &nonzeros, 9); - let mut instance = circuit.finalize(); +// nonzero_gadget(&mut circuit, &nonzeros, 9); +// let mut instance = circuit.finalize(); - let pi_a = C::random(OsRng).to_affine(); - instance.set_ext(pi_a_ext.0, pi_a.x); - instance.set_ext(pi_a_ext.1, pi_a.y); +// let pi_a = C::random(OsRng).to_affine(); +// instance.set_ext(pi_a_ext.0, pi_a.x); +// instance.set_ext(pi_a_ext.1, pi_a.y); - //1+9+81+...+9^{num_limbs - 1} = (9^{num_limbs}-1)/8 +// //1+9+81+...+9^{num_limbs - 1} = (9^{num_limbs}-1)/8 - let bscale = (Fq::from(9).pow([num_limbs as u64])-Fq::ONE)*(Fq::from(8).invert().unwrap()); - let pi_b = -(C::from(pi_a)*bscale).to_affine(); - instance.set_ext(pi_b_ext.0, pi_b.x); - instance.set_ext(pi_b_ext.1, pi_b.y); +// let bscale = (Fq::from(9).pow([num_limbs as u64])-Fq::ONE)*(Fq::from(8).invert().unwrap()); +// let pi_b = -(C::from(pi_a)*bscale).to_affine(); +// instance.set_ext(pi_b_ext.0, pi_b.x); +// instance.set_ext(pi_b_ext.1, pi_b.y); - let pi_pt = C::random(OsRng).to_affine(); - instance.set_ext(pi_pt_ext.0, pi_pt.x); - instance.set_ext(pi_pt_ext.1, pi_pt.y); +// let pi_pt = C::random(OsRng).to_affine(); +// instance.set_ext(pi_pt_ext.0, pi_pt.x); +// instance.set_ext(pi_pt_ext.1, pi_pt.y); - instance.set_ext(pi_sc_ext, F::from(23)); +// instance.set_ext(pi_sc_ext, F::from(23)); - instance.execute(0); +// instance.execute(0); - instance.valid_witness(); +// instance.valid_witness(); - let answer = grumpkin::G1Affine::from_xy(instance.cs.getvar(scmul.x), instance.cs.getvar(scmul.y)).unwrap(); +// let answer = grumpkin::G1Affine::from_xy(instance.cs.getvar(scmul.x), instance.cs.getvar(scmul.y)).unwrap(); - assert!(answer == (pi_pt*::ScalarExt::from(23)).to_affine()); +// assert!(answer == (pi_pt*::ScalarExt::from(23)).to_affine()); - println!("Total circuit size: private: {} public: {}", instance.cs.wtns[0].privs.len(), instance.cs.wtns[0].pubs.len()); - } +// println!("Total circuit size: private: {} public: {}", instance.cs.wtns[0].privs.len(), instance.cs.wtns[0].pubs.len()); +// } -} \ No newline at end of file +// } \ No newline at end of file From 3584e61dd183a97448352e9df5409c6eccd144c5 Mon Sep 17 00:00:00 2001 From: rebenkoy Date: Wed, 22 Nov 2023 17:39:35 +0300 Subject: [PATCH 2/2] Inner Value not just for inner uses --- benches/bench_ecmul.rs | 6 +- benches/bench_poseidons.rs | 6 +- src/circuit.rs | 32 +- src/external_interface.rs | 105 +++++ src/gadgets/lookup.rs | 766 +++++++++++++++++++------------------ src/lib.rs | 3 +- src/test.rs | 690 +++++++++++++++++---------------- 7 files changed, 869 insertions(+), 739 deletions(-) create mode 100644 src/external_interface.rs diff --git a/benches/bench_ecmul.rs b/benches/bench_ecmul.rs index 96dd71c..b7248a1 100644 --- a/benches/bench_ecmul.rs +++ b/benches/bench_ecmul.rs @@ -83,7 +83,8 @@ pub fn ecmul_pseudo_fold(c: &mut Criterion) { assemble_ecmul_circuit(&mut circuit, &pi, num_limbs); - let mut instance = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); let pi_a_ext = (pi[0], pi[1]); let pi_b_ext = (pi[2], pi[3]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band @@ -141,7 +142,8 @@ pub fn ecmul_msm(c: &mut Criterion) { assemble_ecmul_circuit(&mut circuit, &pi, num_limbs); - let mut instance = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); let pi_a_ext = (pi[0], pi[1]); let pi_b_ext = (pi[2], pi[3]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band diff --git a/benches/bench_poseidons.rs b/benches/bench_poseidons.rs index 922dc4c..6c7210e 100644 --- a/benches/bench_poseidons.rs +++ b/benches/bench_poseidons.rs @@ -64,7 +64,8 @@ pub fn poseidons_pseudo_fold(c: &mut Criterion) { assemble_poseidon_circuit(&mut circuit, &cfg, pi); - let mut instance = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); instance.set_ext(pi, F::random(OsRng)); instance.execute(0); @@ -99,7 +100,8 @@ pub fn poseidons_msm(c: &mut Criterion) { let pi = circuit.ext_val(1)[0]; assemble_poseidon_circuit(&mut circuit, &cfg, pi); - let mut instance = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); instance.set_ext(pi, F::random(OsRng)); instance.execute(0); diff --git a/src/circuit.rs b/src/circuit.rs index a0c52ea..8e78556 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -2,7 +2,7 @@ use std::{rc::{Rc, Weak}, marker::PhantomData, iter::repeat_with, cell::RefCell} use elsa::map::FrozenMap; use ff::PrimeField; -use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub} }; +use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}, external_interface::{RunIndex, RunAllocator} }; use self::circuit_operations::CircuitOperation; @@ -310,7 +310,7 @@ where pub fn finalize(self) -> ConstructedCircuit<'circuit, F, G> { ConstructedCircuit { circuit: self, - num_runs: RefCell::new(0), + run_allocator: RefCell::new(RunAllocator::new()), } } @@ -323,33 +323,24 @@ where } } -pub struct RunIndex { - idx: usize, -} - -impl RunIndex { - fn new(idx: usize) -> Self { - Self { - idx, - } - } -} - pub struct ConstructedCircuit<'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> { circuit: Circuit<'circuit, F, G>, - num_runs: RefCell, + run_allocator: RefCell, } impl<'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> ConstructedCircuit<'circuit, F, G> { pub fn spawn<'constructed>(&'constructed self) -> CircuitRun<'constructed, 'circuit, F, G> { - *self.num_runs.borrow_mut() += 1; CircuitRun { constructed: &self, cs: CSWtns::::new(&self.circuit.cs), round_counter: 0, - run_idx: RunIndex::new(*self.num_runs.borrow() - 1), + run_idx: self.run_allocator.borrow_mut().allocate(), } } + + fn deallocate<'constructed>(&'constructed self, idx: RunIndex) { + self.run_allocator.borrow_mut().deallocate(idx); + } } pub struct CircuitRun<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>>{ @@ -393,5 +384,12 @@ where pub fn iter_constraints(&self) -> impl Iterator> { self.constructed.circuit.cs.iter_constraints() } + + pub fn finish(self) -> (CSWtns<'circuit, F, G>, &'constructed ConstraintSystem<'circuit, F, G>) { + let Self {constructed, cs, round_counter: _, run_idx} = self; + + constructed.deallocate(run_idx); + (cs, &constructed.circuit.cs) + } } diff --git a/src/external_interface.rs b/src/external_interface.rs new file mode 100644 index 0000000..0943865 --- /dev/null +++ b/src/external_interface.rs @@ -0,0 +1,105 @@ +use std::{cell::RefCell, rc::Rc}; + +pub struct RunAllocator { + free_slots: Vec, + total_spawned: usize, + active: usize, + allocated: usize, +} + +impl RunAllocator { + pub fn new() -> Self { + Self { free_slots: vec![], total_spawned: 0, active: 0, allocated: 0 } + } + + pub fn allocate(&mut self) -> RunIndex { + let slot = self.free_slots.pop().unwrap_or_else(|| { + self.allocated += 1; + self.allocated - 1 + }); + self.active += 1; + self.total_spawned += 1; + RunIndex { muid: self.total_spawned - 1, slot } + } + + pub fn deallocate(&mut self, idx: RunIndex) { + self.free_slots.push(idx.slot); + self.active -= 1; + } +} + +#[derive(Debug)] +pub struct RunIndex { + pub(crate) muid: usize, + pub(crate) slot: usize, +} + +struct CuratedSlot { + value: T, + muid: usize, +} + +#[derive(Clone)] +pub struct InnerValue { + data: Rc>>>> +} + +impl InnerValue { + pub fn new() -> Self { + Self { + data: Rc::new(RefCell::new(vec![])), + } + } + + pub fn get(&self, idx: &RunIndex) -> Option { + match self.data.borrow().get(idx.slot) { + Some(opt) => match opt { + Some(CuratedSlot{value, muid}) => match muid == &idx.muid { + true => Some(value.clone()), + false => match muid < &idx.muid { + true => None, + false => panic!("Accessing value with muid {} by idx: {:?}", muid, idx), + }, + }, + None => None, + }, + None => None, + } + + } + + pub fn set(&self, idx: &RunIndex, value: T) { + assert!(self.replace(idx, value).is_none(), "Attempting to set value by idx: {:?}, but is already set", idx) + } + + #[must_use = "if you intended to set a value, consider `set` method instead"] + pub fn replace(&self, idx: &RunIndex, value: T) -> Option { + let mut data = self.data.borrow_mut(); + if data.len() <= idx.slot { + data.resize_with(idx.slot + 1, || None); + } + match data[idx.slot] { + Some(CuratedSlot{muid, value: _}) => assert!(muid <= idx.muid, "Writing value with muid {} by idx: {:?}", muid, idx), + None => (), + } + data[idx.slot].replace(CuratedSlot { value: value.clone(), muid: idx.muid }).and_then(|CuratedSlot{value, muid}| if muid == idx.muid {Some(value)} else {None}) + } +} + + +#[test] +fn normal_usage() { + let x = InnerValue::new(); + + x.set(&RunIndex { muid: 0, slot: 0 }, 0); + x.set(&RunIndex { muid: 1, slot: 1 }, 1); + x.set(&RunIndex { muid: 2, slot: 2 }, 2); + assert_eq!(x.get(&RunIndex { muid: 0, slot: 0 }), Some(0)); + assert_eq!(x.get(&RunIndex { muid: 1, slot: 1 }), Some(1)); + assert_eq!(x.get(&RunIndex { muid: 2, slot: 2 }), Some(2)); + assert_eq!(x.get(&RunIndex { muid: 3, slot: 0 }), None); + x.set(&RunIndex { muid: 3, slot: 0 }, 3); + assert_eq!(x.get(&RunIndex { muid: 3, slot: 0 }), Some(3)); + assert_eq!(x.replace(&RunIndex { muid: 1, slot: 1 }, 5), Some(1)) +} + diff --git a/src/gadgets/lookup.rs b/src/gadgets/lookup.rs index 465211a..7509786 100644 --- a/src/gadgets/lookup.rs +++ b/src/gadgets/lookup.rs @@ -273,405 +273,415 @@ impl<'c, F: PrimeField+FieldUtils> Lookup<'c, F> for StaticLookup { } } -// #[cfg(test)] -// mod test { -// use super::*; -// const TEST_LEN: usize = 12; -// use ff::Field; -// use halo2::halo2curves::bn256; -// use itertools::Itertools; -// use rand_core::OsRng; - -// mod montgomery { -// use super::*; - -// #[test] -// fn empty() { -// type F = bn256::Fr; -// assert_eq!(montgomery::(&[]), (F::ONE, vec![])); -// } - -// #[test] -// fn one() { -// type F = bn256::Fr; -// let points = [F::random(OsRng)]; -// assert_eq!(montgomery::(&points), (points[0], vec![F::ONE])); -// } - -// #[test] -// fn random() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let (res_mul, res_partials) = montgomery::(&points); -// assert_eq!(res_mul, points.iter().fold(F::ONE, |acc, n| acc * n)); -// assert!(points.iter().zip_eq(res_partials).all(|(point, partial)| point * partial == res_mul)) -// } -// } +#[cfg(test)] +mod test { + use super::*; + const TEST_LEN: usize = 12; + use ff::Field; + use halo2::halo2curves::bn256; + use itertools::Itertools; + use rand_core::OsRng; + + mod montgomery { + use super::*; + + #[test] + fn empty() { + type F = bn256::Fr; + assert_eq!(montgomery::(&[]), (F::ONE, vec![])); + } + + #[test] + fn one() { + type F = bn256::Fr; + let points = [F::random(OsRng)]; + assert_eq!(montgomery::(&points), (points[0], vec![F::ONE])); + } + + #[test] + fn random() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let (res_mul, res_partials) = montgomery::(&points); + assert_eq!(res_mul, points.iter().fold(F::ONE, |acc, n| acc * n)); + assert!(points.iter().zip_eq(res_partials).all(|(point, partial)| point * partial == res_mul)) + } + } -// mod sum_of_fractions { -// use super::*; - -// mod invalid { -// use super::*; - -// #[test] -// #[should_panic] -// fn no_args() { -// type F = bn256::Fr; -// sum_of_fractions::(&[], 0); -// } - -// #[test] -// #[should_panic] -// fn small_k() { -// type F = bn256::Fr; -// sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 1); -// } - -// #[test] -// #[should_panic] -// fn big_k() { -// type F = bn256::Fr; -// sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 3); -// } -// } - - -// #[test] -// fn empty() { -// type F = bn256::Fr; -// let c = F::random(OsRng); - -// assert_eq!(sum_of_fractions::(&[F::ZERO, c], 0), F::ZERO); -// } - -// #[test] -// fn random_eq() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let c = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let sum = points.iter().map(|p| (p - c).invert().unwrap() * F::ONE).fold(F::ZERO, |acc, n| acc + n); -// let mut inputs = vec![sum, c]; -// inputs.extend(points.iter()); -// assert_eq!(sum_of_fractions::(&inputs, indexes.len()), F::ZERO); -// } - -// #[test] -// fn aware_constrain_random() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let c = F::random(OsRng); -// let fake_sum = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let mut inputs = vec![fake_sum, c]; -// inputs.extend(points.iter()); -// let res = sum_of_fractions::(&inputs, indexes.len()); -// let padded = points.iter().map(|p| (p - c)).collect_vec(); -// let inverces = padded.iter().map(|p| p.invert().unwrap()).collect_vec(); -// let real_sum = inverces.iter().fold(F::ZERO, |acc, n| acc + n); -// let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); -// let real_numerator = real_sum * real_denominator; -// assert_eq!(fake_sum * real_denominator - real_numerator, res); -// } -// } - -// mod sum_of_fractions_with_nums { -// use super::*; - -// mod invalid { -// use super::*; - -// #[test] -// #[should_panic] -// fn no_args() { -// type F = bn256::Fr; -// sum_of_fractions_with_nums::(&[], &[], 0); -// } - -// #[test] -// #[should_panic] -// fn small_k() { -// type F = bn256::Fr; -// sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE], 1); -// } - -// #[test] -// #[should_panic] -// fn big_k() { -// type F = bn256::Fr; -// sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE, F::ONE, F::ONE], 3); -// } -// } - -// #[test] -// fn empty() { -// type F = bn256::Fr; -// let c = F::random(OsRng); - -// assert_eq!(sum_of_fractions_with_nums::(&[F::ZERO, c], &[], 0), F::ZERO); -// } - -// #[test] -// fn random_eq() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let c = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); - -// let sum = points.iter().zip_eq(&numerators).map(|(p, n)| (p - c).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - -// let mut inputs = vec![sum, c]; -// inputs.extend(numerators.iter()); -// assert_eq!(sum_of_fractions_with_nums::(&inputs, &points, indexes.len()), F::ZERO); -// } - -// #[test] -// fn aware_constrain_random() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let c = F::random(OsRng); -// let fake_sum = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let mut inputs = vec![fake_sum, c]; -// inputs.extend(numerators.iter()); -// let res = sum_of_fractions_with_nums::(&inputs, &points, indexes.len()); -// let padded = points.iter().map(|p| (p - c)).collect_vec(); -// let real_sum = padded.iter().zip_eq(&numerators).map(|(p, n)| p.invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); -// let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); -// let real_numerator = real_sum * real_denominator; -// assert_eq!(fake_sum * real_denominator - real_numerator, res); -// } -// } - -// mod invsum_flat_constrain { -// use super::*; - -// #[test] -// fn random_eq() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; + mod sum_of_fractions { + use super::*; + + mod invalid { + use super::*; + + #[test] + #[should_panic] + fn no_args() { + type F = bn256::Fr; + sum_of_fractions::(&[], 0); + } + + #[test] + #[should_panic] + fn small_k() { + type F = bn256::Fr; + sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 1); + } + + #[test] + #[should_panic] + fn big_k() { + type F = bn256::Fr; + sum_of_fractions::(&[F::ONE, F::ONE, F::ONE, F::ONE], 3); + } + } + + + #[test] + fn empty() { + type F = bn256::Fr; + let c = F::random(OsRng); + + assert_eq!(sum_of_fractions::(&[F::ZERO, c], 0), F::ZERO); + } + + #[test] + fn random_eq() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let c = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let sum = points.iter().map(|p| (p - c).invert().unwrap() * F::ONE).fold(F::ZERO, |acc, n| acc + n); + let mut inputs = vec![sum, c]; + inputs.extend(points.iter()); + assert_eq!(sum_of_fractions::(&inputs, indexes.len()), F::ZERO); + } + + #[test] + fn aware_constrain_random() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let c = F::random(OsRng); + let fake_sum = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let mut inputs = vec![fake_sum, c]; + inputs.extend(points.iter()); + let res = sum_of_fractions::(&inputs, indexes.len()); + let padded = points.iter().map(|p| (p - c)).collect_vec(); + let inverces = padded.iter().map(|p| p.invert().unwrap()).collect_vec(); + let real_sum = inverces.iter().fold(F::ZERO, |acc, n| acc + n); + let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); + let real_numerator = real_sum * real_denominator; + assert_eq!(fake_sum * real_denominator - real_numerator, res); + } + } + + mod sum_of_fractions_with_nums { + use super::*; + + mod invalid { + use super::*; + + #[test] + #[should_panic] + fn no_args() { + type F = bn256::Fr; + sum_of_fractions_with_nums::(&[], &[], 0); + } + + #[test] + #[should_panic] + fn small_k() { + type F = bn256::Fr; + sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE], 1); + } + + #[test] + #[should_panic] + fn big_k() { + type F = bn256::Fr; + sum_of_fractions_with_nums::(&[F::ONE, F::ONE], &[F::ONE, F::ONE, F::ONE, F::ONE, F::ONE], 3); + } + } + + #[test] + fn empty() { + type F = bn256::Fr; + let c = F::random(OsRng); + + assert_eq!(sum_of_fractions_with_nums::(&[F::ZERO, c], &[], 0), F::ZERO); + } + + #[test] + fn random_eq() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let c = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + + let sum = points.iter().zip_eq(&numerators).map(|(p, n)| (p - c).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); + + let mut inputs = vec![sum, c]; + inputs.extend(numerators.iter()); + assert_eq!(sum_of_fractions_with_nums::(&inputs, &points, indexes.len()), F::ZERO); + } + + #[test] + fn aware_constrain_random() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let c = F::random(OsRng); + let fake_sum = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let mut inputs = vec![fake_sum, c]; + inputs.extend(numerators.iter()); + let res = sum_of_fractions_with_nums::(&inputs, &points, indexes.len()); + let padded = points.iter().map(|p| (p - c)).collect_vec(); + let real_sum = padded.iter().zip_eq(&numerators).map(|(p, n)| p.invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); + let real_denominator = padded.iter().fold(F::ONE, |acc, n| acc * n); + let real_numerator = real_sum * real_denominator; + assert_eq!(fake_sum * real_denominator - real_numerator, res); + } + } + + mod invsum_flat_constrain { + use super::*; + + #[test] + fn random_eq() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + + let challenge = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); + + let mut circuit = Circuit::new(TEST_LEN + 1, 1); + let challenge_value = circuit.ext_val(1)[0]; + let points_values = circuit.ext_val(TEST_LEN); + let result_value = circuit.ext_val(1)[0]; + + let challenge_variable = input(&mut circuit, challenge_value, 0); + let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); + let reslut_variable = input(&mut circuit, result_value, 0); + + invsum_flat_constrain(&mut circuit, &points_variables, reslut_variable, challenge_variable); -// let challenge = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); + + instance.set_ext(challenge_value, challenge); + points_values.into_iter().zip_eq(points).map(|(val, point)| instance.set_ext(val, point)).last(); + instance.set_ext(result_value, result); -// let mut circuit = Circuit::new(TEST_LEN + 1, 1); -// let challenge_value = circuit.ext_val(1)[0]; -// let points_values = circuit.ext_val(TEST_LEN); -// let result_value = circuit.ext_val(1)[0]; + instance.execute(0); + instance.valid_witness(); -// let challenge_variable = input(&mut circuit, challenge_value, 0); -// let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); -// let reslut_variable = input(&mut circuit, result_value, 0); + } + } -// invsum_flat_constrain(&mut circuit, &points_variables, reslut_variable, challenge_variable); -// let mut instance = circuit.finalize(); + mod fracsum_flat_constrain { + use super::*; -// instance.set_ext(challenge_value, challenge); -// points_values.into_iter().zip_eq(points).map(|(val, point)| instance.set_ext(val, point)).last(); -// instance.set_ext(result_value, result); + #[test] + fn random_eq() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + + let challenge = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); -// instance.execute(0); -// instance.valid_witness(); -// } -// } + let mut circuit = Circuit::new(TEST_LEN + 1, 1); + let challenge_value = circuit.ext_val(1)[0]; + let numerators_values = circuit.ext_val(TEST_LEN); + let result_value = circuit.ext_val(1)[0]; -// mod fracsum_flat_constrain { -// use super::*; + let challenge_variable = input(&mut circuit, challenge_value, 0); + let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); + let reslut_variable = input(&mut circuit, result_value, 0); -// #[test] -// fn random_eq() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; + fracsum_flat_constrain(&mut circuit, &numerator_variables, &points, reslut_variable, challenge_variable); -// let challenge = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - - -// let mut circuit = Circuit::new(TEST_LEN + 1, 1); -// let challenge_value = circuit.ext_val(1)[0]; -// let numerators_values = circuit.ext_val(TEST_LEN); -// let result_value = circuit.ext_val(1)[0]; - -// let challenge_variable = input(&mut circuit, challenge_value, 0); -// let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); -// let reslut_variable = input(&mut circuit, result_value, 0); - -// fracsum_flat_constrain(&mut circuit, &numerator_variables, &points, reslut_variable, challenge_variable); -// let mut instance = circuit.finalize(); - -// instance.set_ext(challenge_value, challenge); -// numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| instance.set_ext(val, point)).last(); -// instance.set_ext(result_value, result); - -// instance.execute(0); -// instance.valid_witness(); -// } -// } -// mod invsum_gadget{ -// use super::*; - -// #[test] -// fn random_eq() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let rate = 3; -// let challenge = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); + + instance.set_ext(challenge_value, challenge); + numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| instance.set_ext(val, point)).last(); + instance.set_ext(result_value, result); + + instance.execute(0); + instance.valid_witness(); + } + } + mod invsum_gadget{ + use super::*; + + #[test] + fn random_eq() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let rate = 3; + let challenge = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let result = points.iter().map(|p| (p - challenge).invert().unwrap()).fold(F::ZERO, |acc, n| acc + n); -// let mut circuit = Circuit::new(10, 1); -// let challenge_value = circuit.ext_val(1)[0]; -// let points_values = circuit.ext_val(TEST_LEN); + let mut circuit = Circuit::new(10, 1); + let challenge_value = circuit.ext_val(1)[0]; + let points_values = circuit.ext_val(TEST_LEN); -// let challenge_variable = input(&mut circuit, challenge_value, 0); -// let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); + let challenge_variable = input(&mut circuit, challenge_value, 0); + let points_variables = points_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); -// let result_variable = invsum_gadget(&mut circuit, &points_variables, challenge_variable, rate, 0); -// let mut circuit = circuit.finalize(); + let result_variable = invsum_gadget(&mut circuit, &points_variables, challenge_variable, rate, 0); + + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// circuit.set_ext(challenge_value, challenge); -// points_values.into_iter().zip_eq(points).map(|(val, point)| circuit.set_ext(val, point)).last(); + instance.set_ext(challenge_value, challenge); + points_values.into_iter().zip_eq(points).map(|(val, point)| instance.set_ext(val, point)).last(); -// circuit.execute(0); -// circuit.valid_witness(); + instance.execute(0); + instance.valid_witness(); -// assert_eq!(result, circuit.cs.getvar(result_variable)); -// } -// } + assert_eq!(result, instance.cs.getvar(result_variable)); + } + } + + mod fracsum_gadget { + use super::*; + + #[test] + fn random_eq() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + + let challenge = F::random(OsRng); + let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); + let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); + + let mut circuit = Circuit::new(TEST_LEN + 1, 1); + let challenge_value = circuit.ext_val(1)[0]; + let numerators_values = circuit.ext_val(TEST_LEN); -// mod fracsum_gadget { -// use super::*; + let challenge_variable = input(&mut circuit, challenge_value, 0); + let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); -// #[test] -// fn random_eq() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; + let result_variable = fracsum_gadget(&mut circuit, &numerator_variables, &points, challenge_variable, 3, 0); -// let challenge = F::random(OsRng); -// let points = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let numerators = indexes.clone().map(|_| F::random(OsRng)).collect_vec(); -// let result = points.iter().zip_eq(&numerators).map(|(p, n)| (p - challenge).invert().unwrap() * n).fold(F::ZERO, |acc, n| acc + n); - -// let mut circuit = Circuit::new(TEST_LEN + 1, 1); -// let challenge_value = circuit.ext_val(1)[0]; -// let numerators_values = circuit.ext_val(TEST_LEN); - -// let challenge_variable = input(&mut circuit, challenge_value, 0); -// let numerator_variables = numerators_values.clone().into_iter().map(|val| input(&mut circuit, val, 0)).collect_vec(); - -// let result_variable = fracsum_gadget(&mut circuit, &numerator_variables, &points, challenge_variable, 3, 0); -// let mut circuit = circuit.finalize(); - -// circuit.set_ext(challenge_value, challenge); -// numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| circuit.set_ext(val, point)).last(); - -// circuit.execute(0); -// circuit.valid_witness(); -// assert_eq!(result, circuit.cs.getvar(result_variable)); -// } -// } - -// mod range_lookup { -// use super::*; - -// use rand_core::RngCore; - -// #[test] -// fn random() { -// type F = bn256::Fr; -// let indexes = 0..TEST_LEN; -// let range = 16; - -// let table = (0..range).map(|_| F::random(OsRng)).collect_vec(); -// let mut circuit = Circuit::new(range + 1, TEST_LEN + 1); - -// let challenge_value = circuit.ext_val(1)[0]; -// let test_values = circuit.ext_val(TEST_LEN); -// let mut range_lookup = StaticLookup::new(challenge_value, &table); - -// let test_variables = test_values.clone().into_iter().enumerate().map(|(i, v)| input(&mut circuit, v, i)).collect_vec(); -// test_variables.into_iter().map(|variable| range_lookup.check(&mut circuit, variable)).last(); -// range_lookup.finalize(&mut circuit, 0, TEST_LEN - 1, TEST_LEN, 2); -// let mut circuit = circuit.finalize(); - -// test_values.into_iter().map(|val| circuit.set_ext(val, table[(OsRng.next_u64() % range as u64) as usize])).last(); -// for i in indexes { -// circuit.execute(i); -// } -// let challenge = F::random(OsRng); -// circuit.set_ext(challenge_value, challenge); -// circuit.execute(TEST_LEN); -// circuit.valid_witness(); -// } - -// mod invalid { -// use super::*; - -// #[test] -// #[should_panic] -// fn low_challendge_round() { -// type F = bn256::Fr; -// let range = 16; -// let rounds = 3; + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); + + instance.set_ext(challenge_value, challenge); + numerators_values.into_iter().zip_eq(numerators).map(|(val, point)| instance.set_ext(val, point)).last(); + + instance.execute(0); + instance.valid_witness(); + assert_eq!(result, instance.cs.getvar(result_variable)); + } + } + + mod range_lookup { + use super::*; + + use rand_core::RngCore; + + #[test] + fn random() { + type F = bn256::Fr; + let indexes = 0..TEST_LEN; + let range = 16; + + let table = (0..range).map(|_| F::random(OsRng)).collect_vec(); + let mut circuit = Circuit::new(range + 1, TEST_LEN + 1); + + let challenge_value = circuit.ext_val(1)[0]; + let test_values = circuit.ext_val(TEST_LEN); + let mut range_lookup = StaticLookup::new(challenge_value, &table); + + let test_variables = test_values.clone().into_iter().enumerate().map(|(i, v)| input(&mut circuit, v, i)).collect_vec(); + test_variables.into_iter().map(|variable| range_lookup.check(&mut circuit, variable)).last(); + range_lookup.finalize(&mut circuit, 0, TEST_LEN - 1, TEST_LEN, 2); + + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); + + test_values.into_iter().map(|val| instance.set_ext(val, table[(OsRng.next_u64() % range as u64) as usize])).last(); + for i in indexes { + instance.execute(i); + } + let challenge = F::random(OsRng); + instance.set_ext(challenge_value, challenge); + instance.execute(TEST_LEN); + instance.valid_witness(); + } + + mod invalid { + use super::*; + + #[test] + #[should_panic] + fn low_challendge_round() { + type F = bn256::Fr; + let range = 16; + let rounds = 3; -// let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); -// let mut circuit = Circuit::new(range + 1, rounds); - -// let challenge_value: ExternalValue = circuit.ext_val(1)[0]; -// let test_value = circuit.ext_val(1)[0]; -// let mut range_lookup = StaticLookup::new(challenge_value, &table); - -// let test_variable = input(&mut circuit, test_value, 0); -// range_lookup.check(&mut circuit, test_variable); -// range_lookup.finalize(&mut circuit, 1, 1, 1, 2); -// } - -// #[test] -// #[should_panic] -// fn high_value_round() { -// type F = bn256::Fr; -// let range = 16; -// let rounds = 3; + let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); + let mut circuit = Circuit::new(range + 1, rounds); + + let challenge_value: ExternalValue = circuit.ext_val(1)[0]; + let test_value = circuit.ext_val(1)[0]; + let mut range_lookup = StaticLookup::new(challenge_value, &table); + + let test_variable = input(&mut circuit, test_value, 0); + range_lookup.check(&mut circuit, test_variable); + range_lookup.finalize(&mut circuit, 1, 1, 1, 2); + } + + #[test] + #[should_panic] + fn high_value_round() { + type F = bn256::Fr; + let range = 16; + let rounds = 3; -// let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); -// let mut circuit = Circuit::new(range + 1, rounds); - -// let challenge_value: ExternalValue = circuit.ext_val(1)[0]; -// let test_value = circuit.ext_val(1)[0]; -// let mut range_lookup = StaticLookup::new(challenge_value, &table); - -// let test_variable = input(&mut circuit, test_value, 2); -// range_lookup.check(&mut circuit, test_variable); -// range_lookup.finalize(&mut circuit, 1, 1, 1, 2); -// } - -// #[test] -// #[should_panic] -// fn high_table_round() { -// type F = bn256::Fr; -// let range = 16; -// let rounds = 3; + let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); + let mut circuit = Circuit::new(range + 1, rounds); + + let challenge_value: ExternalValue = circuit.ext_val(1)[0]; + let test_value = circuit.ext_val(1)[0]; + let mut range_lookup = StaticLookup::new(challenge_value, &table); + + let test_variable = input(&mut circuit, test_value, 2); + range_lookup.check(&mut circuit, test_variable); + range_lookup.finalize(&mut circuit, 1, 1, 1, 2); + } + + #[test] + #[should_panic] + fn high_table_round() { + type F = bn256::Fr; + let range = 16; + let rounds = 3; -// let mut circuit = Circuit::new(range + 1, rounds); + let mut circuit = Circuit::new(range + 1, rounds); -// let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); - -// let challenge_value: ExternalValue = circuit.ext_val(1)[0]; -// let test_value = circuit.ext_val(1)[0]; -// let mut range_lookup = StaticLookup::new(challenge_value, &table); - -// let test_variable = input(&mut circuit, test_value, 2); -// range_lookup.check(&mut circuit, test_variable); -// range_lookup.finalize(&mut circuit, 1, 0, 2, 2); -// } -// } -// } -// } \ No newline at end of file + let table = (0..range).map(|x| F::from(x as u64)).collect_vec(); + + let challenge_value: ExternalValue = circuit.ext_val(1)[0]; + let test_value = circuit.ext_val(1)[0]; + let mut range_lookup = StaticLookup::new(challenge_value, &table); + + let test_variable = input(&mut circuit, test_value, 2); + range_lookup.check(&mut circuit, test_variable); + range_lookup.finalize(&mut circuit, 1, 0, 2, 2); + } + } + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index c45c7ae..9c646c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,4 +10,5 @@ pub mod gadgets; pub mod utils; pub mod folding; pub mod test; -pub mod gatelib; \ No newline at end of file +pub mod gatelib; +pub mod external_interface; \ No newline at end of file diff --git a/src/test.rs b/src/test.rs index de2cbce..833a8e5 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,435 +1,447 @@ -// #[cfg(test)] -// mod tests { -// use std::rc::Rc; - -// use crate::{ -// gate::Gatebb, -// constraint_system::{Variable, Visibility}, -// circuit::{Circuit, PolyOp, Advice}, -// gadgets::{ -// poseidon::{ -// poseidon_gadget_mixstrat, -// poseidon_gadget_internal -// }, -// bits::bit_decomposition_gadget, -// ecmul::{ -// add_proj, -// double_proj, -// EcAffinePoint, -// escalarmul_gadget_9 -// }, -// range::{ -// rangecheck, -// limb_decompose_gadget, -// lagrange_choice, -// lagrange_choice_batched, -// VarSmall, -// choice_gadget -// }, -// nonzero_check::nonzero_gadget, input::input -// }, folding::poseidon::Poseidon -// }; -// use ff::{PrimeField, Field}; -// use group::{Group, Curve}; -// use halo2::halo2curves::{bn256, grumpkin, CurveAffine, CurveExt}; -// use rand_core::OsRng; -// use crate::utils::poly_utils::{check_poly, find_degree}; -// use crate::utils::field_precomp::FieldUtils; - -// type F = bn256::Fr; -// type C = grumpkin::G1; - -// type Fq = ::ScalarExt; - -// // #[test] - -// // fn test_cross_terms() { - -// // for d in 2..10{ -// // let f = Rc::new(|v: &[F]| vec![v[0].pow([2 as u64])]); -// // let gate = Gatebb::new(2, 1, 1, f); -// // let tmp = gate.cross_terms_adjust(&vec![F::ONE], &vec![F::ONE], d); -// // println!("{:?}", tmp.iter().map(|v|v[0]).collect::>()); -// // } -// // } - -// #[test] - -// fn test_circuit_builder() { -// let mut circuit = Circuit::>::new(2, 1); -// let public_input_source = circuit.ext_val(1)[0]; - -// let sq = PolyOp::new(2, 1, 1, |x, _| vec!(x[0]*x[0])); -// let input = input(&mut circuit, public_input_source, 0); -// let sq1 = circuit.apply(0, sq.clone(), vec![input]); -// let _ = circuit.apply_pub(0, sq.clone(), sq1); - -// let mut constructed = circuit.finalize(); +#[cfg(test)] +mod tests { + use std::rc::Rc; + + use crate::{ + gate::Gatebb, + constraint_system::{Variable, Visibility}, + circuit::{Circuit, PolyOp, Advice}, + gadgets::{ + poseidon::{ + poseidon_gadget_mixstrat, + poseidon_gadget_internal + }, + bits::bit_decomposition_gadget, + ecmul::{ + add_proj, + double_proj, + EcAffinePoint, + escalarmul_gadget_9 + }, + range::{ + rangecheck, + limb_decompose_gadget, + lagrange_choice, + lagrange_choice_batched, + VarSmall, + choice_gadget + }, + nonzero_check::nonzero_gadget, input::input + }, folding::poseidon::Poseidon + }; + use ff::{PrimeField, Field}; + use group::{Group, Curve}; + use halo2::halo2curves::{bn256, grumpkin, CurveAffine, CurveExt}; + use rand_core::OsRng; + use crate::utils::poly_utils::{check_poly, find_degree}; + use crate::utils::field_precomp::FieldUtils; + + type F = bn256::Fr; + type C = grumpkin::G1; + + type Fq = ::ScalarExt; + + // #[test] + + // fn test_cross_terms() { + + // for d in 2..10{ + // let f = Rc::new(|v: &[F]| vec![v[0].pow([2 as u64])]); + // let gate = Gatebb::new(2, 1, 1, f); + // let tmp = gate.cross_terms_adjust(&vec![F::ONE], &vec![F::ONE], d); + // println!("{:?}", tmp.iter().map(|v|v[0]).collect::>()); + // } + // } + + #[test] + + fn test_circuit_builder() { + let mut circuit = Circuit::>::new(2, 1); + let public_input_source = circuit.ext_val(1)[0]; + + let sq = PolyOp::new(2, 1, 1, |x, _| vec!(x[0]*x[0])); + let input = input(&mut circuit, public_input_source, 0); + let sq1 = circuit.apply(0, sq.clone(), vec![input]); + let _ = circuit.apply_pub(0, sq.clone(), sq1); + + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// instance.set_ext(public_input_source, F::from(2)); + instance.set_ext(public_input_source, F::from(2)); -// instance.execute(0); + instance.execute(0); -// let var = Variable { visibility: Visibility::Public, round: 0, index: 2 }; -// assert_eq!(F::from(16), instance.cs.getvar(var)); -// } + let var = Variable { visibility: Visibility::Public, round: 0, index: 2 }; + assert_eq!(F::from(16), instance.cs.getvar(var)); + } + + #[test] -// #[test] - -// fn test_permutation_argument() { - -// let mut circuit = Circuit::new(2, 2); -// let pi_ext = circuit.ext_val(5); -// let challenge_ext = circuit.ext_val(1)[0]; - -// let one = circuit.one(); - -// let mut pi = vec![]; -// for k in 0..5{ -// pi.push( -// input(&mut circuit, pi_ext[k], 0) -// ); -// } - -// let challenge = input(&mut circuit, challenge_ext, 1); + fn test_permutation_argument() { + + let mut circuit = Circuit::new(2, 2); + let pi_ext = circuit.ext_val(5); + let challenge_ext = circuit.ext_val(1)[0]; + + let one = circuit.one(); + + let mut pi = vec![]; + for k in 0..5{ + pi.push( + input(&mut circuit, pi_ext[k], 0) + ); + } + + let challenge = input(&mut circuit, challenge_ext, 1); -// let division_advice = Advice::new(2, 0, 1, |ivar : &[F], _| { -// let ch = ivar[0]; -// let x = ivar[1]; -// vec![(x-ch).invert().unwrap()] -// }); + let division_advice = Advice::new(2, 0, 1, |ivar : &[F], _| { + let ch = ivar[0]; + let x = ivar[1]; + vec![(x-ch).invert().unwrap()] + }); -// let mut fractions = vec![]; -// for k in 0..5 { -// fractions.push( -// circuit.advice(1, division_advice.clone(), vec![challenge, pi[k]])[0] -// ); -// } + let mut fractions = vec![]; + for k in 0..5 { + fractions.push( + circuit.advice(1, division_advice.clone(), vec![challenge, pi[k]])[0] + ); + } -// let div_constr = Gatebb::::new( -// 2, 4, 1, -// Rc::new(|args, _|{ -// let one = args[0]; -// let ch = args[1]; -// let x = args[2]; -// let res = args[3]; -// vec![one*one - res * (x-ch)] -// }), -// vec![], -// ); + let div_constr = Gatebb::::new( + 2, 4, 1, + Rc::new(|args, _|{ + let one = args[0]; + let ch = args[1]; + let x = args[2]; + let res = args[3]; + vec![one*one - res * (x-ch)] + }), + vec![], + ); -// for k in 0..5 { -// circuit.constrain(&[one, challenge, pi[k], fractions[k]], div_constr.clone()); -// } + for k in 0..5 { + circuit.constrain(&[one, challenge, pi[k], fractions[k]], div_constr.clone()); + } -// let mut circuit = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// // construction phase ended -// circuit.set_ext(pi_ext[0], F::from(2)); -// circuit.set_ext(pi_ext[1], F::from(3)); -// circuit.set_ext(pi_ext[2], F::from(4)); -// circuit.set_ext(pi_ext[3], F::from(5)); -// circuit.set_ext(pi_ext[4], F::from(6)); + // construction phase ended + instance.set_ext(pi_ext[0], F::from(2)); + instance.set_ext(pi_ext[1], F::from(3)); + instance.set_ext(pi_ext[2], F::from(4)); + instance.set_ext(pi_ext[3], F::from(5)); + instance.set_ext(pi_ext[4], F::from(6)); -// circuit.execute(0); + instance.execute(0); -// circuit.set_ext(challenge_ext, F::random(OsRng)); + instance.set_ext(challenge_ext, F::random(OsRng)); -// circuit.execute(1); + instance.execute(1); -// circuit.valid_witness(); // test that constraints are satisfied -// } + instance.valid_witness(); // test that constraints are satisfied + } -// #[test] -// fn test_poseidon_gadget(){ -// let cfg = Poseidon::new(); -// let mut circuit = Circuit::new(25, 1); -// let pi_ext = circuit.ext_val(1)[0]; -// let pi = input(&mut circuit, pi_ext, 0); -// let ret = poseidon_gadget_internal(&mut circuit, &cfg, 1, 0, vec![pi]); + #[test] + fn test_poseidon_gadget(){ + let cfg = Poseidon::new(); + let mut circuit = Circuit::new(25, 1); + let pi_ext = circuit.ext_val(1)[0]; + let pi = input(&mut circuit, pi_ext, 0); + let ret = poseidon_gadget_internal(&mut circuit, &cfg, 1, 0, vec![pi]); -// let mut circuit = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// circuit.set_ext(pi_ext, F::ONE); + instance.set_ext(pi_ext, F::ONE); -// circuit.execute(0); -// circuit.valid_witness(); + instance.execute(0); + instance.valid_witness(); -// assert_eq!(circuit.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); -// } + assert_eq!(instance.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); + } -// #[test] -// fn test_poseidon_gadget_k_equals_two(){ -// let cfg = Poseidon::new(); -// let mut circuit = Circuit::new(25, 1); -// let pi_ext = circuit.ext_val(1)[0]; -// let pi = input(&mut circuit, pi_ext, 0); -// let ret = poseidon_gadget_internal(&mut circuit, &cfg, 2, 0, vec![pi]); + #[test] + fn test_poseidon_gadget_k_equals_two(){ + let cfg = Poseidon::new(); + let mut circuit = Circuit::new(25, 1); + let pi_ext = circuit.ext_val(1)[0]; + let pi = input(&mut circuit, pi_ext, 0); + let ret = poseidon_gadget_internal(&mut circuit, &cfg, 2, 0, vec![pi]); -// let mut circuit = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// circuit.set_ext(pi_ext, F::ONE); + instance.set_ext(pi_ext, F::ONE); -// circuit.execute(0); -// circuit.valid_witness(); + instance.execute(0); + instance.valid_witness(); -// assert_eq!(circuit.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); -// } + assert_eq!(instance.cs.getvar(ret), F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); + } -// #[test] -// fn test_poseidon_gadget_mixstrat(){ -// let cfg = Poseidon::new(); -// let mut circuit = Circuit::new(25, 1); -// let pi_ext = circuit.ext_val(1)[0]; -// let pi = input(&mut circuit, pi_ext, 0); -// let ret = poseidon_gadget_mixstrat(&mut circuit, &cfg, 0, vec![pi]); + #[test] + fn test_poseidon_gadget_mixstrat(){ + let cfg = Poseidon::new(); + let mut circuit = Circuit::new(25, 1); + let pi_ext = circuit.ext_val(1)[0]; + let pi = input(&mut circuit, pi_ext, 0); + let ret = poseidon_gadget_mixstrat(&mut circuit, &cfg, 0, vec![pi]); -// let mut circuit = circuit.finalize(); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// circuit.set_ext(pi_ext, F::ONE); + instance.set_ext(pi_ext, F::ONE); -// circuit.execute(0); -// circuit.valid_witness(); + instance.execute(0); + instance.valid_witness(); -// assert!(circuit.cs.getvar(ret) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); + assert!(instance.cs.getvar(ret) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); -// assert!(cfg.hash(vec![F::ONE]) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); + assert!(cfg.hash(vec![F::ONE]) == F::from_str_vartime("18586133768512220936620570745912940619677854269274689475585506675881198879027").unwrap()); -// println!("{:?}", circuit.cs.getvar(ret).to_repr()); -// } + println!("{:?}", instance.cs.getvar(ret).to_repr()); + } -// #[test] + #[test] -// fn test_bit_decomposition(){ -// let mut circuit = Circuit::new(2, 1); -// let pi_ext = circuit.ext_val(1)[0]; + fn test_bit_decomposition(){ + let mut circuit = Circuit::new(2, 1); + let pi_ext = circuit.ext_val(1)[0]; -// let pi = input(&mut circuit, pi_ext, 0); + let pi = input(&mut circuit, pi_ext, 0); -// let bits = bit_decomposition_gadget(&mut circuit, 0, 3, pi); + let bits = bit_decomposition_gadget(&mut circuit, 0, 3, pi); -// let mut circuit = circuit.finalize(); -// circuit.set_ext(pi_ext, F::from(6)); -// circuit.execute(0); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); + + instance.set_ext(pi_ext, F::from(6)); + instance.execute(0); -// circuit.valid_witness(); + instance.valid_witness(); -// assert!(bits.len()==3); -// assert!(circuit.cs.getvar(bits[0]) == F::ZERO); -// assert!(circuit.cs.getvar(bits[1]) == F::ONE); -// assert!(circuit.cs.getvar(bits[2]) == F::ONE); -// } + assert!(bits.len()==3); + assert!(instance.cs.getvar(bits[0]) == F::ZERO); + assert!(instance.cs.getvar(bits[1]) == F::ONE); + assert!(instance.cs.getvar(bits[2]) == F::ONE); + } -// #[test] + #[test] -// fn test_check_poly() { -// let f = Rc::new(|x: &[F], _: &[F]|{vec![x[0].pow([5])]}); -// check_poly(5, 1, 1, f, &[]).unwrap(); -// } + fn test_check_poly() { + let f = Rc::new(|x: &[F], _: &[F]|{vec![x[0].pow([5])]}); + check_poly(5, 1, 1, f, &[]).unwrap(); + } -// #[test] + #[test] -// fn test_scale(){ -// let x = F::random(OsRng); -// for y in 0..100 { -// assert!(x.scale(y) == x*F::from(y)); -// } -// } + fn test_scale(){ + let x = F::random(OsRng); + for y in 0..100 { + assert!(x.scale(y) == x*F::from(y)); + } + } -// #[test] + #[test] -// fn test_add() { -// let pt1 = C::random(OsRng).to_affine(); -// let pt2 = C::random(OsRng).to_affine(); + fn test_add() { + let pt1 = C::random(OsRng).to_affine(); + let pt2 = C::random(OsRng).to_affine(); -// let pt1_ = (pt1.x, pt1.y); -// let pt2_ = (pt2.x, pt2.y); + let pt1_ = (pt1.x, pt1.y); + let pt2_ = (pt2.x, pt2.y); + + let pt3_ = add_proj::(pt1_, pt2_); -// let pt3_ = add_proj::(pt1_, pt2_); + let r3_inv = pt3_.2.invert().unwrap(); + let pt3 = grumpkin::G1Affine::from_xy(pt3_.0*r3_inv, pt3_.1*r3_inv).unwrap(); -// let r3_inv = pt3_.2.invert().unwrap(); -// let pt3 = grumpkin::G1Affine::from_xy(pt3_.0*r3_inv, pt3_.1*r3_inv).unwrap(); - -// assert!(Into::::into(pt3) == pt1+pt2); -// } + assert!(Into::::into(pt3) == pt1+pt2); + } -// #[test] + #[test] -// fn test_double() { -// let pt = C::random(OsRng).to_affine(); -// let pt_ = (pt.x, pt.y); -// let pt2_ = double_proj::(pt_); -// let rinv = pt2_.2.invert().unwrap(); -// let pt2 = grumpkin::G1Affine::from_xy(pt2_.0*rinv, pt2_.1*rinv).unwrap(); -// assert!(Into::::into(pt2) == pt+pt); + fn test_double() { + let pt = C::random(OsRng).to_affine(); + let pt_ = (pt.x, pt.y); + let pt2_ = double_proj::(pt_); + let rinv = pt2_.2.invert().unwrap(); + let pt2 = grumpkin::G1Affine::from_xy(pt2_.0*rinv, pt2_.1*rinv).unwrap(); + assert!(Into::::into(pt2) == pt+pt); -// } + } -// #[test] + #[test] -// fn test_range_check() { -// for range in 1..10 { -// for i in 1..10 { -// let x = F::from(i); -// assert!(if i < range {rangecheck(x, range) == F::ZERO} else {rangecheck(x, range) != F::ZERO}); -// } -// } -// } + fn test_range_check() { + for range in 1..10 { + for i in 1..10 { + let x = F::from(i); + assert!(if i < range {rangecheck(x, range) == F::ZERO} else {rangecheck(x, range) != F::ZERO}); + } + } + } -// #[test] + #[test] -// fn test_limb_decompose_gadget() { + fn test_limb_decompose_gadget() { -// let mut circuit = Circuit::new(9, 1); -// let pi_ext = circuit.ext_val(1)[0]; -// let pi = input(&mut circuit, pi_ext, 0); + let mut circuit = Circuit::new(9, 1); + let pi_ext = circuit.ext_val(1)[0]; + let pi = input(&mut circuit, pi_ext, 0); -// let limbs = limb_decompose_gadget(&mut circuit, 9, 0, 2, pi); + let limbs = limb_decompose_gadget(&mut circuit, 9, 0, 2, pi); -// let mut circuit = circuit.finalize(); -// circuit.set_ext(pi_ext, F::from(25)); -// circuit.execute(0); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); + + instance.set_ext(pi_ext, F::from(25)); + instance.execute(0); -// circuit.valid_witness(); + instance.valid_witness(); -// assert!(limbs.len()==2); -// assert!(circuit.cs.getvar(limbs[0].var) == F::from(7)); -// assert!(circuit.cs.getvar(limbs[1].var) == F::from(2)); + assert!(limbs.len()==2); + assert!(instance.cs.getvar(limbs[0].var) == F::from(7)); + assert!(instance.cs.getvar(limbs[1].var) == F::from(2)); -// } + } -// #[test] + #[test] -// fn test_lagrange_choice() -> () { -// for n in 2..12 { -// for t in 0..n { -// assert!(find_degree(32, 1, 1, Rc::new(move |v: &[F], _| vec![lagrange_choice(v[0],t,n)]), &[]).unwrap() == (n-1) as usize); -// for x in 0..n { -// if x == t { -// assert!(lagrange_choice(F::from(x), t, n) == F::ONE); -// } else { -// assert!(lagrange_choice(F::from(x), t, n) == F::ZERO); -// } -// } + fn test_lagrange_choice() -> () { + for n in 2..12 { + for t in 0..n { + assert!(find_degree(32, 1, 1, Rc::new(move |v: &[F], _| vec![lagrange_choice(v[0],t,n)]), &[]).unwrap() == (n-1) as usize); + for x in 0..n { + if x == t { + assert!(lagrange_choice(F::from(x), t, n) == F::ONE); + } else { + assert!(lagrange_choice(F::from(x), t, n) == F::ZERO); + } + } -// } -// } -// } + } + } + } -// #[test] + #[test] -// fn test_lagrange_batch() -> () { -// for n in 2..12 { -// assert!(find_degree(32, 1, n, Rc::new(move |v: &[F], _| lagrange_choice_batched(v[0], n as u64)), &[]).unwrap() == (n-1)); -// for x in 0..n { -// let v = lagrange_choice_batched(F::from(x as u64), n as u64); -// for t in 0..n { -// assert!(if t==x {v[t] == F::ONE} else {v[t] == F::ZERO}) -// } -// } -// } -// } + fn test_lagrange_batch() -> () { + for n in 2..12 { + assert!(find_degree(32, 1, n, Rc::new(move |v: &[F], _| lagrange_choice_batched(v[0], n as u64)), &[]).unwrap() == (n-1)); + for x in 0..n { + let v = lagrange_choice_batched(F::from(x as u64), n as u64); + for t in 0..n { + assert!(if t==x {v[t] == F::ONE} else {v[t] == F::ZERO}) + } + } + } + } -// #[test] + #[test] -// fn test_choice_gadget() -> () { -// let mut circuit = Circuit::new(10, 1); + fn test_choice_gadget() -> () { + let mut circuit = Circuit::new(10, 1); -// let mut pi_ext = vec![]; -// let pi_id_ext = circuit.ext_val(1)[0]; -// for _ in 0..9 { -// pi_ext.push(circuit.ext_val(3)); -// } + let mut pi_ext = vec![]; + let pi_id_ext = circuit.ext_val(1)[0]; + for _ in 0..9 { + pi_ext.push(circuit.ext_val(3)); + } -// let mut pi = vec![]; -// for i in 0..9 { -// pi.push(vec![]); -// for j in 0..3 { -// pi[i].push(input(&mut circuit, pi_ext[i][j], 0)); -// } -// } -// let pi_id = input(&mut circuit, pi_id_ext, 0); + let mut pi = vec![]; + for i in 0..9 { + pi.push(vec![]); + for j in 0..3 { + pi[i].push(input(&mut circuit, pi_ext[i][j], 0)); + } + } + let pi_id = input(&mut circuit, pi_id_ext, 0); -// let pi : Vec<_> = pi.iter().map(|x|x.as_ref()).collect(); -// let chosen = choice_gadget(&mut circuit, &pi, VarSmall::new_unchecked(pi_id, 9), 0); + let pi : Vec<_> = pi.iter().map(|x|x.as_ref()).collect(); + let chosen = choice_gadget(&mut circuit, &pi, VarSmall::new_unchecked(pi_id, 9), 0); + + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// let mut circuit = circuit.finalize(); -// circuit.set_ext(pi_id_ext, F::from(5)); -// for i in 0..9 { -// for j in 0..3 { -// circuit.set_ext(pi_ext[i][j], F::random(OsRng)); -// } -// } -// circuit.execute(0); + instance.set_ext(pi_id_ext, F::from(5)); + for i in 0..9 { + for j in 0..3 { + instance.set_ext(pi_ext[i][j], F::random(OsRng)); + } + } + instance.execute(0); -// circuit.valid_witness(); + instance.valid_witness(); -// assert!(chosen.len() == 3); + assert!(chosen.len() == 3); -// for j in 0..3 { -// assert!(circuit.cs.getvar(pi[5][j]) == circuit.cs.getvar(chosen[j])) -// } -// } + for j in 0..3 { + assert!(instance.cs.getvar(pi[5][j]) == instance.cs.getvar(chosen[j])) + } + } -// #[test] -// fn test_escalarmul_gadget()->(){ -// let mut circuit = Circuit::new(10, 1); + #[test] + fn test_escalarmul_gadget()->(){ + let mut circuit = Circuit::new(10, 1); -// let pi_a_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); -// let pi_b_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band -// let pi_pt_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); -// let pi_sc_ext = circuit.ext_val(1)[0]; + let pi_a_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); + let pi_b_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band + let pi_pt_ext = (circuit.ext_val(1)[0], circuit.ext_val(1)[0]); + let pi_sc_ext = circuit.ext_val(1)[0]; -// let x = input(&mut circuit, pi_a_ext.0, 0); -// let y = input(&mut circuit, pi_a_ext.1, 0); -// let a = EcAffinePoint::::new(&mut circuit, x, y); -// let x = input(&mut circuit, pi_b_ext.0, 0); -// let y = input(&mut circuit, pi_b_ext.1, 0); -// let b = EcAffinePoint::::new(&mut circuit, x, y); -// let x = input(&mut circuit, pi_pt_ext.0, 0); -// let y = input(&mut circuit, pi_pt_ext.1, 0); -// let pt = EcAffinePoint::::new(&mut circuit, x, y); -// let sc = input(&mut circuit, pi_sc_ext, 0); + let x = input(&mut circuit, pi_a_ext.0, 0); + let y = input(&mut circuit, pi_a_ext.1, 0); + let a = EcAffinePoint::::new(&mut circuit, x, y); + let x = input(&mut circuit, pi_b_ext.0, 0); + let y = input(&mut circuit, pi_b_ext.1, 0); + let b = EcAffinePoint::::new(&mut circuit, x, y); + let x = input(&mut circuit, pi_pt_ext.0, 0); + let y = input(&mut circuit, pi_pt_ext.1, 0); + let pt = EcAffinePoint::::new(&mut circuit, x, y); + let sc = input(&mut circuit, pi_sc_ext, 0); -// let mut nonzeros = vec![]; -// let num_limbs = 81; + let mut nonzeros = vec![]; + let num_limbs = 81; -// let scmul = escalarmul_gadget_9(&mut circuit, sc, pt, num_limbs, 0, a, b, &mut nonzeros); + let scmul = escalarmul_gadget_9(&mut circuit, sc, pt, num_limbs, 0, a, b, &mut nonzeros); -// nonzero_gadget(&mut circuit, &nonzeros, 9); -// let mut instance = circuit.finalize(); + nonzero_gadget(&mut circuit, &nonzeros, 9); + let constructed = circuit.finalize(); + let mut instance = constructed.spawn(); -// let pi_a = C::random(OsRng).to_affine(); -// instance.set_ext(pi_a_ext.0, pi_a.x); -// instance.set_ext(pi_a_ext.1, pi_a.y); + let pi_a = C::random(OsRng).to_affine(); + instance.set_ext(pi_a_ext.0, pi_a.x); + instance.set_ext(pi_a_ext.1, pi_a.y); -// //1+9+81+...+9^{num_limbs - 1} = (9^{num_limbs}-1)/8 + //1+9+81+...+9^{num_limbs - 1} = (9^{num_limbs}-1)/8 -// let bscale = (Fq::from(9).pow([num_limbs as u64])-Fq::ONE)*(Fq::from(8).invert().unwrap()); -// let pi_b = -(C::from(pi_a)*bscale).to_affine(); -// instance.set_ext(pi_b_ext.0, pi_b.x); -// instance.set_ext(pi_b_ext.1, pi_b.y); + let bscale = (Fq::from(9).pow([num_limbs as u64])-Fq::ONE)*(Fq::from(8).invert().unwrap()); + let pi_b = -(C::from(pi_a)*bscale).to_affine(); + instance.set_ext(pi_b_ext.0, pi_b.x); + instance.set_ext(pi_b_ext.1, pi_b.y); -// let pi_pt = C::random(OsRng).to_affine(); -// instance.set_ext(pi_pt_ext.0, pi_pt.x); -// instance.set_ext(pi_pt_ext.1, pi_pt.y); + let pi_pt = C::random(OsRng).to_affine(); + instance.set_ext(pi_pt_ext.0, pi_pt.x); + instance.set_ext(pi_pt_ext.1, pi_pt.y); -// instance.set_ext(pi_sc_ext, F::from(23)); + instance.set_ext(pi_sc_ext, F::from(23)); -// instance.execute(0); + instance.execute(0); -// instance.valid_witness(); + instance.valid_witness(); -// let answer = grumpkin::G1Affine::from_xy(instance.cs.getvar(scmul.x), instance.cs.getvar(scmul.y)).unwrap(); + let answer = grumpkin::G1Affine::from_xy(instance.cs.getvar(scmul.x), instance.cs.getvar(scmul.y)).unwrap(); -// assert!(answer == (pi_pt*::ScalarExt::from(23)).to_affine()); + assert!(answer == (pi_pt*::ScalarExt::from(23)).to_affine()); -// println!("Total circuit size: private: {} public: {}", instance.cs.wtns[0].privs.len(), instance.cs.wtns[0].pubs.len()); -// } + println!("Total circuit size: private: {} public: {}", instance.cs.wtns[0].privs.len(), instance.cs.wtns[0].pubs.len()); + } -// } \ No newline at end of file +} \ No newline at end of file