arnaucube
arnaucube/circom-compatPublic Self-hosted repository
circom-compat/tests/verifier.sol
tests/verifier.solRaw
  1// THIS FILE IS GENERATED BY HARDHAT-CIRCOM. DO NOT EDIT THIS FILE.
  2
  3//
  4// Copyright 2017 Christian Reitwiessner
  5// 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:
  6// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  7// 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.
  8//
  9// 2019 OKIMS
 10//      ported to solidity 0.5
 11//      fixed linter warnings
 12//      added requiere error messages
 13//
 14pragma solidity ^0.7.6;
 15pragma abicoder v2;
 16
 17contract TestVerifier{
 18    constructor() {}
 19
 20    function verify(
 21        uint256[] memory input,
 22        Verifier.Proof memory proof,
 23        Verifier.VerifyingKey memory vk
 24    ) public view returns (bool) {
 25        uint256 err = Verifier.verify(
 26            input,
 27            proof,
 28            vk
 29        );
 30
 31        if (err == 0) {
 32            return true;
 33        } else {
 34            return false;
 35        }
 36    }
 37}
 38
 39library Verifier {
 40    using Pairing for *;
 41    struct VerifyingKey {
 42        Pairing.G1Point alfa1;
 43        Pairing.G2Point beta2;
 44        Pairing.G2Point gamma2;
 45        Pairing.G2Point delta2;
 46        Pairing.G1Point[] IC;
 47    }
 48    struct Proof {
 49        Pairing.G1Point A;
 50        Pairing.G2Point B;
 51        Pairing.G1Point C;
 52    }
 53
 54    function verify(
 55        uint256[] memory input,
 56        Proof memory proof,
 57        VerifyingKey memory vk
 58    ) internal view returns (uint256) {
 59        uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
 60        require(input.length + 1 == vk.IC.length, "verifier-bad-input");
 61        // Compute the linear combination vk_x
 62        Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
 63        for (uint256 i = 0; i < input.length; i++) {
 64            require(input[i] < snark_scalar_field, "verifier-gte-snark-scalar-field");
 65            vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i]));
 66        }
 67        vk_x = Pairing.addition(vk_x, vk.IC[0]);
 68        if (
 69            !Pairing.pairingProd4(
 70                Pairing.negate(proof.A),
 71                proof.B,
 72                vk.alfa1,
 73                vk.beta2,
 74                vk_x,
 75                vk.gamma2,
 76                proof.C,
 77                vk.delta2
 78            )
 79        ) return 1;
 80        return 0;
 81    }
 82
 83    function verifyProof(
 84        uint256[2] memory a,
 85        uint256[2][2] memory b,
 86        uint256[2] memory c,
 87        uint256[] memory input,
 88        VerifyingKey memory vk
 89    ) internal view returns (bool) {
 90        Proof memory proof;
 91        proof.A = Pairing.G1Point(a[0], a[1]);
 92        proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
 93        proof.C = Pairing.G1Point(c[0], c[1]);
 94        if (verify(input, proof, vk) == 0) {
 95            return true;
 96        } else {
 97            return false;
 98        }
 99    }
