Merge pull request #32 from zk-passport/contracts

add contracts
This commit is contained in:
turboblitz
2023-12-26 17:32:04 +01:00
committed by GitHub
14 changed files with 1364 additions and 6129 deletions

View File

@@ -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();
}
}
}

View File

@@ -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");
}
}

View 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()
)
);
}
}

View File

@@ -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;
}
}
}

View 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)
}
}
}

View 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;
}
}

View File

@@ -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],
},
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -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"
}
}

View File

@@ -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
View 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()

View File

@@ -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"
// );
// });
});
});

View 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);
});
});
});

File diff suppressed because it is too large Load Diff