arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/eq.rs
r1cs-std/src/eq.rsRaw
  1use crate::{prelude::*, Vec};
  2use algebra::Field;
  3use r1cs_core::SynthesisError;
  4
  5pub trait EqGadget<F: Field> {
  6    /// Output a `Boolean` value representing whether `self.value() == other.value()`.
  7    fn is_eq(&self, other: &Self) -> Result<Boolean<F>, SynthesisError>;
  8
  9    /// Output a `Boolean` value representing whether `self.value() != other.value()`.
 10    fn is_neq(&self, other: &Self) -> Result<Boolean<F>, SynthesisError> {
 11        Ok(self.is_eq(other)?.not())
 12    }
 13
 14    /// If `should_enforce == true`, enforce that `self` and `other` are equal; else,
 15    /// enforce a vacuously true statement.
 16    fn conditional_enforce_equal(
 17        &self,
 18        other: &Self,
 19        should_enforce: &Boolean<F>,
 20    ) -> Result<(), SynthesisError> {
 21        self.is_eq(&other)?
 22            .conditional_enforce_equal(&Boolean::constant(true), should_enforce)
 23    }
 24
 25    /// Enforce that `self` and `other` are equal.
 26    fn enforce_equal(&self, other: &Self) -> Result<(), SynthesisError> {
 27        self.conditional_enforce_equal(other, &Boolean::constant(true))
 28    }
 29
 30    /// If `should_enforce == true`, enforce that `self` and `other` are not equal; else,
 31    /// enforce a vacuously true statement.
 32    fn conditional_enforce_not_equal(
 33        &self,
 34        other: &Self,
 35        should_enforce: &Boolean<F>,
 36    ) -> Result<(), SynthesisError> {
 37        self.is_neq(&other)?
 38            .conditional_enforce_equal(&Boolean::constant(true), should_enforce)
 39    }
 40
 41    /// Enforce that `self` and `other` are not equal.
 42    fn enforce_not_equal(&self, other: &Self) -> Result<(), SynthesisError> {
 43        self.conditional_enforce_not_equal(other, &Boolean::constant(true))
 44    }
 45}
 46
 47impl<T: EqGadget<F> + R1CSVar<F>, F: Field> EqGadget<F> for [T] {
 48    fn is_eq(&self, other: &Self) -> Result<Boolean<F>, SynthesisError> {
 49        assert_eq!(self.len(), other.len());
 50        assert!(!self.is_empty());
 51        let mut results = Vec::with_capacity(self.len());
 52        for (a, b) in self.iter().zip(other) {
 53            results.push(a.is_eq(b)?);
 54        }
 55        Boolean::kary_and(&results)
 56    }
 57
 58    fn conditional_enforce_equal(
 59        &self,
 60        other: &Self,
 61        condition: &Boolean<F>,
 62    ) -> Result<(), SynthesisError> {
 63        assert_eq!(self.len(), other.len());
 64        for (a, b) in self.iter().zip(other) {
 65            a.conditional_enforce_equal(b, condition)?;
 66        }
 67        Ok(())
 68    }
 69
 70    fn conditional_enforce_not_equal(
 71        &self,
 72        other: &Self,
 73        should_enforce: &Boolean<F>,
 74    ) -> Result<(), SynthesisError> {
 75        assert_eq!(self.len(), other.len());
 76        let some_are_different = self.is_neq(other)?;
 77        if let Some(cs) = some_are_different.cs().or(should_enforce.cs()) {
 78            cs.enforce_constraint(
 79                some_are_different.lc(),
 80                should_enforce.lc(),
 81                should_enforce.lc(),
 82            )
 83        } else {
 84            // `some_are_different` and `should_enforce` are both constants
 85            assert!(some_are_different.value().unwrap());
 86            Ok(())
 87        }
 88    }
 89}
 90
 91pub trait OrEqualsGadget<ConstraintF: Field>
 92where
 93    Self: Sized,
 94{
 95    /// If `should_enforce == true`, enforce that `self` equals
 96    /// (a) `first` (if `cond` is `true`)
 97    /// (b) `second` (if `cond` is `false`)
 98    fn conditional_enforce_equal_or(
 99        &self,
100        cond: &Boolean<ConstraintF>,
101        first: &Self,
102        second: &Self,
103        should_enforce: &Boolean<ConstraintF>,
104    ) -> Result<(), SynthesisError>;
105
106    fn enforce_equal_or(
107        &self,
108        cond: &Boolean<ConstraintF>,
109        first: &Self,
110        second: &Self,
111    ) -> Result<(), SynthesisError> {
112        self.conditional_enforce_equal_or(cond, first, second, &Boolean::Constant(true))
113    }
114}
115
116impl<ConstraintF, T> OrEqualsGadget<ConstraintF> for T
117where
118    ConstraintF: Field,
119    T: Sized + EqGadget<ConstraintF> + CondSelectGadget<ConstraintF>,
120{
121    fn conditional_enforce_equal_or(
122        &self,
123        cond: &Boolean<ConstraintF>,
124        first: &Self,
125        second: &Self,
126        should_enforce: &Boolean<ConstraintF>,
127    ) -> Result<(), SynthesisError> {
128        let match_opt = cond.select(first, second)?;
129        self.conditional_enforce_equal(&match_opt, should_enforce)
130    }
131}