diff --git a/contracts/Proofs.sol b/contracts/Proofs.sol index 9d33063..0e6d521 100644 --- a/contracts/Proofs.sol +++ b/contracts/Proofs.sol @@ -134,6 +134,13 @@ contract Proofs { return _isProofRequired(id, currentPeriod()); } + function _willProofBeRequired(bytes32 id) internal view returns (bool) { + bool isRequired; + uint8 pointer; + (isRequired, pointer) = _getProofRequirement(id, currentPeriod()); + return isRequired && pointer < downtime; + } + function _submitProof(bytes32 id, Types.Proof calldata proof) internal { require(proof._verifyProof(), "Invalid proof"); require(!received[id][currentPeriod()], "Proof already submitted"); @@ -152,5 +159,5 @@ contract Proofs { missed[id] += 1; } - event ProofSubmitted(bytes32 id, bytes proof); + event ProofSubmitted(bytes32 id, Types.Proof proof); } diff --git a/contracts/ecc/Types.sol b/contracts/ecc/Types.sol index 32780fa..be2af32 100644 --- a/contracts/ecc/Types.sol +++ b/contracts/ecc/Types.sol @@ -28,7 +28,7 @@ library Types { struct Proof { // TODO: should `q` be bounded? QElement[] q; - uint256[10] mus; + uint256[] mus; // sigma is probably only the x coordinate // (https://github.com/supranational/blst#serialization-format) G1Point sigma; diff --git a/contracts/ecc/curves/Bn254.sol b/contracts/ecc/curves/Bn254.sol index 00def0b..e726852 100644 --- a/contracts/ecc/curves/Bn254.sol +++ b/contracts/ecc/curves/Bn254.sol @@ -76,7 +76,7 @@ library Bn254 { pure returns (bool) { - return BN256G2._isOnCurve(p1.x[0], p1.y[0], p1.x[1], p1.y[1]); + return BN256G2._isOnCurve(p1.x[0], p1.x[1], p1.y[0], p1.y[1]); } /// @dev Derives the y coordinate from a compressed-format point x [[SEC-1]](https://www.secg.org/SEC1-Ver-1.0.pdf). @@ -163,15 +163,18 @@ library Bn254 { 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 + s.y[1] // y imaginary coordinate of point S ] ); } function _verifyProof(Types.Proof memory proof) internal returns (bool) { require(_isOnCurve(proof.sigma), "proof generated incorrectly"); - require(_isOnCurve(proof.publicKey), "proof keys generated incorrectly"); + require(_isOnCurve(proof.publicKey), "public key not on Bn254 curve"); require(proof.name.length > 0, "proof name must be provided"); + require(proof.mus.length == proof.q.length && + proof.q.length == proof.u.length, + "setup, query, and proof length mismatch"); // var first: blst_p1 // for qelem in q : // var prod: blst_p1 diff --git a/test/Bn254.test.js b/test/Bn254.test.js index d47c0af..7765143 100644 --- a/test/Bn254.test.js +++ b/test/Bn254.test.js @@ -140,7 +140,7 @@ describe("Bn254", function () { { i: -2, v: 2 }, { i: -3, v: 3 }, ], - mus: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], + mus: [1, 2, 3], sigma: { x: 111, y: 222 }, // Wrong u: [ { x: 1, y: 2 }, @@ -165,7 +165,7 @@ describe("Bn254", function () { { i: -2, v: 2 }, { i: -3, v: 3 }, ], - mus: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], + mus: [1, 2, 3], sigma: { x: 1, y: 2 }, u: [ { x: 1, y: 2 }, @@ -174,12 +174,13 @@ describe("Bn254", function () { ], name: ethers.utils.toUtf8Bytes("test"), publicKey: { - x: [111, 222], // Wrong + // Wrong + x: [1, 2], y: [1, 2], }, } expect(bn254.callStatic.verifyProof(proof)).to.be.revertedWith( - "proof keys generated incorrectly" + "public key not on Bn254 curve" ) }) @@ -190,7 +191,7 @@ describe("Bn254", function () { { i: -2, v: 2 }, { i: -3, v: 3 }, ], - mus: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], + mus: [1, 2, 3], sigma: { x: 1, y: 2 }, u: [ { x: 1, y: 2 }, @@ -215,7 +216,7 @@ describe("Bn254", function () { { i: -2, v: 2 }, { i: -3, v: 3 }, ], - mus: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], + mus: [1, 2, 3], sigma: { x: 1, y: 2 }, u: [ { x: 111, y: 222 }, // Wrong @@ -232,4 +233,82 @@ describe("Bn254", function () { "incorrect proof setup" ) }) + + it("should fail proof verification with length mismatch", 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], // Wrong + sigma: { x: 1, y: 2 }, + u: [ + { x: 1, y: 2 }, + { x: 1, y: 2 }, + { x: 1, y: 2 }, + ], + name: ethers.utils.toUtf8Bytes("test"), + publicKey: { + x: [1, 2], + y: [1, 2], + }, + } + expect(bn254.callStatic.verifyProof(proof)).to.be.revertedWith( + "setup, query, and proof length mismatch" + ) + }) + + it("should fail to verify a proof with an incorrect public key", async function () { + let proof = { + q: [ + { + i: 0, + v: "0x0c31b73f16d1c31de28dd4651a9b5f62a9212938b4b041f3f4db25a65539ce9c", + }, + ], + mus: [ + "0x25920f9d4590bcb099933cae3afeda6ad9a0e4bb8602f167c31d1ab332f6718b", + ], + sigma: { + x: "0x24e9c16ab07296e7a16c06d91c10fd52eda14798ca5bf6a7e16a98d528bd199e", + y: "0x204ab8989fc6a373baa71bed526ed0f63705dd2617ae6b9f9df9e115f5e8fae4", + }, + u: [ + { + x: "0x102bd2e684495754b9ef8edd0aa70cf628fb8666c692a11ee89ad9fbfeb11a02", + y: "0x245369d1ea21fbaaea3264b9867ea74c121e72f66a94b3b785b9ce742be6c8f6", + }, + ], + name: ethers.utils.toUtf8Bytes( + "91de7326fea6823a95d65880e7d9c695de96d84e0c1292f1fe6beae6b33d26927699" + + "22796b3c2f213e2f667202babb53a97ff54443520998192b82da11a1de7c2e90875f" + + "84b4fed5f31622093fe57d89669f660e8fc731bf22293529a141ece41d4060e7a664" + + "5bd8fe0c1172ae377fdc5ae73889d34f81d2dbf105c3f756b4e0a253451a5a7a3cfb" + + "fb253b21c49c59701513b9ad9f8a9b192c3cc7232024254be4173785a7c08f32a60c" + + "3425d74c263584078604d2527ffdec60c15b050877eedd8c73700991f4efd04d7639" + + "14b73d8179e25aa6bd4ee6ae0fcd0b11f8c502baf828e0cbbd3a6dfd712894f10e8c" + + "96a90f454ef4b2a22ef19ea550555e324d69e977a9e5a8bd57b34563fb199530919a" + + "d80acd8d2f2c1eb4c9b48d2e57e6305131f1878b68c45d6b1fa35ab0e6bf44001f81" + + "1f613538f11f2efaba53e339d521074d8c14756c39c9b0b5cc68b14779cb223cd2e1" + + "c08bacc55f6499b72ea5ceca033efb6826c699d225ed772428a2153da091f6f6536c" + + "8df25e51e861526e2f9bb130f33c6d03c94f65bd3a3f4a6f0e7ab80ee5303b275667" + + "a922ae87102e6862a80fa8840ef291ec6a66a1ee94818e6b715fba1546a2aeffae38" + + "078986ecdc6df4305836e17dd4633b3b9bbd0f22d8e1a0292f4940509d98fa7ee0d5" + + "2078c85080458fdab6b4bf9a42400248e8b4e9530fa9f1cd421e98f40ee8585434e4" + + "98d2" + ), + publicKey: { + x: [ + "0x07d42b42c4eddef5a05309382acd6facd59cee75d1d811cbbcd52b1b55b8e31b", + "0x21e4617026fdf43d59893c2ad8fb00acb4167ae895e80c58a5d013928a601184", + ], + y: [ + "0x0e86e2f05fb3e72609b0cfea77633eca05f4bf34851874d84e5a2c2f2985fa7d", + "0x1d20bf4bc725cc14d0d0a8bc98b3391582c48ad99a41669a5349a5cab5864e10", + ], + }, + } + expect(await bn254.callStatic.verifyProof(proof)).to.be.equal(false) + }) }) diff --git a/test/Proofs.test.js b/test/Proofs.test.js index 1786825..47f4688 100644 --- a/test/Proofs.test.js +++ b/test/Proofs.test.js @@ -141,7 +141,25 @@ describe("Proofs", function () { }) describe("when proofs are required", function () { - const proof = hexlify(randomBytes(42)) + 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: 1, y: 2 }, + { x: 1, y: 2 }, + ], + name: ethers.utils.toUtf8Bytes("test"), + publicKey: { + x: [1, 2], + y: [1, 2], + }, + } beforeEach(async function () { await proofs.expectProofs(id, probability, duration) @@ -177,7 +195,9 @@ describe("Proofs", function () { }) it("submits a correct proof", async function () { - let proof = { + // TODO: update to a correct proof. Waiting on valid proof inputs from + // https://github.com/status-im/nim-codex/pulls/101. + proof = { q: [ { i: -1, v: 1 }, { i: -2, v: 2 }, @@ -200,7 +220,7 @@ describe("Proofs", function () { }) it("fails proof submission when proof is incorrect", async function () { - let proof = { + proof = { q: [ { i: -1, v: 1 }, { i: -2, v: 2 }, @@ -232,7 +252,7 @@ describe("Proofs", function () { it("fails proof submission when already submitted", async function () { await advanceTimeTo(periodEnd(periodOf(await currentTime()))) - let proof = { + proof = { q: [ { i: -1, v: 1 }, { i: -2, v: 2 }, @@ -286,7 +306,7 @@ describe("Proofs", function () { it("does not mark a submitted proof as missing", async function () { await waitUntilProofIsRequired(id) let submittedPeriod = periodOf(await currentTime()) - let proof = { + proof = { q: [ { i: -1, v: 1 }, { i: -2, v: 2 },