@@ -35,21 +35,25 @@ pub enum DataType {
3535 U256Data ( ark_ff:: BigInt < 4 > ) ,
3636}
3737
38- /// Represent coordinates by evaluation form (-x/y, 1/y), see more: https://github.com/BitVM/BitVM/issues/213
39- #[ derive( Debug , Clone , Copy ) ]
38+ /// Represent evaluation form (-x/y, 1/y) for G1Affine points , see more: https://github.com/BitVM/BitVM/issues/213
39+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
4040pub struct FqPair {
41- x : ark_bn254:: Fq , // -x/y
42- y : ark_bn254:: Fq , // 1/y
43- pub zero : bool , // true if y is zero
41+ x : ark_bn254:: Fq ,
42+ y : ark_bn254:: Fq ,
4443}
4544
4645impl FqPair {
46+ pub const ZERO : Self = Self {
47+ x : ark_bn254:: Fq :: ZERO ,
48+ y : ark_bn254:: Fq :: ZERO ,
49+ } ;
50+
4751 pub fn new ( x : ark_bn254:: Fq , y : ark_bn254:: Fq ) -> Self {
48- Self {
49- x,
50- y,
51- zero : y == ark_bn254:: Fq :: ZERO ,
52+ if x == ark_bn254:: Fq :: ZERO || y == ark_bn254:: Fq :: ZERO {
53+ assert_eq ! ( x, ark_bn254:: Fq :: ZERO ) ;
54+ assert_eq ! ( y, ark_bn254:: Fq :: ZERO ) ;
5255 }
56+ Self { x, y }
5357 }
5458
5559 pub fn x ( & self ) -> ark_bn254:: Fq {
@@ -61,81 +65,55 @@ impl FqPair {
6165 }
6266
6367 /// Recover the evaluation form to original form.
64- pub fn recover ( & self ) -> Self {
65- if self . zero {
66- if self . x == ark_bn254:: Fq :: ZERO {
67- return Self :: new ( ark_bn254:: Fq :: ZERO , ark_bn254:: Fq :: ZERO ) ;
68- }
69- return Self :: new ( self . x , self . y ) ;
68+ pub fn recover ( & self ) -> ark_bn254:: G1Affine {
69+ if self . y == ark_bn254:: Fq :: ZERO {
70+ return ark_bn254:: G1Affine :: zero ( ) ;
7071 }
71-
7272 let ( nx, ny) = ( self . x , self . y ) ;
73- let y = ny. inverse ( ) . expect ( "ny should be non-zero to recover" ) ;
73+ let y = ny
74+ . inverse ( )
75+ . expect ( "ny must be nonzero for evaluation form" ) ;
7476 let x = -nx * y; // equivalent to -nx / ny⁻¹
75-
76- Self :: new ( x, y)
77+ // Use new_unchecked to get compitiable with generate_segments_using_mock_vk_and_mock_proof.
78+ ark_bn254 :: G1Affine :: new_unchecked ( x, y)
7779 }
7880
7981 pub fn rand < R : Rng + ?Sized > ( rng : & mut R ) -> Self {
8082 let p = ark_bn254:: G1Affine :: rand ( rng) ;
8183 Self :: new ( p. x , p. y )
8284 }
85+
86+ pub fn is_zero ( & self ) -> bool {
87+ * self == Self :: ZERO
88+ }
8389}
8490
8591impl From < ark_bn254:: G1Affine > for FqPair {
8692 fn from ( p : ark_bn254:: G1Affine ) -> Self {
8793 if p. y == ark_bn254:: Fq :: ZERO {
88- return Self {
89- x : p. x ,
90- y : p. y ,
91- zero : true ,
92- } ;
94+ return Self { x : p. x , y : p. y } ;
9395 }
9496 let ( x, y) = ( p. x , p. y ) ;
9597 let ny = y. inverse ( ) . expect ( "y must be nonzero for evaluation form" ) ;
9698 let nx = -( x * ny) ;
97- Self {
98- x : nx,
99- y : ny,
100- zero : false ,
101- }
99+ Self { x : nx, y : ny }
102100 }
103101}
104102
105- //impl From<FqPair> for ark_bn254::G1Affine {
106- // fn from(pi: FqPair) -> Self {
107- // if pi.zero {
108- // if pi.x == ark_bn254::Fq::ZERO {
109- // return ark_bn254::G1Affine::zero();
110- // }
111- // return ark_bn254::G1Affine::new_unchecked(pi.x, pi.y);
112- // }
113- //
114- // let (nx, ny) = (pi.x, pi.y);
115- // let y = ny
116- // .inverse()
117- // .expect("ny must be nonzero for evaluation form");
118- // let x = -nx * y; // equivalent to -nx / ny⁻¹
119- //
120- // ark_bn254::G1Affine::new_unchecked(x, y)
121- // }
122- //}
123-
124103/// Non-G2 Group on E'
125104#[ derive( Debug , Clone , Copy , PartialEq , Hash , Eq ) ]
126105pub struct TwistPoint {
127106 x : ark_bn254:: Fq2 ,
128107 y : ark_bn254:: Fq2 ,
129- pub zero : bool ,
130108}
131109
132110impl TwistPoint {
111+ pub const ZERO : Self = Self {
112+ x : ark_bn254:: Fq2 :: ZERO ,
113+ y : ark_bn254:: Fq2 :: ZERO ,
114+ } ;
133115 pub fn new ( x : ark_bn254:: Fq2 , y : ark_bn254:: Fq2 ) -> Self {
134- Self {
135- x,
136- y,
137- zero : x == ark_bn254:: Fq2 :: ZERO && y == ark_bn254:: Fq2 :: ZERO ,
138- }
116+ Self { x, y }
139117 }
140118
141119 pub fn x ( & self ) -> ark_bn254:: Fq2 {
@@ -146,25 +124,38 @@ impl TwistPoint {
146124 self . y
147125 }
148126
149- pub fn is_zero ( & self ) -> bool {
150- self . zero
151- }
152-
153127 pub fn rand < R : Rng + ?Sized > ( rng : & mut R ) -> Self {
154- let p = ark_bn254:: G2Affine :: rand ( rng) ;
155- Self :: new ( p. x , p. y )
128+ loop {
129+ let x = ark_bn254:: Fq2 :: rand ( rng) ;
130+ let rhs = x * x * x + G2Config :: COEFF_B ;
131+ if let Some ( y) = rhs. sqrt ( ) {
132+ // This (x, y) satisfies the twist curve equation but is *not* subgroup-checked.
133+ let p = ark_bn254:: G2Affine :: new_unchecked ( x, y) ;
134+ assert ! ( p. is_on_curve( ) , "curve equation must hold" ) ;
135+ return TwistPoint :: new ( x, y) ;
136+ }
137+ }
156138 }
157139
158140 /// y^2 = x^3 + b' (b' from E')
159141 pub fn is_on_curve ( & self ) -> bool {
142+ if self . is_zero ( ) {
143+ return true ;
144+ }
145+ let x2 = self . x . square ( ) ;
160146 let y2 = self . y . square ( ) ;
161- let x3b = self . x . square ( ) * self . x + <G2Config as SWCurveConfig >:: COEFF_B ;
147+ let x3b = x2 * self . x + <G2Config as SWCurveConfig >:: COEFF_B ;
162148 y2 == x3b
163149 }
164150
151+ // check if a zero point
152+ pub fn is_zero ( & self ) -> bool {
153+ * self == Self :: ZERO
154+ }
155+
165156 /// Negation
166157 pub fn neg ( & self ) -> Self {
167- if self . zero {
158+ if self . is_zero ( ) {
168159 * self
169160 } else {
170161 Self :: new ( self . x , -self . y )
@@ -173,7 +164,7 @@ impl TwistPoint {
173164
174165 /// Point doubling: (x3, y3) = 2 * (x1, y1)
175166 pub fn double ( & self ) -> Self {
176- if self . zero {
167+ if self . is_zero ( ) {
177168 return * self ;
178169 }
179170
@@ -187,7 +178,6 @@ impl TwistPoint {
187178 return Self {
188179 x : ark_bn254:: Fq2 :: zero ( ) ,
189180 y : ark_bn254:: Fq2 :: zero ( ) ,
190- zero : true ,
191181 } ;
192182 }
193183
@@ -200,10 +190,10 @@ impl TwistPoint {
200190
201191 /// Point addition on E': P3 = P1 + P2
202192 pub fn add ( & self , other : & Self ) -> Self {
203- if self . zero {
193+ if self . is_zero ( ) {
204194 return * other;
205195 }
206- if other. zero {
196+ if other. is_zero ( ) {
207197 return * self ;
208198 }
209199
@@ -217,7 +207,6 @@ impl TwistPoint {
217207 return Self {
218208 x : ark_bn254:: Fq2 :: zero ( ) ,
219209 y : ark_bn254:: Fq2 :: zero ( ) ,
220- zero : true ,
221210 } ;
222211 } else {
223212 return self . double ( ) ;
@@ -234,11 +223,7 @@ impl TwistPoint {
234223
235224impl From < ark_bn254:: G2Affine > for TwistPoint {
236225 fn from ( p : ark_bn254:: G2Affine ) -> Self {
237- Self {
238- x : p. x ,
239- y : p. y ,
240- zero : p. is_zero ( ) ,
241- }
226+ Self { x : p. x , y : p. y }
242227 }
243228}
244229
@@ -419,7 +404,7 @@ impl DataType {
419404 DataType :: U256Data ( f) => CompressedStateObject :: U256 ( f) ,
420405 DataType :: G1Data ( r) => {
421406 let r = r. recover ( ) ;
422- let hash = extern_hash_fps ( vec ! [ r. x( ) , r. y( ) ] ) ;
407+ let hash = extern_hash_fps ( vec ! [ r. x, r. y] ) ;
423408 CompressedStateObject :: Hash ( hash)
424409 }
425410 }
@@ -502,7 +487,7 @@ fn as_hints_scalarelemtype_u256data(elem: ark_ff::BigInt<4>) -> Vec<Hint> {
502487
503488fn as_hints_g1type_g1data ( r : & FqPair ) -> Vec < Hint > {
504489 let r = r. recover ( ) ;
505- let hints = vec ! [ Hint :: Fq ( r. x( ) ) , Hint :: Fq ( r. y( ) ) ] ;
490+ let hints = vec ! [ Hint :: Fq ( r. x) , Hint :: Fq ( r. y) ] ;
506491 hints
507492}
508493
@@ -636,21 +621,16 @@ mod test {
636621
637622 #[ test]
638623 fn test_fq_pair ( ) {
639- let zero = ark_bn254:: G1Affine :: new_unchecked ( ark_bn254 :: Fq :: ZERO , ark_bn254 :: Fq :: ZERO ) ;
624+ let zero = ark_bn254:: G1Affine :: zero ( ) ;
640625 let fp_zero = FqPair :: from ( zero) ;
641- assert ! ( fp_zero. zero) ;
642- assert_eq ! (
643- zero,
644- ark_bn254:: G1Affine :: new_unchecked( fp_zero. x( ) , fp_zero. y( ) )
645- ) ;
626+ assert_eq ! ( zero, fp_zero. recover( ) ) ;
646627
647628 let mut rng = thread_rng ( ) ;
648629 ( 0 ..100 ) . into_iter ( ) . for_each ( |_| {
649630 let random = ark_bn254:: G1Affine :: rand ( & mut rng) ;
650631 let fp_rand = FqPair :: from ( random) ;
651- assert ! ( !fp_rand. zero) ;
652632 let lifted = fp_rand. recover ( ) ;
653- assert_eq ! ( random, ark_bn254 :: G1Affine :: new ( lifted. x ( ) , lifted . y ( ) ) ) ;
633+ assert_eq ! ( random, lifted) ;
654634 } ) ;
655635 }
656636
@@ -691,7 +671,7 @@ mod test {
691671 // P + (-P) = 0
692672 let neg = p. neg ( ) ;
693673 let s3 = p. add ( & neg) ;
694- assert ! ( s3. zero , "P + (-P) should be zero point" ) ;
674+ assert ! ( s3. is_zero ( ) , "P + (-P) should be zero point" ) ;
695675 }
696676
697677 #[ test]
0 commit comments