100}
101
102library Pairing {
103    struct G1Point {
104        uint256 X;
105        uint256 Y;
106    }
107    // Encoding of field elements is: X[0] * z + X[1]
108    struct G2Point {
109        uint256[2] X;
110        uint256[2] Y;
111    }
112
113    /// @return the generator of G1
114    function P1() internal pure returns (G1Point memory) {
115        return G1Point(1, 2);
116    }
117
118    /// @return the generator of G2
119    function P2() internal pure returns (G2Point memory) {
120        // Original code point
121        return
122            G2Point(
123                [
124                    11559732032986387107991004021392285783925812861821192530917403151452391805634,
125                    10857046999023057135944570762232829481370756359578518086990519993285655852781
126                ],
127                [
128                    4082367875863433681332203403145435568316851327593401208105741076214120093531,
129                    8495653923123431417604973247489272438418190587263600148770280649306958101930
130                ]
131            );
132
133        /*
134        // Changed by Jordi point
135        return G2Point(
136            [10857046999023057135944570762232829481370756359578518086990519993285655852781,
137             11559732032986387107991004021392285783925812861821192530917403151452391805634],
138            [8495653923123431417604973247489272438418190587263600148770280649306958101930,
139             4082367875863433681332203403145435568316851327593401208105741076214120093531]
140        );
141*/
142    }
143
144    /// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.
145    function negate(G1Point memory p) internal pure returns (G1Point memory r) {
146        // The prime q in the base field F_q for G1
147            uint256 q
148         = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
149        if (p.X == 0 && p.Y == 0) return G1Point(0, 0);
150        return G1Point(p.X, q - (p.Y % q));
151    }
152
153    /// @return r the sum of two points of G1
154    function addition(G1Point memory p1, G1Point memory p2)
155        internal
156        view
157        returns (G1Point memory r)
158    {
159        uint256[4] memory input;
160        input[0] = p1.X;
161        input[1] = p1.Y;
162        input[2] = p2.X;
163        input[3] = p2.Y;
164        bool success;
165        // solium-disable-next-line security/no-inline-assembly
166        assembly {
167            success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
168            // Use "invalid" to make gas estimation work
169            switch success
170                case 0 {
171                    invalid()
172                }
173        }
174        require(success, "pairing-add-failed");
175    }
176
177    /// @return r the product of a point on G1 and a scalar, i.e.
178    /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.
179    function scalar_mul(G1Point memory p, uint256 s)
180        internal
181        view
182        returns (G1Point memory r)
183    {
184        uint256[3] memory input;
185        input[0] = p.X;
186        input[1] = p.Y;
187        input[2] = s;
188        bool success;
189        // solium-disable-next-line security/no-inline-assembly
190        assembly {
191            success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
192            // Use "invalid" to make gas estimation work
193            switch success
194                case 0 {
195                    invalid()
196                }
197        }
198        require(success, "pairing-mul-failed");
199    }
200
201    /// @return the result of computing the pairing check
202    /// e(p1[0], p2[0]) *  .... * e(p1[n], p2[n]) == 1
203    /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
204    /// return true.
205    function pairing(G1Point[] memory p1, G2Point[] memory p2)
206        internal
207        view
208        returns (bool)
209    {
210        require(p1.length == p2.length, "pairing-lengths-failed");
211        uint256 elements = p1.length;
212        uint256 inputSize = elements * 6;
213        uint256[] memory input = new uint256[](inputSize);
214        for (uint256 i = 0; i < elements; i++) {
215            input[i * 6 + 0] = p1[i].X;
216            input[i * 6 + 1] = p1[i].Y;
217            input[i * 6 + 2] = p2[i].X[0];
218            input[i * 6 + 3] = p2[i].X[1];
219            input[i * 6 + 4] = p2[i].Y[0];
220            input[i * 6 + 5] = p2[i].Y[1];
221        }
222        uint256[1] memory out;
223        bool success;
224        // solium-disable-next-line security/no-inline-assembly
225        assembly {
226            success := staticcall(
227                sub(gas(), 2000),
228                8,
229                add(input, 0x20),
230                mul(inputSize, 0x20),
231                out,
232                0x20
233            )
234            // Use "invalid" to make gas estimation work
235            switch success
236                case 0 {
237                    invalid()
238                }
239        }
240        require(success, "pairing-opcode-failed");
241        return out[0] != 0;
242    }
243
244    /// Convenience method for a pairing check for two pairs.
245    function pairingProd2(
246        G1Point memory a1,
247        G2Point memory a2,
248        G1Point memory b1,
249        G2Point memory b2
250    ) internal view returns (bool) {
251        G1Point[] memory p1 = new G1Point[](2);
252        G2Point[] memory p2 = new G2Point[](2);
253        p1[0] = a1;
254        p1[1] = b1;
255        p2[0] = a2;
256        p2[1] = b2;
257        return pairing(p1, p2);
258    }
259
260    /// Convenience method for a pairing check for three pairs.
261    function pairingProd3(
262        G1Point memory a1,
263        G2Point memory a2,
264        G1Point memory b1,
265        G2Point memory b2,
266        G1Point memory c1,
267        G2Point memory c2
268    ) internal view returns (bool) {
269        G1Point[] memory p1 = new G1Point[](3);
270        G2Point[] memory p2 = new G2Point[](3);
271        p1[0] = a1;
272        p1[1] = b1;
273        p1[2] = c1;
274        p2[0] = a2;
275        p2[1] = b2;
276        p2[2] = c2;
277        return pairing(p1, p2);
278    }
279
280    /// Convenience method for a pairing check for four pairs.
281    function pairingProd4(
282        G1Point memory a1,
283        G2Point memory a2,
284        G1Point memory b1,
285        G2Point memory b2,
286        G1Point memory c1,
287        G2Point memory c2,
288        G1Point memory d1,
289        G2Point memory d2
290    ) internal view returns (bool) {
291        G1Point[] memory p1 = new G1Point[](4);
292        G2Point[] memory p2 = new G2Point[](4);
293        p1[0] = a1;
294        p1[1] = b1;
295        p1[2] = c1;
296        p1[3] = d1;
297        p2[0] = a2;
298        p2[1] = b2;
299        p2[2] = c2;
300        p2[3] = d2;
301        return pairing(p1, p2);
302    }
303}
304