| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 |
| // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Pairing} from '../libraries/Pairing.sol';
contract ScopeNullifierVerifier {
using Pairing for *;
uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
struct VerifyingKey {
Pairing.G1Point alpha1;
Pairing.G2Point beta2;
Pairing.G2Point gamma2;
Pairing.G2Point delta2;
Pairing.G1Point[7] IC;
}
struct Proof {
Pairing.G1Point A;
Pairing.G2Point B;
Pairing.G1Point C;
}
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
vk.alpha1 = Pairing.G1Point(uint256(20491192805390485299153009773594534940189261866228447918068658471970481763042),uint256(9383485363053290200918347156157836566562967994039712273449902621266178545958));
vk.beta2 = Pairing.G2Point([uint256(4252822878758300859123897981450591353533073413197771768651442665752259397132),uint256(6375614351688725206403948262868962793625744043794305715222011528459656738731)], [uint256(21847035105528745403288232691147584728191162732299865338377159692350059136679),uint256(10505242626370262277552901082094356697409835680220590971873171140371331206856)]);
vk.gamma2 = Pairing.G2Point([uint256(11559732032986387107991004021392285783925812861821192530917403151452391805634),uint256(10857046999023057135944570762232829481370756359578518086990519993285655852781)], [uint256(4082367875863433681332203403145435568316851327593401208105741076214120093531),uint256(8495653923123431417604973247489272438418190587263600148770280649306958101930)]);
vk.delta2 = Pairing.G2Point([uint256(5666489024275286169250791440722814977614126163778206438141262556282061512002),uint256(540747141504075684752232898717393297822559868876345671598445347660931523251)], [uint256(17190886388044124829417364226173329005889292514756956656149420079968651447186),uint256(4393450194024433026294902644308966913288665920071257685620003833050151819571)]);
vk.IC[0] = Pairing.G1Point(uint256(11903510552258965149535766990334045400718664941719931907900414114512168951723),uint256(6018504193352359221002929867148393780119681496717989242481605164824219853171));
vk.IC[1] = Pairing.G1Point(uint256(8634393683357695741162691821923171296877983580540306228926673107463201591678),uint256(18812528258074360139442142016133999509597661419000666915245136913330799070168));
vk.IC[2] = Pairing.G1Point(uint256(19118826476775952662494208114309931037651099753194341426050790555026506942542),uint256(13474347494827073503606825312957201118876277062211757196491967680375889623619));
vk.IC[3] = Pairing.G1Point(uint256(1595398998032590462347042337115166670753940052080071583382824951603520431755),uint256(5219981137899726150547269794460954751574675007643444704741602683715317206003));
vk.IC[4] = Pairing.G1Point(uint256(311975309415029222617554096876375552852632482603413731411501820422141528274),uint256(301918551398995084114892405101556908156602266797726792129458990077553380962));
vk.IC[5] = Pairing.G1Point(uint256(17657462559350247815644763332673472470361174443560019141359062904485776475340),uint256(18143183638755761461091576883018118058392108705137317138884854423331887287903));
vk.IC[6] = Pairing.G1Point(uint256(2950221870316210072926604855533020394454953379578230622412982695526173242896),uint256(14402752147162090261849565486474814081514910189409119333357222730798349881663));
}
/*
* @returns Whether the proof is valid given the hardcoded verifying key
* above and the public inputs
*/
function verifyProof(
uint256[] calldata input,
uint256[8] calldata _proof
) public view returns (bool) {
Proof memory proof;
proof.A = Pairing.G1Point(_proof[0], _proof[1]);
proof.B = Pairing.G2Point([_proof[2], _proof[3]], [_proof[4], _proof[5]]);
proof.C = Pairing.G1Point(_proof[6], _proof[7]);
VerifyingKey memory vk = verifyingKey();
// Compute the linear combination vk_x
Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
// Make sure that proof.A, B, and C are each less than the prime q
require(proof.A.X < PRIME_Q, "verifier-aX-gte-prime-q");
require(proof.A.Y < PRIME_Q, "verifier-aY-gte-prime-q");
require(proof.B.X[0] < PRIME_Q, "verifier-bX0-gte-prime-q");
require(proof.B.Y[0] < PRIME_Q, "verifier-bY0-gte-prime-q");
require(proof.B.X[1] < PRIME_Q, "verifier-bX1-gte-prime-q");
require(proof.B.Y[1] < PRIME_Q, "verifier-bY1-gte-prime-q");
require(proof.C.X < PRIME_Q, "verifier-cX-gte-prime-q");
require(proof.C.Y < PRIME_Q, "verifier-cY-gte-prime-q");
// Make sure that every input is less than the snark scalar field
//for (uint256 i = 0; i < input.length; i++) {
for (uint256 i = 0; i < 6; i++) {
require(input[i] < SNARK_SCALAR_FIELD,"verifier-gte-snark-scalar-field");
vk_x = Pairing.plus(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i]));
}
vk_x = Pairing.plus(vk_x, vk.IC[0]);
return Pairing.pairing(
Pairing.negate(proof.A),
proof.B,
vk.alpha1,
vk.beta2,
vk_x,
vk.gamma2,
proof.C,
vk.delta2
);
}
}
|