|
| 1 | +// Take a look at some other code,which is taken from https://github.com/JacobEberhardt/ZoKrates |
| 2 | + |
| 3 | +pragma solidity ^0.5.0; |
| 4 | + |
| 5 | +library Verifier |
| 6 | +{ |
| 7 | + function ScalarField () |
| 8 | + internal pure returns (uint256) |
| 9 | + { |
| 10 | + return 21888242871839275222246405745257275088548364400416034343698204186575808495617; |
| 11 | + } |
| 12 | + |
| 13 | + |
| 14 | + function NegateY( uint256 Y ) |
| 15 | + internal pure returns (uint256) |
| 16 | + { |
| 17 | + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; |
| 18 | + return q - (Y % q); |
| 19 | + } |
| 20 | + |
| 21 | + |
| 22 | + /* |
| 23 | + * This implements the Solidity equivalent of the following Python code: |
| 24 | +
|
| 25 | + from py_ecc.bn128 import * |
| 26 | +
|
| 27 | + data = # ... arguments to function [in_vk, vk_gammaABC, in_proof, proof_inputs] |
| 28 | +
|
| 29 | + vk = [int(_, 16) for _ in data[0]] |
| 30 | + ic = [FQ(int(_, 16)) for _ in data[1]] |
| 31 | + proof = [int(_, 16) for _ in data[2]] |
| 32 | + inputs = [int(_, 16) for _ in data[3]] |
| 33 | +
|
| 34 | + it = iter(ic) |
| 35 | + ic = [(_, next(it)) for _ in it] |
| 36 | + vk_alpha = [FQ(_) for _ in vk[:2]] |
| 37 | + vk_beta = (FQ2(vk[2:4][::-1]), FQ2(vk[4:6][::-1])) |
| 38 | + vk_gamma = (FQ2(vk[6:8][::-1]), FQ2(vk[8:10][::-1])) |
| 39 | + vk_delta = (FQ2(vk[10:12][::-1]), FQ2(vk[12:14][::-1])) |
| 40 | +
|
| 41 | + assert is_on_curve(vk_alpha, b) |
| 42 | + assert is_on_curve(vk_beta, b2) |
| 43 | + assert is_on_curve(vk_gamma, b2) |
| 44 | + assert is_on_curve(vk_delta, b2) |
| 45 | +
|
| 46 | + proof_A = [FQ(_) for _ in proof[:2]] |
| 47 | + proof_B = (FQ2(proof[2:4][::-1]), FQ2(proof[4:-2][::-1])) |
| 48 | + proof_C = [FQ(_) for _ in proof[-2:]] |
| 49 | +
|
| 50 | + assert is_on_curve(proof_A, b) |
| 51 | + assert is_on_curve(proof_B, b2) |
| 52 | + assert is_on_curve(proof_C, b) |
| 53 | +
|
| 54 | + vk_x = ic[0] |
| 55 | + for i, s in enumerate(inputs): |
| 56 | + vk_x = add(vk_x, multiply(ic[i + 1], s)) |
| 57 | +
|
| 58 | + check_1 = pairing(proof_B, proof_A) |
| 59 | + check_2 = pairing(vk_beta, neg(vk_alpha)) |
| 60 | + check_3 = pairing(vk_gamma, neg(vk_x)) |
| 61 | + check_4 = pairing(vk_delta, neg(proof_C)) |
| 62 | +
|
| 63 | + ok = check_1 * check_2 * check_3 * check_4 |
| 64 | + assert ok == FQ12.one() |
| 65 | + */ |
| 66 | + function Verify ( uint256[14] memory in_vk, uint256[] memory vk_gammaABC, uint256[8] memory in_proof, uint256[] memory proof_inputs ) |
| 67 | + internal view returns (bool) |
| 68 | + { |
| 69 | + uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; |
| 70 | + require( ((vk_gammaABC.length / 2) - 1) == proof_inputs.length ); |
| 71 | + |
| 72 | + // Compute the linear combination vk_x |
| 73 | + uint256[3] memory mul_input; |
| 74 | + uint256[4] memory add_input; |
| 75 | + bool success; |
| 76 | + uint m = 2; |
| 77 | + |
| 78 | + // First two fields are used as the sum |
| 79 | + add_input[0] = vk_gammaABC[0]; |
| 80 | + add_input[1] = vk_gammaABC[1]; |
| 81 | + |
| 82 | + // Performs a sum of gammaABC[0] + sum[ gammaABC[i+1]^proof_inputs[i] ] |
| 83 | + for (uint i = 0; i < proof_inputs.length; i++) |
| 84 | + { |
| 85 | + require( proof_inputs[i] < snark_scalar_field ); |
| 86 | + mul_input[0] = vk_gammaABC[m++]; |
| 87 | + mul_input[1] = vk_gammaABC[m++]; |
| 88 | + mul_input[2] = proof_inputs[i]; |
| 89 | + |
| 90 | + assembly { |
| 91 | + // ECMUL, output to last 2 elements of `add_input` |
| 92 | + success := staticcall(sub(gas, 2000), 7, mul_input, 0x80, add(add_input, 0x40), 0x60) |
| 93 | + } |
| 94 | + require( success ); |
| 95 | + |
| 96 | + assembly { |
| 97 | + // ECADD |
| 98 | + success := staticcall(sub(gas, 2000), 6, add_input, 0xc0, add_input, 0x60) |
| 99 | + } |
| 100 | + require( success ); |
| 101 | + } |
| 102 | + |
| 103 | + uint[24] memory input = [ |
| 104 | + // (proof.A, proof.B) |
| 105 | + in_proof[0], in_proof[1], // proof.A (G1) |
| 106 | + in_proof[2], in_proof[3], in_proof[4], in_proof[5], // proof.B (G2) |
| 107 | + |
| 108 | + // (-vk.alpha, vk.beta) |
| 109 | + in_vk[0], NegateY(in_vk[1]), // -vk.alpha (G1) |
| 110 | + in_vk[2], in_vk[3], in_vk[4], in_vk[5], // vk.beta (G2) |
| 111 | + |
| 112 | + // (-vk_x, vk.gamma) |
| 113 | + add_input[0], NegateY(add_input[1]), // -vk_x (G1) |
| 114 | + in_vk[6], in_vk[7], in_vk[8], in_vk[9], // vk.gamma (G2) |
| 115 | + |
| 116 | + // (-proof.C, vk.delta) |
| 117 | + in_proof[6], NegateY(in_proof[7]), // -proof.C (G1) |
| 118 | + in_vk[10], in_vk[11], in_vk[12], in_vk[13] // vk.delta (G2) |
| 119 | + ]; |
| 120 | + |
| 121 | + uint[1] memory out; |
| 122 | + assembly { |
| 123 | + success := staticcall(sub(gas, 2000), 8, input, 768, out, 0x20) |
| 124 | + } |
| 125 | + require(success); |
| 126 | + return out[0] != 0; |
| 127 | + } |
| 128 | +} |
0 commit comments