diff --git a/contracts/contracts/ProofOfPassportRegister.sol b/contracts/contracts/ProofOfPassportRegister.sol index 02707094b..ffdd91386 100644 --- a/contracts/contracts/ProofOfPassportRegister.sol +++ b/contracts/contracts/ProofOfPassportRegister.sol @@ -60,6 +60,9 @@ contract ProofOfPassportRegister is IRegister, Ownable { using InternalLeanIMT for LeanIMTData; LeanIMTData internal imt; + // poseidon("E-PASSPORT") + bytes32 public attestationId = bytes32(0x12d57183e0a41615471a14e5a93c87b9db757118c1d7a6a9f73106819d656f24); + mapping(uint256 => bool) public nullifiers; mapping(uint256 => bool) public merkleRootsCreated; mapping(uint256 => address) public verifiers; @@ -69,18 +72,18 @@ contract ProofOfPassportRegister is IRegister, Ownable { transferOwnership(msg.sender); } - function validateProof(RegisterProof calldata proof) external override { + function validateProof(RegisterProof calldata proof, uint256 signature_algorithm) external override { if (!registry.checkRoot(bytes32(proof.merkle_root))) { - revert Register__InvalidMerkleRoot(); + revert("InvalidMerkleRoot"); } if (nullifiers[proof.nullifier]) { - revert Register__YouAreUsingTheSameNullifierTwice(); + revert("YouAreUsingTheSameNullifierTwice"); } - if (verifiers[proof.signature_algorithm] == address(0)) { - revert Register__InvalidSignatureAlgorithm(); + if (bytes32(proof.attestation_id) != attestationId) { + revert("InvalidAttestationId"); } - if (!verifyProof(proof)) { - revert Register__InvalidProof(); + if (!verifyProof(proof, signature_algorithm)) { + revert("InvalidProof"); } nullifiers[proof.nullifier] = true; @@ -95,10 +98,11 @@ contract ProofOfPassportRegister is IRegister, Ownable { } function verifyProof( - RegisterProof calldata proof + RegisterProof calldata proof, + uint256 signature_algorithm ) public view override returns (bool) { return - IVerifier(verifiers[proof.signature_algorithm]).verifyProof( + IVerifier(verifiers[signature_algorithm]).verifyProof( proof.a, proof.b, proof.c, @@ -106,7 +110,7 @@ contract ProofOfPassportRegister is IRegister, Ownable { uint(proof.commitment), uint(proof.nullifier), uint(proof.merkle_root), - uint(proof.signature_algorithm) + uint(proof.attestation_id) ] ); } diff --git a/contracts/contracts/ProofOfPassportRegister_dev.sol b/contracts/contracts/ProofOfPassportRegister_dev.sol index c1c17cf9f..01654f5b9 100644 --- a/contracts/contracts/ProofOfPassportRegister_dev.sol +++ b/contracts/contracts/ProofOfPassportRegister_dev.sol @@ -60,6 +60,9 @@ contract ProofOfPassportRegister_dev is IRegister, Ownable { using InternalLeanIMT for LeanIMTData; LeanIMTData internal imt; + // poseidon("E-PASSPORT") + bytes32 public attestationId = bytes32(0x12d57183e0a41615471a14e5a93c87b9db757118c1d7a6a9f73106819d656f24); + mapping(uint256 => bool) public nullifiers; mapping(uint256 => bool) public merkleRootsCreated; mapping(uint256 => address) public verifiers; @@ -69,18 +72,18 @@ contract ProofOfPassportRegister_dev is IRegister, Ownable { transferOwnership(msg.sender); } - function validateProof(RegisterProof calldata proof) external override { + function validateProof(RegisterProof calldata proof, uint256 signature_algorithm) external override { if (!registry.checkRoot(bytes32(proof.merkle_root))) { - revert Register__InvalidMerkleRoot(); + revert("InvalidMerkleRoot"); } if (nullifiers[proof.nullifier]) { - revert Register__YouAreUsingTheSameNullifierTwice(); + revert("YouAreUsingTheSameNullifierTwice"); } - if (verifiers[proof.signature_algorithm] == address(0)) { - revert Register__InvalidSignatureAlgorithm(); + if (bytes32(proof.attestation_id) != attestationId) { + revert("InvalidAttestationId"); } - if (!verifyProof(proof)) { - revert Register__InvalidProof(); + if (!verifyProof(proof, signature_algorithm)) { + revert("InvalidProof"); } nullifiers[proof.nullifier] = true; @@ -95,10 +98,11 @@ contract ProofOfPassportRegister_dev is IRegister, Ownable { } function verifyProof( - RegisterProof calldata proof + RegisterProof calldata proof, + uint256 signature_algorithm ) public view override returns (bool) { return - IVerifier(verifiers[proof.signature_algorithm]).verifyProof( + IVerifier(verifiers[signature_algorithm]).verifyProof( proof.a, proof.b, proof.c, @@ -106,7 +110,7 @@ contract ProofOfPassportRegister_dev is IRegister, Ownable { uint(proof.commitment), uint(proof.nullifier), uint(proof.merkle_root), - uint(proof.signature_algorithm) + uint(proof.attestation_id) ] ); } @@ -160,13 +164,11 @@ contract ProofOfPassportRegister_dev is IRegister, Ownable { verifiers[signature_algorithm] = verifier_address; } - function removeSignatureAlgorithm( - uint256 signature_algorithm - ) external onlyOwner { + function removeSignatureAlgorithm(uint256 signature_algorithm) external onlyOwner { verifiers[signature_algorithm] = address(0); } function devAddCommitment(uint256 commitment) external onlyOwner { _addCommitment(commitment); } -} +} \ No newline at end of file diff --git a/contracts/contracts/interfaces/IRegister.sol b/contracts/contracts/interfaces/IRegister.sol index 614e9f583..7a55ebbbf 100644 --- a/contracts/contracts/interfaces/IRegister.sol +++ b/contracts/contracts/interfaces/IRegister.sol @@ -35,7 +35,7 @@ interface IRegister { uint commitment; uint nullifier; uint merkle_root; - uint signature_algorithm; + uint attestation_id; uint[2] a; uint[2][2] b; uint[2] c; @@ -43,13 +43,14 @@ interface IRegister { /// @notice Validates a Register proof /// @param proof The Register proof to validate - function validateProof(RegisterProof calldata proof) external; + function validateProof(RegisterProof calldata proof, uint256 signature_algorithm) external; /// @notice Verifies a Register proof /// @param proof The Register proof to verify /// @return bool Returns true if the proof is valid, false otherwise function verifyProof( - RegisterProof calldata proof + RegisterProof calldata proof, + uint256 signature_algorithm ) external view returns (bool); /// @notice Checks if a given root is valid diff --git a/contracts/test/RegisterAndDisclose.ts b/contracts/test/RegisterAndDisclose.ts index 8f5a1f637..23a6e4a4d 100644 --- a/contracts/test/RegisterAndDisclose.ts +++ b/contracts/test/RegisterAndDisclose.ts @@ -2,13 +2,14 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect, assert } from "chai"; import { ethers } from "hardhat"; import { mockPassportData_sha256WithRSAEncryption_65537 } from "../../common/src/utils/mockPassportData"; -import { countryCodes } from "../../common/src/constants/constants"; +import { countryCodes, PASSPORT_ATTESTATION_ID } from "../../common/src/constants/constants"; import { formatRoot, getCurrentDateYYMMDD } from "../../common/src/utils/utils"; import { groth16 } from 'snarkjs' import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import axios from 'axios'; import { revealBitmapFromMapping } from "../../common/src/utils/revealBitmap"; import { generateCircuitInputsRegister, generateCircuitInputsDisclose } from "../../common/src/utils/generateInputs"; +import { formatCallData_disclose, formatCallData_register } from "../../common/src/utils/formatCallData"; import fs from 'fs'; import { IMT, LeanIMT } from "@zk-kit/imt"; import { poseidon2 } from "poseidon-lite"; @@ -36,7 +37,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () let bitmap, scope, user_address, majority, user_identifier, current_date, 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 secret: string = BigInt(0).toString(); - let attestation_id: string = BigInt(0).toString(); + let attestation_id: string = PASSPORT_ATTESTATION_ID; before( async function generateProof() { @@ -114,10 +115,15 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () await verifier_disclose.waitForDeployment(); console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`); - await register.addSignatureAlgorithm(0, verifier_register.target); // dev function - will not be deployed in production + await register.addSignatureAlgorithm(1, verifier_register.target); // dev function - will not be deployed in production SBT = await ethers.getContractFactory("SBT"); - sbt = await SBT.deploy(verifier_disclose.target, formatter.target, register.target, deployOptions); + 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}`); } @@ -160,20 +166,12 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () const rawCallData = await groth16.exportSolidityCallData(proof, publicSignals); parsedCallData_register = JSON.parse(`[${rawCallData}]`); - formattedCallData_register = { - commitment: parsedCallData_register[3][0], - nullifier: parsedCallData_register[3][1], - merkle_root: parsedCallData_register[3][2], - signature_algorithm: parsedCallData_register[3][3], - a: parsedCallData_register[0], - b: [parsedCallData_register[1][0], parsedCallData_register[1][1]], - c: parsedCallData_register[2], - }; + formattedCallData_register = formatCallData_register(parsedCallData_register) // Set fake commitments into the tree const commitments = [1, 2, 3]; for (const commitment of commitments) { - await register.dev_add_commitment(commitment); // this is a dev function and will not be deplyed in production + await register.devAddCommitment(commitment); // this is a dev function and will not be deplyed in production imt.insert(BigInt(commitment)); } }); @@ -186,16 +184,25 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () it("Register with a wrong proof should fail - Register", async function () { await expect(register - .validateProof({ ...formattedCallData_register, a: [0, 0] })) + .validateProof({ ...formattedCallData_register, a: [0, 0] }, 1)) .to.be.revertedWith("Register__InvalidProof()") .catch(error => { assert(error.message.includes("Register__InvalidProof()"), "Expected revert with Register__InvalidProof(), but got another error"); }); }); + it("Register with a wrong attestation id should fail - Register", async function () { + await expect(register + .validateProof({ ...formattedCallData_register, attestation_id: "10" }, 1)) + .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 signature algorithm should fail - Register", async function () { await expect(register - .validateProof({ ...formattedCallData_register, signature_algorithm: 10 })) + .validateProof({ ...formattedCallData_register}, 2)) .to.be.revertedWith("Register__InvalidSignatureAlgorithm()") .catch(error => { assert(error.message.includes("Register__InvalidSignatureAlgorithm()"), "Expected revert with Register__InvalidSignatureAlgorithm(), but got another error"); @@ -204,7 +211,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () it("Register with a wrong merkle root should fail - Register", async function () { await expect(register - .validateProof({ ...formattedCallData_register, merkle_root: 0 })) + .validateProof({ ...formattedCallData_register, merkle_root: 0 }, 1)) .to.be.revertedWith("Register__InvalidMerkleRoot()") .catch(error => { assert(error.message.includes("Register__InvalidMerkleRoot()"), "Expected revert with Register__InvalidMerkleRoot(), but got another error"); @@ -213,7 +220,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () it("Register should succeed - Register", async function () { expect(await register - .validateProof(formattedCallData_register)).not.to.be.reverted; + .validateProof(formattedCallData_register, 1)).not.to.be.reverted; imt.insert(BigInt(formattedCallData_register.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}`); @@ -225,7 +232,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () it("Register with the same proof should fail - Register", async function () { await expect(register - .validateProof(formattedCallData_register)) + .validateProof(formattedCallData_register, 1)) .to.be.revertedWith("Register__YouAreUsingTheSameNullifierTwice()") .catch(error => { assert(error.message.includes("Register__YouAreUsingTheSameNullifierTwice()"), "Expected revert with Register__YouAreUsingTheSameNullifierTwice(), but got another error"); @@ -245,7 +252,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () // refactor in generate inputs function bitmap = Array(90).fill("1"); - scope = BigInt(5).toString(); + scope = BigInt(1).toString(); user_address = await thirdAccount.getAddress(); majority = ["1", "8"]; input_disclose = generateCircuitInputsDisclose( @@ -278,18 +285,8 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function () 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 = { - nullifier: parsedCallData_disclose[3][0], - revealedData_packed: [parsedCallData_disclose[3][1], parsedCallData_disclose[3][2], parsedCallData_disclose[3][3]], - attestation_id: parsedCallData_disclose[3][4], - merkle_root: parsedCallData_disclose[3][5], - scope: parsedCallData_disclose[3][6], - current_date: [parsedCallData_disclose[3][7], parsedCallData_disclose[3][8], parsedCallData_disclose[3][9], parsedCallData_disclose[3][10], parsedCallData_disclose[3][11], parsedCallData_disclose[3][12]], - user_identifier: parsedCallData_disclose[3][13], - a: parsedCallData_disclose[0], - b: [parsedCallData_disclose[1][0], parsedCallData_disclose[1][1]], - c: parsedCallData_disclose[2], - }; + formattedCallData_disclose = formatCallData_disclose(parsedCallData_disclose); + }) it("SBT mint should fail with a wrong current date - SBT", async function () { await expect(sbt.mint({ ...formattedCallData_disclose, current_date: [2, 4, 0, 1, 0, 1] }))