diff --git a/contracts/Pairing.sol b/contracts/Pairing.sol deleted file mode 100644 index 4db5150..0000000 --- a/contracts/Pairing.sol +++ /dev/null @@ -1,157 +0,0 @@ -// This code is taken from https://github.com/JacobEberhardt/ZoKrates - -pragma solidity ^0.5.0; - -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() - internal pure returns (G1Point memory) - { - return G1Point(1, 2); - } - - /// @return the generator of G2 - function P2() internal pure returns (G2Point memory) { - return G2Point( - [11559732032986387107991004021392285783925812861821192530917403151452391805634, - 10857046999023057135944570762232829481370756359578518086990519993285655852781], - [4082367875863433681332203403145435568316851327593401208105741076214120093531, - 8495653923123431417604973247489272438418190587263600148770280649306958101930] - ); - } - - /// @return the negation of p, i.e. p.add(p.negate()) should be zero. - function negate(G1Point memory p) internal pure 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 the sum of two points of G1 - function pointAdd(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) - } - require(success); - } - - /// @return 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 pointMul(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) - } - 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[0]; - input[i * 6 + 3] = p2[i].X[1]; - input[i * 6 + 4] = p2[i].Y[0]; - input[i * 6 + 5] = p2[i].Y[1]; - } - uint[1] memory out; - bool success; - assembly { - success := staticcall(sub(gas, 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) - } - 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); - } -} - diff --git a/contracts/Verifier.sol b/contracts/Verifier.sol index 7dd764a..6347355 100644 --- a/contracts/Verifier.sol +++ b/contracts/Verifier.sol @@ -2,41 +2,14 @@ pragma solidity ^0.5.0; -import "./Pairing.sol"; - library Verifier { - using Pairing for Pairing.G1Point; - using Pairing for Pairing.G2Point; - function ScalarField () - public pure returns (uint256) + internal pure returns (uint256) { return 21888242871839275222246405745257275088548364400416034343698204186575808495617; } - struct VerifyingKey - { - Pairing.G1Point alpha; - Pairing.G2Point beta; - Pairing.G2Point gamma; - Pairing.G2Point delta; - Pairing.G1Point[] gammaABC; - } - - struct Proof - { - Pairing.G1Point A; - Pairing.G2Point B; - Pairing.G1Point C; - } - - struct ProofWithInput - { - Proof proof; - uint256[] input; - } - function NegateY( uint256 Y ) internal pure returns (uint256) @@ -93,6 +66,7 @@ library Verifier function Verify ( uint256[14] memory in_vk, uint256[] memory vk_gammaABC, uint256[8] memory in_proof, uint256[] memory proof_inputs ) internal view returns (bool) { + uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; require( ((vk_gammaABC.length / 2) - 1) == proof_inputs.length ); // Compute the linear combination vk_x @@ -106,7 +80,9 @@ library Verifier add_input[1] = vk_gammaABC[1]; // Performs a sum of gammaABC[0] + sum[ gammaABC[i+1]^proof_inputs[i] ] - for (uint i = 0; i < proof_inputs.length; i++) { + for (uint i = 0; i < proof_inputs.length; i++) + { + require( proof_inputs[i] < snark_scalar_field ); mul_input[0] = vk_gammaABC[m++]; mul_input[1] = vk_gammaABC[m++]; mul_input[2] = proof_inputs[i]; @@ -149,30 +125,4 @@ library Verifier require(success); return out[0] != 0; } - - - function Verify (VerifyingKey memory vk, ProofWithInput memory pwi) - internal view returns (bool) - { - return Verify(vk, pwi.proof, pwi.input); - } - - - function Verify (VerifyingKey memory vk, Proof memory proof, uint256[] memory input) - internal view returns (bool) - { - require(input.length + 1 == vk.gammaABC.length); - - // Compute the linear combination vk_x - Pairing.G1Point memory vk_x = vk.gammaABC[0]; - for (uint i = 0; i < input.length; i++) - vk_x = Pairing.pointAdd(vk_x, Pairing.pointMul(vk.gammaABC[i + 1], input[i])); - - // Verify proof - return Pairing.pairingProd4( - proof.A, proof.B, - vk_x.negate(), vk.gamma, - proof.C.negate(), vk.delta, - vk.alpha.negate(), vk.beta); - } } diff --git a/test/TestVerifier.sol b/test/TestVerifier.sol index 9a6850e..09e255d 100644 --- a/test/TestVerifier.sol +++ b/test/TestVerifier.sol @@ -5,39 +5,55 @@ import "../contracts/Verifier.sol"; contract TestVerifier { - function testVerifyProof () public + function testVerifyProof () + public { - Verifier.ProofWithInput memory pwi; - _getStaticProof(pwi); + uint256[14] memory vk = [ + // alpha + 0x1a9b4e2ac1995dd16f454f29e99eb5117ad746622861e7f431b6c4c8d3baafb9, 0x31cdc99db948afc75eabbe2eae7a9eca07d381015a2328113c3167b917be3ca, - Verifier.VerifyingKey memory vk; - _getVerifyingKey(vk); + // beta + 0xc6f1198c576e2207e51f67b68ff7bdf4c0e025a06d939ed60dc48cec66d4039, 0x17284231b380c0e58a7427ba62d81361c270d736dac2da24a79e4f7c636768c4, + 0x1a8943f3de1661a58bbabc79383c2d0f21a383c60f63a02137e745b9c37773, 0x1c2a6f9fbbcc6cf56138e592c88e85c9bd3b9475502ee74ee2e2270bdada1721, - Assert.isTrue(Verifier.Verify(vk, pwi), "Verification failed"); - } + // gamma + 0x2696d25a7afb6661334ab032c2f542228dde68b5bbf40b632b565548a62b4609, 0x44603e77c3089413bb7b14919796794945cfd8dff60f24c3c95ce934174a764, + 0x24af680afaf803574962a13aa200fbef3ce72195115f58311d49e7bc6258c329, 0x1e1ec3dcdb121633453b323616ef4534ac3c85aaf7bd55dc81c742d0b04ba9fc, - function _getVerifyingKey (Verifier.VerifyingKey memory vk) - internal pure - { - vk.beta = Pairing.G2Point([0xc6f1198c576e2207e51f67b68ff7bdf4c0e025a06d939ed60dc48cec66d4039, 0x17284231b380c0e58a7427ba62d81361c270d736dac2da24a79e4f7c636768c4], [0x1a8943f3de1661a58bbabc79383c2d0f21a383c60f63a02137e745b9c37773, 0x1c2a6f9fbbcc6cf56138e592c88e85c9bd3b9475502ee74ee2e2270bdada1721]); - vk.gamma = Pairing.G2Point([0x2696d25a7afb6661334ab032c2f542228dde68b5bbf40b632b565548a62b4609, 0x44603e77c3089413bb7b14919796794945cfd8dff60f24c3c95ce934174a764], [0x24af680afaf803574962a13aa200fbef3ce72195115f58311d49e7bc6258c329, 0x1e1ec3dcdb121633453b323616ef4534ac3c85aaf7bd55dc81c742d0b04ba9fc]); - vk.delta = Pairing.G2Point([0x19769645773ead44e472cc5e7c4e10452c04c822eb30907a02eb040b9a27354d, 0x5154440eb40fb1784183c61fb0e601f37987c550f6ed3fad38c250dd8c1b8fd], [0x2f1f75b1858a0054df7f216ef1b56f309f164179bfca1741062c724c8556dc8c, 0x25909e78312ff8925a6c32df4510716c58ad8433582ad192be8ebcf3e4958533]); - vk.alpha = Pairing.G1Point(0x1a9b4e2ac1995dd16f454f29e99eb5117ad746622861e7f431b6c4c8d3baafb9, 0x31cdc99db948afc75eabbe2eae7a9eca07d381015a2328113c3167b917be3ca); - vk.gammaABC = new Pairing.G1Point[](3); - vk.gammaABC[0] = Pairing.G1Point(0x1caac86452b8e9a97f3999ecb5655bc114fa5adeabaf99ad81d8b683435afb7f, 0x169d8cd35287b8292902371d04e51a01450d08845911f2393563b754ca859767); - vk.gammaABC[1] = Pairing.G1Point(0x26efb6f2c684ac0efe064724e6417e13060a963c0d1684fad0fd1c4168b29055, 0x2c1aa9c6e49dc7a7ccb633f02195c9a8fd1aab04fac22b89056e1c33b9c40188); - vk.gammaABC[2] = Pairing.G1Point(0x522736633167bb2752cfda11562c05b2d17ab8f5a0a5615f7f14972f0fb7ccd, 0x8648d86f08c4afd8578bd3a1ac84eadc6168f48551ffa3a20b7630070d83f37); - } + // delta + 0x19769645773ead44e472cc5e7c4e10452c04c822eb30907a02eb040b9a27354d, 0x5154440eb40fb1784183c61fb0e601f37987c550f6ed3fad38c250dd8c1b8fd, + 0x2f1f75b1858a0054df7f216ef1b56f309f164179bfca1741062c724c8556dc8c, 0x25909e78312ff8925a6c32df4510716c58ad8433582ad192be8ebcf3e4958533 + ]; - function _getStaticProof (Verifier.ProofWithInput memory output) - internal pure - { - Verifier.Proof memory proof = output.proof; - proof.B = Pairing.G2Point([0x2e416841c35c40c19ad12b5412257c30000997a34fe80ceee4ef05ffae4e5dd7, 0xca0968c96862fa37a3e7f6352e036715b19f650c3a088054a9fd7145a98ed27], [0x28d28ee72c8091bf9999a9776098880bacbc3c52fcfa25d669a8c8bbaced0cba, 0xabc52932061ab659f7127549e0a7d27626f44f6829cd22bb2e36f3828b30364]); - proof.A = Pairing.G1Point(0x6e07b410bc94ff66d22fc9c954649e25e46f05cdf0fdc4f8482ab97b8d3e618, 0x25087e637a414e698bd1a661bdf1dad9234f6a8a22b2b439422aa6aa183c0482); - proof.C = Pairing.G1Point(0x499945e18eebc8eabb2143f02bbd4c1d7165715c60c1236cb42442e76506a2e, 0x208074aa4a026f42e086089c50fd815038cfaba4f963c23535fecd0f627b17d6); - output.input = new uint256[](2); - output.input[0] = 0x6f63883e503af3bf844c55046e43b5c79f7676c67327d0267f2e1a1a76f294b; - output.input[1] = 0x7; + uint256[] memory gammaABC = new uint256[](6); + // Point 0 + gammaABC[0] = 0x1caac86452b8e9a97f3999ecb5655bc114fa5adeabaf99ad81d8b683435afb7f; + gammaABC[1] = 0x169d8cd35287b8292902371d04e51a01450d08845911f2393563b754ca859767; + + // Point 1 + gammaABC[2] = 0x26efb6f2c684ac0efe064724e6417e13060a963c0d1684fad0fd1c4168b29055; + gammaABC[3] = 0x2c1aa9c6e49dc7a7ccb633f02195c9a8fd1aab04fac22b89056e1c33b9c40188; + + // Point 2 + gammaABC[4] = 0x522736633167bb2752cfda11562c05b2d17ab8f5a0a5615f7f14972f0fb7ccd; + gammaABC[5] = 0x8648d86f08c4afd8578bd3a1ac84eadc6168f48551ffa3a20b7630070d83f37; + + uint256[8] memory proof = [ + // A (G1) + 0x6e07b410bc94ff66d22fc9c954649e25e46f05cdf0fdc4f8482ab97b8d3e618, 0x25087e637a414e698bd1a661bdf1dad9234f6a8a22b2b439422aa6aa183c0482, + + // B (G2) + 0x2e416841c35c40c19ad12b5412257c30000997a34fe80ceee4ef05ffae4e5dd7, 0xca0968c96862fa37a3e7f6352e036715b19f650c3a088054a9fd7145a98ed27, + 0x28d28ee72c8091bf9999a9776098880bacbc3c52fcfa25d669a8c8bbaced0cba, 0xabc52932061ab659f7127549e0a7d27626f44f6829cd22bb2e36f3828b30364, + + // C (G1) + 0x499945e18eebc8eabb2143f02bbd4c1d7165715c60c1236cb42442e76506a2e, 0x208074aa4a026f42e086089c50fd815038cfaba4f963c23535fecd0f627b17d6 + ]; + + uint256[] memory inputs = new uint256[](2); + inputs[0] = 0x6f63883e503af3bf844c55046e43b5c79f7676c67327d0267f2e1a1a76f294b; + inputs[1] = 0x7; + + Assert.isTrue( Verifier.Verify( vk, gammaABC, proof, inputs ), "Verification failed"); } }