From d2d1b61d0843196d748be5f71d71662a21c84e4b Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Sat, 29 Aug 2020 13:04:13 -0700 Subject: [PATCH] Refactor NIZK/MT verification to return a bit --- .../src/merkle_tree/constraints.rs | 38 ++++------------- crypto-primitives/src/nizk/constraints.rs | 16 ++----- .../src/nizk/gm17/constraints.rs | 26 ++++++------ .../src/nizk/groth16/constraints.rs | 27 ++++++------ r1cs-std/src/bits/boolean.rs | 8 ++++ r1cs-std/src/eq.rs | 42 ------------------- 6 files changed, 46 insertions(+), 111 deletions(-) diff --git a/crypto-primitives/src/merkle_tree/constraints.rs b/crypto-primitives/src/merkle_tree/constraints.rs index 0ac863e..7a97737 100644 --- a/crypto-primitives/src/merkle_tree/constraints.rs +++ b/crypto-primitives/src/merkle_tree/constraints.rs @@ -30,39 +30,21 @@ where parameters: &CRHGadget::ParametersVar, root: &CRHGadget::OutputVar, leaf: impl ToBytesGadget, - ) -> Result<(), SynthesisError> { - self.conditionally_check_membership(parameters, root, leaf, &Boolean::Constant(true)) - } - - pub fn conditionally_check_membership( - &self, - parameters: &CRHGadget::ParametersVar, - root: &CRHGadget::OutputVar, - leaf: impl ToBytesGadget, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError> { + ) -> Result, SynthesisError> { assert_eq!(self.path.len(), P::HEIGHT - 1); // Check that the hash of the given leaf matches the leaf hash in the membership // proof. let leaf_bits = leaf.to_bytes()?; let leaf_hash = CRHGadget::evaluate(parameters, &leaf_bits)?; - let cs = leaf_hash - .cs() - .or(root.cs()) - .or(should_enforce.cs()) - .unwrap(); + let cs = leaf_hash.cs().or(root.cs()).unwrap(); // Check if leaf is one of the bottom-most siblings. let leaf_is_left = Boolean::new_witness(cs.ns("leaf_is_left"), || { Ok(leaf_hash.value()?.eq(&self.path[0].0.value()?)) })?; - leaf_hash.conditional_enforce_equal_or( - &leaf_is_left, - &self.path[0].0, - &self.path[0].1, - should_enforce, - )?; + let mut result = + leaf_hash.is_eq(&leaf_is_left.select(&self.path[0].0, &self.path[0].1)?)?; // Check levels between leaf level and root. let mut previous_hash = leaf_hash; @@ -77,12 +59,8 @@ where "enforcing that inner hash is correct at i-th level{}", i )); - previous_hash.conditional_enforce_equal_or( - &previous_is_left, - left_hash, - right_hash, - should_enforce, - )?; + let equality_cmp = previous_is_left.select(left_hash, right_hash)?; + result = result.and(&previous_hash.is_eq(&equality_cmp)?)?; drop(ns); previous_hash = @@ -90,7 +68,7 @@ where i += 1; } - root.conditional_enforce_equal(&previous_hash, should_enforce) + result.and(&root.is_eq(&previous_hash)?) } } @@ -235,6 +213,8 @@ mod test { println!("constraints from path: {}", constraints_from_path); let leaf_g: &[_] = leaf_g.as_slice(); cw.check_membership(&crh_parameters, &root, &leaf_g) + .unwrap() + .enforce_equal(&Boolean::TRUE) .unwrap(); if !cs.is_satisfied().unwrap() { satisfied = false; diff --git a/crypto-primitives/src/nizk/constraints.rs b/crypto-primitives/src/nizk/constraints.rs index e727e6e..789749d 100644 --- a/crypto-primitives/src/nizk/constraints.rs +++ b/crypto-primitives/src/nizk/constraints.rs @@ -39,21 +39,11 @@ pub trait NIZKVerifierGadget { verification_key: &Self::VerificationKeyVar, input: impl IntoIterator, proof: &Self::ProofVar, - ) -> Result<(), SynthesisError> { - Self::conditional_verify(verification_key, input, proof, &Boolean::constant(true)) - } - - fn conditional_verify<'a, T: 'a + ToBitsGadget + ?Sized>( - verification_key: &Self::VerificationKeyVar, - input: impl IntoIterator, - proof: &Self::ProofVar, - condition: &Boolean, - ) -> Result<(), SynthesisError>; + ) -> Result, SynthesisError>; - fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( + fn verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( prepared_verification_key: &Self::PreparedVerificationKeyVar, input: impl IntoIterator, proof: &Self::ProofVar, - condition: &Boolean, - ) -> Result<(), SynthesisError>; + ) -> Result, SynthesisError>; } diff --git a/crypto-primitives/src/nizk/gm17/constraints.rs b/crypto-primitives/src/nizk/gm17/constraints.rs index 810f6d4..22260bd 100644 --- a/crypto-primitives/src/nizk/gm17/constraints.rs +++ b/crypto-primitives/src/nizk/gm17/constraints.rs @@ -176,24 +176,20 @@ where }) } - fn conditional_verify<'a, T: 'a + ToBitsGadget + ?Sized>( + fn verify<'a, T: 'a + ToBitsGadget + ?Sized>( vk: &Self::VerificationKeyVar, input: impl IntoIterator, proof: &Self::ProofVar, - condition: &Boolean, - ) -> Result<(), SynthesisError> { + ) -> Result, SynthesisError> { let pvk = vk.prepare()?; - , E::Fq>>::conditional_verify_prepared( - &pvk, input, proof, condition, - ) + , E::Fq>>::verify_prepared(&pvk, input, proof) } - fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( + fn verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( pvk: &Self::PreparedVerificationKeyVar, input: impl IntoIterator, proof: &Self::ProofVar, - condition: &Boolean, - ) -> Result<(), SynthesisError> { + ) -> Result, SynthesisError> { let pvk = pvk.clone(); // e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) * // e(C, H) where psi = \sum_{i=0}^l input_i pvk.query[i] @@ -256,9 +252,7 @@ where let test2 = P::final_exponentiation(&test2_exp)?; let one = P::GTVar::one(); - test1.conditional_enforce_equal(&one, condition)?; - test2.conditional_enforce_equal(&one, condition)?; - Ok(()) + test1.is_eq(&one)?.and(&test2.is_eq(&one)?) } } @@ -506,7 +500,10 @@ mod test { &input_gadgets, &proof_gadget, ) + .unwrap() + .enforce_equal(&Boolean::TRUE) .unwrap(); + if !cs.is_satisfied().unwrap() { println!("========================================================="); println!("Unsatisfied constraints:"); @@ -648,7 +645,8 @@ mod test_recursive { &vk_gadget, &input_gadgets, &proof_gadget, - )?; + )? + .enforce_equal(&Boolean::TRUE)?; Ok(()) } } @@ -752,6 +750,8 @@ mod test_recursive { &input_gadgets, &proof_gadget, ) + .unwrap() + .enforce_equal(&Boolean::TRUE) .unwrap(); if !cs.is_satisfied().unwrap() { println!("========================================================="); diff --git a/crypto-primitives/src/nizk/groth16/constraints.rs b/crypto-primitives/src/nizk/groth16/constraints.rs index c43f30b..9a3b549 100644 --- a/crypto-primitives/src/nizk/groth16/constraints.rs +++ b/crypto-primitives/src/nizk/groth16/constraints.rs @@ -164,24 +164,20 @@ where }) } - fn conditional_verify<'a, T: 'a + ToBitsGadget + ?Sized>( + fn verify<'a, T: 'a + ToBitsGadget + ?Sized>( vk: &Self::VerificationKeyVar, input: impl IntoIterator, proof: &Self::ProofVar, - condition: &Boolean, - ) -> Result<(), SynthesisError> { + ) -> Result, SynthesisError> { let pvk = vk.prepare()?; - , E::Fq>>::conditional_verify_prepared( - &pvk, input, proof, condition, - ) + , E::Fq>>::verify_prepared(&pvk, input, proof) } - fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( + fn verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( pvk: &Self::PreparedVerificationKeyVar, public_inputs: impl IntoIterator, proof: &Self::ProofVar, - condition: &Boolean, - ) -> Result<(), SynthesisError> { + ) -> Result, SynthesisError> { let pvk = pvk.clone(); let g_ic = { @@ -216,10 +212,8 @@ where )? }; - let test = P::final_exponentiation(&test_exp).unwrap(); - - test.conditional_enforce_equal(&pvk.alpha_g1_beta_g2, condition)?; - Ok(()) + let test = P::final_exponentiation(&test_exp)?; + test.is_eq(&pvk.alpha_g1_beta_g2) } } @@ -468,6 +462,8 @@ mod test { &input_gadgets, &proof_gadget, ) + .unwrap() + .enforce_equal(&Boolean::TRUE) .unwrap(); if !cs.is_satisfied().unwrap() { println!("========================================================="); @@ -610,7 +606,8 @@ mod test_recursive { &vk_gadget, &input_gadgets, &proof_gadget, - )?; + )? + .enforce_equal(&Boolean::TRUE)?; Ok(()) } } @@ -714,6 +711,8 @@ mod test_recursive { &input_gadgets, &proof_gadget, ) + .unwrap() + .enforce_equal(&Boolean::TRUE) .unwrap(); if !cs.is_satisfied().unwrap() { println!("========================================================="); diff --git a/r1cs-std/src/bits/boolean.rs b/r1cs-std/src/bits/boolean.rs index 1f23b93..ad56ac6 100644 --- a/r1cs-std/src/bits/boolean.rs +++ b/r1cs-std/src/bits/boolean.rs @@ -7,6 +7,7 @@ use r1cs_core::{lc, ConstraintSystemRef, LinearCombination, Namespace, Synthesis /// Represents a variable in the constraint system which is guaranteed /// to be either zero or one. #[derive(Clone, Debug, Eq, PartialEq)] +#[must_use] pub struct AllocatedBit { variable: Variable, cs: ConstraintSystemRef, @@ -216,6 +217,7 @@ impl CondSelectGadget for AllocatedBit { /// This is a boolean value which may be either a constant or /// an interpretation of an `AllocatedBit`. #[derive(Clone, Debug, Eq, PartialEq)] +#[must_use] pub enum Boolean { /// Existential view of the boolean variable Is(AllocatedBit), @@ -245,6 +247,12 @@ impl R1CSVar for Boolean { } impl Boolean { + /// Returns the constrant `true`. + pub const TRUE: Self = Boolean::Constant(true); + + /// Returns the constrant `false`. + pub const FALSE: Self = Boolean::Constant(false); + pub fn lc(&self) -> LinearCombination { match self { Boolean::Constant(false) => lc!(), diff --git a/r1cs-std/src/eq.rs b/r1cs-std/src/eq.rs index 65075f9..9c8867c 100644 --- a/r1cs-std/src/eq.rs +++ b/r1cs-std/src/eq.rs @@ -87,45 +87,3 @@ impl + R1CSVar, F: Field> EqGadget for [T] { } } } - -pub trait OrEqualsGadget -where - Self: Sized, -{ - /// If `should_enforce == true`, enforce that `self` equals - /// (a) `first` (if `cond` is `true`) - /// (b) `second` (if `cond` is `false`) - fn conditional_enforce_equal_or( - &self, - cond: &Boolean, - first: &Self, - second: &Self, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError>; - - fn enforce_equal_or( - &self, - cond: &Boolean, - first: &Self, - second: &Self, - ) -> Result<(), SynthesisError> { - self.conditional_enforce_equal_or(cond, first, second, &Boolean::Constant(true)) - } -} - -impl OrEqualsGadget for T -where - ConstraintF: Field, - T: Sized + EqGadget + CondSelectGadget, -{ - fn conditional_enforce_equal_or( - &self, - cond: &Boolean, - first: &Self, - second: &Self, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError> { - let match_opt = cond.select(first, second)?; - self.conditional_enforce_equal(&match_opt, should_enforce) - } -}