@@ -33,7 +33,7 @@ pub trait EqGadget<F: Field> {
3333 should_enforce : & Boolean < F > ,
3434 ) -> Result < ( ) , SynthesisError > {
3535 self . is_eq ( & other) ?
36- . conditional_enforce_equal ( & Boolean :: constant ( true ) , should_enforce)
36+ . conditional_enforce_equal ( & Boolean :: TRUE , should_enforce)
3737 }
3838
3939 /// Enforce that `self` and `other` are equal.
@@ -46,7 +46,7 @@ pub trait EqGadget<F: Field> {
4646 /// are encouraged to carefully analyze the efficiency and safety of these.
4747 #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
4848 fn enforce_equal ( & self , other : & Self ) -> Result < ( ) , SynthesisError > {
49- self . conditional_enforce_equal ( other, & Boolean :: constant ( true ) )
49+ self . conditional_enforce_equal ( other, & Boolean :: TRUE )
5050 }
5151
5252 /// If `should_enforce == true`, enforce that `self` and `other` are *not*
@@ -65,7 +65,7 @@ pub trait EqGadget<F: Field> {
6565 should_enforce : & Boolean < F > ,
6666 ) -> Result < ( ) , SynthesisError > {
6767 self . is_neq ( & other) ?
68- . conditional_enforce_equal ( & Boolean :: constant ( true ) , should_enforce)
68+ . conditional_enforce_equal ( & Boolean :: TRUE , should_enforce)
6969 }
7070
7171 /// Enforce that `self` and `other` are *not* equal.
@@ -78,20 +78,23 @@ pub trait EqGadget<F: Field> {
7878 /// are encouraged to carefully analyze the efficiency and safety of these.
7979 #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
8080 fn enforce_not_equal ( & self , other : & Self ) -> Result < ( ) , SynthesisError > {
81- self . conditional_enforce_not_equal ( other, & Boolean :: constant ( true ) )
81+ self . conditional_enforce_not_equal ( other, & Boolean :: TRUE )
8282 }
8383}
8484
8585impl < T : EqGadget < F > + R1CSVar < F > , F : PrimeField > EqGadget < F > for [ T ] {
8686 #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
8787 fn is_eq ( & self , other : & Self ) -> Result < Boolean < F > , SynthesisError > {
8888 assert_eq ! ( self . len( ) , other. len( ) ) ;
89- assert ! ( !self . is_empty( ) ) ;
90- let mut results = Vec :: with_capacity ( self . len ( ) ) ;
91- for ( a, b) in self . iter ( ) . zip ( other) {
92- results. push ( a. is_eq ( b) ?) ;
89+ if self . is_empty ( ) & other. is_empty ( ) {
90+ Ok ( Boolean :: TRUE )
91+ } else {
92+ let mut results = Vec :: with_capacity ( self . len ( ) ) ;
93+ for ( a, b) in self . iter ( ) . zip ( other) {
94+ results. push ( a. is_eq ( b) ?) ;
95+ }
96+ Boolean :: kary_and ( & results)
9397 }
94- Boolean :: kary_and ( & results)
9598 }
9699
97100 #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
@@ -128,3 +131,91 @@ impl<T: EqGadget<F> + R1CSVar<F>, F: PrimeField> EqGadget<F> for [T] {
128131 }
129132 }
130133}
134+
135+ /// This blanket implementation just forwards to the impl on [`[T]`].
136+ impl < T : EqGadget < F > + R1CSVar < F > , F : PrimeField > EqGadget < F > for Vec < T > {
137+ #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
138+ fn is_eq ( & self , other : & Self ) -> Result < Boolean < F > , SynthesisError > {
139+ self . as_slice ( ) . is_eq ( other. as_slice ( ) )
140+ }
141+
142+ #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
143+ fn conditional_enforce_equal (
144+ & self ,
145+ other : & Self ,
146+ condition : & Boolean < F > ,
147+ ) -> Result < ( ) , SynthesisError > {
148+ self . as_slice ( )
149+ . conditional_enforce_equal ( other. as_slice ( ) , condition)
150+ }
151+
152+ #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
153+ fn conditional_enforce_not_equal (
154+ & self ,
155+ other : & Self ,
156+ should_enforce : & Boolean < F > ,
157+ ) -> Result < ( ) , SynthesisError > {
158+ self . as_slice ( )
159+ . conditional_enforce_not_equal ( other. as_slice ( ) , should_enforce)
160+ }
161+ }
162+
163+ /// Dummy impl for `()`.
164+ impl < F : Field > EqGadget < F > for ( ) {
165+ /// Output a `Boolean` value representing whether `self.value() ==
166+ /// other.value()`.
167+ #[ inline]
168+ fn is_eq ( & self , _other : & Self ) -> Result < Boolean < F > , SynthesisError > {
169+ Ok ( Boolean :: TRUE )
170+ }
171+
172+ /// If `should_enforce == true`, enforce that `self` and `other` are equal;
173+ /// else, enforce a vacuously true statement.
174+ ///
175+ /// This is a no-op as `self.is_eq(other)?` is always `true`.
176+ #[ tracing:: instrument( target = "r1cs" , skip( self , _other) ) ]
177+ fn conditional_enforce_equal (
178+ & self ,
179+ _other : & Self ,
180+ _should_enforce : & Boolean < F > ,
181+ ) -> Result < ( ) , SynthesisError > {
182+ Ok ( ( ) )
183+ }
184+
185+ /// Enforce that `self` and `other` are equal.
186+ ///
187+ /// This does not generate any constraints as `self.is_eq(other)?` is always
188+ /// `true`.
189+ #[ tracing:: instrument( target = "r1cs" , skip( self , _other) ) ]
190+ fn enforce_equal ( & self , _other : & Self ) -> Result < ( ) , SynthesisError > {
191+ Ok ( ( ) )
192+ }
193+ }
194+
195+ /// This blanket implementation just forwards to the impl on [`[T]`].
196+ impl < T : EqGadget < F > + R1CSVar < F > , F : PrimeField , const N : usize > EqGadget < F > for [ T ; N ] {
197+ #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
198+ fn is_eq ( & self , other : & Self ) -> Result < Boolean < F > , SynthesisError > {
199+ self . as_slice ( ) . is_eq ( other. as_slice ( ) )
200+ }
201+
202+ #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
203+ fn conditional_enforce_equal (
204+ & self ,
205+ other : & Self ,
206+ condition : & Boolean < F > ,
207+ ) -> Result < ( ) , SynthesisError > {
208+ self . as_slice ( )
209+ . conditional_enforce_equal ( other. as_slice ( ) , condition)
210+ }
211+
212+ #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
213+ fn conditional_enforce_not_equal (
214+ & self ,
215+ other : & Self ,
216+ should_enforce : & Boolean < F > ,
217+ ) -> Result < ( ) , SynthesisError > {
218+ self . as_slice ( )
219+ . conditional_enforce_not_equal ( other. as_slice ( ) , should_enforce)
220+ }
221+ }
0 commit comments