mirror of
https://github.com/logos-storage/logos-storage-contracts-eth.git
synced 2026-01-12 02:03:11 +00:00
WIP: reorg curves, use witnet as base
Now that curve ops are transactions, need to change up tests so that we can verify the result somehow? https://docs.ethers.io/v5/api/contract/contract/#Contract--write
This commit is contained in:
parent
32ff556691
commit
c0be4e9b1d
@ -1,11 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "./ecc/verifiers/Bn254Verifier.sol";
|
||||
import "./ecc/Verifier.sol";
|
||||
import "./ecc/curves/Bn254.sol";
|
||||
import "./ecc/Types.sol";
|
||||
|
||||
contract Proofs {
|
||||
using Bn254Verifier for Verifier.Proof;
|
||||
using Bn254 for Types.Proof;
|
||||
|
||||
uint256 private immutable period;
|
||||
uint256 private immutable timeout;
|
||||
@ -134,7 +134,7 @@ contract Proofs {
|
||||
return _isProofRequired(id, currentPeriod());
|
||||
}
|
||||
|
||||
function _submitProof(bytes32 id, Verifier.Proof calldata proof) internal {
|
||||
function _submitProof(bytes32 id, Types.Proof calldata proof) internal {
|
||||
require(proof._verifyProof(), "Invalid proof");
|
||||
require(!received[id][currentPeriod()], "Proof already submitted");
|
||||
received[id][currentPeriod()] = true;
|
||||
|
||||
@ -86,7 +86,7 @@ contract Storage is Collateral, Marketplace, Proofs {
|
||||
return _getPointer(id);
|
||||
}
|
||||
|
||||
function submitProof(bytes32 contractId, Verifier.Proof calldata proof) public {
|
||||
function submitProof(bytes32 contractId, Types.Proof calldata proof) public {
|
||||
_submitProof(contractId, proof);
|
||||
}
|
||||
|
||||
|
||||
@ -3,147 +3,150 @@
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "./ecc/curves/Bn254.sol";
|
||||
import "./ecc/Curve.sol";
|
||||
import "./ecc/Types.sol";
|
||||
|
||||
contract TestBn254 {
|
||||
using Bn254 for *;
|
||||
struct VerifyingKey {
|
||||
Curve.G2Point A;
|
||||
Curve.G1Point B;
|
||||
Curve.G2Point C;
|
||||
Curve.G2Point gamma;
|
||||
Curve.G1Point gammaBeta1;
|
||||
Curve.G2Point gammaBeta2;
|
||||
Curve.G2Point Z;
|
||||
Curve.G1Point[] IC;
|
||||
Types.G2Point A;
|
||||
Types.G1Point B;
|
||||
Types.G2Point C;
|
||||
Types.G2Point gamma;
|
||||
Types.G1Point gammaBeta1;
|
||||
Types.G2Point gammaBeta2;
|
||||
Types.G2Point Z;
|
||||
Types.G1Point[] IC;
|
||||
}
|
||||
struct Proof {
|
||||
Curve.G1Point A;
|
||||
Curve.G1Point A_p;
|
||||
Curve.G2Point B;
|
||||
Curve.G1Point B_p;
|
||||
Curve.G1Point C;
|
||||
Curve.G1Point C_p;
|
||||
Curve.G1Point K;
|
||||
Curve.G1Point H;
|
||||
Types.G1Point A;
|
||||
Types.G1Point A_p;
|
||||
Types.G2Point B;
|
||||
Types.G1Point B_p;
|
||||
Types.G1Point C;
|
||||
Types.G1Point C_p;
|
||||
Types.G1Point K;
|
||||
Types.G1Point H;
|
||||
}
|
||||
function f() public view returns (bool) {
|
||||
Curve.G1Point memory p1;
|
||||
Curve.G1Point memory p2;
|
||||
p1.X = 1; p1.Y = 2;
|
||||
p2.X = 1; p2.Y = 2;
|
||||
Curve.G1Point memory explict_sum = Bn254.g1add(p1, p2);
|
||||
Curve.G1Point memory scalar_prod = Bn254.g1mul(p1, 2);
|
||||
return (explict_sum.X == scalar_prod.X &&
|
||||
explict_sum.Y == scalar_prod.Y);
|
||||
function f() public returns (bool) {
|
||||
Types.G1Point memory p1;
|
||||
Types.G1Point memory p2;
|
||||
p1.x = 1; p1.y = 2;
|
||||
p2.x = 1; p2.y = 2;
|
||||
Types.G1Point memory explict_sum = Bn254._add(p1, p2);
|
||||
Types.G1Point memory scalar_prod = Bn254._multiply(p1, 2);
|
||||
return (explict_sum.x == scalar_prod.x &&
|
||||
explict_sum.y == scalar_prod.y);
|
||||
}
|
||||
function g() public view returns (bool) {
|
||||
Curve.G1Point memory x = Bn254.g1add(Bn254.P1(), Bn254.g1neg(Bn254.P1()));
|
||||
function g() public returns (bool) {
|
||||
Types.G1Point memory x = Bn254._add(Bn254._p1Generator(), Bn254._negate(Bn254._p1Generator()));
|
||||
// should be zero
|
||||
return (x.X == 0 && x.Y == 0);
|
||||
return (x.x == 0 && x.y == 0);
|
||||
}
|
||||
function testMul() public view returns (bool) {
|
||||
Curve.G1Point memory p;
|
||||
function testMul() public returns (bool) {
|
||||
Types.G1Point memory p;
|
||||
// @TODO The points here are reported to be not well-formed
|
||||
p.X = 14125296762497065001182820090155008161146766663259912659363835465243039841726;
|
||||
p.Y = 16229134936871442251132173501211935676986397196799085184804749187146857848057;
|
||||
p = Bn254.g1mul(p, 13986731495506593864492662381614386532349950841221768152838255933892789078521);
|
||||
p.x = 14125296762497065001182820090155008161146766663259912659363835465243039841726;
|
||||
p.y = 16229134936871442251132173501211935676986397196799085184804749187146857848057;
|
||||
p = Bn254._multiply(p, 13986731495506593864492662381614386532349950841221768152838255933892789078521);
|
||||
return
|
||||
p.X == 18256332256630856740336504687838346961237861778318632856900758565550522381207 &&
|
||||
p.Y == 6976682127058094634733239494758371323697222088503263230319702770853579280803;
|
||||
p.x == 18256332256630856740336504687838346961237861778318632856900758565550522381207 &&
|
||||
p.y == 6976682127058094634733239494758371323697222088503263230319702770853579280803;
|
||||
}
|
||||
function pair() public view returns (bool) {
|
||||
Curve.G2Point memory fiveTimesP2 = Curve.G2Point(
|
||||
[4540444681147253467785307942530223364530218361853237193970751657229138047649, 20954117799226682825035885491234530437475518021362091509513177301640194298072],
|
||||
[11631839690097995216017572651900167465857396346217730511548857041925508482915, 21508930868448350162258892668132814424284302804699005394342512102884055673846]
|
||||
);
|
||||
// The prime p in the base field F_p for G1
|
||||
uint p = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
Curve.G1Point[] memory g1points = new Curve.G1Point[](2);
|
||||
Curve.G2Point[] memory g2points = new Curve.G2Point[](2);
|
||||
// check e(5 P1, P2)e(-P1, 5 P2) == 1
|
||||
g1points[0] = Bn254.P1().g1mul(5);
|
||||
g1points[1] = Bn254.P1();
|
||||
g1points[1].Y = p - g1points[1].Y;
|
||||
g2points[0] = Bn254.P2();
|
||||
g2points[1] = fiveTimesP2;
|
||||
if (!Bn254.pairing(g1points, g2points))
|
||||
return false;
|
||||
// check e(P1, P2)e(-P1, P2) == 0
|
||||
g1points[0] = Bn254.P1();
|
||||
g1points[1] = Bn254.P1().g1neg();
|
||||
g2points[0] = Bn254.P2();
|
||||
g2points[1] = Bn254.P2();
|
||||
if (!Bn254.pairing(g1points, g2points))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
function _verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.A = Curve.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]);
|
||||
vk.B = Curve.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84);
|
||||
vk.C = Curve.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]);
|
||||
vk.gamma = Curve.G2Point([0x25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1, 0x22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d], [0x065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68, 0x06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb]);
|
||||
vk.gammaBeta1 = Curve.G1Point(0x15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21, 0x14db745c6780e9df549864cec19c2daf4531f6ec0c89cc1c7436cc4d8d300c6d);
|
||||
vk.gammaBeta2 = Curve.G2Point([0x1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e, 0x283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39], [0x140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e, 0x0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4]);
|
||||
vk.Z = Curve.G2Point([0x217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29, 0x0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c], [0x26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855, 0x2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7]);
|
||||
vk.IC = new Curve.G1Point[](10);
|
||||
vk.IC[0] = Curve.G1Point(0x0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a, 0x044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf);
|
||||
vk.IC[1] = Curve.G1Point(0x1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc, 0x2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb);
|
||||
vk.IC[2] = Curve.G1Point(0x1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f, 0x042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db);
|
||||
vk.IC[3] = Curve.G1Point(0x17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5, 0x02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1);
|
||||
vk.IC[4] = Curve.G1Point(0x0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d, 0x0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b);
|
||||
vk.IC[5] = Curve.G1Point(0x232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8, 0x2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7);
|
||||
vk.IC[6] = Curve.G1Point(0x09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe, 0x18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4);
|
||||
vk.IC[7] = Curve.G1Point(0x0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a, 0x18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e);
|
||||
vk.IC[8] = Curve.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e);
|
||||
vk.IC[9] = Curve.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30);
|
||||
}
|
||||
function _verify(uint[] memory input, Proof memory proof) internal view returns (uint) {
|
||||
VerifyingKey memory vk = _verifyingKey();
|
||||
require(input.length + 1 == vk.IC.length);
|
||||
// Compute the linear combination vk_x
|
||||
Curve.G1Point memory vk_x = Curve.G1Point(0, 0);
|
||||
for (uint i = 0; i < input.length; i++)
|
||||
vk_x = Bn254.g1add(vk_x, Bn254.g1mul(vk.IC[i + 1], input[i]));
|
||||
vk_x = Bn254.g1add(vk_x, vk.IC[0]);
|
||||
if (!Bn254.pairingProd2(proof.A, vk.A, Bn254.g1neg(proof.A_p), Bn254.P2())) return 1;
|
||||
if (!Bn254.pairingProd2(vk.B, proof.B, Bn254.g1neg(proof.B_p), Bn254.P2())) return 2;
|
||||
if (!Bn254.pairingProd2(proof.C, vk.C, Bn254.g1neg(proof.C_p), Bn254.P2())) return 3;
|
||||
if (!Bn254.pairingProd3(
|
||||
proof.K, vk.gamma,
|
||||
Bn254.g1neg(Bn254.g1add(vk_x, Bn254.g1add(proof.A, proof.C))), vk.gammaBeta2,
|
||||
Bn254.g1neg(vk.gammaBeta1), proof.B
|
||||
)) return 4;
|
||||
if (!Bn254.pairingProd3(
|
||||
Bn254.g1add(vk_x, proof.A), proof.B,
|
||||
Bn254.g1neg(proof.H), vk.Z,
|
||||
Bn254.g1neg(proof.C), Bn254.P2()
|
||||
)) return 5;
|
||||
return 0;
|
||||
function verifyProof(Types.Proof memory p) public returns (bool) {
|
||||
return p._verifyProof();
|
||||
}
|
||||
// function pair() public view returns (bool) {
|
||||
// Types.G2Point memory fiveTimesP2 = Types.G2Point(
|
||||
// [4540444681147253467785307942530223364530218361853237193970751657229138047649, 20954117799226682825035885491234530437475518021362091509513177301640194298072],
|
||||
// [11631839690097995216017572651900167465857396346217730511548857041925508482915, 21508930868448350162258892668132814424284302804699005394342512102884055673846]
|
||||
// );
|
||||
// // The prime p in the base field F_p for G1
|
||||
// uint p = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
// Types.G1Point[] memory g1points = new Types.G1Point[](2);
|
||||
// Types.G2Point[] memory g2points = new Types.G2Point[](2);
|
||||
// // check e(5 P1, P2)e(-P1, 5 P2) == 1
|
||||
// g1points[0] = Bn254._p1Generator().multiply(5);
|
||||
// g1points[1] = Bn254._p1Generator();
|
||||
// g1points[1].y = p - g1points[1].y;
|
||||
// g2points[0] = Bn254._p2Generator();
|
||||
// g2points[1] = fiveTimesP2;
|
||||
// if (!Bn254.checkPairing(g1points, g2points))
|
||||
// return false;
|
||||
// // check e(P1, P2)e(-P1, P2) == 0
|
||||
// g1points[0] = Bn254._p1Generator();
|
||||
// g1points[1] = Bn254._p1Generator().negate();
|
||||
// g2points[0] = Bn254._p2Generator();
|
||||
// g2points[1] = Bn254._p2Generator();
|
||||
// if (!Bn254.checkPairing(g1points, g2points))
|
||||
// return false;
|
||||
// return true;
|
||||
// }
|
||||
// function _verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
// vk.A = Types.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]);
|
||||
// vk.B = Types.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84);
|
||||
// vk.C = Types.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]);
|
||||
// vk.gamma = Types.G2Point([0x25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1, 0x22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d], [0x065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68, 0x06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb]);
|
||||
// vk.gammaBeta1 = Types.G1Point(0x15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21, 0x14db745c6780e9df549864cec19c2daf4531f6ec0c89cc1c7436cc4d8d300c6d);
|
||||
// vk.gammaBeta2 = Types.G2Point([0x1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e, 0x283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39], [0x140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e, 0x0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4]);
|
||||
// vk.Z = Types.G2Point([0x217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29, 0x0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c], [0x26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855, 0x2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7]);
|
||||
// vk.IC = new Types.G1Point[](10);
|
||||
// vk.IC[0] = Types.G1Point(0x0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a, 0x044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf);
|
||||
// vk.IC[1] = Types.G1Point(0x1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc, 0x2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb);
|
||||
// vk.IC[2] = Types.G1Point(0x1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f, 0x042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db);
|
||||
// vk.IC[3] = Types.G1Point(0x17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5, 0x02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1);
|
||||
// vk.IC[4] = Types.G1Point(0x0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d, 0x0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b);
|
||||
// vk.IC[5] = Types.G1Point(0x232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8, 0x2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7);
|
||||
// vk.IC[6] = Types.G1Point(0x09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe, 0x18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4);
|
||||
// vk.IC[7] = Types.G1Point(0x0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a, 0x18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e);
|
||||
// vk.IC[8] = Types.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e);
|
||||
// vk.IC[9] = Types.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30);
|
||||
// }
|
||||
// function _verify(uint[] memory input, Proof memory proof) internal view returns (uint) {
|
||||
// VerifyingKey memory vk = _verifyingKey();
|
||||
// require(input.length + 1 == vk.IC.length);
|
||||
// // Compute the linear combination vk_x
|
||||
// Types.G1Point memory vk_x = Types.G1Point(0, 0);
|
||||
// for (uint i = 0; i < input.length; i++)
|
||||
// vk_x = Bn254.add(vk_x, Bn254.multiply(vk.IC[i + 1], input[i]));
|
||||
// vk_x = Bn254.add(vk_x, vk.IC[0]);
|
||||
// if (!Bn254.pairingProd2(proof.A, vk.A, Bn254.negate(proof.A_p), Bn254._p2Generator())) return 1;
|
||||
// if (!Bn254.pairingProd2(vk.B, proof.B, Bn254.negate(proof.B_p), Bn254._p2Generator())) return 2;
|
||||
// if (!Bn254.pairingProd2(proof.C, vk.C, Bn254.negate(proof.C_p), Bn254._p2Generator())) return 3;
|
||||
// if (!Bn254.pairingProd3(
|
||||
// proof.K, vk.gamma,
|
||||
// Bn254.negate(Bn254.add(vk_x, Bn254.add(proof.A, proof.C))), vk.gammaBeta2,
|
||||
// Bn254.negate(vk.gammaBeta1), proof.B
|
||||
// )) return 4;
|
||||
// if (!Bn254.pairingProd3(
|
||||
// Bn254.add(vk_x, proof.A), proof.B,
|
||||
// Bn254.negate(proof.H), vk.Z,
|
||||
// Bn254.negate(proof.C), Bn254._p2Generator()
|
||||
// )) return 5;
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
function verifyTx() public view returns (bool r) {
|
||||
uint[] memory input = new uint[](9);
|
||||
Proof memory proof;
|
||||
proof.A = Curve.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497);
|
||||
proof.A_p = Curve.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366);
|
||||
proof.B = Curve.G2Point(
|
||||
[8176651290984905087450403379100573157708110416512446269839297438960217797614, 15588556568726919713003060429893850972163943674590384915350025440408631945055],
|
||||
[15347511022514187557142999444367533883366476794364262773195059233657571533367, 4265071979090628150845437155927259896060451682253086069461962693761322642015]);
|
||||
proof.B_p = Curve.G1Point(2979746655438963305714517285593753729335852012083057917022078236006592638393, 6470627481646078059765266161088786576504622012540639992486470834383274712950);
|
||||
proof.C = Curve.G1Point(6851077925310461602867742977619883934042581405263014789956638244065803308498, 10336382210592135525880811046708757754106524561907815205241508542912494488506);
|
||||
proof.C_p = Curve.G1Point(12491625890066296859584468664467427202390981822868257437245835716136010795448, 13818492518017455361318553880921248537817650587494176379915981090396574171686);
|
||||
proof.H = Curve.G1Point(12091046215835229523641173286701717671667447745509192321596954139357866668225, 14446807589950902476683545679847436767890904443411534435294953056557941441758);
|
||||
proof.K = Curve.G1Point(21341087976609916409401737322664290631992568431163400450267978471171152600502, 2942165230690572858696920423896381470344658299915828986338281196715687693170);
|
||||
input[0] = 13986731495506593864492662381614386532349950841221768152838255933892789078521;
|
||||
input[1] = 622860516154313070522697309645122400675542217310916019527100517240519630053;
|
||||
input[2] = 11094488463398718754251685950409355128550342438297986977413505294941943071569;
|
||||
input[3] = 6627643779954497813586310325594578844876646808666478625705401786271515864467;
|
||||
input[4] = 2957286918163151606545409668133310005545945782087581890025685458369200827463;
|
||||
input[5] = 1384290496819542862903939282897996566903332587607290986044945365745128311081;
|
||||
input[6] = 5613571677741714971687805233468747950848449704454346829971683826953541367271;
|
||||
input[7] = 9643208548031422463313148630985736896287522941726746581856185889848792022807;
|
||||
input[8] = 18066496933330839731877828156604;
|
||||
return _verify(input, proof) == 0;
|
||||
}
|
||||
// function verifyTx() public view returns (bool r) {
|
||||
// uint[] memory input = new uint[](9);
|
||||
// Proof memory proof;
|
||||
// proof.A = Types.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497);
|
||||
// proof.A_p = Types.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366);
|
||||
// proof.B = Types.G2Point(
|
||||
// [8176651290984905087450403379100573157708110416512446269839297438960217797614, 15588556568726919713003060429893850972163943674590384915350025440408631945055],
|
||||
// [15347511022514187557142999444367533883366476794364262773195059233657571533367, 4265071979090628150845437155927259896060451682253086069461962693761322642015]);
|
||||
// proof.B_p = Types.G1Point(2979746655438963305714517285593753729335852012083057917022078236006592638393, 6470627481646078059765266161088786576504622012540639992486470834383274712950);
|
||||
// proof.C = Types.G1Point(6851077925310461602867742977619883934042581405263014789956638244065803308498, 10336382210592135525880811046708757754106524561907815205241508542912494488506);
|
||||
// proof.C_p = Types.G1Point(12491625890066296859584468664467427202390981822868257437245835716136010795448, 13818492518017455361318553880921248537817650587494176379915981090396574171686);
|
||||
// proof.H = Types.G1Point(12091046215835229523641173286701717671667447745509192321596954139357866668225, 14446807589950902476683545679847436767890904443411534435294953056557941441758);
|
||||
// proof.K = Types.G1Point(21341087976609916409401737322664290631992568431163400450267978471171152600502, 2942165230690572858696920423896381470344658299915828986338281196715687693170);
|
||||
// input[0] = 13986731495506593864492662381614386532349950841221768152838255933892789078521;
|
||||
// input[1] = 622860516154313070522697309645122400675542217310916019527100517240519630053;
|
||||
// input[2] = 11094488463398718754251685950409355128550342438297986977413505294941943071569;
|
||||
// input[3] = 6627643779954497813586310325594578844876646808666478625705401786271515864467;
|
||||
// input[4] = 2957286918163151606545409668133310005545945782087581890025685458369200827463;
|
||||
// input[5] = 1384290496819542862903939282897996566903332587607290986044945365745128311081;
|
||||
// input[6] = 5613571677741714971687805233468747950848449704454346829971683826953541367271;
|
||||
// input[7] = 9643208548031422463313148630985736896287522941726746581856185889848792022807;
|
||||
// input[8] = 18066496933330839731877828156604;
|
||||
// return _verify(input, proof) == 0;
|
||||
// }
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "./ecc/verifiers/Bn254Verifier.sol";
|
||||
import "./ecc/Verifier.sol";
|
||||
|
||||
// exposes internal functions of Proofs for testing
|
||||
contract TestBn254Verifier {
|
||||
using Bn254Verifier for Verifier.Proof;
|
||||
function verifyProof(Verifier.Proof memory p) public view returns (bool) {
|
||||
// Proof memory p;
|
||||
// p.q = [
|
||||
// Curve.QElement(i, v),
|
||||
// Curve.QElement(i, v),
|
||||
// Curve.QElement(i, v)
|
||||
// ];
|
||||
// p.mus = [];
|
||||
// p.sigma = Curve.G1Point(x, y);
|
||||
// p.u = [
|
||||
// Curve.G1Point(x, y),
|
||||
// Curve.G1Point(x, y),
|
||||
// Curve.G1Point(x, y)
|
||||
// ];
|
||||
// p.publicKey = Curve.G2Point(
|
||||
// [
|
||||
// 11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
// 10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
// ],
|
||||
// [
|
||||
// 4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||
// 8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
// ]
|
||||
return p._verifyProof();
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ contract TestProofs is Proofs {
|
||||
return _getPointer(id);
|
||||
}
|
||||
|
||||
function submitProof(bytes32 id, Verifier.Proof calldata proof) public {
|
||||
function submitProof(bytes32 id, Types.Proof calldata proof) public {
|
||||
_submitProof(id, proof);
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
library Curve {
|
||||
struct G1Point {
|
||||
uint256 X;
|
||||
uint256 Y;
|
||||
}
|
||||
|
||||
// Encoding of field elements is: X[0] * z + X[1]
|
||||
struct G2Point {
|
||||
uint256[2] X;
|
||||
uint256[2] Y;
|
||||
}
|
||||
}
|
||||
40
contracts/ecc/Types.sol
Normal file
40
contracts/ecc/Types.sol
Normal file
@ -0,0 +1,40 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
library Types {
|
||||
struct G1PointJac {
|
||||
uint256 x;
|
||||
uint256 y;
|
||||
uint256 z;
|
||||
}
|
||||
|
||||
struct G1Point {
|
||||
uint256 x;
|
||||
uint256 y;
|
||||
}
|
||||
|
||||
// Encoding of field elements is: X[0] * z + X[1]
|
||||
struct G2Point {
|
||||
uint256[2] x;
|
||||
uint256[2] y;
|
||||
}
|
||||
|
||||
struct QElement {
|
||||
int64 i;
|
||||
uint256 v;
|
||||
}
|
||||
|
||||
struct Proof {
|
||||
// TODO: should `q` be bounded?
|
||||
QElement[] q;
|
||||
uint256[10] mus;
|
||||
// sigma is probably only the x coordinate
|
||||
// (https://github.com/supranational/blst#serialization-format)
|
||||
G1Point sigma;
|
||||
// TODO: should `u` be bounded?
|
||||
G1Point[] u;
|
||||
bytes name;
|
||||
G2Point publicKey;
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "./Curve.sol";
|
||||
|
||||
library Verifier {
|
||||
struct QElement {
|
||||
int64 i;
|
||||
uint256 v;
|
||||
}
|
||||
|
||||
struct Proof {
|
||||
// TODO: should `q` be bounded?
|
||||
QElement[] q;
|
||||
uint256[10] mus;
|
||||
// sigma is probably only the x coordinate
|
||||
// (https://github.com/supranational/blst#serialization-format)
|
||||
Curve.G1Point sigma;
|
||||
// TODO: should `u` be bounded?
|
||||
Curve.G1Point[] u;
|
||||
bytes name;
|
||||
Curve.G2Point publicKey;
|
||||
}
|
||||
}
|
||||
@ -2,143 +2,24 @@
|
||||
//
|
||||
// From: https://github.com/HarryR/solcrypto/blob/master/contracts/altbn128.sol
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
pragma solidity >=0.7.0 <=0.8.13;
|
||||
|
||||
import "../Curve.sol";
|
||||
import "../Types.sol";
|
||||
import "../vendor/witnet/elliptic-curve-solidity/contracts/EllipticCurve.sol";
|
||||
import "../vendor/witnet/bls-solidity/contracts/BN256G1.sol";
|
||||
import "../vendor/witnet/bls-solidity/contracts/BN256G2.sol";
|
||||
|
||||
library Bn254 {
|
||||
// p = p(u) = 36u^4 + 36u^3 + 24u^2 + 6u + 1
|
||||
uint256 internal constant FIELD_ORDER =
|
||||
0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
|
||||
|
||||
// Number of elements in the field (often called `q`)
|
||||
// n = n(u) = 36u^4 + 36u^3 + 18u^2 + 6u + 1
|
||||
uint256 internal constant GEN_ORDER =
|
||||
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
|
||||
|
||||
uint256 internal constant CURVE_B = 3;
|
||||
|
||||
// a = (p+1) / 4
|
||||
uint256 internal constant CURVE_A =
|
||||
0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52;
|
||||
|
||||
// struct Curve.G1Point {
|
||||
// uint256 X;
|
||||
// uint256 Y;
|
||||
// }
|
||||
|
||||
// // Encoding of field elements is: X[0] * z + X[1]
|
||||
// struct Curve.G2Point {
|
||||
// uint256[2] X;
|
||||
// uint256[2] Y;
|
||||
// }
|
||||
|
||||
// (P+1) / 4
|
||||
function A() internal pure returns (uint256) {
|
||||
return CURVE_A;
|
||||
}
|
||||
|
||||
function B() internal pure returns (uint256) {
|
||||
return CURVE_B;
|
||||
}
|
||||
|
||||
function P() internal pure returns (uint256) {
|
||||
return FIELD_ORDER;
|
||||
}
|
||||
|
||||
function N() internal pure returns (uint256) {
|
||||
return GEN_ORDER;
|
||||
}
|
||||
|
||||
/// @return the generator of G1
|
||||
function P1() internal pure returns (Curve.G1Point memory) {
|
||||
return Curve.G1Point(1, 2);
|
||||
}
|
||||
|
||||
function HashToPoint(uint256 s) internal view returns (Curve.G1Point memory g) {
|
||||
uint256 beta = 0;
|
||||
uint256 y = 0;
|
||||
|
||||
// XXX: Gen Order (n) or Field Order (p) ?
|
||||
uint256 x = s % GEN_ORDER;
|
||||
|
||||
while (true) {
|
||||
(beta, y) = FindYforX(x);
|
||||
|
||||
// y^2 == beta
|
||||
if (beta == mulmod(y, y, FIELD_ORDER)) {
|
||||
return Curve.G1Point(x, y);
|
||||
}
|
||||
|
||||
x = addmod(x, 1, FIELD_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given X, find Y
|
||||
*
|
||||
* where y = sqrt(x^3 + b)
|
||||
*
|
||||
* Returns: (x^3 + b), y
|
||||
*/
|
||||
function FindYforX(uint256 x) internal view returns (uint256, uint256) {
|
||||
// beta = (x^3 + b) % p
|
||||
uint256 beta = addmod(
|
||||
mulmod(mulmod(x, x, FIELD_ORDER), x, FIELD_ORDER),
|
||||
CURVE_B,
|
||||
FIELD_ORDER
|
||||
);
|
||||
|
||||
// y^2 = x^3 + b
|
||||
// this acts like: y = sqrt(beta)
|
||||
uint256 y = expMod(beta, CURVE_A, FIELD_ORDER);
|
||||
|
||||
return (beta, y);
|
||||
}
|
||||
|
||||
// a - b = c;
|
||||
function submod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 a_nn;
|
||||
|
||||
if (a > b) {
|
||||
a_nn = a;
|
||||
} else {
|
||||
a_nn = a + GEN_ORDER;
|
||||
}
|
||||
|
||||
return addmod(a_nn - b, 0, GEN_ORDER);
|
||||
}
|
||||
|
||||
function expMod(
|
||||
uint256 _base,
|
||||
uint256 _exponent,
|
||||
uint256 _modulus
|
||||
) internal view returns (uint256 retval) {
|
||||
bool success;
|
||||
uint256[1] memory output;
|
||||
uint256[6] memory input;
|
||||
input[0] = 0x20; // baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
|
||||
input[1] = 0x20; // expLen = new(big.Int).SetBytes(getData(input, 32, 32))
|
||||
input[2] = 0x20; // modLen = new(big.Int).SetBytes(getData(input, 64, 32))
|
||||
input[3] = _base;
|
||||
input[4] = _exponent;
|
||||
input[5] = _modulus;
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 5, input, 0xc0, output, 0x20)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
require(success);
|
||||
return output[0];
|
||||
function _p1Generator() internal pure returns (Types.G1Point memory) {
|
||||
return Types.G1Point(1, 2);
|
||||
}
|
||||
|
||||
/// @return the generator of G2
|
||||
function P2() internal pure returns (Curve.G2Point memory) {
|
||||
function _p2Generator() internal pure returns (Types.G2Point memory) {
|
||||
return
|
||||
Curve.G2Point(
|
||||
Types.G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
@ -150,185 +31,188 @@ library Bn254 {
|
||||
);
|
||||
}
|
||||
|
||||
/// @return the negation of p, i.e. p.add(p.negate()) should be zero.
|
||||
function g1neg(Curve.G1Point memory p) internal pure returns (Curve.G1Point memory) {
|
||||
// The prime q in the base field F_q for G1
|
||||
uint256 q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
if (p.X == 0 && p.Y == 0) return Curve.G1Point(0, 0);
|
||||
return Curve.G1Point(p.X, q - (p.Y % q));
|
||||
}
|
||||
|
||||
/// @return r the sum of two points of G1
|
||||
function g1add(Curve.G1Point memory p1, Curve.G1Point memory p2)
|
||||
/// @dev computes P + Q
|
||||
/// @param p: G1 point p
|
||||
/// @param q: G1 point q
|
||||
/// @return G1 point with x and y coordinates of P+Q.
|
||||
function _add(Types.G1Point memory p, Types.G1Point memory q)
|
||||
internal
|
||||
view
|
||||
returns (Curve.G1Point memory r)
|
||||
returns (Types.G1Point memory)
|
||||
{
|
||||
uint256[4] memory input;
|
||||
input[0] = p1.X;
|
||||
input[1] = p1.Y;
|
||||
input[2] = p2.X;
|
||||
input[3] = p2.Y;
|
||||
bool success;
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
require(success);
|
||||
(uint256 x, uint256 y) = BN256G1._add([p.x, p.y, q.x, q.y]);
|
||||
return Types.G1Point(x, y);
|
||||
}
|
||||
|
||||
/// @return r the product of a point on G1 and a scalar, i.e.
|
||||
/// p == p.mul(1) and p.add(p) == p.mul(2) for all points p.
|
||||
function g1mul(Curve.G1Point memory p, uint256 s)
|
||||
/// @dev computes P*k.
|
||||
/// @param p: G1 point p
|
||||
/// @param k: scalar k.
|
||||
/// @return G1 point with x and y coordinates of P*k.
|
||||
function _multiply(Types.G1Point memory p, uint256 k)
|
||||
internal
|
||||
view
|
||||
returns (Curve.G1Point memory r)
|
||||
returns (Types.G1Point memory)
|
||||
{
|
||||
uint256[3] memory input;
|
||||
input[0] = p.X;
|
||||
input[1] = p.Y;
|
||||
input[2] = s;
|
||||
bool success;
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
require(success);
|
||||
(uint256 x, uint256 y) = BN256G1._multiply([p.x, p.y, k]);
|
||||
return Types.G1Point(x, y);
|
||||
}
|
||||
|
||||
/// @return the result of computing the pairing check
|
||||
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||
/// return true.
|
||||
function pairing(Curve.G1Point[] memory p1, Curve.G2Point[] memory p2)
|
||||
|
||||
/// @dev Check whether point (x,y) is on curve BN254.
|
||||
/// @param p1 G1 point
|
||||
/// @return true if x,y in the curve, false else
|
||||
function _isOnCurve(Types.G1Point memory p1)
|
||||
internal
|
||||
view
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
require(p1.length == p2.length);
|
||||
uint256 elements = p1.length;
|
||||
uint256 inputSize = elements * 6;
|
||||
uint256[] memory input = new uint256[](inputSize);
|
||||
for (uint256 i = 0; i < elements; i++) {
|
||||
input[i * 6 + 0] = p1[i].X;
|
||||
input[i * 6 + 1] = p1[i].Y;
|
||||
input[i * 6 + 2] = p2[i].X[0];
|
||||
input[i * 6 + 3] = p2[i].X[1];
|
||||
input[i * 6 + 4] = p2[i].Y[0];
|
||||
input[i * 6 + 5] = p2[i].Y[1];
|
||||
}
|
||||
uint256[1] memory out;
|
||||
bool success;
|
||||
assembly {
|
||||
success := staticcall(
|
||||
sub(gas(), 2000),
|
||||
8,
|
||||
add(input, 0x20),
|
||||
mul(inputSize, 0x20),
|
||||
out,
|
||||
0x20
|
||||
)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success
|
||||
case 0 {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
require(success);
|
||||
return out[0] != 0;
|
||||
return BN256G1._isOnCurve([p1.x, p1.y]);
|
||||
}
|
||||
/**
|
||||
* @notice Checks if FQ2 is on G2
|
||||
* @param p1 G2 Point
|
||||
* @return True if the FQ2 is on G2
|
||||
*/
|
||||
function _isOnCurve(Types.G2Point memory p1)
|
||||
internal
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
return BN256G2._isOnCurve(p1.x[0], p1.y[0], p1.x[1], p1.y[1]);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for two pairs.
|
||||
function pairingProd2(
|
||||
Curve.G1Point memory a1,
|
||||
Curve.G2Point memory a2,
|
||||
Curve.G1Point memory b1,
|
||||
Curve.G2Point memory b2
|
||||
) internal view returns (bool) {
|
||||
Curve.G1Point[] memory p1 = new Curve.G1Point[](2);
|
||||
Curve.G2Point[] memory p2 = new Curve.G2Point[](2);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
return pairing(p1, p2);
|
||||
/// @dev Derives the y coordinate from a compressed-format point x [[SEC-1]](https://www.secg.org/SEC1-Ver-1.0.pdf).
|
||||
/// @param prefix parity byte (0x02 even, 0x03 odd)
|
||||
/// @param x coordinate x
|
||||
/// @return y coordinate y
|
||||
function _deriveY(uint8 prefix, uint256 x)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return BN256G1._deriveY(prefix, x);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for three pairs.
|
||||
function pairingProd3(
|
||||
Curve.G1Point memory a1,
|
||||
Curve.G2Point memory a2,
|
||||
Curve.G1Point memory b1,
|
||||
Curve.G2Point memory b2,
|
||||
Curve.G1Point memory c1,
|
||||
Curve.G2Point memory c2
|
||||
) internal view returns (bool) {
|
||||
Curve.G1Point[] memory p1 = new Curve.G1Point[](3);
|
||||
Curve.G2Point[] memory p2 = new Curve.G2Point[](3);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
return pairing(p1, p2);
|
||||
/// @dev Calculate inverse (x, -y) of point (x, y).
|
||||
/// @param p1 G1 point
|
||||
/// @return (x, -y)
|
||||
function _negate(Types.G1Point memory p1)
|
||||
internal
|
||||
pure
|
||||
returns (Types.G1Point memory)
|
||||
{
|
||||
(uint256 x, uint256 y) = EllipticCurve.ecInv(p1.x, p1.y, BN256G1.PP);
|
||||
return Types.G1Point(x, y);
|
||||
}
|
||||
|
||||
/// Convenience method for a pairing check for four pairs.
|
||||
function pairingProd4(
|
||||
Curve.G1Point memory a1,
|
||||
Curve.G2Point memory a2,
|
||||
Curve.G1Point memory b1,
|
||||
Curve.G2Point memory b2,
|
||||
Curve.G1Point memory c1,
|
||||
Curve.G2Point memory c2,
|
||||
Curve.G1Point memory d1,
|
||||
Curve.G2Point memory d2
|
||||
) internal view returns (bool) {
|
||||
Curve.G1Point[] memory p1 = new Curve.G1Point[](4);
|
||||
Curve.G2Point[] memory p2 = new Curve.G2Point[](4);
|
||||
p1[0] = a1;
|
||||
p1[1] = b1;
|
||||
p1[2] = c1;
|
||||
p1[3] = d1;
|
||||
p2[0] = a2;
|
||||
p2[1] = b2;
|
||||
p2[2] = c2;
|
||||
p2[3] = d2;
|
||||
return pairing(p1, p2);
|
||||
/// @dev Substract two points (x1, y1) and (x2, y2) in affine coordinates.
|
||||
/// @param p1 G1 point P1
|
||||
/// @param p2 G1 point P2
|
||||
/// @return (qx, qy) = P1-P2 in affine coordinates
|
||||
function _subtract(Types.G1Point memory p1, Types.G1Point memory p2)
|
||||
internal
|
||||
pure
|
||||
returns(Types.G1Point memory)
|
||||
{
|
||||
(uint256 x, uint256 y) = EllipticCurve.ecSub(
|
||||
p1.x,
|
||||
p1.y,
|
||||
p2.x,
|
||||
p2.y,
|
||||
BN256G1.AA,
|
||||
BN256G1.PP);
|
||||
|
||||
return Types.G1Point(x, y);
|
||||
}
|
||||
|
||||
function isOnCurve(Curve.G1Point memory g1) internal pure returns (bool) {
|
||||
uint256 aa = Bn254.A();
|
||||
uint256 bb = Bn254.B();
|
||||
uint256 pp = Bn254.P();
|
||||
/// @dev Function to convert a `Hash(msg|DATA)` to a point in the curve as defined in [VRF-draft-04](https://tools.ietf.org/pdf/draft-irtf-cfrg-vrf-04).
|
||||
/// @param _message The message used for computing the VRF
|
||||
/// @return The hash point in affine coordinates
|
||||
function _hashToPoint(bytes memory _message)
|
||||
internal
|
||||
pure
|
||||
returns (Types.G1Point memory)
|
||||
{
|
||||
(uint256 x, uint256 y) = BN256G1._hashToTryAndIncrement(_message);
|
||||
return Types.G1Point(x, y);
|
||||
}
|
||||
|
||||
// Implementation borrowed from the witnet/elliptic-curve-solidity lib:
|
||||
// https://github.com/witnet/elliptic-curve-solidity/blob/b6886bb08333ccf6883ac42827d62c1bfdb37d44/contracts/EllipticCurve.sol#L113-L145
|
||||
if (0 == g1.X || g1.X == pp || 0 == g1.Y || g1.Y == pp) {
|
||||
return false;
|
||||
/// @dev Checks if e(P, Q) = e (R,S).
|
||||
/// @param p: G1 point P
|
||||
/// @param q: G2 point Q
|
||||
/// @param r: G1 point R
|
||||
/// @param s: G2 point S
|
||||
/// @return true if e(P, Q) = e (R,S).
|
||||
function _checkPairing(
|
||||
Types.G1Point memory p,
|
||||
Types.G2Point memory q,
|
||||
Types.G1Point memory r,
|
||||
Types.G2Point memory s
|
||||
)
|
||||
internal
|
||||
returns (bool)
|
||||
{
|
||||
return BN256G1._bn256CheckPairing(
|
||||
[
|
||||
p.x, // x-coordinate of point P
|
||||
p.y, // y-coordinate of point P
|
||||
q.x[0], // x real coordinate of point Q
|
||||
q.x[1], // x imaginary coordinate of point Q
|
||||
q.y[0], // y real coordinate of point Q
|
||||
q.y[1], // y imaginary coordinate of point Q
|
||||
r.x, // x-coordinate of point R
|
||||
r.y, // y-coordinate of point R
|
||||
s.x[0], // x real coordinate of point S
|
||||
s.x[1], // x imaginary coordinate of point S
|
||||
s.y[0], // y real coordinate of point S
|
||||
s.y[1] // y imaginary coordinate of point S
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
function _verifyProof(Types.Proof memory proof) internal returns (bool) {
|
||||
// var first: blst_p1
|
||||
// for qelem in q :
|
||||
// var prod: blst_p1
|
||||
// prod.blst_p1_mult(hashNameI(tau.t.name, qelem.I), qelem.V, 255)
|
||||
// first.blst_p1_add_or_double(first, prod)
|
||||
// doAssert(blst_p1_on_curve(first).bool)
|
||||
Types.G1Point memory first;
|
||||
for (uint256 i = 0; i<proof.q.length; i++) {
|
||||
Types.QElement memory qelem = proof.q[i];
|
||||
bytes32 namei = sha256(abi.encodePacked(proof.name, qelem.i));
|
||||
// Step 4: arbitraty string to point and check if it is on curve
|
||||
// uint256 hPointX = abi.encodePacked(namei);
|
||||
Types.G1Point memory h = _hashToPoint(abi.encodePacked(namei));
|
||||
// TODO: Where does 255 get used???
|
||||
Types.G1Point memory prod = _multiply(h, uint256(qelem.v));
|
||||
first = _add(first, prod);
|
||||
require(_isOnCurve(first), "must be on Bn254 curve");
|
||||
}
|
||||
// y^2
|
||||
uint256 lhs = mulmod(g1.Y, g1.Y, pp);
|
||||
// x^3
|
||||
uint256 rhs = mulmod(mulmod(g1.X, g1.X, pp), g1.X, pp);
|
||||
if (aa != 0) {
|
||||
// x^3 + a*x
|
||||
rhs = addmod(rhs, mulmod(g1.X, aa, pp), pp);
|
||||
}
|
||||
if (bb != 0) {
|
||||
// x^3 + a*x + b
|
||||
rhs = addmod(rhs, bb, pp);
|
||||
// let us = tau.t.u
|
||||
// var second: blst_p1
|
||||
// for j in 0 ..< len(us) :
|
||||
// var prod: blst_p1
|
||||
// prod.blst_p1_mult(us[j], mus[j], 255)
|
||||
// second.blst_p1_add_or_double(second, prod)
|
||||
// doAssert(blst_p1_on_curve(second).bool)
|
||||
Types.G1Point[] memory us = proof.u;
|
||||
Types.G1Point memory second;
|
||||
for (uint256 j = 0; j<us.length; j++) {
|
||||
// TODO: Where does 255 get used???
|
||||
Types.G1Point memory prod = _multiply(us[j], proof.mus[j]);
|
||||
second = _add(second, prod);
|
||||
require(_isOnCurve(second), "must be on Bn254 curve");
|
||||
}
|
||||
|
||||
return lhs == rhs;
|
||||
// var sum: blst_p1
|
||||
// sum.blst_p1_add_or_double(first, second)
|
||||
Types.G1Point memory sum = _add(first, second);
|
||||
|
||||
// var g{.noInit.}: blst_p2
|
||||
// g.blst_p2_from_affine(BLS12_381_G2)
|
||||
// TODO: do we need to convert Bn254._p2Generator() to/from affine???
|
||||
|
||||
// return verifyPairings(sum, spk.key, sigma, g)
|
||||
return Bn254._checkPairing(sum, proof.publicKey, proof.sigma, Bn254._p2Generator());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
218
contracts/ecc/vendor/witnet/bls-solidity/contracts/BN256G1.sol
vendored
Normal file
218
contracts/ecc/vendor/witnet/bls-solidity/contracts/BN256G1.sol
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "../../elliptic-curve-solidity/contracts/EllipticCurve.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title BN256G1 Curve Library
|
||||
* @dev Library providing arithmetic operations over G1 in bn256.
|
||||
* Provides additional methods like pairing and pairing_batch
|
||||
* Heavily influenced by https://github.com/PhilippSchindler/ethdkg
|
||||
* Calls to assembly are public and not external because assembly cannot be applied on calldata
|
||||
* @author Witnet Foundation
|
||||
*/
|
||||
|
||||
library BN256G1 {
|
||||
|
||||
// Generator coordinate `x` of the EC curve
|
||||
uint256 public constant GX = 1;
|
||||
// Generator coordinate `y` of the EC curve
|
||||
uint256 public constant GY = 2;
|
||||
// Constant `a` of EC equation
|
||||
uint256 internal constant AA = 0;
|
||||
// Constant `b` of EC equation
|
||||
uint256 internal constant BB = 3;
|
||||
// Prime number of the curve
|
||||
uint256 internal constant PP = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
|
||||
// Order of the curve
|
||||
uint256 internal constant NN = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
|
||||
|
||||
// This is 0xf1f5883e65f820d099915c908786b9d3f58714d70a38f4c22ca2bc723a70f263, the last mulitple of the modulus before 2^256
|
||||
uint256 internal constant LAST_MULTIPLE_OF_PP_LOWER_THAN_2_256 = 0xf1f5883e65f820d099915c908786b9d3f58714d70a38f4c22ca2bc723a70f263;
|
||||
|
||||
|
||||
/// @dev computes P + Q
|
||||
/// @param input: 4 values of 256 bits each
|
||||
/// *) x-coordinate of point P
|
||||
/// *) y-coordinate of point P
|
||||
/// *) x-coordinate of point Q
|
||||
/// *) y-coordinate of point Q
|
||||
/// @return An array with x and y coordinates of P+Q.
|
||||
function _add(uint256[4] memory input) internal returns (uint256, uint256) {
|
||||
bool success;
|
||||
uint256[2] memory result;
|
||||
assembly {
|
||||
// 0x06 id of the bn256Add precompile
|
||||
// 0 number of ether to transfer
|
||||
// 128 size of call parameters, i.e. 128 bytes total
|
||||
// 64 size of call return value, i.e. 64 bytes / 512 bit for a BN256 curve point
|
||||
success := call(not(0), 0x06, 0, input, 128, result, 64)
|
||||
}
|
||||
require(success, "bn256 addition failed");
|
||||
|
||||
return (result[0], result[1]);
|
||||
}
|
||||
|
||||
/// @dev computes P*k.
|
||||
/// @param input: 3 values of 256 bits each:
|
||||
/// *) x-coordinate of point P
|
||||
/// *) y-coordinate of point P
|
||||
/// *) scalar k.
|
||||
/// @return An array with x and y coordinates of P*k.
|
||||
function _multiply(uint256[3] memory input) internal returns (uint256, uint256) {
|
||||
bool success;
|
||||
uint256[2] memory result;
|
||||
assembly {
|
||||
// 0x07 id of the bn256ScalarMul precompile
|
||||
// 0 number of ether to transfer
|
||||
// 96 size of call parameters, i.e. 96 bytes total (256 bit for x, 256 bit for y, 256 bit for scalar)
|
||||
// 64 size of call return value, i.e. 64 bytes / 512 bit for a BN256 curve point
|
||||
success := call(not(0), 0x07, 0, input, 96, result, 64)
|
||||
}
|
||||
require(success, "elliptic curve multiplication failed");
|
||||
return (result[0], result[1]);
|
||||
}
|
||||
|
||||
/// @dev Checks if P is on G1 using the EllipticCurve library.
|
||||
/// @param point: 2 values of 256 bits each:
|
||||
/// *) x-coordinate of point P
|
||||
/// *) y-coordinate of point P
|
||||
/// @return true if P is in G1.
|
||||
function _isOnCurve(uint[2] memory point) internal pure returns (bool) {
|
||||
// checks if the given point is a valid point from the first elliptic curve group
|
||||
// uses the EllipticCurve library
|
||||
return EllipticCurve.isOnCurve(
|
||||
point[0],
|
||||
point[1],
|
||||
AA,
|
||||
BB,
|
||||
PP);
|
||||
}
|
||||
|
||||
/// @dev Checks if e(P, Q) = e (R,S).
|
||||
/// @param input: 12 values of 256 bits each:
|
||||
/// *) x-coordinate of point P
|
||||
/// *) y-coordinate of point P
|
||||
/// *) x real coordinate of point Q
|
||||
/// *) x imaginary coordinate of point Q
|
||||
/// *) y real coordinate of point Q
|
||||
/// *) y imaginary coordinate of point Q
|
||||
/// *) x-coordinate of point R
|
||||
/// *) y-coordinate of point R
|
||||
/// *) x real coordinate of point S
|
||||
/// *) x imaginary coordinate of point S
|
||||
/// *) y real coordinate of point S
|
||||
/// *) y imaginary coordinate of point S
|
||||
/// @return true if e(P, Q) = e (R,S).
|
||||
function _bn256CheckPairing(uint256[12] memory input) internal returns (bool) {
|
||||
uint256[1] memory result;
|
||||
bool success;
|
||||
assembly {
|
||||
// 0x08 id of the bn256CheckPairing precompile (checking the elliptic curve pairings)
|
||||
// 0 number of ether to transfer
|
||||
// 0 since we have an array of fixed length, our input starts in 0
|
||||
// 384 size of call parameters, i.e. 12*256 bits == 384 bytes
|
||||
// 32 size of result (one 32 byte boolean!)
|
||||
success := call(sub(gas(), 2000), 0x08, 0, input, 384, result, 32)
|
||||
}
|
||||
require(success, "elliptic curve pairing failed");
|
||||
return result[0] == 1;
|
||||
}
|
||||
|
||||
/// @dev Checks if e(P, Q) = e (R,S)*e(T,U)...
|
||||
/// @param input: A modulo 6 length array of values of 256 bits each:
|
||||
/// *) x-coordinate of point P
|
||||
/// *) y-coordinate of point P
|
||||
/// *) x real coordinate of point Q
|
||||
/// *) x imaginary coordinate of point Q
|
||||
/// *) y real coordinate of point Q
|
||||
/// *) y imaginary coordinate of point Q
|
||||
/// *) x-coordinate of point R
|
||||
/// *) y-coordinate of point R
|
||||
/// *) x real coordinate of point S
|
||||
/// *) x imaginary coordinate of point S
|
||||
/// *) y real coordinate of point S
|
||||
/// *) y imaginary coordinate of point S
|
||||
/// *) and so forth with additional pairing checks
|
||||
/// @return true if e(input[0,1], input[2,3,4,5]) = e(input[6,7], input[8,9,10,11])*e(input[12,13], input[14,15,16,17])...
|
||||
function _bn256CheckPairingBatch(uint256[] memory input) internal returns (bool) {
|
||||
uint256[1] memory result;
|
||||
bool success;
|
||||
require(input.length % 6 == 0, "Incorrect input length");
|
||||
uint256 inLen = input.length * 32;
|
||||
assembly {
|
||||
// 0x08 id of the bn256CheckPairing precompile (checking the elliptic curve pairings)
|
||||
// 0 number of ether to transfer
|
||||
// add(input, 0x20) since we have an unbounded array, the first 256 bits refer to its length
|
||||
// 384 size of call parameters, i.e. 12*256 bits == 384 bytes
|
||||
// 32 size of result (one 32 byte boolean!)
|
||||
success := call(sub(gas(), 2000), 0x08, 0, add(input, 0x20), inLen, result, 32)
|
||||
}
|
||||
require(success, "elliptic curve pairing failed");
|
||||
return result[0] == 1;
|
||||
}
|
||||
|
||||
/// @dev Function to transform compressed bytes into a x and a y coordinate in the curve.
|
||||
/// @param _point The point bytes
|
||||
/// @return The coordinates `x` and `y` in an array
|
||||
function _fromCompressed(bytes memory _point) internal pure returns (uint256, uint256) {
|
||||
require(_point.length == 33, "invalid encoding");
|
||||
uint8 sign;
|
||||
uint256 x;
|
||||
assembly {
|
||||
sign := mload(add(_point, 1))
|
||||
x := mload(add(_point, 33))
|
||||
}
|
||||
|
||||
return (
|
||||
x, _deriveY(
|
||||
sign,
|
||||
x)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Function to convert a `Hash(msg|DATA)` to a point in the curve as defined in [VRF-draft-04](https://tools.ietf.org/pdf/draft-irtf-cfrg-vrf-04).
|
||||
/// @param _message The message used for computing the VRF
|
||||
/// @return The hash point in affine coordinates
|
||||
function _hashToTryAndIncrement(bytes memory _message) internal pure returns (uint, uint) {
|
||||
// Find a valid EC point
|
||||
// Loop over counter ctr starting at 0x00 and do hash
|
||||
for (uint8 ctr = 0; ctr < 256; ctr++) {
|
||||
// Counter update
|
||||
// c[cLength-1] = byte(ctr);
|
||||
bytes32 sha = sha256(abi.encodePacked(_message, ctr));
|
||||
// Step 4: arbitraty string to point and check if it is on curve
|
||||
uint hPointX = uint256(sha);
|
||||
// Avoid hashes that are above the last multiple of _PP, otherwise odds are biased
|
||||
if (hPointX >= LAST_MULTIPLE_OF_PP_LOWER_THAN_2_256) {
|
||||
continue;
|
||||
}
|
||||
// Do the modulus to avoid excesive iterations of the loop
|
||||
hPointX = hPointX % PP;
|
||||
uint hPointY = _deriveY(2, hPointX);
|
||||
// we do not use the subsidized one as it appears to consume more gas
|
||||
if (_isOnCurve([hPointX,hPointY])) {
|
||||
// Step 5 (omitted): calculate H (cofactor is 1 on bn256g1)
|
||||
// If H is not "INVALID" and cofactor > 1, set H = cofactor * H
|
||||
return (hPointX, hPointY);
|
||||
}
|
||||
}
|
||||
revert("No valid point was found");
|
||||
}
|
||||
|
||||
/// @dev Function to derive the `y` coordinate given the `x` coordinate and the parity byte (`0x03` for odd `y` and `0x04` for even `y`).
|
||||
/// @param _yByte The parity byte following the ec point compressed format
|
||||
/// @param _x The coordinate `x` of the point
|
||||
/// @return The coordinate `y` of the point
|
||||
function _deriveY(uint8 _yByte, uint256 _x) internal pure returns (uint256) {
|
||||
return EllipticCurve.deriveY(
|
||||
_yByte,
|
||||
_x,
|
||||
AA,
|
||||
BB,
|
||||
PP);
|
||||
}
|
||||
|
||||
}
|
||||
764
contracts/ecc/vendor/witnet/bls-solidity/contracts/BN256G2.sol
vendored
Normal file
764
contracts/ecc/vendor/witnet/bls-solidity/contracts/BN256G2.sol
vendored
Normal file
@ -0,0 +1,764 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// solium-disable security/no-assign-params
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
|
||||
/**
|
||||
* @title Elliptic curve operations on twist points on bn256 (G2)
|
||||
* @dev Adaptation of https://github.com/musalbas/solidity-BN256G2 to 0.6.0
|
||||
*/
|
||||
library BN256G2 {
|
||||
uint256 internal constant FIELD_MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
|
||||
uint256 internal constant TWISTBX = 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5;
|
||||
uint256 internal constant TWISTBY = 0x9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2;
|
||||
uint internal constant PTXX = 0;
|
||||
uint internal constant PTXY = 1;
|
||||
uint internal constant PTYX = 2;
|
||||
uint internal constant PTYY = 3;
|
||||
uint internal constant PTZX = 4;
|
||||
uint internal constant PTZY = 5;
|
||||
|
||||
// This is the generator negated, to use for pairing
|
||||
uint256 public constant G2_NEG_X_RE = 0x198E9393920D483A7260BFB731FB5D25F1AA493335A9E71297E485B7AEF312C2;
|
||||
uint256 public constant G2_NEG_X_IM = 0x1800DEEF121F1E76426A00665E5C4479674322D4F75EDADD46DEBD5CD992F6ED;
|
||||
uint256 public constant G2_NEG_Y_RE = 0x275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec;
|
||||
uint256 public constant G2_NEG_Y_IM = 0x1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d;
|
||||
|
||||
/**
|
||||
* @notice Add two twist points
|
||||
* @param pt1xx Coefficient 1 of x on point 1
|
||||
* @param pt1xy Coefficient 2 of x on point 1
|
||||
* @param pt1yx Coefficient 1 of y on point 1
|
||||
* @param pt1yy Coefficient 2 of y on point 1
|
||||
* @param pt2xx Coefficient 1 of x on point 2
|
||||
* @param pt2xy Coefficient 2 of x on point 2
|
||||
* @param pt2yx Coefficient 1 of y on point 2
|
||||
* @param pt2yy Coefficient 2 of y on point 2
|
||||
* @return (pt3xx, pt3xy, pt3yx, pt3yy)
|
||||
*/
|
||||
function ecTwistAdd(
|
||||
uint256 pt1xx, uint256 pt1xy,
|
||||
uint256 pt1yx, uint256 pt1yy,
|
||||
uint256 pt2xx, uint256 pt2xy,
|
||||
uint256 pt2yx, uint256 pt2yy
|
||||
)
|
||||
internal view returns (uint256, uint256, uint256, uint256)
|
||||
{
|
||||
if (pt1xx == 0 && pt1xy == 0 && pt1yx == 0 && pt1yy == 0) {
|
||||
if (!(pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0)) {
|
||||
require(
|
||||
_isOnCurve(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt2yx,
|
||||
pt2yy
|
||||
),
|
||||
"point not in curve");
|
||||
}
|
||||
return (
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt2yx,
|
||||
pt2yy);
|
||||
} else if (pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0) {
|
||||
require(
|
||||
_isOnCurve(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy),
|
||||
"point not in curve");
|
||||
return (
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy);
|
||||
}
|
||||
|
||||
require(
|
||||
_isOnCurve(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy
|
||||
),
|
||||
"point not in curve");
|
||||
|
||||
require(
|
||||
_isOnCurve(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt2yx,
|
||||
pt2yy
|
||||
),
|
||||
"point not in curve");
|
||||
|
||||
uint256[6] memory pt3 = ecTwistAddJacobian(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
1,
|
||||
0,
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt2yx,
|
||||
pt2yy,
|
||||
1,
|
||||
0
|
||||
);
|
||||
|
||||
return _fromJacobian(
|
||||
pt3[PTXX],
|
||||
pt3[PTXY],
|
||||
pt3[PTYX],
|
||||
pt3[PTYY],
|
||||
pt3[PTZX],
|
||||
pt3[PTZY]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Multiply a twist point by a scalar
|
||||
* @param s Scalar to multiply by
|
||||
* @param pt1xx Coefficient 1 of x
|
||||
* @param pt1xy Coefficient 2 of x
|
||||
* @param pt1yx Coefficient 1 of y
|
||||
* @param pt1yy Coefficient 2 of y
|
||||
* @return (pt2xx, pt2xy, pt2yx, pt2yy)
|
||||
*/
|
||||
function ecTwistMul(
|
||||
uint256 s,
|
||||
uint256 pt1xx, uint256 pt1xy,
|
||||
uint256 pt1yx, uint256 pt1yy
|
||||
) internal view returns (uint256, uint256, uint256, uint256)
|
||||
{
|
||||
uint256 pt1zx = 1;
|
||||
if (pt1xx == 0 && pt1xy == 0 && pt1yx == 0 && pt1yy == 0) {
|
||||
pt1xx = 1;
|
||||
pt1yx = 1;
|
||||
pt1zx = 0;
|
||||
} else {
|
||||
require(
|
||||
_isOnCurve(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy
|
||||
),"point not in curve");
|
||||
}
|
||||
uint256[6] memory pt2 = _ecTwistMulJacobian(
|
||||
s,
|
||||
pt1xx, pt1xy,
|
||||
pt1yx, pt1yy,
|
||||
pt1zx, 0
|
||||
);
|
||||
|
||||
return _fromJacobian(
|
||||
pt2[PTXX], pt2[PTXY],
|
||||
pt2[PTYX], pt2[PTYY],
|
||||
pt2[PTZX], pt2[PTZY]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get the field modulus
|
||||
* @return The field modulus
|
||||
*/
|
||||
function getFieldModulus() external pure returns (uint256) {
|
||||
return FIELD_MODULUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice a-b mod n
|
||||
* @param a First operand
|
||||
* @param b Second operand
|
||||
* @param n modulus
|
||||
* @return The result of the operation
|
||||
*/
|
||||
function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) {
|
||||
return addmod(a, n - b, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice FQ2*FQ2 multiplication operation
|
||||
* @param xx First FQ2 operands first coordinate
|
||||
* @param xy First FQ2 operands second coordinate
|
||||
* @param yx Second FQ2 operands first coordinate
|
||||
* @param yy Second FQ2 operands second coordinate
|
||||
* @return [xx*yx-xy*yy, xx*yy+xy*yx]
|
||||
*/
|
||||
function _fq2mul(
|
||||
uint256 xx, uint256 xy,
|
||||
uint256 yx, uint256 yy
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256, uint256)
|
||||
{
|
||||
return (
|
||||
submod(mulmod(xx, yx, FIELD_MODULUS), mulmod(xy, yy, FIELD_MODULUS), FIELD_MODULUS),
|
||||
addmod(mulmod(xx, yy, FIELD_MODULUS), mulmod(xy, yx, FIELD_MODULUS), FIELD_MODULUS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Fq2*k multiplication operation
|
||||
* @param xx FQ2 operands first coordinate
|
||||
* @param xy FQ2 operands second coordinate
|
||||
* @param k scalar to multiply with
|
||||
* @return [xx*k, xy*k]
|
||||
*/
|
||||
function _fq2muc(
|
||||
uint256 xx, uint256 xy,
|
||||
uint256 k
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256, uint256)
|
||||
{
|
||||
return (
|
||||
mulmod(xx, k, FIELD_MODULUS),
|
||||
mulmod(xy, k, FIELD_MODULUS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice FQ2+FQ2 addition operation
|
||||
* @param xx First FQ2 operands first coordinate
|
||||
* @param xy First FQ2 operands second coordinate
|
||||
* @param yx Second FQ2 operands first coordinate
|
||||
* @param yy Second FQ2 operands second coordinate
|
||||
* @return [xx+yx, xy+yy]f
|
||||
*/
|
||||
function _fq2add(
|
||||
uint256 xx, uint256 xy,
|
||||
uint256 yx, uint256 yy
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns(uint256, uint256)
|
||||
{
|
||||
return (
|
||||
addmod(xx, yx, FIELD_MODULUS),
|
||||
addmod(xy, yy, FIELD_MODULUS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice FQ2-FQ2 substraction operation
|
||||
* @param xx First FQ2 operands first coordinate
|
||||
* @param xy First FQ2 operands second coordinate
|
||||
* @param yx Second FQ2 operands first coordinate
|
||||
* @param yy Second FQ2 operands second coordinate
|
||||
* @return [xx-yx, xy-yy]
|
||||
*/
|
||||
function _fq2sub(
|
||||
uint256 xx, uint256 xy,
|
||||
uint256 yx, uint256 yy
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256, uint256)
|
||||
{
|
||||
return (
|
||||
submod(xx, yx, FIELD_MODULUS),
|
||||
submod(xy, yy, FIELD_MODULUS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice FQ2/FQ2 division operation
|
||||
* @param xx First FQ2 operands first coordinate
|
||||
* @param xy First FQ2 operands second coordinate
|
||||
* @param yx Second FQ2 operands first coordinate
|
||||
* @param yy Second FQ2 operands second coordinate
|
||||
* @return [xx, xy] * Inv([yx, yy])
|
||||
*/
|
||||
function _fq2div(
|
||||
uint256 xx, uint256 xy,
|
||||
uint256 yx, uint256 yy
|
||||
)
|
||||
internal
|
||||
view
|
||||
returns (uint256, uint256)
|
||||
{
|
||||
(yx, yy) = _fq2inv(yx, yy);
|
||||
return _fq2mul(
|
||||
xx,
|
||||
xy,
|
||||
yx,
|
||||
yy);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 1/FQ2 inverse operation
|
||||
* @param x FQ2 operands first coordinate
|
||||
* @param y FQ2 operands second coordinate
|
||||
* @return Inv([xx, xy])
|
||||
*/
|
||||
function _fq2inv(uint256 x, uint256 y) internal view returns (uint256, uint256) {
|
||||
uint256 inv = _modInv(addmod(mulmod(y, y, FIELD_MODULUS), mulmod(x, x, FIELD_MODULUS), FIELD_MODULUS), FIELD_MODULUS);
|
||||
return (
|
||||
mulmod(x, inv, FIELD_MODULUS),
|
||||
FIELD_MODULUS - mulmod(y, inv, FIELD_MODULUS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Checks if FQ2 is on G2
|
||||
* @param xx First FQ2 operands first coordinate
|
||||
* @param xy First FQ2 operands second coordinate
|
||||
* @param yx Second FQ2 operands first coordinate
|
||||
* @param yy Second FQ2 operands second coordinate
|
||||
* @return True if the FQ2 is on G2
|
||||
*/
|
||||
function _isOnCurve(
|
||||
uint256 xx, uint256 xy,
|
||||
uint256 yx, uint256 yy
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
uint256 yyx;
|
||||
uint256 yyy;
|
||||
uint256 xxxx;
|
||||
uint256 xxxy;
|
||||
(yyx, yyy) = _fq2mul(
|
||||
yx,
|
||||
yy,
|
||||
yx,
|
||||
yy);
|
||||
(xxxx, xxxy) = _fq2mul(
|
||||
xx,
|
||||
xy,
|
||||
xx,
|
||||
xy);
|
||||
(xxxx, xxxy) = _fq2mul(
|
||||
xxxx,
|
||||
xxxy,
|
||||
xx,
|
||||
xy);
|
||||
(yyx, yyy) = _fq2sub(
|
||||
yyx,
|
||||
yyy,
|
||||
xxxx,
|
||||
xxxy);
|
||||
(yyx, yyy) = _fq2sub(
|
||||
yyx,
|
||||
yyy,
|
||||
TWISTBX,
|
||||
TWISTBY);
|
||||
return yyx == 0 && yyy == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculates the modular inverse of a over n
|
||||
* @param a The operand to calcualte the inverse of
|
||||
* @param n The modulus
|
||||
* @return result Inv(a)modn
|
||||
**/
|
||||
function _modInv(uint256 a, uint256 n) internal view returns (uint256 result) {
|
||||
bool success;
|
||||
assembly {
|
||||
let freemem := mload(0x40)
|
||||
mstore(freemem, 0x20)
|
||||
mstore(add(freemem,0x20), 0x20)
|
||||
mstore(add(freemem,0x40), 0x20)
|
||||
mstore(add(freemem,0x60), a)
|
||||
mstore(add(freemem,0x80), sub(n, 2))
|
||||
mstore(add(freemem,0xA0), n)
|
||||
success := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20)
|
||||
result := mload(freemem)
|
||||
}
|
||||
require(success, "error calculating the modular inverse");
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Converts a point from jacobian to affine
|
||||
* @param pt1xx First point x real coordinate
|
||||
* @param pt1xy First point x imaginary coordinate
|
||||
* @param pt1yx First point y real coordinate
|
||||
* @param pt1yy First point y imaginary coordinate
|
||||
* @param pt1zx First point z real coordinate
|
||||
* @param pt1zy First point z imaginary coordinate
|
||||
* @return pt2xx (x real affine coordinate)
|
||||
pt2xy (x imaginary affine coordinate)
|
||||
pt2yx (y real affine coordinate)
|
||||
pt1zy (y imaginary affine coordinate)
|
||||
**/
|
||||
function _fromJacobian(
|
||||
uint256 pt1xx, uint256 pt1xy,
|
||||
uint256 pt1yx, uint256 pt1yy,
|
||||
uint256 pt1zx, uint256 pt1zy
|
||||
)
|
||||
internal view returns (uint256, uint256, uint256, uint256)
|
||||
{
|
||||
uint256 invzx;
|
||||
uint256 invzy;
|
||||
uint256[4] memory pt2;
|
||||
(invzx, invzy) = _fq2inv(pt1zx, pt1zy);
|
||||
(pt2[0], pt2[1]) = _fq2mul(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
invzx,
|
||||
invzy);
|
||||
(pt2[2], pt2[3]) = _fq2mul(
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
invzx,
|
||||
invzy);
|
||||
return(
|
||||
pt2[0],
|
||||
pt2[1],
|
||||
pt2[2],
|
||||
pt2[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Adds two points in jacobian coordinates
|
||||
* @param pt1xx First point x real coordinate
|
||||
* @param pt1xy First point x imaginary coordinate
|
||||
* @param pt1yx First point y real coordinate
|
||||
* @param pt1yy First point y imaginary coordinate
|
||||
* @param pt1zx First point z real coordinate
|
||||
* @param pt1zy First point z imaginary coordinate
|
||||
* @param pt2xx Second point x real coordinate
|
||||
* @param pt2xy Second point x imaginary coordinate
|
||||
* @param pt2yx Second point y real coordinate
|
||||
* @param pt2yy Second point y imaginary coordinate
|
||||
* @param pt2zx Second point z real coordinate
|
||||
* @param pt2zy Second point z imaginary coordinate
|
||||
* @return pt3 = pt1+pt2 in jacobian
|
||||
**/
|
||||
function ecTwistAddJacobian(
|
||||
uint256 pt1xx, uint256 pt1xy,
|
||||
uint256 pt1yx, uint256 pt1yy,
|
||||
uint256 pt1zx, uint256 pt1zy,
|
||||
uint256 pt2xx, uint256 pt2xy,
|
||||
uint256 pt2yx, uint256 pt2yy,
|
||||
uint256 pt2zx, uint256 pt2zy)
|
||||
internal
|
||||
pure
|
||||
returns (uint256[6] memory pt3)
|
||||
{
|
||||
if (pt1zx == 0 && pt1zy == 0) {
|
||||
(
|
||||
pt3[PTXX], pt3[PTXY],
|
||||
pt3[PTYX], pt3[PTYY],
|
||||
pt3[PTZX], pt3[PTZY]
|
||||
) = (
|
||||
pt2xx, pt2xy,
|
||||
pt2yx, pt2yy,
|
||||
pt2zx, pt2zy
|
||||
);
|
||||
return pt3;
|
||||
} else if (pt2zx == 0 && pt2zy == 0) {
|
||||
(
|
||||
pt3[PTXX], pt3[PTXY],
|
||||
pt3[PTYX], pt3[PTYY],
|
||||
pt3[PTZX], pt3[PTZY]
|
||||
) = (
|
||||
pt1xx, pt1xy,
|
||||
pt1yx, pt1yy,
|
||||
pt1zx, pt1zy
|
||||
);
|
||||
return pt3;
|
||||
}
|
||||
|
||||
(pt2yx, pt2yy) = _fq2mul(
|
||||
pt2yx,
|
||||
pt2yy,
|
||||
pt1zx,
|
||||
pt1zy); // U1 = y2 * z1
|
||||
(pt3[PTYX], pt3[PTYY]) = _fq2mul(
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt2zx,
|
||||
pt2zy); // U2 = y1 * z2
|
||||
(pt2xx, pt2xy) = _fq2mul(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt1zx,
|
||||
pt1zy); // V1 = x2 * z1
|
||||
(pt3[PTZX], pt3[PTZY]) = _fq2mul(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt2zx,
|
||||
pt2zy); // V2 = x1 * z2
|
||||
|
||||
if (pt2xx == pt3[PTZX] && pt2xy == pt3[PTZY]) {
|
||||
if (pt2yx == pt3[PTYX] && pt2yy == pt3[PTYY]) {
|
||||
(
|
||||
pt3[PTXX], pt3[PTXY],
|
||||
pt3[PTYX], pt3[PTYY],
|
||||
pt3[PTZX], pt3[PTZY]
|
||||
) = _ecTwistDoubleJacobian(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt1zx,
|
||||
pt1zy);
|
||||
return pt3;
|
||||
}
|
||||
(
|
||||
pt3[PTXX], pt3[PTXY],
|
||||
pt3[PTYX], pt3[PTYY],
|
||||
pt3[PTZX], pt3[PTZY]
|
||||
) = (
|
||||
1, 0,
|
||||
1, 0,
|
||||
0, 0
|
||||
);
|
||||
return pt3;
|
||||
}
|
||||
|
||||
(pt2zx, pt2zy) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt2zx,
|
||||
pt2zy); // W = z1 * z2
|
||||
(pt1xx, pt1xy) = _fq2sub(
|
||||
pt2yx,
|
||||
pt2yy,
|
||||
pt3[PTYX],
|
||||
pt3[PTYY]); // U = U1 - U2
|
||||
(pt1yx, pt1yy) = _fq2sub(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt3[PTZX],
|
||||
pt3[PTZY]); // V = V1 - V2
|
||||
(pt1zx, pt1zy) = _fq2mul(
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt1yx,
|
||||
pt1yy); // V_squared = V * V
|
||||
(pt2yx, pt2yy) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt3[PTZX],
|
||||
pt3[PTZY]); // V_squared_times_V2 = V_squared * V2
|
||||
(pt1zx, pt1zy) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt1yx,
|
||||
pt1yy); // V_cubed = V * V_squared
|
||||
(pt3[PTZX], pt3[PTZY]) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt2zx,
|
||||
pt2zy); // newz = V_cubed * W
|
||||
(pt2xx, pt2xy) = _fq2mul(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1xx,
|
||||
pt1xy); // U * U
|
||||
(pt2xx, pt2xy) = _fq2mul(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt2zx,
|
||||
pt2zy); // U * U * W
|
||||
(pt2xx, pt2xy) = _fq2sub(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt1zx,
|
||||
pt1zy); // U * U * W - V_cubed
|
||||
(pt2zx, pt2zy) = _fq2muc(pt2yx, pt2yy, 2); // 2 * V_squared_times_V2
|
||||
(pt2xx, pt2xy) = _fq2sub(
|
||||
pt2xx,
|
||||
pt2xy,
|
||||
pt2zx,
|
||||
pt2zy); // A = U * U * W - V_cubed - 2 * V_squared_times_V2
|
||||
(pt3[PTXX], pt3[PTXY]) = _fq2mul(
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt2xx,
|
||||
pt2xy); // newx = V * A
|
||||
(pt1yx, pt1yy) = _fq2sub(
|
||||
pt2yx,
|
||||
pt2yy,
|
||||
pt2xx,
|
||||
pt2xy); // V_squared_times_V2 - A
|
||||
(pt1yx, pt1yy) = _fq2mul(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy); // U * (V_squared_times_V2 - A)
|
||||
(pt1xx, pt1xy) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt3[PTYX],
|
||||
pt3[PTYY]); // V_cubed * U2
|
||||
(pt3[PTYX], pt3[PTYY]) = _fq2sub(
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt1xx,
|
||||
pt1xy); // newy = U * (V_squared_times_V2 - A) - V_cubed * U2
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Doubls a point in jacobian coordinates
|
||||
* @param pt1xx Point x real coordinate
|
||||
* @param pt1xy Point x imaginary coordinate
|
||||
* @param pt1yx Point y real coordinate
|
||||
* @param pt1yy Point y imaginary coordinate
|
||||
* @param pt1zx Point z real coordinate
|
||||
* @param pt1zy Point z imaginary coordinate
|
||||
* @return pt2xx, pt2xy, pt2yx, pt2yy, pt2zx, pt2zy the coordinates of pt2 = 2*pt1
|
||||
**/
|
||||
function _ecTwistDoubleJacobian(
|
||||
uint256 pt1xx,
|
||||
uint256 pt1xy,
|
||||
uint256 pt1yx,
|
||||
uint256 pt1yy,
|
||||
uint256 pt1zx,
|
||||
uint256 pt1zy
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256
|
||||
)
|
||||
{
|
||||
uint256[6] memory pt2;
|
||||
(pt2[0], pt2[1]) = _fq2muc(pt1xx, pt1xy, 3); // 3 * x
|
||||
(pt2[0], pt2[1]) = _fq2mul(
|
||||
pt2[0],
|
||||
pt2[1],
|
||||
pt1xx,
|
||||
pt1xy); // W = 3 * x * x
|
||||
(pt1zx, pt1zy) = _fq2mul(
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt1zx,
|
||||
pt1zy); // S = y * z
|
||||
(pt2[2], pt2[3]) = _fq2mul(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy); // x * y
|
||||
(pt2[2], pt2[3]) = _fq2mul(
|
||||
pt2[2],
|
||||
pt2[3],
|
||||
pt1zx,
|
||||
pt1zy); // B = x * y * S
|
||||
(pt1xx, pt1xy) = _fq2mul(
|
||||
pt2[0],
|
||||
pt2[1],
|
||||
pt2[0],
|
||||
pt2[1]); // W * W
|
||||
(pt2[4], pt2[5]) = _fq2muc(pt2[2], pt2[3], 8); // 8 * B
|
||||
(pt1xx, pt1xy) = _fq2sub(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt2[4],
|
||||
pt2[5]); // H = W * W - 8 * B
|
||||
(pt2[4], pt2[5]) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt1zx,
|
||||
pt1zy); // S_squared = S * S
|
||||
(pt2[2], pt2[3]) = _fq2muc(pt2[2], pt2[3], 4); // 4 * B
|
||||
(pt2[2], pt2[3]) = _fq2sub(
|
||||
pt2[2],
|
||||
pt2[3],
|
||||
pt1xx,
|
||||
pt1xy); // 4 * B - H
|
||||
(pt2[2], pt2[3]) = _fq2mul(
|
||||
pt2[2],
|
||||
pt2[3],
|
||||
pt2[0],
|
||||
pt2[1]); // W * (4 * B - H)
|
||||
(pt2[0], pt2[1]) = _fq2muc(pt1yx, pt1yy, 8); // 8 * y
|
||||
(pt2[0], pt2[1]) = _fq2mul(
|
||||
pt2[0],
|
||||
pt2[1],
|
||||
pt1yx,
|
||||
pt1yy); // 8 * y * y
|
||||
(pt2[0], pt2[1]) = _fq2mul(
|
||||
pt2[0],
|
||||
pt2[1],
|
||||
pt2[4],
|
||||
pt2[5]); // 8 * y * y * S_squared
|
||||
(pt2[2], pt2[3]) = _fq2sub(
|
||||
pt2[2],
|
||||
pt2[3],
|
||||
pt2[0],
|
||||
pt2[1]); // newy = W * (4 * B - H) - 8 * y * y * S_squared
|
||||
(pt2[0], pt2[1]) = _fq2muc(pt1xx, pt1xy, 2); // 2 * H
|
||||
(pt2[0], pt2[1]) = _fq2mul(
|
||||
pt2[0],
|
||||
pt2[1],
|
||||
pt1zx,
|
||||
pt1zy); // newx = 2 * H * S
|
||||
(pt2[4], pt2[5]) = _fq2mul(
|
||||
pt1zx,
|
||||
pt1zy,
|
||||
pt2[4],
|
||||
pt2[5]); // S * S_squared
|
||||
(pt2[4], pt2[5]) = _fq2muc(pt2[4], pt2[5], 8); // newz = 8 * S * S_squared
|
||||
|
||||
return (pt2[0], pt2[1], pt2[2], pt2[3], pt2[4], pt2[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Doubls a point in jacobian coordinates
|
||||
* @param d scalar to multiply the point with
|
||||
* @param pt1xx Point x real coordinate
|
||||
* @param pt1xy Point x imaginary coordinate
|
||||
* @param pt1yx Point y real coordinate
|
||||
* @param pt1yy Point y imaginary coordinate
|
||||
* @param pt1zx Point z real coordinate
|
||||
* @param pt1zy Point z imaginary coordinate
|
||||
* @return a point representing pt2 = d*pt1 in jacobian coordinates
|
||||
**/
|
||||
function _ecTwistMulJacobian(
|
||||
uint256 d,
|
||||
uint256 pt1xx,
|
||||
uint256 pt1xy,
|
||||
uint256 pt1yx,
|
||||
uint256 pt1yy,
|
||||
uint256 pt1zx,
|
||||
uint256 pt1zy
|
||||
) internal pure returns (uint256[6] memory)
|
||||
{
|
||||
uint[6] memory pt2;
|
||||
while (d != 0) {
|
||||
if ((d & 1) != 0) {
|
||||
pt2 = ecTwistAddJacobian(
|
||||
pt2[PTXX],
|
||||
pt2[PTXY],
|
||||
pt2[PTYX],
|
||||
pt2[PTYY],
|
||||
pt2[PTZX],
|
||||
pt2[PTZY],
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt1zx,
|
||||
pt1zy
|
||||
);
|
||||
}
|
||||
(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy) = _ecTwistDoubleJacobian(
|
||||
pt1xx,
|
||||
pt1xy,
|
||||
pt1yx,
|
||||
pt1yy,
|
||||
pt1zx,
|
||||
pt1zy
|
||||
);
|
||||
|
||||
d = d / 2;
|
||||
}
|
||||
return pt2;
|
||||
}
|
||||
}
|
||||
427
contracts/ecc/vendor/witnet/elliptic-curve-solidity/contracts/EllipticCurve.sol
vendored
Normal file
427
contracts/ecc/vendor/witnet/elliptic-curve-solidity/contracts/EllipticCurve.sol
vendored
Normal file
@ -0,0 +1,427 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// taken from: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
|
||||
/**
|
||||
* @title Elliptic Curve Library
|
||||
* @dev Library providing arithmetic operations over elliptic curves.
|
||||
* This library does not check whether the inserted points belong to the curve
|
||||
* `isOnCurve` function should be used by the library user to check the aforementioned statement.
|
||||
* @author Witnet Foundation
|
||||
*/
|
||||
library EllipticCurve {
|
||||
|
||||
// Pre-computed constant for 2 ** 255
|
||||
uint256 constant private U255_MAX_PLUS_1 = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
|
||||
|
||||
/// @dev Modular euclidean inverse of a number (mod p).
|
||||
/// @param _x The number
|
||||
/// @param _pp The modulus
|
||||
/// @return q such that x*q = 1 (mod _pp)
|
||||
function invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) {
|
||||
require(_x != 0 && _x != _pp && _pp != 0, "Invalid number");
|
||||
uint256 q = 0;
|
||||
uint256 newT = 1;
|
||||
uint256 r = _pp;
|
||||
uint256 t;
|
||||
while (_x != 0) {
|
||||
t = r / _x;
|
||||
(q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp));
|
||||
(r, _x) = (_x, r - t * _x);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
/// @dev Modular exponentiation, b^e % _pp.
|
||||
/// Source: https://github.com/androlo/standard-contracts/blob/master/contracts/src/crypto/ECCMath.sol
|
||||
/// @param _base base
|
||||
/// @param _exp exponent
|
||||
/// @param _pp modulus
|
||||
/// @return r such that r = b**e (mod _pp)
|
||||
function expMod(uint256 _base, uint256 _exp, uint256 _pp) internal pure returns (uint256) {
|
||||
require(_pp!=0, "Modulus is zero");
|
||||
|
||||
if (_base == 0)
|
||||
return 0;
|
||||
if (_exp == 0)
|
||||
return 1;
|
||||
|
||||
uint256 r = 1;
|
||||
uint256 bit = U255_MAX_PLUS_1;
|
||||
assembly {
|
||||
for { } gt(bit, 0) { }{
|
||||
r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, bit)))), _pp)
|
||||
r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, div(bit, 2))))), _pp)
|
||||
r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, div(bit, 4))))), _pp)
|
||||
r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, div(bit, 8))))), _pp)
|
||||
bit := div(bit, 16)
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// @dev Converts a point (x, y, z) expressed in Jacobian coordinates to affine coordinates (x', y', 1).
|
||||
/// @param _x coordinate x
|
||||
/// @param _y coordinate y
|
||||
/// @param _z coordinate z
|
||||
/// @param _pp the modulus
|
||||
/// @return (x', y') affine coordinates
|
||||
function toAffine(
|
||||
uint256 _x,
|
||||
uint256 _y,
|
||||
uint256 _z,
|
||||
uint256 _pp)
|
||||
internal pure returns (uint256, uint256)
|
||||
{
|
||||
uint256 zInv = invMod(_z, _pp);
|
||||
uint256 zInv2 = mulmod(zInv, zInv, _pp);
|
||||
uint256 x2 = mulmod(_x, zInv2, _pp);
|
||||
uint256 y2 = mulmod(_y, mulmod(zInv, zInv2, _pp), _pp);
|
||||
|
||||
return (x2, y2);
|
||||
}
|
||||
|
||||
/// @dev Derives the y coordinate from a compressed-format point x [[SEC-1]](https://www.secg.org/SEC1-Ver-1.0.pdf).
|
||||
/// @param _prefix parity byte (0x02 even, 0x03 odd)
|
||||
/// @param _x coordinate x
|
||||
/// @param _aa constant of curve
|
||||
/// @param _bb constant of curve
|
||||
/// @param _pp the modulus
|
||||
/// @return y coordinate y
|
||||
function deriveY(
|
||||
uint8 _prefix,
|
||||
uint256 _x,
|
||||
uint256 _aa,
|
||||
uint256 _bb,
|
||||
uint256 _pp)
|
||||
internal pure returns (uint256)
|
||||
{
|
||||
require(_prefix == 0x02 || _prefix == 0x03, "Invalid compressed EC point prefix");
|
||||
|
||||
// x^3 + ax + b
|
||||
uint256 y2 = addmod(mulmod(_x, mulmod(_x, _x, _pp), _pp), addmod(mulmod(_x, _aa, _pp), _bb, _pp), _pp);
|
||||
y2 = expMod(y2, (_pp + 1) / 4, _pp);
|
||||
// uint256 cmp = yBit ^ y_ & 1;
|
||||
uint256 y = (y2 + _prefix) % 2 == 0 ? y2 : _pp - y2;
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/// @dev Check whether point (x,y) is on curve defined by a, b, and _pp.
|
||||
/// @param _x coordinate x of P1
|
||||
/// @param _y coordinate y of P1
|
||||
/// @param _aa constant of curve
|
||||
/// @param _bb constant of curve
|
||||
/// @param _pp the modulus
|
||||
/// @return true if x,y in the curve, false else
|
||||
function isOnCurve(
|
||||
uint _x,
|
||||
uint _y,
|
||||
uint _aa,
|
||||
uint _bb,
|
||||
uint _pp)
|
||||
internal pure returns (bool)
|
||||
{
|
||||
if (0 == _x || _x >= _pp || 0 == _y || _y >= _pp) {
|
||||
return false;
|
||||
}
|
||||
// y^2
|
||||
uint lhs = mulmod(_y, _y, _pp);
|
||||
// x^3
|
||||
uint rhs = mulmod(mulmod(_x, _x, _pp), _x, _pp);
|
||||
if (_aa != 0) {
|
||||
// x^3 + a*x
|
||||
rhs = addmod(rhs, mulmod(_x, _aa, _pp), _pp);
|
||||
}
|
||||
if (_bb != 0) {
|
||||
// x^3 + a*x + b
|
||||
rhs = addmod(rhs, _bb, _pp);
|
||||
}
|
||||
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
/// @dev Calculate inverse (x, -y) of point (x, y).
|
||||
/// @param _x coordinate x of P1
|
||||
/// @param _y coordinate y of P1
|
||||
/// @param _pp the modulus
|
||||
/// @return (x, -y)
|
||||
function ecInv(
|
||||
uint256 _x,
|
||||
uint256 _y,
|
||||
uint256 _pp)
|
||||
internal pure returns (uint256, uint256)
|
||||
{
|
||||
return (_x, (_pp - _y) % _pp);
|
||||
}
|
||||
|
||||
/// @dev Add two points (x1, y1) and (x2, y2) in affine coordinates.
|
||||
/// @param _x1 coordinate x of P1
|
||||
/// @param _y1 coordinate y of P1
|
||||
/// @param _x2 coordinate x of P2
|
||||
/// @param _y2 coordinate y of P2
|
||||
/// @param _aa constant of the curve
|
||||
/// @param _pp the modulus
|
||||
/// @return (qx, qy) = P1+P2 in affine coordinates
|
||||
function ecAdd(
|
||||
uint256 _x1,
|
||||
uint256 _y1,
|
||||
uint256 _x2,
|
||||
uint256 _y2,
|
||||
uint256 _aa,
|
||||
uint256 _pp)
|
||||
internal pure returns(uint256, uint256)
|
||||
{
|
||||
uint x = 0;
|
||||
uint y = 0;
|
||||
uint z = 0;
|
||||
|
||||
// Double if x1==x2 else add
|
||||
if (_x1==_x2) {
|
||||
// y1 = -y2 mod p
|
||||
if (addmod(_y1, _y2, _pp) == 0) {
|
||||
return(0, 0);
|
||||
} else {
|
||||
// P1 = P2
|
||||
(x, y, z) = jacDouble(
|
||||
_x1,
|
||||
_y1,
|
||||
1,
|
||||
_aa,
|
||||
_pp);
|
||||
}
|
||||
} else {
|
||||
(x, y, z) = jacAdd(
|
||||
_x1,
|
||||
_y1,
|
||||
1,
|
||||
_x2,
|
||||
_y2,
|
||||
1,
|
||||
_pp);
|
||||
}
|
||||
// Get back to affine
|
||||
return toAffine(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
_pp);
|
||||
}
|
||||
|
||||
/// @dev Substract two points (x1, y1) and (x2, y2) in affine coordinates.
|
||||
/// @param _x1 coordinate x of P1
|
||||
/// @param _y1 coordinate y of P1
|
||||
/// @param _x2 coordinate x of P2
|
||||
/// @param _y2 coordinate y of P2
|
||||
/// @param _aa constant of the curve
|
||||
/// @param _pp the modulus
|
||||
/// @return (qx, qy) = P1-P2 in affine coordinates
|
||||
function ecSub(
|
||||
uint256 _x1,
|
||||
uint256 _y1,
|
||||
uint256 _x2,
|
||||
uint256 _y2,
|
||||
uint256 _aa,
|
||||
uint256 _pp)
|
||||
internal pure returns(uint256, uint256)
|
||||
{
|
||||
// invert square
|
||||
(uint256 x, uint256 y) = ecInv(_x2, _y2, _pp);
|
||||
// P1-square
|
||||
return ecAdd(
|
||||
_x1,
|
||||
_y1,
|
||||
x,
|
||||
y,
|
||||
_aa,
|
||||
_pp);
|
||||
}
|
||||
|
||||
/// @dev Multiply point (x1, y1, z1) times d in affine coordinates.
|
||||
/// @param _k scalar to multiply
|
||||
/// @param _x coordinate x of P1
|
||||
/// @param _y coordinate y of P1
|
||||
/// @param _aa constant of the curve
|
||||
/// @param _pp the modulus
|
||||
/// @return (qx, qy) = d*P in affine coordinates
|
||||
function ecMul(
|
||||
uint256 _k,
|
||||
uint256 _x,
|
||||
uint256 _y,
|
||||
uint256 _aa,
|
||||
uint256 _pp)
|
||||
internal pure returns(uint256, uint256)
|
||||
{
|
||||
// Jacobian multiplication
|
||||
(uint256 x1, uint256 y1, uint256 z1) = jacMul(
|
||||
_k,
|
||||
_x,
|
||||
_y,
|
||||
1,
|
||||
_aa,
|
||||
_pp);
|
||||
// Get back to affine
|
||||
return toAffine(
|
||||
x1,
|
||||
y1,
|
||||
z1,
|
||||
_pp);
|
||||
}
|
||||
|
||||
/// @dev Adds two points (x1, y1, z1) and (x2 y2, z2).
|
||||
/// @param _x1 coordinate x of P1
|
||||
/// @param _y1 coordinate y of P1
|
||||
/// @param _z1 coordinate z of P1
|
||||
/// @param _x2 coordinate x of square
|
||||
/// @param _y2 coordinate y of square
|
||||
/// @param _z2 coordinate z of square
|
||||
/// @param _pp the modulus
|
||||
/// @return (qx, qy, qz) P1+square in Jacobian
|
||||
function jacAdd(
|
||||
uint256 _x1,
|
||||
uint256 _y1,
|
||||
uint256 _z1,
|
||||
uint256 _x2,
|
||||
uint256 _y2,
|
||||
uint256 _z2,
|
||||
uint256 _pp)
|
||||
internal pure returns (uint256, uint256, uint256)
|
||||
{
|
||||
if (_x1==0 && _y1==0)
|
||||
return (_x2, _y2, _z2);
|
||||
if (_x2==0 && _y2==0)
|
||||
return (_x1, _y1, _z1);
|
||||
|
||||
// We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5
|
||||
uint[4] memory zs; // z1^2, z1^3, z2^2, z2^3
|
||||
zs[0] = mulmod(_z1, _z1, _pp);
|
||||
zs[1] = mulmod(_z1, zs[0], _pp);
|
||||
zs[2] = mulmod(_z2, _z2, _pp);
|
||||
zs[3] = mulmod(_z2, zs[2], _pp);
|
||||
|
||||
// u1, s1, u2, s2
|
||||
zs = [
|
||||
mulmod(_x1, zs[2], _pp),
|
||||
mulmod(_y1, zs[3], _pp),
|
||||
mulmod(_x2, zs[0], _pp),
|
||||
mulmod(_y2, zs[1], _pp)
|
||||
];
|
||||
|
||||
// In case of zs[0] == zs[2] && zs[1] == zs[3], double function should be used
|
||||
require(zs[0] != zs[2] || zs[1] != zs[3], "Use jacDouble function instead");
|
||||
|
||||
uint[4] memory hr;
|
||||
//h
|
||||
hr[0] = addmod(zs[2], _pp - zs[0], _pp);
|
||||
//r
|
||||
hr[1] = addmod(zs[3], _pp - zs[1], _pp);
|
||||
//h^2
|
||||
hr[2] = mulmod(hr[0], hr[0], _pp);
|
||||
// h^3
|
||||
hr[3] = mulmod(hr[2], hr[0], _pp);
|
||||
// qx = -h^3 -2u1h^2+r^2
|
||||
uint256 qx = addmod(mulmod(hr[1], hr[1], _pp), _pp - hr[3], _pp);
|
||||
qx = addmod(qx, _pp - mulmod(2, mulmod(zs[0], hr[2], _pp), _pp), _pp);
|
||||
// qy = -s1*z1*h^3+r(u1*h^2 -x^3)
|
||||
uint256 qy = mulmod(hr[1], addmod(mulmod(zs[0], hr[2], _pp), _pp - qx, _pp), _pp);
|
||||
qy = addmod(qy, _pp - mulmod(zs[1], hr[3], _pp), _pp);
|
||||
// qz = h*z1*z2
|
||||
uint256 qz = mulmod(hr[0], mulmod(_z1, _z2, _pp), _pp);
|
||||
return(qx, qy, qz);
|
||||
}
|
||||
|
||||
/// @dev Doubles a points (x, y, z).
|
||||
/// @param _x coordinate x of P1
|
||||
/// @param _y coordinate y of P1
|
||||
/// @param _z coordinate z of P1
|
||||
/// @param _aa the a scalar in the curve equation
|
||||
/// @param _pp the modulus
|
||||
/// @return (qx, qy, qz) 2P in Jacobian
|
||||
function jacDouble(
|
||||
uint256 _x,
|
||||
uint256 _y,
|
||||
uint256 _z,
|
||||
uint256 _aa,
|
||||
uint256 _pp)
|
||||
internal pure returns (uint256, uint256, uint256)
|
||||
{
|
||||
if (_z == 0)
|
||||
return (_x, _y, _z);
|
||||
|
||||
// We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5
|
||||
// Note: there is a bug in the paper regarding the m parameter, M=3*(x1^2)+a*(z1^4)
|
||||
// x, y, z at this point represent the squares of _x, _y, _z
|
||||
uint256 x = mulmod(_x, _x, _pp); //x1^2
|
||||
uint256 y = mulmod(_y, _y, _pp); //y1^2
|
||||
uint256 z = mulmod(_z, _z, _pp); //z1^2
|
||||
|
||||
// s
|
||||
uint s = mulmod(4, mulmod(_x, y, _pp), _pp);
|
||||
// m
|
||||
uint m = addmod(mulmod(3, x, _pp), mulmod(_aa, mulmod(z, z, _pp), _pp), _pp);
|
||||
|
||||
// x, y, z at this point will be reassigned and rather represent qx, qy, qz from the paper
|
||||
// This allows to reduce the gas cost and stack footprint of the algorithm
|
||||
// qx
|
||||
x = addmod(mulmod(m, m, _pp), _pp - addmod(s, s, _pp), _pp);
|
||||
// qy = -8*y1^4 + M(S-T)
|
||||
y = addmod(mulmod(m, addmod(s, _pp - x, _pp), _pp), _pp - mulmod(8, mulmod(y, y, _pp), _pp), _pp);
|
||||
// qz = 2*y1*z1
|
||||
z = mulmod(2, mulmod(_y, _z, _pp), _pp);
|
||||
|
||||
return (x, y, z);
|
||||
}
|
||||
|
||||
/// @dev Multiply point (x, y, z) times d.
|
||||
/// @param _d scalar to multiply
|
||||
/// @param _x coordinate x of P1
|
||||
/// @param _y coordinate y of P1
|
||||
/// @param _z coordinate z of P1
|
||||
/// @param _aa constant of curve
|
||||
/// @param _pp the modulus
|
||||
/// @return (qx, qy, qz) d*P1 in Jacobian
|
||||
function jacMul(
|
||||
uint256 _d,
|
||||
uint256 _x,
|
||||
uint256 _y,
|
||||
uint256 _z,
|
||||
uint256 _aa,
|
||||
uint256 _pp)
|
||||
internal pure returns (uint256, uint256, uint256)
|
||||
{
|
||||
// Early return in case that `_d == 0`
|
||||
if (_d == 0) {
|
||||
return (_x, _y, _z);
|
||||
}
|
||||
|
||||
uint256 remaining = _d;
|
||||
uint256 qx = 0;
|
||||
uint256 qy = 0;
|
||||
uint256 qz = 1;
|
||||
|
||||
// Double and add algorithm
|
||||
while (remaining != 0) {
|
||||
if ((remaining & 1) != 0) {
|
||||
(qx, qy, qz) = jacAdd(
|
||||
qx,
|
||||
qy,
|
||||
qz,
|
||||
_x,
|
||||
_y,
|
||||
_z,
|
||||
_pp);
|
||||
}
|
||||
remaining = remaining / 2;
|
||||
(_x, _y, _z) = jacDouble(
|
||||
_x,
|
||||
_y,
|
||||
_z,
|
||||
_aa,
|
||||
_pp);
|
||||
}
|
||||
return (qx, qy, qz);
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "../curves/Bn254.sol";
|
||||
import "../Verifier.sol";
|
||||
|
||||
library Bn254Verifier {
|
||||
|
||||
|
||||
function _verifyProof(Verifier.Proof memory proof) internal view returns (bool) {
|
||||
// var first: blst_p1
|
||||
// for qelem in q :
|
||||
// var prod: blst_p1
|
||||
// prod.blst_p1_mult(hashNameI(tau.t.name, qelem.I), qelem.V, 255)
|
||||
// first.blst_p1_add_or_double(first, prod)
|
||||
// doAssert(blst_p1_on_curve(first).bool)
|
||||
Curve.G1Point memory first;
|
||||
for (uint256 i = 0; i<proof.q.length; i++) {
|
||||
Verifier.QElement memory qelem = proof.q[i];
|
||||
bytes32 namei = sha256(abi.encodePacked(proof.name, qelem.i));
|
||||
// Step 4: arbitraty string to point and check if it is on curve
|
||||
uint256 hPointX = uint256(namei);
|
||||
Curve.G1Point memory h = Bn254.HashToPoint(hPointX);
|
||||
// TODO: Where does 255 get used???
|
||||
Curve.G1Point memory prod = Bn254.g1mul(h, uint256(qelem.v));
|
||||
first = Bn254.g1add(first, prod);
|
||||
require(Bn254.isOnCurve(first), "must be on Bn254 curve");
|
||||
}
|
||||
// let us = tau.t.u
|
||||
// var second: blst_p1
|
||||
// for j in 0 ..< len(us) :
|
||||
// var prod: blst_p1
|
||||
// prod.blst_p1_mult(us[j], mus[j], 255)
|
||||
// second.blst_p1_add_or_double(second, prod)
|
||||
// doAssert(blst_p1_on_curve(second).bool)
|
||||
Curve.G1Point[] memory us = proof.u;
|
||||
Curve.G1Point memory second;
|
||||
for (uint256 j = 0; j<us.length; j++) {
|
||||
// TODO: Where does 255 get used???
|
||||
Curve.G1Point memory prod = Bn254.g1mul(us[j], proof.mus[j]);
|
||||
second = Bn254.g1add(second, prod);
|
||||
require(Bn254.isOnCurve(second), "must be on Bn254 curve");
|
||||
}
|
||||
|
||||
// var sum: blst_p1
|
||||
// sum.blst_p1_add_or_double(first, second)
|
||||
Curve.G1Point memory sum = Bn254.g1add(first, second);
|
||||
|
||||
// var g{.noInit.}: blst_p2
|
||||
// g.blst_p2_from_affine(BLS12_381_G2)
|
||||
// TODO: do we need to convert Bn254.P2() to/from affine???
|
||||
|
||||
// return verifyPairings(sum, spk.key, sigma, g)
|
||||
return Bn254.pairingProd2(sum, proof.publicKey, proof.sigma, Bn254.P2());
|
||||
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,9 @@ describe("Bn254", function () {
|
||||
})
|
||||
|
||||
it("explicit sum and scalar prod are the same", async function () {
|
||||
let fRes = await bn254.f()
|
||||
console.log("f result: ")
|
||||
console.log(JSON.stringify(fRes, null, 2))
|
||||
expect(await bn254.f()).to.be.true
|
||||
})
|
||||
|
||||
@ -29,13 +32,38 @@ describe("Bn254", function () {
|
||||
expect(await bn254.g()).to.be.true
|
||||
})
|
||||
|
||||
it("points should be paired correctly", async function () {
|
||||
expect(await bn254.pair()).to.be.true
|
||||
it("fails when first point is not on Bn254 curve", async function () {
|
||||
let proof = {
|
||||
q: [
|
||||
{ i: -1, v: 1 },
|
||||
{ i: -2, v: 2 },
|
||||
{ i: -3, v: 3 },
|
||||
],
|
||||
mus: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
|
||||
sigma: { x: 1, y: 2 },
|
||||
u: [
|
||||
{ x: 1, y: 2 },
|
||||
{ x: 2, y: 2 },
|
||||
{ x: 3, y: 3 },
|
||||
],
|
||||
name: ethers.utils.toUtf8Bytes("test"),
|
||||
publicKey: {
|
||||
x: [1, 2],
|
||||
y: [1, 2],
|
||||
},
|
||||
}
|
||||
await expect(bn254.verifyProof(proof)).to.be.revertedWith(
|
||||
"elliptic curve multiplication failed"
|
||||
)
|
||||
})
|
||||
|
||||
it("can verify proof", async function () {
|
||||
let result = await bn254.verifyTx()
|
||||
console.log("verify result: " + JSON.stringify(result, null, 2))
|
||||
expect(await bn254.verifyTx()).to.be.true
|
||||
})
|
||||
// it("points should be paired correctly", async function () {
|
||||
// expect(await bn254.pair()).to.be.true
|
||||
// })
|
||||
|
||||
// it("can verify proof", async function () {
|
||||
// let result = await bn254.verifyTx()
|
||||
// console.log("verify result: " + JSON.stringify(result, null, 2))
|
||||
// expect(await bn254.verifyTx()).to.be.true
|
||||
// })
|
||||
})
|
||||
|
||||
@ -29,20 +29,20 @@ describe("Bn254Verifier", function () {
|
||||
{ i: -3, v: 3 },
|
||||
],
|
||||
mus: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
|
||||
sigma: { X: 1, Y: 2 },
|
||||
sigma: { x: 1, y: 2 },
|
||||
u: [
|
||||
{ X: 1, Y: 2 },
|
||||
{ X: 2, Y: 2 },
|
||||
{ X: 3, Y: 3 },
|
||||
{ x: 1, y: 2 },
|
||||
{ x: 2, y: 2 },
|
||||
{ x: 3, y: 3 },
|
||||
],
|
||||
name: ethers.utils.toUtf8Bytes("test"),
|
||||
publicKey: {
|
||||
X: [1, 2],
|
||||
Y: [1, 2],
|
||||
x: [1, 2],
|
||||
y: [1, 2],
|
||||
},
|
||||
}
|
||||
await expect(verifier.verifyProof(proof)).to.be.revertedWith(
|
||||
"must be on Bn254 curve"
|
||||
"elliptic curve multiplication failed"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user