From 149ab5383a36682f34e93058c9aed3b98de0b453 Mon Sep 17 00:00:00 2001 From: dwebchapey Date: Mon, 22 Nov 2021 12:05:03 +0530 Subject: [PATCH 1/9] feat: zokrates worker and verifier sol to g16 --- config/default.js | 4 +- nightfall-deployer/contracts/Verifier.sol | 98 ++++++++++--------- zokrates-worker/src/services/generateKeys.mjs | 8 +- .../src/services/generateProof.mjs | 4 +- .../src/zokrates-lib/generate-proof.mjs | 4 +- zokrates-worker/src/zokrates-lib/setup.mjs | 4 +- zokrates-worker/src/zokrates-lib/verify.mjs | 4 +- 7 files changed, 68 insertions(+), 58 deletions(-) diff --git a/config/default.js b/config/default.js index 7b50191d2..b43fa12a8 100644 --- a/config/default.js +++ b/config/default.js @@ -53,8 +53,8 @@ module.exports = { onTimeout: false, }, }, - PROVING_SCHEME: process.env.PROVING_SCHEME || 'gm17', - BACKEND: process.env.BACKEND || 'libsnark', + PROVING_SCHEME: process.env.PROVING_SCHEME || 'g16', + BACKEND: process.env.BACKEND || 'bellman', CURVE: process.env.CURVE || 'bn128', PROOF_QUEUE: 'generate-proof', BN128_GROUP_ORDER: 21888242871839275222246405745257275088548364400416034343698204186575808495617n, diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index dfd402de1..935bd109b 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -41,12 +41,11 @@ library Verifier { } struct Verification_Key_GM17 { - Pairing.G2Point H; - Pairing.G1Point Galpha; - Pairing.G2Point Hbeta; - Pairing.G1Point Ggamma; - Pairing.G2Point Hgamma; - Pairing.G1Point[2] query; + Pairing.G1Point alpha; + Pairing.G2Point beta; + Pairing.G2Point gamma; + Pairing.G2Point delta; + Pairing.G1Point[] gamma_abc; } function verify(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public returns (bool result) { @@ -69,21 +68,20 @@ library Verifier { proof.B = Pairing.G2Point([_proof[2], _proof[3]], [_proof[4], _proof[5]]); proof.C = Pairing.G1Point(_proof[6], _proof[7]); - vk.H = Pairing.G2Point([_vk[0],_vk[1]],[_vk[2],_vk[3]]); - vk.Galpha = Pairing.G1Point(_vk[4],_vk[5]); - vk.Hbeta = Pairing.G2Point([_vk[6],_vk[7]],[_vk[8],_vk[9]]); - vk.Ggamma = Pairing.G1Point(_vk[10],_vk[11]); - vk.Hgamma = Pairing.G2Point([_vk[12],_vk[13]],[_vk[14],_vk[15]]); + vk.alpha = Pairing.G1Point(_vk[4],_vk[5]); + vk.beta = Pairing.G2Point([_vk[6],_vk[7]],[_vk[8],_vk[9]]); + vk.gamma = Pairing.G2Point([_vk[10],_vk[11]],[_vk[12],_vk[13]]); + vk.delta = Pairing.G2Point([_vk[14],_vk[15]],[_vk[16],_vk[17]]); - // vk.query.length = (_vk.length - 16)/2; + // vk.gamma_abc.length = (_vk.length - 18)/2; uint j = 0; - for (uint i = 16; i < _vk.length; i+=2) { - vk.query[j++] = Pairing.G1Point(_vk[i], _vk[i+1]); + for (uint i = 18; i < _vk.length; i+=2) { + vk.gamma_abc[j++] = Pairing.G1Point(_vk[i], _vk[i+1]); } /* require(vk.query.length == 2, "Length of vk.query is incorrect!"); */ // Replacing for the above require statement so that the proof verification returns false. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works - if (vk.query.length != 2) { + if (vk.gamma_abc.length != 2) { return 1; } @@ -92,7 +90,7 @@ library Verifier { // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works bool success_sm_qpih; bool success_vkdi_sm_qpih; - (sm_qpih, success_sm_qpih) = Pairing.scalar_mul(vk.query[1], _publicInputsHash); + (sm_qpih, success_sm_qpih) = Pairing.scalar_mul(vk.gamma_abc[1], _publicInputsHash); (vk_dot_inputs, success_vkdi_sm_qpih) = Pairing.addition( vk_dot_inputs, sm_qpih @@ -105,7 +103,7 @@ library Verifier { { // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works bool success_vkdi_q; - (vk_dot_inputs, success_vkdi_q) = Pairing.addition(vk_dot_inputs, vk.query[0]); + (vk_dot_inputs, success_vkdi_q) = Pairing.addition(vk_dot_inputs, vk.gamma_abc[0]); if (!success_vkdi_q) { return 3; } @@ -117,37 +115,49 @@ library Verifier { * * e(C, H) * where psi = \sum_{i=0}^l input_i pvk.query[i] */ + // { + // Pairing.G1Point memory add_A_Galpha; + // // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works + // bool success_pp4_out_not_0; + // bool success_pp4_pairing; + // { + // bool success_add_A_Galpha; + // (add_A_Galpha, success_add_A_Galpha) = Pairing.addition(proof.A, vk.a); + // if (!success_add_A_Galpha) { + // return 4; + // } + // } + // (success_pp4_out_not_0, success_pp4_pairing) = Pairing.pairingProd4(vk.Galpha, vk.Hbeta, vk_dot_inputs, vk.Hgamma, proof.C, vk.H, Pairing.negate(add_A_Galpha), Pairing.addition2(proof.B, vk.Hbeta)); + // if (!success_pp4_out_not_0 || !success_pp4_pairing) { + // return 5; + // } + // } + + // /** + // * e(A, H^{gamma}) = e(G^{gamma}, B) + // */ + // { + // // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works + // bool success_pp2_out_not_0; + // bool success_pp2_pairing; + // (success_pp2_out_not_0, success_pp2_pairing) = Pairing.pairingProd2(proof.A, vk.Hgamma, Pairing.negate(vk.Ggamma), proof.B); + // if (!success_pp2_out_not_0 || !success_pp2_pairing) { + // return 6; + // } + // } { - Pairing.G1Point memory add_A_Galpha; - // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works bool success_pp4_out_not_0; bool success_pp4_pairing; - { - bool success_add_A_Galpha; - (add_A_Galpha, success_add_A_Galpha) = Pairing.addition(proof.A, vk.Galpha); - if (!success_add_A_Galpha) { - return 4; - } - } - (success_pp4_out_not_0, success_pp4_pairing) = Pairing.pairingProd4(vk.Galpha, vk.Hbeta, vk_dot_inputs, vk.Hgamma, proof.C, vk.H, Pairing.negate(add_A_Galpha), Pairing.addition2(proof.B, vk.Hbeta)); - if (!success_pp4_out_not_0 || !success_pp4_pairing) { - return 5; - } + (success_pp4_out_not_0,success_pp4_pairing)=Pairing.pairingProd4( + proof.A, proof.B, + Pairing.negate(vk_dot_inputs), vk.gamma, + Pairing.negate(proof.C), vk.delta, + Pairing.negate(vk.alpha), vk.beta); + + if(!success_pp4_out_not_0 || !success_pp4_pairing) { + return 1; + } } - - /** - * e(A, H^{gamma}) = e(G^{gamma}, B) - */ - { - // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works - bool success_pp2_out_not_0; - bool success_pp2_pairing; - (success_pp2_out_not_0, success_pp2_pairing) = Pairing.pairingProd2(proof.A, vk.Hgamma, Pairing.negate(vk.Ggamma), proof.B); - if (!success_pp2_out_not_0 || !success_pp2_pairing) { - return 6; - } - } - return 0; } } diff --git a/zokrates-worker/src/services/generateKeys.mjs b/zokrates-worker/src/services/generateKeys.mjs index c9249d646..17bf42961 100644 --- a/zokrates-worker/src/services/generateKeys.mjs +++ b/zokrates-worker/src/services/generateKeys.mjs @@ -5,9 +5,9 @@ import logger from '../utils/logger.mjs'; export default async function generateKeys({ filepath, - curve = 'bls12_377', - backend = 'ark', - provingScheme = 'gm17', + curve = 'bn128', + backend = 'bellman', + provingScheme = 'g16', }) { const outputPath = `./output`; const circuitsPath = `./circuits`; @@ -18,7 +18,7 @@ export default async function generateKeys({ fs.mkdirSync(`${outputPath}/${circuitDir}`, { recursive: true }); - logger.debug( + logger.info( `${circuitsPath}/${filepath}`, `${outputPath}/${circuitDir}`, `${circuitName}_out`, diff --git a/zokrates-worker/src/services/generateProof.mjs b/zokrates-worker/src/services/generateProof.mjs index e706de851..51653943e 100644 --- a/zokrates-worker/src/services/generateProof.mjs +++ b/zokrates-worker/src/services/generateProof.mjs @@ -14,8 +14,8 @@ export default async ({ transactionInputs, outputDirectoryPath, proofFileName, - backend = 'ark', - provingScheme = 'gm17', + backend = 'bellman', + provingScheme = 'g16', }) => { const outputPath = `./output`; let proof; diff --git a/zokrates-worker/src/zokrates-lib/generate-proof.mjs b/zokrates-worker/src/zokrates-lib/generate-proof.mjs index 8a204a5de..19f627e2b 100644 --- a/zokrates-worker/src/zokrates-lib/generate-proof.mjs +++ b/zokrates-worker/src/zokrates-lib/generate-proof.mjs @@ -34,8 +34,8 @@ export default async function generateProof( provingKeyPath, codePath, witnessPath, - provingScheme = 'gm17', - backend = 'ark', + provingScheme = 'g16', + backend = 'bellman', options = {}, ) { if (!fs.existsSync(codePath)) { diff --git a/zokrates-worker/src/zokrates-lib/setup.mjs b/zokrates-worker/src/zokrates-lib/setup.mjs index 9b8ecfa40..6c3604ca8 100644 --- a/zokrates-worker/src/zokrates-lib/setup.mjs +++ b/zokrates-worker/src/zokrates-lib/setup.mjs @@ -22,8 +22,8 @@ const { spawn } = childProcess; export default async function setup( codePath, outputPath = './', - provingScheme = 'gm17', - backend = 'ark', + provingScheme = 'g16', + backend = 'bellman', vkName = 'verification.key', pkName = 'proving.key', options = {}, diff --git a/zokrates-worker/src/zokrates-lib/verify.mjs b/zokrates-worker/src/zokrates-lib/verify.mjs index 39928aa93..eacd0f17a 100644 --- a/zokrates-worker/src/zokrates-lib/verify.mjs +++ b/zokrates-worker/src/zokrates-lib/verify.mjs @@ -33,8 +33,8 @@ const { writeFile } = jsonfile; export default async function verify( vk, proof, - provingScheme = 'gm17', - backend = 'ark', + provingScheme = 'g16', + backend = 'bellman', curve = 'bn128', ) { // we've provided a json proof and a verifying key but Zokrates needs to read From 9fde55440f08fe9569eec98c55400fcf3f974a54 Mon Sep 17 00:00:00 2001 From: dwebchapey Date: Tue, 23 Nov 2021 17:21:35 +0530 Subject: [PATCH 2/9] feat: modify vk structure for G16 --- common-files/classes/proof.mjs | 2 +- common-files/utils/curve-maths/curves.mjs | 2 +- nightfall-deployer/contracts/Pairing.sol | 644 ++++-------------- nightfall-deployer/contracts/Verifier.sol | 87 +-- .../migrations/2_Shield_migration.js | 3 - .../src/classes/verification-key.mjs | 12 +- .../src/utils/curve-maths/curves.mjs | 2 +- nightfall-optimist/test/compression.mjs | 4 +- zokrates-worker/src/utils/filing.mjs | 4 +- 9 files changed, 161 insertions(+), 599 deletions(-) diff --git a/common-files/classes/proof.mjs b/common-files/classes/proof.mjs index 597ab8f42..b9f66064a 100644 --- a/common-files/classes/proof.mjs +++ b/common-files/classes/proof.mjs @@ -2,7 +2,7 @@ /* ignore unused exports */ /** -Class representing a GM17 proof. Depending on the local definition of 'proof', +Class representing a G16 proof. Depending on the local definition of 'proof', an object from this class may contain the public inputs as well as the a, b, c terms. Verifier.sol expects the public inputs to be separate, zokrates verify expects them to be in the same object. This class can accomodate either. diff --git a/common-files/utils/curve-maths/curves.mjs b/common-files/utils/curve-maths/curves.mjs index 2a9731fdc..2a2279104 100644 --- a/common-files/utils/curve-maths/curves.mjs +++ b/common-files/utils/curve-maths/curves.mjs @@ -36,7 +36,7 @@ export function compressG2(point) { } /** -This compresses a GM17 proof object in its entirety, returning promises of a +This compresses a G16 proof object in its entirety, returning promises of a flattened, compressed result. That's nice because you can await it with a Promise.all. We can turn off G2 compression as G2 decompression isn't done yet. It can cope with the proof as an object or as a flattened array. diff --git a/nightfall-deployer/contracts/Pairing.sol b/nightfall-deployer/contracts/Pairing.sol index 2b263e125..06e35a77c 100644 --- a/nightfall-deployer/contracts/Pairing.sol +++ b/nightfall-deployer/contracts/Pairing.sol @@ -6,517 +6,141 @@ pragma solidity ^0.8.0; * @title Elliptic curve operations on twist points for alt_bn128 * @author Mustafa Al-Bassam (mus@musalbas.com) */ -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; - /** - * @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 - ) public pure returns ( - uint256, uint256, - uint256, uint256 - ) { - if ( - pt1xx == 0 && pt1xy == 0 && - pt1yx == 0 && pt1yy == 0 - ) { - if (!( - pt2xx == 0 && pt2xy == 0 && - pt2yx == 0 && pt2yy == 0 - )) { - assert(_isOnCurve( - pt2xx, pt2xy, - pt2yx, pt2yy - )); - } - return ( - pt2xx, pt2xy, - pt2yx, pt2yy - ); - } else if ( - pt2xx == 0 && pt2xy == 0 && - pt2yx == 0 && pt2yy == 0 - ) { - assert(_isOnCurve( - pt1xx, pt1xy, - pt1yx, pt1yy - )); - return ( - pt1xx, pt1xy, - pt1yx, pt1yy - ); - } - assert(_isOnCurve( - pt1xx, pt1xy, - pt1yx, pt1yy - )); - assert(_isOnCurve( - pt2xx, pt2xy, - pt2yx, pt2yy - )); - 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 - ) public pure returns ( - uint256, uint256, - uint256, uint256 - ) { - uint256 pt1zx = 1; - if ( - pt1xx == 0 && pt1xy == 0 && - pt1yx == 0 && pt1yy == 0 - ) { - pt1xx = 1; - pt1yx = 1; - pt1zx = 0; - } else { - assert(_isOnCurve( - pt1xx, pt1xy, - pt1yx, pt1yy - )); - } - 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() public pure returns (uint256) { - return FIELD_MODULUS; - } - function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) { - return addmod(a, n - b, n); - } - 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) - ); - } - function _FQ2Muc( - uint256 xx, uint256 xy, - uint256 c - ) internal pure returns(uint256, uint256) { - return ( - mulmod(xx, c, FIELD_MODULUS), - mulmod(xy, c, FIELD_MODULUS) - ); - } - 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) - ); - } - function _FQ2Sub( - uint256 xx, uint256 xy, - uint256 yx, uint256 yy - ) internal pure returns(uint256 rx, uint256 ry) { - return ( - submod(xx, yx, FIELD_MODULUS), - submod(xy, yy, FIELD_MODULUS) - ); - } - function _FQ2Div( - uint256 xx, uint256 xy, - uint256 yx, uint256 yy - ) internal pure returns(uint256, uint256) { - (yx, yy) = _FQ2Inv(yx, yy); - return _FQ2Mul(xx, xy, yx, yy); - } - function _FQ2Inv(uint256 x, uint256 y) internal pure 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) - ); - } - 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; - } - function _modInv(uint256 a, uint256 n) internal pure returns(uint256 t) { - t = 0; - uint256 newT = 1; - uint256 r = n; - uint256 newR = a; - uint256 q; - while (newR != 0) { - q = r / newR; - (t, newT) = (newT, submod(t, mulmod(q, newT, n), n)); - (r, newR) = (newR, r - q * newR); - } - } - function _fromJacobian( - uint256 pt1xx, uint256 pt1xy, - uint256 pt1yx, uint256 pt1yy, - uint256 pt1zx, uint256 pt1zy - ) internal pure returns ( - uint256 pt2xx, uint256 pt2xy, - uint256 pt2yx, uint256 pt2yy - ) { - uint256 invzx; - uint256 invzy; - (invzx, invzy) = _FQ2Inv(pt1zx, pt1zy); - (pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, invzx, invzy); - (pt2yx, pt2yy) = _FQ2Mul(pt1yx, pt1yy, invzx, invzy); - } - 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 - } - function _ECTwistDoubleJacobian( - uint256 pt1xx, uint256 pt1xy, - uint256 pt1yx, uint256 pt1yy, - uint256 pt1zx, uint256 pt1zy - ) internal pure returns( - uint256 pt2xx, uint256 pt2xy, - uint256 pt2yx, uint256 pt2yy, - uint256 pt2zx, uint256 pt2zy - ) { - (pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 3); // 3 * x - (pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1xx, pt1xy); // W = 3 * x * x - (pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1zx, pt1zy); // S = y * z - (pt2yx, pt2yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // x * y - (pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // B = x * y * S - (pt1xx, pt1xy) = _FQ2Mul(pt2xx, pt2xy, pt2xx, pt2xy); // W * W - (pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 8); // 8 * B - (pt1xx, pt1xy) = _FQ2Sub(pt1xx, pt1xy, pt2zx, pt2zy); // H = W * W - 8 * B - (pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt1zx, pt1zy); // S_squared = S * S - (pt2yx, pt2yy) = _FQ2Muc(pt2yx, pt2yy, 4); // 4 * B - (pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt1xx, pt1xy); // 4 * B - H - (pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt2xx, pt2xy); // W * (4 * B - H) - (pt2xx, pt2xy) = _FQ2Muc(pt1yx, pt1yy, 8); // 8 * y - (pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1yx, pt1yy); // 8 * y * y - (pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // 8 * y * y * S_squared - (pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // newy = W * (4 * B - H) - 8 * y * y * S_squared - (pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 2); // 2 * H - (pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // newx = 2 * H * S - (pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // S * S_squared - (pt2zx, pt2zy) = _FQ2Muc(pt2zx, pt2zy, 8); // newz = 8 * S * S_squared - } - function _ECTwistMulJacobian( - uint256 d, - uint256 pt1xx, uint256 pt1xy, - uint256 pt1yx, uint256 pt1yy, - uint256 pt1zx, uint256 pt1zy - ) internal pure returns(uint256[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; - } - } -} - -// This file is MIT Licensed. -// -// Copyright 2017 Christian Reitwiessner -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// More information at https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d library Pairing { + struct G1Point { + uint X; + uint Y; + } + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint[2] X; + uint[2] Y; + } + /// @return the generator of G1 + function P1() pure internal returns (G1Point memory) { + return G1Point(1, 2); + } + /// @return the generator of G2 + function P2() pure internal returns (G2Point memory) { + return G2Point( + [10857046999023057135944570762232829481370756359578518086990519993285655852781, + 11559732032986387107991004021392285783925812861821192530917403151452391805634], + [8495653923123431417604973247489272438418190587263600148770280649306958101930, + 4082367875863433681332203403145435568316851327593401208105741076214120093531] + ); + } + /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. + function negate(G1Point memory p) pure internal returns (G1Point memory) { + // The prime q in the base field F_q for G1 + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + if (p.X == 0 && p.Y == 0) + return G1Point(0, 0); + return G1Point(p.X, q - (p.Y % q)); + } + /// @return r the sum of two points of G1 + function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { + uint[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); + } - struct G1Point { - uint X; - uint Y; - } - // Encoding of field elements is: X[0] * z + X[1] - struct G2Point { - uint[2] X; - uint[2] Y; - } - - /// @return the generator of G1 - function P1() pure internal returns (G1Point memory) { - return G1Point(1, 2); - } - /// @return the generator of G2 - function P2() pure internal returns (G2Point memory ) { - return G2Point( - [10857046999023057135944570762232829481370756359578518086990519993285655852781, - 11559732032986387107991004021392285783925812861821192530917403151452391805634], - [8495653923123431417604973247489272438418190587263600148770280649306958101930, - 4082367875863433681332203403145435568316851327593401208105741076214120093531] - ); - } - /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. - function negate(G1Point memory p) pure internal returns (G1Point memory) { - // The prime q in the base field F_q for G1 - uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; - if (p.X == 0 && p.Y == 0) - return G1Point(0, 0); - return G1Point(p.X, q - (p.Y % q)); - } - /// @return r the sum of two points of G1 - function addition(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r, bool success) { - uint[4] memory input; - input[0] = p1.X; - input[1] = p1.Y; - input[2] = p2.X; - input[3] = p2.Y; - assembly { - success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } - // Removing this check to ensure a wrong proof verification challenge's require statement correctly works. - // This condition will be checked upstream using the returned bool value - /* require(success, "EC addition failed"); */ - } - /// @return r the sum of two points of G2 - function addition2(G2Point memory p1, G2Point memory p2) internal pure returns (G2Point memory r) { - (r.X[0], r.X[1], r.Y[0], r.Y[1]) = BN256G2.ECTwistAdd(p1.X[0],p1.X[1],p1.Y[0],p1.Y[1],p2.X[0],p2.X[1],p2.Y[0],p2.Y[1]); - } - /// @return r the product of a point on G1 and a scalar, i.e. - /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. - function scalar_mul(G1Point memory p, uint s) internal returns (G1Point memory r, bool success) { - uint[3] memory input; - input[0] = p.X; - input[1] = p.Y; - input[2] = s; - assembly { - success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } - // Removing this check to ensure a wrong proof verification challenge's require statement correctly works. - // This condition will be checked upstream using the returned bool value - /* require (success, "EC scalar multiplication failed"); */ - } - /// @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(G1Point[] memory p1, G2Point[] memory p2) internal returns (bool, bool) { - // pairingProd2 and pairingProd4 are called with correct lengths in Verifier.sol. Removing this check to ensure a wrong proof verification challenge's require statement correctly works. Adding this check runs a stack too deep error in Verifier.sol. So we are avoiding this because we know this is correctly called - /* require(p1.length == p2.length, "EC pairing p1 length != p2 length"); */ - uint elements = p1.length; - uint inputSize = elements * 6; - uint[] memory input = new uint[](inputSize); - for (uint 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[1]; - input[i * 6 + 3] = p2[i].X[0]; - input[i * 6 + 4] = p2[i].Y[1]; - input[i * 6 + 5] = p2[i].Y[0]; - } - uint[1] memory out; - bool success; - assembly { - success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) - // Use "invalid" to make gas estimation work - //switch success case 0 { invalid() } //MC has commented out so that 'false' can be returned (rather than an error being thrown) - } - // Removing this check to ensure a wrong proof verification challenge's require statement correctly works. - // This condition will be checked upstream using the returned bool value - //require(success, "EC Pairing calculation failed"); //MC has commented out so that 'false' can be returned (rather than an error being thrown) - return (out[0] != 0, success); - } - /// Convenience method for a pairing check for two pairs. - function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool, bool) { - G1Point[] memory p1 = new G1Point[](2); - G2Point[] memory p2 = new G2Point[](2); - p1[0] = a1; - p1[1] = b1; - p2[0] = a2; - p2[1] = b2; - return pairing(p1, p2); - } - /// 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 - ) internal returns (bool, bool) { - G1Point[] memory p1 = new G1Point[](3); - G2Point[] memory p2 = new G2Point[](3); - p1[0] = a1; - p1[1] = b1; - p1[2] = c1; - p2[0] = a2; - p2[1] = b2; - p2[2] = c2; - return pairing(p1, p2); - } - /// 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 - ) internal returns (bool, bool) { - G1Point[] memory p1 = new G1Point[](4); - G2Point[] memory p2 = new 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); - } -} + /// @return r the product of a point on G1 and a scalar, i.e. + /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. + function scalar_mul(G1Point memory p, uint s) internal view returns (G1Point memory r) { + uint[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); + } + /// @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(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) { + require(p1.length == p2.length); + uint elements = p1.length; + uint inputSize = elements * 6; + uint[] memory input = new uint[](inputSize); + for (uint 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[1]; + input[i * 6 + 3] = p2[i].X[0]; + input[i * 6 + 4] = p2[i].Y[1]; + input[i * 6 + 5] = p2[i].Y[0]; + } + uint[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; + } + /// Convenience method for a pairing check for two pairs. + function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal view returns (bool) { + G1Point[] memory p1 = new G1Point[](2); + G2Point[] memory p2 = new G2Point[](2); + p1[0] = a1; + p1[1] = b1; + p2[0] = a2; + p2[1] = b2; + return pairing(p1, p2); + } + /// 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 + ) internal view returns (bool) { + G1Point[] memory p1 = new G1Point[](3); + G2Point[] memory p2 = new G2Point[](3); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + return pairing(p1, p2); + } + /// 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 + ) internal view returns (bool) { + G1Point[] memory p1 = new G1Point[](4); + G2Point[] memory p2 = new 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); + } + } \ No newline at end of file diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index 935bd109b..52bddf343 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -17,11 +17,12 @@ Michael Connor Duncan Westland Chaitanya Konda Harry R +Migrated to G16 by Hari Krishnan */ /** @title Verifier -@dev Example Verifier Implementation - GM17 proof verification. +@dev Example Verifier Implementation - G16 proof verification. @notice Do not use this example in any production code! */ @@ -34,13 +35,13 @@ library Verifier { using Pairing for *; - struct Proof_GM17 { + struct Proof_G16 { Pairing.G1Point A; Pairing.G2Point B; Pairing.G1Point C; } - struct Verification_Key_GM17 { + struct Verification_Key_G16 { Pairing.G1Point alpha; Pairing.G2Point beta; Pairing.G2Point gamma; @@ -48,7 +49,7 @@ library Verifier { Pairing.G1Point[] gamma_abc; } - function verify(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public returns (bool result) { + function verify(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public view returns (bool result) { if (verificationCalculation(_proof, _publicInputsHash, _vk) == 0) { result = true; } else { @@ -56,11 +57,11 @@ library Verifier { } } - function verificationCalculation(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public returns (uint) { + function verificationCalculation(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) internal view returns (uint) { - Proof_GM17 memory proof; + Proof_G16 memory proof; Pairing.G1Point memory vk_dot_inputs; - Verification_Key_GM17 memory vk; + Verification_Key_G16 memory vk; vk_dot_inputs = Pairing.G1Point(0, 0); //initialise @@ -79,85 +80,25 @@ library Verifier { vk.gamma_abc[j++] = Pairing.G1Point(_vk[i], _vk[i+1]); } - /* require(vk.query.length == 2, "Length of vk.query is incorrect!"); */ + /* require(vk.gamma.abc.length == 2, "Length of vk.gamma.abc is incorrect!"); */ // Replacing for the above require statement so that the proof verification returns false. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works if (vk.gamma_abc.length != 2) { return 1; } - { - Pairing.G1Point memory sm_qpih; - // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works - bool success_sm_qpih; - bool success_vkdi_sm_qpih; - (sm_qpih, success_sm_qpih) = Pairing.scalar_mul(vk.gamma_abc[1], _publicInputsHash); - (vk_dot_inputs, success_vkdi_sm_qpih) = Pairing.addition( - vk_dot_inputs, - sm_qpih - ); - if (!success_sm_qpih || !success_vkdi_sm_qpih) { - return 2; - } - } - - { - // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works - bool success_vkdi_q; - (vk_dot_inputs, success_vkdi_q) = Pairing.addition(vk_dot_inputs, vk.gamma_abc[0]); - if (!success_vkdi_q) { - return 3; - } - } + vk_dot_inputs = Pairing.addition(vk_dot_inputs, Pairing.scalar_mul(vk.gamma_abc[1],_publicInputsHash)); + vk_dot_inputs = Pairing.addition(vk_dot_inputs, vk.gamma_abc[0]); - - /** - * e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) - * * e(C, H) - * where psi = \sum_{i=0}^l input_i pvk.query[i] - */ - // { - // Pairing.G1Point memory add_A_Galpha; - // // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works - // bool success_pp4_out_not_0; - // bool success_pp4_pairing; - // { - // bool success_add_A_Galpha; - // (add_A_Galpha, success_add_A_Galpha) = Pairing.addition(proof.A, vk.a); - // if (!success_add_A_Galpha) { - // return 4; - // } - // } - // (success_pp4_out_not_0, success_pp4_pairing) = Pairing.pairingProd4(vk.Galpha, vk.Hbeta, vk_dot_inputs, vk.Hgamma, proof.C, vk.H, Pairing.negate(add_A_Galpha), Pairing.addition2(proof.B, vk.Hbeta)); - // if (!success_pp4_out_not_0 || !success_pp4_pairing) { - // return 5; - // } - // } - - // /** - // * e(A, H^{gamma}) = e(G^{gamma}, B) - // */ - // { - // // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works - // bool success_pp2_out_not_0; - // bool success_pp2_pairing; - // (success_pp2_out_not_0, success_pp2_pairing) = Pairing.pairingProd2(proof.A, vk.Hgamma, Pairing.negate(vk.Ggamma), proof.B); - // if (!success_pp2_out_not_0 || !success_pp2_pairing) { - // return 6; - // } - // } - { - bool success_pp4_out_not_0; + bool success_pp4_pairing; - (success_pp4_out_not_0,success_pp4_pairing)=Pairing.pairingProd4( + success_pp4_pairing=Pairing.pairingProd4( proof.A, proof.B, Pairing.negate(vk_dot_inputs), vk.gamma, Pairing.negate(proof.C), vk.delta, Pairing.negate(vk.alpha), vk.beta); - - if(!success_pp4_out_not_0 || !success_pp4_pairing) { + if(!success_pp4_pairing) { return 1; } - } return 0; } } diff --git a/nightfall-deployer/migrations/2_Shield_migration.js b/nightfall-deployer/migrations/2_Shield_migration.js index 3a204fca6..6415d59d2 100644 --- a/nightfall-deployer/migrations/2_Shield_migration.js +++ b/nightfall-deployer/migrations/2_Shield_migration.js @@ -1,4 +1,3 @@ -const BN256G2 = artifacts.require('BN256G2'); const Verifier = artifacts.require('Verifier.sol'); const Shield = artifacts.require('Shield.sol'); const MerkleTree_Stateless = artifacts.require('MerkleTree_Stateless.sol'); @@ -13,8 +12,6 @@ const State = artifacts.require('State.sol'); module.exports = function(deployer) { deployer.then(async () => { - await deployer.deploy(BN256G2); - await deployer.link(BN256G2, Verifier); await deployer.deploy(Verifier); await deployer.link(Verifier, [Challenges,ChallengesUtil]); await deployer.deploy(MiMC); diff --git a/nightfall-optimist/src/classes/verification-key.mjs b/nightfall-optimist/src/classes/verification-key.mjs index 541f7d62b..a4361dc62 100644 --- a/nightfall-optimist/src/classes/verification-key.mjs +++ b/nightfall-optimist/src/classes/verification-key.mjs @@ -17,12 +17,12 @@ class VerificationKey { if (!Array.isArray(vkArray)) throw new Error('The input must be an array'); if (vkArray.length % 2 !== 0) throw new Error('The verification array must have an even length'); - this.h = generalise([vkArray.slice(0, 2), vkArray.slice(2, 4)]).all.hex(32); - this.g_alpha = generalise(vkArray.slice(4, 6)).all.hex(32); - this.h_beta = generalise([vkArray.slice(6, 8), vkArray.slice(8, 10)]).all.hex(32); - this.g_gamma = generalise(vkArray.slice(10, 12)).all.hex(32); - this.h_gamma = generalise([vkArray.slice(12, 14), vkArray.slice(14, 16)]).all.hex(32); - this.query = generalise(pairArray(vkArray.slice(16))).all.hex(32); + this.alpha = generalise(vkArray.slice(0, 2)).all.hex(32); + this.beta = generalise([vkArray.slice(2, 4), vkArray.slice(4, 6)]).all.hex(32); + this.gamma = generalise([vkArray.slice(6, 8), vkArray.slice(8, 10)]).all.hex(32); + this.delta = generalise([vkArray.slice(10, 12), vkArray.slice(12, 14)]).all.hex(32); + this.gamma_abc = generalise(pairArray(vkArray.slice(14))).all.hex(32); + } } diff --git a/nightfall-optimist/src/utils/curve-maths/curves.mjs b/nightfall-optimist/src/utils/curve-maths/curves.mjs index d19fa5317..fee04c6fc 100644 --- a/nightfall-optimist/src/utils/curve-maths/curves.mjs +++ b/nightfall-optimist/src/utils/curve-maths/curves.mjs @@ -38,7 +38,7 @@ export function compressG2(point) { } /** -This compresses a GM17 proof object in its entirety, returning promises of a +This compresses a G16 proof object in its entirety, returning promises of a flattened, compressed result. That's nice because you can await it with a Promise.all. We can turn off G2 compression as G2 decompression isn't done yet. It can cope with the proof as an object or as a flattened array. diff --git a/nightfall-optimist/test/compression.mjs b/nightfall-optimist/test/compression.mjs index 979b8ff2a..d4007e456 100644 --- a/nightfall-optimist/test/compression.mjs +++ b/nightfall-optimist/test/compression.mjs @@ -49,14 +49,14 @@ describe('compression tests', () => { assert.deepStrictEqual(testProof.b, decompressedG2b); }); - it('should compress and decompress a GM17 proof object', async () => { + it('should compress and decompress a G16 proof object', async () => { const compressedProof = await compressProof(testProof); const decompressedProof = decompressProof(compressedProof); const flatProof = [testProof.a, testProof.b, testProof.c].flat(2); assert.deepStrictEqual(flatProof, decompressedProof); }); - it('should compress and decompress a flattened GM17 proof array', async () => { + it('should compress and decompress a flattened G16 proof array', async () => { const compressedProof = await compressProof(Object.values(testProof).flat(Infinity)); const decompressedProof = decompressProof(compressedProof); const flatProof = [testProof.a, testProof.b, testProof.c].flat(2); diff --git a/zokrates-worker/src/utils/filing.mjs b/zokrates-worker/src/utils/filing.mjs index 87a5b8d89..ef14d2662 100644 --- a/zokrates-worker/src/utils/filing.mjs +++ b/zokrates-worker/src/utils/filing.mjs @@ -22,8 +22,8 @@ const readJsonFile = filePath => { Strip the 'raw' field from the vk data */ const stripRawData = vk => { - const { h, g_alpha, h_beta, g_gamma, h_gamma, query } = vk; - return { h, g_alpha, h_beta, g_gamma, h_gamma, query }; + const { alpha, beta, gamma, delta, gamma_abc } = vk; + return { alpha, beta, gamma, delta, gamma_abc }; }; export const getVerificationKeyByCircuitPath = circuitPath => { From ca942fde146b1beba05118eec7889385085a8139 Mon Sep 17 00:00:00 2001 From: dwebchapey Date: Tue, 23 Nov 2021 18:59:03 +0530 Subject: [PATCH 3/9] fix: removing unused imports in verifier.sol --- nightfall-deployer/contracts/Verifier.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index 52bddf343..4055fdd89 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -28,7 +28,6 @@ Migrated to G16 by Hari Krishnan pragma solidity ^0.8.0; -import "./Ownable.sol"; import "./Pairing.sol"; library Verifier { From 1776c1e5b4db6a051c51950834733808ae9ae0a0 Mon Sep 17 00:00:00 2001 From: dwebchapey Date: Tue, 23 Nov 2021 20:13:07 +0530 Subject: [PATCH 4/9] fix: verification key js for g16 --- nightfall-optimist/src/classes/verification-key.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/nightfall-optimist/src/classes/verification-key.mjs b/nightfall-optimist/src/classes/verification-key.mjs index a4361dc62..02095f75d 100644 --- a/nightfall-optimist/src/classes/verification-key.mjs +++ b/nightfall-optimist/src/classes/verification-key.mjs @@ -22,7 +22,6 @@ class VerificationKey { this.gamma = generalise([vkArray.slice(6, 8), vkArray.slice(8, 10)]).all.hex(32); this.delta = generalise([vkArray.slice(10, 12), vkArray.slice(12, 14)]).all.hex(32); this.gamma_abc = generalise(pairArray(vkArray.slice(14))).all.hex(32); - } } From 5eb620fa7dc22b43dff4e1f9bd5ca8ee0fde9848 Mon Sep 17 00:00:00 2001 From: dwebchapey Date: Wed, 24 Nov 2021 23:45:02 +0530 Subject: [PATCH 5/9] fix: remove require from contracts --- common-files/utils/curve-maths/curves.mjs | 2 +- nightfall-deployer/contracts/Pairing.sol | 280 +++++++++++----------- nightfall-deployer/contracts/Verifier.sol | 57 ++++- 3 files changed, 191 insertions(+), 148 deletions(-) diff --git a/common-files/utils/curve-maths/curves.mjs b/common-files/utils/curve-maths/curves.mjs index 2a2279104..2a9731fdc 100644 --- a/common-files/utils/curve-maths/curves.mjs +++ b/common-files/utils/curve-maths/curves.mjs @@ -36,7 +36,7 @@ export function compressG2(point) { } /** -This compresses a G16 proof object in its entirety, returning promises of a +This compresses a GM17 proof object in its entirety, returning promises of a flattened, compressed result. That's nice because you can await it with a Promise.all. We can turn off G2 compression as G2 decompression isn't done yet. It can cope with the proof as an object or as a flattened array. diff --git a/nightfall-deployer/contracts/Pairing.sol b/nightfall-deployer/contracts/Pairing.sol index 06e35a77c..cc7cd4e3f 100644 --- a/nightfall-deployer/contracts/Pairing.sol +++ b/nightfall-deployer/contracts/Pairing.sol @@ -7,140 +7,152 @@ pragma solidity ^0.8.0; * @author Mustafa Al-Bassam (mus@musalbas.com) */ +// Copyright 2017 Christian Reitwiessner +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// More information at https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d + library Pairing { - struct G1Point { - uint X; - uint Y; - } - // Encoding of field elements is: X[0] * z + X[1] - struct G2Point { - uint[2] X; - uint[2] Y; - } - /// @return the generator of G1 - function P1() pure internal returns (G1Point memory) { - return G1Point(1, 2); - } - /// @return the generator of G2 - function P2() pure internal returns (G2Point memory) { - return G2Point( - [10857046999023057135944570762232829481370756359578518086990519993285655852781, - 11559732032986387107991004021392285783925812861821192530917403151452391805634], - [8495653923123431417604973247489272438418190587263600148770280649306958101930, - 4082367875863433681332203403145435568316851327593401208105741076214120093531] - ); - } - /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. - function negate(G1Point memory p) pure internal returns (G1Point memory) { - // The prime q in the base field F_q for G1 - uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; - if (p.X == 0 && p.Y == 0) - return G1Point(0, 0); - return G1Point(p.X, q - (p.Y % q)); - } - /// @return r the sum of two points of G1 - function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { - uint[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); - } + struct G1Point { + uint X; + uint Y; + } + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint[2] X; + uint[2] Y; + } - /// @return r the product of a point on G1 and a scalar, i.e. - /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. - function scalar_mul(G1Point memory p, uint s) internal view returns (G1Point memory r) { - uint[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); - } - /// @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(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) { - require(p1.length == p2.length); - uint elements = p1.length; - uint inputSize = elements * 6; - uint[] memory input = new uint[](inputSize); - for (uint 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[1]; - input[i * 6 + 3] = p2[i].X[0]; - input[i * 6 + 4] = p2[i].Y[1]; - input[i * 6 + 5] = p2[i].Y[0]; - } - uint[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; - } - /// Convenience method for a pairing check for two pairs. - function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal view returns (bool) { - G1Point[] memory p1 = new G1Point[](2); - G2Point[] memory p2 = new G2Point[](2); - p1[0] = a1; - p1[1] = b1; - p2[0] = a2; - p2[1] = b2; - return pairing(p1, p2); - } - /// 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 - ) internal view returns (bool) { - G1Point[] memory p1 = new G1Point[](3); - G2Point[] memory p2 = new G2Point[](3); - p1[0] = a1; - p1[1] = b1; - p1[2] = c1; - p2[0] = a2; - p2[1] = b2; - p2[2] = c2; - return pairing(p1, p2); - } - /// 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 - ) internal view returns (bool) { - G1Point[] memory p1 = new G1Point[](4); - G2Point[] memory p2 = new 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); - } - } \ No newline at end of file + /// @return the generator of G1 + function P1() pure internal returns (G1Point memory) { + return G1Point(1, 2); + } + /// @return the generator of G2 + function P2() pure internal returns (G2Point memory ) { + return G2Point( + [10857046999023057135944570762232829481370756359578518086990519993285655852781, + 11559732032986387107991004021392285783925812861821192530917403151452391805634], + [8495653923123431417604973247489272438418190587263600148770280649306958101930, + 4082367875863433681332203403145435568316851327593401208105741076214120093531] + ); + } + /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. + function negate(G1Point memory p) pure internal returns (G1Point memory) { + // The prime q in the base field F_q for G1 + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + if (p.X == 0 && p.Y == 0) + return G1Point(0, 0); + return G1Point(p.X, q - (p.Y % q)); + } + /// @return r the sum of two points of G1 + function addition(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r, bool success) { + uint[4] memory input; + input[0] = p1.X; + input[1] = p1.Y; + input[2] = p2.X; + input[3] = p2.Y; + assembly { + success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + // Removing this check to ensure a wrong proof verification challenge's require statement correctly works. + // This condition will be checked upstream using the returned bool value + /* require(success, "EC addition failed"); */ + } + /// @return r the product of a point on G1 and a scalar, i.e. + /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. + function scalar_mul(G1Point memory p, uint s) internal returns (G1Point memory r, bool success) { + uint[3] memory input; + input[0] = p.X; + input[1] = p.Y; + input[2] = s; + assembly { + success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + // Removing this check to ensure a wrong proof verification challenge's require statement correctly works. + // This condition will be checked upstream using the returned bool value + /* require (success, "EC scalar multiplication failed"); */ + } + /// @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(G1Point[] memory p1, G2Point[] memory p2) internal returns (bool, bool) { + // pairingProd2 and pairingProd4 are called with correct lengths in Verifier.sol. Removing this check to ensure a wrong proof verification challenge's require statement correctly works. Adding this check runs a stack too deep error in Verifier.sol. So we are avoiding this because we know this is correctly called + /* require(p1.length == p2.length, "EC pairing p1 length != p2 length"); */ + uint elements = p1.length; + uint inputSize = elements * 6; + uint[] memory input = new uint[](inputSize); + for (uint 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[1]; + input[i * 6 + 3] = p2[i].X[0]; + input[i * 6 + 4] = p2[i].Y[1]; + input[i * 6 + 5] = p2[i].Y[0]; + } + uint[1] memory out; + bool success; + assembly { + success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + // Use "invalid" to make gas estimation work + //switch success case 0 { invalid() } //MC has commented out so that 'false' can be returned (rather than an error being thrown) + } + // Removing this check to ensure a wrong proof verification challenge's require statement correctly works. + // This condition will be checked upstream using the returned bool value + //require(success, "EC Pairing calculation failed"); //MC has commented out so that 'false' can be returned (rather than an error being thrown) + return (out[0] != 0, success); + } + /// Convenience method for a pairing check for two pairs. + function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool, bool) { + G1Point[] memory p1 = new G1Point[](2); + G2Point[] memory p2 = new G2Point[](2); + p1[0] = a1; + p1[1] = b1; + p2[0] = a2; + p2[1] = b2; + return pairing(p1, p2); + } + /// 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 + ) internal returns (bool, bool) { + G1Point[] memory p1 = new G1Point[](3); + G2Point[] memory p2 = new G2Point[](3); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + return pairing(p1, p2); + } + /// 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 + ) internal returns (bool, bool) { + G1Point[] memory p1 = new G1Point[](4); + G2Point[] memory p2 = new 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); + } +} + \ No newline at end of file diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index 4055fdd89..8389a640e 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -17,7 +17,6 @@ Michael Connor Duncan Westland Chaitanya Konda Harry R -Migrated to G16 by Hari Krishnan */ /** @@ -28,6 +27,7 @@ Migrated to G16 by Hari Krishnan pragma solidity ^0.8.0; +import "./Ownable.sol"; import "./Pairing.sol"; library Verifier { @@ -41,14 +41,14 @@ library Verifier { } struct Verification_Key_G16 { - Pairing.G1Point alpha; + Pairing.G1Point alpha; Pairing.G2Point beta; Pairing.G2Point gamma; Pairing.G2Point delta; Pairing.G1Point[] gamma_abc; } - function verify(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public view returns (bool result) { + function verify(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public returns (bool result) { if (verificationCalculation(_proof, _publicInputsHash, _vk) == 0) { result = true; } else { @@ -56,7 +56,7 @@ library Verifier { } } - function verificationCalculation(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) internal view returns (uint) { + function verificationCalculation(uint256[] memory _proof, uint256 _publicInputsHash, uint256[] memory _vk) public returns (uint) { Proof_G16 memory proof; Pairing.G1Point memory vk_dot_inputs; @@ -79,25 +79,56 @@ library Verifier { vk.gamma_abc[j++] = Pairing.G1Point(_vk[i], _vk[i+1]); } - /* require(vk.gamma.abc.length == 2, "Length of vk.gamma.abc is incorrect!"); */ + + /* require(vk.gamma.abc.length == 2, "Length of vk.gamma.abc is incorrect!"); */ // Replacing for the above require statement so that the proof verification returns false. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works if (vk.gamma_abc.length != 2) { return 1; } - vk_dot_inputs = Pairing.addition(vk_dot_inputs, Pairing.scalar_mul(vk.gamma_abc[1],_publicInputsHash)); - vk_dot_inputs = Pairing.addition(vk_dot_inputs, vk.gamma_abc[0]); + { + Pairing.G1Point memory sm_qpih; + // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works + bool success_sm_qpih; + bool success_vkdi_sm_qpih; + (sm_qpih, success_sm_qpih) = Pairing.scalar_mul(vk.gamma_abc[1], _publicInputsHash); + (vk_dot_inputs, success_vkdi_sm_qpih) = Pairing.addition( + vk_dot_inputs, + sm_qpih + ); + if (!success_sm_qpih || !success_vkdi_sm_qpih) { + return 2; + } + } + + { + // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works + bool success_vkdi_q; + (vk_dot_inputs, success_vkdi_q) = Pairing.addition(vk_dot_inputs, vk.gamma_abc[0]); + if (!success_vkdi_q) { + return 3; + } + } + - + /** + * e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) + * * e(C, H) + * where psi = \sum_{i=0}^l input_i pvk.query[i] + */ + { + // The following success variables replace require statements with corresponding functions called. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works + bool success_pp4_out_not_0; bool success_pp4_pairing; - success_pp4_pairing=Pairing.pairingProd4( + (success_pp4_out_not_0, success_pp4_pairing) = Pairing.pairingProd4( proof.A, proof.B, Pairing.negate(vk_dot_inputs), vk.gamma, Pairing.negate(proof.C), vk.delta, Pairing.negate(vk.alpha), vk.beta); - if(!success_pp4_pairing) { - return 1; - } + if (!success_pp4_out_not_0 || !success_pp4_pairing) { + return 5; + } + } return 0; } -} +} \ No newline at end of file From 28659db73aa051b6b8f70024b3d2e90f4ce376d1 Mon Sep 17 00:00:00 2001 From: dwebchapey Date: Wed, 24 Nov 2021 23:48:03 +0530 Subject: [PATCH 6/9] fix: migrate to G16 --- nightfall-optimist/src/utils/curve-maths/curves.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nightfall-optimist/src/utils/curve-maths/curves.mjs b/nightfall-optimist/src/utils/curve-maths/curves.mjs index fee04c6fc..d19fa5317 100644 --- a/nightfall-optimist/src/utils/curve-maths/curves.mjs +++ b/nightfall-optimist/src/utils/curve-maths/curves.mjs @@ -38,7 +38,7 @@ export function compressG2(point) { } /** -This compresses a G16 proof object in its entirety, returning promises of a +This compresses a GM17 proof object in its entirety, returning promises of a flattened, compressed result. That's nice because you can await it with a Promise.all. We can turn off G2 compression as G2 decompression isn't done yet. It can cope with the proof as an object or as a flattened array. From 4ac26539d39d25f8c49be341f8d1ebfc22eb560e Mon Sep 17 00:00:00 2001 From: Hari Date: Sun, 28 Nov 2021 18:15:11 +0530 Subject: [PATCH 7/9] Update nightfall-deployer/contracts/Verifier.sol Co-authored-by: Miranda Wood --- nightfall-deployer/contracts/Verifier.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index 8389a640e..2a811f513 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -68,10 +68,10 @@ library Verifier { proof.B = Pairing.G2Point([_proof[2], _proof[3]], [_proof[4], _proof[5]]); proof.C = Pairing.G1Point(_proof[6], _proof[7]); - vk.alpha = Pairing.G1Point(_vk[4],_vk[5]); - vk.beta = Pairing.G2Point([_vk[6],_vk[7]],[_vk[8],_vk[9]]); - vk.gamma = Pairing.G2Point([_vk[10],_vk[11]],[_vk[12],_vk[13]]); - vk.delta = Pairing.G2Point([_vk[14],_vk[15]],[_vk[16],_vk[17]]); + vk.alpha = Pairing.G1Point(_vk[0],_vk[1]); + vk.beta = Pairing.G2Point([_vk[2],_vk[3]],[_vk[4],_vk[5]]); + vk.gamma = Pairing.G2Point([_vk[6],_vk[7]],[_vk[8],_vk[9]]); + vk.delta = Pairing.G2Point([_vk[10],_vk[11]],[_vk[12],_vk[13]]); // vk.gamma_abc.length = (_vk.length - 18)/2; uint j = 0; From 26d0e428837db0f83683020827bee11e212ad8f7 Mon Sep 17 00:00:00 2001 From: Hari Date: Sun, 28 Nov 2021 18:15:19 +0530 Subject: [PATCH 8/9] Update nightfall-deployer/contracts/Verifier.sol Co-authored-by: Miranda Wood --- nightfall-deployer/contracts/Verifier.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index 2a811f513..a13c839d2 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -75,8 +75,12 @@ library Verifier { // vk.gamma_abc.length = (_vk.length - 18)/2; uint j = 0; - for (uint i = 18; i < _vk.length; i+=2) { - vk.gamma_abc[j++] = Pairing.G1Point(_vk[i], _vk[i+1]); + if (_vk.length > 14) { + for (uint i = 14; i < _vk.length; i+=2) { + vk.gamma_abc[(i-14)/2] = Pairing.G1Point( + _vk[i], _vk[i+1] + ); + } } From 8fcc1aac9e4d3a82a934e04a11480100aed716d7 Mon Sep 17 00:00:00 2001 From: MirandaWood Date: Tue, 30 Nov 2021 17:24:32 +0000 Subject: [PATCH 9/9] fix: fix silent revert in verifier.sol --- nightfall-deployer/contracts/Verifier.sol | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/nightfall-deployer/contracts/Verifier.sol b/nightfall-deployer/contracts/Verifier.sol index a13c839d2..e4c00e893 100644 --- a/nightfall-deployer/contracts/Verifier.sol +++ b/nightfall-deployer/contracts/Verifier.sol @@ -73,18 +73,16 @@ library Verifier { vk.gamma = Pairing.G2Point([_vk[6],_vk[7]],[_vk[8],_vk[9]]); vk.delta = Pairing.G2Point([_vk[10],_vk[11]],[_vk[12],_vk[13]]); - // vk.gamma_abc.length = (_vk.length - 18)/2; - uint j = 0; + // vk.gamma_abc.length = (_vk.length - 14)/2; if (_vk.length > 14) { + vk.gamma_abc = new Pairing.G1Point[]((_vk.length - 14)/2); // num public inputs + 1 for (uint i = 14; i < _vk.length; i+=2) { - vk.gamma_abc[(i-14)/2] = Pairing.G1Point( - _vk[i], _vk[i+1] - ); + vk.gamma_abc[(i-14)/2] = Pairing.G1Point( + _vk[i], _vk[i+1] + ); } } - - - /* require(vk.gamma.abc.length == 2, "Length of vk.gamma.abc is incorrect!"); */ + /* require(vk.gamma.abc.length == 2, "Length of vk.gamma.abc is incorrect!"); */ // Replacing for the above require statement so that the proof verification returns false. Removing require statements to ensure a wrong proof verification challenge's require statement correctly works if (vk.gamma_abc.length != 2) { return 1;