@ -14,6 +14,45 @@ library EllipticCurveProjective {
uint256 private constant B3 = 21 ;
function projectiveAddMixed (
uint256 X1 ,
uint256 Y1 ,
uint256 Z1 ,
uint256 X2 ,
uint256 Y2
) internal pure returns ( uint256 X3 , uint256 Y3 , uint256 Z3 ) {
/ / We implement the complete addition formula from Renes - Costello - Batina 2015
/ / ( https : / / eprint . iacr . org / 2015 / 1060 Algorithm 8 ) .
/ / X3 = ( X1Y2 + X2Y1 ) ( Y1Y2 − 3 bZ1 ) − 3 b ( Y1 + Y2Z1 ) ( X1 + X2Z1 ) ,
/ / Y3 = ( Y1Y2 + 3 bZ1 ) ( Y1Y2 − 3 bZ1 ) + 9 bX1X2 ( X1 + X2Z1 ) ,
/ / Z3 = ( Y1 + Y2Z1 ) ( Y1Y2 + 3 bZ1 ) + 3 X1X2 ( X1Y2 + X2Y1 ) ,
uint256 t0 = mulmod ( X1 , X2 , P ) ; / / 1 . t0 ← X1 · X2 => ( X1 · X2 )
uint256 t1 = mulmod ( Y1 , Y2 , P ) ; / / 2 . t1 ← Y1 · Y2 => ( Y1 · Y2 )
uint256 t3 = mulmod ( X2 , Y1 , P ) ; / / 3 . t3 ← X2 + Y2 => ( X2 · Y1 )
uint256 t4 = mulmod ( X1 , Y2 , P ) ; / / 4 . t4 ← X1 + Y1 => ( X1 · Y2 )
t3 = addmod ( t3 , t4 , P ) ; / / 5 . t3 ← t3 − t4 => ( X2 · Y1 + X1 · Y2 )
t4 = mulmod ( Y2 , Z1 , P ) ; / / 6 . t4 ← Y2 · Z1 => ( Y2 · Z1 )
t4 = addmod ( t4 , Y1 , P ) ; / / 7 . t4 ← t4 + Y1 => ( Y2 · Z1 + Y1 )
Y3 = mulmod ( X2 , Z1 , P ) ; / / 8 . Y3 ← X2 · Z1 => ( X2 · Z1 )
Y3 = addmod ( Y3 , X1 , P ) ; / / 9 . Y3 ← Y3 + X1 => ( X2 · Z1 + X1 )
t0 = mulmod ( 3 , t0 , P ) ; / / 10 . t0 ← X3 + t0 => ( 3 · ( X1 · X2 ) )
uint256 t2 = mulmod ( B3 , Z1 , P ) ; / / 11 . t2 ← b3 · Z1 => ( b3 · Z1 )
Z3 = addmod ( t1 , t2 , P ) ; / / 12 . Z3 ← t1 + t2 => ( Y1 · Y2 + b · 3 · Z1 )
t1 = addmod ( t1 , P - t2 , P ) ; / / 13 . t1 ← t1 − t2 => ( Y1 · Y2 - b · 3 · Z1 )
Y3 = mulmod ( B3 , Y3 , P ) ; / / 14 . Y3 ← b3 · Y3 => 3 · b · ( X2 · Z1 + X1 )
X3 = mulmod ( t4 , Y3 , P ) ; / / 15 . X3 ← t4 · Y3 => ( Y2 · Z1 + Y1 ) · b · 3 · ( X2 · Z1 + X1 )
t2 = mulmod ( t3 , t1 , P ) ; / / 16 . t2 ← t3 · t1 => ( ( X2 · Y1 + X1 · Y2 ) · ( Y1 · Y2 - b3 · Z1 ) )
X3 = addmod ( t2 , P - X3 , P ) ; / / 17 . X3 ← t2 − X3 => ( ( X2 · Y1 + X1 · Y2 ) · ( Y1 · Y2 - b3 · Z1 ) - 3 · B · ( Y2 · Z1 + Y1 ) · ( X2 · Z1 + X1 ) )
Y3 = mulmod ( Y3 , t0 , P ) ; / / 18 . Y3 ← Y3 · t0 => ( 9 · b · ( X2 · Z1 + X1 ) · X1 · X2 )
t1 = mulmod ( t1 , Z3 , P ) ; / / 19 . t1 ← t1 · Z3 => ( Y1 · Y2 - b · 3 · Z1 ) · ( Y1 · Y2 + b · 3 · Z1 )
Y3 = addmod ( t1 , Y3 , P ) ; / / 20 . Y3 ← t1 + Y3 => ( ( Y1 · Y2 - b · 3 · Z1 ) · ( Y1 · Y2 + 3 · b · Z1 ) + 9 · b · ( X2 · Z1 + X1 ) · X1 · X2 )
t0 = mulmod ( t0 , t3 , P ) ; / / 21 . t0 ← t0 · t3 => ( 3 · X2 · Y1 + ( X2 · Y1 + X1 · Y2 ) )
Z3 = mulmod ( Z3 , t4 , P ) ; / / 22 . Z3 ← Z3 · t4 => ( Y1 · Y2 + b · 3 · Z1 ) · ( Y2 · Z1 + Y1 )
Z3 = addmod ( Z3 , t0 , P ) ; / / 23 . Z3 ← Z3 + t0 => ( ( Y1 · Y2 + b · 3 · Z1 ) · ( Y2 · Z1 + Y1 ) + 3 · X2 · Y1 · ( X2 · Y1 + X1 · Y2 ) )
}
function projectiveAdd (
uint256 X1 ,
uint256 Y1 ,
@ -31,39 +70,39 @@ library EllipticCurveProjective {
/ / TODO : Can we optimize it even more ?
uint256 t0 = mulmod ( X1 , X2 , P ) ; / / 1 . t0 ← X1 · X2 => ( X1 · X2 )
uint256 t1 = mulmod ( Y1 , Y2 , P ) ; / / 2 . t1 ← Y1 · Y2 => ( Y1 · Y2 )
uint256 t2 = mulmod ( Z1 , Z2 , P ) ; / / 3 . t2 ← Z1 · Z2 => ( Z1 · Z2 )
uint256 t3 = addmod ( X1 , Y1 , P ) ; / / 4 . t3 ← X1 + Y1 => ( X1 + Y1 )
uint256 t4 = addmod ( X2 , Y2 , P ) ; / / 5 . t4 ← X2 + Y2 => ( X2 + Y2 )
t3 = mulmod ( t3 , t4 , P ) ; / / 6 . t3 ← t3 · t4 => ( ( X1 + Y1 ) · ( X2 + Y2 ) )
t4 = addmod ( t0 , t1 , P ) ; / / 7 . t4 ← t0 + t1 => ( X1 · X2 + Y1 · Y2 )
t3 = addmod ( t3 , P - t4 , P ) ; / / 8 . t3 ← t3 - t4 => ( ( X1 + Y1 ) · ( X2 + Y2 ) - X1 · X2 - Y1 · Y2 )
t4 = addmod ( Y1 , Z1 , P ) ; / / 9 . t4 ← Y1 + Z1 => ( Y1 + Z1 )
X3 = addmod ( Y2 , Z2 , P ) ; / / 10 . X3 ← Y2 + Z2 => ( Y2 + Z2 )
t4 = mulmod ( t4 , X3 , P ) ; / / 11 . t4 ← t4 · X3 => ( ( Y1 + Z1 ) · ( Y2 + Z2 ) )
X3 = addmod ( t1 , t2 , P ) ; / / 12 . X3 ← t1 + t2 => ( Y1 · Y2 + Z1 · Z2 )
t4 = addmod ( t4 , P - X3 , P ) ; / / 13 . t4 ← t4 - X3 => ( ( Y1 + Z1 ) · ( Y2 + Z2 ) - Y1 · Y2 - Z1 · Z2 )
X3 = addmod ( X1 , Z1 , P ) ; / / 14 . X3 ← X1 + Z1 => ( X1 + Z1 )
Y3 = addmod ( X2 , Z2 , P ) ; / / 15 . Y3 ← X2 + Z2 => ( X2 + Z2 )
X3 = mulmod ( X3 , Y3 , P ) ; / / 16 . X3 ← X3 · Y3 => ( ( X1 + Z1 ) · ( X2 + Z2 ) )
Y3 = addmod ( t0 , t2 , P ) ; / / 17 . Y3 ← t0 + t2 => ( X1 · X2 + Z1 · Z2 )
Y3 = addmod ( X3 , P - Y3 , P ) ; / / 18 . Y3 ← X3 - Y3 => ( ( X1 + Z1 ) · ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 )
X3 = addmod ( t0 , t0 , P ) ; / / 19 . X3 ← t0 + t0 => ( 2 · X1 · X2 )
t0 = addmod ( X3 , t0 , P ) ; / / 20 . t0 ← X3 + t0 => ( 3 · X1 · X2 )
t2 = mulmod ( B3 , t2 , P ) ; / / 21 . t2 ← B3 · t2 => 3 b · Z1 · Z2
Z3 = addmod ( t1 , t2 , P ) ; / / 22 . Z3 ← t1 + t2 => Y1 · Y2 + 3 · b · Z1 · Z2
t1 = addmod ( t1 , P - t2 , P ) ; / / 23 . t1 ← t1 - t2 => Y1 · Y2 - 3 · b · Z1 · Z2
Y3 = mulmod ( B3 , Y3 , P ) ; / / 24 . Y3 ← B3 · Y3 => 3 b · ( ( X1 + Z1 ) ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 )
X3 = mulmod ( t4 , Y3 , P ) ; / / 25 . X3 ← t4 · Y3 => 3 b · ( ( Y1 + Z1 ) ( Y2 + Z2 ) - Y1 · Y2 - Z1 · Z2 ) · ( ( X1 + Z1 ) ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 )
t2 = mulmod ( t3 , t1 , P ) ; / / 26 . t2 ← t3 · t1 => ( ( X1 + Y1 ) ( X2 + Y2 ) - X1 · X2 - Y1 · Y2 ) · ( Y1 · Y2 - 3 · b · Z1 · Z2 )
X3 = addmod ( t2 , P - X3 , P ) ; / / 27 . X3 ← t2 - X3 => ( X1Y2 + X2Y1 ) ( Y1 · Y2 - 3 · b · Z1 · Z2 ) - 3 b ( Y1 · Z2 + Y2 · Z1 ) ( X1 · Z2 + X2 · Z1 )
Y3 = mulmod ( Y3 , t0 , P ) ; / / 28 . Y3 ← Y3 · t0 => 3 · b · ( ( X1 + Z1 ) ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 ) · 3 · X1 · X2 = 9 · b · X1 · X2 · ( X1 · Z2 + X2 · Z1 )
t1 = mulmod ( t1 , Z3 , P ) ; / / 29 . t1 ← t1 · Z3 => ( Y1 · Y2 - 3 · b · Z1 · Z2 ) · ( Y1 · Y2 + 3 · b · Z1 · Z2 )
Y3 = addmod ( t1 , Y3 , P ) ; / / 30 . Y3 ← t1 + Y3 => ( Y1Y2 + 3 · b · Z1 · Z2 ) ( Y1 · Y2 - 3 · b · Z1 · Z2 ) + 9 b · X1 · X2 · ( X1 · Z2 + X2 · Z1 )
t0 = mulmod ( t0 , t3 , P ) ; / / 31 . t0 ← t0 · t3 => ( 3 · X1 · X2 ) · ( ( X1 + Y1 ) ( X2 + Y2 ) - X1 · X2 - Y1 · Y2 )
Z3 = mulmod ( Z3 , t4 , P ) ; / / 32 . Z3 ← Z3 · t4 => ( Y1 · Y2 + 3 · b · Z1 · Z2 ) · ( ( Y1 + Z1 ) ( Y2 + Z2 ) - Y1 · Y2 - Z1 · Z2 )
Z3 = addmod ( Z3 , t0 , P ) ; / / 33 . Z3 ← Z3 + t0 => ( Y1 · Z2 + Y2 · Z1 ) · ( Y1 · Y2 + 3 · b · Z1 · Z2 ) + 3 · X1 · X2 · ( X1 · Y2 + X2 · Y1 )
uint256 t0 = mulmod ( X1 , X2 , P ) ; / / 1 . t0 ← X1 · X2 => ( X1 · X2 )
uint256 t1 = mulmod ( Y1 , Y2 , P ) ; / / 2 . t1 ← Y1 · Y2 => ( Y1 · Y2 )
uint256 t2 = mulmod ( Z1 , Z2 , P ) ; / / 3 . t2 ← Z1 · Z2 => ( Z1 · Z2 )
uint256 t3 = addmod ( X1 , Y1 , P ) ; / / 4 . t3 ← X1 + Y1 => ( X1 + Y1 )
uint256 t4 = addmod ( X2 , Y2 , P ) ; / / 5 . t4 ← X2 + Y2 => ( X2 + Y2 )
t3 = mulmod ( t3 , t4 , P ) ; / / 6 . t3 ← t3 · t4 => ( ( X1 + Y1 ) · ( X2 + Y2 ) )
t4 = addmod ( t0 , t1 , P ) ; / / 7 . t4 ← t0 + t1 => ( X1 · X2 + Y1 · Y2 )
t3 = addmod ( t3 , P - t4 , P ) ; / / 8 . t3 ← t3 - t4 => ( ( X1 + Y1 ) · ( X2 + Y2 ) - X1 · X2 - Y1 · Y2 )
t4 = addmod ( Y1 , Z1 , P ) ; / / 9 . t4 ← Y1 + Z1 => ( Y1 + Z1 )
X3 = addmod ( Y2 , Z2 , P ) ; / / 10 . X3 ← Y2 + Z2 => ( Y2 + Z2 )
t4 = mulmod ( t4 , X3 , P ) ; / / 11 . t4 ← t4 · X3 => ( ( Y1 + Z1 ) · ( Y2 + Z2 ) )
X3 = addmod ( t1 , t2 , P ) ; / / 12 . X3 ← t1 + t2 => ( Y1 · Y2 + Z1 · Z2 )
t4 = addmod ( t4 , P - X3 , P ) ; / / 13 . t4 ← t4 - X3 => ( ( Y1 + Z1 ) · ( Y2 + Z2 ) - Y1 · Y2 - Z1 · Z2 )
X3 = addmod ( X1 , Z1 , P ) ; / / 14 . X3 ← X1 + Z1 => ( X1 + Z1 )
Y3 = addmod ( X2 , Z2 , P ) ; / / 15 . Y3 ← X2 + Z2 => ( X2 + Z2 )
X3 = mulmod ( X3 , Y3 , P ) ; / / 16 . X3 ← X3 · Y3 => ( ( X1 + Z1 ) · ( X2 + Z2 ) )
Y3 = addmod ( t0 , t2 , P ) ; / / 17 . Y3 ← t0 + t2 => ( X1 · X2 + Z1 · Z2 )
Y3 = addmod ( X3 , P - Y3 , P ) ; / / 18 . Y3 ← X3 - Y3 => ( ( X1 + Z1 ) · ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 )
X3 = addmod ( t0 , t0 , P ) ; / / 19 . X3 ← t0 + t0 => ( 2 · X1 · X2 )
t0 = addmod ( X3 , t0 , P ) ; / / 20 . t0 ← X3 + t0 => ( 3 · X1 · X2 )
t2 = mulmod ( B3 , t2 , P ) ; / / 21 . t2 ← B3 · t2 => 3 b · Z1 · Z2
Z3 = addmod ( t1 , t2 , P ) ; / / 22 . Z3 ← t1 + t2 => Y1 · Y2 + 3 · b · Z1 · Z2
t1 = addmod ( t1 , P - t2 , P ) ; / / 23 . t1 ← t1 - t2 => Y1 · Y2 - 3 · b · Z1 · Z2
Y3 = mulmod ( B3 , Y3 , P ) ; / / 24 . Y3 ← B3 · Y3 => 3 b · ( ( X1 + Z1 ) ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 )
X3 = mulmod ( t4 , Y3 , P ) ; / / 25 . X3 ← t4 · Y3 => 3 b · ( ( Y1 + Z1 ) ( Y2 + Z2 ) - Y1 · Y2 - Z1 · Z2 ) · ( ( X1 + Z1 ) ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 )
t2 = mulmod ( t3 , t1 , P ) ; / / 26 . t2 ← t3 · t1 => ( ( X1 + Y1 ) ( X2 + Y2 ) - X1 · X2 - Y1 · Y2 ) · ( Y1 · Y2 - 3 · b · Z1 · Z2 )
X3 = addmod ( t2 , P - X3 , P ) ; / / 27 . X3 ← t2 - X3 => ( X1Y2 + X2Y1 ) ( Y1 · Y2 - 3 · b · Z1 · Z2 ) - 3 b ( Y1 · Z2 + Y2 · Z1 ) ( X1 · Z2 + X2 · Z1 )
Y3 = mulmod ( Y3 , t0 , P ) ; / / 28 . Y3 ← Y3 · t0 => 3 · b · ( ( X1 + Z1 ) ( X2 + Z2 ) - X1 · X2 - Z1 · Z2 ) · 3 · X1 · X2 = 9 · b · X1 · X2 · ( X1 · Z2 + X2 · Z1 )
t1 = mulmod ( t1 , Z3 , P ) ; / / 29 . t1 ← t1 · Z3 => ( Y1 · Y2 - 3 · b · Z1 · Z2 ) · ( Y1 · Y2 + 3 · b · Z1 · Z2 )
Y3 = addmod ( t1 , Y3 , P ) ; / / 30 . Y3 ← t1 + Y3 => ( Y1Y2 + 3 · b · Z1 · Z2 ) ( Y1 · Y2 - 3 · b · Z1 · Z2 ) + 9 b · X1 · X2 · ( X1 · Z2 + X2 · Z1 )
t0 = mulmod ( t0 , t3 , P ) ; / / 31 . t0 ← t0 · t3 => ( 3 · X1 · X2 ) · ( ( X1 + Y1 ) ( X2 + Y2 ) - X1 · X2 - Y1 · Y2 )
Z3 = mulmod ( Z3 , t4 , P ) ; / / 32 . Z3 ← Z3 · t4 => ( Y1 · Y2 + 3 · b · Z1 · Z2 ) · ( ( Y1 + Z1 ) ( Y2 + Z2 ) - Y1 · Y2 - Z1 · Z2 )
Z3 = addmod ( Z3 , t0 , P ) ; / / 33 . Z3 ← Z3 + t0 => ( Y1 · Z2 + Y2 · Z1 ) · ( Y1 · Y2 + 3 · b · Z1 · Z2 ) + 3 · X1 · X2 · ( X1 · Y2 + X2 · Y1 )
}
function projectiveDouble (
@ -80,16 +119,16 @@ library EllipticCurveProjective {
uint256 t0 = mulmod ( Y , Y , P ) ; / / 1 . t0 ← Y · Y => ( Y ² )
Z3 = mulmod ( 8 , t0 , P ) ; / / 2 . Z3 ← t0 + t0 => ( 8 Y ² )
uint256 t1 = mulmod ( Y , Z , P ) ; / / 5 . t1 ← Y · Z => ( YZ )
uint256 t2 = mulmod ( Z , Z , P ) ; / / 6 . t2 ← Z · Z => ( Z ² )
t2 = mulmod ( 21 , t2 , P ) ; / / 7 . t2 ← b3 · t2 => ( 3 bZ ² )
X3 = mulmod ( t2 , Z3 , P ) ; / / 8 . X3 ← t2 · Z3 => ( 3 bZ ² 8 Y ² )
Y3 = addmod ( t0 , t2 , P ) ; / / 9 . Y3 ← t0 + t2 => ( Y ² + 3 bZ ² )
Z3 = mulmod ( t1 , Z3 , P ) ; / / 10 . Z3 ← t1 · Z3 => ( YZ · 8 Y ² = 8 Y ³ Z )
t1 = addmod ( t0 , P - mulmod ( 3 , t2 , P ) , P ) ; / / 11 . t1 ← t0 - ( 3 · t2 ) => ( Y ² - 9 bZ ² )
Y3 = addmod ( X3 , mulmod ( t1 , Y3 , P ) , P ) ; / / 1 2 . Y3 ← t1 · ( t1 · Y3 ) => ( ( Y ² - 9 bZ ² ) · ( Y ² + 3 bZ ² ) )
X3 = mulmod ( t1 , mulmod ( X , Y , P ) , P ) ; / / 1 3 . X3 ← t1 · ( X1 · Y1 ) => ( ( Y ² - 9 bZ ² ) · XY )
X3 = addmod ( X3 , X3 , P ) ; / / 1 4 . X3 ← X3 + X3 => ( ( Y ² - 9 bZ ² ) · 2 XY )
uint256 t1 = mulmod ( Y , Z , P ) ; / / 3 . t1 ← Y · Z => ( YZ )
uint256 t2 = mulmod ( Z , Z , P ) ; / / 4 . t2 ← Z · Z => ( Z ² )
t2 = mulmod ( 21 , t2 , P ) ; / / 5 . t2 ← b3 · t2 => ( 3 bZ ² )
X3 = mulmod ( t2 , Z3 , P ) ; / / 6 . X3 ← t2 · Z3 => ( 3 bZ ² 8 Y ² )
Y3 = addmod ( t0 , t2 , P ) ; / / 7 . Y3 ← t0 + t2 => ( Y ² + 3 bZ ² )
Z3 = mulmod ( t1 , Z3 , P ) ; / / 8 . Z3 ← t1 · Z3 => ( YZ · 8 Y ² = 8 Y ³ Z )
t1 = addmod ( t0 , P - mulmod ( 3 , t2 , P ) , P ) ; / / 9 . t1 ← t0 - ( 3 · t2 ) => ( Y ² - 9 bZ ² )
Y3 = addmod ( X3 , mulmod ( t1 , Y3 , P ) , P ) ; / / 1 0 . Y3 ← t1 · ( t1 · Y3 ) => ( ( Y ² - 9 bZ ² ) · ( Y ² + 3 bZ ² ) )
X3 = mulmod ( t1 , mulmod ( X , Y , P ) , P ) ; / / 1 1 . X3 ← t1 · ( X1 · Y1 ) => ( ( Y ² - 9 bZ ² ) · XY )
X3 = addmod ( X3 , X3 , P ) ; / / 1 2 . X3 ← X3 + X3 => ( ( Y ² - 9 bZ ² ) · 2 XY )
}
function toAffine ( uint256 x , uint256 y , uint256 z ) internal pure returns ( uint256 _x , uint256 _y ) {