2525 F : FieldVar < P :: BaseField , <P :: BaseField as Field >:: BasePrimeField > ,
2626 for < ' a > & ' a F : FieldOpsBounds < ' a , P :: BaseField , F > ,
2727{
28- pub ( crate ) fn new ( x : F , y : F ) -> Self {
28+ pub fn new ( x : F , y : F ) -> Self {
2929 Self {
3030 x,
3131 y,
@@ -35,13 +35,13 @@ where
3535
3636 /// Converts self into a non-zero projective point.
3737 #[ tracing:: instrument( target = "r1cs" , skip( self ) ) ]
38- pub ( crate ) fn into_projective ( & self ) -> ProjectiveVar < P , F > {
38+ pub fn into_projective ( & self ) -> ProjectiveVar < P , F > {
3939 ProjectiveVar :: new ( self . x . clone ( ) , self . y . clone ( ) , F :: one ( ) )
4040 }
4141
4242 /// Performs an addition without checking that other != ±self.
4343 #[ tracing:: instrument( target = "r1cs" , skip( self , other) ) ]
44- pub ( crate ) fn add_unchecked ( & self , other : & Self ) -> Result < Self , SynthesisError > {
44+ pub fn add_unchecked ( & self , other : & Self ) -> Result < Self , SynthesisError > {
4545 if [ self , other] . is_constant ( ) {
4646 let result =
4747 ( self . value ( ) ?. into_projective ( ) + other. value ( ) ?. into_projective ( ) ) . into_affine ( ) ;
6767 /// Doubles `self`. As this is a prime order curve point,
6868 /// the output is guaranteed to not be the point at infinity.
6969 #[ tracing:: instrument( target = "r1cs" , skip( self ) ) ]
70- pub ( crate ) fn double ( & self ) -> Result < Self , SynthesisError > {
70+ pub fn double ( & self ) -> Result < Self , SynthesisError > {
7171 if [ self ] . is_constant ( ) {
7272 let result = self . value ( ) ?. into_projective ( ) . double ( ) . into_affine ( ) ;
7373 // Panic if the result is zero.
9696 ///
9797 /// This follows the formulae from [\[ELM03\]](https://arxiv.org/abs/math/0208038).
9898 #[ tracing:: instrument( target = "r1cs" , skip( self ) ) ]
99- pub ( crate ) fn double_and_add_unchecked ( & self , other : & Self ) -> Result < Self , SynthesisError > {
99+ pub fn double_and_add_unchecked ( & self , other : & Self ) -> Result < Self , SynthesisError > {
100100 if [ self ] . is_constant ( ) || other. is_constant ( ) {
101101 self . double ( ) ?. add_unchecked ( other)
102102 } else {
@@ -126,7 +126,7 @@ where
126126
127127 /// Doubles `self` in place.
128128 #[ tracing:: instrument( target = "r1cs" , skip( self ) ) ]
129- pub ( crate ) fn double_in_place ( & mut self ) -> Result < ( ) , SynthesisError > {
129+ pub fn double_in_place ( & mut self ) -> Result < ( ) , SynthesisError > {
130130 * self = self . double ( ) ?;
131131 Ok ( ( ) )
132132 }
@@ -169,9 +169,62 @@ where
169169 }
170170}
171171
172+ impl < P , F > EqGadget < <P :: BaseField as Field >:: BasePrimeField > for NonZeroAffineVar < P , F >
173+ where
174+ P : SWModelParameters ,
175+ F : FieldVar < P :: BaseField , <P :: BaseField as Field >:: BasePrimeField > ,
176+ for < ' a > & ' a F : FieldOpsBounds < ' a , P :: BaseField , F > ,
177+ {
178+ #[ tracing:: instrument( target = "r1cs" ) ]
179+ fn is_eq (
180+ & self ,
181+ other : & Self ,
182+ ) -> Result < Boolean < <P :: BaseField as Field >:: BasePrimeField > , SynthesisError > {
183+ let x_equal = self . x . is_eq ( & other. x ) ?;
184+ let y_equal = self . y . is_eq ( & other. y ) ?;
185+ x_equal. and ( & y_equal)
186+ }
187+
188+ #[ inline]
189+ #[ tracing:: instrument( target = "r1cs" ) ]
190+ fn conditional_enforce_equal (
191+ & self ,
192+ other : & Self ,
193+ condition : & Boolean < <P :: BaseField as Field >:: BasePrimeField > ,
194+ ) -> Result < ( ) , SynthesisError > {
195+ let x_equal = self . x . is_eq ( & other. x ) ?;
196+ let y_equal = self . y . is_eq ( & other. y ) ?;
197+ let coordinates_equal = x_equal. and ( & y_equal) ?;
198+ coordinates_equal. conditional_enforce_equal ( & Boolean :: Constant ( true ) , condition) ?;
199+ Ok ( ( ) )
200+ }
201+
202+ #[ inline]
203+ #[ tracing:: instrument( target = "r1cs" ) ]
204+ fn enforce_equal ( & self , other : & Self ) -> Result < ( ) , SynthesisError > {
205+ self . x . enforce_equal ( & other. x ) ?;
206+ self . y . enforce_equal ( & other. y ) ?;
207+ Ok ( ( ) )
208+ }
209+
210+ #[ inline]
211+ #[ tracing:: instrument( target = "r1cs" ) ]
212+ fn conditional_enforce_not_equal (
213+ & self ,
214+ other : & Self ,
215+ condition : & Boolean < <P :: BaseField as Field >:: BasePrimeField > ,
216+ ) -> Result < ( ) , SynthesisError > {
217+ let is_equal = self . is_eq ( other) ?;
218+ is_equal
219+ . and ( condition) ?
220+ . enforce_equal ( & Boolean :: Constant ( false ) )
221+ }
222+ }
223+
172224#[ cfg( test) ]
173225mod test_non_zero_affine {
174226 use crate :: alloc:: AllocVar ;
227+ use crate :: eq:: EqGadget ;
175228 use crate :: fields:: fp:: { AllocatedFp , FpVar } ;
176229 use crate :: groups:: curves:: short_weierstrass:: non_zero_affine:: NonZeroAffineVar ;
177230 use crate :: groups:: curves:: short_weierstrass:: ProjectiveVar ;
@@ -300,4 +353,50 @@ mod test_non_zero_affine {
300353 assert_eq ! ( sum_a. 0 , sum_b. 0 ) ;
301354 assert_eq ! ( sum_a. 1 , sum_b. 1 ) ;
302355 }
356+
357+ #[ test]
358+ fn correctness_test_eq ( ) {
359+ let cs = ConstraintSystem :: < Fq > :: new_ref ( ) ;
360+
361+ let x = FpVar :: Var (
362+ AllocatedFp :: < Fq > :: new_witness ( cs. clone ( ) , || {
363+ Ok ( G1Parameters :: AFFINE_GENERATOR_COEFFS . 0 )
364+ } )
365+ . unwrap ( ) ,
366+ ) ;
367+ let y = FpVar :: Var (
368+ AllocatedFp :: < Fq > :: new_witness ( cs. clone ( ) , || {
369+ Ok ( G1Parameters :: AFFINE_GENERATOR_COEFFS . 1 )
370+ } )
371+ . unwrap ( ) ,
372+ ) ;
373+
374+ let a = NonZeroAffineVar :: < G1Parameters , FpVar < Fq > > :: new ( x, y) ;
375+
376+ let n = 10 ;
377+
378+ let a_multiples: Vec < NonZeroAffineVar < G1Parameters , FpVar < Fq > > > =
379+ std:: iter:: successors ( Some ( a. clone ( ) ) , |acc| Some ( acc. add_unchecked ( & a) . unwrap ( ) ) )
380+ . take ( n)
381+ . collect ( ) ;
382+
383+ let all_equal: Vec < NonZeroAffineVar < G1Parameters , FpVar < Fq > > > = ( 0 ..n / 2 )
384+ . map ( |i| {
385+ a_multiples[ i]
386+ . add_unchecked ( & a_multiples[ n - i - 1 ] )
387+ . unwrap ( )
388+ } )
389+ . collect ( ) ;
390+
391+ for i in 0 ..n - 1 {
392+ a_multiples[ i]
393+ . enforce_not_equal ( & a_multiples[ i + 1 ] )
394+ . unwrap ( ) ;
395+ }
396+ for i in 0 ..all_equal. len ( ) - 1 {
397+ all_equal[ i] . enforce_equal ( & all_equal[ i + 1 ] ) . unwrap ( ) ;
398+ }
399+
400+ assert ! ( cs. is_satisfied( ) . unwrap( ) ) ;
401+ }
303402}
0 commit comments