ghost-exodus-draft/test/MathTester.t.sol
Uncle Fatso c66175a577
Shamir-Straus trick for pair and quartet
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2025-10-18 15:48:45 +03:00

210 lines
6.7 KiB
Solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, stdJson, console} from "forge-std/Test.sol";
import {MathTester} from "../src/MathTester.sol";
struct Point {
uint256 k;
bytes32 x;
bytes32 y;
}
contract MathTesterTest is Test {
MathTester public math;
Point[] public points;
function setUp() public {
math = new MathTester();
string memory path = "raw_vectors.json";
string memory json = vm.readFile(path);
bytes memory data = vm.parseJson(json);
points = abi.decode(data, (Point[]));
}
function test_quartet() public view {
uint256 len = points.length - 3;
for (uint256 i; i < len;) {
(uint256 x_p, uint256 y_p, uint256 z_p) = math.mulProjectiveQuartet(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i].k),
uint256(points[i+1].x),
uint256(points[i+1].y),
uint256(points[i+1].k),
uint256(points[i+2].x),
uint256(points[i+2].y),
uint256(points[i+2].k),
uint256(points[i+3].x),
uint256(points[i+3].y),
uint256(points[i+3].k)
);
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
(uint256 x_j, uint256 y_j) = math.mulEcQuartet(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i].k),
uint256(points[i+1].x),
uint256(points[i+1].y),
uint256(points[i+1].k),
uint256(points[i+2].x),
uint256(points[i+2].y),
uint256(points[i+2].k),
uint256(points[i+3].x),
uint256(points[i+3].y),
uint256(points[i+3].k)
);
assertEq(x_p, x_j);
assertEq(y_p, y_j);
assertEq(math.isOnCurve(x_p, y_p), true);
unchecked { ++i; }
}
}
function test_pair() public view {
uint256 len = points.length - 1;
for (uint256 i; i < len;) {
(uint256 x_p, uint256 y_p, uint256 z_p) = math.mulProjectivePair(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i].k),
uint256(points[i+1].x),
uint256(points[i+1].y),
uint256(points[i+1].k)
);
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
(uint256 x_j, uint256 y_j) = math.mulEcPair(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i].k),
uint256(points[i+1].x),
uint256(points[i+1].y),
uint256(points[i+1].k)
);
assertEq(x_p, x_j);
assertEq(y_p, y_j);
assertEq(math.isOnCurve(x_p, y_p), true);
unchecked { ++i; }
}
}
function test_triplet() public view {
uint256 len = points.length - 2;
for (uint256 i; i < len;) {
(uint256 x_p, uint256 y_p, uint256 z_p) = math.mulProjectiveTriplet(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i].k),
uint256(points[i+1].x),
uint256(points[i+1].y),
uint256(points[i+1].k),
uint256(points[i+2].x),
uint256(points[i+2].y),
uint256(points[i+2].k)
);
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
(uint256 x_j, uint256 y_j) = math.mulEcTriplet(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i].k),
uint256(points[i+1].x),
uint256(points[i+1].y),
uint256(points[i+1].k),
uint256(points[i+2].x),
uint256(points[i+2].y),
uint256(points[i+2].k)
);
assertEq(x_p, x_j);
assertEq(y_p, y_j);
assertEq(math.isOnCurve(x_p, y_p), true);
unchecked { ++i; }
}
}
function test_addition() public view {
uint256 len = points.length - 1;
for (uint256 i; i < len;) {
(uint256 x_p, uint256 y_p, uint256 z_p) = math.addProjective(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i+1].x),
uint256(points[i+1].y)
);
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
(uint256 x_j, uint256 y_j, uint256 z_j) = math.addJacobian(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i+1].x),
uint256(points[i+1].y)
);
(x_j, y_j) = math.toAffineJacobian(x_j, y_j, z_j);
assertEq(x_p, x_j);
assertEq(y_p, y_j);
assertEq(math.isOnCurve(x_p, y_p), true);
unchecked { ++i; }
}
}
function test_mixedAddition() public view {
uint256 len = points.length - 1;
for (uint256 i; i < len;) {
(uint256 x_p, uint256 y_p, uint256 z_p) = math.addProjectiveMixed(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i+1].x),
uint256(points[i+1].y)
);
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
(uint256 x_j, uint256 y_j, uint256 z_j) = math.addJacobian(
uint256(points[i].x),
uint256(points[i].y),
uint256(points[i+1].x),
uint256(points[i+1].y)
);
(x_j, y_j) = math.toAffineJacobian(x_j, y_j, z_j);
assertEq(x_p, x_j);
assertEq(y_p, y_j);
assertEq(math.isOnCurve(x_p, y_p), true);
unchecked { ++i; }
}
}
function test_double() public view {
uint256 len = points.length;
for (uint256 i; i < len;) {
(uint256 x_p, uint256 y_p, uint256 z_p) = math.doubleProjective(
uint256(points[i].x),
uint256(points[i].y)
);
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
(uint256 x_j, uint256 y_j, uint256 z_j) = math.doubleJacobian(
uint256(points[i].x),
uint256(points[i].y)
);
(x_j, y_j) = math.toAffineJacobian(x_j, y_j, z_j);
assertEq(x_p, x_j);
assertEq(y_p, y_j);
assertEq(math.isOnCurve(x_p, y_p), true);
unchecked { ++i; }
}
}
}