diff --git a/src/circuit/lookup.rs b/src/circuit/lookup.rs index d1123fb..1ffc7f7 100644 --- a/src/circuit/lookup.rs +++ b/src/circuit/lookup.rs @@ -1,6 +1,9 @@ use pairing::{Engine, Field}; use super::*; -use super::num::AllocatedNum; +use super::num::{ + AllocatedNum, + Num +}; use super::boolean::Boolean; use bellman::{ ConstraintSystem @@ -123,7 +126,7 @@ pub fn lookup3_xy_with_conditional_negation( mut cs: CS, bits: &[Boolean], coords: &[(E::Fr, E::Fr)] -) -> Result<(AllocatedNum, AllocatedNum), SynthesisError> +) -> Result<(Num, Num), SynthesisError> where CS: ConstraintSystem { assert_eq!(bits.len(), 3); @@ -145,17 +148,9 @@ pub fn lookup3_xy_with_conditional_negation( _ => None }; - // Allocate the x-coordinate resulting from the lookup - let res_x = AllocatedNum::alloc( - cs.namespace(|| "x"), - || { - Ok(coords[*i.get()?].0) - } - )?; - // Allocate the y-coordinate resulting from the lookup // and conditional negation - let res_y = AllocatedNum::alloc( + let y = AllocatedNum::alloc( cs.namespace(|| "y"), || { let mut tmp = coords[*i.get()?].1; @@ -176,15 +171,11 @@ pub fn lookup3_xy_with_conditional_negation( let precomp = Boolean::and(cs.namespace(|| "precomp"), &bits[0], &bits[1])?; - cs.enforce( - || "x-coordinate lookup", - |lc| lc + (x_coeffs[0b00], one) - + &bits[0].lc::(one, x_coeffs[0b01]) - + &bits[1].lc::(one, x_coeffs[0b10]) - + &precomp.lc::(one, x_coeffs[0b11]), - |lc| lc + one, - |lc| lc + res_x.get_variable() - ); + let x = Num::zero() + .add_bool_with_coeff(one, &Boolean::constant(true), x_coeffs[0b00]) + .add_bool_with_coeff(one, &bits[0], x_coeffs[0b01]) + .add_bool_with_coeff(one, &bits[1], x_coeffs[0b10]) + .add_bool_with_coeff(one, &precomp, x_coeffs[0b11]); let y_lc = precomp.lc::(one, y_coeffs[0b11]) + &bits[1].lc::(one, y_coeffs[0b10]) + @@ -195,10 +186,10 @@ pub fn lookup3_xy_with_conditional_negation( || "y-coordinate lookup", |lc| lc + &y_lc + &y_lc, |lc| lc + &bits[2].lc::(one, E::Fr::one()), - |lc| lc + &y_lc - res_y.get_variable() + |lc| lc + &y_lc - y.get_variable() ); - Ok((res_x, res_y)) + Ok((x, y.into())) } #[cfg(test)] diff --git a/src/circuit/mont.rs b/src/circuit/mont.rs index 798e041..b470a6c 100644 --- a/src/circuit/mont.rs +++ b/src/circuit/mont.rs @@ -12,7 +12,10 @@ use super::{ Assignment }; -use super::num::AllocatedNum; +use super::num::{ + AllocatedNum, + Num +}; use ::jubjub::{ JubjubEngine, @@ -470,8 +473,8 @@ impl EdwardsPoint { } pub struct MontgomeryPoint { - x: AllocatedNum, - y: AllocatedNum + x: Num, + y: Num } impl MontgomeryPoint { @@ -504,9 +507,9 @@ impl MontgomeryPoint { cs.enforce( || "u computation", - |lc| lc + self.y.get_variable(), + |lc| lc + &self.y.lc(E::Fr::one()), |lc| lc + u.get_variable(), - |lc| lc + (*params.scale(), self.x.get_variable()) + |lc| lc + &self.x.lc(*params.scale()) ); // Compute v = (x - 1) / (x + 1) @@ -531,10 +534,10 @@ impl MontgomeryPoint { let one = CS::one(); cs.enforce( || "v computation", - |lc| lc + self.x.get_variable() + |lc| lc + &self.x.lc(E::Fr::one()) + one, |lc| lc + v.get_variable(), - |lc| lc + self.x.get_variable() + |lc| lc + &self.x.lc(E::Fr::one()) - one, ); @@ -549,8 +552,8 @@ impl MontgomeryPoint { /// on the curve. Useful for constants and /// window table lookups. pub fn interpret_unchecked( - x: AllocatedNum, - y: AllocatedNum + x: Num, + y: Num ) -> Self { MontgomeryPoint { @@ -590,13 +593,13 @@ impl MontgomeryPoint { cs.enforce( || "evaluate lambda", - |lc| lc + other.x.get_variable() - - self.x.get_variable(), + |lc| lc + &other.x.lc(E::Fr::one()) + - &self.x.lc(E::Fr::one()), |lc| lc + lambda.get_variable(), - |lc| lc + other.y.get_variable() - - self.y.get_variable() + |lc| lc + &other.y.lc(E::Fr::one()) + - &self.y.lc(E::Fr::one()) ); // Compute x'' = lambda^2 - A - x - x' @@ -617,8 +620,8 @@ impl MontgomeryPoint { |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + (*params.montgomery_a(), one) - + self.x.get_variable() - + other.x.get_variable() + + &self.x.lc(E::Fr::one()) + + &other.x.lc(E::Fr::one()) + xprime.get_variable() ); @@ -636,18 +639,18 @@ impl MontgomeryPoint { // y' + y = lambda(x - x') cs.enforce( || "evaluate yprime", - |lc| lc + self.x.get_variable() + |lc| lc + &self.x.lc(E::Fr::one()) - xprime.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + yprime.get_variable() - + self.y.get_variable() + + &self.y.lc(E::Fr::one()) ); Ok(MontgomeryPoint { - x: xprime, - y: yprime + x: xprime.into(), + y: yprime.into() }) } } @@ -697,7 +700,7 @@ mod test { Ok(y) }).unwrap(); - let p = MontgomeryPoint::interpret_unchecked(numx, numy); + let p = MontgomeryPoint::interpret_unchecked(numx.into(), numy.into()); let q = p.into_edwards(&mut cs, params).unwrap(); @@ -1068,13 +1071,13 @@ mod test { }).unwrap(); let p1 = MontgomeryPoint { - x: num_x0, - y: num_y0 + x: num_x0.into(), + y: num_y0.into() }; let p2 = MontgomeryPoint { - x: num_x1, - y: num_y1 + x: num_x1.into(), + y: num_y1.into() }; let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap(); diff --git a/src/circuit/num.rs b/src/circuit/num.rs index 310bd95..fe20050 100644 --- a/src/circuit/num.rs +++ b/src/circuit/num.rs @@ -321,6 +321,61 @@ impl AllocatedNum { } } +pub struct Num { + value: Option, + lc: LinearCombination +} + +impl From> for Num { + fn from(num: AllocatedNum) -> Num { + Num { + value: num.value, + lc: LinearCombination::::zero() + num.variable + } + } +} + +impl Num { + pub fn zero() -> Self { + Num { + value: Some(E::Fr::zero()), + lc: LinearCombination::zero() + } + } + + pub fn get_value(&self) -> Option { + self.value + } + + pub fn lc(&self, coeff: E::Fr) -> LinearCombination { + LinearCombination::zero() + (coeff, &self.lc) + } + + pub fn add_bool_with_coeff( + self, + one: Variable, + bit: &Boolean, + coeff: E::Fr + ) -> Self + { + let newval = match (self.value, bit.get_value()) { + (Some(mut curval), Some(mut bval)) => { + if bval { + curval.add_assign(&coeff); + } + + Some(curval) + }, + _ => None + }; + + Num { + value: newval, + lc: self.lc + &bit.lc(one, coeff) + } + } +} + #[cfg(test)] mod test { use rand::{SeedableRng, Rand, Rng, XorShiftRng}; diff --git a/src/circuit/pedersen_hash.rs b/src/circuit/pedersen_hash.rs index 19e56b8..258ed94 100644 --- a/src/circuit/pedersen_hash.rs +++ b/src/circuit/pedersen_hash.rs @@ -155,7 +155,7 @@ mod test { ).unwrap(); assert!(cs.is_satisfied()); - assert_eq!(cs.num_constraints(), 1549); + assert_eq!(cs.num_constraints(), 1377); } #[test]