update elliptic curve libraries

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2025-10-28 20:03:26 +03:00
parent c66175a577
commit 3c5963eab9
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
2 changed files with 55 additions and 29 deletions

View File

@ -10,6 +10,9 @@ pragma solidity ^0.8.0;
** @author Witnet Foundation ** @author Witnet Foundation
*/ */
library EllipticCurve { library EllipticCurve {
// Pre-computed constant for 2 ** 128 - 1
uint256 private constant U128_MAX = 340282366920938463463374607431768211455;
// Pre-computed constant for 2 ** 255 // Pre-computed constant for 2 ** 255
uint256 private constant U255_MAX_PLUS_1 = uint256 private constant U255_MAX_PLUS_1 =
57896044618658097711785492504343953926634992332820282019728792003956564819968; 57896044618658097711785492504343953926634992332820282019728792003956564819968;

View File

@ -14,8 +14,6 @@ library EllipticCurveProjective {
uint256 public constant P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; uint256 public constant P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;
uint256 public constant N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; uint256 public constant N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
uint256 private constant B3 = 21;
function findMaxBitLength( function findMaxBitLength(
uint256 k1, uint256 k1,
uint256 k2, uint256 k2,
@ -72,9 +70,41 @@ library EllipticCurveProjective {
} }
} }
function mulAddProjectiveSingle(
uint256 x1, uint256 y1, uint256 k1
) internal pure returns (uint256 x2, uint256 y2, uint256 z2) {
// We implement the Straus-Shamir trick described in
// Trading Inversions for Multiplications in Elliptic Curve Cryptography.
// (https://eprint.iacr.org/2003/257.pdf Page 7).
// TODO: handle edge case k1 == 0
uint256 bits = findMaxBitLength(k1, 0, 0, 0);
x2 = 0;
y2 = 1;
z2 = 0;
for (; bits > 0;) {
unchecked { --bits; }
(x2, y2, z2) = projectiveDouble(x2, y2, z2);
uint8 mask;
assembly {
mask := and(shr(bits, k1), 1)
}
if (mask != 0) {
(x2, y2, z2) = projectiveAddMixed(
x2, y2, z2, x1, y1
);
}
}
}
function mulAddProjectivePair( function mulAddProjectivePair(
uint256 x1, uint256 y1, uint256 k1, uint256 x1, uint256 y1, uint256 z1, uint256 k1,
uint256 x2, uint256 y2, uint256 k2 uint256 x2, uint256 y2, uint256 z2, uint256 k2
) internal pure returns (uint256 x3, uint256 y3, uint256 z3) { ) internal pure returns (uint256 x3, uint256 y3, uint256 z3) {
// We implement the Straus-Shamir trick described in // We implement the Straus-Shamir trick described in
// Trading Inversions for Multiplications in Elliptic Curve Cryptography. // Trading Inversions for Multiplications in Elliptic Curve Cryptography.
@ -86,10 +116,10 @@ library EllipticCurveProjective {
uint256[4] memory precomputedYs; uint256[4] memory precomputedYs;
uint256[4] memory precomputedZs; uint256[4] memory precomputedZs;
precomputedXs[1] = x2; precomputedYs[1] = y2; precomputedZs[1] = 1; // 01: P2 precomputedXs[1] = x2; precomputedYs[1] = y2; precomputedZs[1] = z2; // 01: P2
precomputedXs[2] = x1; precomputedYs[2] = y1; precomputedZs[2] = 1; // 10: P1 precomputedXs[2] = x1; precomputedYs[2] = y1; precomputedZs[2] = z1; // 10: P1
(x3, y3, z3) = projectiveAddMixed(x1, y1, 1, x2, y2); // 11: P1+P2 (x3, y3, z3) = projectiveAdd(x1, y1, z1, x2, y2, z2); // 11: P1+P2
precomputedXs[3] = x3; precomputedXs[3] = x3;
precomputedYs[3] = y3; precomputedYs[3] = y3;
precomputedZs[3] = z3; precomputedZs[3] = z3;
@ -111,18 +141,10 @@ library EllipticCurveProjective {
) )
} }
if (mask == 0) { if (mask != 0) {
continue;
}
if (mask == 3) {
(x3, y3, z3) = projectiveAdd( (x3, y3, z3) = projectiveAdd(
x3, y3, z3, precomputedXs[mask], precomputedYs[mask], precomputedZs[mask] x3, y3, z3, precomputedXs[mask], precomputedYs[mask], precomputedZs[mask]
); );
} else {
(x3, y3, z3) = projectiveAddMixed(
x3, y3, z3, precomputedXs[mask], precomputedYs[mask]
);
} }
} }
} }
@ -204,7 +226,7 @@ library EllipticCurveProjective {
uint256 x2, uint256 y2, uint256 k2, uint256 x2, uint256 y2, uint256 k2,
uint256 x3, uint256 y3, uint256 k3, uint256 x3, uint256 y3, uint256 k3,
uint256 x4, uint256 y4, uint256 k4 uint256 x4, uint256 y4, uint256 k4
) internal pure returns (uint256 x5, uint256 y5, uint256 z5) { ) internal pure returns (uint256, uint256, uint256) {
// We implement the Straus-Shamir trick described in // We implement the Straus-Shamir trick described in
// Trading Inversions for Multiplications in Elliptic Curve Cryptography. // Trading Inversions for Multiplications in Elliptic Curve Cryptography.
// (https://eprint.iacr.org/2003/257.pdf Page 7). // (https://eprint.iacr.org/2003/257.pdf Page 7).
@ -267,14 +289,14 @@ library EllipticCurveProjective {
y4 y4
); // 1111: P4+P3+P2+P1 ); // 1111: P4+P3+P2+P1
x5 = 0; x1 = 0;
y5 = 1; y1 = 1;
z5 = 0; uint256 z1 = 0;
for (; bits > 0;) { for (; bits > 0;) {
unchecked { --bits; } unchecked { --bits; }
(x5, y5, z5) = projectiveDouble(x5, y5, z5); (x1, y1, z1) = projectiveDouble(x1, y1, z1);
uint8 mask; uint8 mask;
uint16 bitmask; uint16 bitmask;
@ -300,15 +322,16 @@ library EllipticCurveProjective {
} }
if (bitmask == 1) { if (bitmask == 1) {
(x5, y5, z5) = projectiveAddMixed( (x1, y1, z1) = projectiveAddMixed(
x5, y5, z5, precomputedXs[mask], precomputedYs[mask] x1, y1, z1, precomputedXs[mask], precomputedYs[mask]
); );
} else { } else {
(x5, y5, z5) = projectiveAdd( (x1, y1, z1) = projectiveAdd(
x5, y5, z5, precomputedXs[mask], precomputedYs[mask], precomputedZs[mask] x1, y1, z1, precomputedXs[mask], precomputedYs[mask], precomputedZs[mask]
); );
} }
} }
return (x1, y1, z1);
} }
function projectiveAddMixed( function projectiveAddMixed(
@ -335,10 +358,10 @@ library EllipticCurveProjective {
Y3 = mulmod(X2, Z1, P); // 8. Y3 X2 · Z1 => (X2·Z1) Y3 = mulmod(X2, Z1, P); // 8. Y3 X2 · Z1 => (X2·Z1)
Y3 = addmod(Y3, X1, P); // 9. Y3 Y3 + X1 => (X2·Z1 + X1) Y3 = addmod(Y3, X1, P); // 9. Y3 Y3 + X1 => (X2·Z1 + X1)
t0 = mulmod(3, t0, P); // 10. t0 X3 + t0 => (3·(X1·X2)) t0 = mulmod(3, t0, P); // 10. t0 X3 + t0 => (3·(X1·X2))
uint256 t2 = mulmod(B3, Z1, P); // 11. t2 b3 · Z1 => (b3·Z1) uint256 t2 = mulmod(21, Z1, P); // 11. t2 b3 · Z1 => (b3·Z1)
Z3 = addmod(t1, t2, P); // 12. Z3 t1 + t2 => (Y1·Y2 + b·3·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) 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) Y3 = mulmod(21, 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) 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)) 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)) 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))
@ -385,10 +408,10 @@ library EllipticCurveProjective {
Y3 = addmod(X3, P - Y3, P); // 18. Y3 X3 - Y3 => ((X1 + Z1)·(X2 + Z2) - 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) X3 = addmod(t0, t0, P); // 19. X3 t0 + t0 => (2·X1·X2)
t0 = addmod(X3, t0, P); // 20. t0 X3 + t0 => (3·X1·X2) t0 = addmod(X3, t0, P); // 20. t0 X3 + t0 => (3·X1·X2)
t2 = mulmod(B3, t2, P); // 21. t2 B3 · t2 => 3b · Z1·Z2 t2 = mulmod(21, t2, P); // 21. t2 B3 · t2 => 3b · Z1·Z2
Z3 = addmod(t1, t2, P); // 22. Z3 t1 + t2 => Y1·Y2 + 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 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 => 3b · ((X1+Z1)(X2+Z2) - X1·X2 - Z1·Z2) Y3 = mulmod(21, Y3, P); // 24. Y3 B3 · Y3 => 3b · ((X1+Z1)(X2+Z2) - X1·X2 - Z1·Z2)
X3 = mulmod(t4, Y3, P); // 25. X3 t4 · Y3 => 3b·((Y1+Z1)(Y2+Z2)-Y1·Y2-Z1·Z2) · ((X1+Z1)(X2+Z2)-X1·X2-Z1·Z2) X3 = mulmod(t4, Y3, P); // 25. X3 t4 · Y3 => 3b·((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) 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) - 3b(Y1·Z2+Y2·Z1)(X1·Z2+X2·Z1) X3 = addmod(t2, P - X3, P); // 27. X3 t2 - X3 => (X1Y2+X2Y1)(Y1·Y2-3·b·Z1·Z2) - 3b(Y1·Z2+Y2·Z1)(X1·Z2+X2·Z1)