ark-r1cs-std/r1cs-std/src/eq.rs
r1cs-std/src/eq.rsRaw
1use crate::prelude::*;
2use r1cs_core::{ConstraintSystem, SynthesisError};
3use algebra::Field;
4
5/// If `condition == 1`, then enforces that `self` and `other` are equal;
6/// otherwise, it doesn't enforce anything.
7pub trait ConditionalEqGadget<ConstraintF: Field>: Eq {
8 fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
9 &self,
10 cs: CS,
11 other: &Self,
12 condition: &Boolean,
13 ) -> Result<(), SynthesisError>;
14
15 fn cost() -> usize;
16}
17impl<T: ConditionalEqGadget<ConstraintF>, ConstraintF: Field> ConditionalEqGadget<ConstraintF> for [T] {
18 fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
19 &self,
20 mut cs: CS,
21 other: &Self,
22 condition: &Boolean,
23 ) -> Result<(), SynthesisError> {
24 for (i, (a, b)) in self.iter().zip(other.iter()).enumerate() {
25 let mut cs = cs.ns(|| format!("Iteration {}", i));
26 a.conditional_enforce_equal(&mut cs, b, condition)?;
27 }
28 Ok(())
29 }
30
31 fn cost() -> usize {
32 unimplemented!()
33 }
34}
35
36pub trait EqGadget<ConstraintF: Field>: Eq
37where
38 Self: ConditionalEqGadget<ConstraintF>,
39{
40 fn enforce_equal<CS: ConstraintSystem<ConstraintF>>(
41 &self,
42 cs: CS,
43 other: &Self,
44 ) -> Result<(), SynthesisError> {
45 self.conditional_enforce_equal(cs, other, &Boolean::constant(true))
46 }
47
48 fn cost() -> usize {
49 <Self as ConditionalEqGadget<ConstraintF>>::cost()
50 }
51}
52
53impl<T: EqGadget<ConstraintF>, ConstraintF: Field> EqGadget<ConstraintF> for [T] {}
54
55pub trait NEqGadget<ConstraintF: Field>: Eq {
56 fn enforce_not_equal<CS: ConstraintSystem<ConstraintF>>(
57 &self,
58 cs: CS,
59 other: &Self,
60 ) -> Result<(), SynthesisError>;
61
62 fn cost() -> usize;
63}
64
65pub trait OrEqualsGadget<ConstraintF: Field>
66where
67 Self: Sized,
68{
69 fn enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
70 cs: CS,
71 cond: &Boolean,
72 var: &Self,
73 first: &Self,
74 second: &Self,
75 ) -> Result<(), SynthesisError>;
76
77 fn cost() -> usize;
78}
79
80impl<ConstraintF: Field, T: Sized + ConditionalOrEqualsGadget<ConstraintF>> OrEqualsGadget<ConstraintF> for T {
81 fn enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
82 cs: CS,
83 cond: &Boolean,
84 var: &Self,
85 first: &Self,
86 second: &Self,
87 ) -> Result<(), SynthesisError> {
88 Self::conditional_enforce_equal_or(cs, cond, var, first, second, &Boolean::Constant(true))
89 }
90
91 fn cost() -> usize {
92 <Self as ConditionalOrEqualsGadget<ConstraintF>>::cost()
93 }
94}
95
96pub trait ConditionalOrEqualsGadget<ConstraintF: Field>
97where
98 Self: Sized,
99{
100 fn conditional_enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
101 cs: CS,
102 cond: &Boolean,
103 var: &Self,
104 first: &Self,
105 second: &Self,
106 should_enforce: &Boolean,
107 ) -> Result<(), SynthesisError>;
108
109 fn cost() -> usize;
110}
111
112impl<ConstraintF: Field, T: Sized + ConditionalEqGadget<ConstraintF> + CondSelectGadget<ConstraintF>>
113 ConditionalOrEqualsGadget<ConstraintF> for T
114{
115 fn conditional_enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
116 mut cs: CS,
117 cond: &Boolean,
118 var: &Self,
119 first: &Self,
120 second: &Self,
121 should_enforce: &Boolean,
122 ) -> Result<(), SynthesisError> {
123 let match_opt = Self::conditionally_select(
124 &mut cs.ns(|| "conditional_select_in_or"),
125 cond,
126 first,
127 second,
128 )?;
129 var.conditional_enforce_equal(&mut cs.ns(|| "equals_in_or"), &match_opt, should_enforce)
130 }
131
132 fn cost() -> usize {
133 <Self as ConditionalEqGadget<ConstraintF>>::cost() + <Self as CondSelectGadget<ConstraintF>>::cost()
134 }
135}
136
137