diff --git a/zcash_proofs/examples/bench.rs b/zcash_proofs/examples/bench.rs index a187ec6..a5c8a13 100644 --- a/zcash_proofs/examples/bench.rs +++ b/zcash_proofs/examples/bench.rs @@ -1,30 +1,20 @@ -extern crate ff; extern crate bellman; +extern crate ff; extern crate pairing; extern crate rand_core; extern crate rand_xorshift; extern crate zcash_primitives; extern crate zcash_proofs; -use ff::Field; -use std::time::{Duration, Instant}; -use zcash_primitives::jubjub::{ - JubjubBls12, - edwards, - fs, -}; -use zcash_proofs::circuit::sapling::{ - Spend -}; -use zcash_primitives::primitives::{ - Diversifier, - ProofGenerationKey, - ValueCommitment -}; use bellman::groth16::*; +use ff::Field; +use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; -use pairing::bls12_381::{Bls12, Fr}; +use std::time::{Duration, Instant}; +use zcash_primitives::jubjub::{edwards, fs, JubjubBls12}; +use zcash_primitives::primitives::{Diversifier, ProofGenerationKey, ValueCommitment}; +use zcash_proofs::circuit::sapling::Spend; const TREE_DEPTH: usize = 32; @@ -45,10 +35,11 @@ fn main() { commitment_randomness: None, ar: None, auth_path: vec![None; TREE_DEPTH], - anchor: None + anchor: None, }, - rng - ).unwrap(); + rng, + ) + .unwrap(); const SAMPLES: u32 = 50; @@ -56,7 +47,7 @@ fn main() { for _ in 0..SAMPLES { let value_commitment = ValueCommitment { value: 1, - randomness: fs::Fs::random(rng) + randomness: fs::Fs::random(rng), }; let nsk = fs::Fs::random(rng); @@ -64,7 +55,7 @@ fn main() { let proof_generation_key = ProofGenerationKey { ak: ak.clone(), - nsk: nsk.clone() + nsk: nsk.clone(), }; let viewing_key = proof_generation_key.into_viewing_key(jubjub_params); @@ -78,11 +69,7 @@ fn main() { Diversifier(d) }; - if let Some(p) = viewing_key.into_payment_address( - diversifier, - jubjub_params - ) - { + if let Some(p) = viewing_key.into_payment_address(diversifier, jubjub_params) { payment_address = p; break; } @@ -94,21 +81,25 @@ fn main() { let anchor = Fr::random(rng); let start = Instant::now(); - let _ = create_random_proof(Spend { - params: jubjub_params, - value_commitment: Some(value_commitment), - proof_generation_key: Some(proof_generation_key), - payment_address: Some(payment_address), - commitment_randomness: Some(commitment_randomness), - ar: Some(ar), - auth_path: auth_path, - anchor: Some(anchor) - }, &groth_params, rng).unwrap(); + let _ = create_random_proof( + Spend { + params: jubjub_params, + value_commitment: Some(value_commitment), + proof_generation_key: Some(proof_generation_key), + payment_address: Some(payment_address), + commitment_randomness: Some(commitment_randomness), + ar: Some(ar), + auth_path: auth_path, + anchor: Some(anchor), + }, + &groth_params, + rng, + ) + .unwrap(); total_time += start.elapsed(); } let avg = total_time / SAMPLES; - let avg = avg.subsec_nanos() as f64 / 1_000_000_000f64 - + (avg.as_secs() as f64); + let avg = avg.subsec_nanos() as f64 / 1_000_000_000f64 + (avg.as_secs() as f64); println!("Average proving time (in seconds): {}", avg); } diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index 593c57d..4c07829 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -1,37 +1,22 @@ use ff::Field; use pairing::Engine; -use bellman::{ - SynthesisError, - ConstraintSystem -}; +use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::{ - Assignment -}; +use bellman::gadgets::Assignment; -use bellman::gadgets::num::{ - AllocatedNum, - Num -}; +use bellman::gadgets::num::{AllocatedNum, Num}; -use zcash_primitives::jubjub::{ - edwards, - JubjubEngine, - JubjubParams, - FixedGenerators -}; +use zcash_primitives::jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams}; -use bellman::gadgets::lookup::{ - lookup3_xy -}; +use bellman::gadgets::lookup::lookup3_xy; use bellman::gadgets::boolean::Boolean; #[derive(Clone)] pub struct EdwardsPoint { x: AllocatedNum, - y: AllocatedNum + y: AllocatedNum, } /// Perform a fixed-base scalar multiplication with @@ -40,32 +25,40 @@ pub fn fixed_base_multiplication( mut cs: CS, base: FixedGenerators, by: &[Boolean], - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where CS: ConstraintSystem, - E: JubjubEngine +where + CS: ConstraintSystem, + E: JubjubEngine, { // Represents the result of the multiplication let mut result = None; - for (i, (chunk, window)) in by.chunks(3) - .zip(params.circuit_generators(base).iter()) - .enumerate() + for (i, (chunk, window)) in by + .chunks(3) + .zip(params.circuit_generators(base).iter()) + .enumerate() { - let chunk_a = chunk.get(0).map(|e| e.clone()).unwrap_or(Boolean::constant(false)); - let chunk_b = chunk.get(1).map(|e| e.clone()).unwrap_or(Boolean::constant(false)); - let chunk_c = chunk.get(2).map(|e| e.clone()).unwrap_or(Boolean::constant(false)); + let chunk_a = chunk + .get(0) + .map(|e| e.clone()) + .unwrap_or(Boolean::constant(false)); + let chunk_b = chunk + .get(1) + .map(|e| e.clone()) + .unwrap_or(Boolean::constant(false)); + let chunk_c = chunk + .get(2) + .map(|e| e.clone()) + .unwrap_or(Boolean::constant(false)); let (x, y) = lookup3_xy( cs.namespace(|| format!("window table lookup {}", i)), &[chunk_a, chunk_b, chunk_c], - window + window, )?; - let p = EdwardsPoint { - x: x, - y: y - }; + let p = EdwardsPoint { x: x, y: y }; if result.is_none() { result = Some(p); @@ -73,7 +66,7 @@ pub fn fixed_base_multiplication( result = Some(result.unwrap().add( cs.namespace(|| format!("addition {}", i)), &p, - params + params, )?); } } @@ -93,22 +86,14 @@ impl EdwardsPoint { pub fn assert_not_small_order( &self, mut cs: CS, - params: &E::Params + params: &E::Params, ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + where + CS: ConstraintSystem, { - let tmp = self.double( - cs.namespace(|| "first doubling"), - params - )?; - let tmp = tmp.double( - cs.namespace(|| "second doubling"), - params - )?; - let tmp = tmp.double( - cs.namespace(|| "third doubling"), - params - )?; + let tmp = self.double(cs.namespace(|| "first doubling"), params)?; + let tmp = tmp.double(cs.namespace(|| "second doubling"), params)?; + let tmp = tmp.double(cs.namespace(|| "third doubling"), params)?; // (0, -1) is a small order point, but won't ever appear here // because cofactor is 2^3, and we performed three doublings. @@ -119,11 +104,9 @@ impl EdwardsPoint { Ok(()) } - pub fn inputize( - &self, - mut cs: CS - ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + pub fn inputize(&self, mut cs: CS) -> Result<(), SynthesisError> + where + CS: ConstraintSystem, { self.x.inputize(cs.namespace(|| "x"))?; self.y.inputize(cs.namespace(|| "y"))?; @@ -132,21 +115,15 @@ impl EdwardsPoint { } /// This converts the point into a representation. - pub fn repr( - &self, - mut cs: CS - ) -> Result, SynthesisError> - where CS: ConstraintSystem + pub fn repr(&self, mut cs: CS) -> Result, SynthesisError> + where + CS: ConstraintSystem, { let mut tmp = vec![]; - let x = self.x.into_bits_le_strict( - cs.namespace(|| "unpack x") - )?; + let x = self.x.into_bits_le_strict(cs.namespace(|| "unpack x"))?; - let y = self.y.into_bits_le_strict( - cs.namespace(|| "unpack y") - )?; + let y = self.y.into_bits_le_strict(cs.namespace(|| "unpack y"))?; tmp.extend(y); tmp.push(x[0].clone()); @@ -159,34 +136,20 @@ impl EdwardsPoint { pub fn witness( mut cs: CS, p: Option>, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { let p = p.map(|p| p.into_xy()); // Allocate x - let x = AllocatedNum::alloc( - cs.namespace(|| "x"), - || { - Ok(p.get()?.0) - } - )?; + let x = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(p.get()?.0))?; // Allocate y - let y = AllocatedNum::alloc( - cs.namespace(|| "y"), - || { - Ok(p.get()?.1) - } - )?; + let y = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(p.get()?.1))?; - Self::interpret( - cs.namespace(|| "point interpretation"), - &x, - &y, - params - ) + Self::interpret(cs.namespace(|| "point interpretation"), &x, &y, params) } /// Returns `self` if condition is true, and the neutral @@ -194,9 +157,10 @@ 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'"), || { @@ -215,7 +179,7 @@ impl EdwardsPoint { || "x' computation", |lc| lc + self.x.get_variable(), |_| condition.lc(one, E::Fr::one()), - |lc| lc + x_prime.get_variable() + |lc| lc + x_prime.get_variable(), ); // Compute y' = self.y if condition, and 1 otherwise @@ -234,13 +198,12 @@ impl EdwardsPoint { || "y' computation", |lc| lc + self.y.get_variable(), |_| condition.lc(one, E::Fr::one()), - |lc| lc + y_prime.get_variable() - - &condition.not().lc(one, E::Fr::one()) + |lc| lc + y_prime.get_variable() - &condition.not().lc(one, E::Fr::one()), ); Ok(EdwardsPoint { x: x_prime, - y: y_prime + y: y_prime, }) } @@ -251,9 +214,10 @@ impl EdwardsPoint { &self, mut cs: CS, by: &[Boolean], - params: &E::Params + 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, @@ -269,8 +233,9 @@ impl EdwardsPoint { } else { // Double the previous value curbase = Some( - curbase.unwrap() - .double(cs.namespace(|| format!("doubling {}", i)), params)? + curbase + .unwrap() + .double(cs.namespace(|| format!("doubling {}", i)), params)?, ); } @@ -278,12 +243,10 @@ impl EdwardsPoint { // is true, this will return `curbase`. Otherwise it will // return the neutral element, which will have no effect on // the result. - let thisbase = curbase.as_ref() - .unwrap() - .conditionally_select( - cs.namespace(|| format!("selection {}", i)), - bit - )?; + let thisbase = curbase + .as_ref() + .unwrap() + .conditionally_select(cs.namespace(|| format!("selection {}", i)), bit)?; if result.is_none() { result = Some(thisbase); @@ -291,7 +254,7 @@ impl EdwardsPoint { result = Some(result.unwrap().add( cs.namespace(|| format!("addition {}", i)), &thisbase, - params + params, )?); } } @@ -303,9 +266,10 @@ impl EdwardsPoint { mut cs: CS, x: &AllocatedNum, y: &AllocatedNum, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // -x^2 + y^2 = 1 + dx^2y^2 @@ -316,25 +280,20 @@ impl EdwardsPoint { let one = CS::one(); cs.enforce( || "on curve check", - |lc| lc - x2.get_variable() - + y2.get_variable(), + |lc| lc - x2.get_variable() + y2.get_variable(), |lc| lc + one, - |lc| lc + one - + (*params.edwards_d(), x2y2.get_variable()) + |lc| lc + one + (*params.edwards_d(), x2y2.get_variable()), ); Ok(EdwardsPoint { x: x.clone(), - y: y.clone() + y: y.clone(), }) } - pub fn double( - &self, - mut cs: CS, - params: &E::Params - ) -> Result - where CS: ConstraintSystem + pub fn double(&self, mut cs: CS, params: &E::Params) -> Result + where + CS: ConstraintSystem, { // Compute T = (x1 + y1) * (x1 + y1) let t = AllocatedNum::alloc(cs.namespace(|| "T"), || { @@ -351,11 +310,9 @@ impl EdwardsPoint { cs.enforce( || "T computation", - |lc| lc + self.x.get_variable() - + self.y.get_variable(), - |lc| lc + self.x.get_variable() - + self.y.get_variable(), - |lc| lc + t.get_variable() + |lc| lc + self.x.get_variable() + self.y.get_variable(), + |lc| lc + self.x.get_variable() + self.y.get_variable(), + |lc| lc + t.get_variable(), ); // Compute A = x1 * y1 @@ -374,7 +331,7 @@ impl EdwardsPoint { || "C computation", |lc| lc + (*params.edwards_d(), a.get_variable()), |lc| lc + a.get_variable(), - |lc| lc + c.get_variable() + |lc| lc + c.get_variable(), ); // Compute x3 = (2.A) / (1 + C) @@ -390,10 +347,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -402,8 +357,7 @@ impl EdwardsPoint { || "x3 computation", |lc| lc + one + c.get_variable(), |lc| lc + x3.get_variable(), - |lc| lc + a.get_variable() - + a.get_variable() + |lc| lc + a.get_variable() + a.get_variable(), ); // Compute y3 = (U - 2.A) / (1 - C) @@ -421,10 +375,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -432,15 +384,10 @@ impl EdwardsPoint { || "y3 computation", |lc| lc + one - c.get_variable(), |lc| lc + y3.get_variable(), - |lc| lc + t.get_variable() - - a.get_variable() - - a.get_variable() + |lc| lc + t.get_variable() - a.get_variable() - a.get_variable(), ); - Ok(EdwardsPoint { - x: x3, - y: y3 - }) + Ok(EdwardsPoint { x: x3, y: y3 }) } /// Perform addition between any two points @@ -448,9 +395,10 @@ impl EdwardsPoint { &self, mut cs: CS, other: &Self, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute U = (x1 + y1) * (x2 + y2) let u = AllocatedNum::alloc(cs.namespace(|| "U"), || { @@ -467,11 +415,9 @@ impl EdwardsPoint { cs.enforce( || "U computation", - |lc| lc + self.x.get_variable() - + self.y.get_variable(), - |lc| lc + other.x.get_variable() - + other.y.get_variable(), - |lc| lc + u.get_variable() + |lc| lc + self.x.get_variable() + self.y.get_variable(), + |lc| lc + other.x.get_variable() + other.y.get_variable(), + |lc| lc + u.get_variable(), ); // Compute A = y2 * x1 @@ -493,7 +439,7 @@ impl EdwardsPoint { || "C computation", |lc| lc + (*params.edwards_d(), a.get_variable()), |lc| lc + b.get_variable(), - |lc| lc + c.get_variable() + |lc| lc + c.get_variable(), ); // Compute x3 = (A + B) / (1 + C) @@ -509,10 +455,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -521,8 +465,7 @@ impl EdwardsPoint { || "x3 computation", |lc| lc + one + c.get_variable(), |lc| lc + x3.get_variable(), - |lc| lc + a.get_variable() - + b.get_variable() + |lc| lc + a.get_variable() + b.get_variable(), ); // Compute y3 = (U - A - B) / (1 - C) @@ -539,10 +482,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -550,21 +491,16 @@ impl EdwardsPoint { || "y3 computation", |lc| lc + one - c.get_variable(), |lc| lc + y3.get_variable(), - |lc| lc + u.get_variable() - - a.get_variable() - - b.get_variable() + |lc| lc + u.get_variable() - a.get_variable() - b.get_variable(), ); - Ok(EdwardsPoint { - x: x3, - y: y3 - }) + Ok(EdwardsPoint { x: x3, y: y3 }) } } pub struct MontgomeryPoint { x: Num, - y: Num + y: Num, } impl MontgomeryPoint { @@ -574,9 +510,10 @@ impl MontgomeryPoint { pub fn into_edwards( &self, mut cs: CS, - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute u = (scale*x) / y let u = AllocatedNum::alloc(cs.namespace(|| "u"), || { @@ -588,10 +525,8 @@ impl MontgomeryPoint { t0.mul_assign(&invy); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -599,7 +534,7 @@ impl MontgomeryPoint { || "u computation", |lc| lc + &self.y.lc(E::Fr::one()), |lc| lc + u.get_variable(), - |lc| lc + &self.x.lc(*params.scale()) + |lc| lc + &self.x.lc(*params.scale()), ); // Compute v = (x - 1) / (x + 1) @@ -614,42 +549,28 @@ impl MontgomeryPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; let one = CS::one(); cs.enforce( || "v computation", - |lc| lc + &self.x.lc(E::Fr::one()) - + one, + |lc| lc + &self.x.lc(E::Fr::one()) + one, |lc| lc + v.get_variable(), - |lc| lc + &self.x.lc(E::Fr::one()) - - one, + |lc| lc + &self.x.lc(E::Fr::one()) - one, ); - Ok(EdwardsPoint { - x: u, - y: v - }) + Ok(EdwardsPoint { x: u, y: v }) } /// Interprets an (x, y) pair as a point /// in Montgomery, does not check that it's /// on the curve. Useful for constants and /// window table lookups. - pub fn interpret_unchecked( - x: Num, - y: Num - ) -> Self - { - MontgomeryPoint { - x: x, - y: y - } + pub fn interpret_unchecked(x: Num, y: Num) -> Self { + MontgomeryPoint { x: x, y: y } } /// Performs an affine point addition, not defined for @@ -658,9 +579,10 @@ impl MontgomeryPoint { &self, mut cs: CS, other: &Self, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute lambda = (y' - y) / (x' - x) let lambda = AllocatedNum::alloc(cs.namespace(|| "lambda"), || { @@ -674,22 +596,16 @@ impl MontgomeryPoint { Some(d) => { n.mul_assign(&d); Ok(n) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; cs.enforce( || "evaluate lambda", - |lc| lc + &other.x.lc(E::Fr::one()) - - &self.x.lc(E::Fr::one()), - + |lc| lc + &other.x.lc(E::Fr::one()) - &self.x.lc(E::Fr::one()), |lc| lc + lambda.get_variable(), - - |lc| lc + &other.y.lc(E::Fr::one()) - - &self.y.lc(E::Fr::one()) + |lc| lc + &other.y.lc(E::Fr::one()) - &self.y.lc(E::Fr::one()), ); // Compute x'' = lambda^2 - A - x - x' @@ -709,10 +625,12 @@ impl MontgomeryPoint { || "evaluate xprime", |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), - |lc| lc + (*params.montgomery_a(), one) + |lc| { + lc + (*params.montgomery_a(), one) + &self.x.lc(E::Fr::one()) + &other.x.lc(E::Fr::one()) + xprime.get_variable() + }, ); // Compute y' = -(y + lambda(x' - x)) @@ -729,57 +647,41 @@ impl MontgomeryPoint { // y' + y = lambda(x - x') cs.enforce( || "evaluate yprime", - |lc| lc + &self.x.lc(E::Fr::one()) - - xprime.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.lc(E::Fr::one()) + |lc| lc + yprime.get_variable() + &self.y.lc(E::Fr::one()), ); Ok(MontgomeryPoint { x: xprime.into(), - y: yprime.into() + y: yprime.into(), }) } } #[cfg(test)] mod test { - use bellman::{ConstraintSystem}; + use bellman::ConstraintSystem; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use bellman::gadgets::test::*; - use zcash_primitives::jubjub::{ - montgomery, - edwards, - JubjubBls12, - JubjubParams, - FixedGenerators - }; use zcash_primitives::jubjub::fs::Fs; + use zcash_primitives::jubjub::{ + edwards, montgomery, FixedGenerators, JubjubBls12, JubjubParams, + }; - use super::{ - MontgomeryPoint, - EdwardsPoint, - AllocatedNum, - fixed_base_multiplication - }; - use bellman::gadgets::boolean::{ - Boolean, - AllocatedBit - }; + use super::{fixed_base_multiplication, AllocatedNum, EdwardsPoint, MontgomeryPoint}; + use bellman::gadgets::boolean::{AllocatedBit, Boolean}; #[test] fn test_into_edwards() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -789,12 +691,8 @@ mod test { let (u, v) = edwards::Point::from_montgomery(&p, params).into_xy(); let (x, y) = p.into_xy().unwrap(); - let numx = AllocatedNum::alloc(cs.namespace(|| "mont x"), || { - Ok(x) - }).unwrap(); - let numy = AllocatedNum::alloc(cs.namespace(|| "mont y"), || { - Ok(y) - }).unwrap(); + let numx = AllocatedNum::alloc(cs.namespace(|| "mont x"), || Ok(x)).unwrap(); + let numy = AllocatedNum::alloc(cs.namespace(|| "mont y"), || Ok(y)).unwrap(); let p = MontgomeryPoint::interpret_unchecked(numx.into(), numy.into()); @@ -820,19 +718,15 @@ mod test { fn test_interpret() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { let p = edwards::Point::::rand(rng, ¶ms); let mut cs = TestConstraintSystem::::new(); - let q = EdwardsPoint::witness( - &mut cs, - Some(p.clone()), - ¶ms - ).unwrap(); + let q = EdwardsPoint::witness(&mut cs, Some(p.clone()), ¶ms).unwrap(); let p = p.into_xy(); @@ -846,12 +740,8 @@ mod test { let (x, y) = p.into_xy(); let mut cs = TestConstraintSystem::::new(); - let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || { - Ok(x) - }).unwrap(); - let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || { - Ok(y) - }).unwrap(); + let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(x)).unwrap(); + let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(y)).unwrap(); let p = EdwardsPoint::interpret(&mut cs, &numx, &numy, ¶ms).unwrap(); @@ -866,12 +756,8 @@ mod test { let y = Fr::random(rng); let mut cs = TestConstraintSystem::::new(); - let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || { - Ok(x) - }).unwrap(); - let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || { - Ok(y) - }).unwrap(); + let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(x)).unwrap(); + let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(y)).unwrap(); EdwardsPoint::interpret(&mut cs, &numx, &numy, ¶ms).unwrap(); @@ -880,11 +766,11 @@ mod test { } #[test] - fn test_edwards_fixed_base_multiplication() { + fn test_edwards_fixed_base_multiplication() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -899,18 +785,23 @@ mod test { s_bits.reverse(); s_bits.truncate(Fs::NUM_BITS as usize); - let s_bits = s_bits.into_iter() - .enumerate() - .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)).unwrap()) - .map(|v| Boolean::from(v)) - .collect::>(); + let s_bits = s_bits + .into_iter() + .enumerate() + .map(|(i, b)| { + AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)) + .unwrap() + }) + .map(|v| Boolean::from(v)) + .collect::>(); let q = fixed_base_multiplication( cs.namespace(|| "multiplication"), FixedGenerators::NoteCommitmentRandomness, &s_bits, - params - ).unwrap(); + params, + ) + .unwrap(); assert_eq!(q.x.get_value().unwrap(), x1); assert_eq!(q.y.get_value().unwrap(), y1); @@ -921,8 +812,8 @@ mod test { fn test_edwards_multiplication() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -935,45 +826,37 @@ mod test { let (x0, y0) = p.into_xy(); let (x1, y1) = q.into_xy(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); let p = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let mut s_bits = BitIterator::new(s.into_repr()).collect::>(); s_bits.reverse(); s_bits.truncate(Fs::NUM_BITS as usize); - let s_bits = s_bits.into_iter() - .enumerate() - .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)).unwrap()) - .map(|v| Boolean::from(v)) - .collect::>(); + let s_bits = s_bits + .into_iter() + .enumerate() + .map(|(i, b)| { + AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)) + .unwrap() + }) + .map(|v| Boolean::from(v)) + .collect::>(); - let q = p.mul( - cs.namespace(|| "scalar mul"), - &s_bits, - params - ).unwrap(); + let q = p + .mul(cs.namespace(|| "scalar mul"), &s_bits, params) + .unwrap(); assert!(cs.is_satisfied()); - assert_eq!( - q.x.get_value().unwrap(), - x1 - ); + assert_eq!(q.x.get_value().unwrap(), x1); - assert_eq!( - q.y.get_value().unwrap(), - y1 - ); + assert_eq!(q.y.get_value().unwrap(), y1); } } @@ -981,8 +864,8 @@ mod test { fn test_conditionally_select() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -992,26 +875,22 @@ mod test { let (x0, y0) = p.into_xy(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); let p = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let mut should_we_select = rng.next_u32() % 2 != 0; // Conditionally allocate let mut b = if rng.next_u32() % 2 != 0 { - Boolean::from(AllocatedBit::alloc( - cs.namespace(|| "condition"), - Some(should_we_select) - ).unwrap()) + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| "condition"), Some(should_we_select)) + .unwrap(), + ) } else { Boolean::constant(should_we_select) }; @@ -1022,7 +901,9 @@ mod test { should_we_select = !should_we_select; } - let q = p.conditionally_select(cs.namespace(|| "select"), &b).unwrap(); + let q = p + .conditionally_select(cs.namespace(|| "select"), &b) + .unwrap(); assert!(cs.is_satisfied()); @@ -1050,8 +931,8 @@ mod test { fn test_edwards_addition() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -1066,28 +947,20 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); - let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || { - Ok(x1) - }).unwrap(); - let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || { - Ok(y1) - }).unwrap(); + let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || Ok(x1)).unwrap(); + let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || Ok(y1)).unwrap(); let p1 = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let p2 = EdwardsPoint { x: num_x1, - y: num_y1 + y: num_y1, }; let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap(); @@ -1121,8 +994,8 @@ mod test { fn test_edwards_doubling() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -1134,16 +1007,12 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); let p1 = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let p2 = p1.double(cs.namespace(|| "doubling"), params).unwrap(); @@ -1159,8 +1028,8 @@ mod test { fn test_montgomery_addition() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -1190,28 +1059,20 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); - let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || { - Ok(x1) - }).unwrap(); - let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || { - Ok(y1) - }).unwrap(); + let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || Ok(x1)).unwrap(); + let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || Ok(y1)).unwrap(); let p1 = MontgomeryPoint { x: num_x0.into(), - y: num_y0.into() + y: num_y0.into(), }; let p2 = MontgomeryPoint { x: num_x1.into(), - y: num_y1.into() + y: num_y1.into(), }; let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap(); diff --git a/zcash_proofs/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs index 0b67597..21c0bf5 100644 --- a/zcash_proofs/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -1,17 +1,13 @@ -use super::ecc::{ - MontgomeryPoint, - EdwardsPoint -}; +use super::ecc::{EdwardsPoint, MontgomeryPoint}; use bellman::gadgets::boolean::Boolean; -use zcash_primitives::jubjub::*; -use bellman::{ - ConstraintSystem, SynthesisError -}; use bellman::gadgets::lookup::*; +use bellman::{ConstraintSystem, SynthesisError}; +use zcash_primitives::jubjub::*; pub use zcash_primitives::pedersen_hash::Personalization; fn get_constant_bools(person: &Personalization) -> Vec { - person.get_bits() + person + .get_bits() .into_iter() .map(|e| Boolean::constant(e)) .collect() @@ -21,9 +17,10 @@ pub fn pedersen_hash( mut cs: CS, personalization: Personalization, bits: &[Boolean], - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where CS: ConstraintSystem +where + CS: ConstraintSystem, { let personalization = get_constant_bools(&personalization); assert_eq!(personalization.len(), 6); @@ -36,8 +33,7 @@ pub fn pedersen_hash( let mut segment_i = 0; loop { let mut segment_result = None; - let mut segment_windows = &segment_generators.next() - .expect("enough segments")[..]; + let mut segment_windows = &segment_generators.next().expect("enough segments")[..]; let mut window_i = 0; while let Some(a) = bits.next() { @@ -47,7 +43,7 @@ pub fn pedersen_hash( let tmp = lookup3_xy_with_conditional_negation( cs.namespace(|| format!("segment {}, window {}", segment_i, window_i)), &[a.clone(), b.clone(), c.clone()], - &segment_windows[0] + &segment_windows[0], )?; let tmp = MontgomeryPoint::interpret_unchecked(tmp.0, tmp.1); @@ -55,12 +51,14 @@ pub fn pedersen_hash( match segment_result { None => { segment_result = Some(tmp); - }, + } Some(ref mut segment_result) => { *segment_result = tmp.add( - cs.namespace(|| format!("addition of segment {}, window {}", segment_i, window_i)), + cs.namespace(|| { + format!("addition of segment {}, window {}", segment_i, window_i) + }), segment_result, - params + params, )?; } } @@ -79,22 +77,24 @@ pub fn pedersen_hash( // Convert this segment into twisted Edwards form. let segment_result = segment_result.into_edwards( cs.namespace(|| format!("conversion of segment {} into edwards", segment_i)), - params + params, )?; match edwards_result { Some(ref mut edwards_result) => { *edwards_result = segment_result.add( - cs.namespace(|| format!("addition of segment {} to accumulator", segment_i)), + cs.namespace(|| { + format!("addition of segment {} to accumulator", segment_i) + }), edwards_result, - params + params, )?; - }, + } None => { edwards_result = Some(segment_result); } } - }, + } None => { // We didn't process any new bits. break; @@ -110,37 +110,44 @@ pub fn pedersen_hash( #[cfg(test)] mod test { use super::*; + use bellman::gadgets::boolean::{AllocatedBit, Boolean}; use bellman::gadgets::test::*; - use bellman::gadgets::boolean::{Boolean, AllocatedBit}; - use zcash_primitives::pedersen_hash; use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; + use zcash_primitives::pedersen_hash; #[test] fn test_pedersen_hash_constraints() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let params = &JubjubBls12::new(); let mut cs = TestConstraintSystem::::new(); - let input: Vec = (0..(Fr::NUM_BITS * 2)).map(|_| rng.next_u32() % 2 != 0).collect(); + let input: Vec = (0..(Fr::NUM_BITS * 2)) + .map(|_| rng.next_u32() % 2 != 0) + .collect(); - let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { - Boolean::from( - AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap() - ) - }).collect(); + let input_bools: Vec = input + .iter() + .enumerate() + .map(|(i, b)| { + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap(), + ) + }) + .collect(); pedersen_hash( cs.namespace(|| "pedersen hash"), Personalization::NoteCommitment, &input_bools, - params - ).unwrap(); + params, + ) + .unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 1377); @@ -149,8 +156,8 @@ mod test { #[test] fn test_pedersen_hash() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let params = &JubjubBls12::new(); @@ -160,26 +167,33 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { - Boolean::from( - AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap() - ) - }).collect(); + let input_bools: Vec = input + .iter() + .enumerate() + .map(|(i, b)| { + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)) + .unwrap(), + ) + }) + .collect(); let res = pedersen_hash( cs.namespace(|| "pedersen hash"), Personalization::MerkleTree(1), &input_bools, - params - ).unwrap(); + params, + ) + .unwrap(); assert!(cs.is_satisfied()); let expected = pedersen_hash::pedersen_hash::( Personalization::MerkleTree(1), input.clone().into_iter(), - params - ).into_xy(); + params, + ) + .into_xy(); assert_eq!(res.get_x().get_value().unwrap(), expected.0); assert_eq!(res.get_y().get_value().unwrap(), expected.1); @@ -188,8 +202,9 @@ mod test { let unexpected = pedersen_hash::pedersen_hash::( Personalization::MerkleTree(0), input.into_iter(), - params - ).into_xy(); + params, + ) + .into_xy(); assert!(res.get_x().get_value().unwrap() != unexpected.0); assert!(res.get_y().get_value().unwrap() != unexpected.1); diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index 1349c8c..0554ff4 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -1,31 +1,20 @@ use ff::{Field, PrimeField, PrimeFieldRepr}; -use bellman::{ - SynthesisError, - ConstraintSystem, - Circuit -}; +use bellman::{Circuit, ConstraintSystem, SynthesisError}; -use zcash_primitives::jubjub::{ - JubjubEngine, - FixedGenerators -}; +use zcash_primitives::jubjub::{FixedGenerators, JubjubEngine}; use zcash_primitives::constants; -use zcash_primitives::primitives::{ - ValueCommitment, - ProofGenerationKey, - PaymentAddress -}; +use zcash_primitives::primitives::{PaymentAddress, ProofGenerationKey, ValueCommitment}; -use bellman::gadgets::Assignment; -use bellman::gadgets::boolean; use super::ecc; use super::pedersen_hash; use bellman::gadgets::blake2s; -use bellman::gadgets::num; +use bellman::gadgets::boolean; use bellman::gadgets::multipack; +use bellman::gadgets::num; +use bellman::gadgets::Assignment; pub const TREE_DEPTH: usize = zcash_primitives::sapling::SAPLING_COMMITMENT_TREE_DEPTH; @@ -54,7 +43,7 @@ pub struct Spend<'a, E: JubjubEngine> { /// The anchor; the root of the tree. If the note being /// spent is zero-value, this can be anything. - pub anchor: Option + pub anchor: Option, } /// This is an output circuit instance. @@ -71,7 +60,7 @@ pub struct Output<'a, E: JubjubEngine> { pub commitment_randomness: Option, /// The ephemeral secret key for DH with recipient - pub esk: Option + pub esk: Option, } /// Exposes a Pedersen commitment to the value as an @@ -79,15 +68,16 @@ pub struct Output<'a, E: JubjubEngine> { fn expose_value_commitment( mut cs: CS, value_commitment: Option>, - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where E: JubjubEngine, - CS: ConstraintSystem +where + E: JubjubEngine, + CS: ConstraintSystem, { // Booleanize the value into little-endian bit order let value_bits = boolean::u64_into_boolean_vec_le( cs.namespace(|| "value"), - value_commitment.as_ref().map(|c| c.value) + value_commitment.as_ref().map(|c| c.value), )?; // Compute the note value in the exponent @@ -95,7 +85,7 @@ fn expose_value_commitment( cs.namespace(|| "compute the value in the exponent"), FixedGenerators::ValueCommitmentValue, &value_bits, - params + params, )?; // Booleanize the randomness. This does not ensure @@ -103,7 +93,7 @@ fn expose_value_commitment( // it doesn't matter for security. let rcv = boolean::field_into_boolean_vec_le( cs.namespace(|| "rcv"), - value_commitment.as_ref().map(|c| c.randomness) + value_commitment.as_ref().map(|c| c.randomness), )?; // Compute the randomness in the exponent @@ -111,15 +101,11 @@ fn expose_value_commitment( cs.namespace(|| "computation of rcv"), FixedGenerators::ValueCommitmentRandomness, &rcv, - params + params, )?; // Compute the Pedersen commitment to the value - let cv = value.add( - cs.namespace(|| "computation of cv"), - &rcv, - params - )?; + let cv = value.add(cs.namespace(|| "computation of cv"), &rcv, params)?; // Expose the commitment as an input to the circuit cv.inputize(cs.namespace(|| "commitment point"))?; @@ -128,43 +114,32 @@ fn expose_value_commitment( } impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { - fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { // Prover witnesses ak (ensures that it's on the curve) let ak = ecc::EdwardsPoint::witness( cs.namespace(|| "ak"), self.proof_generation_key.as_ref().map(|k| k.ak.clone()), - self.params + self.params, )?; // There are no sensible attacks on small order points // of ak (that we're aware of!) but it's a cheap check, // so we do it. - ak.assert_not_small_order( - cs.namespace(|| "ak not small order"), - self.params - )?; + ak.assert_not_small_order(cs.namespace(|| "ak not small order"), self.params)?; // Rerandomize ak and expose it as an input to the circuit { - let ar = boolean::field_into_boolean_vec_le( - cs.namespace(|| "ar"), - self.ar - )?; + let ar = boolean::field_into_boolean_vec_le(cs.namespace(|| "ar"), self.ar)?; // Compute the randomness in the exponent let ar = ecc::fixed_base_multiplication( cs.namespace(|| "computation of randomization for the signing key"), FixedGenerators::SpendingKeyGenerator, &ar, - self.params + self.params, )?; - let rk = ak.add( - cs.namespace(|| "computation of rk"), - &ar, - self.params - )?; + let rk = ak.add(cs.namespace(|| "computation of rk"), &ar, self.params)?; rk.inputize(cs.namespace(|| "rk"))?; } @@ -175,7 +150,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // Witness nsk as bits let nsk = boolean::field_into_boolean_vec_le( cs.namespace(|| "nsk"), - self.proof_generation_key.as_ref().map(|k| k.nsk.clone()) + self.proof_generation_key.as_ref().map(|k| k.nsk.clone()), )?; // NB: We don't ensure that the bit representation of nsk @@ -188,7 +163,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "computation of nk"), FixedGenerators::ProofGenerationKey, &nsk, - self.params + self.params, )?; } @@ -196,9 +171,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let mut ivk_preimage = vec![]; // Place ak in the preimage for CRH^ivk - ivk_preimage.extend( - ak.repr(cs.namespace(|| "representation of ak"))? - ); + ivk_preimage.extend(ak.repr(cs.namespace(|| "representation of ak"))?); // This is the nullifier preimage for PRF^nf let mut nf_preimage = vec![]; @@ -206,9 +179,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // Extend ivk and nf preimages with the representation of // nk. { - let repr_nk = nk.repr( - cs.namespace(|| "representation of nk") - )?; + let repr_nk = nk.repr(cs.namespace(|| "representation of nk"))?; ivk_preimage.extend(repr_nk.iter().cloned()); nf_preimage.extend(repr_nk); @@ -221,7 +192,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let mut ivk = blake2s::blake2s( cs.namespace(|| "computation of ivk"), &ivk_preimage, - constants::CRH_IVK_PERSONALIZATION + constants::CRH_IVK_PERSONALIZATION, )?; // drop_5 to ensure it's in the field @@ -239,7 +210,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { ecc::EdwardsPoint::witness( cs.namespace(|| "witness g_d"), self.payment_address.as_ref().and_then(|a| a.g_d(params)), - self.params + self.params, )? }; @@ -247,17 +218,10 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // is already done in the Output circuit, and this proof ensures // g_d is bound to a product of that check, but for defense in // depth let's check it anyway. It's cheap. - g_d.assert_not_small_order( - cs.namespace(|| "g_d not small order"), - self.params - )?; + g_d.assert_not_small_order(cs.namespace(|| "g_d not small order"), self.params)?; // Compute pk_d = g_d^ivk - let pk_d = g_d.mul( - cs.namespace(|| "compute pk_d"), - &ivk, - self.params - )?; + let pk_d = g_d.mul(cs.namespace(|| "compute pk_d"), &ivk, self.params)?; // Compute note contents: // value (in big endian) followed by g_d and pk_d @@ -271,18 +235,14 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let value_bits = expose_value_commitment( cs.namespace(|| "value commitment"), self.value_commitment, - self.params + self.params, )?; // Compute the note's value as a linear combination // of the bits. let mut coeff = E::Fr::one(); for bit in &value_bits { - value_num = value_num.add_bool_with_coeff( - CS::one(), - bit, - coeff - ); + value_num = value_num.add_bool_with_coeff(CS::one(), bit, coeff); coeff.double(); } @@ -291,14 +251,10 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { } // Place g_d in the note - note_contents.extend( - g_d.repr(cs.namespace(|| "representation of g_d"))? - ); + note_contents.extend(g_d.repr(cs.namespace(|| "representation of g_d"))?); // Place pk_d in the note - note_contents.extend( - pk_d.repr(cs.namespace(|| "representation of pk_d"))? - ); + note_contents.extend(pk_d.repr(cs.namespace(|| "representation of pk_d"))?); assert_eq!( note_contents.len(), @@ -312,14 +268,14 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "note content hash"), pedersen_hash::Personalization::NoteCommitment, ¬e_contents, - self.params + self.params, )?; { // Booleanize the randomness for the note commitment let rcm = boolean::field_into_boolean_vec_le( cs.namespace(|| "rcm"), - self.commitment_randomness + self.commitment_randomness, )?; // Compute the note commitment randomness in the exponent @@ -327,7 +283,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "computation of commitment randomness"), FixedGenerators::NoteCommitmentRandomness, &rcm, - self.params + self.params, )?; // Randomize the note commitment. Pedersen hashes are not @@ -335,7 +291,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cm = cm.add( cs.namespace(|| "randomization of note commitment"), &rcm, - self.params + self.params, )?; } @@ -356,7 +312,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // depth of the tree. let cur_is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc( cs.namespace(|| "position bit"), - e.map(|e| e.1) + e.map(|e| e.1), )?); // Push this boolean for nullifier computation later @@ -364,19 +320,15 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // Witness the authentication path element adjacent // at this depth. - let path_element = num::AllocatedNum::alloc( - cs.namespace(|| "path element"), - || { - Ok(e.get()?.0) - } - )?; + let path_element = + num::AllocatedNum::alloc(cs.namespace(|| "path element"), || Ok(e.get()?.0))?; // Swap the two if the current subtree is on the right let (xl, xr) = num::AllocatedNum::conditionally_reverse( cs.namespace(|| "conditional reversal of preimage"), &cur, &path_element, - &cur_is_right + &cur_is_right, )?; // We don't need to be strict, because the function is @@ -392,20 +344,19 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "computation of pedersen hash"), pedersen_hash::Personalization::MerkleTree(i), &preimage, - self.params - )?.get_x().clone(); // Injective encoding + self.params, + )? + .get_x() + .clone(); // Injective encoding } { let real_anchor_value = self.anchor; // Allocate the "real" anchor that will be exposed. - let rt = num::AllocatedNum::alloc( - cs.namespace(|| "conditional anchor"), - || { - Ok(*real_anchor_value.get()?) - } - )?; + let rt = num::AllocatedNum::alloc(cs.namespace(|| "conditional anchor"), || { + Ok(*real_anchor_value.get()?) + })?; // (cur - rt) * value = 0 // if value is zero, cur and rt can be different @@ -414,7 +365,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { || "conditionally enforce correct root", |lc| lc + cur.get_variable() - rt.get_variable(), |lc| lc + &value_num.lc(E::Fr::one()), - |lc| lc + |lc| lc, ); // Expose the anchor @@ -430,29 +381,27 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "g^position"), FixedGenerators::NullifierPosition, &position_bits, - self.params + self.params, )?; // Add the position to the commitment rho = rho.add( cs.namespace(|| "faerie gold prevention"), &position, - self.params + self.params, )?; } - + // Let's compute nf = BLAKE2s(nk || rho) - nf_preimage.extend( - rho.repr(cs.namespace(|| "representation of rho"))? - ); + nf_preimage.extend(rho.repr(cs.namespace(|| "representation of rho"))?); assert_eq!(nf_preimage.len(), 512); - + // Compute nf let nf = blake2s::blake2s( cs.namespace(|| "nf computation"), &nf_preimage, - constants::PRF_NF_PERSONALIZATION + constants::PRF_NF_PERSONALIZATION, )?; multipack::pack_into_inputs(cs.namespace(|| "pack nullifier"), &nf) @@ -460,8 +409,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { } impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { - fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { // Let's start to construct our note, which contains // value (big endian) let mut note_contents = vec![]; @@ -471,7 +419,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { note_contents.extend(expose_value_commitment( cs.namespace(|| "value commitment"), self.value_commitment, - self.params + self.params, )?); // Let's deal with g_d @@ -483,7 +431,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { let g_d = ecc::EdwardsPoint::witness( cs.namespace(|| "witness g_d"), self.payment_address.as_ref().and_then(|a| a.g_d(params)), - self.params + self.params, )?; // g_d is ensured to be large order. The relationship @@ -495,29 +443,17 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { // // Further, if it were small order, epk would be // small order too! - g_d.assert_not_small_order( - cs.namespace(|| "g_d not small order"), - self.params - )?; + g_d.assert_not_small_order(cs.namespace(|| "g_d not small order"), self.params)?; // Extend our note contents with the representation of // g_d. - note_contents.extend( - g_d.repr(cs.namespace(|| "representation of g_d"))? - ); + note_contents.extend(g_d.repr(cs.namespace(|| "representation of g_d"))?); // Booleanize our ephemeral secret key - let esk = boolean::field_into_boolean_vec_le( - cs.namespace(|| "esk"), - self.esk - )?; + let esk = boolean::field_into_boolean_vec_le(cs.namespace(|| "esk"), self.esk)?; // Create the ephemeral public key from g_d. - let epk = g_d.mul( - cs.namespace(|| "epk computation"), - &esk, - self.params - )?; + let epk = g_d.mul(cs.namespace(|| "epk computation"), &esk, self.params)?; // Expose epk publicly. epk.inputize(cs.namespace(|| "epk"))?; @@ -534,13 +470,13 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { // endian bits (to match the representation) let y_contents = boolean::field_into_boolean_vec_le( cs.namespace(|| "pk_d bits of y"), - pk_d.map(|e| e.1) + pk_d.map(|e| e.1), )?; // Witness the sign bit let sign_bit = boolean::Boolean::from(boolean::AllocatedBit::alloc( cs.namespace(|| "pk_d bit of x"), - pk_d.map(|e| e.0.into_repr().is_odd()) + pk_d.map(|e| e.0.into_repr().is_odd()), )?); // Extend the note with pk_d representation @@ -560,14 +496,14 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { cs.namespace(|| "note content hash"), pedersen_hash::Personalization::NoteCommitment, ¬e_contents, - self.params + self.params, )?; { // Booleanize the randomness let rcm = boolean::field_into_boolean_vec_le( cs.namespace(|| "rcm"), - self.commitment_randomness + self.commitment_randomness, )?; // Compute the note commitment randomness in the exponent @@ -575,14 +511,14 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { cs.namespace(|| "computation of commitment randomness"), FixedGenerators::NoteCommitmentRandomness, &rcm, - self.params + self.params, )?; // Randomize our note commitment cm = cm.add( cs.namespace(|| "randomization of note commitment"), &rcm, - self.params + self.params, )?; } @@ -604,7 +540,7 @@ fn test_input_circuit_with_bls12_381() { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use zcash_primitives::{ - jubjub::{JubjubBls12, fs, edwards}, + jubjub::{edwards, fs, JubjubBls12}, pedersen_hash, primitives::{Diversifier, Note, ProofGenerationKey}, }; @@ -628,7 +564,7 @@ fn test_input_circuit_with_bls12_381() { let proof_generation_key = ProofGenerationKey { ak: ak.clone(), - nsk: nsk.clone() + nsk: nsk.clone(), }; let viewing_key = proof_generation_key.into_viewing_key(params); @@ -642,11 +578,7 @@ fn test_input_circuit_with_bls12_381() { Diversifier(d) }; - if let Some(p) = viewing_key.into_payment_address( - diversifier, - params - ) - { + if let Some(p) = viewing_key.into_payment_address(diversifier, params) { payment_address = p; break; } @@ -664,15 +596,14 @@ fn test_input_circuit_with_bls12_381() { value: value_commitment.value, g_d: g_d.clone(), pk_d: payment_address.pk_d.clone(), - r: commitment_randomness.clone() + r: commitment_randomness.clone(), }; let mut position = 0u64; let cm: Fr = note.cm(params); let mut cur = cm.clone(); - for (i, val) in auth_path.clone().into_iter().enumerate() - { + for (i, val) in auth_path.clone().into_iter().enumerate() { let (uncle, b) = val.unwrap(); let mut lhs = cur; @@ -691,10 +622,12 @@ fn test_input_circuit_with_bls12_381() { cur = pedersen_hash::pedersen_hash::( pedersen_hash::Personalization::MerkleTree(i), lhs.into_iter() - .take(Fr::NUM_BITS as usize) - .chain(rhs.into_iter().take(Fr::NUM_BITS as usize)), - params - ).into_xy().0; + .take(Fr::NUM_BITS as usize) + .chain(rhs.into_iter().take(Fr::NUM_BITS as usize)), + params, + ) + .into_xy() + .0; if b { position |= 1 << i; @@ -716,14 +649,17 @@ fn test_input_circuit_with_bls12_381() { commitment_randomness: Some(commitment_randomness), ar: Some(ar), auth_path: auth_path.clone(), - anchor: Some(cur) + anchor: Some(cur), }; instance.synthesize(&mut cs).unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 98777); - assert_eq!(cs.hash(), "d37c738e83df5d9b0bb6495ac96abf21bcb2697477e2c15c2c7916ff7a3b6a89"); + assert_eq!( + cs.hash(), + "d37c738e83df5d9b0bb6495ac96abf21bcb2697477e2c15c2c7916ff7a3b6a89" + ); assert_eq!(cs.get("randomization of note commitment/x3/num"), cm); @@ -731,8 +667,14 @@ fn test_input_circuit_with_bls12_381() { assert_eq!(cs.get_input(0, "ONE"), Fr::one()); assert_eq!(cs.get_input(1, "rk/x/input variable"), rk.0); assert_eq!(cs.get_input(2, "rk/y/input variable"), rk.1); - assert_eq!(cs.get_input(3, "value commitment/commitment point/x/input variable"), expected_value_cm.0); - assert_eq!(cs.get_input(4, "value commitment/commitment point/y/input variable"), expected_value_cm.1); + assert_eq!( + cs.get_input(3, "value commitment/commitment point/x/input variable"), + expected_value_cm.0 + ); + assert_eq!( + cs.get_input(4, "value commitment/commitment point/y/input variable"), + expected_value_cm.1 + ); assert_eq!(cs.get_input(5, "anchor/input variable"), cur); assert_eq!(cs.get_input(6, "pack nullifier/input 0"), expected_nf[0]); assert_eq!(cs.get_input(7, "pack nullifier/input 1"), expected_nf[1]); @@ -748,7 +690,7 @@ fn test_output_circuit_with_bls12_381() { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use zcash_primitives::{ - jubjub::{JubjubBls12, fs, edwards}, + jubjub::{edwards, fs, JubjubBls12}, primitives::{Diversifier, ProofGenerationKey}, }; @@ -769,7 +711,7 @@ fn test_output_circuit_with_bls12_381() { let proof_generation_key = ProofGenerationKey { ak: ak.clone(), - nsk: nsk.clone() + nsk: nsk.clone(), }; let viewing_key = proof_generation_key.into_viewing_key(params); @@ -783,11 +725,7 @@ fn test_output_circuit_with_bls12_381() { Diversifier(d) }; - if let Some(p) = viewing_key.into_payment_address( - diversifier, - params - ) - { + if let Some(p) = viewing_key.into_payment_address(diversifier, params) { payment_address = p; break; } @@ -804,30 +742,41 @@ fn test_output_circuit_with_bls12_381() { value_commitment: Some(value_commitment.clone()), payment_address: Some(payment_address.clone()), commitment_randomness: Some(commitment_randomness), - esk: Some(esk.clone()) + esk: Some(esk.clone()), }; instance.synthesize(&mut cs).unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 7827); - assert_eq!(cs.hash(), "c26d5cdfe6ccd65c03390902c02e11393ea6bb96aae32a7f2ecb12eb9103faee"); + assert_eq!( + cs.hash(), + "c26d5cdfe6ccd65c03390902c02e11393ea6bb96aae32a7f2ecb12eb9103faee" + ); - let expected_cm = payment_address.create_note( - value_commitment.value, - commitment_randomness, - params - ).expect("should be valid").cm(params); + let expected_cm = payment_address + .create_note(value_commitment.value, commitment_randomness, params) + .expect("should be valid") + .cm(params); let expected_value_cm = value_commitment.cm(params).into_xy(); - let expected_epk = payment_address.g_d(params).expect("should be valid").mul(esk, params); + let expected_epk = payment_address + .g_d(params) + .expect("should be valid") + .mul(esk, params); let expected_epk_xy = expected_epk.into_xy(); assert_eq!(cs.num_inputs(), 6); assert_eq!(cs.get_input(0, "ONE"), Fr::one()); - assert_eq!(cs.get_input(1, "value commitment/commitment point/x/input variable"), expected_value_cm.0); - assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm.1); + assert_eq!( + cs.get_input(1, "value commitment/commitment point/x/input variable"), + expected_value_cm.0 + ); + assert_eq!( + cs.get_input(2, "value commitment/commitment point/y/input variable"), + expected_value_cm.1 + ); assert_eq!(cs.get_input(3, "epk/x/input variable"), expected_epk_xy.0); assert_eq!(cs.get_input(4, "epk/y/input variable"), expected_epk_xy.1); assert_eq!(cs.get_input(5, "commitment/input variable"), expected_cm); diff --git a/zcash_proofs/src/circuit/sprout/commitment.rs b/zcash_proofs/src/circuit/sprout/commitment.rs index ba889a3..fba1217 100644 --- a/zcash_proofs/src/circuit/sprout/commitment.rs +++ b/zcash_proofs/src/circuit/sprout/commitment.rs @@ -1,20 +1,18 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::Boolean; +use bellman::gadgets::sha256::sha256; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::sha256::{ - sha256 -}; -use bellman::gadgets::boolean::{ - Boolean -}; +use pairing::Engine; pub fn note_comm( cs: CS, a_pk: &[Boolean], value: &[Boolean], rho: &[Boolean], - r: &[Boolean] + r: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(a_pk.len(), 256); assert_eq!(value.len(), 64); @@ -35,8 +33,5 @@ pub fn note_comm( image.extend(rho.iter().cloned()); image.extend(r.iter().cloned()); - sha256( - cs, - &image - ) + sha256(cs, &image) } diff --git a/zcash_proofs/src/circuit/sprout/input.rs b/zcash_proofs/src/circuit/sprout/input.rs index a84e3a6..ad6091f 100644 --- a/zcash_proofs/src/circuit/sprout/input.rs +++ b/zcash_proofs/src/circuit/sprout/input.rs @@ -1,16 +1,11 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::{AllocatedBit, Boolean}; +use bellman::gadgets::sha256::sha256_block_no_padding; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::sha256::{ - sha256_block_no_padding -}; -use bellman::gadgets::boolean::{ - AllocatedBit, - Boolean -}; +use pairing::Engine; -use super::*; -use super::prfs::*; use super::commitment::note_comm; +use super::prfs::*; +use super::*; pub struct InputNote { pub nf: Vec, @@ -27,49 +22,33 @@ impl InputNote { h_sig: &[Boolean], nonce: bool, auth_path: [Option<([u8; 32], bool)>; TREE_DEPTH], - rt: &[Boolean] + rt: &[Boolean], ) -> Result - where E: Engine, CS: ConstraintSystem + where + E: Engine, + CS: ConstraintSystem, { let a_sk = witness_u252( cs.namespace(|| "a_sk"), - a_sk.as_ref().map(|a_sk| &a_sk.0[..]) + a_sk.as_ref().map(|a_sk| &a_sk.0[..]), )?; - let rho = witness_u256( - cs.namespace(|| "rho"), - rho.as_ref().map(|rho| &rho.0[..]) - )?; + let rho = witness_u256(cs.namespace(|| "rho"), rho.as_ref().map(|rho| &rho.0[..]))?; - let r = witness_u256( - cs.namespace(|| "r"), - r.as_ref().map(|r| &r.0[..]) - )?; + let r = witness_u256(cs.namespace(|| "r"), r.as_ref().map(|r| &r.0[..]))?; - let a_pk = prf_a_pk( - cs.namespace(|| "a_pk computation"), - &a_sk - )?; + let a_pk = prf_a_pk(cs.namespace(|| "a_pk computation"), &a_sk)?; - let nf = prf_nf( - cs.namespace(|| "nf computation"), - &a_sk, - &rho - )?; + let nf = prf_nf(cs.namespace(|| "nf computation"), &a_sk, &rho)?; - let mac = prf_pk( - cs.namespace(|| "mac computation"), - &a_sk, - h_sig, - nonce - )?; + let mac = prf_pk(cs.namespace(|| "mac computation"), &a_sk, h_sig, nonce)?; let cm = note_comm( cs.namespace(|| "cm computation"), &a_pk, &value.bits_le(), &rho, - &r + &r, )?; // Witness into the merkle tree @@ -80,13 +59,13 @@ impl InputNote { let cur_is_right = AllocatedBit::alloc( cs.namespace(|| "cur is right"), - layer.as_ref().map(|&(_, p)| p) + layer.as_ref().map(|&(_, p)| p), )?; let lhs = cur; let rhs = witness_u256( cs.namespace(|| "sibling"), - layer.as_ref().map(|&(ref sibling, _)| &sibling[..]) + layer.as_ref().map(|&(ref sibling, _)| &sibling[..]), )?; // Conditionally swap if cur is right @@ -94,19 +73,16 @@ impl InputNote { cs.namespace(|| "conditional swap"), &lhs[..], &rhs[..], - &cur_is_right + &cur_is_right, )?; - cur = sha256_block_no_padding( - cs.namespace(|| "hash of this layer"), - &preimage - )?; + cur = sha256_block_no_padding(cs.namespace(|| "hash of this layer"), &preimage)?; } // enforce must be true if the value is nonzero let enforce = AllocatedBit::alloc( cs.namespace(|| "enforce"), - value.get_value().map(|n| n != 0) + value.get_value().map(|n| n != 0), )?; // value * (1 - enforce) = 0 @@ -116,7 +92,7 @@ impl InputNote { || "enforce validity", |_| value.lc(), |lc| lc + CS::one() - enforce.get_variable(), - |lc| lc + |lc| lc, ); assert_eq!(cur.len(), rt.len()); @@ -132,14 +108,11 @@ impl InputNote { || format!("conditionally enforce correct root for bit {}", i), |_| cur.lc(CS::one(), E::Fr::one()) - &rt.lc(CS::one(), E::Fr::one()), |lc| lc + enforce.get_variable(), - |lc| lc + |lc| lc, ); } - Ok(InputNote { - mac: mac, - nf: nf - }) + Ok(InputNote { mac: mac, nf: nf }) } } @@ -149,9 +122,11 @@ pub fn conditionally_swap_u256( mut cs: CS, lhs: &[Boolean], rhs: &[Boolean], - condition: &AllocatedBit + condition: &AllocatedBit, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(lhs.len(), 256); assert_eq!(rhs.len(), 256); @@ -164,13 +139,9 @@ pub fn conditionally_swap_u256( let x = Boolean::from(AllocatedBit::alloc( cs.namespace(|| "x"), - condition.get_value().and_then(|v| { - if v { - rhs.get_value() - } else { - lhs.get_value() - } - }) + condition + .get_value() + .and_then(|v| if v { rhs.get_value() } else { lhs.get_value() }), )?); // x = (1-condition)lhs + (condition)rhs @@ -184,33 +155,25 @@ pub fn conditionally_swap_u256( // x = rhs cs.enforce( || "conditional swap for x", - |lc| lc + &rhs.lc(CS::one(), E::Fr::one()) - - &lhs.lc(CS::one(), E::Fr::one()), + |lc| lc + &rhs.lc(CS::one(), E::Fr::one()) - &lhs.lc(CS::one(), E::Fr::one()), |lc| lc + condition.get_variable(), - |lc| lc + &x.lc(CS::one(), E::Fr::one()) - - &lhs.lc(CS::one(), E::Fr::one()) + |lc| lc + &x.lc(CS::one(), E::Fr::one()) - &lhs.lc(CS::one(), E::Fr::one()), ); let y = Boolean::from(AllocatedBit::alloc( cs.namespace(|| "y"), - condition.get_value().and_then(|v| { - if v { - lhs.get_value() - } else { - rhs.get_value() - } - }) + condition + .get_value() + .and_then(|v| if v { lhs.get_value() } else { rhs.get_value() }), )?); // y = (1-condition)rhs + (condition)lhs // y - rhs = condition (lhs - rhs) cs.enforce( || "conditional swap for y", - |lc| lc + &lhs.lc(CS::one(), E::Fr::one()) - - &rhs.lc(CS::one(), E::Fr::one()), + |lc| lc + &lhs.lc(CS::one(), E::Fr::one()) - &rhs.lc(CS::one(), E::Fr::one()), |lc| lc + condition.get_variable(), - |lc| lc + &y.lc(CS::one(), E::Fr::one()) - - &rhs.lc(CS::one(), E::Fr::one()) + |lc| lc + &y.lc(CS::one(), E::Fr::one()) - &rhs.lc(CS::one(), E::Fr::one()), ); new_lhs.push(x); diff --git a/zcash_proofs/src/circuit/sprout/mod.rs b/zcash_proofs/src/circuit/sprout/mod.rs index c28b8d7..358e1bb 100644 --- a/zcash_proofs/src/circuit/sprout/mod.rs +++ b/zcash_proofs/src/circuit/sprout/mod.rs @@ -1,16 +1,13 @@ +use bellman::gadgets::boolean::{AllocatedBit, Boolean}; +use bellman::gadgets::multipack::pack_into_inputs; +use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError}; use ff::Field; use pairing::Engine; -use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination}; -use bellman::gadgets::boolean::{ - AllocatedBit, - Boolean -}; -use bellman::gadgets::multipack::pack_into_inputs; -mod prfs; mod commitment; mod input; mod output; +mod prfs; use self::input::*; use self::output::*; @@ -37,39 +34,29 @@ pub struct JSInput { pub a_sk: Option, pub rho: Option, pub r: Option, - pub auth_path: [Option<([u8; 32], bool)>; TREE_DEPTH] + pub auth_path: [Option<([u8; 32], bool)>; TREE_DEPTH], } pub struct JSOutput { pub value: Option, pub a_pk: Option, - pub r: Option + pub r: Option, } impl Circuit for JoinSplit { - fn synthesize>( - self, - cs: &mut CS - ) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { assert_eq!(self.inputs.len(), 2); assert_eq!(self.outputs.len(), 2); // vpub_old is the value entering the // JoinSplit from the "outside" value // pool - let vpub_old = NoteValue::new( - cs.namespace(|| "vpub_old"), - self.vpub_old - )?; + let vpub_old = NoteValue::new(cs.namespace(|| "vpub_old"), self.vpub_old)?; // vpub_new is the value leaving the // JoinSplit into the "outside" value // pool - let vpub_new = NoteValue::new( - cs.namespace(|| "vpub_new"), - self.vpub_new - )?; + let vpub_new = NoteValue::new(cs.namespace(|| "vpub_new"), self.vpub_new)?; // The left hand side of the balance equation // vpub_old + inputs[0].value + inputs[1].value @@ -80,22 +67,17 @@ impl Circuit for JoinSplit { let mut rhs = vpub_new.lc(); // Witness rt (merkle tree root) - let rt = witness_u256( - cs.namespace(|| "rt"), - self.rt.as_ref().map(|v| &v[..]) - ).unwrap(); + let rt = witness_u256(cs.namespace(|| "rt"), self.rt.as_ref().map(|v| &v[..])).unwrap(); // Witness h_sig let h_sig = witness_u256( cs.namespace(|| "h_sig"), - self.h_sig.as_ref().map(|v| &v[..]) - ).unwrap(); + self.h_sig.as_ref().map(|v| &v[..]), + ) + .unwrap(); // Witness phi - let phi = witness_u252( - cs.namespace(|| "phi"), - self.phi.as_ref().map(|v| &v[..]) - ).unwrap(); + let phi = witness_u252(cs.namespace(|| "phi"), self.phi.as_ref().map(|v| &v[..])).unwrap(); let mut input_notes = vec![]; let mut lhs_total = self.vpub_old; @@ -110,17 +92,14 @@ impl Circuit for JoinSplit { } // Allocate the value of the note - let value = NoteValue::new( - cs.namespace(|| "value"), - input.value - )?; + let value = NoteValue::new(cs.namespace(|| "value"), input.value)?; // Compute the nonce (for PRF inputs) which is false // for the first input, and true for the second input. let nonce = match i { 0 => false, 1 => true, - _ => unreachable!() + _ => unreachable!(), }; // Perform input note computations @@ -133,7 +112,7 @@ impl Circuit for JoinSplit { &h_sig, nonce, input.auth_path, - &rt + &rt, )?); // Add the note value to the left hand side of @@ -148,10 +127,8 @@ impl Circuit for JoinSplit { { // Expected sum of the left hand side of the balance // equation, expressed as a 64-bit unsigned integer - let lhs_total = NoteValue::new( - cs.namespace(|| "total value of left hand side"), - lhs_total - )?; + let lhs_total = + NoteValue::new(cs.namespace(|| "total value of left hand side"), lhs_total)?; // Enforce that the left hand side can be expressed as a 64-bit // integer @@ -159,7 +136,7 @@ impl Circuit for JoinSplit { || "left hand side can be expressed as a 64-bit unsigned integer", |_| lhs.clone(), |lc| lc + CS::one(), - |_| lhs_total.lc() + |_| lhs_total.lc(), ); } @@ -169,17 +146,14 @@ impl Circuit for JoinSplit { for (i, output) in self.outputs.into_iter().enumerate() { let cs = &mut cs.namespace(|| format!("output {}", i)); - let value = NoteValue::new( - cs.namespace(|| "value"), - output.value - )?; + let value = NoteValue::new(cs.namespace(|| "value"), output.value)?; // Compute the nonce (for PRF inputs) which is false // for the first output, and true for the second output. let nonce = match i { 0 => false, 1 => true, - _ => unreachable!() + _ => unreachable!(), }; // Perform output note computations @@ -190,7 +164,7 @@ impl Circuit for JoinSplit { output.r, &phi, &h_sig, - nonce + nonce, )?); // Add the note value to the right hand side of @@ -203,7 +177,7 @@ impl Circuit for JoinSplit { || "balance equation", |_| lhs.clone(), |lc| lc + CS::one(), - |_| rhs + |_| rhs, ); let mut public_inputs = vec![]; @@ -229,15 +203,14 @@ impl Circuit for JoinSplit { pub struct NoteValue { value: Option, // Least significant digit first - bits: Vec + bits: Vec, } impl NoteValue { - fn new( - mut cs: CS, - value: Option - ) -> Result - where E: Engine, CS: ConstraintSystem, + fn new(mut cs: CS, value: Option) -> Result + where + E: Engine, + CS: ConstraintSystem, { let mut values; match value { @@ -247,7 +220,7 @@ impl NoteValue { values.push(Some(val & 1 == 1)); val >>= 1; } - }, + } None => { values = vec![None; 64]; } @@ -255,28 +228,27 @@ impl NoteValue { let mut bits = vec![]; for (i, value) in values.into_iter().enumerate() { - bits.push( - AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - value - )? - ); + bits.push(AllocatedBit::alloc( + cs.namespace(|| format!("bit {}", i)), + value, + )?); } Ok(NoteValue { value: value, - bits: bits + bits: bits, }) } /// Encodes the bits of the value into little-endian /// byte order. fn bits_le(&self) -> Vec { - self.bits.chunks(8) - .flat_map(|v| v.iter().rev()) - .cloned() - .map(|e| Boolean::from(e)) - .collect() + self.bits + .chunks(8) + .flat_map(|v| v.iter().rev()) + .cloned() + .map(|e| Boolean::from(e)) + .collect() } /// Computes this value as a linear combination of @@ -304,15 +276,18 @@ fn witness_bits( mut cs: CS, value: Option<&[u8]>, num_bits: usize, - skip_bits: usize + skip_bits: usize, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +where + E: Engine, + CS: ConstraintSystem, { let bit_values = if let Some(value) = value { let mut tmp = vec![]; - for b in value.iter() - .flat_map(|&m| (0..8).rev().map(move |i| m >> i & 1 == 1)) - .skip(skip_bits) + for b in value + .iter() + .flat_map(|&m| (0..8).rev().map(move |i| m >> i & 1 == 1)) + .skip(skip_bits) { tmp.push(Some(b)); } @@ -327,37 +302,35 @@ fn witness_bits( for (i, value) in bit_values.into_iter().enumerate() { bits.push(Boolean::from(AllocatedBit::alloc( cs.namespace(|| format!("bit {}", i)), - value + value, )?)); } Ok(bits) } -fn witness_u256( - cs: CS, - value: Option<&[u8]>, -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +fn witness_u256(cs: CS, value: Option<&[u8]>) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { witness_bits(cs, value, 256, 0) } -fn witness_u252( - cs: CS, - value: Option<&[u8]>, -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +fn witness_u252(cs: CS, value: Option<&[u8]>) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { witness_bits(cs, value, 252, 4) } #[test] fn test_sprout_constraints() { - use pairing::bls12_381::{Bls12}; use bellman::gadgets::test::*; + use pairing::bls12_381::Bls12; - use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; + use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; let test_vector = include_bytes!("test_vectors.dat"); let mut test_vector = &test_vector[..]; @@ -393,9 +366,7 @@ fn test_sprout_constraints() { } let mut position = test_vector.read_u64::().unwrap(); for i in 0..TREE_DEPTH { - auth_path[i].as_mut().map(|p| { - p.1 = (position & 1) == 1 - }); + auth_path[i].as_mut().map(|p| p.1 = (position & 1) == 1); position >>= 1; } @@ -407,15 +378,13 @@ fn test_sprout_constraints() { let r = Some(CommitmentRandomness(get_u256(&mut test_vector))); let a_sk = Some(SpendingKey(get_u256(&mut test_vector))); - inputs.push( - JSInput { - value: value, - a_sk: a_sk, - rho: rho, - r: r, - auth_path: auth_path - } - ); + inputs.push(JSInput { + value: value, + a_sk: a_sk, + rho: rho, + r: r, + auth_path: auth_path, + }); } let mut outputs = vec![]; @@ -426,13 +395,11 @@ fn test_sprout_constraints() { get_u256(&mut test_vector); let r = Some(CommitmentRandomness(get_u256(&mut test_vector))); - outputs.push( - JSOutput { - value: value, - a_pk: a_pk, - r: r - } - ); + outputs.push(JSOutput { + value: value, + a_pk: a_pk, + r: r, + }); } let vpub_old = Some(test_vector.read_u64::().unwrap()); @@ -454,7 +421,7 @@ fn test_sprout_constraints() { phi: phi, inputs: inputs, outputs: outputs, - rt: rt + rt: rt, }; js.synthesize(&mut cs).unwrap(); @@ -465,7 +432,10 @@ fn test_sprout_constraints() { assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 1989085); assert_eq!(cs.num_inputs(), 10); - assert_eq!(cs.hash(), "1a228d3c6377130d1778c7885811dc8b8864049cb5af8aff7e6cd46c5bc4b84c"); + assert_eq!( + cs.hash(), + "1a228d3c6377130d1778c7885811dc8b8864049cb5af8aff7e6cd46c5bc4b84c" + ); let mut expected_inputs = vec![]; expected_inputs.extend(rt.unwrap().to_vec()); @@ -476,8 +446,12 @@ fn test_sprout_constraints() { expected_inputs.extend(mac2.to_vec()); expected_inputs.extend(cm1.to_vec()); expected_inputs.extend(cm2.to_vec()); - expected_inputs.write_u64::(vpub_old.unwrap()).unwrap(); - expected_inputs.write_u64::(vpub_new.unwrap()).unwrap(); + expected_inputs + .write_u64::(vpub_old.unwrap()) + .unwrap(); + expected_inputs + .write_u64::(vpub_new.unwrap()) + .unwrap(); use bellman::gadgets::multipack; diff --git a/zcash_proofs/src/circuit/sprout/output.rs b/zcash_proofs/src/circuit/sprout/output.rs index f2e504a..a9a1e48 100644 --- a/zcash_proofs/src/circuit/sprout/output.rs +++ b/zcash_proofs/src/circuit/sprout/output.rs @@ -1,13 +1,13 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::Boolean; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::boolean::{Boolean}; +use pairing::Engine; -use super::*; -use super::prfs::*; use super::commitment::note_comm; +use super::prfs::*; +use super::*; pub struct OutputNote { - pub cm: Vec + pub cm: Vec, } impl OutputNote { @@ -18,37 +18,29 @@ impl OutputNote { r: Option, phi: &[Boolean], h_sig: &[Boolean], - nonce: bool + nonce: bool, ) -> Result - where E: Engine, CS: ConstraintSystem, + where + E: Engine, + CS: ConstraintSystem, { - let rho = prf_rho( - cs.namespace(|| "rho"), - phi, - h_sig, - nonce - )?; + let rho = prf_rho(cs.namespace(|| "rho"), phi, h_sig, nonce)?; let a_pk = witness_u256( cs.namespace(|| "a_pk"), - a_pk.as_ref().map(|a_pk| &a_pk.0[..]) + a_pk.as_ref().map(|a_pk| &a_pk.0[..]), )?; - let r = witness_u256( - cs.namespace(|| "r"), - r.as_ref().map(|r| &r.0[..]) - )?; + let r = witness_u256(cs.namespace(|| "r"), r.as_ref().map(|r| &r.0[..]))?; let cm = note_comm( cs.namespace(|| "cm computation"), &a_pk, &value.bits_le(), &rho, - &r + &r, )?; - Ok(OutputNote { - cm: cm - }) + Ok(OutputNote { cm: cm }) } } diff --git a/zcash_proofs/src/circuit/sprout/prfs.rs b/zcash_proofs/src/circuit/sprout/prfs.rs index 0b3e42c..ea87b08 100644 --- a/zcash_proofs/src/circuit/sprout/prfs.rs +++ b/zcash_proofs/src/circuit/sprout/prfs.rs @@ -1,11 +1,7 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::Boolean; +use bellman::gadgets::sha256::sha256_block_no_padding; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::sha256::{ - sha256_block_no_padding -}; -use bellman::gadgets::boolean::{ - Boolean -}; +use pairing::Engine; fn prf( cs: CS, @@ -14,9 +10,11 @@ fn prf( c: bool, d: bool, x: &[Boolean], - y: &[Boolean] + y: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(x.len(), 252); assert_eq!(y.len(), 256); @@ -31,27 +29,35 @@ fn prf( assert_eq!(image.len(), 512); - sha256_block_no_padding( - cs, - &image - ) + sha256_block_no_padding(cs, &image) } -pub fn prf_a_pk( - cs: CS, - a_sk: &[Boolean] -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +pub fn prf_a_pk(cs: CS, a_sk: &[Boolean]) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { - prf(cs, true, true, false, false, a_sk, &(0..256).map(|_| Boolean::constant(false)).collect::>()) + prf( + cs, + true, + true, + false, + false, + a_sk, + &(0..256) + .map(|_| Boolean::constant(false)) + .collect::>(), + ) } pub fn prf_nf( cs: CS, a_sk: &[Boolean], - rho: &[Boolean] + rho: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { prf(cs, true, true, true, false, a_sk, rho) } @@ -60,9 +66,11 @@ pub fn prf_pk( cs: CS, a_sk: &[Boolean], h_sig: &[Boolean], - nonce: bool + nonce: bool, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { prf(cs, false, nonce, false, false, a_sk, h_sig) } @@ -71,9 +79,11 @@ pub fn prf_rho( cs: CS, phi: &[Boolean], h_sig: &[Boolean], - nonce: bool + nonce: bool, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { prf(cs, false, nonce, true, false, phi, h_sig) } diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 1c1a972..6dd5767 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -3,11 +3,11 @@ use bellman::groth16::{Parameters, PreparedVerifyingKey}; use directories::BaseDirs; use pairing::bls12_381::{Bls12, Fr}; +use std::path::Path; use zcash_primitives::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, }; -use std::path::Path; use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, prover::TxProver, diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index e914171..283e76b 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -1,8 +1,6 @@ use bellman::{ gadgets::multipack, - groth16::{ - create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, - }, + groth16::{create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof}, }; use ff::Field; use pairing::bls12_381::{Bls12, Fr};