mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
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:
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||
}
|
||||
|
||||
126
contracts/contracts/constants/CircuitConstantsV2.sol
Normal file
126
contracts/contracts/constants/CircuitConstantsV2.sol
Normal 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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
198
contracts/contracts/libraries/IdCardAttributeHandler.sol
Normal file
198
contracts/contracts/libraries/IdCardAttributeHandler.sol
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
33
contracts/ignition/modules/deployIdCardRegistry.ts
Normal file
33
contracts/ignition/modules/deployIdCardRegistry.ts
Normal 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;
|
||||
}
|
||||
14
contracts/ignition/modules/deployIdCardVerifier.ts
Normal file
14
contracts/ignition/modules/deployIdCardVerifier.ts
Normal 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,
|
||||
};
|
||||
});
|
||||
35
contracts/ignition/modules/deployV2.ts
Normal file
35
contracts/ignition/modules/deployV2.ts
Normal 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,
|
||||
};
|
||||
});
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
216
contracts/scripts/setVerifiersV2.ts
Normal file
216
contracts/scripts/setVerifiersV2.ts
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user