288 lines
9.5 KiB
Solidity
288 lines
9.5 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_single() public view {
|
|
uint256 len = points.length - 1;
|
|
for (uint256 i; i < len;) {
|
|
(uint256 x_p, uint256 y_p, uint256 z_p) = math.mulSingleProjective(
|
|
uint256(points[i].x),
|
|
uint256(points[i].y),
|
|
uint256(points[i].k)
|
|
);
|
|
(x_p, y_p) = math.toAffineProjective(x_p, y_p, z_p);
|
|
|
|
(uint256 x_g, uint256 y_g, uint256 z_g) = math.mulSingleGhost(
|
|
uint256(points[i].x),
|
|
uint256(points[i].y),
|
|
uint256(points[i].k)
|
|
);
|
|
(x_g, y_g) = math.toAffineGhost(x_g, y_g, z_g);
|
|
|
|
(uint256 x_j, uint256 y_j) = math.mulSingleEc(
|
|
uint256(points[i].x),
|
|
uint256(points[i].y),
|
|
uint256(points[i].k)
|
|
);
|
|
|
|
assertEq(x_p, x_j);
|
|
assertEq(x_p, x_g);
|
|
assertEq(y_p, y_j);
|
|
assertEq(y_p, y_g);
|
|
assertEq(math.isOnCurve(x_p, y_p), true);
|
|
assertEq(math.isOnCurveGhost(x_p, y_p), true);
|
|
|
|
unchecked { ++i; }
|
|
}
|
|
}
|
|
|
|
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.mulQuartetProjective(
|
|
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.mulQuartetEc(
|
|
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);
|
|
assertEq(math.isOnCurveGhost(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.mulPairProjective(
|
|
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_g, uint256 y_g, uint256 z_g) = math.mulPairGhost(
|
|
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_g, y_g) = math.toAffineGhost(x_g, y_g, z_g);
|
|
|
|
(uint256 x_j, uint256 y_j) = math.mulPairEc(
|
|
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(x_p, x_g);
|
|
assertEq(y_p, y_j);
|
|
assertEq(y_p, y_g);
|
|
assertEq(math.isOnCurve(x_p, y_p), true);
|
|
assertEq(math.isOnCurveGhost(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.mulTripletProjective(
|
|
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.mulTripletEc(
|
|
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);
|
|
assertEq(math.isOnCurveGhost(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_g, uint256 y_g, uint256 z_g) = math.addGhost(
|
|
uint256(points[i].x),
|
|
uint256(points[i].y),
|
|
uint256(points[i+1].x),
|
|
uint256(points[i+1].y)
|
|
);
|
|
(x_g, y_g) = math.toAffineGhost(x_g, y_g, z_g);
|
|
|
|
(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(x_p, x_g);
|
|
assertEq(y_p, y_j);
|
|
assertEq(y_p, y_g);
|
|
assertEq(math.isOnCurve(x_p, y_p), true);
|
|
assertEq(math.isOnCurveGhost(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.addMixedProjective(
|
|
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_g, uint256 y_g, uint256 z_g) = math.addMixedGhost(
|
|
uint256(points[i].x),
|
|
uint256(points[i].y),
|
|
uint256(points[i+1].x),
|
|
uint256(points[i+1].y)
|
|
);
|
|
(x_g, y_g) = math.toAffineGhost(x_g, y_g, z_g);
|
|
|
|
(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);
|
|
assertEq(math.isOnCurveGhost(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_g, uint256 y_g, uint256 z_g) = math.doubleGhost(
|
|
uint256(points[i].x),
|
|
uint256(points[i].y)
|
|
);
|
|
(x_g, y_g) = math.toAffineProjective(x_g, y_g, z_g);
|
|
|
|
(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(x_p, x_g);
|
|
assertEq(y_p, y_j);
|
|
assertEq(y_p, y_g);
|
|
assertEq(math.isOnCurve(x_p, y_p), true);
|
|
assertEq(math.isOnCurveGhost(x_p, y_p), true);
|
|
|
|
unchecked { ++i; }
|
|
}
|
|
}
|
|
}
|