Feat/eu id contracts (#555)

* add eu id support

* add ofac and disclosure euid support

* add contract support for euid cards

* update contracts

* add comment out to remember the interface what we need to implement

---------

Co-authored-by: turnoffthiscomputer <colin.remi07@gmail.com>
This commit is contained in:
nicoshark
2025-05-31 05:00:49 +09:00
committed by GitHub
parent 5d01e29bf4
commit fb99534de8
11 changed files with 1057 additions and 569 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -14,5 +14,5 @@ library AttestationId {
* Here it is hardcoded as bytes32(uint256(1)) for demonstration purposes.
*/
bytes32 constant E_PASSPORT = bytes32(uint256(1));
bytes32 constant ID_CARD = bytes32(uint256(2));
bytes32 constant EU_ID_CARD = bytes32(uint256(2));
}

View File

@@ -0,0 +1,126 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/**
* @title Circuit Constants Library
* @notice This library defines constants representing indices used to access public signals
* of various circuits such as register, DSC, and VC/Disclose.
* @dev These indices map directly to specific data fields in the corresponding circuits proofs.
*/
library CircuitConstantsV2 {
// ---------------------------
// Register Circuit Constants
// ---------------------------
/**
* @notice Index to access the nullifier in the register circuit public signals.
*/
uint256 constant REGISTER_NULLIFIER_INDEX = 0;
/**
* @notice Index to access the commitment in the register circuit public signals.
*/
uint256 constant REGISTER_COMMITMENT_INDEX = 1;
/**
* @notice Index to access the Merkle root in the register circuit public signals.
*/
uint256 constant REGISTER_MERKLE_ROOT_INDEX = 2;
// ---------------------------
// DSC Circuit Constants
// ---------------------------
/**
* @notice Index to access the tree leaf in the DSC circuit public signals.
*/
uint256 constant DSC_TREE_LEAF_INDEX = 0;
/**
* @notice Index to access the CSCA root in the DSC circuit public signals.
*/
uint256 constant DSC_CSCA_ROOT_INDEX = 1;
// -------------------------------------
// VC and Disclose Circuit Constants
// -------------------------------------
/**
* @notice Index to access the packed revealed data in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_REVEALED_DATA_PACKED_INDEX = 0;
/**
* @notice Index to access the forbidden countries list (packed) in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_FORBIDDEN_COUNTRIES_LIST_PACKED_INDEX = 3;
/**
* @notice Index to access the nullifier in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_NULLIFIER_INDEX = 7;
/**
* @notice Index to access the attestation ID in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_ATTESTATION_ID_INDEX = 8;
/**
* @notice Index to access the Merkle root in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_MERKLE_ROOT_INDEX = 9;
/**
* @notice Index to access the current date in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_CURRENT_DATE_INDEX = 10;
/**
* @notice Index to access the passport number SMT root in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_PASSPORT_NO_SMT_ROOT_INDEX = 16;
/**
* @notice Index to access the name and date of birth SMT root in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_NAME_DOB_SMT_ROOT_INDEX = 17;
/**
* @notice Index to access the name and year of birth SMT root in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_NAME_YOB_SMT_ROOT_INDEX = 18;
/**
* @notice Index to access the scope in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_SCOPE_INDEX = 19;
/**
* @notice Index to access the user identifier in the VC and Disclose circuit public signals.
*/
uint256 constant PASSPORT_DISCLOSE_USER_IDENTIFIER_INDEX = 20;
// From here, shows index of id card
uint256 constant ID_CARD_DISCLOSE_REVEALED_DATA_PACKED_INDEX = 0;
uint256 constant ID_CARD_DISCLOSE_FORBIDDEN_COUNTRIES_LIST_PACKED_INDEX = 4;
uint256 constant ID_CARD_DISCLOSE_NULLIFIER_INDEX = 8;
uint256 constant ID_CARD_DISCLOSE_ATTESTATION_ID_INDEX = 9;
uint256 constant ID_CARD_DISCLOSE_MERKLE_ROOT_INDEX = 10;
uint256 constant ID_CARD_DISCLOSE_CURRENT_DATE_INDEX = 11;
uint256 constant ID_CARD_DISCLOSE_NAME_DOB_SMT_ROOT_INDEX = 17;
uint256 constant ID_CARD_DISCLOSE_NAME_YOB_SMT_ROOT_INDEX = 18;
uint256 constant ID_CARD_DISCLOSE_SCOPE_INDEX = 19;
uint256 constant ID_CARD_DISCLOSE_USER_IDENTIFIER_INDEX = 20;
}

View File

@@ -50,32 +50,14 @@ interface IIdentityVerificationHubV2 {
uint256[4] forbiddenCountriesListPacked;
}
/**
* @notice Structure representing human-readable revealed data after unpacking.
* @param issuingState The issuing state as a string.
* @param name Array of strings representing the passport holder's name.
* @param passportNumber The passport number.
* @param nationality The nationality.
* @param dateOfBirth Formatted date of birth.
* @param gender The gender.
* @param expiryDate Formatted expiration date.
* @param olderThan The verified "older than" age.
* @param passportNoOfac The passport number OFAC verification result.
* @param nameAndDobOfac The name and date of birth OFAC verification result.
* @param nameAndYobOfac The name and year of birth OFAC verification result.
*/
struct ReadableRevealedData {
string issuingState;
string[] name;
string passportNumber;
string nationality;
string dateOfBirth;
string gender;
string expiryDate;
uint256 olderThan;
uint256 passportNoOfac;
uint256 nameAndDobOfac;
uint256 nameAndYobOfac;
struct IdCardVcAndDiscloseVerificationResult {
uint256 attestationId;
uint256 scope;
uint256 userIdentifier;
uint256 nullifier;
uint256 identityCommitmentRoot;
uint256[4] revealedDataPacked;
uint256[4] forbiddenCountriesListPacked;
}
/**
@@ -96,6 +78,15 @@ interface IIdentityVerificationHubV2 {
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof vcAndDiscloseProof;
}
struct IdCardVcAndDiscloseHubProof {
bool olderThanEnabled;
uint256 olderThan;
bool forbiddenCountriesEnabled;
uint256[4] forbiddenCountriesListPacked;
bool[2] ofacEnabled;
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof vcAndDiscloseProof;
}
/**
* @notice Verifies a VC and Disclose proof.
* @dev Checks the provided proof against verification configuration and returns key result data.
@@ -110,52 +101,27 @@ interface IIdentityVerificationHubV2 {
returns (VcAndDiscloseVerificationResult memory result);
/**
* @notice Converts packed revealed data into a human-readable format.
* @dev Uses an array of RevealedDataType to determine which attributes to extract from the packed data.
* @param revealedDataPacked An array of three uint256 containing the packed data.
* @param types An array of RevealedDataType indicating the order of attributes.
* @return readableData The decoded and formatted revealed data.
* @notice Verifies a EU ID Card VC and Disclose proof.
* @dev Checks the provided proof against verification configuration and returns key result data.
* @param proof The hub proof containing configuration flags and the underlying VC and Disclose proof.
* @return result The verification result including attestationId, scope, userIdentifier, nullifier, identityCommitmentRoot, revealed data, and forbidden countries list.
*/
function getReadableRevealedData(
uint256[3] memory revealedDataPacked,
RevealedDataType[] memory types
function verifyEuIdVcAndDisclose(
IdCardVcAndDiscloseHubProof memory proof
)
external
view
returns (ReadableRevealedData memory readableData);
/**
* @notice Retrieves a human-readable list of forbidden countries.
* @dev Converts the packed forbidden countries list into a fixed-size array of strings.
* @param forbiddenCountriesListPacked The packed representation of forbidden countries.
* @return forbiddenCountries A fixed-size array (length defined by CircuitConstants.MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH) of strings representing forbidden countries.
*/
function getReadableForbiddenCountries(
uint256[4] memory forbiddenCountriesListPacked
)
external
view
returns (string[40] memory forbiddenCountries);
returns (IdCardVcAndDiscloseVerificationResult memory result);
/**
* @notice Registers a passport commitment using a register circuit proof.
* @dev Verifies the register circuit proof before registering the passport commitment.
* @param registerCircuitVerifierId The identifier for the register circuit verifier to be used.
* @param registerCircuitProof The proof data for the register circuit.
* @dev Verifies the proof and then calls the Identity Registry to register the commitment.
* @param attestationId The attestation identifier.
* @param registerCircuitVerifierId The identifier for the register circuit verifier to use.
* @param registerCircuitProof The register circuit proof data.
*/
function registerPassportCommitment(
uint256 registerCircuitVerifierId,
IRegisterCircuitVerifier.RegisterCircuitProof memory registerCircuitProof
)
external;
/**
* @notice Registers an Id Card commitment using a register circuit proof.
* @dev Verifies the register circuit proof before registering the Id Card commitment.
* @param registerCircuitVerifierId The identifier for the register circuit verifier to be used.
* @param registerCircuitProof The proof data for the register circuit.
*/
function registerIdCardCommitment(
function registerCommitment(
bytes32 attestationId,
uint256 registerCircuitVerifierId,
IRegisterCircuitVerifier.RegisterCircuitProof memory registerCircuitProof
)
@@ -164,45 +130,30 @@ interface IIdentityVerificationHubV2 {
/**
* @notice Registers a DSC key commitment using a DSC circuit proof.
* @dev Verifies the DSC circuit proof before registering the DSC key commitment.
* @param attestationId The attestation identifier.
* @param dscCircuitVerifierId The identifier for the DSC circuit verifier to be used.
* @param dscCircuitProof The proof data for the DSC circuit.
*/
function registerDscKeyCommitment(
bytes32 attestationId,
uint256 dscCircuitVerifierId,
IDscCircuitVerifier.DscCircuitProof memory dscCircuitProof
)
external;
/**
* @notice Registers an Id Card DSC key commitment using a DSC circuit proof.
* @dev Verifies the DSC proof and then calls the Id Card Identity Registry to register the dsc key commitment.
* @param dscCircuitVerifierId The identifier for the DSC circuit verifier to use.
* @param dscCircuitProof The DSC circuit proof data.
*/
function registerIdCardDscKeyCommitment(
uint256 dscCircuitVerifierId,
IDscCircuitVerifier.DscCircuitProof memory dscCircuitProof
)
external;
/**
* @notice Returns the address of the Identity Registry.
* @notice Returns the address of the Identity Registry for a specific attestation type.
* @param attestationId The attestation identifier.
* @return registryAddr The address of the Identity Registry contract.
*/
function registry() external view returns (address registryAddr);
function registry(bytes32 attestationId) external view returns (address registryAddr);
/**
* @notice Returns the address of the Identity Registry for Id Cards.
* @return registryIdCardAddr The address of the Identity Registry for Id Cards.
*/
function registryIdCard() external view returns (address registryIdCardAddr);
/**
* @notice Returns the address of the VC and Disclose circuit verifier.
* @notice Returns the address of the VC and Disclose circuit verifier for a specific attestation type.
* @param attestationId The attestation identifier.
* @return verifierAddr The address of the VC and Disclose circuit verifier.
*/
function vcAndDiscloseCircuitVerifier() external view returns (address verifierAddr);
function vcAndDiscloseCircuitVerifier(bytes32 attestationId) external view returns (address verifierAddr);
/**
* @notice Retrieves the register circuit verifier for a given signature type.
@@ -229,27 +180,68 @@ interface IIdentityVerificationHubV2 {
returns (address verifier);
/**
* @notice Retrieves the register circuit verifier for a given signature type for Id Cards.
* @param typeId The signature type identifier.
* @return verifier The address of the register circuit verifier.
* @notice Updates the registry address.
* @param attestationId The attestation identifier.
* @param registryAddress The new registry address.
*/
function sigTypeToRegisterCircuitVerifiersIdCard(
uint256 typeId
function updateRegistry(
bytes32 attestationId,
address registryAddress
)
external
view
returns (address verifier);
external;
/**
* @notice Retrieves the DSC circuit verifier for a given signature type for Id Cards.
* @param typeId The signature type identifier.
* @return verifier The address of the DSC circuit verifier.
* @notice Updates the VC and Disclose circuit verifier address.
* @param attestationId The attestation identifier.
* @param vcAndDiscloseCircuitVerifierAddress The new VC and Disclose circuit verifier address.
*/
function sigTypeToDscCircuitVerifiersIdCard(
uint256 typeId
function updateVcAndDiscloseCircuit(
bytes32 attestationId,
address vcAndDiscloseCircuitVerifierAddress
)
external
view
returns (address verifier);
external;
}
/**
* @notice Updates the register circuit verifier for a specific signature type.
* @param typeId The signature type identifier.
* @param verifierAddress The new register circuit verifier address.
*/
function updateRegisterCircuitVerifier(
uint256 typeId,
address verifierAddress
)
external;
/**
* @notice Updates the DSC circuit verifier for a specific signature type.
* @param typeId The signature type identifier.
* @param verifierAddress The new DSC circuit verifier address.
*/
function updateDscVerifier(
uint256 typeId,
address verifierAddress
)
external;
/**
* @notice Batch updates register circuit verifiers.
* @param typeIds An array of signature type identifiers.
* @param verifierAddresses An array of new register circuit verifier addresses.
*/
function batchUpdateRegisterCircuitVerifiers(
uint256[] calldata typeIds,
address[] calldata verifierAddresses
)
external;
/**
* @notice Batch updates DSC circuit verifiers.
* @param typeIds An array of signature type identifiers.
* @param verifierAddresses An array of new DSC circuit verifier addresses.
*/
function batchUpdateDscCircuitVerifiers(
uint256[] calldata typeIds,
address[] calldata verifierAddresses
)
external;
}

View File

@@ -124,6 +124,31 @@ library Formatter {
return bytesArray;
}
function fieldElementsToBytesIdCard(
uint256[4] memory publicSignals
) internal pure returns (bytes memory) {
if (
publicSignals[0] >= SNARK_SCALAR_FIELD ||
publicSignals[1] >= SNARK_SCALAR_FIELD ||
publicSignals[2] >= SNARK_SCALAR_FIELD ||
publicSignals[3] >= SNARK_SCALAR_FIELD
) {
revert InvalidFieldElement();
}
uint8[4] memory bytesCount = [31, 31, 31, 1];
bytes memory bytesArray = new bytes(94);
uint256 index = 0;
for (uint256 i = 0; i < 4; i++) {
uint256 element = publicSignals[i];
for (uint8 j = 0; j < bytesCount[i]; j++) {
bytesArray[index++] = bytes1(uint8(element & 0xff));
element = element >> 8;
}
}
return bytesArray;
}
/**
* @notice Extracts forbidden country codes from a packed uint256.
* @dev Each forbidden country is represented by 3 bytes in the packed data.

View File

@@ -0,0 +1,198 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {CircuitConstants} from "../constants/CircuitConstants.sol";
import {Formatter} from "./Formatter.sol";
/**
* @title CircuitAttributeHandler Library
* @notice Provides functions for extracting and formatting passport attributes from a byte array.
* @dev Utilizes the Formatter library for converting and formatting specific fields.
*/
library IdCardAttributeHandler {
/**
* @dev Reverts when the provided character codes array does not contain enough data to extract an attribute.
*/
error INSUFFICIENT_CHARCODE_LEN();
// Define constant start and end positions for each attribute
uint256 private constant ISSUING_STATE_START = 2;
uint256 private constant ISSUING_STATE_END = 4;
uint256 private constant NAME_START = 60;
uint256 private constant NAME_END = 89;
uint256 private constant ID_CARD_NUMBER_START = 5;
uint256 private constant ID_CARD_NUMBER_END = 13;
uint256 private constant NATIONALITY_START = 45;
uint256 private constant NATIONALITY_END = 47;
uint256 private constant DATE_OF_BIRTH_START = 30;
uint256 private constant DATE_OF_BIRTH_END = 35;
uint256 private constant GENDER_START = 37;
uint256 private constant GENDER_END = 37;
uint256 private constant EXPIRY_DATE_START = 38;
uint256 private constant EXPIRY_DATE_END = 43;
uint256 private constant OLDER_THAN_START = 90;
uint256 private constant OLDER_THAN_END = 91;
uint256 private constant OFAC_START = 92;
uint256 private constant OFAC_END = 92;
/**
* @notice Retrieves the issuing state from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return A string representing the issuing state.
*/
function getIssuingState(bytes memory charcodes) internal pure returns (string memory) {
return extractStringAttribute(charcodes, ISSUING_STATE_START, ISSUING_STATE_END);
}
/**
* @notice Retrieves and formats the name from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return A string array with the formatted name parts.
*/
function getName(bytes memory charcodes) internal pure returns (string[] memory) {
return Formatter.formatName(extractStringAttribute(charcodes, NAME_START, NAME_END));
}
/**
* @notice Retrieves the passport number from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The passport number as a string.
*/
function getPassportNumber(bytes memory charcodes) internal pure returns (string memory) {
return extractStringAttribute(charcodes, ID_CARD_NUMBER_START, ID_CARD_NUMBER_END);
}
/**
* @notice Retrieves the nationality from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The nationality as a string.
*/
function getNationality(bytes memory charcodes) internal pure returns (string memory) {
return extractStringAttribute(charcodes, NATIONALITY_START, NATIONALITY_END);
}
/**
* @notice Retrieves and formats the date of birth from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The formatted date of birth as a string.
*/
function getDateOfBirth(bytes memory charcodes) internal pure returns (string memory) {
return Formatter.formatDate(extractStringAttribute(charcodes, DATE_OF_BIRTH_START, DATE_OF_BIRTH_END));
}
/**
* @notice Retrieves the gender from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The gender as a string.
*/
function getGender(bytes memory charcodes) internal pure returns (string memory) {
return extractStringAttribute(charcodes, GENDER_START, GENDER_END);
}
/**
* @notice Retrieves and formats the passport expiry date from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The formatted passport expiry date as a string.
*/
function getExpiryDate(bytes memory charcodes) internal pure returns (string memory) {
return Formatter.formatDate(extractStringAttribute(charcodes, EXPIRY_DATE_START, EXPIRY_DATE_END));
}
/**
* @notice Retrieves the 'older than' age attribute from the encoded attribute byte array.
* @dev Converts two consecutive numeric ASCII characters to a uint256.
* @param charcodes The byte array containing passport attribute data.
* @return The extracted age as a uint256.
*/
function getOlderThan(bytes memory charcodes) internal pure returns (uint256) {
return Formatter.numAsciiToUint(uint8(charcodes[OLDER_THAN_START])) * 10
+ Formatter.numAsciiToUint(uint8(charcodes[OLDER_THAN_START + 1]));
}
/**
* @notice Retrieves the passport number OFAC status from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The OFAC status for passport number check as a uint256.
*/
function getPassportNoOfac(bytes memory charcodes) internal pure returns (uint256) {
return uint8(charcodes[OFAC_START]);
}
/**
* @notice Retrieves the name and date of birth OFAC status from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The OFAC status for name and DOB check as a uint256.
*/
function getNameAndDobOfac(bytes memory charcodes) internal pure returns (uint256) {
return uint8(charcodes[OFAC_START + 1]);
}
/**
* @notice Retrieves the name and year of birth OFAC status from the encoded attribute byte array.
* @param charcodes The byte array containing passport attribute data.
* @return The OFAC status for name and YOB check as a uint256.
*/
function getNameAndYobOfac(bytes memory charcodes) internal pure returns (uint256) {
return uint8(charcodes[OFAC_START + 2]);
}
/**
* @notice Performs selective OFAC checks based on provided flags.
* @param charcodes The byte array containing passport attribute data.
* @param checkNameAndDob Whether to check the name and date of birth OFAC status.
* @param checkNameAndYob Whether to check the name and year of birth OFAC status.
* @return True if all enabled checks pass (equal 1), false if any enabled check fails.
* @dev Checks are only performed for flags that are set to true. If a flag is false,
* that particular check is considered to have passed regardless of its actual value.
*/
function compareOfac(
bytes memory charcodes,
bool checkNameAndDob,
bool checkNameAndYob
) internal pure returns (bool) {
return (!checkNameAndDob || getNameAndDobOfac(charcodes) == 1) &&
(!checkNameAndYob || getNameAndYobOfac(charcodes) == 1);
}
/**
* @notice Compares the extracted 'older than' value with a provided threshold.
* @param charcodes The byte array containing passport attribute data.
* @param olderThan The threshold value to compare against.
* @return True if the extracted age is greater than or equal to the threshold, false otherwise.
*/
function compareOlderThan(
bytes memory charcodes,
uint256 olderThan
) internal pure returns (bool) {
return getOlderThan(charcodes) >= olderThan;
}
/**
* @notice Extracts a substring from a specified range in the byte array.
* @dev Reverts with INSUFFICIENT_CHARCODE_LEN if the byte array's length is insufficient.
* @param charcodes The byte array containing the encoded passport attribute.
* @param start The starting index (inclusive) of the attribute in the byte array.
* @param end The ending index (inclusive) of the attribute in the byte array.
* @return The extracted attribute as a string.
*/
function extractStringAttribute(bytes memory charcodes, uint256 start, uint256 end) internal pure returns (string memory) {
if (charcodes.length <= end) {
revert INSUFFICIENT_CHARCODE_LEN();
}
bytes memory attributeBytes = new bytes(end - start + 1);
for (uint256 i = start; i <= end; i++) {
attributeBytes[i - start] = charcodes[i];
}
return string(attributeBytes);
}
}

View File

@@ -0,0 +1,33 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
import { artifacts } from "hardhat";
import { ethers } from "ethers";
export default buildModule("DeployIdCardRegistryModule", (m) => {
const poseidonT3 = m.library("PoseidonT3");
const identityRegistryIdCardImpl = m.contract("IdentityRegistryIdCardImplV1", [], {
libraries: { PoseidonT3: poseidonT3 },
});
const registryInterface = getRegistryInitializeData();
const registryInitData = registryInterface.encodeFunctionData("initialize", [
"0x0000000000000000000000000000000000000000"
]);
const idCardRegistry = m.contract("IdentityRegistryIdCard", [
identityRegistryIdCardImpl,
registryInitData
]);
return {
poseidonT3,
identityRegistryIdCardImpl,
idCardRegistry
};
});
function getRegistryInitializeData() {
const registryArtifact = artifacts.readArtifactSync("IdentityRegistryIdCardImplV1");
const registryInterface = new ethers.Interface(registryArtifact.abi);
return registryInterface;
}

View File

@@ -0,0 +1,14 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
/**
* This module deploys the ID Card Verifier contract specifically for register_id
* with SHA256+SHA256+SHA256+RSA verifier
*/
export default buildModule("DeployIdCardVerifier", (m) => {
// Deploy the ID Card Verifier contract
const idCardVerifier = m.contract("Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096");
return {
idCardVerifier,
};
});

View File

@@ -0,0 +1,35 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
import { artifacts, ethers } from "hardhat";
import hre from "hardhat";
function getHubImplV2InitializeData() {
const hubArtifact = artifacts.readArtifactSync("IdentityVerificationHubImplV2");
return new ethers.Interface(hubArtifact.abi);
}
export default buildModule("DeployV2", (m) => {
const identityVerificationHubImplV2 = m.contract("IdentityVerificationHubImplV2");
const hubInterface = getHubImplV2InitializeData();
// Initialize with empty values as per instructions
const initializeData = hubInterface.encodeFunctionData("initialize", [
[], // attestationIds
[], // registryAddresses
[], // vcAndDiscloseCircuitVerifierAddresses
[], // registerCircuitVerifierIds
[], // registerCircuitVerifierAddresses
[], // dscCircuitVerifierIds
[] // dscCircuitVerifierAddresses
]);
const hub = m.contract("IdentityVerificationHub", [
identityVerificationHubImplV2,
initializeData
]);
return {
hub,
identityVerificationHubImplV2,
};
});

View File

@@ -34,43 +34,45 @@ import { ethers } from "ethers";
// 0x034acfcc - REGISTERED_COMMITMENT()
const errorSignatures = [
"InvalidProof()",
"AlreadyClaimed()",
"NotRegistered(address nonRegisteredAddress)",
"RegistrationNotOpen()",
"RegistrationNotClosed()",
"ClaimNotOpen()",
"INSUFFICIENT_CHARCODE_LEN()",
"InvalidDateLength()",
"InvalidAsciiCode()",
"InvalidYearRange()",
"InvalidMonthRange()",
"InvalidDayRange()",
"InvalidFieldElement()",
"InvalidDateDigit()",
"LENGTH_MISMATCH()",
"NO_VERIFIER_SET()",
"CURRENT_DATE_NOT_IN_VALID_RANGE()",
"INVALID_OLDER_THAN()",
"INVALID_FORBIDDEN_COUNTRIES()",
"INVALID_OFAC()",
"INVALID_REGISTER_PROOF()",
"INVALID_DSC_PROOF()",
"INVALID_VC_AND_DISCLOSE_PROOF()",
"INVALID_COMMITMENT_ROOT()",
"INVALID_OFAC_ROOT()",
"INVALID_CSCA_ROOT()",
"INVALID_REVEALED_DATA_TYPE()",
"HUB_NOT_SET()",
"ONLY_HUB_CAN_ACCESS()",
"REGISTERED_COMMITMENT()",
"RegisteredNullifier()",
'InvalidProof()',
'AlreadyClaimed()',
'NotRegistered(address nonRegisteredAddress)',
'RegistrationNotOpen()',
'RegistrationNotClosed()',
'ClaimNotOpen()',
'INSUFFICIENT_CHARCODE_LEN()',
'InvalidDateLength()',
'InvalidAsciiCode()',
'InvalidYearRange()',
'InvalidMonthRange()',
'InvalidDayRange()',
'InvalidFieldElement()',
'InvalidDateDigit()',
'LENGTH_MISMATCH()',
'NO_VERIFIER_SET()',
'CURRENT_DATE_NOT_IN_VALID_RANGE()',
'INVALID_OLDER_THAN()',
'INVALID_FORBIDDEN_COUNTRIES()',
'INVALID_OFAC()',
'INVALID_REGISTER_PROOF()',
'INVALID_DSC_PROOF()',
'INVALID_VC_AND_DISCLOSE_PROOF()',
'INVALID_COMMITMENT_ROOT()',
'INVALID_OFAC_ROOT()',
'INVALID_CSCA_ROOT()',
'INVALID_REVEALED_DATA_TYPE()',
'HUB_NOT_SET()',
'ONLY_HUB_CAN_ACCESS()',
'REGISTERED_COMMITMENT()',
'RegisteredNullifier()',
'INVALID_ATTESTATION_ID()'
];
errorSignatures.forEach((sig) => {
// Pls input the error code
const errorCode = "0x22cbc6a2";
const selector = ethers.id(sig).slice(0, 10);
console.log("selector: ", selector);
if (selector === errorCode) {
console.log(`Found matching error: ${sig}`);
}

View File

@@ -0,0 +1,216 @@
import { ethers } from "ethers";
import * as dotenv from "dotenv";
import * as fs from "fs";
import * as path from "path";
import { RegisterVerifierId, DscVerifierId } from "../../common/src/constants/constants";
dotenv.config();
// Define AttestationId constants directly based on values from AttestationId.sol
const AttestationId = {
// Pad with zeros to create full 32 bytes length
E_PASSPORT: "0x0000000000000000000000000000000000000000000000000000000000000001",
EU_ID_CARD: "0x0000000000000000000000000000000000000000000000000000000000000002",
};
// Debug logs for paths and files
console.log("Current directory:", __dirname);
console.log("Deployed addresses path:", path.join(__dirname, "../ignition/deployments/staging/deployed_addresses.json"));
console.log("Contract ABI path:", path.join(__dirname, "../ignition/deployments/staging/artifacts/DeployV2#IdentityVerificationHubImplV2.json"));
// Debug logs for environment variables (redacted for security)
console.log("CELO_RPC_URL configured:", !!process.env.CELO_ALFAJORES_RPC_URL);
console.log("CELO_KEY configured:", !!process.env.CELO_KEY);
try {
const deployedAddresses = JSON.parse(fs.readFileSync(path.join(__dirname, "../ignition/deployments/staging/deployed_addresses.json"), "utf-8"));
console.log("Deployed addresses loaded:", deployedAddresses);
const identityVerificationHubAbiFile = fs.readFileSync(path.join(__dirname, "../ignition/deployments/staging/artifacts/DeployV2#IdentityVerificationHubImplV2.json"), "utf-8");
console.log("ABI file loaded");
const identityVerificationHubAbi = JSON.parse(identityVerificationHubAbiFile).abi;
console.log("ABI parsed");
function getContractAddressByPartialName(partialName: string): string | unknown {
for (const [key, value] of Object.entries(deployedAddresses)) {
if (key.includes(partialName)) {
return value;
}
}
return undefined;
}
function getContractAddressByExactName(exactName: string): string | unknown {
if (exactName in deployedAddresses) {
return deployedAddresses[exactName];
}
return undefined;
}
function getAttestationIdBytes32(attestationIdName: string): string {
return AttestationId[attestationIdName as keyof typeof AttestationId];
}
async function main() {
const provider = new ethers.JsonRpcProvider(process.env.CELO_ALFAJORES_RPC_URL as string);
console.log("Provider created");
const wallet = new ethers.Wallet(process.env.CELO_KEY as string, provider);
console.log("Wallet created");
// const hubAddress = deployedAddresses["DeployHub#IdentityVerificationHub"];
const hubAddress = "0xbaB9B3c376e84FEB4aFD9423e3aB278B47d34a0a"; // Update with your actual hub address
console.log("Hub address:", hubAddress);
if (!hubAddress) {
throw new Error("Hub address not found in deployed_addresses.json");
}
const identityVerificationHub = new ethers.Contract(
hubAddress,
identityVerificationHubAbi,
wallet
);
console.log("Contract instance created");
// Update registry addresses for different attestation types
const attestationTypes = ["E_PASSPORT", "EU_ID_CARD"];
for (const attestationType of attestationTypes) {
let registryName: any;
if (attestationType == "E_PASSPORT") {
registryName = "DeployRegistryModule#IdentityRegistry"
} else if (attestationType == "EU_ID_CARD") {
registryName = "DeployIdCardRegistryModule#IdentityRegistryIdCard";
}
const registryAddress = getContractAddressByExactName(registryName);
if (!registryAddress) {
console.log(`Skipping registry update for ${attestationType} because no deployed address was found.`);
continue;
}
console.log(`Updating registry for ${attestationType}`);
const attestationId = getAttestationIdBytes32(attestationType);
try {
const tx = await identityVerificationHub.updateRegistry(
attestationId,
registryAddress
);
const receipt = await tx.wait();
console.log(`Registry for ${attestationType} updated with tx: ${receipt.hash}`);
} catch (error) {
console.error(`Error updating registry for ${attestationType}:`, error);
}
}
// Update VC and Disclose circuit verifiers for different attestation types
for (const attestationType of attestationTypes) {
let verifierName: any;
if (attestationType == "E_PASSPORT") {
verifierName = "DeployAllVerifiers#Verifier_vc_and_disclose";
} else if (attestationType == "EU_ID_CARD") {
verifierName = "";
}
const verifierAddress = getContractAddressByExactName(verifierName);
if (!verifierAddress) {
console.log(`Skipping VC and Disclose circuit update for ${attestationType} because no deployed address was found.`);
continue;
}
console.log(`Updating VC and Disclose circuit for ${attestationType}`);
const attestationId = getAttestationIdBytes32(attestationType);
try {
const tx = await identityVerificationHub.updateVcAndDiscloseCircuit(
attestationId,
verifierAddress
);
const receipt = await tx.wait();
console.log(`VC and Disclose circuit for ${attestationType} updated with tx: ${receipt.hash}`);
} catch (error) {
console.error(`Error updating VC and Disclose circuit for ${attestationType}:`, error);
}
}
// Batch update register circuit verifiers
const registerVerifierKeys = Object.keys(RegisterVerifierId).filter(key => isNaN(Number(key)));
const registerCircuitVerifierIds: number[] = [];
const registerCircuitVerifierAddresses: string[] = [];
for (const key of registerVerifierKeys) {
const verifierName = `Verifier_${key}`;
const verifierAddress = getContractAddressByPartialName(verifierName);
if (!verifierAddress) {
console.log(`Skipping ${verifierName} because no deployed address was found.`);
continue;
}
const verifierId = RegisterVerifierId[key as keyof typeof RegisterVerifierId];
registerCircuitVerifierIds.push(verifierId);
registerCircuitVerifierAddresses.push(verifierAddress as string);
}
if (registerCircuitVerifierIds.length > 0) {
console.log("Batch updating register circuit verifiers");
try {
const tx = await identityVerificationHub.batchUpdateRegisterCircuitVerifiers(
registerCircuitVerifierIds,
registerCircuitVerifierAddresses
);
const receipt = await tx.wait();
console.log(`Register circuit verifiers updated with tx: ${receipt.hash}`);
} catch (error) {
console.error("Error batch updating register circuit verifiers:", error);
}
}
// Batch update DSC circuit verifiers
const dscKeys = Object.keys(DscVerifierId).filter(key => isNaN(Number(key)));
const dscCircuitVerifierIds: number[] = [];
const dscCircuitVerifierAddresses: string[] = [];
for (const key of dscKeys) {
const verifierName = `Verifier_${key}`;
const verifierAddress = getContractAddressByPartialName(verifierName);
if (!verifierAddress) {
console.log(`Skipping ${verifierName} because no deployed address was found.`);
continue;
}
const verifierId = DscVerifierId[key as keyof typeof DscVerifierId];
dscCircuitVerifierIds.push(verifierId);
dscCircuitVerifierAddresses.push(verifierAddress as string);
}
if (dscCircuitVerifierIds.length > 0) {
console.log("Batch updating DSC circuit verifiers");
try {
const tx = await identityVerificationHub.batchUpdateDscCircuitVerifiers(
dscCircuitVerifierIds,
dscCircuitVerifierAddresses
);
const receipt = await tx.wait();
console.log(`DSC circuit verifiers updated with tx: ${receipt.hash}`);
} catch (error) {
console.error("Error batch updating DSC circuit verifiers:", error);
}
}
}
main().catch((error) => {
console.error("Execution error:", error);
process.exitCode = 1;
});
} catch (error) {
console.error("Initial setup error:", error);
process.exitCode = 1;
}