@@ -65,7 +65,7 @@ impl ProjectivePoint {
6565 pub ( crate ) fn from_bytes ( bytes : & [ u8 ] ) -> StmResult < Self > {
6666 let mut projective_point_bytes = [ 0u8 ; 32 ] ;
6767 projective_point_bytes
68- . copy_from_slice ( bytes. get ( ..32 ) . ok_or ( SchnorrSignatureError :: SerializationError ) ?) ;
68+ . copy_from_slice ( bytes. get ( ..32 ) . ok_or ( SchnorrSignatureError :: Serialization ) ?) ;
6969
7070 match JubjubExtended :: from_bytes ( & projective_point_bytes) . into_option ( ) {
7171 Some ( projective_point) => Ok ( Self ( projective_point) ) ,
@@ -145,7 +145,7 @@ impl PrimeOrderProjectivePoint {
145145 pub ( crate ) fn from_bytes ( bytes : & [ u8 ] ) -> StmResult < Self > {
146146 let mut prime_order_projective_point_bytes = [ 0u8 ; 32 ] ;
147147 prime_order_projective_point_bytes
148- . copy_from_slice ( bytes. get ( ..32 ) . ok_or ( SchnorrSignatureError :: SerializationError ) ?) ;
148+ . copy_from_slice ( bytes. get ( ..32 ) . ok_or ( SchnorrSignatureError :: Serialization ) ?) ;
149149
150150 match JubjubSubgroup :: from_bytes ( & prime_order_projective_point_bytes) . into_option ( ) {
151151 Some ( prime_order_projective_point) => Ok ( Self ( prime_order_projective_point) ) ,
@@ -177,12 +177,12 @@ impl Mul<PrimeOrderProjectivePoint> for ScalarFieldElement {
177177
178178#[ cfg( test) ]
179179mod tests {
180+ use rand_chacha:: ChaCha20Rng ;
181+ use rand_core:: SeedableRng ;
182+
180183 use super :: * ;
181184
182185 mod golden {
183- use rand_chacha:: ChaCha20Rng ;
184- use rand_core:: SeedableRng ;
185-
186186 use super :: * ;
187187
188188 const GOLDEN_JSON : & str = r#"[144, 52, 95, 161, 127, 253, 49, 32, 140, 217, 231, 207, 32, 238, 244, 196, 97, 241, 47, 95, 101, 9, 70, 136, 194, 66, 187, 253, 200, 32, 218, 43]"# ;
@@ -207,4 +207,228 @@ mod tests {
207207 assert_eq ! ( golden_serialized, serialized) ;
208208 }
209209 }
210+
211+ mod projective_point_arithmetic {
212+ use super :: * ;
213+
214+ #[ test]
215+ fn test_add ( ) {
216+ let mut rng = ChaCha20Rng :: from_seed ( [ 1u8 ; 32 ] ) ;
217+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
218+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
219+
220+ let point = ProjectivePoint :: hash_to_projective_point ( b"test_point" ) ;
221+ let p1 = scalar1 * point;
222+ let p2 = scalar2 * point;
223+
224+ let result = p1 + p2;
225+
226+ let bytes = result. to_bytes ( ) ;
227+ let recovered = ProjectivePoint :: from_bytes ( & bytes) . unwrap ( ) ;
228+ assert_eq ! ( result, recovered) ;
229+ }
230+
231+ #[ test]
232+ fn test_add_identity ( ) {
233+ let point = ProjectivePoint :: hash_to_projective_point ( b"test_point" ) ;
234+ let identity = ProjectivePoint ( JubjubExtended :: identity ( ) ) ;
235+
236+ let result = point + identity;
237+ assert_eq ! ( result, point) ;
238+ }
239+
240+ #[ test]
241+ fn test_add_commutativity ( ) {
242+ let mut rng = ChaCha20Rng :: from_seed ( [ 2u8 ; 32 ] ) ;
243+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
244+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
245+
246+ let point = ProjectivePoint :: hash_to_projective_point ( b"test_point" ) ;
247+ let p1 = scalar1 * point;
248+ let p2 = scalar2 * point;
249+
250+ assert_eq ! ( p1 + p2, p2 + p1) ;
251+ }
252+
253+ #[ test]
254+ fn test_add_associativity ( ) {
255+ let mut rng = ChaCha20Rng :: from_seed ( [ 3u8 ; 32 ] ) ;
256+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
257+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
258+ let scalar3 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
259+
260+ let point = ProjectivePoint :: hash_to_projective_point ( b"test_point" ) ;
261+ let p1 = scalar1 * point;
262+ let p2 = scalar2 * point;
263+ let p3 = scalar3 * point;
264+
265+ assert_eq ! ( ( p1 + p2) + p3, p1 + ( p2 + p3) ) ;
266+ }
267+
268+ #[ test]
269+ fn test_scalar_mul ( ) {
270+ let mut rng = ChaCha20Rng :: from_seed ( [ 4u8 ; 32 ] ) ;
271+ let scalar = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
272+ let point = ProjectivePoint :: hash_to_projective_point ( b"test_point" ) ;
273+
274+ let result = scalar * point;
275+
276+ let bytes = result. to_bytes ( ) ;
277+ let recovered = ProjectivePoint :: from_bytes ( & bytes) . unwrap ( ) ;
278+ assert_eq ! ( result, recovered) ;
279+ }
280+
281+ #[ test]
282+ fn test_scalar_mul_distributivity_over_point_addition ( ) {
283+ let mut rng = ChaCha20Rng :: from_seed ( [ 5u8 ; 32 ] ) ;
284+ let scalar = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
285+ let point1 = ProjectivePoint :: hash_to_projective_point ( b"test_point_1" ) ;
286+ let point2 = ProjectivePoint :: hash_to_projective_point ( b"test_point_2" ) ;
287+
288+ let left = scalar * ( point1 + point2) ;
289+ let right = ( scalar * point1) + ( scalar * point2) ;
290+
291+ assert_eq ! ( left, right) ;
292+ }
293+
294+ #[ test]
295+ fn test_scalar_mul_associativity ( ) {
296+ let mut rng = ChaCha20Rng :: from_seed ( [ 6u8 ; 32 ] ) ;
297+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
298+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
299+ let point = ProjectivePoint :: hash_to_projective_point ( b"test_point" ) ;
300+
301+ let combined_scalar = scalar1 * scalar2;
302+ let left = combined_scalar * point;
303+ let right = scalar1 * ( scalar2 * point) ;
304+
305+ assert_eq ! ( left, right) ;
306+ }
307+ }
308+
309+ mod prime_order_projective_point_arithmetic {
310+ use super :: * ;
311+
312+ #[ test]
313+ fn test_add ( ) {
314+ let mut rng = ChaCha20Rng :: from_seed ( [ 7u8 ; 32 ] ) ;
315+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
316+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
317+
318+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
319+ let p1 = scalar1 * generator;
320+ let p2 = scalar2 * generator;
321+
322+ let result = p1 + p2;
323+
324+ let bytes = result. to_bytes ( ) ;
325+ let recovered = PrimeOrderProjectivePoint :: from_bytes ( & bytes) . unwrap ( ) ;
326+ assert_eq ! ( result, recovered) ;
327+ }
328+
329+ #[ test]
330+ fn test_add_identity ( ) {
331+ let mut rng = ChaCha20Rng :: from_seed ( [ 8u8 ; 32 ] ) ;
332+ let scalar = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
333+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
334+ let point = scalar * generator;
335+ let identity = PrimeOrderProjectivePoint :: default ( ) ;
336+
337+ let result = point + identity;
338+ assert_eq ! ( result, point) ;
339+ }
340+
341+ #[ test]
342+ fn test_add_commutativity ( ) {
343+ let mut rng = ChaCha20Rng :: from_seed ( [ 9u8 ; 32 ] ) ;
344+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
345+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
346+
347+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
348+ let p1 = scalar1 * generator;
349+ let p2 = scalar2 * generator;
350+
351+ assert_eq ! ( p1 + p2, p2 + p1) ;
352+ }
353+
354+ #[ test]
355+ fn test_add_associativity ( ) {
356+ let mut rng = ChaCha20Rng :: from_seed ( [ 10u8 ; 32 ] ) ;
357+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
358+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
359+ let scalar3 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
360+
361+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
362+ let p1 = scalar1 * generator;
363+ let p2 = scalar2 * generator;
364+ let p3 = scalar3 * generator;
365+
366+ assert_eq ! ( ( p1 + p2) + p3, p1 + ( p2 + p3) ) ;
367+ }
368+
369+ #[ test]
370+ fn test_scalar_mul ( ) {
371+ let mut rng = ChaCha20Rng :: from_seed ( [ 11u8 ; 32 ] ) ;
372+ let scalar = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
373+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
374+
375+ let result = scalar * generator;
376+
377+ let bytes = result. to_bytes ( ) ;
378+ let recovered = PrimeOrderProjectivePoint :: from_bytes ( & bytes) . unwrap ( ) ;
379+ assert_eq ! ( result, recovered) ;
380+ }
381+
382+ #[ test]
383+ fn test_scalar_mul_by_generator ( ) {
384+ let scalar = ScalarFieldElement ( dusk_jubjub:: Fr :: one ( ) ) ;
385+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
386+
387+ let result = scalar * generator;
388+ assert_eq ! ( result, generator) ;
389+ }
390+
391+ #[ test]
392+ fn test_scalar_mul_distributivity_over_point_addition ( ) {
393+ let mut rng = ChaCha20Rng :: from_seed ( [ 12u8 ; 32 ] ) ;
394+ let scalar = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
395+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
396+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
397+
398+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
399+ let point1 = scalar1 * generator;
400+ let point2 = scalar2 * generator;
401+
402+ let left = scalar * ( point1 + point2) ;
403+ let right = ( scalar * point1) + ( scalar * point2) ;
404+
405+ assert_eq ! ( left, right) ;
406+ }
407+
408+ #[ test]
409+ fn test_scalar_mul_associativity ( ) {
410+ let mut rng = ChaCha20Rng :: from_seed ( [ 13u8 ; 32 ] ) ;
411+ let scalar1 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
412+ let scalar2 = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
413+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
414+
415+ let combined_scalar = scalar1 * scalar2;
416+ let left = combined_scalar * generator;
417+ let right = scalar1 * ( scalar2 * generator) ;
418+
419+ assert_eq ! ( left, right) ;
420+ }
421+
422+ #[ test]
423+ fn test_point_on_curve ( ) {
424+ let mut rng = ChaCha20Rng :: from_seed ( [ 14u8 ; 32 ] ) ;
425+ let scalar = ScalarFieldElement :: new_random_nonzero_scalar ( & mut rng) . unwrap ( ) ;
426+ let generator = PrimeOrderProjectivePoint :: create_generator ( ) ;
427+
428+ let point = scalar * generator;
429+
430+ let result = point. is_on_curve ( ) . unwrap ( ) ;
431+ assert_eq ! ( result, point) ;
432+ }
433+ }
210434}
0 commit comments