From 6e8d134a705e3385e2de0527043c67c55074ee7c Mon Sep 17 00:00:00 2001 From: motemotech Date: Tue, 8 Oct 2024 20:04:13 +0900 Subject: [PATCH 1/6] add test for mint validations --- common/src/constants/contractConstants.ts | 24 ++ .../src/utils/unitTest/generateMockProof.ts | 111 +++++++ contracts/contracts/OneTimeSBT.sol | 6 +- contracts/contracts/constants/constants.sol | 3 + .../disclose/Verifier_vc_and_disclose.sol | 275 ++++++++++++++++++ contracts/test/OneTimeSBT.ts | 169 ++++++++++- 6 files changed, 583 insertions(+), 5 deletions(-) create mode 100644 common/src/constants/contractConstants.ts create mode 100644 common/src/utils/unitTest/generateMockProof.ts create mode 100644 contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose.sol diff --git a/common/src/constants/contractConstants.ts b/common/src/constants/contractConstants.ts new file mode 100644 index 00000000..6ebe4f6c --- /dev/null +++ b/common/src/constants/contractConstants.ts @@ -0,0 +1,24 @@ +// Constant Values in OneTimeSBT.sol +export const ATTRIBUTE_ISSUING_STATE_INDEX = 0; +export const ATTRIBUTE_NAME_INDEX = 1; +export const ATTRIBUTE_PASSPORT_NUMBER_INDEX = 2; +export const ATTRIBUTE_NATIONALITY_INDEX = 3; +export const ATTRIBUTE_DATE_OF_BIRTH_INDEX = 4; +export const ATTRIBUTE_GENDER_INDEX = 5; +export const ATTRIBUTE_EXPIRY_DATE_INDEX = 6; +export const ATTRIBUTE_OLDER_THAN_INDEX = 7; + +export const PROVE_RSA_NULLIFIER_INDEX = 0; +export const PROVE_RSA_REVEALED_DATA_PACKED_INDEX = 1; +export const PROVE_RSA_OLDER_THAN_INDEX = 4; +export const PROVE_RSA_PUBKEY_DISCLOSED_INDEX = 6; +export const PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX = 38; +export const PROVE_RSA_OFAC_RESULT_INDEX = 40; +export const PROVE_RSA_COMMITMENT_INDEX = 41; +export const PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX = 42; +export const PROVE_RSA_CURRENT_DATE_INDEX = 43; +export const PROVE_RSA_USER_IDENTIFIER_INDEX = 49; +export const PROVE_RSA_SCOPE_INDEX = 50; + +export const DSC_BLINDED_DSC_COMMITMENT_INDEX = 0; + diff --git a/common/src/utils/unitTest/generateMockProof.ts b/common/src/utils/unitTest/generateMockProof.ts new file mode 100644 index 00000000..2a8ce7c6 --- /dev/null +++ b/common/src/utils/unitTest/generateMockProof.ts @@ -0,0 +1,111 @@ +import { + PROVE_RSA_NULLIFIER_INDEX, + PROVE_RSA_REVEALED_DATA_PACKED_INDEX, + PROVE_RSA_OLDER_THAN_INDEX, + PROVE_RSA_PUBKEY_DISCLOSED_INDEX, + PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX, + PROVE_RSA_OFAC_RESULT_INDEX, + PROVE_RSA_COMMITMENT_INDEX, + PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX, + PROVE_RSA_CURRENT_DATE_INDEX, + PROVE_RSA_USER_IDENTIFIER_INDEX, + PROVE_RSA_SCOPE_INDEX, + DSC_BLINDED_DSC_COMMITMENT_INDEX +} from "../../constants/contractConstants"; +import { Proof } from "../types"; + +export function generateMockRSAProveVerifierInputs({ + nullifier = "1", + revealedData_packed = ["2", "3", "4"], + older_than = ["5", "6", "7"], + pubkey_disclosed = ["0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0"], + forbidden_contries_list_packed_disclose = ["8", "9"], + ofac_result = "10", + commitment = "11", + blinded_dsc_commitment = "12", + current_date = new Date(), + user_identifier = "13", + scope = "14", +}: { + nullifier?: string, + revealedData_packed?: string[], + older_than?: string[], + pubkey_disclosed?: string[], + forbidden_contries_list_packed_disclose?: string[], + ofac_result?: string, + commitment?: string, + blinded_dsc_commitment?: string, + current_date?: Date, + user_identifier?: string, + scope?: string, +}): Proof { + + let pub_signals: string[] = []; + + pub_signals[PROVE_RSA_NULLIFIER_INDEX] = nullifier; + pub_signals.splice(PROVE_RSA_REVEALED_DATA_PACKED_INDEX, 0, ...revealedData_packed); + pub_signals.splice(PROVE_RSA_OLDER_THAN_INDEX, 0, ...older_than); + pub_signals.splice(PROVE_RSA_PUBKEY_DISCLOSED_INDEX, 0, ...pubkey_disclosed); + pub_signals.splice(PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX, 0, ...forbidden_contries_list_packed_disclose); + pub_signals[PROVE_RSA_OFAC_RESULT_INDEX] = ofac_result; + pub_signals[PROVE_RSA_COMMITMENT_INDEX] = commitment; + pub_signals[PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX] = blinded_dsc_commitment; + pub_signals.splice(PROVE_RSA_CURRENT_DATE_INDEX, 0, ...getDateNum(current_date)); + pub_signals[PROVE_RSA_USER_IDENTIFIER_INDEX] = user_identifier; + pub_signals[PROVE_RSA_SCOPE_INDEX] = scope; + + let proof: Proof = { + proof: { + a: ["1", "1"], + b: [ + ["1", "2"], + ["3", "4"] + ], + c: ["5", "6"] + }, + pub_signals: pub_signals + }; + return proof; +} + +export function generateMockDSCVerifierInputs({ + blinded_dsc_commitment = "12", +}: { + blinded_dsc_commitment?: string, +}): Proof { + + let pub_signals: string[] = []; + + pub_signals[DSC_BLINDED_DSC_COMMITMENT_INDEX] = blinded_dsc_commitment; + + let proof: Proof = { + proof: { + a: ["1", "1"], + b: [ + ["1", "2"], + ["3", "4"] + ], + c: ["5", "6"] + }, + pub_signals: pub_signals + }; + return proof; +} + +function getDateNum(date: Date = new Date()): string[] { + + const year = date.getUTCFullYear() % 100; + const month = date.getUTCMonth() + 1; + const day = date.getUTCDate(); + + const dateNum = [ + Math.floor(year / 10), + (year % 10), + (Math.floor(month / 10)), + (month % 10), + (Math.floor(day / 10)), + (day % 10), + ]; + + return dateNum.map(num => num.toString()); +} \ No newline at end of file diff --git a/contracts/contracts/OneTimeSBT.sol b/contracts/contracts/OneTimeSBT.sol index 9b30a03f..e963aa1e 100644 --- a/contracts/contracts/OneTimeSBT.sol +++ b/contracts/contracts/OneTimeSBT.sol @@ -49,7 +49,7 @@ contract OneTimeSBT is ERC721Enumerable { // Convert the last four parameters into a valid timestamp, adding 30 years to adjust for block.timestamp starting in 1970 uint[6] memory dateNum; for (uint i = 0; i < 6; i++) { - dateNum[i] = p_proof.pubSignals[PROVE_RSA_COMMITMENT_INDEX + i]; + dateNum[i] = p_proof.pubSignals[PROVE_RSA_CURRENT_DATE_INDEX + i]; } uint currentTimestamp = getCurrentTimestamp(dateNum); @@ -58,8 +58,8 @@ contract OneTimeSBT is ERC721Enumerable { currentTimestamp < block.timestamp - 1 days || currentTimestamp > block.timestamp + 1 days ) { - revert CURRENT_DATE_NOT_VALID_RANGE(); - }; + revert CURRENT_DATE_NOT_IN_VALID_RANGE(); + } // check blinded dcs if ( diff --git a/contracts/contracts/constants/constants.sol b/contracts/contracts/constants/constants.sol index 915c802b..37536a3f 100644 --- a/contracts/contracts/constants/constants.sol +++ b/contracts/contracts/constants/constants.sol @@ -1,3 +1,6 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + uint256 constant ATTRIBUTE_ISSUING_STATE_INDEX = 0; uint256 constant ATTRIBUTE_NAME_INDEX = 1; uint256 constant ATTRIBUTE_PASSPORT_NUMBER_INDEX = 2; diff --git a/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose.sol b/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose.sol new file mode 100644 index 00000000..9ecd949a --- /dev/null +++ b/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose.sol @@ -0,0 +1,275 @@ +// 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 . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Verifier_vc_and_disclose { + // 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 = 8833738114523234241961700168582556351409665088656289578650332355092209409951; + uint256 constant deltax2 = 21572497176558552913060104078169917781107727215916375009020976658111372366491; + uint256 constant deltay1 = 6915235424525365983086165056103755851794061837058687036785171368091389574248; + uint256 constant deltay2 = 16423017652108143072325527846900236321120905316510160884497910357335074865104; + + + uint256 constant IC0x = 11699064754201195007398527350253348403151481002046977275974914515794556464907; + uint256 constant IC0y = 8377098824516723042209547366307545575336194904666442740719435968971891137137; + + uint256 constant IC1x = 15022578671217433728263017879847504938124709144805899886585104521700250021138; + uint256 constant IC1y = 7439374227934829324841183186890967124081563506556263992139697902117577630383; + + uint256 constant IC2x = 8719884923846896418670370483026242120279461454392494350543596555692392150751; + uint256 constant IC2y = 1915572466121040401254047597591235959434056701873531529685278614032487740057; + + uint256 constant IC3x = 15854458635547661044046209019901121787893952481692645870771021335496255904066; + uint256 constant IC3y = 18580362195513971727529458597180322208793324937796157274539580854125510824273; + + uint256 constant IC4x = 20197620246128797797969231334172536167724314393789981313273934960930874757904; + uint256 constant IC4y = 8652383402530547452977109949475477447090780660216084329098279248059527858257; + + uint256 constant IC5x = 6136418035854024647800871603208064108329169082713292338157990550507679741373; + uint256 constant IC5y = 4148249731111469783390189175626927778451683234448732196893033887074109584641; + + uint256 constant IC6x = 435016271093619026896979316149581362925836421109084185028857731123245432006; + uint256 constant IC6y = 21254951437721821548232352310541329777023953579777485090776415227787346519751; + + uint256 constant IC7x = 21278075374621156162040667851377496500311461883308769905293308585207243513686; + uint256 constant IC7y = 12203663506086881329872300647846774063295289884666082497820328056490027198813; + + uint256 constant IC8x = 16308483425091511705934563714250777026234740651509189582674872217820098595375; + uint256 constant IC8y = 7831547100064998764922162707495490598633878334974466872347123357740110689244; + + uint256 constant IC9x = 3291127262603144718778205947439511714981876162713868160237600958297179548397; + uint256 constant IC9y = 21485037857784329908791414402133986495597755287969373075934534732305491839766; + + uint256 constant IC10x = 21016409257036220162904188391746628812174550025367627914783879782321883872463; + uint256 constant IC10y = 771625434822550883448227440257963423499310868732489728802518320854402128338; + + uint256 constant IC11x = 848677157837511141352835832315266404476623536713045891337491496271705963639; + uint256 constant IC11y = 8217347855861380271136078798483880852994161288399697316508954130226938484979; + + uint256 constant IC12x = 7950645217739479484822823131266057021165813197226380213090258700020405406040; + uint256 constant IC12y = 21115671325929956654785783064024579377805406512650003241388844210050677251719; + + uint256 constant IC13x = 3626770947109436638554139078198740121299601968895373800820851494276106181151; + uint256 constant IC13y = 1231434625641659068142386110297841563481701042171599336083256459050627128218; + + uint256 constant IC14x = 16049947947771356656284191511201202183176568879064579206986716057573639688339; + uint256 constant IC14y = 6480470373974113105161133752760352489238403926514542525269014451361964382448; + + uint256 constant IC15x = 16974167980812170374822233712683695773735295177444364620936821746333456881288; + uint256 constant IC15y = 8122261017527118496247636440450416615732682768376367625137811781672190179076; + + uint256 constant IC16x = 4370481621955946039258820475154973643976715870021068098944543782894438093187; + uint256 constant IC16y = 9625487063950556055947770382866627694768814221480630062831377989311939157072; + + + // 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[16] 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))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + + // -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))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/contracts/test/OneTimeSBT.ts b/contracts/test/OneTimeSBT.ts index 31d7d545..0dc3f2f1 100644 --- a/contracts/test/OneTimeSBT.ts +++ b/contracts/test/OneTimeSBT.ts @@ -6,10 +6,17 @@ import { generateCircuitInputsProve, generateCircuitInputsDisclose } from "../../common/src/utils/generateInputs"; +import { + generateMockRSAProveVerifierInputs, + generateMockDSCVerifierInputs +} from "../../common/src/utils/unitTest/generateMockProof"; import { getCSCAModulusMerkleTree } from "../../common/src/utils/csca"; import { formatRoot } from "../../common/src/utils/utils"; import { IMT } from "../../common/node_modules/@zk-kit/imt"; +const TRUE_VERIFIER_ID = 0; +const FALSE_VERIFIER_ID = 1; + describe("Unit test for OneTimeSBT.sol", function() { let verifiersManager: any; @@ -44,6 +51,166 @@ describe("Unit test for OneTimeSBT.sol", function() { describe("Test mint function", async function () { + it("Should revert if current time is +2 dyas", async function() { + let twoDaysPassed = new Date(); + twoDaysPassed.setDate(twoDaysPassed.getDate() + 2); + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + current_date: twoDaysPassed + }); + let p_proof = { + a: mockRSAProveVerifierProof.proof.a, + b: mockRSAProveVerifierProof.proof.b, + c: mockRSAProveVerifierProof.proof.c, + pubSignals: mockRSAProveVerifierProof.pub_signals + } + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = { + a: mockDscVerifierProof.proof.a, + b: mockDscVerifierProof.proof.b, + c: mockDscVerifierProof.proof.c, + pubSignals: mockDscVerifierProof.pub_signals + } + + await expect( + oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "CURRENT_DATE_NOT_IN_VALID_RANGE" + ); + }); + it("Should revert if current time is -2 dyas", async function() { + let twoDaysBefore = new Date(); + twoDaysBefore.setDate(twoDaysBefore.getDate() - 2); + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + current_date: twoDaysBefore + }); + let p_proof = { + a: mockRSAProveVerifierProof.proof.a, + b: mockRSAProveVerifierProof.proof.b, + c: mockRSAProveVerifierProof.proof.c, + pubSignals: mockRSAProveVerifierProof.pub_signals + } + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = { + a: mockDscVerifierProof.proof.a, + b: mockDscVerifierProof.proof.b, + c: mockDscVerifierProof.proof.c, + pubSignals: mockDscVerifierProof.pub_signals + } + + await expect( + oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "CURRENT_DATE_NOT_IN_VALID_RANGE" + ); + }); + + it("Should revert if Blinded_dsc_commitment is not equal", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + blinded_dsc_commitment: "42" + }); + let p_proof = { + a: mockRSAProveVerifierProof.proof.a, + b: mockRSAProveVerifierProof.proof.b, + c: mockRSAProveVerifierProof.proof.c, + pubSignals: mockRSAProveVerifierProof.pub_signals + } + + let mockDscVerifierProof = generateMockDSCVerifierInputs({ + blinded_dsc_commitment: "43" + }); + let d_proof = { + a: mockDscVerifierProof.proof.a, + b: mockDscVerifierProof.proof.b, + c: mockDscVerifierProof.proof.c, + pubSignals: mockDscVerifierProof.pub_signals + } + + await expect( + oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "UNEQUAL_BLINDED_DSC_COMMITMENT" + ); + }); + + it("Should revert if prove verifier returns false", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); + let p_proof = { + a: mockRSAProveVerifierProof.proof.a, + b: mockRSAProveVerifierProof.proof.b, + c: mockRSAProveVerifierProof.proof.c, + pubSignals: mockRSAProveVerifierProof.pub_signals + } + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = { + a: mockDscVerifierProof.proof.a, + b: mockDscVerifierProof.proof.b, + c: mockDscVerifierProof.proof.c, + pubSignals: mockDscVerifierProof.pub_signals + } + + await expect( + oneTimeSBT.mint( + FALSE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "INVALID_PROVE_PROOF" + ); + }); + + it("Should revert if dsc veriifier returns false", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); + let p_proof = { + a: mockRSAProveVerifierProof.proof.a, + b: mockRSAProveVerifierProof.proof.b, + c: mockRSAProveVerifierProof.proof.c, + pubSignals: mockRSAProveVerifierProof.pub_signals + } + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = { + a: mockDscVerifierProof.proof.a, + b: mockDscVerifierProof.proof.b, + c: mockDscVerifierProof.proof.c, + pubSignals: mockDscVerifierProof.pub_signals + } + + await expect( + oneTimeSBT.mint( + TRUE_VERIFIER_ID, + FALSE_VERIFIER_ID, + p_proof, + d_proof + ) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "INVALID_DSC_PROOF" + ); + }); }); describe("Test util functions", async function () { @@ -56,8 +223,6 @@ describe("Unit test for OneTimeSBT.sol", function() { }); - describe("") - }); describe("Test attrs are correctly registerd", async function () { From ca2d7bcfabc51413204a113000834bc8a03bd3ed Mon Sep 17 00:00:00 2001 From: motemotech Date: Tue, 8 Oct 2024 21:22:17 +0900 Subject: [PATCH 2/6] add test when you successfuly mint sbt --- contracts/contracts/OneTimeSBT.sol | 15 +- .../contracts/libraries/AttributeLibrary.sol | 9 -- contracts/test/OneTimeSBT.ts | 140 ++++++++++-------- 3 files changed, 91 insertions(+), 73 deletions(-) diff --git a/contracts/contracts/OneTimeSBT.sol b/contracts/contracts/OneTimeSBT.sol index e963aa1e..564d5963 100644 --- a/contracts/contracts/OneTimeSBT.sol +++ b/contracts/contracts/OneTimeSBT.sol @@ -100,10 +100,23 @@ contract OneTimeSBT is ERC721Enumerable { attributes.values[4] = AttributeLibrary.getDateOfBirth(charcodes); attributes.values[5] = AttributeLibrary.getGender(charcodes); attributes.values[6] = AttributeLibrary.getExpiryDate(charcodes); - attributes.values[7] = AttributeLibrary.getOlderThan(charcodes); + + uint[] memory olderThanAscii = new uint[](2); + olderThanAscii[0] = p_proof.pubSignals[PROVE_RSA_OLDER_THAN_INDEX]; + olderThanAscii[1] = p_proof.pubSignals[PROVE_RSA_OLDER_THAN_INDEX + 1]; + attributes.values[7] = convertUintArrayToString(olderThanAscii); sbtExpiration[newTokenId] = block.timestamp + 90 days; } + + function convertUintArrayToString(uint[] memory input) internal pure returns (string memory) { + bytes memory bytesArray = new bytes(input.length); + for (uint i = 0; i < input.length; i++) { + // 確実に uint8 に収まるようにキャスト + bytesArray[i] = bytes1(uint8(input[i])); + } + return string(bytesArray); + } function fieldElementsToBytes( uint256[3] memory publicSignals diff --git a/contracts/contracts/libraries/AttributeLibrary.sol b/contracts/contracts/libraries/AttributeLibrary.sol index 11233781..f3b3c628 100644 --- a/contracts/contracts/libraries/AttributeLibrary.sol +++ b/contracts/contracts/libraries/AttributeLibrary.sol @@ -93,15 +93,6 @@ library AttributeLibrary { return extractAttribute(charcodes, EXPIRY_DATE_START, EXPIRY_DATE_END); } - /** - * @notice Extracts the "older than" attribute from the charcodes. - * @param charcodes The bytes array containing packed attribute data. - * @return The "older than" value as a string. - */ - function getOlderThan(bytes memory charcodes) internal pure returns (string memory) { - return extractAttribute(charcodes, OLDER_THAN_START, OLDER_THAN_END); - } - /** * @notice Extracts a substring from the charcodes based on start and end indices. * @param charcodes The bytes array containing packed attribute data. diff --git a/contracts/test/OneTimeSBT.ts b/contracts/test/OneTimeSBT.ts index 0dc3f2f1..e327e8d6 100644 --- a/contracts/test/OneTimeSBT.ts +++ b/contracts/test/OneTimeSBT.ts @@ -4,11 +4,12 @@ import { BigNumberish, Block, dataLength } from "ethers"; import { genMockPassportData } from "../../common/src/utils/genMockPassportData"; import { generateCircuitInputsProve, - generateCircuitInputsDisclose + generateCircuitInputsDisclose, } from "../../common/src/utils/generateInputs"; import { generateMockRSAProveVerifierInputs, - generateMockDSCVerifierInputs + generateMockDSCVerifierInputs, + convertProofTypeIntoInput } from "../../common/src/utils/unitTest/generateMockProof"; import { getCSCAModulusMerkleTree } from "../../common/src/utils/csca"; import { formatRoot } from "../../common/src/utils/utils"; @@ -49,6 +50,22 @@ describe("Unit test for OneTimeSBT.sol", function() { console.log('\x1b[34m%s\x1b[0m', `sbt deployed to ${oneTimeSBT.target}`); }); + + async function initializeOneTimeSBT() { + console.log('\x1b[34m%s\x1b[0m', `Initializing OneTimeSBT contract`); + const sbtFactory = await ethers.getContractFactory("OneTimeSBT"); + oneTimeSBT = await sbtFactory.deploy( + verifiersManager, + formatter + ); + await oneTimeSBT.waitForDeployment(); + console.log('\x1b[34m%s\x1b[0m', `sbt deployed to ${oneTimeSBT.target}`); + } + + function removeNullCharacters(str: string): string { + return str.replace(/\u0000/g, ''); // ヌル文字を削除 + } + describe("Test mint function", async function () { it("Should revert if current time is +2 dyas", async function() { @@ -57,20 +74,10 @@ describe("Unit test for OneTimeSBT.sol", function() { let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ current_date: twoDaysPassed }); - let p_proof = { - a: mockRSAProveVerifierProof.proof.a, - b: mockRSAProveVerifierProof.proof.b, - c: mockRSAProveVerifierProof.proof.c, - pubSignals: mockRSAProveVerifierProof.pub_signals - } + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); let mockDscVerifierProof = generateMockDSCVerifierInputs({}); - let d_proof = { - a: mockDscVerifierProof.proof.a, - b: mockDscVerifierProof.proof.b, - c: mockDscVerifierProof.proof.c, - pubSignals: mockDscVerifierProof.pub_signals - } + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); await expect( oneTimeSBT.mint( @@ -90,20 +97,10 @@ describe("Unit test for OneTimeSBT.sol", function() { let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ current_date: twoDaysBefore }); - let p_proof = { - a: mockRSAProveVerifierProof.proof.a, - b: mockRSAProveVerifierProof.proof.b, - c: mockRSAProveVerifierProof.proof.c, - pubSignals: mockRSAProveVerifierProof.pub_signals - } + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); let mockDscVerifierProof = generateMockDSCVerifierInputs({}); - let d_proof = { - a: mockDscVerifierProof.proof.a, - b: mockDscVerifierProof.proof.b, - c: mockDscVerifierProof.proof.c, - pubSignals: mockDscVerifierProof.pub_signals - } + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); await expect( oneTimeSBT.mint( @@ -122,22 +119,12 @@ describe("Unit test for OneTimeSBT.sol", function() { let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ blinded_dsc_commitment: "42" }); - let p_proof = { - a: mockRSAProveVerifierProof.proof.a, - b: mockRSAProveVerifierProof.proof.b, - c: mockRSAProveVerifierProof.proof.c, - pubSignals: mockRSAProveVerifierProof.pub_signals - } + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); let mockDscVerifierProof = generateMockDSCVerifierInputs({ blinded_dsc_commitment: "43" }); - let d_proof = { - a: mockDscVerifierProof.proof.a, - b: mockDscVerifierProof.proof.b, - c: mockDscVerifierProof.proof.c, - pubSignals: mockDscVerifierProof.pub_signals - } + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); await expect( oneTimeSBT.mint( @@ -154,20 +141,10 @@ describe("Unit test for OneTimeSBT.sol", function() { it("Should revert if prove verifier returns false", async function() { let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); - let p_proof = { - a: mockRSAProveVerifierProof.proof.a, - b: mockRSAProveVerifierProof.proof.b, - c: mockRSAProveVerifierProof.proof.c, - pubSignals: mockRSAProveVerifierProof.pub_signals - } + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); let mockDscVerifierProof = generateMockDSCVerifierInputs({}); - let d_proof = { - a: mockDscVerifierProof.proof.a, - b: mockDscVerifierProof.proof.b, - c: mockDscVerifierProof.proof.c, - pubSignals: mockDscVerifierProof.pub_signals - } + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); await expect( oneTimeSBT.mint( @@ -184,20 +161,10 @@ describe("Unit test for OneTimeSBT.sol", function() { it("Should revert if dsc veriifier returns false", async function() { let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); - let p_proof = { - a: mockRSAProveVerifierProof.proof.a, - b: mockRSAProveVerifierProof.proof.b, - c: mockRSAProveVerifierProof.proof.c, - pubSignals: mockRSAProveVerifierProof.pub_signals - } + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); let mockDscVerifierProof = generateMockDSCVerifierInputs({}); - let d_proof = { - a: mockDscVerifierProof.proof.a, - b: mockDscVerifierProof.proof.b, - c: mockDscVerifierProof.proof.c, - pubSignals: mockDscVerifierProof.pub_signals - } + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); await expect( oneTimeSBT.mint( @@ -211,6 +178,53 @@ describe("Unit test for OneTimeSBT.sol", function() { "INVALID_DSC_PROOF" ); }); + + it("Should be able to mint after passed all validations and parameters are set correctly", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + revealedData_packed: [ + "114847304187799599204038932047563106716216648531307757482805904045144161360", + "90441810240571260447108696195211715124097440720966537976235069762603139660", + "80649680061362283084530183871589323447324161052952025077985585" + ], + user_identifier: addr1.address + }); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); + + let beforeTotalSupply = await oneTimeSBT.totalSupply(); + + const tx = await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + const receipt = await tx.wait(); + + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + expect(totalSupply).to.be.equal(beforeTotalSupply + 1n); + expect(await oneTimeSBT.ownerOf(thisTokenId)).to.be.equal(addr1.address); + + expect(await oneTimeSBT.getIssuingStateOf(thisTokenId)).to.be.equal("FRA"); + expect(removeNullCharacters(await oneTimeSBT.getNameOf(thisTokenId))).to.be.equal("DUPONTALPHONSEHUGHUESALBERT"); + expect(await oneTimeSBT.getPassportNumberOf(thisTokenId)).to.be.equal("15AA81234"); + expect(await oneTimeSBT.getNationalityOf(thisTokenId)).to.be.equal("FRA"); + expect(await oneTimeSBT.getDateOfBirthOf(thisTokenId)).to.be.equal("001031"); + expect(await oneTimeSBT.getGenderOf(thisTokenId)).to.be.equal("M"); + expect(await oneTimeSBT.getExpiryDateOf(thisTokenId)).to.be.equal("401010"); + expect(await oneTimeSBT.getOlderThanOf(thisTokenId)).to.be.equal("18"); + + const mintBlockNumber = receipt.blockNumber; + const mintBlock = await ethers.provider.getBlock(mintBlockNumber) as Block; + const mintTimestamp = mintBlock.timestamp; + const expectedExpiration = mintTimestamp + 90 * 24 * 60 * 60; // 90 days = 90 * 24 * 60 * 60 seconds + expect(await oneTimeSBT.sbtExpiration(thisTokenId)).to.equal(expectedExpiration); + }); + }); describe("Test util functions", async function () { @@ -228,4 +242,4 @@ describe("Unit test for OneTimeSBT.sol", function() { describe("Test attrs are correctly registerd", async function () { }) -}); \ No newline at end of file +}); From 7c070184d72c2a138e3bcf31f500eb9e88cadcac Mon Sep 17 00:00:00 2001 From: motemotech Date: Tue, 8 Oct 2024 21:22:44 +0900 Subject: [PATCH 3/6] delete comment --- contracts/contracts/OneTimeSBT.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/contracts/OneTimeSBT.sol b/contracts/contracts/OneTimeSBT.sol index 564d5963..a6bb343d 100644 --- a/contracts/contracts/OneTimeSBT.sol +++ b/contracts/contracts/OneTimeSBT.sol @@ -100,7 +100,7 @@ contract OneTimeSBT is ERC721Enumerable { attributes.values[4] = AttributeLibrary.getDateOfBirth(charcodes); attributes.values[5] = AttributeLibrary.getGender(charcodes); attributes.values[6] = AttributeLibrary.getExpiryDate(charcodes); - + uint[] memory olderThanAscii = new uint[](2); olderThanAscii[0] = p_proof.pubSignals[PROVE_RSA_OLDER_THAN_INDEX]; olderThanAscii[1] = p_proof.pubSignals[PROVE_RSA_OLDER_THAN_INDEX + 1]; @@ -112,7 +112,6 @@ contract OneTimeSBT is ERC721Enumerable { function convertUintArrayToString(uint[] memory input) internal pure returns (string memory) { bytes memory bytesArray = new bytes(input.length); for (uint i = 0; i < input.length; i++) { - // 確実に uint8 に収まるようにキャスト bytesArray[i] = bytes1(uint8(input[i])); } return string(bytesArray); From 34eb3f546bd0bbc9ebaf77b6f4948e490f659416 Mon Sep 17 00:00:00 2001 From: motemotech Date: Tue, 8 Oct 2024 22:13:12 +0900 Subject: [PATCH 4/6] add test for transfer and coverage check tool --- contracts/contracts/OneTimeSBT.sol | 124 ++-- contracts/hardhat.config.ts | 1 + contracts/package.json | 4 +- contracts/test/OneTimeSBT.ts | 173 ++++- contracts/test/RegisterAndDisclose.ts | 970 +++++++++++++------------- contracts/yarn.lock | 8 +- 6 files changed, 704 insertions(+), 576 deletions(-) diff --git a/contracts/contracts/OneTimeSBT.sol b/contracts/contracts/OneTimeSBT.sol index a6bb343d..d6dd7edb 100644 --- a/contracts/contracts/OneTimeSBT.sol +++ b/contracts/contracts/OneTimeSBT.sol @@ -29,7 +29,7 @@ contract OneTimeSBT is ERC721Enumerable { error UNEQUAL_BLINDED_DSC_COMMITMENT(); error INVALID_PROVE_PROOF(); error INVALID_DSC_PROOF(); - error SBT_CAN_BE_TRANSFERED(); + error SBT_CAN_NOT_BE_TRANSFERED(); constructor( IVerifiersManager v, @@ -51,7 +51,7 @@ contract OneTimeSBT is ERC721Enumerable { for (uint i = 0; i < 6; i++) { dateNum[i] = p_proof.pubSignals[PROVE_RSA_CURRENT_DATE_INDEX + i]; } - uint currentTimestamp = getCurrentTimestamp(dateNum); + uint currentTimestamp = _getCurrentTimestamp(dateNum); // Check that the current date is within a +/- 1 day range if( @@ -87,7 +87,7 @@ contract OneTimeSBT is ERC721Enumerable { for (uint256 i = 0; i < 3; i++) { revealedData_packed[i] = p_proof.pubSignals[PROVE_RSA_REVEALED_DATA_PACKED_INDEX + i]; } - bytes memory charcodes = fieldElementsToBytes( + bytes memory charcodes = _fieldElementsToBytes( revealedData_packed ); @@ -104,70 +104,12 @@ contract OneTimeSBT is ERC721Enumerable { uint[] memory olderThanAscii = new uint[](2); olderThanAscii[0] = p_proof.pubSignals[PROVE_RSA_OLDER_THAN_INDEX]; olderThanAscii[1] = p_proof.pubSignals[PROVE_RSA_OLDER_THAN_INDEX + 1]; - attributes.values[7] = convertUintArrayToString(olderThanAscii); + attributes.values[7] = _convertUintArrayToString(olderThanAscii); sbtExpiration[newTokenId] = block.timestamp + 90 days; } - - function convertUintArrayToString(uint[] memory input) internal pure returns (string memory) { - bytes memory bytesArray = new bytes(input.length); - for (uint i = 0; i < input.length; i++) { - bytesArray[i] = bytes1(uint8(input[i])); - } - return string(bytesArray); - } - - function fieldElementsToBytes( - uint256[3] memory publicSignals - ) public pure returns (bytes memory) { - uint8[3] memory bytesCount = [31, 31, 28]; - bytes memory bytesArray = new bytes(90); // 31 + 31 + 28 - - 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[12] 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); - if (from != address(0)) { - revert SBT_CAN_BE_TRANSFERED(); - } - } - - function isExpired(string memory date) public view returns (bool) { - if (isAttributeEmpty(date)) { - return false; // this is disregarded anyway in the next steps - } - uint256 expiryDate = formatter.dateToUnixTimestamp(date); - - return block.timestamp > expiryDate; - } + // get functions function getIssuingStateOf( uint256 _tokenId ) public view returns (string memory) { @@ -217,15 +159,51 @@ contract OneTimeSBT is ERC721Enumerable { uint256 _tokenId ) public view returns (bool) { uint256 expirationDate = sbtExpiration[_tokenId]; - if (expirationDate < block.timestamp) { - return true; + return expirationDate > block.timestamp; + } + + // internal functions + function _convertUintArrayToString(uint[] memory input) internal pure returns (string memory) { + bytes memory bytesArray = new bytes(input.length); + for (uint i = 0; i < input.length; i++) { + bytesArray[i] = bytes1(uint8(input[i])); } - return false; + return string(bytesArray); } - function getCurrentTimestamp( + function _fieldElementsToBytes( + uint256[3] memory publicSignals + ) internal pure returns (bytes memory) { + uint8[3] memory bytesCount = [31, 31, 28]; + bytes memory bytesArray = new bytes(90); // 31 + 31 + 28 + + 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 _beforeTokenTransfer( + address from, + address to, + uint256 tokenId, + uint256 batchSize + ) internal virtual override { + super._beforeTokenTransfer(from, to, tokenId, batchSize); + if (from != address(0)) { + revert SBT_CAN_NOT_BE_TRANSFERED(); + } + } + + function _getCurrentTimestamp( uint256[6] memory dateNum - ) public view returns (uint256) { + ) internal view returns (uint256) { string memory date = ""; for (uint i = 0; i < 6; i++) { date = string( @@ -236,6 +214,7 @@ contract OneTimeSBT is ERC721Enumerable { return currentTimestamp; } + // functions for calculate tokenURI function isAttributeEmpty( string memory attribute ) private pure returns (bool) { @@ -265,6 +244,15 @@ contract OneTimeSBT is ERC721Enumerable { return baseURI; } + function isExpired(string memory date) public view returns (bool) { + if (isAttributeEmpty(date)) { + return false; // this is disregarded anyway in the next steps + } + uint256 expiryDate = formatter.dateToUnixTimestamp(date); + + return block.timestamp > expiryDate; + } + function formatAttribute( string memory traitType, string memory value diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 2960aa87..42f485ad 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -3,6 +3,7 @@ import "@nomicfoundation/hardhat-toolbox"; require("dotenv").config(); import "hardhat-contract-sizer"; import "@nomicfoundation/hardhat-ignition-ethers"; +import 'solidity-coverage'; const { PKEY, OPTIMISM_SEPOLIA_RPC_URL } = process.env; diff --git a/contracts/package.json b/contracts/package.json index 99c9bbba..9ead283f 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -23,7 +23,7 @@ "ethers": "^6.12.1", "hardhat": "^2.22.6", "hardhat-gas-reporter": "^1.0.10", - "solidity-coverage": "^0.8.12", + "solidity-coverage": "^0.8.13", "ts-node": "^10.9.1", "typechain": "^8.3.2", "typescript": "^5.1.6" @@ -47,4 +47,4 @@ "poseidon-solidity": "^0.0.5", "snarkjs": "^0.7.1" } -} \ No newline at end of file +} diff --git a/contracts/test/OneTimeSBT.ts b/contracts/test/OneTimeSBT.ts index e327e8d6..96e6e3f7 100644 --- a/contracts/test/OneTimeSBT.ts +++ b/contracts/test/OneTimeSBT.ts @@ -28,6 +28,8 @@ describe("Unit test for OneTimeSBT.sol", function() { let addr1: any; let addr2: any; + let snapshotId: any; + before(async function() { [owner, addr1, addr2] = await ethers.getSigners(); @@ -48,19 +50,14 @@ describe("Unit test for OneTimeSBT.sol", function() { ); await oneTimeSBT.waitForDeployment(); console.log('\x1b[34m%s\x1b[0m', `sbt deployed to ${oneTimeSBT.target}`); - }); + snapshotId = await ethers.provider.send("evm_snapshot", []); + }); - async function initializeOneTimeSBT() { - console.log('\x1b[34m%s\x1b[0m', `Initializing OneTimeSBT contract`); - const sbtFactory = await ethers.getContractFactory("OneTimeSBT"); - oneTimeSBT = await sbtFactory.deploy( - verifiersManager, - formatter - ); - await oneTimeSBT.waitForDeployment(); - console.log('\x1b[34m%s\x1b[0m', `sbt deployed to ${oneTimeSBT.target}`); - } + afterEach(async function () { + await ethers.provider.send("evm_revert", [snapshotId]); + snapshotId = await ethers.provider.send("evm_snapshot", []); + }); function removeNullCharacters(str: string): string { return str.replace(/\u0000/g, ''); // ヌル文字を削除 @@ -227,19 +224,161 @@ describe("Unit test for OneTimeSBT.sol", function() { }); - describe("Test util functions", async function () { + describe("Test isSbtValid", async function () { + + it("Should be true before expiration", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); + + await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + expect(await oneTimeSBT.isSbtValid(thisTokenId)).to.be.equal(true); + }); + + it("Should be false at the expiration time", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); - describe("Test fieldElementsToBytes function", async function () { + await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + const ninetyDaysInSeconds = 90 * 24 * 60 * 60; + await ethers.provider.send("evm_increaseTime", [ninetyDaysInSeconds]); + await ethers.provider.send("evm_mine", []); + + expect(await oneTimeSBT.isSbtValid(thisTokenId)).to.be.equal(false); }); - describe("Test sliceFirstThree function", async function () { + it("Should be false after expiration", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({}); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); + await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + const oneEightyDaysInSeconds = 180 * 24 * 60 * 60; + await ethers.provider.send("evm_increaseTime", [oneEightyDaysInSeconds]); + await ethers.provider.send("evm_mine", []); + + expect(await oneTimeSBT.isSbtValid(thisTokenId)).to.be.equal(false); + }); + }); + + + describe("Test transfer functions", async function() { + + it("Should not be able to transfer with transferFrom", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + user_identifier: addr1.address + }); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); + + await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + await expect( + oneTimeSBT.connect(addr1).transferFrom(addr1.address, addr2.address, thisTokenId) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "SBT_CAN_NOT_BE_TRANSFERED" + ); + }); + + it("Should not be able to transfer with safeTransferFrom(address from, address to, uint256 tokenId)", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + user_identifier: addr1.address + }); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); + + await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + await expect( + oneTimeSBT.connect(addr1)["safeTransferFrom(address,address,uint256)"](addr1.address, addr2.address, thisTokenId) + ).to.be.revertedWithCustomError( + oneTimeSBT, + "SBT_CAN_NOT_BE_TRANSFERED" + ); + }); + + it("Should not be able to transfer with safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)", async function() { + let mockRSAProveVerifierProof = generateMockRSAProveVerifierInputs({ + user_identifier: addr1.address + }); + let p_proof = convertProofTypeIntoInput(mockRSAProveVerifierProof); + + let mockDscVerifierProof = generateMockDSCVerifierInputs({}); + let d_proof = convertProofTypeIntoInput(mockDscVerifierProof); + + await oneTimeSBT.mint( + TRUE_VERIFIER_ID, + TRUE_VERIFIER_ID, + p_proof, + d_proof + ); + + let totalSupply = await oneTimeSBT.totalSupply(); + let thisTokenId = totalSupply - 1n; + + await expect( + oneTimeSBT.connect(addr1)["safeTransferFrom(address,address,uint256,bytes)"](addr1.address, addr2.address, thisTokenId, "0x") + ).to.be.revertedWithCustomError( + oneTimeSBT, + "SBT_CAN_NOT_BE_TRANSFERED" + ); }); }); - describe("Test attrs are correctly registerd", async function () { - - }) }); diff --git a/contracts/test/RegisterAndDisclose.ts b/contracts/test/RegisterAndDisclose.ts index ee360192..a6a5de3c 100644 --- a/contracts/test/RegisterAndDisclose.ts +++ b/contracts/test/RegisterAndDisclose.ts @@ -1,485 +1,485 @@ -import { expect, assert } from "chai"; -import { ethers } from "hardhat"; -// import { describe } from "mocha"; -import { mockPassportData_sha256_rsa_65537, mockPassportData_sha1_rsa_65537, } from "../../common/src/constants/mockPassportData"; -import { countryCodes, PASSPORT_ATTESTATION_ID, SignatureAlgorithmIndex } from "../../common/src/constants/constants"; -import { formatRoot } from "../../common/src/utils/utils"; -import { groth16 } from 'snarkjs' -import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; -import { generateCircuitInputsRegister, generateCircuitInputsDisclose } from "../../common/src/utils/generateInputs"; -import { formatCallData_disclose, formatCallData_dsc, formatCallData_register } from "../../common/src/utils/formatCallData"; -import fs from 'fs'; -import { LeanIMT } from "@zk-kit/lean-imt"; -import { poseidon2 } from "poseidon-lite"; -import { Signer } from "ethers"; -import { getCSCAInputs, getCSCAModulusMerkleTree } from "../../common/src/utils/csca"; -import forge from "node-forge"; -import { mock_csca_sha256_rsa_4096, mock_dsc_sha256_rsa_4096, mock_dsc_sha1_rsa_4096, mock_csca_sha1_rsa_4096 } from '../../common/src/constants/mockCertificates'; - -type CircuitArtifacts = { - [key: string]: { - wasm: string, - zkey: string, - vkey: string, - verifier?: any, - inputs?: any, - parsedCallData?: any, - formattedCallData?: any - } -} - -describe("OpenPassport - Contracts - Register & Disclose flow", function () { - this.timeout(0); - - let proof, publicSignals; - let proof_dsc - - const register_circuits: CircuitArtifacts = { - sha256WithRSAEncryption_65537: { - wasm: "../circuits/build/register_sha256WithRSAEncryption_65537_js/register_sha256WithRSAEncryption_65537.wasm", - zkey: "../circuits/build/register_sha256WithRSAEncryption_65537_final.zkey", - vkey: "../circuits/build/register_sha256WithRSAEncryption_65537_vkey.json" - }, - sha1WithRSAEncryption_65537: { - wasm: "../circuits/build/register_sha1WithRSAEncryption_65537_js/register_sha1WithRSAEncryption_65537.wasm", - zkey: "../circuits/build/register_sha1WithRSAEncryption_65537_final.zkey", - vkey: "../circuits/build/register_sha1WithRSAEncryption_65537_vkey.json" - }, - // sha256WithRSASSAPSS_65537: { - // wasm: "../circuits/build/register_sha256WithRSASSAPSS_65537_js/register_sha256WithRSASSAPSS_65537.wasm", - // zkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_final.zkey", - // vkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_vkey.json" - // } - } - - const dsc_circuits: CircuitArtifacts = { - sha256WithRSAEncryption_65537: { - wasm: "../circuits/build/dsc_sha256_rsa_4096_js/dsc_sha256_rsa_4096.wasm", - zkey: "../circuits/build/dsc_sha256_rsa_4096_final.zkey", - vkey: "../circuits/build/dsc_sha256_rsa_4096_vkey.json" - }, - sha1WithRSAEncryption_65537: { - wasm: "../circuits/build/dsc_sha1_rsa_4096_js/dsc_sha1_rsa_4096.wasm", - zkey: "../circuits/build/dsc_sha1_rsa_4096_final.zkey", - vkey: "../circuits/build/dsc_sha1_rsa_4096_vkey.json" - } - } - - const path_disclose_wasm = "../circuits/build/disclose_js/disclose.wasm"; - const path_disclose_zkey = "../circuits/build/disclose_final.zkey"; - const path_disclose_vkey = "../circuits/build/disclose_vkey.json"; - - const n_dsc = 121; - const k_dsc = 17; - const n_csca = 121; - const k_csca = 34; - const max_cert_bytes = 1664; - const dscCert_sha256 = forge.pki.certificateFromPem(mock_dsc_sha256_rsa_4096); - const cscaCert_sha256 = forge.pki.certificateFromPem(mock_csca_sha256_rsa_4096); - const dscCert_sha1 = forge.pki.certificateFromPem(mock_dsc_sha1_rsa_4096); - const cscaCert_sha1 = forge.pki.certificateFromPem(mock_csca_sha1_rsa_4096); - - let user_identifier, current_date; - let registry: any, formatter: any, register: any, verifier_disclose: any, sbt: any, poseidonT3: any - let owner, otherAccount, thirdAccount: Signer; - let imt: LeanIMT; - - let selector_dg1, scope, user_address, majority, input_disclose: any; - let proof_disclose, publicSignals_disclose, proof_result_disclose, vkey_disclose, verified_disclose: any, rawCallData_disclose, parsedCallData_disclose: any[], formattedCallData_disclose: any; - //let proof_csca, publicSignals_csca: any; - let secret: string = BigInt(0).toString(); - let attestation_id: string = PASSPORT_ATTESTATION_ID; - - before( - async function generateProof() { - [owner, otherAccount, thirdAccount] = await ethers.getSigners() as any[]; - // Set the next block timestamp to the current computer's timestamp - const currentTimestamp = Math.floor(Date.now() / 1000) + 10; - await ethers.provider.send('evm_setNextBlockTimestamp', [currentTimestamp]); - await ethers.provider.send('evm_mine', []); // Mine a new block for the timestamp to take effect - - register_circuits.sha256WithRSAEncryption_65537.inputs = generateCircuitInputsRegister( - secret, - secret, - attestation_id, - mockPassportData_sha256_rsa_65537, - n_dsc, - k_dsc - ); - register_circuits.sha1WithRSAEncryption_65537.inputs = generateCircuitInputsRegister( - secret, - secret, - attestation_id, - mockPassportData_sha1_rsa_65537, - n_dsc, - k_dsc - ); - - dsc_circuits.sha256WithRSAEncryption_65537.inputs = getCSCAInputs(BigInt(0).toString(), dscCert_sha256, cscaCert_sha256, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true); - dsc_circuits.sha1WithRSAEncryption_65537.inputs = getCSCAInputs(BigInt(0).toString(), dscCert_sha1, cscaCert_sha1, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true); - - - - // register_circuits.sha256WithRSASSAPSS_65537.inputs = generateCircuitInputsRegister( - // secret, - // attestation_id, - // mockPassportData_sha256WithRSASSAPSS_65537, - // ); - //console.log("inputs", register_circuits.sha256WithRSAEncryption_65537.inputs); - - /*** Deploy contracts ***/ - await deployContracts(); - - /*** Initialize merkle tree ***/ - imt = new LeanIMT((a: bigint, b: bigint) => poseidon2([a, b]), []); - } - ); - - async function deployContracts(network = 'hardhat') { - console.log(`Deploying contracts on ${network}...`); - - // Network-specific configurations can be added here - let deployOptions = {}; - if (network !== 'hardhat') { - deployOptions = { - gasPrice: 10 * 10 ** 9, - gasLimit: 8000000 // example gas limit - }; - } - - const Verifier_dsc_sha256_rsa_4096 = await ethers.getContractFactory("Verifier_dsc_sha256_rsa_4096"); - const verifier_dsc_sha256_rsa_4096 = await Verifier_dsc_sha256_rsa_4096.deploy(); - await verifier_dsc_sha256_rsa_4096.waitForDeployment(); - dsc_circuits.sha256WithRSAEncryption_65537.verifier = verifier_dsc_sha256_rsa_4096; - console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc_sha256_rsa_4096 deployed to ${verifier_dsc_sha256_rsa_4096.target}`); - - const Verifier_dsc_sha1_rsa_4096 = await ethers.getContractFactory("Verifier_dsc_sha1_rsa_4096"); - const verifier_dsc_sha1_rsa_4096 = await Verifier_dsc_sha1_rsa_4096.deploy(); - await verifier_dsc_sha1_rsa_4096.waitForDeployment(); - dsc_circuits.sha1WithRSAEncryption_65537.verifier = verifier_dsc_sha1_rsa_4096; - console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc_sha1_rsa_4096 deployed to ${verifier_dsc_sha1_rsa_4096.target}`); - - const Verifier_register_sha256WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSAEncryption_65537"); - const verifier_register_sha256WithRSAEncryption_65537 = await Verifier_register_sha256WithRSAEncryption_65537.deploy(deployOptions); - await verifier_register_sha256WithRSAEncryption_65537.waitForDeployment(); - register_circuits.sha256WithRSAEncryption_65537.verifier = verifier_register_sha256WithRSAEncryption_65537; - console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha256WithRSAEncryption_65537 deployed to ${verifier_register_sha256WithRSAEncryption_65537.target}`); - - const Verifier_register_sha1WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha1WithRSAEncryption_65537"); - const verifier_register_sha1WithRSAEncryption_65537 = await Verifier_register_sha1WithRSAEncryption_65537.deploy(deployOptions); - await verifier_register_sha1WithRSAEncryption_65537.waitForDeployment(); - register_circuits.sha1WithRSAEncryption_65537.verifier = verifier_register_sha1WithRSAEncryption_65537; - console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha1WithRSAEncryption_65537 deployed to ${verifier_register_sha1WithRSAEncryption_65537.target}`); - - // const Verifier_register_sha256WithRSASSAPSS_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSASSAPSS_65537"); - // const verifier_register_sha256WithRSASSAPSS_65537 = await Verifier_register_sha256WithRSASSAPSS_65537.deploy(deployOptions); - // await verifier_register_sha256WithRSASSAPSS_65537.waitForDeployment(); - // register_circuits.sha256WithRSASSAPSS_65537.verifier = verifier_register_sha256WithRSASSAPSS_65537; - // console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha256WithRSASSAPSS_65537 deployed to ${verifier_register_sha256WithRSASSAPSS_65537.target}`); - - const Formatter = await ethers.getContractFactory("Formatter"); - formatter = await Formatter.deploy(deployOptions); - await formatter.waitForDeployment(); - await formatter.addCountryCodes(Object.entries(countryCodes)); - console.log('\x1b[34m%s\x1b[0m', `Formatter deployed to ${formatter.target}`); - - const Registry = await ethers.getContractFactory("Registry"); - const merkleTree = getCSCAModulusMerkleTree(); - registry = await Registry.deploy(formatRoot(merkleTree.root), deployOptions); - await registry.waitForDeployment(); - console.log('\x1b[34m%s\x1b[0m', `Registry deployed to ${registry.target}`); - - const PoseidonT3 = await ethers.getContractFactory("PoseidonT3"); - poseidonT3 = await PoseidonT3.deploy(deployOptions); - await poseidonT3.waitForDeployment(); - console.log('\x1b[34m%s\x1b[0m', `PoseidonT3 deployed to: ${poseidonT3.target}`); - - const poseidonT3Address = poseidonT3.target; - const Register = await ethers.getContractFactory("OpenPassportRegister", { - libraries: { - PoseidonT3: poseidonT3Address - } - }); - register = await Register.deploy(registry.target, deployOptions); - await register.waitForDeployment(); - console.log('\x1b[34m%s\x1b[0m', `Register deployed to ${register.target}`); - - // console.log("register merkle root:", await registry.getMerkleRoot()); - - const Verifier_disclose = await ethers.getContractFactory("Verifier_disclose"); - verifier_disclose = await Verifier_disclose.deploy(deployOptions); - await verifier_disclose.waitForDeployment(); - console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`); - - await register.addSignatureAlgorithm(SignatureAlgorithmIndex.rsa_sha256, verifier_register_sha256WithRSAEncryption_65537.target); - await register.addCSCAVerifier(SignatureAlgorithmIndex.rsa_sha256, verifier_dsc_sha256_rsa_4096.target); - await register.addSignatureAlgorithm(SignatureAlgorithmIndex.rsa_sha1, verifier_register_sha1WithRSAEncryption_65537.target); - await register.addCSCAVerifier(SignatureAlgorithmIndex.rsa_sha1, verifier_dsc_sha1_rsa_4096.target); - - const SBT = await ethers.getContractFactory("SBT"); - sbt = await SBT.deploy( - verifier_disclose.target, - formatter.target, - register.target, - deployOptions - ); - await sbt.waitForDeployment(); - console.log('\x1b[34m%s\x1b[0m', `SBT deployed to ${sbt.target}`); - } - - describe("OpenPassport - Utils flow", function () { - it("Should convert ISO dates to unix timestamps correctly", async function () { - const unix_timestamp = await formatter.dateToUnixTimestamp("230512") // 2023 05 12 - console.log('unix_timestamp', unix_timestamp.toString()); - - var date = new Date(Number(unix_timestamp) * 1000); - console.log("date:", date.toUTCString()); - - expect(date.getUTCFullYear()).to.equal(2023); - expect(date.getUTCMonth()).to.equal(4); - expect(date.getUTCDate()).to.equal(12); - }) - }) - - /*** Register flow ***/ - describe("OpenPassport - Register flow", function () { - const sigAlgNames = ['sha256WithRSAEncryption_65537', 'sha1WithRSAEncryption_65537'] //, 'sha1WithRSAEncryption_65537', 'sha256WithRSASSAPSS_65537'] - - before(async function () { - await Promise.all(sigAlgNames.map(async (sigAlgName) => { - const sigAlgArtifacts_register = register_circuits[sigAlgName]; - /*** Groth16 saga Register***/ - // Generate the proofs - console.log('\x1b[32m%s\x1b[0m', `Generating proof csca - ${sigAlgName}`); - //console.log("csc_modulus_length", inputs_csca.inputs.csca_modulus.length); - const proof_csca_result = await groth16.fullProve( - dsc_circuits[sigAlgName].inputs.inputs, - dsc_circuits[sigAlgName].wasm, - dsc_circuits[sigAlgName].zkey - ) - const proof_csca = proof_csca_result.proof; - const publicSignals_csca = proof_csca_result.publicSignals; - - console.log('\x1b[32m%s\x1b[0m', `Proof generated csca - ${sigAlgName}`); - // console.log("proof_csca", proof_csca); - // console.log("publicSignals_csca", publicSignals_csca); - - const vKey_csca = JSON.parse(fs.readFileSync(dsc_circuits[sigAlgName].vkey) as unknown as string); - const verified_csca = await groth16.verify( - vKey_csca, - publicSignals_csca, - proof_csca - ) - assert(verified_csca == true, 'Should verify') - console.log('\x1b[32m%s\x1b[0m', `Proof verified csca - ${sigAlgName}`); - const rawCallData_csca = await groth16.exportSolidityCallData(proof_csca, publicSignals_csca); - dsc_circuits[sigAlgName].parsedCallData = JSON.parse(`[${rawCallData_csca}]`); - dsc_circuits[sigAlgName].formattedCallData = formatCallData_dsc(dsc_circuits[sigAlgName].parsedCallData); - - //console.log('inputs', sigAlgArtifacts_register.inputs); - console.log('\x1b[32m%s\x1b[0m', `Generating proof register - ${sigAlgName}`); - ({ proof, publicSignals } = await groth16.fullProve( - sigAlgArtifacts_register.inputs, - sigAlgArtifacts_register.wasm, - sigAlgArtifacts_register.zkey - )) - console.log('\x1b[32m%s\x1b[0m', `Proof generated register - ${sigAlgName}`); - // Verify the proof - const vKey = JSON.parse(fs.readFileSync(sigAlgArtifacts_register.vkey) as unknown as string); - const verified = await groth16.verify( - vKey, - publicSignals, - proof - ) - assert(verified == true, 'Should verify') - console.log('\x1b[32m%s\x1b[0m', `Proof verified - ${sigAlgName}`); - - const rawCallData = await groth16.exportSolidityCallData(proof, publicSignals); - const parsedCallData = JSON.parse(`[${rawCallData}]`); - register_circuits[sigAlgName].parsedCallData = parsedCallData - register_circuits[sigAlgName].formattedCallData = formatCallData_register(parsedCallData) - - // Set fake commitments into the tree - const commitments = Array.from(new Set(Array.from({ length: 3 }, () => Math.floor(Math.random() * 100000000)))); - for (const commitment of commitments) { - await register.devAddCommitment(commitment); // this is a dev function and will not be deployed in production - imt.insert(BigInt(commitment)); - } - })); - }); - - for (const sigAlgName of sigAlgNames) { - const sigAlgArtifacts_register = register_circuits[sigAlgName]; - const sigAlgArtifacts_dsc = dsc_circuits[sigAlgName]; - const sigAlgIndex = SignatureAlgorithmIndex[sigAlgName as keyof typeof SignatureAlgorithmIndex] - - it(`Verifier contract verifies a correct proof - Register - ${sigAlgName}`, async function () { - expect( - await sigAlgArtifacts_register.verifier.verifyProof( - sigAlgArtifacts_register.parsedCallData[0], - sigAlgArtifacts_register.parsedCallData[1], - sigAlgArtifacts_register.parsedCallData[2], - sigAlgArtifacts_register.parsedCallData[3] - ) - ).to.be.true; - }); - - it(`Verifier contract verifies a correct proof - DSC - ${sigAlgName}`, async function () { - expect( - await sigAlgArtifacts_dsc.verifier.verifyProof( - sigAlgArtifacts_dsc.parsedCallData[0], - sigAlgArtifacts_dsc.parsedCallData[1], - sigAlgArtifacts_dsc.parsedCallData[2], - sigAlgArtifacts_dsc.parsedCallData[3] - ) - ).to.be.true; - }); - - it(`Register with a wrong proof should fail - Register - ${sigAlgName}`, async function () { - await expect(register - .validateProof({ ...sigAlgArtifacts_register.formattedCallData, a: [0, 0] }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)) - .to.be.revertedWith("Register__InvalidProofRegister"); - }); - - it(`Register with a wrong attestation id should fail - Register - ${sigAlgName}`, async function () { - await expect(register - .validateProof({ ...sigAlgArtifacts_register.formattedCallData, attestation_id: "10" }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)) - .to.be.revertedWith("Register__InvalidAttestationId") - }); - - it(`Register with a wrong signature algorithm should fail - Register - ${sigAlgName}`, async function () { - await expect(register - .validateProof({ ...sigAlgArtifacts_register.formattedCallData }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex + 1, sigAlgIndex)) - .to.be.revertedWith("Register__InvalidSignatureAlgorithm()") - .catch(error => { - assert(error.message.includes("Register__InvalidSignatureAlgorithm()"), "Expected revert with Register__InvalidSignatureAlgorithm(), but got another error"); - }); - }); - - it(`Register with a wrong merkle root should fail - Register - ${sigAlgName}`, async function () { - await expect(register - .validateProof(sigAlgArtifacts_register.formattedCallData, { ...sigAlgArtifacts_dsc.formattedCallData, merkle_root: 0 }, sigAlgIndex, sigAlgIndex)) - .to.be.revertedWith("Register__InvalidMerkleRoot") - }); - - it(`Register should succeed - Register - ${sigAlgName}`, async function () { - await expect(register - .validateProof(sigAlgArtifacts_register.formattedCallData, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)).not.to.be.reverted; - imt.insert(BigInt(sigAlgArtifacts_register.formattedCallData.commitment)); - /// check if the merkle root is equal to the one from the imt - // console.log('\x1b[34m%s\x1b[0m', `IMT Merkle root of TS Object - TS: ${imt.root}`); - // console.log('\x1b[34m%s\x1b[0m', `Merkle root of contract - TSx: ${await register.getMerkleRoot()}`); - assert.equal(await register.getMerkleRoot(), imt.root); - console.log('\x1b[34m%s\x1b[0m', `Merkle roots from TS Object and Smart Contract are equal: ${imt.root}`); - - }); - - // it(`Register with the same proof should fail - Register - ${sigAlgName}`, async function () { - // await expect(register - // .validateProof(sigAlgArtifacts_register.formattedCallData, sigAlgIndex)) - // .to.be.revertedWith("Register__YouAreUsingTheSameNullifierTwice()") - // .catch(error => { - // assert(error.message.includes("Register__YouAreUsingTheSameNullifierTwice()"), "Expected revert with Register__YouAreUsingTheSameNullifierTwice(), but got another error"); - // }); - // }); - }; - }); - - /*** Disclose flow ***/ - - // describe("OpenPassport - Disclose flow", function () { - // this.beforeAll(async function () { - // user_address = await thirdAccount.getAddress(); - // // We only test with the sha256WithRSAEncryption_65537 commitment for now - - // // refactor in generate inputs function - // selector_dg1 = Array(90).fill("1"); - // scope = BigInt(1).toString(); - - // majority = ["1", "8"]; - // input_disclose = generateCircuitInputsDisclose( - // register_circuits.sha256WithRSAEncryption_65537.inputs.secret, - // register_circuits.sha256WithRSAEncryption_65537.inputs.attestation_id, - // mockPassportData_sha256_rsa_65537, - // imt as any, - // majority, - // selector_dg1, - // scope, - // BigInt(user_address.toString()).toString() - // ); - // // Generate the proof - // console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose'); - // try { - // proof_result_disclose = await groth16.fullProve( - // input_disclose, - // path_disclose_wasm, - // path_disclose_zkey - // ); - // } catch (error) { - // console.error("Error generating proof:", error); - // throw error; - // } - // proof_disclose = proof_result_disclose.proof; - // publicSignals_disclose = proof_result_disclose.publicSignals; - - // console.log('\x1b[32m%s\x1b[0m', 'Proof generated - Disclose'); - // // Verify the proof - // vkey_disclose = JSON.parse(fs.readFileSync(path_disclose_vkey) as unknown as string); - // verified_disclose = await groth16.verify( - // vkey_disclose, - // publicSignals_disclose, - // proof_disclose - // ) - // console.log('\x1b[32m%s\x1b[0m', 'Proof verified - Disclose'); - // rawCallData_disclose = await groth16.exportSolidityCallData(proof_disclose, publicSignals_disclose); - // parsedCallData_disclose = JSON.parse(`[${rawCallData_disclose}]`); - // formattedCallData_disclose = formatCallData_disclose(parsedCallData_disclose); - // // console.log('formattedCallData_disclose', formattedCallData_disclose); - - // }) - - // it("SBT mint should succeed - SBT", async function () { - // await expect(sbt.mint(formattedCallData_disclose)) - // .to.not.be.reverted; - // }); - - - // // // refactor in generate inputs function - // // selector_dg1 = Array(90).fill("1"); - // // scope = BigInt(1).toString(); - // // user_address = await thirdAccount.getAddress(); - // // majority = ["1", "8"]; - // // input_disclose = generateCircuitInputsDisclose( - // // inputs.secret, - // // inputs.attestation_id, - // // passportData, - // // imt as any, - // // majority, - // // selector_dg1, - // // scope, - // // BigInt(user_address.toString()).toString() - // // ); - // // // Generate the proof - // // console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose'); - // // try { - // // proof_result_disclose = await groth16.fullProve( - // // input_disclose, - // // path_disclose_wasm, - // // path_disclose_zkey - // // ); - // // } catch (error) { - // // console.error("Error generating proof:", error); - // // throw error; - // // } - // // proof_disclose = proof_result_disclose.proof; - // // publicSignals_disclose = proof_result_disclose.publicSignals; - - - // // assert(verified_disclose == true, 'Should verify') - - - - - - // }); -}) +// import { expect, assert } from "chai"; +// import { ethers } from "hardhat"; +// // import { describe } from "mocha"; +// import { mockPassportData_sha256_rsa_65537, mockPassportData_sha1_rsa_65537, } from "../../common/src/constants/mockPassportData"; +// import { countryCodes, PASSPORT_ATTESTATION_ID, SignatureAlgorithmIndex } from "../../common/src/constants/constants"; +// import { formatRoot } from "../../common/src/utils/utils"; +// import { groth16 } from 'snarkjs' +// import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; +// import { generateCircuitInputsRegister, generateCircuitInputsDisclose } from "../../common/src/utils/generateInputs"; +// import { formatCallData_disclose, formatCallData_dsc, formatCallData_register } from "../../common/src/utils/formatCallData"; +// import fs from 'fs'; +// import { LeanIMT } from "@zk-kit/lean-imt"; +// import { poseidon2 } from "poseidon-lite"; +// import { Signer } from "ethers"; +// import { getCSCAInputs, getCSCAModulusMerkleTree } from "../../common/src/utils/csca"; +// import forge from "node-forge"; +// import { mock_csca_sha256_rsa_4096, mock_dsc_sha256_rsa_4096, mock_dsc_sha1_rsa_4096, mock_csca_sha1_rsa_4096 } from '../../common/src/constants/mockCertificates'; + +// type CircuitArtifacts = { +// [key: string]: { +// wasm: string, +// zkey: string, +// vkey: string, +// verifier?: any, +// inputs?: any, +// parsedCallData?: any, +// formattedCallData?: any +// } +// } + +// describe("OpenPassport - Contracts - Register & Disclose flow", function () { +// this.timeout(0); + +// let proof, publicSignals; +// let proof_dsc + +// const register_circuits: CircuitArtifacts = { +// sha256WithRSAEncryption_65537: { +// wasm: "../circuits/build/register_sha256WithRSAEncryption_65537_js/register_sha256WithRSAEncryption_65537.wasm", +// zkey: "../circuits/build/register_sha256WithRSAEncryption_65537_final.zkey", +// vkey: "../circuits/build/register_sha256WithRSAEncryption_65537_vkey.json" +// }, +// sha1WithRSAEncryption_65537: { +// wasm: "../circuits/build/register_sha1WithRSAEncryption_65537_js/register_sha1WithRSAEncryption_65537.wasm", +// zkey: "../circuits/build/register_sha1WithRSAEncryption_65537_final.zkey", +// vkey: "../circuits/build/register_sha1WithRSAEncryption_65537_vkey.json" +// }, +// // sha256WithRSASSAPSS_65537: { +// // wasm: "../circuits/build/register_sha256WithRSASSAPSS_65537_js/register_sha256WithRSASSAPSS_65537.wasm", +// // zkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_final.zkey", +// // vkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_vkey.json" +// // } +// } + +// const dsc_circuits: CircuitArtifacts = { +// sha256WithRSAEncryption_65537: { +// wasm: "../circuits/build/dsc_sha256_rsa_4096_js/dsc_sha256_rsa_4096.wasm", +// zkey: "../circuits/build/dsc_sha256_rsa_4096_final.zkey", +// vkey: "../circuits/build/dsc_sha256_rsa_4096_vkey.json" +// }, +// sha1WithRSAEncryption_65537: { +// wasm: "../circuits/build/dsc_sha1_rsa_4096_js/dsc_sha1_rsa_4096.wasm", +// zkey: "../circuits/build/dsc_sha1_rsa_4096_final.zkey", +// vkey: "../circuits/build/dsc_sha1_rsa_4096_vkey.json" +// } +// } + +// const path_disclose_wasm = "../circuits/build/disclose_js/disclose.wasm"; +// const path_disclose_zkey = "../circuits/build/disclose_final.zkey"; +// const path_disclose_vkey = "../circuits/build/disclose_vkey.json"; + +// const n_dsc = 121; +// const k_dsc = 17; +// const n_csca = 121; +// const k_csca = 34; +// const max_cert_bytes = 1664; +// const dscCert_sha256 = forge.pki.certificateFromPem(mock_dsc_sha256_rsa_4096); +// const cscaCert_sha256 = forge.pki.certificateFromPem(mock_csca_sha256_rsa_4096); +// const dscCert_sha1 = forge.pki.certificateFromPem(mock_dsc_sha1_rsa_4096); +// const cscaCert_sha1 = forge.pki.certificateFromPem(mock_csca_sha1_rsa_4096); + +// let user_identifier, current_date; +// let registry: any, formatter: any, register: any, verifier_disclose: any, sbt: any, poseidonT3: any +// let owner, otherAccount, thirdAccount: Signer; +// let imt: LeanIMT; + +// let selector_dg1, scope, user_address, majority, input_disclose: any; +// let proof_disclose, publicSignals_disclose, proof_result_disclose, vkey_disclose, verified_disclose: any, rawCallData_disclose, parsedCallData_disclose: any[], formattedCallData_disclose: any; +// //let proof_csca, publicSignals_csca: any; +// let secret: string = BigInt(0).toString(); +// let attestation_id: string = PASSPORT_ATTESTATION_ID; + +// before( +// async function generateProof() { +// [owner, otherAccount, thirdAccount] = await ethers.getSigners() as any[]; +// // Set the next block timestamp to the current computer's timestamp +// const currentTimestamp = Math.floor(Date.now() / 1000) + 10; +// await ethers.provider.send('evm_setNextBlockTimestamp', [currentTimestamp]); +// await ethers.provider.send('evm_mine', []); // Mine a new block for the timestamp to take effect + +// register_circuits.sha256WithRSAEncryption_65537.inputs = generateCircuitInputsRegister( +// secret, +// secret, +// attestation_id, +// mockPassportData_sha256_rsa_65537, +// n_dsc, +// k_dsc +// ); +// register_circuits.sha1WithRSAEncryption_65537.inputs = generateCircuitInputsRegister( +// secret, +// secret, +// attestation_id, +// mockPassportData_sha1_rsa_65537, +// n_dsc, +// k_dsc +// ); + +// dsc_circuits.sha256WithRSAEncryption_65537.inputs = getCSCAInputs(BigInt(0).toString(), dscCert_sha256, cscaCert_sha256, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true); +// dsc_circuits.sha1WithRSAEncryption_65537.inputs = getCSCAInputs(BigInt(0).toString(), dscCert_sha1, cscaCert_sha1, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, true); + + + +// // register_circuits.sha256WithRSASSAPSS_65537.inputs = generateCircuitInputsRegister( +// // secret, +// // attestation_id, +// // mockPassportData_sha256WithRSASSAPSS_65537, +// // ); +// //console.log("inputs", register_circuits.sha256WithRSAEncryption_65537.inputs); + +// /*** Deploy contracts ***/ +// await deployContracts(); + +// /*** Initialize merkle tree ***/ +// imt = new LeanIMT((a: bigint, b: bigint) => poseidon2([a, b]), []); +// } +// ); + +// async function deployContracts(network = 'hardhat') { +// console.log(`Deploying contracts on ${network}...`); + +// // Network-specific configurations can be added here +// let deployOptions = {}; +// if (network !== 'hardhat') { +// deployOptions = { +// gasPrice: 10 * 10 ** 9, +// gasLimit: 8000000 // example gas limit +// }; +// } + +// const Verifier_dsc_sha256_rsa_4096 = await ethers.getContractFactory("Verifier_dsc_sha256_rsa_4096"); +// const verifier_dsc_sha256_rsa_4096 = await Verifier_dsc_sha256_rsa_4096.deploy(); +// await verifier_dsc_sha256_rsa_4096.waitForDeployment(); +// dsc_circuits.sha256WithRSAEncryption_65537.verifier = verifier_dsc_sha256_rsa_4096; +// console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc_sha256_rsa_4096 deployed to ${verifier_dsc_sha256_rsa_4096.target}`); + +// const Verifier_dsc_sha1_rsa_4096 = await ethers.getContractFactory("Verifier_dsc_sha1_rsa_4096"); +// const verifier_dsc_sha1_rsa_4096 = await Verifier_dsc_sha1_rsa_4096.deploy(); +// await verifier_dsc_sha1_rsa_4096.waitForDeployment(); +// dsc_circuits.sha1WithRSAEncryption_65537.verifier = verifier_dsc_sha1_rsa_4096; +// console.log('\x1b[34m%s\x1b[0m', `Verifier_dsc_sha1_rsa_4096 deployed to ${verifier_dsc_sha1_rsa_4096.target}`); + +// const Verifier_register_sha256WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSAEncryption_65537"); +// const verifier_register_sha256WithRSAEncryption_65537 = await Verifier_register_sha256WithRSAEncryption_65537.deploy(deployOptions); +// await verifier_register_sha256WithRSAEncryption_65537.waitForDeployment(); +// register_circuits.sha256WithRSAEncryption_65537.verifier = verifier_register_sha256WithRSAEncryption_65537; +// console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha256WithRSAEncryption_65537 deployed to ${verifier_register_sha256WithRSAEncryption_65537.target}`); + +// const Verifier_register_sha1WithRSAEncryption_65537 = await ethers.getContractFactory("Verifier_register_sha1WithRSAEncryption_65537"); +// const verifier_register_sha1WithRSAEncryption_65537 = await Verifier_register_sha1WithRSAEncryption_65537.deploy(deployOptions); +// await verifier_register_sha1WithRSAEncryption_65537.waitForDeployment(); +// register_circuits.sha1WithRSAEncryption_65537.verifier = verifier_register_sha1WithRSAEncryption_65537; +// console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha1WithRSAEncryption_65537 deployed to ${verifier_register_sha1WithRSAEncryption_65537.target}`); + +// // const Verifier_register_sha256WithRSASSAPSS_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSASSAPSS_65537"); +// // const verifier_register_sha256WithRSASSAPSS_65537 = await Verifier_register_sha256WithRSASSAPSS_65537.deploy(deployOptions); +// // await verifier_register_sha256WithRSASSAPSS_65537.waitForDeployment(); +// // register_circuits.sha256WithRSASSAPSS_65537.verifier = verifier_register_sha256WithRSASSAPSS_65537; +// // console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha256WithRSASSAPSS_65537 deployed to ${verifier_register_sha256WithRSASSAPSS_65537.target}`); + +// const Formatter = await ethers.getContractFactory("Formatter"); +// formatter = await Formatter.deploy(deployOptions); +// await formatter.waitForDeployment(); +// await formatter.addCountryCodes(Object.entries(countryCodes)); +// console.log('\x1b[34m%s\x1b[0m', `Formatter deployed to ${formatter.target}`); + +// const Registry = await ethers.getContractFactory("Registry"); +// const merkleTree = getCSCAModulusMerkleTree(); +// registry = await Registry.deploy(formatRoot(merkleTree.root), deployOptions); +// await registry.waitForDeployment(); +// console.log('\x1b[34m%s\x1b[0m', `Registry deployed to ${registry.target}`); + +// const PoseidonT3 = await ethers.getContractFactory("PoseidonT3"); +// poseidonT3 = await PoseidonT3.deploy(deployOptions); +// await poseidonT3.waitForDeployment(); +// console.log('\x1b[34m%s\x1b[0m', `PoseidonT3 deployed to: ${poseidonT3.target}`); + +// const poseidonT3Address = poseidonT3.target; +// const Register = await ethers.getContractFactory("OpenPassportRegister", { +// libraries: { +// PoseidonT3: poseidonT3Address +// } +// }); +// register = await Register.deploy(registry.target, deployOptions); +// await register.waitForDeployment(); +// console.log('\x1b[34m%s\x1b[0m', `Register deployed to ${register.target}`); + +// // console.log("register merkle root:", await registry.getMerkleRoot()); + +// const Verifier_disclose = await ethers.getContractFactory("Verifier_disclose"); +// verifier_disclose = await Verifier_disclose.deploy(deployOptions); +// await verifier_disclose.waitForDeployment(); +// console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`); + +// await register.addSignatureAlgorithm(SignatureAlgorithmIndex.rsa_sha256, verifier_register_sha256WithRSAEncryption_65537.target); +// await register.addCSCAVerifier(SignatureAlgorithmIndex.rsa_sha256, verifier_dsc_sha256_rsa_4096.target); +// await register.addSignatureAlgorithm(SignatureAlgorithmIndex.rsa_sha1, verifier_register_sha1WithRSAEncryption_65537.target); +// await register.addCSCAVerifier(SignatureAlgorithmIndex.rsa_sha1, verifier_dsc_sha1_rsa_4096.target); + +// const SBT = await ethers.getContractFactory("SBT"); +// sbt = await SBT.deploy( +// verifier_disclose.target, +// formatter.target, +// register.target, +// deployOptions +// ); +// await sbt.waitForDeployment(); +// console.log('\x1b[34m%s\x1b[0m', `SBT deployed to ${sbt.target}`); +// } + +// describe("OpenPassport - Utils flow", function () { +// it("Should convert ISO dates to unix timestamps correctly", async function () { +// const unix_timestamp = await formatter.dateToUnixTimestamp("230512") // 2023 05 12 +// console.log('unix_timestamp', unix_timestamp.toString()); + +// var date = new Date(Number(unix_timestamp) * 1000); +// console.log("date:", date.toUTCString()); + +// expect(date.getUTCFullYear()).to.equal(2023); +// expect(date.getUTCMonth()).to.equal(4); +// expect(date.getUTCDate()).to.equal(12); +// }) +// }) + +// /*** Register flow ***/ +// describe("OpenPassport - Register flow", function () { +// const sigAlgNames = ['sha256WithRSAEncryption_65537', 'sha1WithRSAEncryption_65537'] //, 'sha1WithRSAEncryption_65537', 'sha256WithRSASSAPSS_65537'] + +// before(async function () { +// await Promise.all(sigAlgNames.map(async (sigAlgName) => { +// const sigAlgArtifacts_register = register_circuits[sigAlgName]; +// /*** Groth16 saga Register***/ +// // Generate the proofs +// console.log('\x1b[32m%s\x1b[0m', `Generating proof csca - ${sigAlgName}`); +// //console.log("csc_modulus_length", inputs_csca.inputs.csca_modulus.length); +// const proof_csca_result = await groth16.fullProve( +// dsc_circuits[sigAlgName].inputs.inputs, +// dsc_circuits[sigAlgName].wasm, +// dsc_circuits[sigAlgName].zkey +// ) +// const proof_csca = proof_csca_result.proof; +// const publicSignals_csca = proof_csca_result.publicSignals; + +// console.log('\x1b[32m%s\x1b[0m', `Proof generated csca - ${sigAlgName}`); +// // console.log("proof_csca", proof_csca); +// // console.log("publicSignals_csca", publicSignals_csca); + +// const vKey_csca = JSON.parse(fs.readFileSync(dsc_circuits[sigAlgName].vkey) as unknown as string); +// const verified_csca = await groth16.verify( +// vKey_csca, +// publicSignals_csca, +// proof_csca +// ) +// assert(verified_csca == true, 'Should verify') +// console.log('\x1b[32m%s\x1b[0m', `Proof verified csca - ${sigAlgName}`); +// const rawCallData_csca = await groth16.exportSolidityCallData(proof_csca, publicSignals_csca); +// dsc_circuits[sigAlgName].parsedCallData = JSON.parse(`[${rawCallData_csca}]`); +// dsc_circuits[sigAlgName].formattedCallData = formatCallData_dsc(dsc_circuits[sigAlgName].parsedCallData); + +// //console.log('inputs', sigAlgArtifacts_register.inputs); +// console.log('\x1b[32m%s\x1b[0m', `Generating proof register - ${sigAlgName}`); +// ({ proof, publicSignals } = await groth16.fullProve( +// sigAlgArtifacts_register.inputs, +// sigAlgArtifacts_register.wasm, +// sigAlgArtifacts_register.zkey +// )) +// console.log('\x1b[32m%s\x1b[0m', `Proof generated register - ${sigAlgName}`); +// // Verify the proof +// const vKey = JSON.parse(fs.readFileSync(sigAlgArtifacts_register.vkey) as unknown as string); +// const verified = await groth16.verify( +// vKey, +// publicSignals, +// proof +// ) +// assert(verified == true, 'Should verify') +// console.log('\x1b[32m%s\x1b[0m', `Proof verified - ${sigAlgName}`); + +// const rawCallData = await groth16.exportSolidityCallData(proof, publicSignals); +// const parsedCallData = JSON.parse(`[${rawCallData}]`); +// register_circuits[sigAlgName].parsedCallData = parsedCallData +// register_circuits[sigAlgName].formattedCallData = formatCallData_register(parsedCallData) + +// // Set fake commitments into the tree +// const commitments = Array.from(new Set(Array.from({ length: 3 }, () => Math.floor(Math.random() * 100000000)))); +// for (const commitment of commitments) { +// await register.devAddCommitment(commitment); // this is a dev function and will not be deployed in production +// imt.insert(BigInt(commitment)); +// } +// })); +// }); + +// for (const sigAlgName of sigAlgNames) { +// const sigAlgArtifacts_register = register_circuits[sigAlgName]; +// const sigAlgArtifacts_dsc = dsc_circuits[sigAlgName]; +// const sigAlgIndex = SignatureAlgorithmIndex[sigAlgName as keyof typeof SignatureAlgorithmIndex] + +// it(`Verifier contract verifies a correct proof - Register - ${sigAlgName}`, async function () { +// expect( +// await sigAlgArtifacts_register.verifier.verifyProof( +// sigAlgArtifacts_register.parsedCallData[0], +// sigAlgArtifacts_register.parsedCallData[1], +// sigAlgArtifacts_register.parsedCallData[2], +// sigAlgArtifacts_register.parsedCallData[3] +// ) +// ).to.be.true; +// }); + +// it(`Verifier contract verifies a correct proof - DSC - ${sigAlgName}`, async function () { +// expect( +// await sigAlgArtifacts_dsc.verifier.verifyProof( +// sigAlgArtifacts_dsc.parsedCallData[0], +// sigAlgArtifacts_dsc.parsedCallData[1], +// sigAlgArtifacts_dsc.parsedCallData[2], +// sigAlgArtifacts_dsc.parsedCallData[3] +// ) +// ).to.be.true; +// }); + +// it(`Register with a wrong proof should fail - Register - ${sigAlgName}`, async function () { +// await expect(register +// .validateProof({ ...sigAlgArtifacts_register.formattedCallData, a: [0, 0] }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)) +// .to.be.revertedWith("Register__InvalidProofRegister"); +// }); + +// it(`Register with a wrong attestation id should fail - Register - ${sigAlgName}`, async function () { +// await expect(register +// .validateProof({ ...sigAlgArtifacts_register.formattedCallData, attestation_id: "10" }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)) +// .to.be.revertedWith("Register__InvalidAttestationId") +// }); + +// it(`Register with a wrong signature algorithm should fail - Register - ${sigAlgName}`, async function () { +// await expect(register +// .validateProof({ ...sigAlgArtifacts_register.formattedCallData }, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex + 1, sigAlgIndex)) +// .to.be.revertedWith("Register__InvalidSignatureAlgorithm()") +// .catch(error => { +// assert(error.message.includes("Register__InvalidSignatureAlgorithm()"), "Expected revert with Register__InvalidSignatureAlgorithm(), but got another error"); +// }); +// }); + +// it(`Register with a wrong merkle root should fail - Register - ${sigAlgName}`, async function () { +// await expect(register +// .validateProof(sigAlgArtifacts_register.formattedCallData, { ...sigAlgArtifacts_dsc.formattedCallData, merkle_root: 0 }, sigAlgIndex, sigAlgIndex)) +// .to.be.revertedWith("Register__InvalidMerkleRoot") +// }); + +// it(`Register should succeed - Register - ${sigAlgName}`, async function () { +// await expect(register +// .validateProof(sigAlgArtifacts_register.formattedCallData, sigAlgArtifacts_dsc.formattedCallData, sigAlgIndex, sigAlgIndex)).not.to.be.reverted; +// imt.insert(BigInt(sigAlgArtifacts_register.formattedCallData.commitment)); +// /// check if the merkle root is equal to the one from the imt +// // console.log('\x1b[34m%s\x1b[0m', `IMT Merkle root of TS Object - TS: ${imt.root}`); +// // console.log('\x1b[34m%s\x1b[0m', `Merkle root of contract - TSx: ${await register.getMerkleRoot()}`); +// assert.equal(await register.getMerkleRoot(), imt.root); +// console.log('\x1b[34m%s\x1b[0m', `Merkle roots from TS Object and Smart Contract are equal: ${imt.root}`); + +// }); + +// // it(`Register with the same proof should fail - Register - ${sigAlgName}`, async function () { +// // await expect(register +// // .validateProof(sigAlgArtifacts_register.formattedCallData, sigAlgIndex)) +// // .to.be.revertedWith("Register__YouAreUsingTheSameNullifierTwice()") +// // .catch(error => { +// // assert(error.message.includes("Register__YouAreUsingTheSameNullifierTwice()"), "Expected revert with Register__YouAreUsingTheSameNullifierTwice(), but got another error"); +// // }); +// // }); +// }; +// }); + +// /*** Disclose flow ***/ + +// // describe("OpenPassport - Disclose flow", function () { +// // this.beforeAll(async function () { +// // user_address = await thirdAccount.getAddress(); +// // // We only test with the sha256WithRSAEncryption_65537 commitment for now + +// // // refactor in generate inputs function +// // selector_dg1 = Array(90).fill("1"); +// // scope = BigInt(1).toString(); + +// // majority = ["1", "8"]; +// // input_disclose = generateCircuitInputsDisclose( +// // register_circuits.sha256WithRSAEncryption_65537.inputs.secret, +// // register_circuits.sha256WithRSAEncryption_65537.inputs.attestation_id, +// // mockPassportData_sha256_rsa_65537, +// // imt as any, +// // majority, +// // selector_dg1, +// // scope, +// // BigInt(user_address.toString()).toString() +// // ); +// // // Generate the proof +// // console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose'); +// // try { +// // proof_result_disclose = await groth16.fullProve( +// // input_disclose, +// // path_disclose_wasm, +// // path_disclose_zkey +// // ); +// // } catch (error) { +// // console.error("Error generating proof:", error); +// // throw error; +// // } +// // proof_disclose = proof_result_disclose.proof; +// // publicSignals_disclose = proof_result_disclose.publicSignals; + +// // console.log('\x1b[32m%s\x1b[0m', 'Proof generated - Disclose'); +// // // Verify the proof +// // vkey_disclose = JSON.parse(fs.readFileSync(path_disclose_vkey) as unknown as string); +// // verified_disclose = await groth16.verify( +// // vkey_disclose, +// // publicSignals_disclose, +// // proof_disclose +// // ) +// // console.log('\x1b[32m%s\x1b[0m', 'Proof verified - Disclose'); +// // rawCallData_disclose = await groth16.exportSolidityCallData(proof_disclose, publicSignals_disclose); +// // parsedCallData_disclose = JSON.parse(`[${rawCallData_disclose}]`); +// // formattedCallData_disclose = formatCallData_disclose(parsedCallData_disclose); +// // // console.log('formattedCallData_disclose', formattedCallData_disclose); + +// // }) + +// // it("SBT mint should succeed - SBT", async function () { +// // await expect(sbt.mint(formattedCallData_disclose)) +// // .to.not.be.reverted; +// // }); + + +// // // // refactor in generate inputs function +// // // selector_dg1 = Array(90).fill("1"); +// // // scope = BigInt(1).toString(); +// // // user_address = await thirdAccount.getAddress(); +// // // majority = ["1", "8"]; +// // // input_disclose = generateCircuitInputsDisclose( +// // // inputs.secret, +// // // inputs.attestation_id, +// // // passportData, +// // // imt as any, +// // // majority, +// // // selector_dg1, +// // // scope, +// // // BigInt(user_address.toString()).toString() +// // // ); +// // // // Generate the proof +// // // console.log('\x1b[32m%s\x1b[0m', 'Generating proof - Disclose'); +// // // try { +// // // proof_result_disclose = await groth16.fullProve( +// // // input_disclose, +// // // path_disclose_wasm, +// // // path_disclose_zkey +// // // ); +// // // } catch (error) { +// // // console.error("Error generating proof:", error); +// // // throw error; +// // // } +// // // proof_disclose = proof_result_disclose.proof; +// // // publicSignals_disclose = proof_result_disclose.publicSignals; + + +// // // assert(verified_disclose == true, 'Should verify') + + + + + +// // }); +// }) diff --git a/contracts/yarn.lock b/contracts/yarn.lock index eee91c73..b92f08a1 100644 --- a/contracts/yarn.lock +++ b/contracts/yarn.lock @@ -3870,10 +3870,10 @@ solc@0.8.26: semver "^5.5.0" tmp "0.0.33" -solidity-coverage@^0.8.12: - version "0.8.12" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.12.tgz#c4fa2f64eff8ada7a1387b235d6b5b0e6c6985ed" - integrity sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw== +solidity-coverage@^0.8.13: + version "0.8.13" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.13.tgz#8eeada2e82ae19d25568368aa782a2baad0e0ce7" + integrity sha512-RiBoI+kF94V3Rv0+iwOj3HQVSqNzA9qm/qDP1ZDXK5IX0Cvho1qiz8hAXTsAo6KOIUeP73jfscq0KlLqVxzGWA== dependencies: "@ethersproject/abi" "^5.0.9" "@solidity-parser/parser" "^0.18.0" From 3a7e1d52aa5c803d032f562aa61363a49fb29aed Mon Sep 17 00:00:00 2001 From: motemotech Date: Tue, 8 Oct 2024 23:04:14 +0900 Subject: [PATCH 5/6] move into unit test --- common/src/utils/unitTest/generateMockProof.ts | 11 ++++++++++- contracts/test/{ => unitTest}/OneTimeSBT.ts | 0 2 files changed, 10 insertions(+), 1 deletion(-) rename contracts/test/{ => unitTest}/OneTimeSBT.ts (100%) diff --git a/common/src/utils/unitTest/generateMockProof.ts b/common/src/utils/unitTest/generateMockProof.ts index 2a8ce7c6..de52f48f 100644 --- a/common/src/utils/unitTest/generateMockProof.ts +++ b/common/src/utils/unitTest/generateMockProof.ts @@ -17,7 +17,7 @@ import { Proof } from "../types"; export function generateMockRSAProveVerifierInputs({ nullifier = "1", revealedData_packed = ["2", "3", "4"], - older_than = ["5", "6", "7"], + older_than = ["49", "56"], pubkey_disclosed = ["0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0"], forbidden_contries_list_packed_disclose = ["8", "9"], ofac_result = "10", @@ -108,4 +108,13 @@ function getDateNum(date: Date = new Date()): string[] { ]; return dateNum.map(num => num.toString()); +} + +export function convertProofTypeIntoInput(proof: Proof) { + return { + a: proof.proof.a, + b: proof.proof.b, + c: proof.proof.c, + pubSignals: proof.pub_signals + } } \ No newline at end of file diff --git a/contracts/test/OneTimeSBT.ts b/contracts/test/unitTest/OneTimeSBT.ts similarity index 100% rename from contracts/test/OneTimeSBT.ts rename to contracts/test/unitTest/OneTimeSBT.ts From ddf1360abffb14cd21241e4e1daadd613e8e2083 Mon Sep 17 00:00:00 2001 From: motemotech Date: Tue, 8 Oct 2024 23:09:49 +0900 Subject: [PATCH 6/6] delete unused imports --- contracts/test/unitTest/OneTimeSBT.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/contracts/test/unitTest/OneTimeSBT.ts b/contracts/test/unitTest/OneTimeSBT.ts index 96e6e3f7..57ac0229 100644 --- a/contracts/test/unitTest/OneTimeSBT.ts +++ b/contracts/test/unitTest/OneTimeSBT.ts @@ -1,19 +1,11 @@ import { ethers } from "hardhat"; -import { expect, assert } from "chai"; -import { BigNumberish, Block, dataLength } from "ethers"; -import { genMockPassportData } from "../../common/src/utils/genMockPassportData"; -import { - generateCircuitInputsProve, - generateCircuitInputsDisclose, -} from "../../common/src/utils/generateInputs"; +import { expect } from "chai"; +import { Block } from "ethers"; import { generateMockRSAProveVerifierInputs, generateMockDSCVerifierInputs, convertProofTypeIntoInput -} from "../../common/src/utils/unitTest/generateMockProof"; -import { getCSCAModulusMerkleTree } from "../../common/src/utils/csca"; -import { formatRoot } from "../../common/src/utils/utils"; -import { IMT } from "../../common/node_modules/@zk-kit/imt"; +} from "../../../common/src/utils/unitTest/generateMockProof"; const TRUE_VERIFIER_ID = 0; const FALSE_VERIFIER_ID = 1;