From 2f95a9094abd8e2bb2228efe2450ba8dd0123760 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 13 Feb 2018 12:38:06 -0700 Subject: [PATCH] Refactor to handle changes to ConstraintSystem API (no more Variable associated type, one is now static method). --- src/circuit/blake2s.rs | 16 ++++---- src/circuit/boolean.rs | 75 ++++++++++++++++++------------------ src/circuit/lookup.rs | 22 +++++------ src/circuit/mod.rs | 2 +- src/circuit/mont.rs | 73 +++++++++++++++++------------------ src/circuit/num.rs | 56 +++++++++++++-------------- src/circuit/pedersen_hash.rs | 12 +++--- src/circuit/test/mod.rs | 74 ++++++++++++++++++++++------------- src/circuit/uint32.rs | 40 +++++++++++-------- 9 files changed, 199 insertions(+), 171 deletions(-) diff --git a/src/circuit/blake2s.rs b/src/circuit/blake2s.rs index 9a0d283ad..855a8c64f 100644 --- a/src/circuit/blake2s.rs +++ b/src/circuit/blake2s.rs @@ -90,13 +90,13 @@ const SIGMA: [[usize; 16]; 10] = [ fn mixing_g>( mut cs: CS, - v: &mut [UInt32], + v: &mut [UInt32], a: usize, b: usize, c: usize, d: usize, - x: &UInt32, - y: &UInt32 + x: &UInt32, + y: &UInt32 ) -> Result<(), SynthesisError> { v[a] = UInt32::addmany(cs.namespace(|| "mixing step 1"), &[v[a].clone(), v[b].clone(), x.clone()])?; @@ -162,8 +162,8 @@ fn mixing_g>( fn blake2s_compression>( mut cs: CS, - h: &mut [UInt32], - m: &[UInt32], + h: &mut [UInt32], + m: &[UInt32], t: u64, f: bool ) -> Result<(), SynthesisError> @@ -254,8 +254,8 @@ fn blake2s_compression>( pub fn blake2s>( mut cs: CS, - input: &[Boolean] -) -> Result>, SynthesisError> + input: &[Boolean] +) -> Result, SynthesisError> { assert!(input.len() % 8 == 0); @@ -269,7 +269,7 @@ pub fn blake2s>( h.push(UInt32::constant(0x1F83D9AB)); h.push(UInt32::constant(0x5BE0CD19)); - let mut blocks: Vec>> = vec![]; + let mut blocks: Vec> = vec![]; for block in input.chunks(512) { let mut this_block = Vec::with_capacity(16); diff --git a/src/circuit/boolean.rs b/src/circuit/boolean.rs index 919acbbdc..4d1c358a2 100644 --- a/src/circuit/boolean.rs +++ b/src/circuit/boolean.rs @@ -9,7 +9,8 @@ use pairing::{ use bellman::{ ConstraintSystem, SynthesisError, - LinearCombination + LinearCombination, + Variable }; use super::{ @@ -19,17 +20,17 @@ use super::{ /// Represents a variable in the constraint system which is guaranteed /// to be either zero or one. #[derive(Clone)] -pub struct AllocatedBit { - variable: Var, +pub struct AllocatedBit { + variable: Variable, value: Option } -impl AllocatedBit { +impl AllocatedBit { pub fn get_value(&self) -> Option { self.value } - pub fn get_variable(&self) -> Var { + pub fn get_variable(&self) -> Variable { self.variable } @@ -40,7 +41,7 @@ impl AllocatedBit { value: Option, ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let var = cs.alloc(|| "boolean", || { if *value.get()? { @@ -52,10 +53,9 @@ impl AllocatedBit { // Constrain: (1 - a) * a = 0 // This constrains a to be either 0 or 1. - let one = cs.one(); cs.enforce( || "boolean constraint", - |lc| lc + one - var, + |lc| lc + CS::one() - var, |lc| lc + var, |lc| lc ); @@ -74,7 +74,7 @@ impl AllocatedBit { b: &Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let mut result_value = None; @@ -126,7 +126,7 @@ impl AllocatedBit { b: &Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let mut result_value = None; @@ -164,7 +164,7 @@ impl AllocatedBit { b: &Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let mut result_value = None; @@ -182,11 +182,10 @@ impl AllocatedBit { // Constrain (a) * (1 - b) = (c), ensuring c is 1 iff // a is true and b is false, and otherwise c is 0. - let one = cs.one(); cs.enforce( || "and not constraint", |lc| lc + a.variable, - |lc| lc + one - b.variable, + |lc| lc + CS::one() - b.variable, |lc| lc + result_var ); @@ -203,7 +202,7 @@ impl AllocatedBit { b: &Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let mut result_value = None; @@ -221,11 +220,10 @@ impl AllocatedBit { // Constrain (1 - a) * (1 - b) = (c), ensuring c is 1 iff // a and b are both false, and otherwise c is 0. - let one = cs.one(); cs.enforce( || "nor constraint", - |lc| lc + one - a.variable, - |lc| lc + one - b.variable, + |lc| lc + CS::one() - a.variable, + |lc| lc + CS::one() - b.variable, |lc| lc + result_var ); @@ -239,23 +237,23 @@ impl AllocatedBit { /// This is a boolean value which may be either a constant or /// an interpretation of an `AllocatedBit`. #[derive(Clone)] -pub enum Boolean { +pub enum Boolean { /// Existential view of the boolean variable - Is(AllocatedBit), + Is(AllocatedBit), /// Negated view of the boolean variable - Not(AllocatedBit), + Not(AllocatedBit), /// Constant (not an allocated variable) Constant(bool) } -impl Boolean { +impl Boolean { pub fn enforce_equal( mut cs: CS, a: &Self, b: &Self ) -> Result<(), SynthesisError> where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let c = Self::xor(&mut cs, a, b)?; @@ -270,21 +268,25 @@ impl Boolean { } } - pub fn lc(&self, one: Var, coeff: E::Fr) -> LinearCombination + pub fn lc( + &self, + one: Variable, + coeff: E::Fr + ) -> LinearCombination { match self { &Boolean::Constant(c) => { if c { - LinearCombination::::zero() + (coeff, one) + LinearCombination::::zero() + (coeff, one) } else { - LinearCombination::::zero() + LinearCombination::::zero() } }, &Boolean::Is(ref v) => { - LinearCombination::::zero() + (coeff, v.get_variable()) + LinearCombination::::zero() + (coeff, v.get_variable()) }, &Boolean::Not(ref v) => { - LinearCombination::::zero() + (coeff, one) - (coeff, v.get_variable()) + LinearCombination::::zero() + (coeff, one) - (coeff, v.get_variable()) } } } @@ -310,7 +312,7 @@ impl Boolean { b: &'a Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { match (a, b) { (&Boolean::Constant(false), x) | (x, &Boolean::Constant(false)) => Ok(x.clone()), @@ -337,7 +339,7 @@ impl Boolean { b: &'a Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { match (a, b) { // false AND x is always false @@ -364,7 +366,7 @@ impl Boolean { bits: &[Self] ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { assert!(bits.len() > 0); let mut bits = bits.iter(); @@ -387,7 +389,7 @@ impl Boolean { bits: &[Self] ) -> Result<(), SynthesisError> where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let res = Self::kary_and(&mut cs, bits)?; @@ -409,12 +411,11 @@ impl Boolean { Ok(()) }, Boolean::Not(ref res) => { - let one = cs.one(); cs.enforce( || "enforce nand", |lc| lc, |lc| lc, - |lc| lc + one - res.get_variable() + |lc| lc + CS::one() - res.get_variable() ); Ok(()) @@ -429,7 +430,7 @@ impl Boolean { bits: &[Self] ) -> Result<(), SynthesisError> where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { assert_eq!(bits.len(), F::NUM_BITS as usize); @@ -440,7 +441,7 @@ impl Boolean { b.sub_noborrow(&1.into()); // Runs of ones in r - let mut last_run = Boolean::::constant(true); + let mut last_run = Boolean::constant(true); let mut current_run = vec![]; let mut found_one = false; @@ -495,8 +496,8 @@ impl Boolean { } } -impl From> for Boolean { - fn from(b: AllocatedBit) -> Boolean { +impl From for Boolean { + fn from(b: AllocatedBit) -> Boolean { Boolean::Is(b) } } diff --git a/src/circuit/lookup.rs b/src/circuit/lookup.rs index 77783ba3f..e433cd087 100644 --- a/src/circuit/lookup.rs +++ b/src/circuit/lookup.rs @@ -31,12 +31,12 @@ fn synth<'a, E: Engine, I>( /// Performs a 3-bit window table lookup. `bits` is in /// little-endian order. -pub fn lookup3_xy( +pub fn lookup3_xy( mut cs: CS, - bits: &[Boolean], + bits: &[Boolean], coords: &[(E::Fr, E::Fr)] -) -> Result<(AllocatedNum, AllocatedNum), SynthesisError> - where CS: ConstraintSystem +) -> Result<(AllocatedNum, AllocatedNum), SynthesisError> + where CS: ConstraintSystem { assert_eq!(bits.len(), 3); assert_eq!(coords.len(), 8); @@ -84,7 +84,7 @@ pub fn lookup3_xy( let precomp = Boolean::and(cs.namespace(|| "precomp"), &bits[1], &bits[2])?; - let one = cs.one(); + let one = CS::one(); cs.enforce( || "x-coordinate lookup", @@ -119,12 +119,12 @@ pub fn lookup3_xy( /// Performs a 3-bit window table lookup, where /// one of the bits is a sign bit. -pub fn lookup3_xy_with_conditional_negation( +pub fn lookup3_xy_with_conditional_negation( mut cs: CS, - bits: &[Boolean], + bits: &[Boolean], coords: &[(E::Fr, E::Fr)] -) -> Result<(AllocatedNum, AllocatedNum), SynthesisError> - where CS: ConstraintSystem +) -> Result<(AllocatedNum, AllocatedNum), SynthesisError> + where CS: ConstraintSystem { assert_eq!(bits.len(), 3); assert_eq!(coords.len(), 4); @@ -161,7 +161,7 @@ pub fn lookup3_xy_with_conditional_negation( } )?; - let one = cs.one(); + let one = CS::one(); // Compute the coefficients for the lookup constraints let mut x_coeffs = [E::Fr::zero(); 4]; @@ -289,7 +289,7 @@ mod test { let window_size = 4; - let mut assignment = vec![Fr::zero(); (1 << window_size)]; + let mut assignment = vec![Fr::zero(); 1 << window_size]; let constants: Vec<_> = (0..(1 << window_size)).map(|_| Fr::rand(&mut rng)).collect(); synth::(window_size, &constants, &mut assignment); diff --git a/src/circuit/mod.rs b/src/circuit/mod.rs index c36148704..45de18fd0 100644 --- a/src/circuit/mod.rs +++ b/src/circuit/mod.rs @@ -5,8 +5,8 @@ pub mod boolean; pub mod uint32; pub mod blake2s; pub mod num; -pub mod mont; pub mod lookup; +pub mod mont; pub mod pedersen_hash; use bellman::SynthesisError; diff --git a/src/circuit/mont.rs b/src/circuit/mont.rs index 85fa49531..81a2fcbee 100644 --- a/src/circuit/mont.rs +++ b/src/circuit/mont.rs @@ -26,12 +26,12 @@ use super::lookup::{ use super::boolean::Boolean; -pub struct EdwardsPoint { - pub x: AllocatedNum, - pub y: AllocatedNum +pub struct EdwardsPoint { + pub x: AllocatedNum, + pub y: AllocatedNum } -impl Clone for EdwardsPoint { +impl Clone for EdwardsPoint { fn clone(&self) -> Self { EdwardsPoint { x: self.x.clone(), @@ -43,15 +43,14 @@ impl Clone for EdwardsPoint { /// Perform a fixed-base scalar multiplication with /// `by` being in little-endian bit order. `by` must /// be a multiple of 3. -pub fn fixed_base_multiplication( +pub fn fixed_base_multiplication( mut cs: CS, base: FixedGenerators, - by: &[Boolean], + by: &[Boolean], params: &E::Params -) -> Result, SynthesisError> - where CS: ConstraintSystem, - E: JubjubEngine, - Var: Copy +) -> Result, SynthesisError> + where CS: ConstraintSystem, + E: JubjubEngine { // We're going to chunk the scalar into 3-bit windows, // so let's force the caller to supply the right number @@ -90,10 +89,10 @@ pub fn fixed_base_multiplication( Ok(result.get()?.clone()) } -impl EdwardsPoint { +impl EdwardsPoint { /// This extracts the x-coordinate, which is an injective /// encoding for elements of the prime order subgroup. - pub fn into_num(&self) -> AllocatedNum { + pub fn into_num(&self) -> AllocatedNum { self.x.clone() } @@ -102,9 +101,9 @@ impl EdwardsPoint { pub fn conditionally_select( &self, mut cs: CS, - condition: &Boolean + condition: &Boolean ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { // Compute x' = self.x if condition, and 0 otherwise let x_prime = AllocatedNum::alloc(cs.namespace(|| "x'"), || { @@ -118,7 +117,7 @@ impl EdwardsPoint { // condition * x = x' // if condition is 0, x' must be 0 // if condition is 1, x' must be x - let one = cs.one(); + let one = CS::one(); cs.enforce( || "x' computation", |lc| lc + self.x.get_variable(), @@ -158,10 +157,10 @@ impl EdwardsPoint { pub fn mul( &self, mut cs: CS, - by: &[Boolean], + by: &[Boolean], params: &E::Params ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { // Represents the current "magnitude" of the base // that we're operating over. Starts at self, @@ -209,11 +208,11 @@ impl EdwardsPoint { pub fn interpret( mut cs: CS, - x: &AllocatedNum, - y: &AllocatedNum, + x: &AllocatedNum, + y: &AllocatedNum, params: &E::Params ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { // -x^2 + y^2 = 1 + dx^2y^2 @@ -221,7 +220,7 @@ impl EdwardsPoint { let y2 = y.square(cs.namespace(|| "y^2"))?; let x2y2 = x2.mul(cs.namespace(|| "x^2 y^2"), &y2)?; - let one = cs.one(); + let one = CS::one(); cs.enforce( || "on curve check", |lc| lc - x2.get_variable() @@ -242,7 +241,7 @@ impl EdwardsPoint { cs: CS, params: &E::Params ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { self.add(cs, self, params) } @@ -254,7 +253,7 @@ impl EdwardsPoint { other: &Self, params: &E::Params ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { // Compute U = (x1 + y1) * (x2 + y2) let u = AllocatedNum::alloc(cs.namespace(|| "U"), || { @@ -320,7 +319,7 @@ impl EdwardsPoint { } })?; - let one = cs.one(); + let one = CS::one(); cs.enforce( || "x3 computation", |lc| lc + one + c.get_variable(), @@ -366,12 +365,12 @@ impl EdwardsPoint { } } -pub struct MontgomeryPoint { - x: AllocatedNum, - y: AllocatedNum +pub struct MontgomeryPoint { + x: AllocatedNum, + y: AllocatedNum } -impl MontgomeryPoint { +impl MontgomeryPoint { /// Converts an element in the prime order subgroup into /// a point in the birationally equivalent twisted /// Edwards curve. @@ -379,8 +378,8 @@ impl MontgomeryPoint { &self, mut cs: CS, params: &E::Params - ) -> Result, SynthesisError> - where CS: ConstraintSystem + ) -> Result, SynthesisError> + where CS: ConstraintSystem { // Compute u = (scale*x) / y let u = AllocatedNum::alloc(cs.namespace(|| "u"), || { @@ -425,7 +424,7 @@ impl MontgomeryPoint { } })?; - let one = cs.one(); + let one = CS::one(); cs.enforce( || "v computation", |lc| lc + self.x.get_variable() @@ -446,8 +445,8 @@ impl MontgomeryPoint { /// on the curve. Useful for constants and /// window table lookups. pub fn interpret_unchecked( - x: AllocatedNum, - y: AllocatedNum + x: AllocatedNum, + y: AllocatedNum ) -> Self { MontgomeryPoint { @@ -464,7 +463,7 @@ impl MontgomeryPoint { other: &Self, params: &E::Params ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { // Compute lambda = (y' - y) / (x' - x) let lambda = AllocatedNum::alloc(cs.namespace(|| "lambda"), || { @@ -508,7 +507,7 @@ impl MontgomeryPoint { })?; // (lambda) * (lambda) = (A + x + x' + x'') - let one = cs.one(); + let one = CS::one(); cs.enforce( || "evaluate xprime", |lc| lc + lambda.get_variable(), @@ -555,7 +554,7 @@ impl MontgomeryPoint { mut cs: CS, params: &E::Params ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { // Square x let xx = self.x.square(&mut cs)?; @@ -585,7 +584,7 @@ impl MontgomeryPoint { })?; // (2.y) * (lambda) = (3.xx + 2.A.x + 1) - let one = cs.one(); + let one = CS::one(); cs.enforce( || "evaluate lambda", |lc| lc + self.y.get_variable() diff --git a/src/circuit/num.rs b/src/circuit/num.rs index f0255aa39..aca756276 100644 --- a/src/circuit/num.rs +++ b/src/circuit/num.rs @@ -8,7 +8,8 @@ use pairing::{ use bellman::{ SynthesisError, ConstraintSystem, - LinearCombination + LinearCombination, + Variable }; use super::{ @@ -20,12 +21,12 @@ use super::boolean::{ AllocatedBit }; -pub struct AllocatedNum { +pub struct AllocatedNum { value: Option, - variable: Var + variable: Variable } -impl Clone for AllocatedNum { +impl Clone for AllocatedNum { fn clone(&self) -> Self { AllocatedNum { value: self.value, @@ -34,12 +35,12 @@ impl Clone for AllocatedNum { } } -impl AllocatedNum { +impl AllocatedNum { pub fn alloc( mut cs: CS, value: F, ) -> Result - where CS: ConstraintSystem, + where CS: ConstraintSystem, F: FnOnce() -> Result { let mut new_value = None; @@ -60,8 +61,8 @@ impl AllocatedNum { pub fn into_bits_strict( &self, mut cs: CS - ) -> Result>, SynthesisError> - where CS: ConstraintSystem + ) -> Result, SynthesisError> + where CS: ConstraintSystem { let bits = self.into_bits(&mut cs)?; Boolean::enforce_in_field::<_, _, E::Fr>(&mut cs, &bits)?; @@ -72,8 +73,8 @@ impl AllocatedNum { pub fn into_bits( &self, mut cs: CS - ) -> Result>, SynthesisError> - where CS: ConstraintSystem + ) -> Result, SynthesisError> + where CS: ConstraintSystem { let bit_values = match self.value { Some(value) => { @@ -132,16 +133,16 @@ impl AllocatedNum { pub fn from_bits_strict( mut cs: CS, - bits: &[Boolean] + bits: &[Boolean] ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { assert_eq!(bits.len(), E::Fr::NUM_BITS as usize); Boolean::enforce_in_field::<_, _, E::Fr>(&mut cs, bits)?; - let one = cs.one(); - let mut lc = LinearCombination::::zero(); + let one = CS::one(); + let mut lc = LinearCombination::::zero(); let mut coeff = E::Fr::one(); let mut value = Some(E::Fr::zero()); for bit in bits.iter().rev() { @@ -204,7 +205,7 @@ impl AllocatedNum { mut cs: CS, other: &Self ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { let mut value = None; @@ -235,7 +236,7 @@ impl AllocatedNum { &self, mut cs: CS ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { let mut value = None; @@ -266,7 +267,7 @@ impl AllocatedNum { &self, mut cs: CS ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + where CS: ConstraintSystem { let inv = cs.alloc(|| "ephemeral inverse", || { let tmp = *self.value.get()?; @@ -281,12 +282,11 @@ impl AllocatedNum { // Constrain a * inv = 1, which is only valid // iff a has a multiplicative inverse, untrue // for zero. - let one = cs.one(); cs.enforce( || "nonzero assertion constraint", |lc| lc + self.variable, |lc| lc + inv, - |lc| lc + one + |lc| lc + CS::one() ); Ok(()) @@ -299,9 +299,9 @@ impl AllocatedNum { mut cs: CS, a: &Self, b: &Self, - condition: &Boolean + condition: &Boolean ) -> Result<(Self, Self), SynthesisError> - where CS: ConstraintSystem + where CS: ConstraintSystem { let c = Self::alloc( cs.namespace(|| "conditional reversal result 1"), @@ -314,11 +314,10 @@ impl AllocatedNum { } )?; - let one = cs.one(); cs.enforce( || "first conditional reversal", |lc| lc + a.variable - b.variable, - |_| condition.lc(one, E::Fr::one()), + |_| condition.lc(CS::one(), E::Fr::one()), |lc| lc + a.variable - c.variable ); @@ -336,7 +335,7 @@ impl AllocatedNum { cs.enforce( || "second conditional reversal", |lc| lc + b.variable - a.variable, - |_| condition.lc(one, E::Fr::one()), + |_| condition.lc(CS::one(), E::Fr::one()), |lc| lc + b.variable - d.variable ); @@ -346,9 +345,9 @@ impl AllocatedNum { pub fn conditionally_negate( &self, mut cs: CS, - condition: &Boolean + condition: &Boolean ) -> Result - where CS: ConstraintSystem + where CS: ConstraintSystem { let r = Self::alloc( cs.namespace(|| "conditional negation result"), @@ -365,11 +364,10 @@ impl AllocatedNum { // x - 2cx = r // (2x) * (c) = x - r - let one = cs.one(); cs.enforce( || "conditional negation", |lc| lc + self.variable + self.variable, - |_| condition.lc(one, E::Fr::one()), + |_| condition.lc(CS::one(), E::Fr::one()), |lc| lc + self.variable - r.variable ); @@ -380,7 +378,7 @@ impl AllocatedNum { self.value } - pub fn get_variable(&self) -> Var { + pub fn get_variable(&self) -> Variable { self.variable } } diff --git a/src/circuit/pedersen_hash.rs b/src/circuit/pedersen_hash.rs index ee940a382..a405b7a45 100644 --- a/src/circuit/pedersen_hash.rs +++ b/src/circuit/pedersen_hash.rs @@ -10,12 +10,12 @@ use bellman::{ }; use super::lookup::*; -pub fn pedersen_hash( +pub fn pedersen_hash( mut cs: CS, - bits: &[Boolean], + bits: &[Boolean], params: &E::Params -) -> Result, SynthesisError> - where CS: ConstraintSystem +) -> Result, SynthesisError> + where CS: ConstraintSystem { // Unnecessary if forced personalization is introduced assert!(bits.len() > 0); @@ -116,7 +116,7 @@ mod test { let input: Vec = (0..(Fr::NUM_BITS * 2)).map(|_| rng.gen()).collect(); - let input_bools: Vec> = input.iter().enumerate().map(|(i, b)| { + let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { Boolean::from( AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap() ) @@ -143,7 +143,7 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let input_bools: Vec> = input.iter().enumerate().map(|(i, b)| { + let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { Boolean::from( AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap() ) diff --git a/src/circuit/test/mod.rs b/src/circuit/test/mod.rs index 8e12ff713..ef042fe62 100644 --- a/src/circuit/test/mod.rs +++ b/src/circuit/test/mod.rs @@ -6,17 +6,13 @@ use pairing::{ use bellman::{ LinearCombination, SynthesisError, - ConstraintSystem + ConstraintSystem, + Variable, + Index }; use std::collections::HashMap; -#[derive(Debug, Copy, Clone)] -pub enum Variable { - Input(usize), - Aux(usize) -} - #[derive(Debug)] enum NamedObject { Constraint(usize), @@ -28,7 +24,12 @@ enum NamedObject { pub struct TestConstraintSystem { named_objects: HashMap, current_namespace: Vec, - constraints: Vec<(LinearCombination, LinearCombination, LinearCombination, String)>, + constraints: Vec<( + LinearCombination, + LinearCombination, + LinearCombination, + String + )>, inputs: Vec<(E::Fr, String)>, aux: Vec<(E::Fr, String)> } @@ -42,9 +43,9 @@ fn eval_lc( let mut acc = E::Fr::zero(); for &(var, ref coeff) in terms { - let mut tmp = match var { - Variable::Input(index) => inputs[index].0, - Variable::Aux(index) => aux[index].0 + let mut tmp = match var.get_unchecked() { + Index::Input(index) => inputs[index].0, + Index::Aux(index) => aux[index].0 }; tmp.mul_assign(&coeff); @@ -57,7 +58,7 @@ fn eval_lc( impl TestConstraintSystem { pub fn new() -> TestConstraintSystem { let mut map = HashMap::new(); - map.insert("ONE".into(), NamedObject::Var(Variable::Input(0))); + map.insert("ONE".into(), NamedObject::Var(TestConstraintSystem::::one())); TestConstraintSystem { named_objects: map, @@ -97,8 +98,12 @@ impl TestConstraintSystem { pub fn set(&mut self, path: &str, to: E::Fr) { match self.named_objects.get(path) { - Some(&NamedObject::Var(Variable::Input(index))) => self.inputs[index].0 = to, - Some(&NamedObject::Var(Variable::Aux(index))) => self.aux[index].0 = to, + Some(&NamedObject::Var(ref v)) => { + match v.get_unchecked() { + Index::Input(index) => self.inputs[index].0 = to, + Index::Aux(index) => self.aux[index].0 = to + } + } Some(e) => panic!("tried to set path `{}` to value, but `{:?}` already exists there.", path, e), _ => panic!("no variable exists at path: {}", path) } @@ -107,8 +112,12 @@ impl TestConstraintSystem { pub fn get(&mut self, path: &str) -> E::Fr { match self.named_objects.get(path) { - Some(&NamedObject::Var(Variable::Input(index))) => self.inputs[index].0, - Some(&NamedObject::Var(Variable::Aux(index))) => self.aux[index].0, + Some(&NamedObject::Var(ref v)) => { + match v.get_unchecked() { + Index::Input(index) => self.inputs[index].0, + Index::Aux(index) => self.aux[index].0 + } + } Some(e) => panic!("tried to get value of path `{}`, but `{:?}` exists there (not a variable)", path, e), _ => panic!("no variable exists at path: {}", path) } @@ -145,24 +154,35 @@ fn compute_path(ns: &[String], this: String) -> String { } impl ConstraintSystem for TestConstraintSystem { - type Variable = Variable; type Root = Self; - fn one(&self) -> Self::Variable { - Variable::Input(0) - } - fn alloc( &mut self, annotation: A, f: F - ) -> Result + ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { let index = self.aux.len(); let path = compute_path(&self.current_namespace, annotation().into()); self.aux.push((f()?, path.clone())); - let var = Variable::Aux(index); + let var = Variable::new_unchecked(Index::Aux(index)); + self.set_named_obj(path, NamedObject::Var(var)); + + Ok(var) + } + + fn alloc_input( + &mut self, + annotation: A, + f: F + ) -> Result + where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + { + let index = self.inputs.len(); + let path = compute_path(&self.current_namespace, annotation().into()); + self.inputs.push((f()?, path.clone())); + let var = Variable::new_unchecked(Index::Input(index)); self.set_named_obj(path, NamedObject::Var(var)); Ok(var) @@ -176,9 +196,9 @@ impl ConstraintSystem for TestConstraintSystem { c: LC ) where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination { let path = compute_path(&self.current_namespace, annotation().into()); let index = self.constraints.len(); @@ -234,7 +254,7 @@ fn test_cs() { cs.set("a/var", Fr::from_str("4").unwrap()); - let one = cs.one(); + let one = TestConstraintSystem::::one(); cs.enforce( || "eq", |lc| lc + a, diff --git a/src/circuit/uint32.rs b/src/circuit/uint32.rs index fc24a269d..ff3943377 100644 --- a/src/circuit/uint32.rs +++ b/src/circuit/uint32.rs @@ -18,13 +18,13 @@ use super::boolean::{ /// Represents an interpretation of 32 `Boolean` objects as an /// unsigned integer. #[derive(Clone)] -pub struct UInt32 { +pub struct UInt32 { // Least significant bit first - bits: Vec>, + bits: Vec, value: Option } -impl UInt32 { +impl UInt32 { /// Construct a constant `UInt32` from a `u32` pub fn constant(value: u32) -> Self { @@ -53,7 +53,7 @@ impl UInt32 { value: Option ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let values = match value { Some(mut val) => { @@ -72,7 +72,10 @@ impl UInt32 { let bits = values.into_iter() .enumerate() .map(|(i, v)| { - Ok(Boolean::from(AllocatedBit::alloc(cs.namespace(|| format!("allocated bit {}", i)), v)?)) + Ok(Boolean::from(AllocatedBit::alloc( + cs.namespace(|| format!("allocated bit {}", i)), + v + )?)) }) .collect::, SynthesisError>>()?; @@ -83,7 +86,7 @@ impl UInt32 { } /// Turns this `UInt32` into its little-endian byte order representation. - pub fn into_bits(&self) -> Vec> { + pub fn into_bits(&self) -> Vec { self.bits.chunks(8) .flat_map(|v| v.iter().rev()) .cloned() @@ -92,7 +95,7 @@ impl UInt32 { /// Converts a little-endian byte order representation of bits into a /// `UInt32`. - pub fn from_bits(bits: &[Boolean]) -> Self + pub fn from_bits(bits: &[Boolean]) -> Self { assert_eq!(bits.len(), 32); @@ -157,7 +160,7 @@ impl UInt32 { other: &Self ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { let new_value = match (self.value, other.value) { (Some(a), Some(b)) => { @@ -170,7 +173,11 @@ impl UInt32 { .zip(other.bits.iter()) .enumerate() .map(|(i, (a, b))| { - Boolean::xor(cs.namespace(|| format!("xor of bit {}", i)), a, b) + Boolean::xor( + cs.namespace(|| format!("xor of bit {}", i)), + a, + b + ) }) .collect::>()?; @@ -186,7 +193,7 @@ impl UInt32 { operands: &[Self] ) -> Result where E: Engine, - CS: ConstraintSystem + CS: ConstraintSystem { // Make some arbitrary bounds for ourselves to avoid overflows // in the scalar field @@ -235,11 +242,11 @@ impl UInt32 { all_constants = false; // Add coeff * (1 - bit) = coeff * ONE - coeff * bit - lc = lc + (coeff, cs.one()) - (coeff, bit.get_variable()); + lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable()); }, &Boolean::Constant(bit) => { if bit { - lc = lc + (coeff, cs.one()); + lc = lc + (coeff, CS::one()); } } } @@ -266,7 +273,10 @@ impl UInt32 { let mut i = 0; while max_value != 0 { // Allocate the bit - let b = AllocatedBit::alloc(cs.namespace(|| format!("result bit {}", i)), result_value.map(|v| (v >> i) & 1 == 1))?; + let b = AllocatedBit::alloc( + cs.namespace(|| format!("result bit {}", i)), + result_value.map(|v| (v >> i) & 1 == 1) + )?; // Subtract this bit from the linear combination to ensure the sums balance out lc = lc - (coeff, b.get_variable()); @@ -311,7 +321,7 @@ mod test { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0653]); for _ in 0..1000 { - let mut v = (0..32).map(|_| Boolean::<()>::constant(rng.gen())).collect::>(); + let mut v = (0..32).map(|_| Boolean::constant(rng.gen())).collect::>(); let b = UInt32::from_bits(&v); @@ -473,7 +483,7 @@ mod test { let mut num = rng.gen(); - let a = UInt32::<()>::constant(num); + let a = UInt32::constant(num); for i in 0..32 { let b = a.rotr(i);