mirror of
https://github.com/selfxyz/self.git
synced 2026-01-23 05:28:02 -05:00
@@ -1,32 +0,0 @@
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import "zodiac/core/Module.sol";
|
||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
||||
|
||||
contract PassportRecoverySafeModule is Module {
|
||||
ERC721Enumerable public passportSBT;
|
||||
uint256 public id;
|
||||
|
||||
error NotAuthorized();
|
||||
|
||||
constructor() {
|
||||
_transferOwnership(msg.sender);
|
||||
}
|
||||
|
||||
function setUp(bytes memory initializeParams) public override {}
|
||||
|
||||
function init(address safe, address _passportSBT, uint256 _id) public {
|
||||
setAvatar(safe);
|
||||
setTarget(safe);
|
||||
passportSBT = _passportSBT;
|
||||
id = _id;
|
||||
}
|
||||
|
||||
function claimSafe(bytes memory data) public {
|
||||
if (passportSBT.ownerOf(id) == msg.sender) {
|
||||
exec(avatar, 0, data, Enum.Operation.Call);
|
||||
} else {
|
||||
revert NotAuthorized();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/utils/Counters.sol";
|
||||
import {Verifier} from "./RsaSha256Verifier.sol";
|
||||
|
||||
contract ProofOfBaguette is ERC721Enumerable, Ownable {
|
||||
using Counters for Counters.Counter;
|
||||
|
||||
Verifier public immutable verifier;
|
||||
address public cscaPubkey = 0x0000000000000000000000000000000000000000;
|
||||
|
||||
Counters.Counter public tokenCounter;
|
||||
|
||||
constructor(Verifier v) ERC721("ProofOfPassport", "ProofOfPassport") {
|
||||
verifier = v;
|
||||
transferOwnership(msg.sender);
|
||||
}
|
||||
|
||||
function setCSCApubKey(address _CSCApubKey) public onlyOwner {
|
||||
cscaPubkey = _CSCApubKey;
|
||||
}
|
||||
|
||||
// function check(
|
||||
// uint256[2] memory a,
|
||||
// uint256[2][2] memory b,
|
||||
// uint256[2] memory c,
|
||||
// uint256[100] memory inputs
|
||||
// ) public {
|
||||
// require(Pairing.verifyProof(a, b, c, inputs), "Invalid Proof");
|
||||
// }
|
||||
|
||||
function mint(
|
||||
uint256[2] memory a,
|
||||
uint256[2][2] memory b,
|
||||
uint256[2] memory c,
|
||||
uint256[97] memory inputs
|
||||
) public {
|
||||
// Check eth address committed to in proof matches msg.sender, to avoid replayability
|
||||
// require(address(uint160(inputs[addressIndexInSignals])) == msg.sender, "Invalid address");
|
||||
|
||||
// Verify that the public key for RSA matches the hardcoded one
|
||||
// for (uint256 i = body_len; i < msg_len - 1; i++) {
|
||||
// require(mailServer.isVerified(domain, i - body_len, inputs[i]), "Invalid: RSA modulus not matched");
|
||||
// }
|
||||
|
||||
// Verify that the public key for RSA matches the hardcoded one
|
||||
// commented out for now, since hard to keep up with all
|
||||
// require(cscaPubkey == inputs[], "Invalid pubkey in inputs");
|
||||
|
||||
require(verifier.verifyProof(a, b, c, inputs), "Invalid Proof");
|
||||
|
||||
// Effects: Mint token
|
||||
uint256 tokenId = tokenCounter.current() + 1;
|
||||
_mint(msg.sender, tokenId);
|
||||
tokenCounter.increment();
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId
|
||||
) internal {
|
||||
require(from == address(0), "Cannot transfer - Passport is soulbound");
|
||||
}
|
||||
}
|
||||
183
contracts/contracts/ProofOfPassport.sol
Normal file
183
contracts/contracts/ProofOfPassport.sol
Normal file
@@ -0,0 +1,183 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.18;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import {Groth16Verifier} from "./Verifier.sol";
|
||||
import {Base64} from "./libraries/Base64.sol";
|
||||
import "hardhat/console.sol";
|
||||
|
||||
contract ProofOfPassport is ERC721Enumerable, Ownable {
|
||||
using Strings for uint256;
|
||||
using Base64 for *;
|
||||
|
||||
Groth16Verifier public immutable verifier;
|
||||
address public cscaPubkey = 0x0000000000000000000000000000000000000000;
|
||||
|
||||
mapping(uint256 => bool) public nullifiers;
|
||||
|
||||
struct AttributePosition {
|
||||
string name;
|
||||
uint256 start;
|
||||
uint256 end;
|
||||
uint256 index;
|
||||
}
|
||||
|
||||
struct Attributes {
|
||||
string[7] values;
|
||||
}
|
||||
|
||||
AttributePosition[] public attributePositions;
|
||||
|
||||
mapping(uint256 => Attributes) private tokenAttributes;
|
||||
|
||||
constructor(Groth16Verifier v) ERC721("ProofOfPassport", "ProofOfPassport") {
|
||||
verifier = v;
|
||||
setupAttributes();
|
||||
transferOwnership(msg.sender);
|
||||
}
|
||||
|
||||
function setupAttributes() internal {
|
||||
attributePositions.push(AttributePosition("issuing_state", 2, 4, 0));
|
||||
attributePositions.push(AttributePosition("name", 5, 43, 1));
|
||||
attributePositions.push(AttributePosition("passport_number", 44, 52, 2));
|
||||
attributePositions.push(AttributePosition("nationality", 54, 56, 3));
|
||||
attributePositions.push(AttributePosition("date_of_birth", 57, 62, 4));
|
||||
attributePositions.push(AttributePosition("gender", 64, 64, 5));
|
||||
attributePositions.push(AttributePosition("expiry_date", 65, 70, 6));
|
||||
}
|
||||
|
||||
function setCSCApubKey(address _CSCApubKey) public onlyOwner {
|
||||
cscaPubkey = _CSCApubKey;
|
||||
}
|
||||
|
||||
function mint(
|
||||
uint256[2] memory a,
|
||||
uint256[2][2] memory b,
|
||||
uint256[2] memory c,
|
||||
uint256[6] memory inputs
|
||||
) public {
|
||||
// Check eth address committed to in proof matches msg.sender, to avoid replayability
|
||||
require(address(uint160(inputs[5])) == msg.sender, "Invalid address");
|
||||
// check that the nullifier has not been used before
|
||||
require(!nullifiers[inputs[3]], "Signature already nullified");
|
||||
|
||||
// Verify that the public key for RSA matches the hardcoded one
|
||||
// for (uint256 i = body_len; i < msg_len - 1; i++) {
|
||||
// require(mailServer.isVerified(domain, i - body_len, inputs[i]), "Invalid: RSA modulus not matched");
|
||||
// }
|
||||
// inputs[4]
|
||||
|
||||
// Verify that the public key for RSA matches the hardcoded one
|
||||
// commented out for now, since hard to keep up with all
|
||||
// require(cscaPubkey == inputs[], "Invalid pubkey in inputs");
|
||||
|
||||
require(verifier.verifyProof(a, b, c, inputs), "Invalid Proof");
|
||||
|
||||
// Effects: Mint token
|
||||
uint256 newTokenId = totalSupply();
|
||||
_mint(msg.sender, newTokenId);
|
||||
nullifiers[inputs[3]] = true;
|
||||
|
||||
|
||||
// Set attributes
|
||||
uint256[3] memory firstThree = sliceFirstThree(inputs);
|
||||
bytes memory charcodes = fieldElementsToBytes(firstThree);
|
||||
// console.logBytes1(charcodes[21]);
|
||||
|
||||
Attributes storage attributes = tokenAttributes[newTokenId];
|
||||
|
||||
for (uint i = 0; i < attributePositions.length; i++) {
|
||||
AttributePosition memory attribute = attributePositions[i];
|
||||
bytes memory attributeBytes = new bytes(attribute.end - attribute.start + 1);
|
||||
for (uint j = attribute.start; j <= attribute.end; j++) {
|
||||
attributeBytes[j - attribute.start] = charcodes[j];
|
||||
}
|
||||
string memory attributeValue = string(attributeBytes);
|
||||
attributes.values[i] = attributeValue;
|
||||
console.log(attribute.name, attributes.values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function fieldElementsToBytes(uint256[3] memory publicSignals) public pure returns (bytes memory) {
|
||||
uint8[3] memory bytesCount = [31, 31, 26];
|
||||
bytes memory bytesArray = new bytes(88); // 31 + 31 + 26
|
||||
|
||||
uint256 index = 0;
|
||||
for (uint256 i = 0; i < 3; i++) {
|
||||
uint256 element = publicSignals[i];
|
||||
for (uint8 j = 0; j < bytesCount[i]; j++) {
|
||||
bytesArray[index++] = bytes1(uint8(element & 0xFF));
|
||||
element = element >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesArray;
|
||||
}
|
||||
|
||||
function sliceFirstThree(uint256[6] memory input) public pure returns (uint256[3] memory) {
|
||||
uint256[3] memory sliced;
|
||||
|
||||
for (uint256 i = 0; i < 3; i++) {
|
||||
sliced[i] = input[i];
|
||||
}
|
||||
|
||||
return sliced;
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId,
|
||||
uint256 batchSize
|
||||
) internal virtual override {
|
||||
super._beforeTokenTransfer(from, to, tokenId, batchSize);
|
||||
require(from == address(0), "Cannot transfer - Proof of Passport is soulbound");
|
||||
}
|
||||
|
||||
function tokenURI(
|
||||
uint256 _tokenId
|
||||
) public view virtual override returns (string memory) {
|
||||
require(
|
||||
_exists(_tokenId),
|
||||
"ERC721Metadata: URI query for nonexistent token"
|
||||
);
|
||||
Attributes memory attributes = tokenAttributes[_tokenId];
|
||||
|
||||
console.log("Issuing state in tokenURI", attributes.values[0]);
|
||||
|
||||
bytes memory baseURI = (
|
||||
abi.encodePacked(
|
||||
'{ "attributes": [',
|
||||
'{"trait_type": "Issuing State", "value": "',
|
||||
attributes.values[0],
|
||||
'"},{"trait_type": "Name", "value": "',
|
||||
attributes.values[1],
|
||||
'"},{"trait_type": "Passport Number", "value": "',
|
||||
attributes.values[2],
|
||||
'"},{"trait_type": "Nationality", "value": "',
|
||||
attributes.values[3],
|
||||
'"},{"trait_type": "Date of birth", "value": "',
|
||||
attributes.values[4],
|
||||
'"},{"trait_type": "Gender", "value": "',
|
||||
attributes.values[5],
|
||||
'"},{"trait_type": "Expiry date", "value": "',
|
||||
attributes.values[6],
|
||||
'"}',
|
||||
"],",
|
||||
'"description": "Proof of Passport guarantees possession of a valid passport.","external_url": "https://github.com/zk-passport/proof-of-passport","image": "https://i.imgur.com/9kvetij.png","name": "Proof of Passport #',
|
||||
_tokenId.toString(),
|
||||
'"}'
|
||||
)
|
||||
);
|
||||
|
||||
return
|
||||
string(
|
||||
abi.encodePacked(
|
||||
"data:application/json;base64,",
|
||||
baseURI.encode()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,713 +0,0 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 2019 OKIMS
|
||||
// ported to solidity 0.5
|
||||
// fixed linter warnings
|
||||
// added requiere error messages
|
||||
//
|
||||
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) {
|
||||
// Original code point
|
||||
return
|
||||
G2Point(
|
||||
[
|
||||
11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||
10857046999023057135944570762232829481370756359578518086990519993285655852781
|
||||
],
|
||||
[
|
||||
4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||
8495653923123431417604973247489272438418190587263600148770280649306958101930
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
// Changed by Jordi point
|
||||
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) 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 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;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
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, "pairing-add-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 view returns (G1Point memory r) {
|
||||
uint[3] memory input;
|
||||
input[0] = p.X;
|
||||
input[1] = p.Y;
|
||||
input[2] = s;
|
||||
bool success;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
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, "pairing-mul-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 view returns (bool) {
|
||||
require(p1.length == p2.length, "pairing-lengths-failed");
|
||||
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;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
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, "pairing-opcode-failed");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
contract Verifier {
|
||||
using Pairing for *;
|
||||
struct VerifyingKey {
|
||||
Pairing.G1Point alfa1;
|
||||
Pairing.G2Point beta2;
|
||||
Pairing.G2Point gamma2;
|
||||
Pairing.G2Point delta2;
|
||||
Pairing.G1Point[] IC;
|
||||
}
|
||||
struct Proof {
|
||||
Pairing.G1Point A;
|
||||
Pairing.G2Point B;
|
||||
Pairing.G1Point C;
|
||||
}
|
||||
|
||||
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.alfa1 = Pairing.G1Point(
|
||||
10315822838385842923250715267205960664501004234546269981482666228112421301117,
|
||||
15862104134162712938961972115840401024611162066277059180121297134493484755175
|
||||
);
|
||||
vk.beta2 = Pairing.G2Point(
|
||||
[
|
||||
16075180890105261855785821136620370206478347851900063884177434889569117892728,
|
||||
8999056094627160946941478319055654711627346279360998804980685260524215980818
|
||||
],
|
||||
[
|
||||
19289495299100654012777091634160205804317123853627581171870946780589078726579,
|
||||
7456059757481809576237403196787593289176357510985305159986791878645463459018
|
||||
]
|
||||
);
|
||||
vk.gamma2 = Pairing.G2Point(
|
||||
[
|
||||
13277046752313471688255968585488007150536152283305619319249966594057859924122,
|
||||
1540853480038841992778609939618416755409643379500817690706199269912373494426
|
||||
],
|
||||
[
|
||||
16195521367762890658515156444872542211791369361419964244676840991686196711549,
|
||||
1050887057282964430320854978389799561269435789211688186694933498698817462348
|
||||
]
|
||||
);
|
||||
vk.delta2 = Pairing.G2Point(
|
||||
[
|
||||
1662324983131052880488960499832632400354165691268048997945168703365805496815,
|
||||
13662480426324514348188284803730524793155591206442565309405901461008907655891
|
||||
],
|
||||
[
|
||||
15309139646391078466810181691750047695011680065613748420932752259577867509989,
|
||||
11930459767156654479077330634914217815349186680049037714663239653430389142355
|
||||
]
|
||||
);
|
||||
vk.IC = new Pairing.G1Point[](98);
|
||||
vk.IC[0] = Pairing.G1Point(
|
||||
1386156676430625766660721327519749365352708612284380407007672518761930314522,
|
||||
5895979564403280714499324620374725835931311522554339174840912272198002116986
|
||||
);
|
||||
vk.IC[1] = Pairing.G1Point(
|
||||
174429888906575054944644195492533447677698808764744275768027474986091262795,
|
||||
19449982332092198717836917024306177058078885300180691030479512833448493420426
|
||||
);
|
||||
vk.IC[2] = Pairing.G1Point(
|
||||
4940702259943724495655268600320625166138928124318746483111841772203931372898,
|
||||
21300085871907717167823229271273029592921718070696716598133485043371262113949
|
||||
);
|
||||
vk.IC[3] = Pairing.G1Point(
|
||||
3970523900986966741454839663423325691036075995128843350657752858925317431017,
|
||||
539367542421702393681320993411652316058906805217114528699814649881160035531
|
||||
);
|
||||
vk.IC[4] = Pairing.G1Point(
|
||||
14541643345260800436706406996787362480110194544530475630171161698573516679920,
|
||||
4783331606526584048777066954770982727121131692786538183643102121348439890988
|
||||
);
|
||||
vk.IC[5] = Pairing.G1Point(
|
||||
1075474176916105569002317826203973479107209650628777996236377287648466962810,
|
||||
3232058447014508876051800237288950058552252367302714558767792524271099812787
|
||||
);
|
||||
vk.IC[6] = Pairing.G1Point(
|
||||
2175834186336017845410894889748902248994354180137067840445873611529706706903,
|
||||
3085466328487208450052471722737790746659231597949473931302689657743879290415
|
||||
);
|
||||
vk.IC[7] = Pairing.G1Point(
|
||||
8148131669390700325085948796744014848738121345402965689215540127469598163871,
|
||||
1459937161639492891103296404430347140474089613091612181507607941234824828188
|
||||
);
|
||||
vk.IC[8] = Pairing.G1Point(
|
||||
19724824811793942534870544715526571102183990820436521365546859310276823467490,
|
||||
9742652052240076179420483064624381054258687108701843582619502567192627148901
|
||||
);
|
||||
vk.IC[9] = Pairing.G1Point(
|
||||
7516612085018412567965384915697804249943140639755254403509406043424863699565,
|
||||
13609389560576142128414010599204241098833066563137827296644138017315963061370
|
||||
);
|
||||
vk.IC[10] = Pairing.G1Point(
|
||||
5396430636568898715071511450196374579073195772247524680870475881840606697294,
|
||||
14213494996959147888574066917872324178671816323712570898472101313990748811357
|
||||
);
|
||||
vk.IC[11] = Pairing.G1Point(
|
||||
19580033029544330967448763121940485539766629034681462072482784578056476122075,
|
||||
4714739906270684478426827011422485533664415859906533725309733675967596336877
|
||||
);
|
||||
vk.IC[12] = Pairing.G1Point(
|
||||
6962906881391363529838287799824200955017681097924230628024324423216037180574,
|
||||
2533319035586796547972968495763128583304226889898155603872302902791149215692
|
||||
);
|
||||
vk.IC[13] = Pairing.G1Point(
|
||||
17536765943492961589593406025711160790038974470090381500798551989642376205429,
|
||||
9210978437865389852687238356987463161070296894056858501516143895498895127801
|
||||
);
|
||||
vk.IC[14] = Pairing.G1Point(
|
||||
12879519606836370836828899572118098335153146603118228135363495427283082247364,
|
||||
5758811831466689143387239476857856589657131463745229429624027029582131264569
|
||||
);
|
||||
vk.IC[15] = Pairing.G1Point(
|
||||
15735427660464208356818266871402603071222212568728528929189278663470048519151,
|
||||
18580418584929980580683876981646262205040063567947776691626290499751484842387
|
||||
);
|
||||
vk.IC[16] = Pairing.G1Point(
|
||||
16672772973559614591916036849008777420093824711538705835090610899870382314653,
|
||||
8188923103596302037595788157162335200890030912840313545299503026362065475579
|
||||
);
|
||||
vk.IC[17] = Pairing.G1Point(
|
||||
3482245003117717783432002198738459699873717589098511868698895399302488358634,
|
||||
19652796079067654964753702546413435895310867146965033514795952134870224747298
|
||||
);
|
||||
vk.IC[18] = Pairing.G1Point(
|
||||
9382323532935595934689116629634156851330374962350295158341742092304036335698,
|
||||
291925329935370804008844005614341459550809875961285224043109628983162794811
|
||||
);
|
||||
vk.IC[19] = Pairing.G1Point(
|
||||
6912981219684193325373956580555507527124688523637412271688548642710145407324,
|
||||
17719276416320101991178800934805150313358144003174217318902641925424693400899
|
||||
);
|
||||
vk.IC[20] = Pairing.G1Point(
|
||||
19266481578774074906374076433526482559085483237651754027979037618702501848415,
|
||||
4864429104782323549403921207719837137283226783050574715140728078210440815125
|
||||
);
|
||||
vk.IC[21] = Pairing.G1Point(
|
||||
14887253562463317132282666699497653091722231007983834420246533880775604202046,
|
||||
20039483939999528919395933890813583839636534363798896837987674667077445002909
|
||||
);
|
||||
vk.IC[22] = Pairing.G1Point(
|
||||
12508816416091085449368756125649842984927777064057218811145926432353321314907,
|
||||
1029754988093911081347891722709482405445904745087304835816390911520486811458
|
||||
);
|
||||
vk.IC[23] = Pairing.G1Point(
|
||||
2005084167017357346303758528212973722634282057561071593677784384715301762428,
|
||||
5542975189718331938312935936918047907052872873683385011086540332580563138005
|
||||
);
|
||||
vk.IC[24] = Pairing.G1Point(
|
||||
574144171155849827838725501058774562989672318997217369030672907489094325392,
|
||||
19011911734470524036198981595964567011458551418797935766148211921982472474741
|
||||
);
|
||||
vk.IC[25] = Pairing.G1Point(
|
||||
3608292935417210943680485162182048774922203693936402328868647729908340527540,
|
||||
19717618713526912033181757546212053048433914196349054761157402425200075671138
|
||||
);
|
||||
vk.IC[26] = Pairing.G1Point(
|
||||
16163461701324146513568429102887561273066181667891291346998415488778690716805,
|
||||
18662884437485380367184050862289985597601843562942757559581184607687570812550
|
||||
);
|
||||
vk.IC[27] = Pairing.G1Point(
|
||||
14994566112480375832970198317517069193388049320082571292718031142344097962255,
|
||||
19889898631674322802597671404075063684983733435916365516196892134719573840178
|
||||
);
|
||||
vk.IC[28] = Pairing.G1Point(
|
||||
736585196548664503732509698047552122038996165424116313982190787863322931826,
|
||||
21019115756986596749277994511714050838771464310078186895547975840389783871138
|
||||
);
|
||||
vk.IC[29] = Pairing.G1Point(
|
||||
10974717193636000167380652442472909714934064969981711063607439335825119243469,
|
||||
8613997549030193852101564196304783271636045228187714896154399752466639047526
|
||||
);
|
||||
vk.IC[30] = Pairing.G1Point(
|
||||
15515808334102622843044245600125992020384745623672581785591253976335954691668,
|
||||
7056069273753880907078615715739794771659566915279338309055469505277556660014
|
||||
);
|
||||
vk.IC[31] = Pairing.G1Point(
|
||||
2026995926214775331423673216302815034683334238220808093286826947311593039794,
|
||||
14548613909100523536915943149130374917224265797462738040649328509010392696205
|
||||
);
|
||||
vk.IC[32] = Pairing.G1Point(
|
||||
7347999393948250440988207859344770709243120088530457172274758503515633459971,
|
||||
20430173716253509790919340588694849367500686486837868170440361371544940846857
|
||||
);
|
||||
vk.IC[33] = Pairing.G1Point(
|
||||
8726020462171177960911520449113858654607194259478482096783149613868723406121,
|
||||
21109992085518709586188037780336334901483462217597999928530659225385204929051
|
||||
);
|
||||
vk.IC[34] = Pairing.G1Point(
|
||||
18759571018089650279499799472273628763502429845355459478077716291216286451672,
|
||||
3061120585842126900115563926687483611216432798358081316062265175950975462706
|
||||
);
|
||||
vk.IC[35] = Pairing.G1Point(
|
||||
10081168513618588217797803738246975722763428651743613956930591217530005755308,
|
||||
5223516720621635076713966633725260161024836955550260381664330387742167168437
|
||||
);
|
||||
vk.IC[36] = Pairing.G1Point(
|
||||
18623257401997776504806348144872345347118220689716572995578481344526381397027,
|
||||
12738216514382521354381755763633144591976312475306345247101617502260715984300
|
||||
);
|
||||
vk.IC[37] = Pairing.G1Point(
|
||||
12613017704259258984783441890484052267798710998400588809375095368441312203177,
|
||||
13154863759245282454936298393415245536123605264867594333724866438497549024170
|
||||
);
|
||||
vk.IC[38] = Pairing.G1Point(
|
||||
12709290832361335753305864258009255307237010774441288781285781702671213114765,
|
||||
18349056269309660723886180747727132860619888970885172282384405779461541989577
|
||||
);
|
||||
vk.IC[39] = Pairing.G1Point(
|
||||
17447538751610051385783414732492525667137731039071585637687353043409911312358,
|
||||
8705755619226884560464931039313987689788884448049673193589169040745836183092
|
||||
);
|
||||
vk.IC[40] = Pairing.G1Point(
|
||||
19903040530418130172724072033663794977209466570949249258688233439835382961705,
|
||||
6538405654339479654547899704613913798731714798978111499534963418797636778536
|
||||
);
|
||||
vk.IC[41] = Pairing.G1Point(
|
||||
20190111036656612665976758535510402352901099971723589132364459219237140650804,
|
||||
11657276287181136248459738132957662348970456139200020118947243073509600583324
|
||||
);
|
||||
vk.IC[42] = Pairing.G1Point(
|
||||
5496409758069382276348459990808117794030958339567169207650726751174822075842,
|
||||
15398624126895562271141819515160389374772951137601086902126706157329463089406
|
||||
);
|
||||
vk.IC[43] = Pairing.G1Point(
|
||||
8151283523500801176883094078648061648579761104703136856876223887187491028764,
|
||||
19699576961944733283219819902822060278574556991476755360120251735226112577042
|
||||
);
|
||||
vk.IC[44] = Pairing.G1Point(
|
||||
8533704954946914002953946046744749163319734782733169970628585647060058140849,
|
||||
5141897905579649570194799195601184296177984332792452257361194331009931371352
|
||||
);
|
||||
vk.IC[45] = Pairing.G1Point(
|
||||
17671515716110934550447360224709626247970759130056552979213535489731669688446,
|
||||
1690274318568461080087753254251786392263489028973782647985819430312525336960
|
||||
);
|
||||
vk.IC[46] = Pairing.G1Point(
|
||||
8478603008571616038378551513375406458692917186348304648150064228029895779958,
|
||||
20116202548019188938994896483571557179861045004954664127312673627929525959276
|
||||
);
|
||||
vk.IC[47] = Pairing.G1Point(
|
||||
6432981094696267073379852248786055231176785645227335199813013566498759785384,
|
||||
14983269753830770996227222283167931949083546323507335724535651513681318189079
|
||||
);
|
||||
vk.IC[48] = Pairing.G1Point(
|
||||
9455507927501800915564496121759986854117031410770932562840240404182614698028,
|
||||
5285955876415145827392451089524707681594893418176652281578834051447348307955
|
||||
);
|
||||
vk.IC[49] = Pairing.G1Point(
|
||||
20714130644236382051591460208572376019763347755510239498689871430769906890685,
|
||||
18654357373482716030683276562311098400463035289899424564068036000769595694407
|
||||
);
|
||||
vk.IC[50] = Pairing.G1Point(
|
||||
16832181157818881181838165095351716004273729658170734148090869509398951353661,
|
||||
13189116767733698206617444976497238961678787103102046696228609244708542732492
|
||||
);
|
||||
vk.IC[51] = Pairing.G1Point(
|
||||
8076452889145567190300790005312690920477320514039067078236315139521658556063,
|
||||
890666235559929062329759673773557091924363971646065907430303231638612724999
|
||||
);
|
||||
vk.IC[52] = Pairing.G1Point(
|
||||
8358804823290743257390543678494170562797974621132658774911399394185092545208,
|
||||
20752753364958656771514688460585465011660082299985374260145811301437669043257
|
||||
);
|
||||
vk.IC[53] = Pairing.G1Point(
|
||||
431866034143667612182321520413242716471591638473939166320447500693829929824,
|
||||
13272258147627911088702851414812922302256821216107539459911504860535837022135
|
||||
);
|
||||
vk.IC[54] = Pairing.G1Point(
|
||||
9173989288857204293038005754886211674464077439638776033201321349164196474616,
|
||||
9129103250645493108241162941947967350521408326116971248120638209361233930192
|
||||
);
|
||||
vk.IC[55] = Pairing.G1Point(
|
||||
14370826205941952851735365552127894021162133888463493633318496244143095511040,
|
||||
1651163962095785808536509256199563475789494126010520314335456260358111804976
|
||||
);
|
||||
vk.IC[56] = Pairing.G1Point(
|
||||
12951186966437270849914379924115857496875963456775592910919046812882705115830,
|
||||
16465255691963080311345885861560112122320977883916615486276340659371056324863
|
||||
);
|
||||
vk.IC[57] = Pairing.G1Point(
|
||||
3283421748134600628821861152296048618970465417807515877620876335991742901315,
|
||||
321535500846302427006164553338203893489982138176792264731766129421299212286
|
||||
);
|
||||
vk.IC[58] = Pairing.G1Point(
|
||||
16855387142616687237143755251732902794908605199755471474196892846417162793353,
|
||||
6761300099779160392813801467707189572028647758855510242027256178070516219805
|
||||
);
|
||||
vk.IC[59] = Pairing.G1Point(
|
||||
15257833521992801874267530841829063197963470852447328292085028034633128521860,
|
||||
2677084778946138423753273144604322607349537157189860183844829718089957601689
|
||||
);
|
||||
vk.IC[60] = Pairing.G1Point(
|
||||
12162232048810887816633786290513237732818779568650791939302917523152130208608,
|
||||
21333612874220018324963566977200031875031579203366186578790260941880595484190
|
||||
);
|
||||
vk.IC[61] = Pairing.G1Point(
|
||||
3391460336279928586355347127909680776960941614168264915045172621785079485704,
|
||||
12982837279076354859831048030572798151280294385261501888099056857982051493723
|
||||
);
|
||||
vk.IC[62] = Pairing.G1Point(
|
||||
15657943681489382687201670166559198773174544761807418817146753024083872167923,
|
||||
18015415673040996199684319960118318566240959606331772073882264856214095914848
|
||||
);
|
||||
vk.IC[63] = Pairing.G1Point(
|
||||
8764939161163047254075099233130913745881634109004943576089798043960197509190,
|
||||
8107199767148537717254346850921330983657137386989043360271851202867981408937
|
||||
);
|
||||
vk.IC[64] = Pairing.G1Point(
|
||||
10021072243678930222406582984936927324952592680308844821701808488346598011536,
|
||||
18628636656506555862260913227929463140408813957986050071538961255104712647438
|
||||
);
|
||||
vk.IC[65] = Pairing.G1Point(
|
||||
17321445808461122141320330203945732558478795973243070098294285860455518065400,
|
||||
16836801211792107863813977849708073042443024384474661086287213089562566255496
|
||||
);
|
||||
vk.IC[66] = Pairing.G1Point(
|
||||
6861883922532910695796926319034380512803020100037212756359821156112905138580,
|
||||
4119726663248857193393003082612555725457402139141352624262468551517744622172
|
||||
);
|
||||
vk.IC[67] = Pairing.G1Point(
|
||||
20779722207278452530034931086404649516930804730094114642064752236829364601447,
|
||||
923216039876130666302755287286364480134410103154729240965964497426983067027
|
||||
);
|
||||
vk.IC[68] = Pairing.G1Point(
|
||||
18223166030017443686801675867411730766342079179157572962560303448024540378873,
|
||||
19137631582171918191178945920059761447327783213698872810575523895658550121438
|
||||
);
|
||||
vk.IC[69] = Pairing.G1Point(
|
||||
19280775121328851013552281475852868120438320598442383749752027288009797861226,
|
||||
12490038968016646741084557672265847583317098207883228839969661867319900663938
|
||||
);
|
||||
vk.IC[70] = Pairing.G1Point(
|
||||
15266937199766366472290794995102829438088329284982774063851360931479775159611,
|
||||
13689004097893574081491974026588805143385995491553380346109157632864045768875
|
||||
);
|
||||
vk.IC[71] = Pairing.G1Point(
|
||||
17127411247775554441458092526202757327238548637076996720303283409273103437241,
|
||||
10596065368731694429534822719625874694561881193931687112659878038042780625711
|
||||
);
|
||||
vk.IC[72] = Pairing.G1Point(
|
||||
20787730078931630052831457097859925558304786674420765003148675017286328663454,
|
||||
4766261406083257091458978020157041851129907303478874471741979469684861357286
|
||||
);
|
||||
vk.IC[73] = Pairing.G1Point(
|
||||
7658787061468359549149413908281153599600426600224344615749437495818897340061,
|
||||
19492153087231292728213440771478900053083907495283660596623580137450879415100
|
||||
);
|
||||
vk.IC[74] = Pairing.G1Point(
|
||||
2659875083118001544715497837457590514140432874048404892210543537504037071661,
|
||||
15950956910927529441229027517507989615611330940703370326686704858035089993977
|
||||
);
|
||||
vk.IC[75] = Pairing.G1Point(
|
||||
894399989010319765961292956333169984328533949797732202422998120207741013782,
|
||||
20592958484709720804789976380652330981257235977335874841811437076585969381001
|
||||
);
|
||||
vk.IC[76] = Pairing.G1Point(
|
||||
20463015942337846506404366208676722951112664440577043884221657224419349265426,
|
||||
6421219926717668723328940652796576549618654759959257419184397188890959888254
|
||||
);
|
||||
vk.IC[77] = Pairing.G1Point(
|
||||
9120006372090123874675982389686869282084694298376106330824231921836495845409,
|
||||
15465095824110179992312247621712212010265469017852248921480310833628600196157
|
||||
);
|
||||
vk.IC[78] = Pairing.G1Point(
|
||||
20878479603359665116911215284012493370991345348316318380338256326707347229536,
|
||||
4023483592190020939497447440294056485175982685635791231809180749028140340638
|
||||
);
|
||||
vk.IC[79] = Pairing.G1Point(
|
||||
8597284910335812117769054177782693879835500749625261064784252225098566359260,
|
||||
1994440743925322001344248550218761689604854304576917328729121903199340521566
|
||||
);
|
||||
vk.IC[80] = Pairing.G1Point(
|
||||
7226426264671955929078859416556503158659896696978967948922009868308681953328,
|
||||
5002887692172752997421567561731103949750630834248867239253107045744551201397
|
||||
);
|
||||
vk.IC[81] = Pairing.G1Point(
|
||||
8163659204347449052568944424719246353276866468717985570811227109999390783526,
|
||||
2423554439374965365549822958553913623548960716554949332971802593317970068208
|
||||
);
|
||||
vk.IC[82] = Pairing.G1Point(
|
||||
1452926204022804055491637328319845396827870792644285034170433031762060878731,
|
||||
4515541462700718639411085202358475754243785926272495802232114060028112391704
|
||||
);
|
||||
vk.IC[83] = Pairing.G1Point(
|
||||
10425052225329871422199244352265298427973414162141911718953442959319724848059,
|
||||
6000980400205901551254828664011101250210525131160335488511361553516655902490
|
||||
);
|
||||
vk.IC[84] = Pairing.G1Point(
|
||||
3443318109975964447008176890335731705529322253119216155023763429975158085456,
|
||||
21667811197670469631232954863890416289566410095141706262390806877014912268732
|
||||
);
|
||||
vk.IC[85] = Pairing.G1Point(
|
||||
11012015869641066138899933574589113596936265876486762743315648962963495824732,
|
||||
17255543862480532041551281296396472142322479563450509347024960074045362179060
|
||||
);
|
||||
vk.IC[86] = Pairing.G1Point(
|
||||
15356674987302087761214804729834932350868870076692636651461027280636953611115,
|
||||
106117314594064361971425646139042972248859283384292253606696261962696377665
|
||||
);
|
||||
vk.IC[87] = Pairing.G1Point(
|
||||
19394337841622616135946277478438753742631263129950419370472461951284656870437,
|
||||
18658921822284494457486069764820562705515256999764362724356266226041497733846
|
||||
);
|
||||
vk.IC[88] = Pairing.G1Point(
|
||||
19875109758700507740317077711867102397002017483813266849042947928472067707358,
|
||||
19410883671720154448415997196283075716793971043467577411686702678513758313202
|
||||
);
|
||||
vk.IC[89] = Pairing.G1Point(
|
||||
7249713751934247391364446379816208988062392543310362185047382861082689029853,
|
||||
15650473527588496827417556647724864391410175426412916274036894124836771437372
|
||||
);
|
||||
vk.IC[90] = Pairing.G1Point(
|
||||
10681784480850187071361190982043613309470613382346001095644109815254178261562,
|
||||
21463186786189007954888872290310300639849300805770275708108444072996981167758
|
||||
);
|
||||
vk.IC[91] = Pairing.G1Point(
|
||||
2236471884703014171599710044819634924237606371553705429021763383635629939512,
|
||||
8591793843410995494533247352157879065992731222902203603345134905701260856709
|
||||
);
|
||||
vk.IC[92] = Pairing.G1Point(
|
||||
19527584213761472463971374073739673431341601035403206019474791549273088278339,
|
||||
17023146508154304148121691671727331328909786836109367376841186597185724956581
|
||||
);
|
||||
vk.IC[93] = Pairing.G1Point(
|
||||
13014073780365318482787844435657644319669081253207330065868995816477880130774,
|
||||
7445666461778273821119755595191049214876947852015119252135282618289816306885
|
||||
);
|
||||
vk.IC[94] = Pairing.G1Point(
|
||||
12572056578214122696110853014461970380570794921497586679104888016792687653897,
|
||||
4719197114816095442488216520733780832840070057650826491567278989945747530502
|
||||
);
|
||||
vk.IC[95] = Pairing.G1Point(
|
||||
16403748676169345391285149130393817667502440052483475786225216623710841245155,
|
||||
662053335174191665497628974718863306486637341349159158533932987069502165029
|
||||
);
|
||||
vk.IC[96] = Pairing.G1Point(
|
||||
17138980304892429856246490017005560669710783569541041650327401681838238378449,
|
||||
9291405839197739071712757020744264998332332192064696611245414441329433805436
|
||||
);
|
||||
vk.IC[97] = Pairing.G1Point(
|
||||
6594423345144626172531684508535057814902607027465847698107011859735578724064,
|
||||
1609167828729266896521507304269994081996148238161423140896831053169366858561
|
||||
);
|
||||
}
|
||||
|
||||
function verify(
|
||||
uint[] memory input,
|
||||
Proof memory proof
|
||||
) internal view returns (uint) {
|
||||
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
VerifyingKey memory vk = verifyingKey();
|
||||
require(input.length + 1 == vk.IC.length, "verifier-bad-input");
|
||||
// Compute the linear combination vk_x
|
||||
Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
|
||||
for (uint i = 0; i < input.length; i++) {
|
||||
require(
|
||||
input[i] < snark_scalar_field,
|
||||
"verifier-gte-snark-scalar-field"
|
||||
);
|
||||
vk_x = Pairing.addition(
|
||||
vk_x,
|
||||
Pairing.scalar_mul(vk.IC[i + 1], input[i])
|
||||
);
|
||||
}
|
||||
vk_x = Pairing.addition(vk_x, vk.IC[0]);
|
||||
if (
|
||||
!Pairing.pairingProd4(
|
||||
Pairing.negate(proof.A),
|
||||
proof.B,
|
||||
vk.alfa1,
|
||||
vk.beta2,
|
||||
vk_x,
|
||||
vk.gamma2,
|
||||
proof.C,
|
||||
vk.delta2
|
||||
)
|
||||
) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function verifyProof(
|
||||
uint[2] memory a,
|
||||
uint[2][2] memory b,
|
||||
uint[2] memory c,
|
||||
uint[97] memory input
|
||||
) public view returns (bool r) {
|
||||
Proof memory proof;
|
||||
proof.A = Pairing.G1Point(a[0], a[1]);
|
||||
proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
|
||||
proof.C = Pairing.G1Point(c[0], c[1]);
|
||||
uint[] memory inputValues = new uint[](input.length);
|
||||
for (uint i = 0; i < input.length; i++) {
|
||||
inputValues[i] = input[i];
|
||||
}
|
||||
if (verify(inputValues, proof) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
205
contracts/contracts/Verifier.sol
Normal file
205
contracts/contracts/Verifier.sol
Normal file
@@ -0,0 +1,205 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/*
|
||||
Copyright 2021 0KIMS association.
|
||||
|
||||
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
contract Groth16Verifier {
|
||||
// Scalar field size
|
||||
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
// Base field size
|
||||
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
|
||||
// Verification Key data
|
||||
uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
|
||||
uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
|
||||
uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
|
||||
uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
|
||||
uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
|
||||
uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
|
||||
uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
uint256 constant deltax1 = 10880293230004982776202427122285134624991864544958475343927602874213575641554;
|
||||
uint256 constant deltax2 = 16624665484234285310515487394475180399116885285129839531968705310830253875556;
|
||||
uint256 constant deltay1 = 3613064115835683935137165261501292410418255296432922653635183266285874098430;
|
||||
uint256 constant deltay2 = 19291133931644078725883864430591991945789379570701252372126187841104950813463;
|
||||
|
||||
|
||||
uint256 constant IC0x = 5273738681235489626795253249156042954686324696253697750333394380857132417839;
|
||||
uint256 constant IC0y = 9857192952041840089161633994514015537135554971079134835409588292482738477181;
|
||||
|
||||
uint256 constant IC1x = 13099273046850541163676426713665613850498239380428162716631655985866490422114;
|
||||
uint256 constant IC1y = 805402081419020794565351139094125407243790898682279460683021914187983510021;
|
||||
|
||||
uint256 constant IC2x = 4265450637747300781024965299586779540792520368072350700653387749302516246471;
|
||||
uint256 constant IC2y = 7463843387891834357375737290177319173209344475125750726872035788722899299932;
|
||||
|
||||
uint256 constant IC3x = 20088836232532557466758901319787909748432281529666059108643164527823125804789;
|
||||
uint256 constant IC3y = 16147539042430614121465862556890947026732365730825643639125269303010476393164;
|
||||
|
||||
uint256 constant IC4x = 24929856770016377874928422014228270742044953121105820213504610769400107305;
|
||||
uint256 constant IC4y = 19728513400524546085926773844123831498204802391551889897087063418483261808497;
|
||||
|
||||
uint256 constant IC5x = 16348551320150140412227080661010174367526100186688295471629946307478569964727;
|
||||
uint256 constant IC5y = 20290740830545611972538939670712192944691799477169965616578940279198383183813;
|
||||
|
||||
uint256 constant IC6x = 6054573107363011273023497115562598583444742570417299435209185300867053768320;
|
||||
uint256 constant IC6y = 10299856535915777925194272650832527282284880643409307207104854021775505827551;
|
||||
|
||||
|
||||
// Memory data
|
||||
uint16 constant pVk = 0;
|
||||
uint16 constant pPairing = 128;
|
||||
|
||||
uint16 constant pLastMem = 896;
|
||||
|
||||
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[6] calldata _pubSignals) public view returns (bool) {
|
||||
assembly {
|
||||
function checkField(v) {
|
||||
if iszero(lt(v, q)) {
|
||||
mstore(0, 0)
|
||||
return(0, 0x20)
|
||||
}
|
||||
}
|
||||
|
||||
// G1 function to multiply a G1 value(x,y) to value in an address
|
||||
function g1_mulAccC(pR, x, y, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, x)
|
||||
mstore(add(mIn, 32), y)
|
||||
mstore(add(mIn, 64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0, 0x20)
|
||||
}
|
||||
|
||||
mstore(add(mIn, 64), mload(pR))
|
||||
mstore(add(mIn, 96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0, 0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
|
||||
let _pPairing := add(pMem, pPairing)
|
||||
let _pVk := add(pMem, pVk)
|
||||
|
||||
mstore(_pVk, IC0x)
|
||||
mstore(add(_pVk, 32), IC0y)
|
||||
|
||||
// Compute the linear combination vk_x
|
||||
|
||||
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
|
||||
|
||||
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
|
||||
|
||||
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
|
||||
|
||||
g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
|
||||
|
||||
g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128)))
|
||||
|
||||
g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160)))
|
||||
|
||||
|
||||
// -A
|
||||
mstore(_pPairing, calldataload(pA))
|
||||
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
|
||||
|
||||
// B
|
||||
mstore(add(_pPairing, 64), calldataload(pB))
|
||||
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
|
||||
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
|
||||
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
|
||||
|
||||
// alpha1
|
||||
mstore(add(_pPairing, 192), alphax)
|
||||
mstore(add(_pPairing, 224), alphay)
|
||||
|
||||
// beta2
|
||||
mstore(add(_pPairing, 256), betax1)
|
||||
mstore(add(_pPairing, 288), betax2)
|
||||
mstore(add(_pPairing, 320), betay1)
|
||||
mstore(add(_pPairing, 352), betay2)
|
||||
|
||||
// vk_x
|
||||
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
|
||||
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
|
||||
|
||||
|
||||
// gamma2
|
||||
mstore(add(_pPairing, 448), gammax1)
|
||||
mstore(add(_pPairing, 480), gammax2)
|
||||
mstore(add(_pPairing, 512), gammay1)
|
||||
mstore(add(_pPairing, 544), gammay2)
|
||||
|
||||
// C
|
||||
mstore(add(_pPairing, 576), calldataload(pC))
|
||||
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
|
||||
|
||||
// delta2
|
||||
mstore(add(_pPairing, 640), deltax1)
|
||||
mstore(add(_pPairing, 672), deltax2)
|
||||
mstore(add(_pPairing, 704), deltay1)
|
||||
mstore(add(_pPairing, 736), deltay2)
|
||||
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
|
||||
|
||||
isOk := and(success, mload(_pPairing))
|
||||
}
|
||||
|
||||
let pMem := mload(0x40)
|
||||
mstore(0x40, add(pMem, pLastMem))
|
||||
|
||||
// Validate that all evaluations ∈ F
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 0)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 32)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 64)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 96)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 128)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 160)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 192)))
|
||||
|
||||
|
||||
// Validate all evaluations
|
||||
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
|
||||
|
||||
mstore(0, isValid)
|
||||
return(0, 0x20)
|
||||
}
|
||||
}
|
||||
}
|
||||
63
contracts/contracts/libraries/Base64.sol
Normal file
63
contracts/contracts/libraries/Base64.sol
Normal file
@@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/// @title Base64
|
||||
/// @author Brecht Devos - <brecht@loopring.org>
|
||||
/// @notice Provides a function for encoding some bytes in base64
|
||||
pragma solidity ^0.8.18;
|
||||
library Base64 {
|
||||
string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
function encode(bytes memory data) internal pure returns (string memory) {
|
||||
if (data.length == 0) return '';
|
||||
|
||||
// load the table into memory
|
||||
string memory table = TABLE;
|
||||
|
||||
// multiply by 4/3 rounded up
|
||||
uint256 encodedLen = 4 * ((data.length + 2) / 3);
|
||||
|
||||
// add some extra buffer at the end required for the writing
|
||||
string memory result = new string(encodedLen + 32);
|
||||
|
||||
assembly {
|
||||
// set the actual output length
|
||||
mstore(result, encodedLen)
|
||||
|
||||
// prepare the lookup table
|
||||
let tablePtr := add(table, 1)
|
||||
|
||||
// input ptr
|
||||
let dataPtr := data
|
||||
let endPtr := add(dataPtr, mload(data))
|
||||
|
||||
// result ptr, jump over length
|
||||
let resultPtr := add(result, 32)
|
||||
|
||||
// run over the input, 3 bytes at a time
|
||||
for {} lt(dataPtr, endPtr) {}
|
||||
{
|
||||
dataPtr := add(dataPtr, 3)
|
||||
|
||||
// read 3 bytes
|
||||
let input := mload(dataPtr)
|
||||
|
||||
// write 4 characters
|
||||
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
|
||||
resultPtr := add(resultPtr, 1)
|
||||
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
|
||||
resultPtr := add(resultPtr, 1)
|
||||
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
|
||||
resultPtr := add(resultPtr, 1)
|
||||
mstore(resultPtr, shl(248, mload(add(tablePtr, and( input, 0x3F)))))
|
||||
resultPtr := add(resultPtr, 1)
|
||||
}
|
||||
|
||||
// padding with '='
|
||||
switch mod(mload(data), 3)
|
||||
case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
|
||||
case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,9 @@ import "@nomicfoundation/hardhat-toolbox";
|
||||
require("dotenv").config();
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
solidity: "0.8.9",
|
||||
solidity: "0.8.18",
|
||||
defaultNetwork: "hardhat",
|
||||
networks: {
|
||||
hardhat: {
|
||||
chainId: process.env.HARDHAT_CHAIN_ID
|
||||
? Number(process.env.HARDHAT_CHAIN_ID)
|
||||
: 31337,
|
||||
},
|
||||
goerli: {
|
||||
url: "https://eth-goerli.public.blastapi.io",
|
||||
accounts: [process.env.PKEY as string],
|
||||
@@ -19,26 +14,6 @@ const config: HardhatUserConfig = {
|
||||
url: "https://polygon.llamarpc.com",
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
gnosis: {
|
||||
url: "https://rpc.chiado.gnosis.gateway.fm",
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
linea: {
|
||||
url: `https://linea-goerli.infura.io/v3/${process.env.INFURA_KEY}`,
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
mantle: {
|
||||
url: "https://rpc.testnet.mantle.xyz",
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
neon: {
|
||||
url: "https://devnet.neonevm.org",
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
celo: {
|
||||
url: "https://alfajores-forno.celo-testnet.org",
|
||||
accounts: [process.env.PKEY as string],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
731
contracts/package-lock.json
generated
731
contracts/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,14 @@
|
||||
"name": "hardhat-project",
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
||||
"@types/snarkjs": "^0.7.7",
|
||||
"hardhat": "^2.17.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "^4.9.2",
|
||||
"dotenv": "^16.3.1"
|
||||
"dotenv": "^16.3.1",
|
||||
"snarkjs": "^0.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
async function main() {
|
||||
const Verifier = await ethers.getContractFactory("Verifier");
|
||||
const Verifier = await ethers.getContractFactory("Groth16Verifier");
|
||||
const verifier = await Verifier.deploy();
|
||||
await verifier.waitForDeployment();
|
||||
|
||||
await verifier.deployed();
|
||||
console.log(`Verifier deployed to ${verifier.target}`);
|
||||
|
||||
console.log(`RsaSha256Verifier deployed to ${verifier.address}`);
|
||||
const ProofOfPassport = await ethers.getContractFactory("ProofOfPassport");
|
||||
const proofOfPassport = await ProofOfPassport.deploy(verifier.target);
|
||||
await proofOfPassport.waitForDeployment();
|
||||
|
||||
const ProofOfBaguette = await ethers.getContractFactory("ProofOfBaguette");
|
||||
const proofOfBaguette = await ProofOfBaguette.deploy(verifier.address);
|
||||
|
||||
await proofOfBaguette.deployed();
|
||||
|
||||
console.log(`ProofOfBaguette deployed to ${proofOfBaguette.address}`);
|
||||
console.log(`ProofOfPassport NFT deployed to ${proofOfPassport.target}`);
|
||||
}
|
||||
|
||||
// We recommend this pattern to be able to use async/await everywhere
|
||||
|
||||
93
contracts/scripts/mint.ts
Normal file
93
contracts/scripts/mint.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
||||
import { expect, assert } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
import { DataHash } from "../../common/src/utils/types";
|
||||
import { getPassportData } from "../../common/src/utils/passportData";
|
||||
import { attributeToPosition } from "../../common/src/constants/constants";
|
||||
import { formatMrz, splitToWords, formatAndConcatenateDataHashes, toUnsignedByte, hash, bytesToBigDecimal } from "../../common/src/utils/utils";
|
||||
import { groth16 } from 'snarkjs'
|
||||
const fs = require('fs');
|
||||
|
||||
async function main() {
|
||||
const proofOfPassportAddress = "0x64BfefF18335E3cac8cF8f8E37Ac921371d9c5aa"
|
||||
const proofOfPassport = await ethers.getContractAt("ProofOfPassport", proofOfPassportAddress);
|
||||
|
||||
const passportData = getPassportData();
|
||||
|
||||
const formattedMrz = formatMrz(passportData.mrz);
|
||||
const mrzHash = hash(formatMrz(passportData.mrz));
|
||||
const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
mrzHash,
|
||||
passportData.dataGroupHashes as DataHash[],
|
||||
);
|
||||
|
||||
const attributeToReveal = {
|
||||
issuing_state: true,
|
||||
name: true,
|
||||
passport_number: true,
|
||||
nationality: true,
|
||||
date_of_birth: true,
|
||||
gender: true,
|
||||
expiry_date: true,
|
||||
}
|
||||
|
||||
const bitmap = Array(88).fill('0');
|
||||
|
||||
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
|
||||
if (reveal) {
|
||||
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
|
||||
bitmap.fill('1', start, end + 1);
|
||||
}
|
||||
});
|
||||
|
||||
const inputs = {
|
||||
mrz: formattedMrz.map(byte => String(byte)),
|
||||
reveal_bitmap: bitmap.map(byte => String(byte)),
|
||||
dataHashes: concatenatedDataHashes.map(toUnsignedByte).map(byte => String(byte)),
|
||||
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
|
||||
pubkey: splitToWords(
|
||||
BigInt(passportData.pubKey.modulus as string),
|
||||
BigInt(64),
|
||||
BigInt(32)
|
||||
),
|
||||
signature: splitToWords(
|
||||
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
|
||||
BigInt(64),
|
||||
BigInt(32)
|
||||
),
|
||||
address: "0x9D392187c08fc28A86e1354aD63C70897165b982", // goerli test account
|
||||
}
|
||||
|
||||
console.log('generating proof...');
|
||||
const { proof, publicSignals } = await groth16.fullProve(
|
||||
inputs,
|
||||
"../circuits/build/proof_of_passport_js/proof_of_passport.wasm",
|
||||
"../circuits/build/proof_of_passport_final.zkey"
|
||||
)
|
||||
|
||||
console.log('proof done');
|
||||
|
||||
const vKey = JSON.parse(fs.readFileSync("../circuits/build/verification_key.json"));
|
||||
const verified = await groth16.verify(
|
||||
vKey,
|
||||
publicSignals,
|
||||
proof
|
||||
)
|
||||
|
||||
assert(verified == true, 'Should verifiable')
|
||||
|
||||
const cd = await groth16.exportSolidityCallData(proof, publicSignals);
|
||||
const callData = JSON.parse(`[${cd}]`);
|
||||
console.log('callData', callData);
|
||||
|
||||
const tx = await proofOfPassport.mint(...callData);
|
||||
|
||||
const receipt = await tx.wait();
|
||||
console.log('receipt', receipt?.hash);
|
||||
const tokenURI = await proofOfPassport.tokenURI(0);
|
||||
console.log('tokenURI', tokenURI);
|
||||
|
||||
}
|
||||
|
||||
|
||||
main()
|
||||
@@ -1,229 +0,0 @@
|
||||
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
||||
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
|
||||
import { expect } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
const exampleCorrectProof = {
|
||||
a: [
|
||||
"0x0c7141194fa7a5a26dd3834bd9490908286e3c772dcaecca314b74a58a222642",
|
||||
"0x0494611f581503a05ebd4e8fe17e9c7ec05a0c022081bbe6115a6bf8afcd8c19",
|
||||
],
|
||||
b: [
|
||||
[
|
||||
"0x01b8ab498c66a313e3320b0a65d94ab35e4be73616a56b33685415e5b312cb57",
|
||||
"0x071417e130b6f8c45cee4644adbb90ae62c542ec26fa83377b86fadfe737cddc",
|
||||
],
|
||||
[
|
||||
"0x2d991227175693d047f1e976af6986a58aa313d75677a0e70939b3ddb1912df2",
|
||||
"0x1326e7a60a10320b5477d3bbc824121d1cbf2381293a09bf82ff5418897d7706",
|
||||
],
|
||||
],
|
||||
c: [
|
||||
"0x19912bf5bfee2e72d3cc357fa6b94741ba70bb9e25ca72922cc23cef79adab68",
|
||||
"0x1dc4caae04391e8d72f288970e195f1d317476a1890977083d8db832c5a6552a",
|
||||
],
|
||||
input: [
|
||||
"0x0000000000000000000000000000000000000000000000000000000000010001",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000000000000000df267467de87516",
|
||||
"0x000000000000000000000000000000000000000000000000584863641a75504b",
|
||||
"0x000000000000000000000000000000000000000000000000595bf81a28dc3bd7",
|
||||
"0x0000000000000000000000000000000000000000000000008276a24b60f02a0b",
|
||||
"0x000000000000000000000000000000000000000000000000f394de395425db5b",
|
||||
"0x000000000000000000000000000000000000000000000000a37863419a2760b9",
|
||||
"0x0000000000000000000000000000000000000000000000002332cde4996e768d",
|
||||
"0x00000000000000000000000000000000000000000000000034042fb8b18a254d",
|
||||
"0x000000000000000000000000000000000000000000000000ad20de3a2a2c4881",
|
||||
"0x000000000000000000000000000000000000000000000000572b030ef7b362db",
|
||||
"0x000000000000000000000000000000000000000000000000128b7757b2f7b52e",
|
||||
"0x000000000000000000000000000000000000000000000000c59817a889d2eee4",
|
||||
"0x000000000000000000000000000000000000000000000000a6536f0357bb6a04",
|
||||
"0x00000000000000000000000000000000000000000000000031c38d88190cb650",
|
||||
"0x000000000000000000000000000000000000000000000000e06a5416c45a9abc",
|
||||
"0x000000000000000000000000000000000000000000000000ec78fad95ccef0cb",
|
||||
"0x00000000000000000000000000000000000000000000000006c08a020dadcb14",
|
||||
"0x000000000000000000000000000000000000000000000000463dd85433924204",
|
||||
"0x000000000000000000000000000000000000000000000000ad2dadc6dea40729",
|
||||
"0x000000000000000000000000000000000000000000000000671e4175104c69c8",
|
||||
"0x0000000000000000000000000000000000000000000000000a5b8d4c2d09d069",
|
||||
"0x000000000000000000000000000000000000000000000000456c4a0208587c36",
|
||||
"0x000000000000000000000000000000000000000000000000338e93e219412835",
|
||||
"0x00000000000000000000000000000000000000000000000098cd81aa3d338a4e",
|
||||
"0x00000000000000000000000000000000000000000000000015e468738c5d802c",
|
||||
"0x000000000000000000000000000000000000000000000000bd84a973c66e6c07",
|
||||
"0x000000000000000000000000000000000000000000000000366076382e2a9543",
|
||||
"0x0000000000000000000000000000000000000000000000004d6bfec592ef1293",
|
||||
"0x0000000000000000000000000000000000000000000000002f6b635940e079b0",
|
||||
"0x000000000000000000000000000000000000000000000000dbaeda10ef7c7eea",
|
||||
"0x000000000000000000000000000000000000000000000000f26255cb75fe2de2",
|
||||
"0x0000000000000000000000000000000000000000000000005a78c5d241463136",
|
||||
"0x0000000000000000000000000000000000000000000000008464dcde99f9a9a1",
|
||||
"0x00000000000000000000000000000000000000000000000016ef65b0eb49c697",
|
||||
"0x0000000000000000000000000000000000000000000000006ba33075968396c2",
|
||||
"0x000000000000000000000000000000000000000000000000d08f6baf1487b58f",
|
||||
"0x000000000000000000000000000000000000000000000000baad9f5ed4b6886c",
|
||||
"0x000000000000000000000000000000000000000000000000a2566cbdc9aa0e3c",
|
||||
"0x000000000000000000000000000000000000000000000000ca7a946dd7ac86de",
|
||||
"0x00000000000000000000000000000000000000000000000010451eff67ed87f6",
|
||||
"0x00000000000000000000000000000000000000000000000058ac64a2c6e26bf0",
|
||||
"0x0000000000000000000000000000000000000000000000005debfc3fb15ef7b4",
|
||||
"0x0000000000000000000000000000000000000000000000009d7b54d9509b03f9",
|
||||
"0x00000000000000000000000000000000000000000000000023fc9c3e6cd4902e",
|
||||
"0x000000000000000000000000000000000000000000000000ff26d5c66d231641",
|
||||
"0x000000000000000000000000000000000000000000000000cf9d58eeff43ce2c",
|
||||
"0x00000000000000000000000000000000000000000000000078d4d439d2d659b0",
|
||||
"0x000000000000000000000000000000000000000000000000d2817dd436d5aef7",
|
||||
"0x00000000000000000000000000000000000000000000000078dc49129d55531b",
|
||||
"0x000000000000000000000000000000000000000000000000f9e2cc1e9ca4f476",
|
||||
"0x00000000000000000000000000000000000000000000000058cb0085fa356b13",
|
||||
"0x000000000000000000000000000000000000000000000000d02d9fabcd899520",
|
||||
"0x000000000000000000000000000000000000000000000000f54a26c2ca3493f1",
|
||||
"0x00000000000000000000000000000000000000000000000027cd08da32ce263e",
|
||||
"0x00000000000000000000000000000000000000000000000080e4cdb79e0cdf46",
|
||||
"0x000000000000000000000000000000000000000000000000882f2281537ac7aa",
|
||||
"0x000000000000000000000000000000000000000000000000bb456e5f8ce32148",
|
||||
"0x0000000000000000000000000000000000000000000000006c25614d99232b98",
|
||||
"0x0000000000000000000000000000000000000000000000005af2acb5f5c2bedf",
|
||||
"0x0000000000000000000000000000000000000000000000000072a3c7868f8504",
|
||||
"0x000000000000000000000000000000000000000000000000da6834a23075f203",
|
||||
"0x000000000000000000000000000000000000000000000000094a9b9ecf98e97e",
|
||||
"0x0000000000000000000000000000000000000000000000009e8ce7916ab0fb0b",
|
||||
"0x000000000000000000000000000000000000000000000000df11ba06d7937a05",
|
||||
"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8",
|
||||
],
|
||||
};
|
||||
|
||||
describe("ProofOfBaguette", function () {
|
||||
// We define a fixture to reuse the same setup in every test.
|
||||
// We use loadFixture to run this setup once, snapshot that state,
|
||||
// and reset Hardhat Network to that snapshot in every test.
|
||||
async function deployFixture() {
|
||||
// Contracts are deployed using the first signer/account by default
|
||||
const [owner, otherAccount] = await ethers.getSigners();
|
||||
|
||||
const Verifier = await ethers.getContractFactory("Verifier");
|
||||
const verifier = await Verifier.deploy();
|
||||
|
||||
console.log("otherAccount", otherAccount.address);
|
||||
console.log("owner", owner.address);
|
||||
await verifier.deployed();
|
||||
|
||||
console.log(`RsaSha256Verifier deployed to ${verifier.address}`);
|
||||
|
||||
const ProofOfBaguette = await ethers.getContractFactory("ProofOfBaguette");
|
||||
const proofOfBaguette = await ProofOfBaguette.deploy(verifier.address);
|
||||
|
||||
await proofOfBaguette.deployed();
|
||||
|
||||
console.log(`ProofOfBaguette deployed to ${proofOfBaguette.address}`);
|
||||
return { verifier, proofOfBaguette, owner, otherAccount };
|
||||
}
|
||||
|
||||
describe("Deployment", function () {
|
||||
it("Verifier verifies correct example signature", async () => {
|
||||
const { verifier } = await loadFixture(deployFixture);
|
||||
|
||||
expect(
|
||||
await verifier.verifyProof(
|
||||
exampleCorrectProof.a as any,
|
||||
exampleCorrectProof.b as any,
|
||||
exampleCorrectProof.c as any,
|
||||
exampleCorrectProof.input
|
||||
)
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
it("Should allow a user to mint a SBT", async function () {
|
||||
const { proofOfBaguette, otherAccount } = await loadFixture(
|
||||
deployFixture
|
||||
);
|
||||
|
||||
await proofOfBaguette
|
||||
.connect(otherAccount)
|
||||
.mint(
|
||||
exampleCorrectProof.a as any,
|
||||
exampleCorrectProof.b as any,
|
||||
exampleCorrectProof.c as any,
|
||||
exampleCorrectProof.input
|
||||
);
|
||||
|
||||
expect(await proofOfBaguette.balanceOf(otherAccount.address)).to.equal(1);
|
||||
});
|
||||
|
||||
it("Shouldn't allow an invalid proof", async function () {
|
||||
const { proofOfBaguette, otherAccount } = await loadFixture(
|
||||
deployFixture
|
||||
);
|
||||
|
||||
let invalidA = exampleCorrectProof.a;
|
||||
invalidA[1] =
|
||||
"0x1cdbaf59a0439d55f19162ee0be5a501f5b55c669a6e1f8d27b75d95ff31ff7b";
|
||||
|
||||
expect(
|
||||
proofOfBaguette
|
||||
.connect(otherAccount)
|
||||
.mint(
|
||||
invalidA as any,
|
||||
exampleCorrectProof.b as any,
|
||||
exampleCorrectProof.c as any,
|
||||
exampleCorrectProof.input
|
||||
)
|
||||
).to.be.revertedWith("Invalid proof");
|
||||
});
|
||||
|
||||
// it("Should set the right owner", async function () {
|
||||
// const { lock, owner } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
// expect(await lock.owner()).to.equal(owner.address);
|
||||
// });
|
||||
|
||||
// it("Should receive and store the funds to lock", async function () {
|
||||
// const { lock, lockedAmount } = await loadFixture(
|
||||
// deployOneYearLockFixture
|
||||
// );
|
||||
|
||||
// expect(await ethers.provider.getBalance(lock.address)).to.equal(
|
||||
// lockedAmount
|
||||
// );
|
||||
// });
|
||||
|
||||
// it("Should fail if the unlockTime is not in the future", async function () {
|
||||
// // We don't use the fixture here because we want a different deployment
|
||||
// const latestTime = await time.latest();
|
||||
// const Lock = await ethers.getContractFactory("Lock");
|
||||
// await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
|
||||
// "Unlock time should be in the future"
|
||||
// );
|
||||
// });
|
||||
});
|
||||
});
|
||||
157
contracts/test/ProofOfPassport.ts
Normal file
157
contracts/test/ProofOfPassport.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
||||
import { expect, assert } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
import { DataHash } from "../../common/src/utils/types";
|
||||
import { getPassportData } from "../../common/src/utils/passportData";
|
||||
import { attributeToPosition } from "../../common/src/constants/constants";
|
||||
import { formatMrz, splitToWords, formatAndConcatenateDataHashes, toUnsignedByte, hash, bytesToBigDecimal } from "../../common/src/utils/utils";
|
||||
import { groth16 } from 'snarkjs'
|
||||
const fs = require('fs');
|
||||
|
||||
describe("ProofOfPassport", function () {
|
||||
this.timeout(0);
|
||||
|
||||
async function deployFixture() {
|
||||
const [owner, otherAccount] = await ethers.getSigners();
|
||||
|
||||
const Verifier = await ethers.getContractFactory("Groth16Verifier");
|
||||
const verifier = await Verifier.deploy();
|
||||
await verifier.waitForDeployment();
|
||||
|
||||
console.log(`Verifier deployed to ${verifier.target}`);
|
||||
|
||||
const ProofOfPassport = await ethers.getContractFactory("ProofOfPassport");
|
||||
const proofOfPassport = await ProofOfPassport.deploy(verifier.target);
|
||||
await proofOfPassport.waitForDeployment();
|
||||
|
||||
console.log(`ProofOfPassport NFT deployed to ${proofOfPassport.target}`);
|
||||
|
||||
const passportData = getPassportData();
|
||||
|
||||
const formattedMrz = formatMrz(passportData.mrz);
|
||||
const mrzHash = hash(formatMrz(passportData.mrz));
|
||||
const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
mrzHash,
|
||||
passportData.dataGroupHashes as DataHash[],
|
||||
);
|
||||
|
||||
const attributeToReveal = {
|
||||
issuing_state: true,
|
||||
name: true,
|
||||
passport_number: true,
|
||||
nationality: true,
|
||||
date_of_birth: true,
|
||||
gender: true,
|
||||
expiry_date: true,
|
||||
}
|
||||
|
||||
const bitmap = Array(88).fill('0');
|
||||
|
||||
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
|
||||
if (reveal) {
|
||||
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
|
||||
bitmap.fill('1', start, end + 1);
|
||||
}
|
||||
});
|
||||
|
||||
const inputs = {
|
||||
mrz: formattedMrz.map(byte => String(byte)),
|
||||
reveal_bitmap: bitmap.map(byte => String(byte)),
|
||||
dataHashes: concatenatedDataHashes.map(toUnsignedByte).map(byte => String(byte)),
|
||||
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
|
||||
pubkey: splitToWords(
|
||||
BigInt(passportData.pubKey.modulus as string),
|
||||
BigInt(64),
|
||||
BigInt(32)
|
||||
),
|
||||
signature: splitToWords(
|
||||
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
|
||||
BigInt(64),
|
||||
BigInt(32)
|
||||
),
|
||||
address: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // hardhat account 1
|
||||
}
|
||||
|
||||
console.log('generating proof...');
|
||||
const { proof, publicSignals } = await groth16.fullProve(
|
||||
inputs,
|
||||
"../circuits/build/proof_of_passport_js/proof_of_passport.wasm",
|
||||
"../circuits/build/proof_of_passport_final.zkey"
|
||||
)
|
||||
|
||||
console.log('proof done');
|
||||
|
||||
const revealChars = publicSignals.slice(0, 88).map((byte: string) => String.fromCharCode(parseInt(byte, 10))).join('');
|
||||
// console.log('reveal chars', revealChars);
|
||||
|
||||
const vKey = JSON.parse(fs.readFileSync("../circuits/build/verification_key.json"));
|
||||
const verified = await groth16.verify(
|
||||
vKey,
|
||||
publicSignals,
|
||||
proof
|
||||
)
|
||||
|
||||
assert(verified == true, 'Should verifiable')
|
||||
|
||||
const cd = await groth16.exportSolidityCallData(proof, publicSignals);
|
||||
const callData = JSON.parse(`[${cd}]`);
|
||||
console.log('callData', callData);
|
||||
|
||||
return { verifier, proofOfPassport, owner, otherAccount, passportData, inputs, proof, publicSignals, revealChars, callData };
|
||||
}
|
||||
|
||||
describe("Deployment", function () {
|
||||
it("Verifier verifies a correct proof", async () => {
|
||||
const { verifier, callData } = await loadFixture(deployFixture);
|
||||
|
||||
expect(
|
||||
await verifier.verifyProof(...callData)
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
it("Should allow a user to mint a SBT", async function () {
|
||||
const { proofOfPassport, otherAccount, callData } = await loadFixture(
|
||||
deployFixture
|
||||
);
|
||||
|
||||
await proofOfPassport
|
||||
.connect(otherAccount)
|
||||
.mint(...callData);
|
||||
|
||||
expect(await proofOfPassport.balanceOf(otherAccount.address)).to.equal(1);
|
||||
});
|
||||
|
||||
it("Shouldn't allow minting with an invalid proof", async function () {
|
||||
const { proofOfPassport, otherAccount, callData } = await loadFixture(
|
||||
deployFixture
|
||||
);
|
||||
|
||||
callData[0][1] = "0x1cdbaf59a0439d55f19162ee0be5a501f5b55c669a6e1f8d27b75d95ff31ff7b";
|
||||
|
||||
expect(
|
||||
proofOfPassport
|
||||
.connect(otherAccount)
|
||||
.mint(...callData)
|
||||
).to.be.revertedWith("Invalid proof");
|
||||
});
|
||||
|
||||
it.only("Should have a correct tokenURI a user to mint a SBT", async function () {
|
||||
const { proofOfPassport, otherAccount, callData } = await loadFixture(
|
||||
deployFixture
|
||||
);
|
||||
|
||||
const tx = await proofOfPassport
|
||||
.connect(otherAccount)
|
||||
.mint(...callData);
|
||||
|
||||
const receipt = await tx.wait();
|
||||
|
||||
const tokenURI = await proofOfPassport.tokenURI(0);
|
||||
|
||||
console.log('tokenURI', tokenURI);
|
||||
|
||||
// expect(await proofOfPassport.balanceOf(otherAccount.address)).to.equal(1);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
4972
contracts/yarn.lock
4972
contracts/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user