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}