mirror of
https://github.com/codex-storage/codex-contracts-eth.git
synced 2025-02-21 07:38:20 +00:00
WIP: reorg to allow for more curves
Current tests are failing because ECMUL is not a valid opcode in hardhat. Exploring alternatives.
This commit is contained in:
parent
98c2555036
commit
976ae66cab
@ -1,9 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "./curves/Bn254Proofs.sol";
|
||||
import "./ecc/verifiers/Bn254Verifier.sol";
|
||||
import "./ecc/Verifier.sol";
|
||||
|
||||
contract Proofs {
|
||||
using Bn254Verifier for Verifier.Proof;
|
||||
|
||||
uint256 private immutable period;
|
||||
uint256 private immutable timeout;
|
||||
uint8 private immutable downtime;
|
||||
@ -131,8 +134,8 @@ contract Proofs {
|
||||
return _isProofRequired(id, currentPeriod());
|
||||
}
|
||||
|
||||
function _submitProof(bytes32 id, bytes calldata proof) internal {
|
||||
require(proof.length > 0, "Invalid proof"); // TODO: replace by actual check
|
||||
function _submitProof(bytes32 id, Verifier.Proof calldata proof) internal {
|
||||
require(proof._verifyProof(), "Invalid proof");
|
||||
require(!received[id][currentPeriod()], "Proof already submitted");
|
||||
received[id][currentPeriod()] = true;
|
||||
emit ProofSubmitted(id, proof);
|
||||
|
@ -86,7 +86,7 @@ contract Storage is Collateral, Marketplace, Proofs {
|
||||
return _getPointer(id);
|
||||
}
|
||||
|
||||
function submitProof(bytes32 contractId, bytes calldata proof) public {
|
||||
function submitProof(bytes32 contractId, Verifier.Proof calldata proof) public {
|
||||
_submitProof(contractId, proof);
|
||||
}
|
||||
|
||||
|
@ -2,47 +2,48 @@
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "./curves/Bn254.sol";
|
||||
import "./ecc/curves/Bn254.sol";
|
||||
import "./ecc/Curve.sol";
|
||||
|
||||
contract TestBn254 {
|
||||
using Bn254 for *;
|
||||
struct VerifyingKey {
|
||||
Bn254.G2Point A;
|
||||
Bn254.G1Point B;
|
||||
Bn254.G2Point C;
|
||||
Bn254.G2Point gamma;
|
||||
Bn254.G1Point gammaBeta1;
|
||||
Bn254.G2Point gammaBeta2;
|
||||
Bn254.G2Point Z;
|
||||
Bn254.G1Point[] IC;
|
||||
Curve.G2Point A;
|
||||
Curve.G1Point B;
|
||||
Curve.G2Point C;
|
||||
Curve.G2Point gamma;
|
||||
Curve.G1Point gammaBeta1;
|
||||
Curve.G2Point gammaBeta2;
|
||||
Curve.G2Point Z;
|
||||
Curve.G1Point[] IC;
|
||||
}
|
||||
struct Proof {
|
||||
Bn254.G1Point A;
|
||||
Bn254.G1Point A_p;
|
||||
Bn254.G2Point B;
|
||||
Bn254.G1Point B_p;
|
||||
Bn254.G1Point C;
|
||||
Bn254.G1Point C_p;
|
||||
Bn254.G1Point K;
|
||||
Bn254.G1Point H;
|
||||
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;
|
||||
}
|
||||
function f() internal view returns (bool) {
|
||||
Bn254.G1Point memory p1;
|
||||
Bn254.G1Point memory p2;
|
||||
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;
|
||||
Bn254.G1Point memory explict_sum = Bn254.g1add(p1, p2);
|
||||
Bn254.G1Point memory scalar_prod = Bn254.g1mul(p1, 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 g() internal view returns (bool) {
|
||||
Bn254.G1Point memory x = Bn254.g1add(Bn254.P1(), Bn254.g1neg(Bn254.P1()));
|
||||
function g() public view returns (bool) {
|
||||
Curve.G1Point memory x = Bn254.g1add(Bn254.P1(), Bn254.g1neg(Bn254.P1()));
|
||||
// should be zero
|
||||
return (x.X == 0 && x.Y == 0);
|
||||
}
|
||||
function testMul() internal view returns (bool) {
|
||||
Bn254.G1Point memory p;
|
||||
function testMul() public view returns (bool) {
|
||||
Curve.G1Point memory p;
|
||||
// @TODO The points here are reported to be not well-formed
|
||||
p.X = 14125296762497065001182820090155008161146766663259912659363835465243039841726;
|
||||
p.Y = 16229134936871442251132173501211935676986397196799085184804749187146857848057;
|
||||
@ -51,15 +52,15 @@ contract TestBn254 {
|
||||
p.X == 18256332256630856740336504687838346961237861778318632856900758565550522381207 &&
|
||||
p.Y == 6976682127058094634733239494758371323697222088503263230319702770853579280803;
|
||||
}
|
||||
function pair() internal view returns (bool) {
|
||||
Bn254.G2Point memory fiveTimesP2 = Bn254.G2Point(
|
||||
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;
|
||||
Bn254.G1Point[] memory g1points = new Bn254.G1Point[](2);
|
||||
Bn254.G2Point[] memory g2points = new Bn254.G2Point[](2);
|
||||
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();
|
||||
@ -78,30 +79,30 @@ contract TestBn254 {
|
||||
return true;
|
||||
}
|
||||
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.A = Bn254.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]);
|
||||
vk.B = Bn254.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84);
|
||||
vk.C = Bn254.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]);
|
||||
vk.gamma = Bn254.G2Point([0x25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1, 0x22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d], [0x065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68, 0x06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb]);
|
||||
vk.gammaBeta1 = Bn254.G1Point(0x15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21, 0x14db745c6780e9df549864cec19c2daf4531f6ec0c89cc1c7436cc4d8d300c6d);
|
||||
vk.gammaBeta2 = Bn254.G2Point([0x1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e, 0x283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39], [0x140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e, 0x0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4]);
|
||||
vk.Z = Bn254.G2Point([0x217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29, 0x0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c], [0x26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855, 0x2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7]);
|
||||
vk.IC = new Bn254.G1Point[](10);
|
||||
vk.IC[0] = Bn254.G1Point(0x0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a, 0x044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf);
|
||||
vk.IC[1] = Bn254.G1Point(0x1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc, 0x2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb);
|
||||
vk.IC[2] = Bn254.G1Point(0x1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f, 0x042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db);
|
||||
vk.IC[3] = Bn254.G1Point(0x17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5, 0x02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1);
|
||||
vk.IC[4] = Bn254.G1Point(0x0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d, 0x0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b);
|
||||
vk.IC[5] = Bn254.G1Point(0x232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8, 0x2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7);
|
||||
vk.IC[6] = Bn254.G1Point(0x09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe, 0x18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4);
|
||||
vk.IC[7] = Bn254.G1Point(0x0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a, 0x18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e);
|
||||
vk.IC[8] = Bn254.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e);
|
||||
vk.IC[9] = Bn254.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30);
|
||||
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
|
||||
Bn254.G1Point memory vk_x = Bn254.G1Point(0, 0);
|
||||
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]);
|
||||
@ -124,16 +125,16 @@ contract TestBn254 {
|
||||
function verifyTx() internal returns (bool r) {
|
||||
uint[] memory input = new uint[](9);
|
||||
Proof memory proof;
|
||||
proof.A = Bn254.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497);
|
||||
proof.A_p = Bn254.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366);
|
||||
proof.B = Bn254.G2Point(
|
||||
proof.A = Curve.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497);
|
||||
proof.A_p = Curve.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366);
|
||||
proof.B = Curve.G2Point(
|
||||
[8176651290984905087450403379100573157708110416512446269839297438960217797614, 15588556568726919713003060429893850972163943674590384915350025440408631945055],
|
||||
[15347511022514187557142999444367533883366476794364262773195059233657571533367, 4265071979090628150845437155927259896060451682253086069461962693761322642015]);
|
||||
proof.B_p = Bn254.G1Point(2979746655438963305714517285593753729335852012083057917022078236006592638393, 6470627481646078059765266161088786576504622012540639992486470834383274712950);
|
||||
proof.C = Bn254.G1Point(6851077925310461602867742977619883934042581405263014789956638244065803308498, 10336382210592135525880811046708757754106524561907815205241508542912494488506);
|
||||
proof.C_p = Bn254.G1Point(12491625890066296859584468664467427202390981822868257437245835716136010795448, 13818492518017455361318553880921248537817650587494176379915981090396574171686);
|
||||
proof.H = Bn254.G1Point(12091046215835229523641173286701717671667447745509192321596954139357866668225, 14446807589950902476683545679847436767890904443411534435294953056557941441758);
|
||||
proof.K = Bn254.G1Point(21341087976609916409401737322664290631992568431163400450267978471171152600502, 2942165230690572858696920423896381470344658299915828986338281196715687693170);
|
||||
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;
|
||||
|
@ -56,7 +56,7 @@ contract TestProofs is Proofs {
|
||||
return _getPointer(id);
|
||||
}
|
||||
|
||||
function submitProof(bytes32 id, bytes calldata proof) public {
|
||||
function submitProof(bytes32 id, Verifier.Proof calldata proof) public {
|
||||
_submitProof(id, proof);
|
||||
}
|
||||
|
||||
|
16
contracts/ecc/Curve.sol
Normal file
16
contracts/ecc/Curve.sol
Normal file
@ -0,0 +1,16 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
25
contracts/ecc/Verifier.sol
Normal file
25
contracts/ecc/Verifier.sol
Normal file
@ -0,0 +1,25 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "../Curve.sol";
|
||||
|
||||
library Bn254 {
|
||||
// p = p(u) = 36u^4 + 36u^3 + 24u^2 + 6u + 1
|
||||
uint256 internal constant FIELD_ORDER =
|
||||
@ -20,16 +22,16 @@ library Bn254 {
|
||||
uint256 internal constant CURVE_A =
|
||||
0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52;
|
||||
|
||||
struct G1Point {
|
||||
uint256 X;
|
||||
uint256 Y;
|
||||
}
|
||||
// struct Curve.G1Point {
|
||||
// uint256 X;
|
||||
// uint256 Y;
|
||||
// }
|
||||
|
||||
// Encoding of field elements is: X[0] * z + X[1]
|
||||
struct G2Point {
|
||||
uint256[2] X;
|
||||
uint256[2] 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) {
|
||||
@ -49,11 +51,11 @@ library Bn254 {
|
||||
}
|
||||
|
||||
/// @return the generator of G1
|
||||
function P1() internal pure returns (G1Point memory) {
|
||||
return G1Point(1, 2);
|
||||
function P1() internal pure returns (Curve.G1Point memory) {
|
||||
return Curve.G1Point(1, 2);
|
||||
}
|
||||
|
||||
function HashToPoint(uint256 s) internal view returns (G1Point memory g) {
|
||||
function HashToPoint(uint256 s) internal view returns (Curve.G1Point memory g) {
|
||||
uint256 beta = 0;
|
||||
uint256 y = 0;
|
||||
|
||||
@ -65,7 +67,7 @@ library Bn254 {
|
||||
|
||||
// y^2 == beta
|
||||
if (beta == mulmod(y, y, FIELD_ORDER)) {
|
||||
return G1Point(x, y);
|
||||
return Curve.G1Point(x, y);
|
||||
}
|
||||
|
||||
x = addmod(x, 1, FIELD_ORDER);
|
||||
@ -134,9 +136,9 @@ library Bn254 {
|
||||
}
|
||||
|
||||
/// @return the generator of G2
|
||||
function P2() internal pure returns (G2Point memory) {
|
||||
function P2() internal pure returns (Curve.G2Point memory) {
|
||||
return
|
||||
G2Point(
|
||||
Curve.G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
@ -149,18 +151,18 @@ library Bn254 {
|
||||
}
|
||||
|
||||
/// @return the negation of p, i.e. p.add(p.negate()) should be zero.
|
||||
function g1neg(G1Point memory p) internal pure returns (G1Point memory) {
|
||||
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 G1Point(0, 0);
|
||||
return G1Point(p.X, q - (p.Y % q));
|
||||
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(G1Point memory p1, G1Point memory p2)
|
||||
function g1add(Curve.G1Point memory p1, Curve.G1Point memory p2)
|
||||
internal
|
||||
view
|
||||
returns (G1Point memory r)
|
||||
returns (Curve.G1Point memory r)
|
||||
{
|
||||
uint256[4] memory input;
|
||||
input[0] = p1.X;
|
||||
@ -181,10 +183,10 @@ library Bn254 {
|
||||
|
||||
/// @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(G1Point memory p, uint256 s)
|
||||
function g1mul(Curve.G1Point memory p, uint256 s)
|
||||
internal
|
||||
view
|
||||
returns (G1Point memory r)
|
||||
returns (Curve.G1Point memory r)
|
||||
{
|
||||
uint256[3] memory input;
|
||||
input[0] = p.X;
|
||||
@ -206,7 +208,7 @@ library Bn254 {
|
||||
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||
/// return true.
|
||||
function pairing(G1Point[] memory p1, G2Point[] memory p2)
|
||||
function pairing(Curve.G1Point[] memory p1, Curve.G2Point[] memory p2)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
@ -246,13 +248,13 @@ library Bn254 {
|
||||
|
||||
/// Convenience method for a pairing check for two pairs.
|
||||
function pairingProd2(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2
|
||||
Curve.G1Point memory a1,
|
||||
Curve.G2Point memory a2,
|
||||
Curve.G1Point memory b1,
|
||||
Curve.G2Point memory b2
|
||||
) internal view returns (bool) {
|
||||
G1Point[] memory p1 = new G1Point[](2);
|
||||
G2Point[] memory p2 = new G2Point[](2);
|
||||
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;
|
||||
@ -262,15 +264,15 @@ library Bn254 {
|
||||
|
||||
/// Convenience method for a pairing check for three pairs.
|
||||
function pairingProd3(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2
|
||||
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) {
|
||||
G1Point[] memory p1 = new G1Point[](3);
|
||||
G2Point[] memory p2 = new G2Point[](3);
|
||||
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;
|
||||
@ -282,17 +284,17 @@ library Bn254 {
|
||||
|
||||
/// Convenience method for a pairing check for four pairs.
|
||||
function pairingProd4(
|
||||
G1Point memory a1,
|
||||
G2Point memory a2,
|
||||
G1Point memory b1,
|
||||
G2Point memory b2,
|
||||
G1Point memory c1,
|
||||
G2Point memory c2,
|
||||
G1Point memory d1,
|
||||
G2Point memory d2
|
||||
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) {
|
||||
G1Point[] memory p1 = new G1Point[](4);
|
||||
G2Point[] memory p2 = new G2Point[](4);
|
||||
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;
|
||||
@ -304,7 +306,7 @@ library Bn254 {
|
||||
return pairing(p1, p2);
|
||||
}
|
||||
|
||||
function isOnCurve(Bn254.G1Point memory g1) internal pure returns (bool) {
|
||||
function isOnCurve(Curve.G1Point memory g1) internal pure returns (bool) {
|
||||
uint256 aa = Bn254.A();
|
||||
uint256 bb = Bn254.B();
|
||||
uint256 pp = Bn254.P();
|
@ -2,43 +2,28 @@
|
||||
|
||||
pragma solidity >=0.8.0 <=0.8.13;
|
||||
|
||||
import "./Bn254.sol";
|
||||
import "../curves/Bn254.sol";
|
||||
import "../Verifier.sol";
|
||||
|
||||
library Bn254Proofs {
|
||||
struct QElement {
|
||||
int64 i;
|
||||
uint256 v;
|
||||
}
|
||||
library Bn254Verifier {
|
||||
|
||||
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)
|
||||
Bn254.G1Point sigma;
|
||||
// TODO: should `u` be bounded?
|
||||
Bn254.G1Point[] u;
|
||||
bytes name;
|
||||
Bn254.G2Point publicKey;
|
||||
}
|
||||
|
||||
function verifyProof(Proof memory proof) internal view returns (bool) {
|
||||
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)
|
||||
Bn254.G1Point memory first;
|
||||
Curve.G1Point memory first;
|
||||
for (uint256 i = 0; i<proof.q.length; i++) {
|
||||
QElement memory qelem = proof.q[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);
|
||||
Bn254.G1Point memory h = Bn254.HashToPoint(hPointX);
|
||||
Curve.G1Point memory h = Bn254.HashToPoint(hPointX);
|
||||
// TODO: Where does 255 get used???
|
||||
Bn254.G1Point memory prod = Bn254.g1mul(h, uint256(qelem.v));
|
||||
Curve.G1Point memory prod = Bn254.g1mul(h, uint256(qelem.v));
|
||||
first = Bn254.g1add(first, prod);
|
||||
require(Bn254.isOnCurve(first), "must be on Bn254 curve");
|
||||
}
|
||||
@ -49,18 +34,18 @@ library Bn254Proofs {
|
||||
// prod.blst_p1_mult(us[j], mus[j], 255)
|
||||
// second.blst_p1_add_or_double(second, prod)
|
||||
// doAssert(blst_p1_on_curve(second).bool)
|
||||
Bn254.G1Point[] memory us = proof.u;
|
||||
Bn254.G1Point memory second;
|
||||
Curve.G1Point[] memory us = proof.u;
|
||||
Curve.G1Point memory second;
|
||||
for (uint256 j = 0; j<us.length; j++) {
|
||||
// TODO: Where does 255 get used???
|
||||
Bn254.G1Point memory prod = Bn254.g1mul(us[j], proof.mus[j]);
|
||||
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)
|
||||
Bn254.G1Point memory sum = Bn254.g1add(first, second);
|
||||
Curve.G1Point memory sum = Bn254.g1add(first, second);
|
||||
|
||||
// var g{.noInit.}: blst_p2
|
||||
// g.blst_p2_from_affine(BLS12_381_G2)
|
38
test/Bn254.test.js
Normal file
38
test/Bn254.test.js
Normal file
@ -0,0 +1,38 @@
|
||||
const { expect } = require("chai")
|
||||
const { ethers } = require("hardhat")
|
||||
const {
|
||||
snapshot,
|
||||
revert,
|
||||
ensureMinimumBlockHeight,
|
||||
currentTime,
|
||||
advanceTime,
|
||||
advanceTimeTo,
|
||||
} = require("./evm")
|
||||
const { periodic } = require("./time")
|
||||
|
||||
describe("Bn254", function () {
|
||||
let bn254
|
||||
|
||||
beforeEach(async function () {
|
||||
await snapshot()
|
||||
await ensureMinimumBlockHeight(256)
|
||||
const Bn254 = await ethers.getContractFactory("TestBn254")
|
||||
bn254 = await Bn254.deploy()
|
||||
})
|
||||
|
||||
afterEach(async function () {
|
||||
await revert()
|
||||
})
|
||||
|
||||
it("explicit sum and scalar prod are the same", async function () {
|
||||
expect(await bn254.f()).to.be.true
|
||||
})
|
||||
|
||||
it("adding point to negation of itself should be zero", async function () {
|
||||
expect(await bn254.g()).to.be.true
|
||||
})
|
||||
|
||||
it("multiplication along BN254 emits expected values", async function () {
|
||||
expect(await bn254.testMul()).to.be.true
|
||||
})
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user