@@ -6,8 +6,6 @@ use super::{FieldElement, ProjectivePoint, CURVE_EQUATION_B};
66use crate :: { CompressedPoint , EncodedPoint , FieldBytes , Scalar , Secp256k1 } ;
77use core:: ops:: { Mul , Neg } ;
88use elliptic_curve:: {
9- ff:: Field ,
10- generic_array:: arr,
119 group:: { prime:: PrimeCurveAffine , GroupEncoding } ,
1210 sec1:: { self , FromEncodedPoint , ToEncodedPoint } ,
1311 subtle:: { Choice , ConditionallySelectable , ConstantTimeEq , CtOption } ,
@@ -39,9 +37,46 @@ use elliptic_curve::serde::{de, ser, Deserialize, Serialize};
3937#[ derive( Clone , Copy , Debug ) ]
4038#[ cfg_attr( docsrs, doc( cfg( feature = "arithmetic" ) ) ) ]
4139pub struct AffinePoint {
40+ /// x-coordinate
4241 pub ( crate ) x : FieldElement ,
42+
43+ /// y-coordinate
4344 pub ( crate ) y : FieldElement ,
44- pub ( super ) infinity : Choice ,
45+
46+ /// Is this point the point at infinity? 0 = no, 1 = yes
47+ ///
48+ /// This is a proxy for [`Choice`], but uses `u8` instead to permit `const`
49+ /// constructors for `IDENTITY` and `GENERATOR`.
50+ pub ( super ) infinity : u8 ,
51+ }
52+
53+ impl AffinePoint {
54+ /// Additive identity of the group: the point at infinity.
55+ pub const IDENTITY : Self = Self {
56+ x : FieldElement :: ZERO ,
57+ y : FieldElement :: ZERO ,
58+ infinity : 1 ,
59+ } ;
60+
61+ /// Base point of secp256k1.
62+ ///
63+ /// ```text
64+ /// Gₓ = 79be667e f9dcbbac 55a06295 ce870b07 029bfcdb 2dce28d9 59f2815b 16f81798
65+ /// Gᵧ = 483ada77 26a3c465 5da4fbfc 0e1108a8 fd17b448 a6855419 9c47d08f fb10d4b8
66+ /// ```
67+ pub const GENERATOR : Self = Self {
68+ x : FieldElement :: from_bytes_unchecked ( & [
69+ 0x79 , 0xbe , 0x66 , 0x7e , 0xf9 , 0xdc , 0xbb , 0xac , 0x55 , 0xa0 , 0x62 , 0x95 , 0xce , 0x87 ,
70+ 0x0b , 0x07 , 0x02 , 0x9b , 0xfc , 0xdb , 0x2d , 0xce , 0x28 , 0xd9 , 0x59 , 0xf2 , 0x81 , 0x5b ,
71+ 0x16 , 0xf8 , 0x17 , 0x98 ,
72+ ] ) ,
73+ y : FieldElement :: from_bytes_unchecked ( & [
74+ 0x48 , 0x3a , 0xda , 0x77 , 0x26 , 0xa3 , 0xc4 , 0x65 , 0x5d , 0xa4 , 0xfb , 0xfc , 0x0e , 0x11 ,
75+ 0x08 , 0xa8 , 0xfd , 0x17 , 0xb4 , 0x48 , 0xa6 , 0x85 , 0x54 , 0x19 , 0x9c , 0x47 , 0xd0 , 0x8f ,
76+ 0xfb , 0x10 , 0xd4 , 0xb8 ,
77+ ] ) ,
78+ infinity : 0 ,
79+ } ;
4580}
4681
4782impl PrimeCurveAffine for AffinePoint {
@@ -50,38 +85,17 @@ impl PrimeCurveAffine for AffinePoint {
5085
5186 /// Returns the identity of the group: the point at infinity.
5287 fn identity ( ) -> Self {
53- Self {
54- x : FieldElement :: zero ( ) ,
55- y : FieldElement :: zero ( ) ,
56- infinity : Choice :: from ( 1 ) ,
57- }
88+ Self :: IDENTITY
5889 }
5990
60- /// Returns the base point of SECP256k1 .
91+ /// Returns the base point of secp256k1 .
6192 fn generator ( ) -> Self {
62- // SECP256k1 basepoint in affine coordinates:
63- // x = 79be667e f9dcbbac 55a06295 ce870b07 029bfcdb 2dce28d9 59f2815b 16f81798
64- // y = 483ada77 26a3c465 5da4fbfc 0e1108a8 fd17b448 a6855419 9c47d08f fb10d4b8
65- AffinePoint {
66- x : FieldElement :: from_bytes ( & arr ! [ u8 ;
67- 0x79 , 0xbe , 0x66 , 0x7e , 0xf9 , 0xdc , 0xbb , 0xac , 0x55 , 0xa0 , 0x62 , 0x95 , 0xce , 0x87 ,
68- 0x0b , 0x07 , 0x02 , 0x9b , 0xfc , 0xdb , 0x2d , 0xce , 0x28 , 0xd9 , 0x59 , 0xf2 , 0x81 , 0x5b ,
69- 0x16 , 0xf8 , 0x17 , 0x98
70- ] )
71- . unwrap ( ) ,
72- y : FieldElement :: from_bytes ( & arr ! [ u8 ;
73- 0x48 , 0x3a , 0xda , 0x77 , 0x26 , 0xa3 , 0xc4 , 0x65 , 0x5d , 0xa4 , 0xfb , 0xfc , 0x0e , 0x11 ,
74- 0x08 , 0xa8 , 0xfd , 0x17 , 0xb4 , 0x48 , 0xa6 , 0x85 , 0x54 , 0x19 , 0x9c , 0x47 , 0xd0 , 0x8f ,
75- 0xfb , 0x10 , 0xd4 , 0xb8
76- ] )
77- . unwrap ( ) ,
78- infinity : Choice :: from ( 0 ) ,
79- }
93+ Self :: GENERATOR
8094 }
8195
8296 /// Is this point the identity point?
8397 fn is_identity ( & self ) -> Choice {
84- self . infinity
98+ Choice :: from ( self . infinity )
8599 }
86100
87101 /// Convert to curve representation.
@@ -101,7 +115,7 @@ impl ConditionallySelectable for AffinePoint {
101115 AffinePoint {
102116 x : FieldElement :: conditional_select ( & a. x , & b. x , choice) ,
103117 y : FieldElement :: conditional_select ( & a. y , & b. y , choice) ,
104- infinity : Choice :: conditional_select ( & a. infinity , & b. infinity , choice) ,
118+ infinity : u8 :: conditional_select ( & a. infinity , & b. infinity , choice) ,
105119 }
106120 }
107121}
@@ -116,7 +130,7 @@ impl ConstantTimeEq for AffinePoint {
116130
117131impl Default for AffinePoint {
118132 fn default ( ) -> Self {
119- Self :: identity ( )
133+ Self :: IDENTITY
120134 }
121135}
122136
@@ -146,7 +160,7 @@ impl DecompressPoint<Secp256k1> for AffinePoint {
146160 Self {
147161 x,
148162 y : y. normalize ( ) ,
149- infinity : Choice :: from ( 0 ) ,
163+ infinity : 0 ,
150164 }
151165 } )
152166 } )
@@ -189,7 +203,7 @@ impl FromEncodedPoint<Secp256k1> for AffinePoint {
189203 /// `None` value if `encoded_point` is not on the secp256k1 curve.
190204 fn from_encoded_point ( encoded_point : & EncodedPoint ) -> CtOption < Self > {
191205 match encoded_point. coordinates ( ) {
192- sec1:: Coordinates :: Identity => CtOption :: new ( Self :: identity ( ) , 1 . into ( ) ) ,
206+ sec1:: Coordinates :: Identity => CtOption :: new ( Self :: IDENTITY , 1 . into ( ) ) ,
193207 sec1:: Coordinates :: Compact { .. } => {
194208 // TODO(tarcieri): add decompaction support
195209 CtOption :: new ( Self :: default ( ) , 0 . into ( ) )
@@ -206,11 +220,7 @@ impl FromEncodedPoint<Secp256k1> for AffinePoint {
206220 // Check that the point is on the curve
207221 let lhs = ( y * & y) . negate ( 1 ) ;
208222 let rhs = x * & x * & x + & CURVE_EQUATION_B ;
209- let point = AffinePoint {
210- x,
211- y,
212- infinity : Choice :: from ( 0 ) ,
213- } ;
223+ let point = AffinePoint { x, y, infinity : 0 } ;
214224 CtOption :: new ( point, ( lhs + & rhs) . normalizes_to_zero ( ) )
215225 } )
216226 } )
@@ -228,7 +238,7 @@ impl ToEncodedPoint<Secp256k1> for AffinePoint {
228238 compress,
229239 ) ,
230240 & EncodedPoint :: identity ( ) ,
231- self . infinity ,
241+ self . is_identity ( ) ,
232242 )
233243 }
234244}
@@ -369,16 +379,16 @@ mod tests {
369379
370380 #[ test]
371381 fn affine_negation ( ) {
372- let basepoint = AffinePoint :: generator ( ) ;
382+ let basepoint = AffinePoint :: GENERATOR ;
373383 assert_eq ! ( ( -( -basepoint) ) , basepoint) ;
374384 }
375385
376386 #[ test]
377387 fn identity_encoding ( ) {
378388 // This is technically an invalid SEC1 encoding, but is preferable to panicking.
379- assert_eq ! ( [ 0 ; 33 ] , AffinePoint :: identity ( ) . to_bytes( ) . as_slice( ) ) ;
389+ assert_eq ! ( [ 0 ; 33 ] , AffinePoint :: IDENTITY . to_bytes( ) . as_slice( ) ) ;
380390 assert ! ( bool :: from(
381- AffinePoint :: from_bytes( & AffinePoint :: identity ( ) . to_bytes( ) )
391+ AffinePoint :: from_bytes( & AffinePoint :: IDENTITY . to_bytes( ) )
382392 . unwrap( )
383393 . is_identity( )
384394 ) )
0 commit comments