@@ -383,13 +383,25 @@ impl ProjectivePoint {
383383 let XX = self . X . square ( ) ;
384384 let YY = self . Y . square ( ) ;
385385 let ZZ2 = self . Z . square2 ( ) ;
386- let X_plus_Y = & self . X + & self . Y ;
387- let X_plus_Y_sq = X_plus_Y . square ( ) ;
388386 let YY_plus_XX = & YY + & XX ;
389387 let YY_minus_XX = & YY - & XX ;
390388
389+ cfg_if:: cfg_if! {
390+ if #[ cfg( all( target_os = "zkvm" , target_arch = "riscv32" ) ) ] {
391+ // According to https://en.wikipedia.org/wiki/Edwards_curve#Doubling,
392+ // (x + y)^2 - x^2 - y^2 is used as an optimization for computing 2xy.
393+ // However, multiplication is faster inside the zkvm so we compute
394+ // 2xy directly instead.
395+ let new_x = & ( & FieldElement :: TWO * & self . X ) * & self . Y ;
396+ } else {
397+ let X_plus_Y = & self . X + & self . Y ;
398+ let X_plus_Y_sq = X_plus_Y . square( ) ;
399+ let new_x = & X_plus_Y_sq - & YY_plus_XX ;
400+ }
401+ }
402+
391403 CompletedPoint {
392- X : & X_plus_Y_sq - & YY_plus_XX ,
404+ X : new_x ,
393405 Y : YY_plus_XX ,
394406 Z : YY_minus_XX ,
395407 T : & ZZ2 - & YY_minus_XX ,
@@ -418,7 +430,14 @@ impl<'a, 'b> Add<&'b ProjectiveNielsPoint> for &'a EdwardsPoint {
418430 let MM = & Y_minus_X * & other. Y_minus_X ;
419431 let TT2d = & self . T * & other. T2d ;
420432 let ZZ = & self . Z * & other. Z ;
421- let ZZ2 = & ZZ + & ZZ ;
433+
434+ cfg_if:: cfg_if! {
435+ if #[ cfg( all( target_os = "zkvm" , target_arch = "riscv32" ) ) ] {
436+ let ZZ2 = & FieldElement :: TWO * & ZZ ;
437+ } else {
438+ let ZZ2 = & ZZ + & ZZ ;
439+ }
440+ }
422441
423442 CompletedPoint {
424443 X : & PP - & MM ,
@@ -440,7 +459,14 @@ impl<'a, 'b> Sub<&'b ProjectiveNielsPoint> for &'a EdwardsPoint {
440459 let MP = & Y_minus_X * & other. Y_plus_X ;
441460 let TT2d = & self . T * & other. T2d ;
442461 let ZZ = & self . Z * & other. Z ;
443- let ZZ2 = & ZZ + & ZZ ;
462+
463+ cfg_if:: cfg_if! {
464+ if #[ cfg( all( target_os = "zkvm" , target_arch = "riscv32" ) ) ] {
465+ let ZZ2 = & FieldElement :: TWO * & ZZ ;
466+ } else {
467+ let ZZ2 = & ZZ + & ZZ ;
468+ }
469+ }
444470
445471 CompletedPoint {
446472 X : & PM - & MP ,
@@ -461,7 +487,14 @@ impl<'a, 'b> Add<&'b AffineNielsPoint> for &'a EdwardsPoint {
461487 let PP = & Y_plus_X * & other. y_plus_x ;
462488 let MM = & Y_minus_X * & other. y_minus_x ;
463489 let Txy2d = & self . T * & other. xy2d ;
464- let Z2 = & self . Z + & self . Z ;
490+
491+ cfg_if:: cfg_if! {
492+ if #[ cfg( all( target_os = "zkvm" , target_arch = "riscv32" ) ) ] {
493+ let Z2 = & FieldElement :: TWO * & self . Z ;
494+ } else {
495+ let Z2 = & self . Z + & self . Z ;
496+ }
497+ }
465498
466499 CompletedPoint {
467500 X : & PP - & MM ,
@@ -482,7 +515,14 @@ impl<'a, 'b> Sub<&'b AffineNielsPoint> for &'a EdwardsPoint {
482515 let PM = & Y_plus_X * & other. y_minus_x ;
483516 let MP = & Y_minus_X * & other. y_plus_x ;
484517 let Txy2d = & self . T * & other. xy2d ;
485- let Z2 = & self . Z + & self . Z ;
518+
519+ cfg_if:: cfg_if! {
520+ if #[ cfg( all( target_os = "zkvm" , target_arch = "riscv32" ) ) ] {
521+ let Z2 = & FieldElement :: TWO * & self . Z ;
522+ } else {
523+ let Z2 = & self . Z + & self . Z ;
524+ }
525+ }
486526
487527 CompletedPoint {
488528 X : & PM - & MP ,
0 commit comments