diff --git a/contracts/contracts/IdentityVerificationHubImplV2.sol b/contracts/contracts/IdentityVerificationHubImplV2.sol index c04db6a41..37c4be1bd 100644 --- a/contracts/contracts/IdentityVerificationHubImplV2.sol +++ b/contracts/contracts/IdentityVerificationHubImplV2.sol @@ -16,7 +16,6 @@ import {CircuitConstantsV2} from "./constants/CircuitConstantsV2.sol"; import {Formatter} from "./libraries/Formatter.sol"; contract IdentityVerificationHubImplV2 is ImplRoot { - /// @custom:storage-location erc7201:self.storage.IdentityVerificationHub struct IdentityVerificationHubStorage { uint256 _circuitVersion; @@ -29,15 +28,17 @@ contract IdentityVerificationHubImplV2 is ImplRoot { /// @custom:storage-location erc7201:self.storage.IdentityVerificationHubV2 struct IdentityVerificationHubV2Storage { mapping(bytes32 configId => SelfStructs.VerificationConfigV2) _v2VerificationConfigs; - // We should consider to add bridge address - // address bridgeAddress; } + // We should consider to add bridge address + // address bridgeAddress; /// @dev keccak256(abi.encode(uint256(keccak256("self.storage.IdentityVerificationHub")) - 1)) & ~bytes32(uint256(0xff)) - bytes32 private constant IDENTITYVERIFICATIONHUB_STORAGE_LOCATION = 0x2ade7eace21710c689ddef374add52ace9783e33bac626e58e73a9d190173d00; + bytes32 private constant IDENTITYVERIFICATIONHUB_STORAGE_LOCATION = + 0x2ade7eace21710c689ddef374add52ace9783e33bac626e58e73a9d190173d00; /// @dev keccak256(abi.encode(uint256(keccak256("self.storage.IdentityVerificationHubV2")) - 1)) & ~bytes32(uint256(0xff)) - bytes32 private constant IDENTITYVERIFICATIONHUBV2_STORAGE_LOCATION = 0xf9b5980dcec1a8b0609576a1f453bb2cad4732a0ea02bb89154d44b14a306c00; + bytes32 private constant IDENTITYVERIFICATIONHUBV2_STORAGE_LOCATION = + 0xf9b5980dcec1a8b0609576a1f453bb2cad4732a0ea02bb89154d44b14a306c00; /** * @notice Returns the storage struct for the main IdentityVerificationHub. @@ -260,7 +261,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @param config The verification configuration * @return configId The generated config ID */ - function setVerificationConfigV2(SelfStructs.VerificationConfigV2 memory config) external virtual onlyProxy onlyOwner returns (bytes32 configId) { + function setVerificationConfigV2( + SelfStructs.VerificationConfigV2 memory config + ) external virtual onlyProxy onlyOwner returns (bytes32 configId) { configId = generateConfigId(config); IdentityVerificationHubV2Storage storage $v2 = _getIdentityVerificationHubV2Storage(); $v2._v2VerificationConfigs[configId] = config; @@ -275,14 +278,15 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @param baseVerificationInput The base verification input containing header and proof data. * @param userContextData The user context data containing config ID, destination chain ID, user identifier, and additional data. */ - function verify( - bytes calldata baseVerificationInput, - bytes calldata userContextData - ) external virtual onlyProxy { + function verify(bytes calldata baseVerificationInput, bytes calldata userContextData) external virtual onlyProxy { (SelfStructs.HubInputHeader memory header, bytes calldata proofData) = _decodeInput(baseVerificationInput); // Perform verification and get output along with user data - (bytes memory output, uint256 destChainId, bytes memory userDataToPass) = _executeVerificationFlow(header, proofData, userContextData); + (bytes memory output, uint256 destChainId, bytes memory userDataToPass) = _executeVerificationFlow( + header, + proofData, + userContextData + ); // Use destChainId and userDataToPass returned from _executeVerificationFlow _handleVerificationResult(destChainId, output, userDataToPass); @@ -415,7 +419,10 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @param typeId The type ID to query. * @return The register circuit verifier address associated with the attestation ID and type ID. */ - function registerCircuitVerifiers(bytes32 attestationId, uint256 typeId) external view virtual onlyProxy returns (address) { + function registerCircuitVerifiers( + bytes32 attestationId, + uint256 typeId + ) external view virtual onlyProxy returns (address) { IdentityVerificationHubStorage storage $ = _getIdentityVerificationHubStorage(); return $._registerCircuitVerifiers[attestationId][typeId]; } @@ -426,7 +433,10 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @param typeId The type ID to query. * @return The DSC circuit verifier address associated with the attestation ID and type ID. */ - function dscCircuitVerifiers(bytes32 attestationId, uint256 typeId) external view virtual onlyProxy returns (address) { + function dscCircuitVerifiers( + bytes32 attestationId, + uint256 typeId + ) external view virtual onlyProxy returns (address) { IdentityVerificationHubStorage storage $ = _getIdentityVerificationHubStorage(); return $._dscCircuitVerifiers[attestationId][typeId]; } @@ -523,7 +533,12 @@ contract IdentityVerificationHubImplV2 is ImplRoot { { bytes memory config = _getVerificationConfigById(configId); - bytes memory proofOutput = _basicVerification(header, _decodeVcAndDiscloseProof(proofData), userContextData, userIdentifier); + bytes memory proofOutput = _basicVerification( + header, + _decodeVcAndDiscloseProof(proofData), + userContextData, + userIdentifier + ); SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput = CustomVerifier.customVerify( header.attestationId, @@ -572,14 +587,18 @@ contract IdentityVerificationHubImplV2 is ImplRoot { ) internal returns (bytes memory output) { // Scope 1: Basic checks (scope and user identifier) { - CircuitConstantsV2.DiscloseIndices memory indices = CircuitConstantsV2.getDiscloseIndices(header.attestationId); + CircuitConstantsV2.DiscloseIndices memory indices = CircuitConstantsV2.getDiscloseIndices( + header.attestationId + ); _performScopeCheck(header.scope, vcAndDiscloseProof, indices); _performUserIdentifierCheck(userContextData, vcAndDiscloseProof, header.attestationId, indices); } // Scope 2: Root and date checks { - CircuitConstantsV2.DiscloseIndices memory indices = CircuitConstantsV2.getDiscloseIndices(header.attestationId); + CircuitConstantsV2.DiscloseIndices memory indices = CircuitConstantsV2.getDiscloseIndices( + header.attestationId + ); _performRootCheck(header.attestationId, vcAndDiscloseProof, indices); _performCurrentDateCheck(vcAndDiscloseProof, indices); } @@ -589,7 +608,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { // Scope 4: Create and return output { - CircuitConstantsV2.DiscloseIndices memory indices = CircuitConstantsV2.getDiscloseIndices(header.attestationId); + CircuitConstantsV2.DiscloseIndices memory indices = CircuitConstantsV2.getDiscloseIndices( + header.attestationId + ); return _createVerificationOutput(header.attestationId, vcAndDiscloseProof, indices, userIdentifier); } } @@ -603,7 +624,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @param configId The configuration identifier * @return The verification configuration */ - function getVerificationConfigV2(bytes32 configId) internal view virtual onlyProxy returns (SelfStructs.VerificationConfigV2 memory) { + function getVerificationConfigV2( + bytes32 configId + ) internal view virtual onlyProxy returns (SelfStructs.VerificationConfigV2 memory) { IdentityVerificationHubV2Storage storage $v2 = _getIdentityVerificationHubV2Storage(); return $v2._v2VerificationConfigs[configId]; } @@ -800,12 +823,14 @@ contract IdentityVerificationHubImplV2 is ImplRoot { ) internal view { IdentityVerificationHubStorage storage $ = _getIdentityVerificationHubStorage(); - if (!IVcAndDiscloseCircuitVerifier($._discloseVerifiers[attestationId]).verifyProof( - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - )) { + if ( + !IVcAndDiscloseCircuitVerifier($._discloseVerifiers[attestationId]).verifyProof( + vcAndDiscloseProof.a, + vcAndDiscloseProof.b, + vcAndDiscloseProof.c, + vcAndDiscloseProof.pubSignals + ) + ) { revert InvalidVcAndDiscloseProof(); } } @@ -820,7 +845,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @return header The header of the input data. * @return proofData The proof data of the input data. */ - function _decodeInput(bytes calldata baseVerificationInput) internal pure returns (SelfStructs.HubInputHeader memory header, bytes calldata proofData) { + function _decodeInput( + bytes calldata baseVerificationInput + ) internal pure returns (SelfStructs.HubInputHeader memory header, bytes calldata proofData) { if (baseVerificationInput.length < 97) { revert InputTooShort(); } @@ -838,12 +865,13 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @return userIdentifier The user identifier * @return remainingData The remaining data after the first 96 bytes */ - function _decodeUserContextData(bytes calldata userContextData) internal pure returns ( - bytes32 configId, - uint256 destChainId, - uint256 userIdentifier, - bytes calldata remainingData - ) { + function _decodeUserContextData( + bytes calldata userContextData + ) + internal + pure + returns (bytes32 configId, uint256 destChainId, uint256 userIdentifier, bytes calldata remainingData) + { if (userContextData.length < 96) { revert UserContextDataTooShort(); } @@ -922,7 +950,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { // Extract forbidden countries list for (uint256 i = 0; i < 4; i++) { - passportOutput.forbiddenCountriesListPacked[i] = vcAndDiscloseProof.pubSignals[indices.forbiddenCountriesListPackedIndex + i]; + passportOutput.forbiddenCountriesListPacked[i] = vcAndDiscloseProof.pubSignals[ + indices.forbiddenCountriesListPackedIndex + i + ]; } return abi.encode(passportOutput); @@ -957,7 +987,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { // Extract forbidden countries list for (uint256 i = 0; i < 4; i++) { - euIdOutput.forbiddenCountriesListPacked[i] = vcAndDiscloseProof.pubSignals[indices.forbiddenCountriesListPackedIndex + i]; + euIdOutput.forbiddenCountriesListPacked[i] = vcAndDiscloseProof.pubSignals[ + indices.forbiddenCountriesListPackedIndex + i + ]; } return abi.encode(euIdOutput); @@ -969,7 +1001,9 @@ contract IdentityVerificationHubImplV2 is ImplRoot { * @param data The encoded proof data. * @return The decoded VcAndDiscloseProof struct. */ - function _decodeVcAndDiscloseProof(bytes memory data) internal pure returns (IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory) { + function _decodeVcAndDiscloseProof( + bytes memory data + ) internal pure returns (IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory) { return abi.decode(data, (IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof)); } diff --git a/contracts/contracts/abstract/SelfVerificationRoot.sol b/contracts/contracts/abstract/SelfVerificationRoot.sol index c0e0f0d1b..c242c4f04 100644 --- a/contracts/contracts/abstract/SelfVerificationRoot.sol +++ b/contracts/contracts/abstract/SelfVerificationRoot.sol @@ -59,10 +59,7 @@ abstract contract SelfVerificationRoot is ISelfVerificationRoot { * @param identityVerificationHubV2Address The address of the Identity Verification Hub V2 * @param scopeValue The expected proof scope for user registration */ - constructor( - address identityVerificationHubV2Address, - uint256 scopeValue - ) { + constructor(address identityVerificationHubV2Address, uint256 scopeValue) { _identityVerificationHubV2 = IIdentityVerificationHubV2(identityVerificationHubV2Address); _scope = scopeValue; } @@ -95,10 +92,7 @@ abstract contract SelfVerificationRoot is ISelfVerificationRoot { * @custom:data-format userContextData = | 32 bytes configId | 32 bytes destChainId | 32 bytes userIdentifier | data | * @custom:data-format hubData = | 1 bytes contract version | 31 bytes buffer | 32 bytes scope | 32 bytes attestationId | proofData | */ - function verifySelfProof( - bytes calldata proofPayload, - bytes calldata userContextData - ) public { + function verifySelfProof(bytes calldata proofPayload, bytes calldata userContextData) public { // Minimum expected length for proofData: 32 bytes attestationId + proof data if (proofPayload.length < 32) { revert InvalidDataFormat(); @@ -141,16 +135,16 @@ abstract contract SelfVerificationRoot is ISelfVerificationRoot { * @custom:security Only the authorized hub contract can call this function * @custom:flow This function decodes the output and calls the customizable verification hook */ - function onVerificationSuccess( - bytes memory output, - bytes memory userData - ) public { + function onVerificationSuccess(bytes memory output, bytes memory userData) public { // Only allow the identity verification hub V2 to call this function if (msg.sender != address(_identityVerificationHubV2)) { revert UnauthorizedCaller(); } - ISelfVerificationRoot.GenericDiscloseOutputV2 memory genericDiscloseOutput = abi.decode(output, (ISelfVerificationRoot.GenericDiscloseOutputV2)); + ISelfVerificationRoot.GenericDiscloseOutputV2 memory genericDiscloseOutput = abi.decode( + output, + (ISelfVerificationRoot.GenericDiscloseOutputV2) + ); // Call the customizable verification hook customVerificationHook(genericDiscloseOutput, userData); @@ -170,5 +164,4 @@ abstract contract SelfVerificationRoot is ISelfVerificationRoot { ) internal virtual { // Default implementation is empty - override in derived contracts to add custom logic } - } diff --git a/contracts/contracts/example/Airdrop.sol b/contracts/contracts/example/Airdrop.sol index af09fc6e0..2b28f0e46 100644 --- a/contracts/contracts/example/Airdrop.sol +++ b/contracts/contracts/example/Airdrop.sol @@ -1,4 +1,4 @@ -// // SPDX-License-Identifier: MIT + // // SPDX-License-Identifier: MIT // pragma solidity 0.8.28; // import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/contracts/contracts/example/HappyBirthday.sol b/contracts/contracts/example/HappyBirthday.sol index b2253aaa0..9315d60db 100644 --- a/contracts/contracts/example/HappyBirthday.sol +++ b/contracts/contracts/example/HappyBirthday.sol @@ -1,4 +1,4 @@ -// // SPDX-License-Identifier: MIT + // // SPDX-License-Identifier: MIT // pragma solidity 0.8.28; // import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/contracts/example/SelfPassportERC721.sol b/contracts/contracts/example/SelfPassportERC721.sol index 483700db6..7df8611d1 100644 --- a/contracts/contracts/example/SelfPassportERC721.sol +++ b/contracts/contracts/example/SelfPassportERC721.sol @@ -1,4 +1,4 @@ -// // SPDX-License-Identifier: MIT + // // SPDX-License-Identifier: MIT // pragma solidity 0.8.28; // import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; diff --git a/contracts/contracts/interfaces/IIdentityVerificationHubV2.sol b/contracts/contracts/interfaces/IIdentityVerificationHubV2.sol index 5ac81a1c7..cb566af36 100644 --- a/contracts/contracts/interfaces/IIdentityVerificationHubV2.sol +++ b/contracts/contracts/interfaces/IIdentityVerificationHubV2.sol @@ -11,7 +11,6 @@ import {SelfStructs} from "../libraries/SelfStructs.sol"; * @dev Defines all external and public functions from IdentityVerificationHubImplV2. */ interface IIdentityVerificationHubV2 { - // ==================================================== // External Functions // ==================================================== @@ -48,17 +47,16 @@ interface IIdentityVerificationHubV2 { * @param config The verification configuration * @return configId The generated config ID */ - function setVerificationConfigV2(SelfStructs.VerificationConfigV2 memory config) external returns (bytes32 configId); + function setVerificationConfigV2( + SelfStructs.VerificationConfigV2 memory config + ) external returns (bytes32 configId); /** * @notice Main verification function with new structured input format * @param baseVerificationInput The base verification input data * @param userContextData The user context data */ - function verify( - bytes calldata baseVerificationInput, - bytes calldata userContextData - ) external; + function verify(bytes calldata baseVerificationInput, bytes calldata userContextData) external; /** * @notice Updates the registry address. @@ -72,10 +70,7 @@ interface IIdentityVerificationHubV2 { * @param attestationId The attestation ID. * @param vcAndDiscloseCircuitVerifierAddress The new VC and Disclose circuit verifier address. */ - function updateVcAndDiscloseCircuit( - bytes32 attestationId, - address vcAndDiscloseCircuitVerifierAddress - ) external; + function updateVcAndDiscloseCircuit(bytes32 attestationId, address vcAndDiscloseCircuitVerifierAddress) external; /** * @notice Updates the register circuit verifier for a specific signature type. @@ -83,11 +78,7 @@ interface IIdentityVerificationHubV2 { * @param typeId The signature type identifier. * @param verifierAddress The new register circuit verifier address. */ - function updateRegisterCircuitVerifier( - bytes32 attestationId, - uint256 typeId, - address verifierAddress - ) external; + function updateRegisterCircuitVerifier(bytes32 attestationId, uint256 typeId, address verifierAddress) external; /** * @notice Updates the DSC circuit verifier for a specific signature type. @@ -95,11 +86,7 @@ interface IIdentityVerificationHubV2 { * @param typeId The signature type identifier. * @param verifierAddress The new DSC circuit verifier address. */ - function updateDscVerifier( - bytes32 attestationId, - uint256 typeId, - address verifierAddress - ) external; + function updateDscVerifier(bytes32 attestationId, uint256 typeId, address verifierAddress) external; /** * @notice Batch updates register circuit verifiers. diff --git a/contracts/contracts/interfaces/ISelfVerificationRoot.sol b/contracts/contracts/interfaces/ISelfVerificationRoot.sol index bb478b431..9fa75bb47 100644 --- a/contracts/contracts/interfaces/ISelfVerificationRoot.sol +++ b/contracts/contracts/interfaces/ISelfVerificationRoot.sol @@ -7,7 +7,6 @@ pragma solidity 0.8.28; * @dev Provides base functionality for verifying and disclosing identity credentials */ interface ISelfVerificationRoot { - /** * @notice Structure containing proof data for disclose circuits * @dev Contains the proof elements required for zero-knowledge verification @@ -62,10 +61,7 @@ interface ISelfVerificationRoot { * @param proofPayload Packed data from relayer in format: | 32 bytes attestationId | proof data | * @param userContextData User-defined data in format: | 32 bytes configId | 32 bytes destChainId | 32 bytes userIdentifier | data | */ - function verifySelfProof( - bytes calldata proofPayload, - bytes calldata userContextData - ) external; + function verifySelfProof(bytes calldata proofPayload, bytes calldata userContextData) external; /** * @notice Callback function called upon successful verification @@ -73,8 +69,5 @@ interface ISelfVerificationRoot { * @param output The verification output data containing disclosed identity information * @param userData The user-defined data passed through the verification process */ - function onVerificationSuccess( - bytes memory output, - bytes memory userData - ) external; + function onVerificationSuccess(bytes memory output, bytes memory userData) external; } diff --git a/contracts/contracts/libraries/CustomVerifier.sol b/contracts/contracts/libraries/CustomVerifier.sol index dda8b755c..e94d829eb 100644 --- a/contracts/contracts/libraries/CustomVerifier.sol +++ b/contracts/contracts/libraries/CustomVerifier.sol @@ -8,152 +8,210 @@ import {Formatter} from "./Formatter.sol"; import {GenericFormatter} from "./GenericFormatter.sol"; library CustomVerifier { - error InvalidAttestationId(); - error InvalidOfacCheck(); - error InvalidForbiddenCountries(); - error InvalidOlderThan(); + error InvalidAttestationId(); + error InvalidOfacCheck(); + error InvalidForbiddenCountries(); + error InvalidOlderThan(); - /** - * @notice Verifies the configuration of the custom verifier. - * @param attestationId The attestation ID. - * @param config The verification config of the custom verifier. - * @param proofOutput The proof output of the custom verifier. - * @return genericDiscloseOutput The generic disclose output. - */ - function customVerify(bytes32 attestationId, bytes calldata config, bytes calldata proofOutput) external pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { - SelfStructs.VerificationConfigV2 memory verificationConfig = GenericFormatter.verificationConfigFromBytes(config); + /** + * @notice Verifies the configuration of the custom verifier. + * @param attestationId The attestation ID. + * @param config The verification config of the custom verifier. + * @param proofOutput The proof output of the custom verifier. + * @return genericDiscloseOutput The generic disclose output. + */ + function customVerify( + bytes32 attestationId, + bytes calldata config, + bytes calldata proofOutput + ) external pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { + SelfStructs.VerificationConfigV2 memory verificationConfig = GenericFormatter.verificationConfigFromBytes( + config + ); - if (attestationId == AttestationId.E_PASSPORT) { - SelfStructs.PassportOutput memory passportOutput = abi.decode(proofOutput, (SelfStructs.PassportOutput)); - return CustomVerifier.verifyPassport(verificationConfig, passportOutput); - } else if (attestationId == AttestationId.EU_ID_CARD) { - SelfStructs.EuIdOutput memory idCardOutput = abi.decode(proofOutput, (SelfStructs.EuIdOutput)); - return CustomVerifier.verifyIdCard(verificationConfig, idCardOutput); - } else { - revert InvalidAttestationId(); - } - } - - /** - * @notice Verifies a passport output. - * @param verificationConfig The verification configuration. - * @param passportOutput The passport output from the circuit. - * @return genericDiscloseOutput The generic disclose output. - */ - function verifyPassport(SelfStructs.VerificationConfigV2 memory verificationConfig, SelfStructs.PassportOutput memory passportOutput) internal pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { - if ( - verificationConfig.ofacEnabled[0] || - verificationConfig.ofacEnabled[1] || - verificationConfig.ofacEnabled[2] - ) { - if (!CircuitAttributeHandlerV2.compareOfac( - AttestationId.E_PASSPORT, - passportOutput.revealedDataPacked, - verificationConfig.ofacEnabled[0], - verificationConfig.ofacEnabled[1], - verificationConfig.ofacEnabled[2] - )) { - revert InvalidOfacCheck(); - } - } - if (verificationConfig.forbiddenCountriesEnabled) { - for (uint256 i = 0; i < 4; i++) { - if (passportOutput.forbiddenCountriesListPacked[i] != verificationConfig.forbiddenCountriesListPacked[i]) { - revert InvalidForbiddenCountries(); + if (attestationId == AttestationId.E_PASSPORT) { + SelfStructs.PassportOutput memory passportOutput = abi.decode(proofOutput, (SelfStructs.PassportOutput)); + return CustomVerifier.verifyPassport(verificationConfig, passportOutput); + } else if (attestationId == AttestationId.EU_ID_CARD) { + SelfStructs.EuIdOutput memory idCardOutput = abi.decode(proofOutput, (SelfStructs.EuIdOutput)); + return CustomVerifier.verifyIdCard(verificationConfig, idCardOutput); + } else { + revert InvalidAttestationId(); } - } } - if (verificationConfig.olderThanEnabled) { - if (!CircuitAttributeHandlerV2.compareOlderThan( - AttestationId.E_PASSPORT, - passportOutput.revealedDataPacked, - verificationConfig.olderThan - )) { - revert InvalidOlderThan(); - } - } + /** + * @notice Verifies a passport output. + * @param verificationConfig The verification configuration. + * @param passportOutput The passport output from the circuit. + * @return genericDiscloseOutput The generic disclose output. + */ + function verifyPassport( + SelfStructs.VerificationConfigV2 memory verificationConfig, + SelfStructs.PassportOutput memory passportOutput + ) internal pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { + if ( + verificationConfig.ofacEnabled[0] || verificationConfig.ofacEnabled[1] || verificationConfig.ofacEnabled[2] + ) { + if ( + !CircuitAttributeHandlerV2.compareOfac( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked, + verificationConfig.ofacEnabled[0], + verificationConfig.ofacEnabled[1], + verificationConfig.ofacEnabled[2] + ) + ) { + revert InvalidOfacCheck(); + } + } + if (verificationConfig.forbiddenCountriesEnabled) { + for (uint256 i = 0; i < 4; i++) { + if ( + passportOutput.forbiddenCountriesListPacked[i] != verificationConfig.forbiddenCountriesListPacked[i] + ) { + revert InvalidForbiddenCountries(); + } + } + } - SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput = SelfStructs.GenericDiscloseOutputV2({ - attestationId: AttestationId.E_PASSPORT, - userIdentifier: passportOutput.userIdentifier, - nullifier: passportOutput.nullifier, - forbiddenCountriesListPacked: passportOutput.forbiddenCountriesListPacked, - issuingState: CircuitAttributeHandlerV2.getIssuingState(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - name: CircuitAttributeHandlerV2.getName(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - idNumber: CircuitAttributeHandlerV2.getDocumentNumber(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - nationality: CircuitAttributeHandlerV2.getNationality(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - dateOfBirth: CircuitAttributeHandlerV2.getDateOfBirth(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - gender: CircuitAttributeHandlerV2.getGender(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - expiryDate: CircuitAttributeHandlerV2.getExpiryDate(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - olderThan: verificationConfig.olderThan, - ofac: [ - CircuitAttributeHandlerV2.getDocumentNoOfac(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - CircuitAttributeHandlerV2.getNameAndDobOfac(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), - CircuitAttributeHandlerV2.getNameAndYobOfac(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked) - ] - }); + if (verificationConfig.olderThanEnabled) { + if ( + !CircuitAttributeHandlerV2.compareOlderThan( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked, + verificationConfig.olderThan + ) + ) { + revert InvalidOlderThan(); + } + } - return genericDiscloseOutput; - } + SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput = SelfStructs.GenericDiscloseOutputV2({ + attestationId: AttestationId.E_PASSPORT, + userIdentifier: passportOutput.userIdentifier, + nullifier: passportOutput.nullifier, + forbiddenCountriesListPacked: passportOutput.forbiddenCountriesListPacked, + issuingState: CircuitAttributeHandlerV2.getIssuingState( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + name: CircuitAttributeHandlerV2.getName(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), + idNumber: CircuitAttributeHandlerV2.getDocumentNumber( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + nationality: CircuitAttributeHandlerV2.getNationality( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + dateOfBirth: CircuitAttributeHandlerV2.getDateOfBirth( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + gender: CircuitAttributeHandlerV2.getGender(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked), + expiryDate: CircuitAttributeHandlerV2.getExpiryDate( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + olderThan: verificationConfig.olderThan, + ofac: [ + CircuitAttributeHandlerV2.getDocumentNoOfac( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + CircuitAttributeHandlerV2.getNameAndDobOfac( + AttestationId.E_PASSPORT, + passportOutput.revealedDataPacked + ), + CircuitAttributeHandlerV2.getNameAndYobOfac(AttestationId.E_PASSPORT, passportOutput.revealedDataPacked) + ] + }); - /** - * @notice Verifies an ID card output. - * @param verificationConfig The verification configuration. - * @param idCardOutput The ID card output from the circuit. - * @return genericDiscloseOutput The generic disclose output. - */ - function verifyIdCard(SelfStructs.VerificationConfigV2 memory verificationConfig, SelfStructs.EuIdOutput memory idCardOutput) internal pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { - if (verificationConfig.ofacEnabled[0] || verificationConfig.ofacEnabled[1]) { - if (!CircuitAttributeHandlerV2.compareOfac( - AttestationId.EU_ID_CARD, - idCardOutput.revealedDataPacked, - false, - verificationConfig.ofacEnabled[0], - verificationConfig.ofacEnabled[1] - )) { - revert InvalidOfacCheck(); - } + return genericDiscloseOutput; } - if (verificationConfig.forbiddenCountriesEnabled) { - for (uint256 i = 0; i < 4; i++) { - if (idCardOutput.forbiddenCountriesListPacked[i] != verificationConfig.forbiddenCountriesListPacked[i]) { - revert InvalidForbiddenCountries(); + /** + * @notice Verifies an ID card output. + * @param verificationConfig The verification configuration. + * @param idCardOutput The ID card output from the circuit. + * @return genericDiscloseOutput The generic disclose output. + */ + function verifyIdCard( + SelfStructs.VerificationConfigV2 memory verificationConfig, + SelfStructs.EuIdOutput memory idCardOutput + ) internal pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { + if (verificationConfig.ofacEnabled[0] || verificationConfig.ofacEnabled[1]) { + if ( + !CircuitAttributeHandlerV2.compareOfac( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked, + false, + verificationConfig.ofacEnabled[0], + verificationConfig.ofacEnabled[1] + ) + ) { + revert InvalidOfacCheck(); + } } - } - } - if (verificationConfig.olderThanEnabled) { - if (!CircuitAttributeHandlerV2.compareOlderThan( - AttestationId.EU_ID_CARD, - idCardOutput.revealedDataPacked, - verificationConfig.olderThan - )) { - revert InvalidOlderThan(); - } - } + if (verificationConfig.forbiddenCountriesEnabled) { + for (uint256 i = 0; i < 4; i++) { + if ( + idCardOutput.forbiddenCountriesListPacked[i] != verificationConfig.forbiddenCountriesListPacked[i] + ) { + revert InvalidForbiddenCountries(); + } + } + } - SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput = SelfStructs.GenericDiscloseOutputV2({ - attestationId: AttestationId.EU_ID_CARD, - userIdentifier: idCardOutput.userIdentifier, - nullifier: idCardOutput.nullifier, - forbiddenCountriesListPacked: idCardOutput.forbiddenCountriesListPacked, - issuingState: CircuitAttributeHandlerV2.getIssuingState(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - name: CircuitAttributeHandlerV2.getName(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - idNumber: CircuitAttributeHandlerV2.getDocumentNumber(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - nationality: CircuitAttributeHandlerV2.getNationality(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - dateOfBirth: CircuitAttributeHandlerV2.getDateOfBirth(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - gender: CircuitAttributeHandlerV2.getGender(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - expiryDate: CircuitAttributeHandlerV2.getExpiryDate(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - olderThan: verificationConfig.olderThan, - ofac: [ - false, - CircuitAttributeHandlerV2.getNameAndDobOfac(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), - CircuitAttributeHandlerV2.getNameAndYobOfac(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked) - ] - }); + if (verificationConfig.olderThanEnabled) { + if ( + !CircuitAttributeHandlerV2.compareOlderThan( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked, + verificationConfig.olderThan + ) + ) { + revert InvalidOlderThan(); + } + } + + SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput = SelfStructs.GenericDiscloseOutputV2({ + attestationId: AttestationId.EU_ID_CARD, + userIdentifier: idCardOutput.userIdentifier, + nullifier: idCardOutput.nullifier, + forbiddenCountriesListPacked: idCardOutput.forbiddenCountriesListPacked, + issuingState: CircuitAttributeHandlerV2.getIssuingState( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked + ), + name: CircuitAttributeHandlerV2.getName(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), + idNumber: CircuitAttributeHandlerV2.getDocumentNumber( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked + ), + nationality: CircuitAttributeHandlerV2.getNationality( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked + ), + dateOfBirth: CircuitAttributeHandlerV2.getDateOfBirth( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked + ), + gender: CircuitAttributeHandlerV2.getGender(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), + expiryDate: CircuitAttributeHandlerV2.getExpiryDate( + AttestationId.EU_ID_CARD, + idCardOutput.revealedDataPacked + ), + olderThan: verificationConfig.olderThan, + ofac: [ + false, + CircuitAttributeHandlerV2.getNameAndDobOfac(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked), + CircuitAttributeHandlerV2.getNameAndYobOfac(AttestationId.EU_ID_CARD, idCardOutput.revealedDataPacked) + ] + }); - return genericDiscloseOutput; - } + return genericDiscloseOutput; + } } diff --git a/contracts/contracts/libraries/Formatter.sol b/contracts/contracts/libraries/Formatter.sol index 278ef45c6..7c5a8d96c 100644 --- a/contracts/contracts/libraries/Formatter.sol +++ b/contracts/contracts/libraries/Formatter.sol @@ -154,7 +154,7 @@ library Formatter { * @param publicSignals A packed uint256 containing encoded forbidden country data. * @return forbiddenCountries An array of strings representing the forbidden country codes. */ - // TODO: look at this function a bit + // TODO: look at this function a bit function extractForbiddenCountriesFromPacked( uint256[4] memory publicSignals ) internal pure returns (string[MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH] memory forbiddenCountries) { @@ -172,7 +172,9 @@ library Formatter { uint256 shift = byteIndex * 8; uint256 mask = 0xFFFFFF; uint256 packedData = (publicSignals[index * 3] >> shift) & mask; - uint256 reversedPackedData = ((packedData & 0xff) << 16) | ((packedData & 0xff00)) | ((packedData & 0xff0000) >> 16); + uint256 reversedPackedData = ((packedData & 0xff) << 16) | + ((packedData & 0xff00)) | + ((packedData & 0xff0000) >> 16); forbiddenCountries[j] = string(abi.encodePacked(uint24(reversedPackedData))); } else if (byteIndex < 31) { uint256 part0 = (publicSignals[0] >> (byteIndex * 8)); @@ -185,7 +187,9 @@ library Formatter { uint256 shift = byteIndexIn1 * 8; uint256 mask = 0xFFFFFF; uint256 packedData = (publicSignals[1] >> shift) & mask; - uint256 reversedPackedData = ((packedData & 0xff) << 16) | ((packedData & 0xff00)) | ((packedData & 0xff0000) >> 16); + uint256 reversedPackedData = ((packedData & 0xff) << 16) | + ((packedData & 0xff00)) | + ((packedData & 0xff0000) >> 16); forbiddenCountries[j] = string(abi.encodePacked(uint24(reversedPackedData))); } else if (byteIndex < 62) { uint256 part0 = (publicSignals[1] >> ((byteIndex - 31) * 8)) & 0x00ffff; @@ -198,7 +202,9 @@ library Formatter { uint256 shift = byteIndexIn1 * 8; uint256 mask = 0xFFFFFF; uint256 packedData = (publicSignals[2] >> shift) & mask; - uint256 reversedPackedData = ((packedData & 0xff) << 16) | ((packedData & 0xff00)) | ((packedData & 0xff0000) >> 16); + uint256 reversedPackedData = ((packedData & 0xff) << 16) | + ((packedData & 0xff00)) | + ((packedData & 0xff0000) >> 16); forbiddenCountries[j] = string(abi.encodePacked(uint24(reversedPackedData))); } } diff --git a/contracts/contracts/libraries/GenericFormatter.sol b/contracts/contracts/libraries/GenericFormatter.sol index 0259fe6ca..da16da46c 100644 --- a/contracts/contracts/libraries/GenericFormatter.sol +++ b/contracts/contracts/libraries/GenericFormatter.sol @@ -4,60 +4,70 @@ pragma solidity ^0.8.0; import {SelfStructs} from "./SelfStructs.sol"; struct GenericVerificationStruct { - uint8 attestationId; - bytes verificationConfig; + uint8 attestationId; + bytes verificationConfig; } library GenericFormatter { - /** - * @notice Converts a VerificationConfigV1 struct to a VerificationConfigV2 struct. - * @param verificationConfigV1 The VerificationConfigV1 struct to convert. - * @return verificationConfig The converted VerificationConfigV2 struct. - */ - function fromV1Config(SelfStructs.VerificationConfigV1 memory verificationConfigV1) internal pure returns (SelfStructs.VerificationConfigV2 memory verificationConfig) { - verificationConfig = SelfStructs.VerificationConfigV2({ - olderThanEnabled: verificationConfigV1.olderThanEnabled, - olderThan: verificationConfigV1.olderThan, - forbiddenCountriesEnabled: verificationConfigV1.forbiddenCountriesEnabled, - forbiddenCountriesListPacked: verificationConfigV1.forbiddenCountriesListPacked, - ofacEnabled: verificationConfigV1.ofacEnabled - }); - } + /** + * @notice Converts a VerificationConfigV1 struct to a VerificationConfigV2 struct. + * @param verificationConfigV1 The VerificationConfigV1 struct to convert. + * @return verificationConfig The converted VerificationConfigV2 struct. + */ + function fromV1Config( + SelfStructs.VerificationConfigV1 memory verificationConfigV1 + ) internal pure returns (SelfStructs.VerificationConfigV2 memory verificationConfig) { + verificationConfig = SelfStructs.VerificationConfigV2({ + olderThanEnabled: verificationConfigV1.olderThanEnabled, + olderThan: verificationConfigV1.olderThan, + forbiddenCountriesEnabled: verificationConfigV1.forbiddenCountriesEnabled, + forbiddenCountriesListPacked: verificationConfigV1.forbiddenCountriesListPacked, + ofacEnabled: verificationConfigV1.ofacEnabled + }); + } - /** - * @notice Converts a bytes array to the latest VerificationConfig struct. - * @param verificationConfig The bytes array to convert. - * @return verificationConfigV2 The converted VerificationConfig struct. - */ - function verificationConfigFromBytes(bytes memory verificationConfig) internal pure returns (SelfStructs.VerificationConfigV2 memory verificationConfigV2) { - return abi.decode(verificationConfig, (SelfStructs.VerificationConfigV2)); - } + /** + * @notice Converts a bytes array to the latest VerificationConfig struct. + * @param verificationConfig The bytes array to convert. + * @return verificationConfigV2 The converted VerificationConfig struct. + */ + function verificationConfigFromBytes( + bytes memory verificationConfig + ) internal pure returns (SelfStructs.VerificationConfigV2 memory verificationConfigV2) { + return abi.decode(verificationConfig, (SelfStructs.VerificationConfigV2)); + } - /** - * @notice Formats a VerificationConfigV1 struct to the latest verification config bytes array. - * @param verificationConfigV1 The VerificationConfigV1 struct to format. - * @return v1ConfigBytes The latest verification config formatted bytes array. - */ - function formatV1Config(SelfStructs.VerificationConfigV1 memory verificationConfigV1) internal pure returns (bytes memory v1ConfigBytes) { - SelfStructs.VerificationConfigV2 memory verificationConfigV2 = fromV1Config(verificationConfigV1); - return abi.encode(verificationConfigV2); - } + /** + * @notice Formats a VerificationConfigV1 struct to the latest verification config bytes array. + * @param verificationConfigV1 The VerificationConfigV1 struct to format. + * @return v1ConfigBytes The latest verification config formatted bytes array. + */ + function formatV1Config( + SelfStructs.VerificationConfigV1 memory verificationConfigV1 + ) internal pure returns (bytes memory v1ConfigBytes) { + SelfStructs.VerificationConfigV2 memory verificationConfigV2 = fromV1Config(verificationConfigV1); + return abi.encode(verificationConfigV2); + } - /** - * @notice Formats a VerificationConfigV2 struct to the latest verification config bytes array. - * @param verificationConfigV2 The VerificationConfigV2 struct to format. - * @return v2ConfigBytes The latest verification config formatted bytes array. - */ - function formatV2Config(SelfStructs.VerificationConfigV2 memory verificationConfigV2) internal pure returns (bytes memory v2ConfigBytes) { - return abi.encode(verificationConfigV2); - } + /** + * @notice Formats a VerificationConfigV2 struct to the latest verification config bytes array. + * @param verificationConfigV2 The VerificationConfigV2 struct to format. + * @return v2ConfigBytes The latest verification config formatted bytes array. + */ + function formatV2Config( + SelfStructs.VerificationConfigV2 memory verificationConfigV2 + ) internal pure returns (bytes memory v2ConfigBytes) { + return abi.encode(verificationConfigV2); + } - /** - * @notice Formats a GenericDiscloseOutputV2 struct to the latest generic disclose output bytes array. - * @param genericDiscloseOutput The GenericDiscloseOutputV2 struct to format. - * @return v2StructBytes The latest generic disclose output formatted bytes array. - */ - function toV2Struct(SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput) internal pure returns (bytes memory v2StructBytes) { - v2StructBytes = abi.encode(genericDiscloseOutput); - } + /** + * @notice Formats a GenericDiscloseOutputV2 struct to the latest generic disclose output bytes array. + * @param genericDiscloseOutput The GenericDiscloseOutputV2 struct to format. + * @return v2StructBytes The latest generic disclose output formatted bytes array. + */ + function toV2Struct( + SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput + ) internal pure returns (bytes memory v2StructBytes) { + v2StructBytes = abi.encode(genericDiscloseOutput); + } } diff --git a/contracts/contracts/libraries/SelfStructs.sol b/contracts/contracts/libraries/SelfStructs.sol index 9603ffe3c..14b1fbb99 100644 --- a/contracts/contracts/libraries/SelfStructs.sol +++ b/contracts/contracts/libraries/SelfStructs.sol @@ -7,118 +7,118 @@ pragma solidity 0.8.28; * @notice Defines structs for passport verification, EU ID verification, and generic disclosure outputs */ library SelfStructs { - /** - * @dev Header structure for Hub input containing contract version and scope information - * @param contractVersion Version of the contract being used - * @param scope Scope identifier for the verification request - * @param attestationId Unique identifier for the attestation - */ - struct HubInputHeader { - uint8 contractVersion; - uint256 scope; - bytes32 attestationId; - } + /** + * @dev Header structure for Hub input containing contract version and scope information + * @param contractVersion Version of the contract being used + * @param scope Scope identifier for the verification request + * @param attestationId Unique identifier for the attestation + */ + struct HubInputHeader { + uint8 contractVersion; + uint256 scope; + bytes32 attestationId; + } - /** - * @dev Output structure for passport verification results - * @param attestationId Unique identifier for the attestation - * @param revealedDataPacked Packed binary data of revealed information - * @param userIdentifier Unique identifier for the user - * @param nullifier Cryptographic nullifier to prevent double-spending - * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) - */ - struct PassportOutput { - uint256 attestationId; - bytes revealedDataPacked; - uint256 userIdentifier; - uint256 nullifier; - uint256[4] forbiddenCountriesListPacked; - } + /** + * @dev Output structure for passport verification results + * @param attestationId Unique identifier for the attestation + * @param revealedDataPacked Packed binary data of revealed information + * @param userIdentifier Unique identifier for the user + * @param nullifier Cryptographic nullifier to prevent double-spending + * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) + */ + struct PassportOutput { + uint256 attestationId; + bytes revealedDataPacked; + uint256 userIdentifier; + uint256 nullifier; + uint256[4] forbiddenCountriesListPacked; + } - /** - * @dev Output structure for EU ID verification results - * @param attestationId Unique identifier for the attestation - * @param revealedDataPacked Packed binary data of revealed information - * @param userIdentifier Unique identifier for the user - * @param nullifier Cryptographic nullifier to prevent double-spending - * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) - */ - struct EuIdOutput { - uint256 attestationId; - bytes revealedDataPacked; - uint256 userIdentifier; - uint256 nullifier; - uint256[4] forbiddenCountriesListPacked; - } + /** + * @dev Output structure for EU ID verification results + * @param attestationId Unique identifier for the attestation + * @param revealedDataPacked Packed binary data of revealed information + * @param userIdentifier Unique identifier for the user + * @param nullifier Cryptographic nullifier to prevent double-spending + * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) + */ + struct EuIdOutput { + uint256 attestationId; + bytes revealedDataPacked; + uint256 userIdentifier; + uint256 nullifier; + uint256[4] forbiddenCountriesListPacked; + } - /// @dev OFAC verification mode: Passport number only - uint256 constant passportNoOfac = 0; - /// @dev OFAC verification mode: Name and date of birth - uint256 constant nameAndDobOfac = 1; - /// @dev OFAC verification mode: Name and year of birth - uint256 constant nameAndYobOfac = 2; + /// @dev OFAC verification mode: Passport number only + uint256 constant passportNoOfac = 0; + /// @dev OFAC verification mode: Name and date of birth + uint256 constant nameAndDobOfac = 1; + /// @dev OFAC verification mode: Name and year of birth + uint256 constant nameAndYobOfac = 2; - /** - * @dev Generic disclosure output structure (Version 2) with detailed personal information - * @param attestationId Unique identifier for the attestation - * @param userIdentifier Unique identifier for the user - * @param nullifier Cryptographic nullifier to prevent double-spending - * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) - * @param issuingState Country or state that issued the document - * @param name Array of name components (first, middle, last names) - * @param idNumber Government-issued identification number - * @param nationality Nationality of the document holder - * @param dateOfBirth Date of birth in string format - * @param gender Gender of the document holder - * @param expiryDate Document expiration date in string format - * @param olderThan Minimum age verification result - * @param ofac Array of OFAC (Office of Foreign Assets Control) verification results for different modes - */ - struct GenericDiscloseOutputV2 { - bytes32 attestationId; - uint256 userIdentifier; - uint256 nullifier; - uint256[4] forbiddenCountriesListPacked; - string issuingState; - string[] name; - string idNumber; - string nationality; - string dateOfBirth; - string gender; - string expiryDate; - uint256 olderThan; - bool[3] ofac; - } + /** + * @dev Generic disclosure output structure (Version 2) with detailed personal information + * @param attestationId Unique identifier for the attestation + * @param userIdentifier Unique identifier for the user + * @param nullifier Cryptographic nullifier to prevent double-spending + * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) + * @param issuingState Country or state that issued the document + * @param name Array of name components (first, middle, last names) + * @param idNumber Government-issued identification number + * @param nationality Nationality of the document holder + * @param dateOfBirth Date of birth in string format + * @param gender Gender of the document holder + * @param expiryDate Document expiration date in string format + * @param olderThan Minimum age verification result + * @param ofac Array of OFAC (Office of Foreign Assets Control) verification results for different modes + */ + struct GenericDiscloseOutputV2 { + bytes32 attestationId; + uint256 userIdentifier; + uint256 nullifier; + uint256[4] forbiddenCountriesListPacked; + string issuingState; + string[] name; + string idNumber; + string nationality; + string dateOfBirth; + string gender; + string expiryDate; + uint256 olderThan; + bool[3] ofac; + } - /** - * @dev Verification configuration structure (Version 1) - * @param olderThanEnabled Whether minimum age verification is enabled - * @param olderThan Minimum age requirement - * @param forbiddenCountriesEnabled Whether forbidden countries check is enabled - * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) - * @param ofacEnabled Array of boolean flags for different OFAC verification modes - */ - struct VerificationConfigV1 { - bool olderThanEnabled; - uint256 olderThan; - bool forbiddenCountriesEnabled; - uint256[4] forbiddenCountriesListPacked; - bool[3] ofacEnabled; - } + /** + * @dev Verification configuration structure (Version 1) + * @param olderThanEnabled Whether minimum age verification is enabled + * @param olderThan Minimum age requirement + * @param forbiddenCountriesEnabled Whether forbidden countries check is enabled + * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) + * @param ofacEnabled Array of boolean flags for different OFAC verification modes + */ + struct VerificationConfigV1 { + bool olderThanEnabled; + uint256 olderThan; + bool forbiddenCountriesEnabled; + uint256[4] forbiddenCountriesListPacked; + bool[3] ofacEnabled; + } - /** - * @dev Verification configuration structure (Version 2) - * @param olderThanEnabled Whether minimum age verification is enabled - * @param olderThan Minimum age requirement - * @param forbiddenCountriesEnabled Whether forbidden countries check is enabled - * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) - * @param ofacEnabled Array of boolean flags for different OFAC verification modes - */ - struct VerificationConfigV2 { - bool olderThanEnabled; - uint256 olderThan; - bool forbiddenCountriesEnabled; - uint256[4] forbiddenCountriesListPacked; - bool[3] ofacEnabled; - } + /** + * @dev Verification configuration structure (Version 2) + * @param olderThanEnabled Whether minimum age verification is enabled + * @param olderThan Minimum age requirement + * @param forbiddenCountriesEnabled Whether forbidden countries check is enabled + * @param forbiddenCountriesListPacked Packed list of forbidden countries (4 uint256 array) + * @param ofacEnabled Array of boolean flags for different OFAC verification modes + */ + struct VerificationConfigV2 { + bool olderThanEnabled; + uint256 olderThan; + bool forbiddenCountriesEnabled; + uint256[4] forbiddenCountriesListPacked; + bool[3] ofacEnabled; + } } diff --git a/contracts/contracts/tests/TestCustomVerifier.sol b/contracts/contracts/tests/TestCustomVerifier.sol index 0a379b95f..077233905 100644 --- a/contracts/contracts/tests/TestCustomVerifier.sol +++ b/contracts/contracts/tests/TestCustomVerifier.sol @@ -5,7 +5,11 @@ import {CustomVerifier} from "../libraries/CustomVerifier.sol"; import {SelfStructs} from "../libraries/SelfStructs.sol"; contract TestCustomVerifier { - function testCustomVerify(bytes32 attestationId, bytes calldata config, bytes calldata proofOutput) external pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { + function testCustomVerify( + bytes32 attestationId, + bytes calldata config, + bytes calldata proofOutput + ) external pure returns (SelfStructs.GenericDiscloseOutputV2 memory) { return CustomVerifier.customVerify(attestationId, config, proofOutput); } } diff --git a/contracts/contracts/tests/TestSelfVerificationRoot.sol b/contracts/contracts/tests/TestSelfVerificationRoot.sol index 102b41611..ee136363a 100644 --- a/contracts/contracts/tests/TestSelfVerificationRoot.sol +++ b/contracts/contracts/tests/TestSelfVerificationRoot.sol @@ -10,7 +10,6 @@ import {ISelfVerificationRoot} from "../interfaces/ISelfVerificationRoot.sol"; * @dev This contract provides a concrete implementation of the abstract SelfVerificationRoot */ contract TestSelfVerificationRoot is SelfVerificationRoot { - // Storage for testing purposes bool public verificationSuccessful; ISelfVerificationRoot.GenericDiscloseOutputV2 public lastOutput; @@ -83,10 +82,7 @@ contract TestSelfVerificationRoot is SelfVerificationRoot { * @param output The verification output * @param userData The user data */ - function testOnVerificationSuccess( - bytes memory output, - bytes memory userData - ) external { + function testOnVerificationSuccess(bytes memory output, bytes memory userData) external { // This should fail if called by anyone other than the hub onVerificationSuccess(output, userData); } diff --git a/contracts/contracts/tests/testGenericFormatter.sol b/contracts/contracts/tests/testGenericFormatter.sol index 820971bae..3f563a321 100644 --- a/contracts/contracts/tests/testGenericFormatter.sol +++ b/contracts/contracts/tests/testGenericFormatter.sol @@ -1,25 +1,34 @@ import {GenericFormatter} from "../libraries/GenericFormatter.sol"; import {SelfStructs} from "../libraries/SelfStructs.sol"; - contract TestGenericFormatter { - function testFromV1Config(SelfStructs.VerificationConfigV1 memory verificationConfigV1) public pure returns (SelfStructs.VerificationConfigV2 memory verificationConfigV2) { - verificationConfigV2 = GenericFormatter.fromV1Config(verificationConfigV1); - } + function testFromV1Config( + SelfStructs.VerificationConfigV1 memory verificationConfigV1 + ) public pure returns (SelfStructs.VerificationConfigV2 memory verificationConfigV2) { + verificationConfigV2 = GenericFormatter.fromV1Config(verificationConfigV1); + } - function testVerificationConfigFromBytes(bytes memory verificationConfig) public pure returns (SelfStructs.VerificationConfigV2 memory verificationConfigV2) { - verificationConfigV2 = GenericFormatter.verificationConfigFromBytes(verificationConfig); - } + function testVerificationConfigFromBytes( + bytes memory verificationConfig + ) public pure returns (SelfStructs.VerificationConfigV2 memory verificationConfigV2) { + verificationConfigV2 = GenericFormatter.verificationConfigFromBytes(verificationConfig); + } - function testFormatV1Config(SelfStructs.VerificationConfigV1 memory verificationConfigV1) public pure returns (bytes memory v1ConfigBytes) { - v1ConfigBytes = GenericFormatter.formatV1Config(verificationConfigV1); - } + function testFormatV1Config( + SelfStructs.VerificationConfigV1 memory verificationConfigV1 + ) public pure returns (bytes memory v1ConfigBytes) { + v1ConfigBytes = GenericFormatter.formatV1Config(verificationConfigV1); + } - function testFormatV2Config(SelfStructs.VerificationConfigV2 memory verificationConfigV2) public pure returns (bytes memory v2ConfigBytes) { - v2ConfigBytes = GenericFormatter.formatV2Config(verificationConfigV2); - } + function testFormatV2Config( + SelfStructs.VerificationConfigV2 memory verificationConfigV2 + ) public pure returns (bytes memory v2ConfigBytes) { + v2ConfigBytes = GenericFormatter.formatV2Config(verificationConfigV2); + } - function testToV2Struct(SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput) public pure returns (bytes memory v2StructBytes) { - v2StructBytes = GenericFormatter.toV2Struct(genericDiscloseOutput); - } + function testToV2Struct( + SelfStructs.GenericDiscloseOutputV2 memory genericDiscloseOutput + ) public pure returns (bytes memory v2StructBytes) { + v2StructBytes = GenericFormatter.toV2Struct(genericDiscloseOutput); + } } diff --git a/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose_id.sol b/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose_id.sol index c153fe887..598366bc6 100644 --- a/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose_id.sol +++ b/contracts/contracts/verifiers/disclose/Verifier_vc_and_disclose_id.sol @@ -22,17 +22,17 @@ pragma solidity >=0.7.0 <0.9.0; contract Verifier_vc_and_disclose_id { // Scalar field size - uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Base field size - uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + 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 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; @@ -42,81 +42,84 @@ contract Verifier_vc_and_disclose_id { uint256 constant deltay1 = 7697803293347511746398205466597805067891748159831340108443169903730430911531; uint256 constant deltay2 = 18135141573537061188590013042324734692899788683249633264832904379088420521347; - uint256 constant IC0x = 5856920506801943179747940431507261587545690354191837904074746625856713057019; uint256 constant IC0y = 19124539120756340306225201952668471579555384876400327849356328019845881097562; - + uint256 constant IC1x = 3907275788156399155726133032274445611289536322362606696599801283854580295437; uint256 constant IC1y = 8451119154682439762054395905067543035497291620054904162598329277934126172016; - + uint256 constant IC2x = 20530143257595175213619797207279919184153764911566159122843961254673243634293; uint256 constant IC2y = 18418107796075636508766997478881789861884175034155105905934657000306915821371; - + uint256 constant IC3x = 14368654893588239986356440315957545435792265903841511372331944472664329358460; uint256 constant IC3y = 12284629478683204119754717091716141149657267016652380030058008792997116131875; - + uint256 constant IC4x = 9578716983925369516022217522731093507962466534359837901987460531141004851058; uint256 constant IC4y = 11546230489007268978353544383968439771367148945013199458278541261408798518042; - + uint256 constant IC5x = 20186291580274548265191299475582935526688657371386630094736889868165148343049; uint256 constant IC5y = 7066081396404019076294461314754121975461942238116236506003634245369912659348; - + uint256 constant IC6x = 7223725756527208741423329209765674164138947999927552108248321109787428330576; uint256 constant IC6y = 7090893321878038809726547992284174238790568751222590654054815492845205850020; - + uint256 constant IC7x = 3508039657302366273723082871441943167324729420192561664273405366370025413334; uint256 constant IC7y = 16077897542007852149081275458028106372577804015189016149401990661491415919989; - + uint256 constant IC8x = 7157834980199389511778623097557341082580034352641045942337042309147987264745; uint256 constant IC8y = 17810088059705235516956644702714110398594370075197014246657966746880992708168; - + uint256 constant IC9x = 19990085150526235401122450579432100767788242749821689359772693208891467804622; uint256 constant IC9y = 11875741660249391520213283913162030612995484283095257075118031592533202953731; - + uint256 constant IC10x = 565576411533726770996320843760026133874517147039816053645457725776038253277; uint256 constant IC10y = 6930421180986466104206189528520482999522362852059930498501019935177194699565; - + uint256 constant IC11x = 9687304248878239799475267106341943076035784248337790140346422230644442528821; uint256 constant IC11y = 8718390928981091008213508300667652242975655218883879916045519674874973495651; - + uint256 constant IC12x = 13400562939760543038178200762869273415986171711360997974863414188041195677804; uint256 constant IC12y = 19454142021037427981814241940238985741634162007055597028328858197655005999592; - + uint256 constant IC13x = 5304642595939683424612415509804552638020604037251875803456909825635793998553; uint256 constant IC13y = 5306882009576422477327808720898870532843294871978759595546305216807124752880; - + uint256 constant IC14x = 14031793532934637725744550192616647697277176739864804433516834701426772096040; uint256 constant IC14y = 13997965923135752232663850400013330288274429042096588718589372655870427909076; - + uint256 constant IC15x = 6857315285146692182841362377259336559693847336499456322687817740418786750593; uint256 constant IC15y = 7773075738364850482446135825145951942474724287022442267891210024402400169358; - + uint256 constant IC16x = 7350867218242766859946239631839980088884228896188196079908494306313085242757; uint256 constant IC16y = 16585312954662800633717122107305570207242746661443177600922110732010586303604; - + uint256 constant IC17x = 12371794706813431625295862613989653271433404490947256703099159689503429758617; uint256 constant IC17y = 16874395293051993576135801684114190330547607587787157588928779976192005582901; - + uint256 constant IC18x = 18408185524203075886684659649084141997263054479485752795420181339411166689531; uint256 constant IC18y = 16243204335737707642434624849163560305778796389979434010995242909912410681115; - + uint256 constant IC19x = 12827474512217515366731958666602059443683014227879101851822634933350038305567; uint256 constant IC19y = 12103285317170015797205692728698593084779876459612203243369112597137507623396; - + uint256 constant IC20x = 21871607573936419852307486960157754714579931787264995102940433544145315016287; uint256 constant IC20y = 3793515164944941168720752793034269182533154487955578472737823429132294441082; - + uint256 constant IC21x = 694085742582167480921564969992368553233272238548053666297768861621687596406; uint256 constant IC21y = 19146278969945936933324725088253247909700597465969498560427768702663925772917; - - + // 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[21] calldata _pubSignals) public view returns (bool) { + function verifyProof( + uint[2] calldata _pA, + uint[2][2] calldata _pB, + uint[2] calldata _pC, + uint[21] calldata _pubSignals + ) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -124,7 +127,7 @@ contract Verifier_vc_and_disclose_id { 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 @@ -159,49 +162,48 @@ contract Verifier_vc_and_disclose_id { 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))) - + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) - + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) - + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) - + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) - + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) - // -A mstore(_pPairing, calldataload(pA)) @@ -227,7 +229,6 @@ contract Verifier_vc_and_disclose_id { 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) @@ -244,7 +245,6 @@ contract Verifier_vc_and_disclose_id { 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)) @@ -254,55 +254,54 @@ contract Verifier_vc_and_disclose_id { 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))) - + checkField(calldataload(add(_pubSignals, 544))) - + checkField(calldataload(add(_pubSignals, 576))) - + checkField(calldataload(add(_pubSignals, 608))) - + checkField(calldataload(add(_pubSignals, 640))) - // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) mstore(0, isValid) - return(0, 0x20) - } - } - } + return(0, 0x20) + } + } +} diff --git a/contracts/contracts/verifiers/register_id/Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096.sol b/contracts/contracts/verifiers/register_id/Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096.sol index 37e0e0026..50d7b9f92 100644 --- a/contracts/contracts/verifiers/register_id/Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096.sol +++ b/contracts/contracts/verifiers/register_id/Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096.sol @@ -22,17 +22,17 @@ pragma solidity >=0.7.0 <0.9.0; contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { // Scalar field size - uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Base field size - uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + 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 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; @@ -42,27 +42,30 @@ contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { uint256 constant deltay1 = 17093903636529404715977441649383548797208493053670591927268936136905628890632; uint256 constant deltay2 = 4972965029582644081071578284460620299080512423640837516215418184958287485742; - uint256 constant IC0x = 10355093401382030671225395655869217898600304666279529568537338332467402365304; uint256 constant IC0y = 4965486376320532678254373789150183805614443765077280090063627634214290673841; - + uint256 constant IC1x = 15499415295419376168702866885907180620949913073936284071089537160198730049399; uint256 constant IC1y = 9281988302763410034273237781396743554700695834575740098855226007996985888530; - + uint256 constant IC2x = 14098031970434182418452511377672297745474345532972352145312731453903292311930; uint256 constant IC2y = 5496357494362502413877905425401698232434560336945612609023708765434745421701; - + uint256 constant IC3x = 6540495825150439480926083011463382216384205445522489211977434270583326380648; uint256 constant IC3y = 4164688383627561794431395614711252825194458846441353030452544157419373614848; - - + // 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[3] calldata _pubSignals) public view returns (bool) { + function verifyProof( + uint[2] calldata _pA, + uint[2][2] calldata _pB, + uint[2] calldata _pC, + uint[3] calldata _pubSignals + ) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -70,7 +73,7 @@ contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { 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 @@ -105,13 +108,12 @@ contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { 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))) - // -A mstore(_pPairing, calldataload(pA)) @@ -137,7 +139,6 @@ contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { 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) @@ -154,7 +155,6 @@ contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { 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)) @@ -164,19 +164,18 @@ contract Verifier_register_id_sha256_sha256_sha256_rsa_65537_4096 { 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))) - // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) mstore(0, isValid) - return(0, 0x20) - } - } - } + return(0, 0x20) + } + } +} diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index c744043fd..fd6c97d2c 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -1,7 +1,7 @@ import { HardhatUserConfig } from "hardhat/config"; import "@nomicfoundation/hardhat-toolbox"; require("dotenv").config({ - path: process.env.CI ? ".env.test" : ".env" + path: process.env.CI ? ".env.test" : ".env", }); import "hardhat-contract-sizer"; import "@nomicfoundation/hardhat-ignition-ethers"; diff --git a/contracts/ignition/modules/hub/deployHub.ts b/contracts/ignition/modules/hub/deployHub.ts index b8747d6e4..cbdee499c 100644 --- a/contracts/ignition/modules/hub/deployHub.ts +++ b/contracts/ignition/modules/hub/deployHub.ts @@ -18,14 +18,7 @@ export default buildModule("DeployHubV1", (m) => { const identityVerificationHubImplV1 = m.contract("IdentityVerificationHubImplV1"); const hubInterface = getHubInitializeData(); - const initializeData = hubInterface.encodeFunctionData("initialize", [ - "", - "", - [], - [], - [], - [], - ]); + const initializeData = hubInterface.encodeFunctionData("initialize", ["", "", [], [], [], []]); // Deploy proxy with V1 implementation const hubV1 = m.contract("IdentityVerificationHub", [identityVerificationHubImplV1, initializeData]); diff --git a/contracts/ignition/modules/verifiers/deployAllVerifiers.ts b/contracts/ignition/modules/verifiers/deployAllVerifiers.ts index 1cca736a7..cae65f8f3 100644 --- a/contracts/ignition/modules/verifiers/deployAllVerifiers.ts +++ b/contracts/ignition/modules/verifiers/deployAllVerifiers.ts @@ -7,7 +7,7 @@ import * as path from "path"; * Get enum keys (circuit names) excluding numeric values */ function getEnumKeys>(enumObject: T): string[] { - return Object.keys(enumObject).filter(key => isNaN(Number(key))); + return Object.keys(enumObject).filter((key) => isNaN(Number(key))); } /** @@ -22,7 +22,7 @@ function contractExists(contractName: string): boolean { path.join(contractsDir, "verifiers", `${contractName}.sol`), ]; - return possiblePaths.some(filePath => fs.existsSync(filePath)); + return possiblePaths.some((filePath) => fs.existsSync(filePath)); } export default buildModule("DeployAllVerifiers", (m) => { @@ -64,8 +64,12 @@ export default buildModule("DeployAllVerifiers", (m) => { console.log(`Total verifiers deployment summary:`); console.log(` - VC and Disclose: 1`); - console.log(` - Register: ${successfulRegisterDeployments}/${registerCircuits.length} (${registerCircuits.length - successfulRegisterDeployments} skipped)`); - console.log(` - DSC: ${successfulDscDeployments}/${dscCircuits.length} (${dscCircuits.length - successfulDscDeployments} skipped)`); + console.log( + ` - Register: ${successfulRegisterDeployments}/${registerCircuits.length} (${registerCircuits.length - successfulRegisterDeployments} skipped)`, + ); + console.log( + ` - DSC: ${successfulDscDeployments}/${dscCircuits.length} (${dscCircuits.length - successfulDscDeployments} skipped)`, + ); console.log(` - Total successful deployments: ${1 + successfulRegisterDeployments + successfulDscDeployments}`); return deployedContracts; diff --git a/contracts/scripts/README.md b/contracts/scripts/README.md index 6262546e5..603ee45ab 100644 --- a/contracts/scripts/README.md +++ b/contracts/scripts/README.md @@ -134,12 +134,14 @@ chmod +x scripts/test.sh scripts/dev.sh ### "hardhat.config.ts not found" Error This means the script couldn't find the Hardhat configuration. Make sure you're running from: + - The `contracts/` directory, or - The `contracts/scripts/` directory ### Yarn 4 Workspace Issues -If you encounter Yarn workspace issues, these scripts are designed to work directly with `npx hardhat` to avoid the workspace complexities. +If you encounter Yarn workspace issues, these scripts are designed to work directly with `npx hardhat` to avoid the +workspace complexities. ## Integration with Package.json diff --git a/contracts/scripts/setHubV2.ts b/contracts/scripts/setHubV2.ts index e35e32b56..1138da559 100644 --- a/contracts/scripts/setHubV2.ts +++ b/contracts/scripts/setHubV2.ts @@ -13,9 +13,9 @@ const PRIVATE_KEY = process.env.CELO_KEY; // Network to Chain ID mapping const NETWORK_TO_CHAIN_ID: Record = { - "localhost": "31337", - "celoAlfajores": "44787", - "celo": "42220", + localhost: "31337", + celoAlfajores: "44787", + celo: "42220", }; // Get chain ID from network name @@ -34,7 +34,10 @@ const AttestationId = { // Dynamic paths based on chain ID const deployedAddressesPath = path.join(__dirname, `../ignition/deployments/chain-${CHAIN_ID}/deployed_addresses.json`); -const contractAbiPath = path.join(__dirname, `../ignition/deployments/chain-${CHAIN_ID}/artifacts/DeployHubV2#IdentityVerificationHubImplV2.json`); +const contractAbiPath = path.join( + __dirname, + `../ignition/deployments/chain-${CHAIN_ID}/artifacts/DeployHubV2#IdentityVerificationHubImplV2.json`, +); // Debug logs for paths and files console.log("Network:", NETWORK); @@ -222,7 +225,7 @@ try { } } -main().catch((error) => { + main().catch((error) => { console.error("Execution error:", error); process.exitCode = 1; }); diff --git a/contracts/scripts/setRegistry.ts b/contracts/scripts/setRegistry.ts index 821883524..ebddb0b79 100644 --- a/contracts/scripts/setRegistry.ts +++ b/contracts/scripts/setRegistry.ts @@ -16,9 +16,9 @@ const CSCA_ROOT = process.env.CSCA_ROOT; // Allow manual CSCA root setting // Network to Chain ID mapping const NETWORK_TO_CHAIN_ID: Record = { - "localhost": "31337", - "celoAlfajores": "44787", - "celo": "42220", + localhost: "31337", + celoAlfajores: "44787", + celo: "42220", }; // Get chain ID from network name @@ -30,7 +30,10 @@ const CHAIN_ID = getChainId(NETWORK); // Dynamic paths based on chain ID const deployedAddressesPath = path.join(__dirname, `../ignition/deployments/chain-${CHAIN_ID}/deployed_addresses.json`); -const contractAbiPath = path.join(__dirname, `../ignition/deployments/chain-${CHAIN_ID}/artifacts/DeployRegistryModule#IdentityRegistryImplV1.json`); +const contractAbiPath = path.join( + __dirname, + `../ignition/deployments/chain-${CHAIN_ID}/artifacts/DeployRegistryModule#IdentityRegistryImplV1.json`, +); // Debug logs for paths and files console.log("Network:", NETWORK); diff --git a/contracts/scripts/setRegistryId.ts b/contracts/scripts/setRegistryId.ts index bc7d9d295..47193e7ca 100644 --- a/contracts/scripts/setRegistryId.ts +++ b/contracts/scripts/setRegistryId.ts @@ -16,9 +16,9 @@ const CSCA_ROOT = process.env.CSCA_ROOT; // Allow manual CSCA root setting // Network to Chain ID mapping const NETWORK_TO_CHAIN_ID: Record = { - "localhost": "31337", - "celoAlfajores": "44787", - "celo": "42220", + localhost: "31337", + celoAlfajores: "44787", + celo: "42220", }; // Get chain ID from network name @@ -30,7 +30,10 @@ const CHAIN_ID = getChainId(NETWORK); // Dynamic paths based on chain ID const deployedAddressesPath = path.join(__dirname, `../ignition/deployments/chain-${CHAIN_ID}/deployed_addresses.json`); -const contractAbiPath = path.join(__dirname, `../ignition/deployments/chain-${CHAIN_ID}/artifacts/DeployIdCardRegistryModule#IdentityRegistryIdCardImplV1.json`); +const contractAbiPath = path.join( + __dirname, + `../ignition/deployments/chain-${CHAIN_ID}/artifacts/DeployIdCardRegistryModule#IdentityRegistryIdCardImplV1.json`, +); // Debug logs for paths and files console.log("Network:", NETWORK); @@ -83,7 +86,11 @@ try { throw new Error("Hub address not found in deployed_addresses.json"); } - const identityRegistryIdCard = new ethers.Contract(registryIdCardAddress as string, identityRegistryIdCardAbi, wallet); + const identityRegistryIdCard = new ethers.Contract( + registryIdCardAddress as string, + identityRegistryIdCardAbi, + wallet, + ); console.log("Registry ID Card contract instance created"); // Update hub address diff --git a/contracts/test/example/airdrop.test.ts b/contracts/test/example/airdrop.test.ts index f9685f87f..3ef303a20 100644 --- a/contracts/test/example/airdrop.test.ts +++ b/contracts/test/example/airdrop.test.ts @@ -32,7 +32,7 @@ describe("Airdrop", () => { before(async () => { deployedActors = await deploySystemFixtures(); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); registerSecret = generateRandomFieldElement(); nullifier = generateRandomFieldElement(); attestationIds = [BigInt(ATTESTATION_ID.E_PASSPORT)]; @@ -74,15 +74,13 @@ describe("Airdrop", () => { ); const airdropFactory = await ethers.getContractFactory("Airdrop"); - airdrop = await airdropFactory - .connect(deployedActors.owner) - .deploy( - deployedActors.hub.target, - hashEndpointWithScope("https://test.com", "test-scope"), - 0, // the types show we need a contract version here - attestationIds, - token.target, - ); + airdrop = await airdropFactory.connect(deployedActors.owner).deploy( + deployedActors.hub.target, + hashEndpointWithScope("https://test.com", "test-scope"), + 0, // the types show we need a contract version here + attestationIds, + token.target, + ); await airdrop.waitForDeployment(); const verificationConfig = { @@ -275,7 +273,6 @@ describe("Airdrop", () => { }); it("should not able to register address by user if attestation id is invalid", async () => { - const { registry, owner, user1 } = deployedActors; const invalidCommitment = generateCommitment( @@ -290,7 +287,7 @@ describe("Airdrop", () => { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const invalidImt = new LeanIMT(hashFunction); await invalidImt.insert(BigInt(commitment)); await invalidImt.insert(BigInt(invalidCommitment)); @@ -352,7 +349,7 @@ describe("Airdrop", () => { const airdropFactory = await ethers.getContractFactory("Airdrop"); const newAirdrop = await airdropFactory .connect(owner) - .deploy(hub.target, hashEndpointWithScope("https://test.com", "test-scope"),0, attestationIds, token.target); + .deploy(hub.target, hashEndpointWithScope("https://test.com", "test-scope"), 0, attestationIds, token.target); await newAirdrop.waitForDeployment(); const verificationConfig = { diff --git a/contracts/test/integration/commitmentRegistration.test.ts b/contracts/test/integration/commitmentRegistration.test.ts index 9abfcd999..1301bb8ed 100644 --- a/contracts/test/integration/commitmentRegistration.test.ts +++ b/contracts/test/integration/commitmentRegistration.test.ts @@ -59,7 +59,7 @@ describe("Commitment Registration Tests", function () { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const imt = new LeanIMT(hashFunction); await imt.insert(BigInt(dscProof.pubSignals[CIRCUIT_CONSTANTS.DSC_TREE_LEAF_INDEX])); @@ -243,7 +243,7 @@ describe("Commitment Registration Tests", function () { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const imt = new LeanIMT(hashFunction); await imt.insert(BigInt(registerProof.pubSignals[CIRCUIT_CONSTANTS.REGISTER_COMMITMENT_INDEX])); diff --git a/contracts/test/integration/endToEnd.test.ts b/contracts/test/integration/endToEnd.test.ts index 6262bc6f0..7cf10c1f3 100644 --- a/contracts/test/integration/endToEnd.test.ts +++ b/contracts/test/integration/endToEnd.test.ts @@ -86,7 +86,7 @@ describe("End to End Tests", function () { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const imt = new LeanIMT(hashFunction); await imt.insert(BigInt(registerProof.pubSignals[CIRCUIT_CONSTANTS.REGISTER_COMMITMENT_INDEX])); @@ -183,20 +183,18 @@ describe("End to End Tests", function () { await token.waitForDeployment(); const airdropFactory = await ethers.getContractFactory("Airdrop"); - const airdrop = await airdropFactory - .connect(owner) - .deploy( - hub.target, - castFromScope("test-scope"), - ATTESTATION_ID.E_PASSPORT, - token.target, - true, - 20, - // @ts-expect-error - true, - countriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], - [true, true, true], - ); + const airdrop = await airdropFactory.connect(owner).deploy( + hub.target, + castFromScope("test-scope"), + ATTESTATION_ID.E_PASSPORT, + token.target, + true, + 20, + // @ts-expect-error + true, + countriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + [true, true, true], + ); await airdrop.waitForDeployment(); await token.connect(owner).mint(airdrop.target, BigInt(1000000000000000000)); diff --git a/contracts/test/integration/vcAndDisclose.test.ts b/contracts/test/integration/vcAndDisclose.test.ts index bd6cf65cc..c15d799c8 100644 --- a/contracts/test/integration/vcAndDisclose.test.ts +++ b/contracts/test/integration/vcAndDisclose.test.ts @@ -10,11 +10,7 @@ import { generateCommitment } from "@selfxyz/common/utils/passports/passport"; import { BigNumberish } from "ethers"; import { generateRandomFieldElement, getStartOfDayTimestamp, splitHexFromBack } from "../utils/utils"; import { Formatter, CircuitAttributeHandler } from "../utils/formatter"; -import { - formatCountriesList, - reverseBytes, - reverseCountryBytes, -} from "@selfxyz/common/utils/circuits/formatInputs"; +import { formatCountriesList, reverseBytes, reverseCountryBytes } from "@selfxyz/common/utils/circuits/formatInputs"; import { getPackedForbiddenCountries } from "@selfxyz/common/utils/contracts/forbiddenCountries"; import { countries, Country3LetterCode } from "@selfxyz/common/constants/countries"; import fs from "fs"; @@ -47,7 +43,7 @@ describe("VC and Disclose", () => { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); imt = new LeanIMT(hashFunction); await imt.insert(BigInt(commitment)); @@ -93,7 +89,7 @@ describe("VC and Disclose", () => { "ABC", "CBA", ] as Country3LetterCode[]; - forbiddenCountriesListPacked = getPackedForbiddenCountries(forbiddenCountriesList) + forbiddenCountriesListPacked = getPackedForbiddenCountries(forbiddenCountriesList); invalidForbiddenCountriesList = ["AAA", "ABC", "CBA", "CBA"]; // const invalidWholePacked = reverseBytes(Formatter.bytesToHexString(new Uint8Array(formatCountriesList(invalidForbiddenCountriesList)))); @@ -133,11 +129,16 @@ describe("VC and Disclose", () => { it("should verify and get result successfully", async () => { const { hub, registry, owner } = deployedActors; - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked.slice(0, 4) as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked.slice(0, 4) as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], vcAndDiscloseProof: vcAndDiscloseProof, }; diff --git a/contracts/test/integration/verifyAll.test.ts b/contracts/test/integration/verifyAll.test.ts index 3562311b7..6fe782c73 100644 --- a/contracts/test/integration/verifyAll.test.ts +++ b/contracts/test/integration/verifyAll.test.ts @@ -41,7 +41,7 @@ describe("VerifyAll", () => { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); imt = new LeanIMT(hashFunction); await imt.insert(BigInt(commitment)); @@ -178,7 +178,7 @@ describe("VerifyAll", () => { await registry.connect(owner).devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); vcAndDiscloseProof.pubSignals[CIRCUIT_CONSTANTS.VC_AND_DISCLOSE_MERKLE_ROOT_INDEX] = generateRandomFieldElement(); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -199,7 +199,7 @@ describe("VerifyAll", () => { await registry.connect(owner).devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -222,7 +222,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.a[0] = generateRandomFieldElement(); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: false, olderThan: "20", forbiddenCountriesEnabled: false, @@ -245,7 +245,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.pubSignals[CIRCUIT_CONSTANTS.VC_AND_DISCLOSE_CURRENT_DATE_INDEX] = 0; - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -266,7 +266,7 @@ describe("VerifyAll", () => { const { registry, owner } = deployedActors; await registry.connect(owner).devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); - const vcAndDiscloseHubProof : VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "21", // Higher than the age in proof forbiddenCountriesEnabled: false, @@ -304,7 +304,7 @@ describe("VerifyAll", () => { "0", ); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: false, @@ -329,7 +329,7 @@ describe("VerifyAll", () => { const { registry, owner } = deployedActors; await registry.connect(owner).devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -350,7 +350,7 @@ describe("VerifyAll", () => { const { registry, owner } = deployedActors; await registry.connect(owner).devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -378,7 +378,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.pubSignals[CIRCUIT_CONSTANTS.VC_AND_DISCLOSE_PASSPORT_NO_SMT_ROOT_INDEX] = generateRandomFieldElement(); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -402,7 +402,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.pubSignals[CIRCUIT_CONSTANTS.VC_AND_DISCLOSE_NAME_DOB_SMT_ROOT_INDEX] = generateRandomFieldElement(); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -426,7 +426,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.pubSignals[CIRCUIT_CONSTANTS.VC_AND_DISCLOSE_NAME_YOB_SMT_ROOT_INDEX] = generateRandomFieldElement(); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -479,7 +479,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.a[0] = generateRandomFieldElement(); - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, @@ -502,7 +502,7 @@ describe("VerifyAll", () => { vcAndDiscloseProof.pubSignals[CIRCUIT_CONSTANTS.VC_AND_DISCLOSE_CURRENT_DATE_INDEX] = 0; - const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { + const vcAndDiscloseHubProof: VcAndDiscloseHubProof = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, diff --git a/contracts/test/unit/CustomVerifier.test.ts b/contracts/test/unit/CustomVerifier.test.ts index 01f85f507..ab168b0c5 100644 --- a/contracts/test/unit/CustomVerifier.test.ts +++ b/contracts/test/unit/CustomVerifier.test.ts @@ -4,7 +4,7 @@ import { TestCustomVerifier, CustomVerifier } from "../../typechain-types"; export const AttestationId = { E_PASSPORT: "0x0000000000000000000000000000000000000000000000000000000000000001", - EU_ID_CARD: "0x0000000000000000000000000000000000000000000000000000000000000002" + EU_ID_CARD: "0x0000000000000000000000000000000000000000000000000000000000000002", } as const; describe("CustomVerifier", function () { @@ -18,8 +18,8 @@ describe("CustomVerifier", function () { const TestVerifierFactory = await ethers.getContractFactory("TestCustomVerifier", { libraries: { - CustomVerifier: await customVerifier.getAddress() - } + CustomVerifier: await customVerifier.getAddress(), + }, }); testVerifier = await TestVerifierFactory.deploy(); await testVerifier.waitForDeployment(); @@ -35,7 +35,7 @@ describe("CustomVerifier", function () { mrzBytes, // revealedDataPacked (bytes) ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // userIdentifier (uint256) ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // nullifier (uint256) - [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)] // forbiddenCountriesListPacked + [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], // forbiddenCountriesListPacked ]; it("should verify passport with all checks disabled", async function () { @@ -44,13 +44,16 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.E_PASSPORT, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.E_PASSPORT); @@ -62,14 +65,20 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [true, false, true] + [true, false, true], ]; - expect(async () => await testVerifier.testCustomVerify( - AttestationId.E_PASSPORT, - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) - )).to.be.revertedWithCustomError(customVerifier, "INVALID_OFAC"); + expect( + async () => + await testVerifier.testCustomVerify( + AttestationId.E_PASSPORT, + ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), + ), + ).to.be.revertedWithCustomError(customVerifier, "INVALID_OFAC"); }); it("should return proper OFAC results", async function () { @@ -78,20 +87,23 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.E_PASSPORT, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.E_PASSPORT); expect(result.ofac[0]).to.equal(true); expect(result.ofac[1]).to.equal(false); expect(result.ofac[2]).to.equal(true); - }) + }); it("should verify passport with forbidden countries check", async function () { const config = [ @@ -99,13 +111,16 @@ describe("CustomVerifier", function () { 0, true, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.E_PASSPORT, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.E_PASSPORT); @@ -117,14 +132,20 @@ describe("CustomVerifier", function () { 19, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; - expect(async () => await testVerifier.testCustomVerify( - AttestationId.E_PASSPORT, - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) - )).to.be.revertedWithCustomError(customVerifier, "INVALID_OLDER_THAN"); + expect( + async () => + await testVerifier.testCustomVerify( + AttestationId.E_PASSPORT, + ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), + ), + ).to.be.revertedWithCustomError(customVerifier, "INVALID_OLDER_THAN"); }); it("should not throw an error if older than is not enabled", async function () { @@ -133,17 +154,20 @@ describe("CustomVerifier", function () { 19, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.E_PASSPORT, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.E_PASSPORT); - }) + }); it("should not throw an error if age is valid", async function () { const config = [ @@ -151,18 +175,21 @@ describe("CustomVerifier", function () { 18, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.E_PASSPORT, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [samplePassportOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [samplePassportOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.E_PASSPORT); expect(result.olderThan).to.equal(18); - }) + }); }); describe("ID Card Verification", function () { @@ -173,7 +200,7 @@ describe("CustomVerifier", function () { mrzBytes, // revealedDataPacked (bytes) ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // userIdentifier (uint256) ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // nullifier (uint256) - [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)] // forbiddenCountriesListPacked + [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], // forbiddenCountriesListPacked ]; it("should verify ID card with all checks disabled", async function () { @@ -182,13 +209,16 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.EU_ID_CARD, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.EU_ID_CARD); @@ -200,14 +230,20 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [true, false, true] + [true, false, true], ]; - expect(async () => await testVerifier.testCustomVerify( - AttestationId.EU_ID_CARD, - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) - )).to.be.revertedWithCustomError(customVerifier, "INVALID_OFAC"); + expect( + async () => + await testVerifier.testCustomVerify( + AttestationId.EU_ID_CARD, + ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), + ), + ).to.be.revertedWithCustomError(customVerifier, "INVALID_OFAC"); }); it("should return proper OFAC results", async function () { @@ -216,13 +252,16 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.EU_ID_CARD, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.EU_ID_CARD); @@ -237,13 +276,16 @@ describe("CustomVerifier", function () { 0, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.EU_ID_CARD, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.EU_ID_CARD); @@ -255,13 +297,16 @@ describe("CustomVerifier", function () { 0, true, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.EU_ID_CARD, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.EU_ID_CARD); @@ -273,14 +318,20 @@ describe("CustomVerifier", function () { 19, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; - expect(async () => await testVerifier.testCustomVerify( - AttestationId.EU_ID_CARD, - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) - )).to.be.revertedWithCustomError(customVerifier, "INVALID_OLDER_THAN"); + expect( + async () => + await testVerifier.testCustomVerify( + AttestationId.EU_ID_CARD, + ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), + ), + ).to.be.revertedWithCustomError(customVerifier, "INVALID_OLDER_THAN"); }); it("should not throw an error if older than is not enabled", async function () { @@ -289,13 +340,16 @@ describe("CustomVerifier", function () { 19, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.EU_ID_CARD, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.EU_ID_CARD); @@ -307,13 +361,16 @@ describe("CustomVerifier", function () { 18, false, [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] + [false, false, false], ]; const result = await testVerifier.testCustomVerify( AttestationId.EU_ID_CARD, ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [sampleIdCardOutput]) + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [sampleIdCardOutput], + ), ); expect(result.attestationId).to.equal(AttestationId.EU_ID_CARD); @@ -321,29 +378,34 @@ describe("CustomVerifier", function () { }); }); - it("should revert with invalid attestation ID", async function () { - const config = [ - false, - 0, - false, - [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], - [false, false, false] - ]; + it("should revert with invalid attestation ID", async function () { + const config = [ + false, + 0, + false, + [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], + [false, false, false], + ]; - const invalidAttestationId = ethers.zeroPadValue(ethers.toBeHex(999), 32); - - await expect( - testVerifier.testCustomVerify( - invalidAttestationId, - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), - ethers.AbiCoder.defaultAbiCoder().encode(["tuple(uint256,bytes,uint256,uint256,uint256[4])"], [[ - ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // attestationId (uint256) - ethers.randomBytes(88), // revealedDataPacked (bytes) - ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // userIdentifier (uint256) - ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // nullifier (uint256) - [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)] // forbiddenCountriesListPacked - ]]) - ) - ).to.be.revertedWithCustomError(customVerifier, "INVALID_ATTESTATION_ID"); + const invalidAttestationId = ethers.zeroPadValue(ethers.toBeHex(999), 32); + + await expect( + testVerifier.testCustomVerify( + invalidAttestationId, + ethers.AbiCoder.defaultAbiCoder().encode(["tuple(bool,uint256,bool,uint256[4],bool[3])"], [config]), + ethers.AbiCoder.defaultAbiCoder().encode( + ["tuple(uint256,bytes,uint256,uint256,uint256[4])"], + [ + [ + ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // attestationId (uint256) + ethers.randomBytes(88), // revealedDataPacked (bytes) + ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // userIdentifier (uint256) + ethers.getBigInt(ethers.hexlify(ethers.randomBytes(32))), // nullifier (uint256) + [ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0), ethers.getBigInt(0)], // forbiddenCountriesListPacked + ], + ], + ), + ), + ).to.be.revertedWithCustomError(customVerifier, "INVALID_ATTESTATION_ID"); }); }); diff --git a/contracts/test/unit/GenericFormatter.test.ts b/contracts/test/unit/GenericFormatter.test.ts index b704a5466..4e84a601a 100644 --- a/contracts/test/unit/GenericFormatter.test.ts +++ b/contracts/test/unit/GenericFormatter.test.ts @@ -19,7 +19,7 @@ describe("GenericFormatter", function () { olderThan: 18, forbiddenCountriesEnabled: false, forbiddenCountriesListPacked: [0n, 0n, 0n, 0n], - ofacEnabled: [false, false, false] + ofacEnabled: [false, false, false], }; const verificationConfigV2 = await testGenericFormatter.testFromV1Config(verificationConfigV1); @@ -28,7 +28,9 @@ describe("GenericFormatter", function () { expect(verificationConfigV2.olderThanEnabled).to.equal(verificationConfigV1.olderThanEnabled); expect(verificationConfigV2.olderThan).to.equal(verificationConfigV1.olderThan); expect(verificationConfigV2.forbiddenCountriesEnabled).to.equal(verificationConfigV1.forbiddenCountriesEnabled); - expect(verificationConfigV2.forbiddenCountriesListPacked).to.deep.equal(verificationConfigV1.forbiddenCountriesListPacked); + expect(verificationConfigV2.forbiddenCountriesListPacked).to.deep.equal( + verificationConfigV1.forbiddenCountriesListPacked, + ); expect(verificationConfigV2.ofacEnabled).to.deep.equal(verificationConfigV1.ofacEnabled); }); @@ -39,27 +41,35 @@ describe("GenericFormatter", function () { olderThan: 18, forbiddenCountriesEnabled: false, forbiddenCountriesListPacked: [0n, 0n, 0n, 0n], - ofacEnabled: [false, false, false] + ofacEnabled: [false, false, false], }; //abi encode the verificationConfigV2 struct const verificationConfigV2Bytes = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(bool,uint256,bool,uint256[4],bool[3])"], - [[ - verificationConfigV2.olderThanEnabled, - verificationConfigV2.olderThan, - verificationConfigV2.forbiddenCountriesEnabled, - verificationConfigV2.forbiddenCountriesListPacked, - verificationConfigV2.ofacEnabled - ]]); + [ + [ + verificationConfigV2.olderThanEnabled, + verificationConfigV2.olderThan, + verificationConfigV2.forbiddenCountriesEnabled, + verificationConfigV2.forbiddenCountriesListPacked, + verificationConfigV2.ofacEnabled, + ], + ], + ); - const verificationConfigV2BytesDecoded = await testGenericFormatter.testVerificationConfigFromBytes(verificationConfigV2Bytes); + const verificationConfigV2BytesDecoded = + await testGenericFormatter.testVerificationConfigFromBytes(verificationConfigV2Bytes); // Add your assertions here expect(verificationConfigV2BytesDecoded.olderThanEnabled).to.equal(verificationConfigV2.olderThanEnabled); expect(verificationConfigV2BytesDecoded.olderThan).to.equal(verificationConfigV2.olderThan); - expect(verificationConfigV2BytesDecoded.forbiddenCountriesEnabled).to.equal(verificationConfigV2.forbiddenCountriesEnabled); - expect(verificationConfigV2BytesDecoded.forbiddenCountriesListPacked).to.deep.equal(verificationConfigV2.forbiddenCountriesListPacked); + expect(verificationConfigV2BytesDecoded.forbiddenCountriesEnabled).to.equal( + verificationConfigV2.forbiddenCountriesEnabled, + ); + expect(verificationConfigV2BytesDecoded.forbiddenCountriesListPacked).to.deep.equal( + verificationConfigV2.forbiddenCountriesListPacked, + ); expect(verificationConfigV2BytesDecoded.ofacEnabled).to.deep.equal(verificationConfigV2.ofacEnabled); }); @@ -70,14 +80,14 @@ describe("GenericFormatter", function () { olderThan: 18, forbiddenCountriesEnabled: false, forbiddenCountriesListPacked: [0n, 0n, 0n, 0n], - ofacEnabled: [false, false, false] + ofacEnabled: [false, false, false], }; const verificationConfigLatest = await testGenericFormatter.testFormatV1Config(verificationConfigV1); const verificationConfigLatestDecoded = ethers.AbiCoder.defaultAbiCoder().decode( ["tuple(bool,uint256,bool,uint256[4],bool[3])"], - verificationConfigLatest + verificationConfigLatest, ); // Add your assertions here @@ -95,14 +105,14 @@ describe("GenericFormatter", function () { olderThan: 18, forbiddenCountriesEnabled: false, forbiddenCountriesListPacked: [0n, 0n, 0n, 0n], - ofacEnabled: [false, false, false] + ofacEnabled: [false, false, false], }; const verificationConfigV2Bytes = await testGenericFormatter.testFormatV2Config(verificationConfigV2); const verificationConfigLatest = ethers.AbiCoder.defaultAbiCoder().decode( ["tuple(bool,uint256,bool,uint256[4],bool[3])"], - verificationConfigV2Bytes + verificationConfigV2Bytes, ); // Add your assertions here @@ -128,14 +138,14 @@ describe("GenericFormatter", function () { gender: "Male", expiryDate: "2025-01-01", olderThan: 18, - ofac: [false, false, false] + ofac: [false, false, false], }; const genericDiscloseOutputV2Bytes = await testGenericFormatter.testToV2Struct(genericDiscloseOutputV2); const genericDiscloseOutputLatest = ethers.AbiCoder.defaultAbiCoder().decode( ["tuple(bytes32,uint256,uint256,uint256[4],string,string[],string,string,string,string,string,uint256,bool[3])"], - genericDiscloseOutputV2Bytes + genericDiscloseOutputV2Bytes, ); expect(genericDiscloseOutputV2.attestationId.toString()).to.equal(genericDiscloseOutputV2.attestationId); diff --git a/contracts/test/unit/IdentityRegistry.test.ts b/contracts/test/unit/IdentityRegistry.test.ts index cd6738e33..8a387762b 100644 --- a/contracts/test/unit/IdentityRegistry.test.ts +++ b/contracts/test/unit/IdentityRegistry.test.ts @@ -192,7 +192,7 @@ describe("Unit Tests for IdentityRegistry", () => { const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until verison 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const imt = new LeanIMT(hashFunction); imt.insert(BigInt(commitment)); expect(imt.root).to.equal(root); diff --git a/contracts/test/unit/formatter.test.ts b/contracts/test/unit/formatter.test.ts index 1d5c4b301..568ce8bdd 100644 --- a/contracts/test/unit/formatter.test.ts +++ b/contracts/test/unit/formatter.test.ts @@ -154,14 +154,21 @@ describe("Formatter", function () { const input2 = "0x4542524c42425242444742524842534842455a415355415742414d52414752"; const input3 = "0x4e41434d484b5650434e52424c4f424e5442554d424e45425a4c42554d424c"; const input4 = "0x4853454d4559424d5a45575a5455564b4e445453454e4843564943"; - const contractResult = await testFormatter.testExtractForbiddenCountriesFromPacked([input1, input2, input3, input4]); + const contractResult = await testFormatter.testExtractForbiddenCountriesFromPacked([ + input1, + input2, + input3, + input4, + ]); const tsResult: string[] = Formatter.extractForbiddenCountriesFromPacked([input1, input2, input3, input4], "id"); - let formattedTsResult = tsResult.map((item: string, index: number) => { - if (index % 3 === 0) { - return item + tsResult[index + 1] + tsResult[index + 2]; - } - return undefined; - }).filter(Boolean); + let formattedTsResult = tsResult + .map((item: string, index: number) => { + if (index % 3 === 0) { + return item + tsResult[index + 1] + tsResult[index + 2]; + } + return undefined; + }) + .filter(Boolean); expect(contractResult).to.deep.equal(formattedTsResult); }); diff --git a/contracts/test/utils/deploymentV2.ts b/contracts/test/utils/deploymentV2.ts index 9f585031a..5c1fdf935 100644 --- a/contracts/test/utils/deploymentV2.ts +++ b/contracts/test/utils/deploymentV2.ts @@ -7,9 +7,7 @@ import { getCscaTreeRoot } from "@selfxyz/common/utils/trees"; import { PassportData } from "@selfxyz/common/utils/types"; import { getSMTs } from "./generateProof"; import serialized_csca_tree from "../../../common/pubkeys/serialized_csca_tree.json"; -import { - DeployedActorsV2, -} from "./types"; +import { DeployedActorsV2 } from "./types"; import { hashEndpointWithScope } from "@selfxyz/common/utils/scope"; // Verifier artifacts (local staging) @@ -52,7 +50,7 @@ export async function deploySystemFixturesV2(): Promise { const vcAndDiscloseVerifierArtifact = VcAndDiscloseVerifierArtifactLocal; const vcAndDiscloseVerifierFactory = await ethers.getContractFactory( vcAndDiscloseVerifierArtifact.abi, - vcAndDiscloseVerifierArtifact.bytecode + vcAndDiscloseVerifierArtifact.bytecode, ); vcAndDiscloseVerifier = await vcAndDiscloseVerifierFactory.connect(owner).deploy(); await vcAndDiscloseVerifier.waitForDeployment(); @@ -61,7 +59,7 @@ export async function deploySystemFixturesV2(): Promise { const vcAndDiscloseIdVerifierArtifact = VcAndDiscloseIdVerifierArtifactLocal; const vcAndDiscloseIdVerifierFactory = await ethers.getContractFactory( vcAndDiscloseIdVerifierArtifact.abi, - vcAndDiscloseIdVerifierArtifact.bytecode + vcAndDiscloseIdVerifierArtifact.bytecode, ); vcAndDiscloseIdVerifier = await vcAndDiscloseIdVerifierFactory.connect(owner).deploy(); await vcAndDiscloseIdVerifier.waitForDeployment(); @@ -70,7 +68,7 @@ export async function deploySystemFixturesV2(): Promise { const registerVerifierArtifact = RegisterVerifierArtifactLocal; const registerVerifierFactory = await ethers.getContractFactory( registerVerifierArtifact.abi, - registerVerifierArtifact.bytecode + registerVerifierArtifact.bytecode, ); registerVerifier = await registerVerifierFactory.connect(owner).deploy(); await registerVerifier.waitForDeployment(); @@ -79,17 +77,14 @@ export async function deploySystemFixturesV2(): Promise { const registerIdVerifierArtifact = RegisterIdVerifierArtifactLocal; const registerIdVerifierFactory = await ethers.getContractFactory( registerIdVerifierArtifact.abi, - registerIdVerifierArtifact.bytecode + registerIdVerifierArtifact.bytecode, ); registerIdVerifier = await registerIdVerifierFactory.connect(owner).deploy(); await registerIdVerifier.waitForDeployment(); // Deploy dsc verifier const dscVerifierArtifact = DscVerifierArtifactLocal; - const dscVerifierFactory = await ethers.getContractFactory( - dscVerifierArtifact.abi, - dscVerifierArtifact.bytecode - ); + const dscVerifierFactory = await ethers.getContractFactory(dscVerifierArtifact.abi, dscVerifierArtifact.bytecode); dscVerifier = await dscVerifierFactory.connect(owner).deploy(); await dscVerifier.waitForDeployment(); @@ -109,37 +104,28 @@ export async function deploySystemFixturesV2(): Promise { await genericFormatter.waitForDeployment(); // Deploy IdentityRegistryImplV1 (same registry as V1) - const IdentityRegistryImplFactory = await ethers.getContractFactory( - "IdentityRegistryImplV1", - { - libraries: { - PoseidonT3: poseidonT3.target - } - } - ); + const IdentityRegistryImplFactory = await ethers.getContractFactory("IdentityRegistryImplV1", { + libraries: { + PoseidonT3: poseidonT3.target, + }, + }); identityRegistryImpl = await IdentityRegistryImplFactory.connect(owner).deploy(); await identityRegistryImpl.waitForDeployment(); // Deploy IdentityRegistryIdCardImplV1 for ID cards - const IdentityRegistryIdImplFactory = await ethers.getContractFactory( - "IdentityRegistryIdCardImplV1", - { - libraries: { - PoseidonT3: poseidonT3.target - } - } - ); + const IdentityRegistryIdImplFactory = await ethers.getContractFactory("IdentityRegistryIdCardImplV1", { + libraries: { + PoseidonT3: poseidonT3.target, + }, + }); identityRegistryIdImpl = await IdentityRegistryIdImplFactory.connect(owner).deploy(); await identityRegistryIdImpl.waitForDeployment(); // Deploy IdentityVerificationHubImplV2 - const IdentityVerificationHubImplV2Factory = await ethers.getContractFactory( - "IdentityVerificationHubImplV2", - { - libraries: { - CustomVerifier: customVerifier.target - } - } - ); + const IdentityVerificationHubImplV2Factory = await ethers.getContractFactory("IdentityVerificationHubImplV2", { + libraries: { + CustomVerifier: customVerifier.target, + }, + }); identityVerificationHubImplV2 = await IdentityVerificationHubImplV2Factory.connect(owner).deploy(); await identityVerificationHubImplV2.waitForDeployment(); @@ -147,19 +133,25 @@ export async function deploySystemFixturesV2(): Promise { const temporaryHubAddress = "0x0000000000000000000000000000000000000000"; const registryInitData = identityRegistryImpl.interface.encodeFunctionData("initialize", [temporaryHubAddress]); const registryProxyFactory = await ethers.getContractFactory("IdentityRegistry"); - identityRegistryProxy = await registryProxyFactory.connect(owner).deploy(identityRegistryImpl.target, registryInitData); + identityRegistryProxy = await registryProxyFactory + .connect(owner) + .deploy(identityRegistryImpl.target, registryInitData); await identityRegistryProxy.waitForDeployment(); // Deploy ID card registry with temporary hub address const registryIdInitData = identityRegistryIdImpl.interface.encodeFunctionData("initialize", [temporaryHubAddress]); const registryIdProxyFactory = await ethers.getContractFactory("IdentityRegistry"); - identityRegistryIdProxy = await registryIdProxyFactory.connect(owner).deploy(identityRegistryIdImpl.target, registryIdInitData); + identityRegistryIdProxy = await registryIdProxyFactory + .connect(owner) + .deploy(identityRegistryIdImpl.target, registryIdInitData); await identityRegistryIdProxy.waitForDeployment(); // Deploy hub V2 with simple initialization (V2 has different initialization) const initializeDataV2 = identityVerificationHubImplV2.interface.encodeFunctionData("initialize"); const hubFactory = await ethers.getContractFactory("IdentityVerificationHub"); - identityVerificationHubV2 = await hubFactory.connect(owner).deploy(identityVerificationHubImplV2.target, initializeDataV2); + identityVerificationHubV2 = await hubFactory + .connect(owner) + .deploy(identityVerificationHubImplV2.target, initializeDataV2); await identityVerificationHubV2.waitForDeployment(); // Get contracts with implementation ABI and update hub address @@ -171,10 +163,10 @@ export async function deploySystemFixturesV2(): Promise { const updateIdHubTx = await registryIdContract.updateHub(identityVerificationHubV2.target); await updateIdHubTx.wait(); - const hubContract = await ethers.getContractAt( + const hubContract = (await ethers.getContractAt( "IdentityVerificationHubImplV2", - identityVerificationHubV2.target - ) as any; + identityVerificationHubV2.target, + )) as any; // Initialize roots const csca_root = getCscaTreeRoot(serialized_csca_tree); @@ -205,26 +197,18 @@ export async function deploySystemFixturesV2(): Promise { await hubContract.updateRegisterCircuitVerifier( E_PASSPORT, RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096, - registerVerifier.target + registerVerifier.target, ); await hubContract.updateRegisterCircuitVerifier( EU_ID_CARD, RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096, - registerIdVerifier.target + registerIdVerifier.target, ); // Update DSC verifiers - await hubContract.updateDscVerifier( - E_PASSPORT, - DscVerifierId.dsc_sha256_rsa_65537_4096, - dscVerifier.target - ); + await hubContract.updateDscVerifier(E_PASSPORT, DscVerifierId.dsc_sha256_rsa_65537_4096, dscVerifier.target); // Add DSC verifier for EU_ID_CARD as well - await hubContract.updateDscVerifier( - EU_ID_CARD, - DscVerifierId.dsc_sha256_rsa_65537_4096, - dscVerifier.target - ); + await hubContract.updateDscVerifier(EU_ID_CARD, DscVerifierId.dsc_sha256_rsa_65537_4096, dscVerifier.target); // Deploy TestSelfVerificationRoot const testScope = hashEndpointWithScope("example.com", "test-scope"); diff --git a/contracts/test/utils/formatter.ts b/contracts/test/utils/formatter.ts index 9a01bd67e..a74ef9fe5 100644 --- a/contracts/test/utils/formatter.ts +++ b/contracts/test/utils/formatter.ts @@ -88,15 +88,14 @@ export class Formatter { ); } - static extractForbiddenCountriesFromPacked(revealedData_packed: string | string[], - id_type: 'passport' | 'id' + static extractForbiddenCountriesFromPacked( + revealedData_packed: string | string[], + id_type: "passport" | "id", ): string[] { // If revealedData_packed is not an array, convert it to an array - const packedArray = Array.isArray(revealedData_packed) - ? revealedData_packed - : [revealedData_packed]; + const packedArray = Array.isArray(revealedData_packed) ? revealedData_packed : [revealedData_packed]; - const bytesCount = id_type === 'passport' ? [31, 31, 31] : [31, 31, 31, 27]; // nb of bytes in each of the first three field elements + const bytesCount = id_type === "passport" ? [31, 31, 31] : [31, 31, 31, 27]; // nb of bytes in each of the first three field elements const bytesArray = packedArray.flatMap((element: string, index: number) => { const bytes = bytesCount[index] || 31; // Use 31 as default if index is out of range const elementBigInt = BigInt(element); diff --git a/contracts/test/utils/generateProof.ts b/contracts/test/utils/generateProof.ts index e5ed8b3fd..52520a578 100644 --- a/contracts/test/utils/generateProof.ts +++ b/contracts/test/utils/generateProof.ts @@ -1,5 +1,5 @@ -import { LeanIMT } from "@openpassport/zk-kit-lean-imt" -import { ChildNodes, SMT } from "@openpassport/zk-kit-smt" +import { LeanIMT } from "@openpassport/zk-kit-lean-imt"; +import { ChildNodes, SMT } from "@openpassport/zk-kit-smt"; import fs from "fs"; import path from "path"; import { poseidon2, poseidon3 } from "poseidon-lite"; @@ -26,11 +26,11 @@ const registerCircuits: CircuitArtifacts = { }, }; const registerCircuitsId: CircuitArtifacts = { - register_id_sha256_sha256_sha256_rsa_65537_4096: { - wasm: "../circuits/build/register_id/register_id_sha256_sha256_sha256_rsa_65537_4096/register_id_sha256_sha256_sha256_rsa_65537_4096_js/register_id_sha256_sha256_sha256_rsa_65537_4096.wasm", - zkey: "../circuits/build/register_id/register_id_sha256_sha256_sha256_rsa_65537_4096/register_id_sha256_sha256_sha256_rsa_65537_4096_final.zkey", - vkey: "../circuits/build/register_id/register_id_sha256_sha256_sha256_rsa_65537_4096/register_id_sha256_sha256_sha256_rsa_65537_4096_vkey.json", - }, + register_id_sha256_sha256_sha256_rsa_65537_4096: { + wasm: "../circuits/build/register_id/register_id_sha256_sha256_sha256_rsa_65537_4096/register_id_sha256_sha256_sha256_rsa_65537_4096_js/register_id_sha256_sha256_sha256_rsa_65537_4096.wasm", + zkey: "../circuits/build/register_id/register_id_sha256_sha256_sha256_rsa_65537_4096/register_id_sha256_sha256_sha256_rsa_65537_4096_final.zkey", + vkey: "../circuits/build/register_id/register_id_sha256_sha256_sha256_rsa_65537_4096/register_id_sha256_sha256_sha256_rsa_65537_4096_vkey.json", + }, }; const dscCircuits: CircuitArtifacts = { dsc_sha256_rsa_65537_4096: { @@ -47,11 +47,11 @@ const vcAndDiscloseCircuits: CircuitArtifacts = { }, }; const vcAndDiscloseIdCircuits: CircuitArtifacts = { - vc_and_disclose_id: { - wasm: "../circuits/build/disclose/vc_and_disclose_id/vc_and_disclose_id_js/vc_and_disclose_id.wasm", - zkey: "../circuits/build/disclose/vc_and_disclose_id/vc_and_disclose_id_final.zkey", - vkey: "../circuits/build/disclose/vc_and_disclose_id/vc_and_disclose_id_vkey.json", - } + vc_and_disclose_id: { + wasm: "../circuits/build/disclose/vc_and_disclose_id/vc_and_disclose_id_js/vc_and_disclose_id.wasm", + zkey: "../circuits/build/disclose/vc_and_disclose_id/vc_and_disclose_id_final.zkey", + vkey: "../circuits/build/disclose/vc_and_disclose_id/vc_and_disclose_id_vkey.json", + }, }; export async function generateRegisterProof(secret: string, passportData: PassportData): Promise { @@ -87,9 +87,12 @@ export async function generateRegisterProof(secret: string, passportData: Passpo return fixedProof; } -export async function generateRegisterIdProof(secret: string, passportData: PassportData): Promise { +export async function generateRegisterIdProof( + secret: string, + passportData: PassportData, +): Promise { // Get the correct circuit name based on passport data - const circuitName = getCircuitNameFromPassportData(passportData, 'register'); + const circuitName = getCircuitNameFromPassportData(passportData, "register"); // Get the circuit inputs for ID card - passportData should already be parsed from genMockIdDocAndInitDataParsing const registerCircuitInputs: CircuitSignals = await generateCircuitInputsRegister( @@ -103,7 +106,7 @@ export async function generateRegisterIdProof(secret: string, passportData: Pass let artifactKey; // Check if this is an ID circuit - if (circuitName.startsWith('register_id_')) { + if (circuitName.startsWith("register_id_")) { circuitArtifacts = registerCircuitsId; // Use the actual circuit name as the key artifactKey = circuitName; @@ -123,9 +126,7 @@ export async function generateRegisterIdProof(secret: string, passportData: Pass ); // Verify the proof - const vKey = JSON.parse( - fs.readFileSync(circuitArtifacts[artifactKey].vkey, "utf8"), - ); + const vKey = JSON.parse(fs.readFileSync(circuitArtifacts[artifactKey].vkey, "utf8")); const isValid = await groth16.verify(vKey, registerProof.publicSignals, registerProof.proof); if (!isValid) { throw new Error("Generated register ID proof verification failed"); @@ -366,8 +367,8 @@ export async function generateVcAndDiscloseIdProof( const idCardPassportData = { ...passportData, - documentType: passportData.documentType.includes('id') ? passportData.documentType : 'id_card', - documentCategory: 'id_card' as const + documentType: passportData.documentType.includes("id") ? passportData.documentType : "id_card", + documentCategory: "id_card" as const, }; const vcAndDiscloseCircuitInputs: CircuitSignals = generateCircuitInputsVCandDisclose( @@ -419,7 +420,7 @@ export function parseSolidityCalldata(rawCallData: string, _type: T): T { pubSignals: parsed[3].map((x: string) => { const cleaned = x.replace(/"/g, ""); // Convert hex strings to decimal strings for Solidity compatibility - if (cleaned.startsWith('0x')) { + if (cleaned.startsWith("0x")) { return BigInt(cleaned).toString(); } return cleaned; diff --git a/contracts/test/utils/types.ts b/contracts/test/utils/types.ts index cc69510ce..3f1ef2539 100644 --- a/contracts/test/utils/types.ts +++ b/contracts/test/utils/types.ts @@ -27,7 +27,7 @@ import { IIdentityRegistryV1, IRegisterCircuitVerifier, IDscCircuitVerifier, - IVcAndDiscloseCircuitVerifier + IVcAndDiscloseCircuitVerifier, } from "../../typechain-types"; import { DscVerifierId, RegisterVerifierId } from "@selfxyz/common"; @@ -40,9 +40,15 @@ export type VcAndDiscloseProof = IVcAndDiscloseCircuitVerifier.VcAndDiscloseProo // Type definitions export type VcAndDiscloseVerifier = typeof process.env.TEST_ENV extends "local" ? LocalVerifier : ProdVerifier; -export type VcAndDiscloseIdVerifier = typeof process.env.TEST_ENV extends "local" ? LocalIdCardVerifier : ProdIdCardVerifier; -export type RegisterVerifier = typeof process.env.TEST_ENV extends "local" ? LocalRegisterVerifier : ProdRegisterVerifier; -export type IdCardRegisterVerifier = typeof process.env.TEST_ENV extends "local" ? LocalIdCardRegisterVerifier : ProdIdCardRegisterVerifier; +export type VcAndDiscloseIdVerifier = typeof process.env.TEST_ENV extends "local" + ? LocalIdCardVerifier + : ProdIdCardVerifier; +export type RegisterVerifier = typeof process.env.TEST_ENV extends "local" + ? LocalRegisterVerifier + : ProdRegisterVerifier; +export type IdCardRegisterVerifier = typeof process.env.TEST_ENV extends "local" + ? LocalIdCardRegisterVerifier + : ProdIdCardRegisterVerifier; export type DscVerifier = typeof process.env.TEST_ENV extends "local" ? LocalDscVerifier : ProdDscVerifier; export interface DeployedActors { diff --git a/contracts/test/v2/discloseId.test.ts b/contracts/test/v2/discloseId.test.ts index 45d02d36e..35c3a09f2 100644 --- a/contracts/test/v2/discloseId.test.ts +++ b/contracts/test/v2/discloseId.test.ts @@ -17,9 +17,11 @@ import { genMockIdDocAndInitDataParsing } from "@selfxyz/common/utils/passports/ // Helper function to calculate user identifier hash (same as passport test) function calculateUserIdentifierHash(userContextData: string): string { - const sha256Hash = createHash('sha256').update(Buffer.from(userContextData.slice(2), 'hex')).digest(); - const ripemdHash = createHash('ripemd160').update(sha256Hash).digest(); - return '0x' + ripemdHash.toString('hex').padStart(40, '0'); + const sha256Hash = createHash("sha256") + .update(Buffer.from(userContextData.slice(2), "hex")) + .digest(); + const ripemdHash = createHash("ripemd160").update(sha256Hash).digest(); + return "0x" + ripemdHash.toString("hex").padStart(40, "0"); } describe("Self Verification Flow V2 - ID Card", () => { @@ -44,13 +46,13 @@ describe("Self Verification Flow V2 - ID Card", () => { // Generate mock ID card data mockIdCardData = genMockIdDocAndInitDataParsing({ - idType: 'mock_id_card', - dgHashAlgo: 'sha256', - eContentHashAlgo: 'sha256', - signatureType: 'rsa_sha256_65537_2048', - nationality: 'USA', - birthDate: '920315', - expiryDate: '321231', + idType: "mock_id_card", + dgHashAlgo: "sha256", + eContentHashAlgo: "sha256", + signatureType: "rsa_sha256_65537_2048", + nationality: "USA", + birthDate: "920315", + expiryDate: "321231", }); registerSecret = generateRandomFieldElement(); @@ -58,37 +60,33 @@ describe("Self Verification Flow V2 - ID Card", () => { commitment = generateCommitment(registerSecret, ID_CARD_ATTESTATION_ID.toString(), mockIdCardData); const attestationIdBytes32 = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); - await deployedActors.registry.connect(deployedActors.owner).devAddIdentityCommitment( - attestationIdBytes32, - nullifier, - commitment - ); + await deployedActors.registry + .connect(deployedActors.owner) + .devAddIdentityCommitment(attestationIdBytes32, nullifier, commitment); - await deployedActors.registryId.connect(deployedActors.owner).devAddIdentityCommitment( - attestationIdBytes32, - nullifier, - commitment - ); + await deployedActors.registryId + .connect(deployedActors.owner) + .devAddIdentityCommitment(attestationIdBytes32, nullifier, commitment); const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); // must be imported dynamic since @openpassport/zk-kit-lean-imt is exclusively esm and hardhat does not support esm with typescript until version 3 - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); imt = new LeanIMT(hashFunction); await imt.insert(BigInt(commitment)); - forbiddenCountriesList = [ - countries.AFGHANISTAN, - "ABC", - "CBA", - "AAA", - ] as Country3LetterCode[]; + forbiddenCountriesList = [countries.AFGHANISTAN, "ABC", "CBA", "AAA"] as Country3LetterCode[]; forbiddenCountriesListPacked = getPackedForbiddenCountries(forbiddenCountriesList); verificationConfigV2 = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -101,7 +99,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const tempUserContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(tempUserContextData); @@ -125,7 +123,7 @@ describe("Self Verification Flow V2 - ID Card", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); pristineBaseVcAndDiscloseProof = structuredClone(baseVcAndDiscloseProof); @@ -139,22 +137,18 @@ describe("Self Verification Flow V2 - ID Card", () => { // Re-register the commitment after snapshot revert to ensure registry state is consistent // Check if commitment already exists to avoid LeafAlreadyExists error const currentRoot = await deployedActors.hub.getIdentityCommitmentMerkleRoot( - ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32) + ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32), ); if (currentRoot.toString() === "0") { const attestationIdBytes32 = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); - await deployedActors.registry.connect(deployedActors.owner).devAddIdentityCommitment( - attestationIdBytes32, - nullifier, - commitment - ); + await deployedActors.registry + .connect(deployedActors.owner) + .devAddIdentityCommitment(attestationIdBytes32, nullifier, commitment); - await deployedActors.registryId.connect(deployedActors.owner).devAddIdentityCommitment( - attestationIdBytes32, - nullifier, - commitment - ); + await deployedActors.registryId + .connect(deployedActors.owner) + .devAddIdentityCommitment(attestationIdBytes32, nullifier, commitment); } }); @@ -172,32 +166,21 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); await deployedActors.testSelfVerificationRoot.resetTestState(); - const tx = await deployedActors.testSelfVerificationRoot.verifySelfProof( - proofData, - userContextData - ); + const tx = await deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData); await expect(tx).to.emit(deployedActors.testSelfVerificationRoot, "VerificationCompleted"); @@ -206,10 +189,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const lastOutput = await deployedActors.testSelfVerificationRoot.lastOutput(); expect(lastOutput).to.not.equal("0x"); - const expectedUserData = ethers.solidityPacked( - ["bytes"], - [userData] - ); + const expectedUserData = ethers.solidityPacked(["bytes"], [userData]); const actualUserData = await deployedActors.testSelfVerificationRoot.lastUserData(); expect(actualUserData).to.equal(expectedUserData); }); @@ -221,14 +201,14 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); // Create proofData with less than 32 bytes (invalid) const invalidProofData = ethers.toUtf8Bytes("short"); // Only 5 bytes await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(invalidProofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(invalidProofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "InvalidDataFormat"); }); @@ -236,24 +216,16 @@ describe("Self Verification Flow V2 - ID Card", () => { const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // Create userContextData with less than 96 bytes (invalid) const invalidUserContextData = ethers.toUtf8Bytes("short_data"); // Only 10 bytes await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "InvalidDataFormat"); }); @@ -262,7 +234,12 @@ describe("Self Verification Flow V2 - ID Card", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -275,7 +252,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); @@ -283,18 +260,20 @@ describe("Self Verification Flow V2 - ID Card", () => { // Create a separate commitment and register it const scopeRegisterSecret = generateRandomFieldElement(); const scopeNullifier = generateRandomFieldElement(); - const scopeCommitment = generateCommitment(scopeRegisterSecret, ID_CARD_ATTESTATION_ID.toString(), mockIdCardData); + const scopeCommitment = generateCommitment( + scopeRegisterSecret, + ID_CARD_ATTESTATION_ID.toString(), + mockIdCardData, + ); const attestationIdBytes32 = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); - await deployedActors.registryId.connect(deployedActors.owner).devAddIdentityCommitment( - attestationIdBytes32, - scopeNullifier, - scopeCommitment - ); + await deployedActors.registryId + .connect(deployedActors.owner) + .devAddIdentityCommitment(attestationIdBytes32, scopeNullifier, scopeCommitment); // Create IMT for this specific commitment const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const scopeIMT = new LeanIMT(hashFunction); await scopeIMT.insert(BigInt(scopeCommitment)); @@ -320,27 +299,19 @@ describe("Self Verification Flow V2 - ID Card", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - differentScopeProof.a, - differentScopeProof.b, - differentScopeProof.c, - differentScopeProof.pubSignals - ]] + [[differentScopeProof.a, differentScopeProof.b, differentScopeProof.c, differentScopeProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with ScopeMismatch because the proof has a different scope await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "ScopeMismatch"); }); @@ -364,7 +335,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const invalidUserAddress = await deployedActors.user2.getAddress(); const invalidUserContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(invalidUserAddress, 32), userData] + [configId, destChainId, ethers.zeroPadValue(invalidUserAddress, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); @@ -372,22 +343,14 @@ describe("Self Verification Flow V2 - ID Card", () => { // Use the original valid proof without modification const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with InvalidUserIdentifierInProof because the userContextData doesn't match the proof await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidUserIdentifierInProof"); }); @@ -396,7 +359,12 @@ describe("Self Verification Flow V2 - ID Card", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -409,7 +377,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); @@ -420,21 +388,20 @@ describe("Self Verification Flow V2 - ID Card", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - modifiedVcAndDiscloseProof.a, - modifiedVcAndDiscloseProof.b, - modifiedVcAndDiscloseProof.c, - modifiedVcAndDiscloseProof.pubSignals - ]] + [ + [ + modifiedVcAndDiscloseProof.a, + modifiedVcAndDiscloseProof.b, + modifiedVcAndDiscloseProof.c, + modifiedVcAndDiscloseProof.pubSignals, + ], + ], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidIdentityCommitmentRoot"); }); @@ -443,7 +410,12 @@ describe("Self Verification Flow V2 - ID Card", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -456,7 +428,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); @@ -482,22 +454,14 @@ describe("Self Verification Flow V2 - ID Card", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with CurrentDateNotInValidRange because the date is in the future await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "CurrentDateNotInValidRange"); }); @@ -506,7 +470,12 @@ describe("Self Verification Flow V2 - ID Card", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -519,7 +488,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); @@ -545,22 +514,14 @@ describe("Self Verification Flow V2 - ID Card", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with CurrentDateNotInValidRange because the date is in the past await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "CurrentDateNotInValidRange"); }); @@ -569,7 +530,12 @@ describe("Self Verification Flow V2 - ID Card", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -582,7 +548,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ID_CARD_ATTESTATION_ID)), 32); @@ -591,28 +557,23 @@ describe("Self Verification Flow V2 - ID Card", () => { // but keep the pubSignals valid so it doesn't fail at earlier checks const invalidGrothProof = { ...vcAndDiscloseProof }; invalidGrothProof.a = ["999999999", "888888888"]; // Invalid proof components - invalidGrothProof.b = [["777777777", "666666666"], ["555555555", "444444444"]]; + invalidGrothProof.b = [ + ["777777777", "666666666"], + ["555555555", "444444444"], + ]; invalidGrothProof.c = ["333333333", "222222222"]; // Keep pubSignals unchanged so other validations pass const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - invalidGrothProof.a, - invalidGrothProof.b, - invalidGrothProof.c, - invalidGrothProof.pubSignals - ]] + [[invalidGrothProof.a, invalidGrothProof.b, invalidGrothProof.c, invalidGrothProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with InvalidVcAndDiscloseProof because the groth16 proof is invalid await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidVcAndDiscloseProof"); }); @@ -621,7 +582,12 @@ describe("Self Verification Flow V2 - ID Card", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -634,7 +600,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); // Use invalid attestation ID @@ -642,21 +608,13 @@ describe("Self Verification Flow V2 - ID Card", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [invalidAttestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [invalidAttestationId, encodedProof]); await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWith("Invalid attestation ID"); }); @@ -679,7 +637,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -710,26 +668,18 @@ describe("Self Verification Flow V2 - ID Card", () => { nameAndYob_smt, "0", // This will make OFAC verification fail forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - ofacFailingProof.a, - ofacFailingProof.b, - ofacFailingProof.c, - ofacFailingProof.pubSignals - ]] + [[ofacFailingProof.a, ofacFailingProof.b, ofacFailingProof.c, ofacFailingProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.customVerifier, "InvalidOfacCheck"); }); @@ -752,7 +702,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -783,27 +733,19 @@ describe("Self Verification Flow V2 - ID Card", () => { nameAndYob_smt, "1", forbiddenCountriesList, // Use the original forbidden countries list (different from config) - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - forbiddenCountryProof.a, - forbiddenCountryProof.b, - forbiddenCountryProof.c, - forbiddenCountryProof.pubSignals - ]] + [[forbiddenCountryProof.a, forbiddenCountryProof.b, forbiddenCountryProof.c, forbiddenCountryProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail because the forbidden countries list in the proof doesn't match the config await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.customVerifier, "InvalidForbiddenCountries"); }); @@ -826,7 +768,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -857,27 +799,19 @@ describe("Self Verification Flow V2 - ID Card", () => { nameAndYob_smt, "1", forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - youngerAgeProof.a, - youngerAgeProof.b, - youngerAgeProof.c, - youngerAgeProof.pubSignals - ]] + [[youngerAgeProof.a, youngerAgeProof.b, youngerAgeProof.c, youngerAgeProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail because age 20 is less than required 25 await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.customVerifier, "InvalidOlderThan"); }); @@ -900,7 +834,7 @@ describe("Self Verification Flow V2 - ID Card", () => { const invalidDestChainId = ethers.zeroPadValue(ethers.toBeHex(999999), 32); const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, invalidDestChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, invalidDestChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -931,27 +865,19 @@ describe("Self Verification Flow V2 - ID Card", () => { nameAndYob_smt, "1", forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - validProof.a, - validProof.b, - validProof.c, - validProof.pubSignals - ]] + [[validProof.a, validProof.b, validProof.c, validProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with CrossChainIsNotSupportedYet because destChainId (999999) != block.chainid (31337) await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "CrossChainIsNotSupportedYet"); }); @@ -961,12 +887,16 @@ describe("Self Verification Flow V2 - ID Card", () => { // Try to call onVerificationSuccess directly from a non-hub address await expect( - deployedActors.testSelfVerificationRoot.connect(deployedActors.user1).onVerificationSuccess(mockOutput, mockUserData) + deployedActors.testSelfVerificationRoot + .connect(deployedActors.user1) + .onVerificationSuccess(mockOutput, mockUserData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "UnauthorizedCaller"); // Also test with owner account (should still fail) await expect( - deployedActors.testSelfVerificationRoot.connect(deployedActors.owner).onVerificationSuccess(mockOutput, mockUserData) + deployedActors.testSelfVerificationRoot + .connect(deployedActors.owner) + .onVerificationSuccess(mockOutput, mockUserData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "UnauthorizedCaller"); }); }); diff --git a/contracts/test/v2/disclosePassport.test.ts b/contracts/test/v2/disclosePassport.test.ts index 762ff1931..f32e803d1 100644 --- a/contracts/test/v2/disclosePassport.test.ts +++ b/contracts/test/v2/disclosePassport.test.ts @@ -17,8 +17,8 @@ import { createHash } from "crypto"; // Helper function to format date for passport (YYMMDD format) function formatDateForPassport(date: Date): string { const year = date.getUTCFullYear().toString().slice(-2); // Get last 2 digits of year - const month = (date.getUTCMonth() + 1).toString().padStart(2, '0'); // Month is 0-indexed - const day = date.getUTCDate().toString().padStart(2, '0'); + const month = (date.getUTCMonth() + 1).toString().padStart(2, "0"); // Month is 0-indexed + const day = date.getUTCDate().toString().padStart(2, "0"); return year + month + day; } @@ -39,9 +39,11 @@ describe("Self Verification Flow V2", () => { let configId: string; function calculateUserIdentifierHash(userContextData: string): string { - const sha256Hash = createHash('sha256').update(Buffer.from(userContextData.slice(2), 'hex')).digest(); - const ripemdHash = createHash('ripemd160').update(sha256Hash).digest(); - return '0x' + ripemdHash.toString('hex').padStart(40, '0'); + const sha256Hash = createHash("sha256") + .update(Buffer.from(userContextData.slice(2), "hex")) + .digest(); + const ripemdHash = createHash("ripemd160").update(sha256Hash).digest(); + return "0x" + ripemdHash.toString("hex").padStart(40, "0"); } before(async () => { @@ -54,36 +56,32 @@ describe("Self Verification Flow V2", () => { nullifier = generateRandomFieldElement(); commitment = generateCommitment(registerSecret, ATTESTATION_ID.E_PASSPORT, deployedActors.mockPassport); - await deployedActors.registry.connect(deployedActors.owner).devAddIdentityCommitment( - ATTESTATION_ID.E_PASSPORT, - nullifier, - commitment - ); + await deployedActors.registry + .connect(deployedActors.owner) + .devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); - await deployedActors.registryId.connect(deployedActors.owner).devAddIdentityCommitment( - ATTESTATION_ID.E_PASSPORT, - nullifier, - commitment - ); + await deployedActors.registryId + .connect(deployedActors.owner) + .devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); imt = new LeanIMT(hashFunction); await imt.insert(BigInt(commitment)); - forbiddenCountriesList = [ - countries.AFGHANISTAN, - "ABC", - "CBA", - "AAA", - ] as Country3LetterCode[]; + forbiddenCountriesList = [countries.AFGHANISTAN, "ABC", "CBA", "AAA"] as Country3LetterCode[]; forbiddenCountriesListPacked = getPackedForbiddenCountries(forbiddenCountriesList); verificationConfigV2 = { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -96,7 +94,7 @@ describe("Self Verification Flow V2", () => { const tempUserContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(tempUserContextData); @@ -120,7 +118,7 @@ describe("Self Verification Flow V2", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); pristineBaseVcAndDiscloseProof = structuredClone(baseVcAndDiscloseProof); @@ -135,17 +133,13 @@ describe("Self Verification Flow V2", () => { const currentRoot = await deployedActors.hub.getIdentityCommitmentMerkleRoot(ATTESTATION_ID.E_PASSPORT); if (currentRoot.toString() === "0") { - await deployedActors.registry.connect(deployedActors.owner).devAddIdentityCommitment( - ATTESTATION_ID.E_PASSPORT, - nullifier, - commitment - ); + await deployedActors.registry + .connect(deployedActors.owner) + .devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); - await deployedActors.registryId.connect(deployedActors.owner).devAddIdentityCommitment( - ATTESTATION_ID.E_PASSPORT, - nullifier, - commitment - ); + await deployedActors.registryId + .connect(deployedActors.owner) + .devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, nullifier, commitment); } }); @@ -163,32 +157,21 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); await deployedActors.testSelfVerificationRoot.resetTestState(); - const tx = await deployedActors.testSelfVerificationRoot.verifySelfProof( - proofData, - userContextData - ); + const tx = await deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData); await expect(tx).to.emit(deployedActors.testSelfVerificationRoot, "VerificationCompleted"); @@ -197,10 +180,7 @@ describe("Self Verification Flow V2", () => { const lastOutput = await deployedActors.testSelfVerificationRoot.lastOutput(); expect(lastOutput).to.not.equal("0x"); - const expectedUserData = ethers.solidityPacked( - ["bytes"], - [userData] - ); + const expectedUserData = ethers.solidityPacked(["bytes"], [userData]); const actualUserData = await deployedActors.testSelfVerificationRoot.lastUserData(); expect(actualUserData).to.equal(expectedUserData); }); @@ -213,14 +193,14 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); // Create proofData with less than 32 bytes (invalid) const invalidProofData = ethers.toUtf8Bytes("short"); // Only 5 bytes await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(invalidProofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(invalidProofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "InvalidDataFormat"); }); @@ -228,24 +208,16 @@ describe("Self Verification Flow V2", () => { const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // Create userContextData with less than 96 bytes (invalid) const invalidUserContextData = ethers.toUtf8Bytes("short_data"); // Only 10 bytes await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "InvalidDataFormat"); }); @@ -254,7 +226,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -267,7 +244,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); @@ -275,17 +252,19 @@ describe("Self Verification Flow V2", () => { // Create a separate commitment and register it const scopeRegisterSecret = generateRandomFieldElement(); const scopeNullifier = generateRandomFieldElement(); - const scopeCommitment = generateCommitment(scopeRegisterSecret, ATTESTATION_ID.E_PASSPORT, deployedActors.mockPassport); - - await deployedActors.registry.connect(deployedActors.owner).devAddIdentityCommitment( + const scopeCommitment = generateCommitment( + scopeRegisterSecret, ATTESTATION_ID.E_PASSPORT, - scopeNullifier, - scopeCommitment + deployedActors.mockPassport, ); + await deployedActors.registry + .connect(deployedActors.owner) + .devAddIdentityCommitment(ATTESTATION_ID.E_PASSPORT, scopeNullifier, scopeCommitment); + // Create IMT for this specific commitment const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const scopeIMT = new LeanIMT(hashFunction); await scopeIMT.insert(BigInt(scopeCommitment)); @@ -311,27 +290,19 @@ describe("Self Verification Flow V2", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - differentScopeProof.a, - differentScopeProof.b, - differentScopeProof.c, - differentScopeProof.pubSignals - ]] + [[differentScopeProof.a, differentScopeProof.b, differentScopeProof.c, differentScopeProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with ScopeMismatch because the proof has a different scope await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "ScopeMismatch"); }); @@ -355,7 +326,7 @@ describe("Self Verification Flow V2", () => { const invalidUserAddress = await deployedActors.user2.getAddress(); const invalidUserContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(invalidUserAddress, 32), userData] + [configId, destChainId, ethers.zeroPadValue(invalidUserAddress, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); @@ -363,22 +334,14 @@ describe("Self Verification Flow V2", () => { // Use the original valid proof without modification const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with InvalidUserIdentifierInProof because the userContextData doesn't match the proof await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, invalidUserContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidUserIdentifierInProof"); }); @@ -387,7 +350,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -400,7 +368,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -415,11 +383,15 @@ describe("Self Verification Flow V2", () => { // Create a separate commitment with a different secret to generate a different merkle root const differentRegisterSecret = generateRandomFieldElement(); const differentNullifier = generateRandomFieldElement(); - const differentCommitment = generateCommitment(differentRegisterSecret, ATTESTATION_ID.E_PASSPORT, deployedActors.mockPassport); + const differentCommitment = generateCommitment( + differentRegisterSecret, + ATTESTATION_ID.E_PASSPORT, + deployedActors.mockPassport, + ); // Create a new IMT with different commitment (different root) const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); - const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then(mod => mod.LeanIMT); + const LeanIMT = await import("@openpassport/zk-kit-lean-imt").then((mod) => mod.LeanIMT); const differentIMT = new LeanIMT(hashFunction); await differentIMT.insert(BigInt(differentCommitment)); @@ -438,26 +410,18 @@ describe("Self Verification Flow V2", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - differentRootProof.a, - differentRootProof.b, - differentRootProof.c, - differentRootProof.pubSignals - ]] + [[differentRootProof.a, differentRootProof.b, differentRootProof.c, differentRootProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidIdentityCommitmentRoot"); }); @@ -466,7 +430,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -479,7 +448,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); @@ -505,22 +474,14 @@ describe("Self Verification Flow V2", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with CurrentDateNotInValidRange because the date is in the future await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "CurrentDateNotInValidRange"); }); @@ -529,7 +490,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -542,7 +508,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); @@ -568,22 +534,14 @@ describe("Self Verification Flow V2", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with CurrentDateNotInValidRange because the date is in the past await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "CurrentDateNotInValidRange"); }); @@ -592,7 +550,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -605,7 +568,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const attestationId = ethers.zeroPadValue(ethers.toBeHex(BigInt(ATTESTATION_ID.E_PASSPORT)), 32); @@ -614,28 +577,23 @@ describe("Self Verification Flow V2", () => { // but keep the pubSignals valid so it doesn't fail at earlier checks const invalidGrothProof = structuredClone(vcAndDiscloseProof); invalidGrothProof.a = ["999999999", "888888888"]; // Invalid proof components - invalidGrothProof.b = [["777777777", "666666666"], ["555555555", "444444444"]]; + invalidGrothProof.b = [ + ["777777777", "666666666"], + ["555555555", "444444444"], + ]; invalidGrothProof.c = ["333333333", "222222222"]; // Keep pubSignals unchanged so other validations pass const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - invalidGrothProof.a, - invalidGrothProof.b, - invalidGrothProof.c, - invalidGrothProof.pubSignals - ]] + [[invalidGrothProof.a, invalidGrothProof.b, invalidGrothProof.c, invalidGrothProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with InvalidVcAndDiscloseProof because the groth16 proof is invalid await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidVcAndDiscloseProof"); }); @@ -644,7 +602,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: true, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: forbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: forbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [true, true, true] as [boolean, boolean, boolean], }; @@ -657,7 +620,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); // Use invalid attestation ID @@ -665,21 +628,13 @@ describe("Self Verification Flow V2", () => { const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - vcAndDiscloseProof.a, - vcAndDiscloseProof.b, - vcAndDiscloseProof.c, - vcAndDiscloseProof.pubSignals - ]] + [[vcAndDiscloseProof.a, vcAndDiscloseProof.b, vcAndDiscloseProof.c, vcAndDiscloseProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [invalidAttestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [invalidAttestationId, encodedProof]); await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWith("Invalid attestation ID"); }); @@ -702,7 +657,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -733,26 +688,18 @@ describe("Self Verification Flow V2", () => { nameAndYob_smt, "0", // This will make OFAC verification fail forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - ofacFailingProof.a, - ofacFailingProof.b, - ofacFailingProof.c, - ofacFailingProof.pubSignals - ]] + [[ofacFailingProof.a, ofacFailingProof.b, ofacFailingProof.c, ofacFailingProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.customVerifier, "InvalidOfacCheck"); }); @@ -770,7 +717,12 @@ describe("Self Verification Flow V2", () => { olderThanEnabled: false, olderThan: "20", forbiddenCountriesEnabled: true, - forbiddenCountriesListPacked: mismatchedForbiddenCountriesListPacked as [BigNumberish, BigNumberish, BigNumberish, BigNumberish], + forbiddenCountriesListPacked: mismatchedForbiddenCountriesListPacked as [ + BigNumberish, + BigNumberish, + BigNumberish, + BigNumberish, + ], ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; @@ -783,7 +735,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -810,27 +762,19 @@ describe("Self Verification Flow V2", () => { undefined, undefined, forbiddenCountriesList, // Use the original forbidden countries list (different from config) - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - forbiddenCountryProof.a, - forbiddenCountryProof.b, - forbiddenCountryProof.c, - forbiddenCountryProof.pubSignals - ]] + [[forbiddenCountryProof.a, forbiddenCountryProof.b, forbiddenCountryProof.c, forbiddenCountryProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail because the forbidden countries list in the proof doesn't match the config await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.customVerifier, "InvalidForbiddenCountries"); }); @@ -853,7 +797,7 @@ describe("Self Verification Flow V2", () => { const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, destChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -880,27 +824,19 @@ describe("Self Verification Flow V2", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - youngerAgeProof.a, - youngerAgeProof.b, - youngerAgeProof.c, - youngerAgeProof.pubSignals - ]] + [[youngerAgeProof.a, youngerAgeProof.b, youngerAgeProof.c, youngerAgeProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail because age 20 is less than required 25 await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.customVerifier, "InvalidOlderThan"); }); @@ -923,7 +859,7 @@ describe("Self Verification Flow V2", () => { const invalidDestChainId = ethers.zeroPadValue(ethers.toBeHex(999999), 32); const userContextData = ethers.solidityPacked( ["bytes32", "bytes32", "bytes32", "bytes"], - [configId, invalidDestChainId, ethers.zeroPadValue(user1Address, 32), userData] + [configId, invalidDestChainId, ethers.zeroPadValue(user1Address, 32), userData], ); const userIdentifierHash = calculateUserIdentifierHash(userContextData); @@ -950,27 +886,19 @@ describe("Self Verification Flow V2", () => { undefined, undefined, forbiddenCountriesList, - userIdentifierBigInt.toString(16).padStart(64, '0'), + userIdentifierBigInt.toString(16).padStart(64, "0"), ); const encodedProof = ethers.AbiCoder.defaultAbiCoder().encode( ["tuple(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[21] pubSignals)"], - [[ - validProof.a, - validProof.b, - validProof.c, - validProof.pubSignals - ]] + [[validProof.a, validProof.b, validProof.c, validProof.pubSignals]], ); - const proofData = ethers.solidityPacked( - ["bytes32", "bytes"], - [attestationId, encodedProof] - ); + const proofData = ethers.solidityPacked(["bytes32", "bytes"], [attestationId, encodedProof]); // This should fail with CrossChainIsNotSupportedYet because destChainId (999999) != block.chainid (31337) await expect( - deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData) + deployedActors.testSelfVerificationRoot.verifySelfProof(proofData, userContextData), ).to.be.revertedWithCustomError(deployedActors.hub, "CrossChainIsNotSupportedYet"); }); @@ -980,12 +908,16 @@ describe("Self Verification Flow V2", () => { // Try to call onVerificationSuccess directly from a non-hub address await expect( - deployedActors.testSelfVerificationRoot.connect(deployedActors.user1).onVerificationSuccess(mockOutput, mockUserData) + deployedActors.testSelfVerificationRoot + .connect(deployedActors.user1) + .onVerificationSuccess(mockOutput, mockUserData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "UnauthorizedCaller"); // Also test with owner account (should still fail) await expect( - deployedActors.testSelfVerificationRoot.connect(deployedActors.owner).onVerificationSuccess(mockOutput, mockUserData) + deployedActors.testSelfVerificationRoot + .connect(deployedActors.owner) + .onVerificationSuccess(mockOutput, mockUserData), ).to.be.revertedWithCustomError(deployedActors.testSelfVerificationRoot, "UnauthorizedCaller"); }); }); diff --git a/contracts/test/v2/hubOther.test.ts b/contracts/test/v2/hubOther.test.ts index 922783842..b9ee2a38d 100644 --- a/contracts/test/v2/hubOther.test.ts +++ b/contracts/test/v2/hubOther.test.ts @@ -39,11 +39,7 @@ describe("Hub Other Functions Test", function () { const verifierAddresses = [ethers.ZeroAddress, ethers.ZeroAddress]; await expect( - deployedActors.hub.batchUpdateRegisterCircuitVerifiers( - attestationIds, - typeIds, - verifierAddresses - ) + deployedActors.hub.batchUpdateRegisterCircuitVerifiers(attestationIds, typeIds, verifierAddresses), ).to.be.revertedWithCustomError(deployedActors.hub, "LengthMismatch"); }); @@ -53,11 +49,7 @@ describe("Hub Other Functions Test", function () { const verifierAddresses = [ethers.ZeroAddress]; await expect( - deployedActors.hub.batchUpdateDscCircuitVerifiers( - attestationIds, - typeIds, - verifierAddresses - ) + deployedActors.hub.batchUpdateDscCircuitVerifiers(attestationIds, typeIds, verifierAddresses), ).to.be.revertedWithCustomError(deployedActors.hub, "LengthMismatch"); }); @@ -66,13 +58,8 @@ describe("Hub Other Functions Test", function () { const typeIds = [1, 2]; const verifierAddresses = [ethers.ZeroAddress, ethers.ZeroAddress]; - await expect( - deployedActors.hub.batchUpdateRegisterCircuitVerifiers( - attestationIds, - typeIds, - verifierAddresses - ) - ).to.not.be.reverted; + await expect(deployedActors.hub.batchUpdateRegisterCircuitVerifiers(attestationIds, typeIds, verifierAddresses)) + .to.not.be.reverted; }); it("should successfully batch update DSC circuit verifiers with matching array lengths", async () => { @@ -80,13 +67,8 @@ describe("Hub Other Functions Test", function () { const typeIds = [1, 2]; const verifierAddresses = [ethers.ZeroAddress, ethers.ZeroAddress]; - await expect( - deployedActors.hub.batchUpdateDscCircuitVerifiers( - attestationIds, - typeIds, - verifierAddresses - ) - ).to.not.be.reverted; + await expect(deployedActors.hub.batchUpdateDscCircuitVerifiers(attestationIds, typeIds, verifierAddresses)).to.not + .be.reverted; }); }); @@ -94,21 +76,14 @@ describe("Hub Other Functions Test", function () { it("should fail when non-owner tries to call onlyOwner functions", async () => { const nonOwnerHub = deployedActors.hub.connect(deployedActors.user1); - await expect( - nonOwnerHub.updateRegistry(attestationIdBytes32, ethers.ZeroAddress) - ).to.be.reverted; // Should revert due to onlyOwner modifier + await expect(nonOwnerHub.updateRegistry(attestationIdBytes32, ethers.ZeroAddress)).to.be.reverted; // Should revert due to onlyOwner modifier - await expect( - nonOwnerHub.updateVcAndDiscloseCircuit(attestationIdBytes32, ethers.ZeroAddress) - ).to.be.reverted; // Should revert due to onlyOwner modifier + await expect(nonOwnerHub.updateVcAndDiscloseCircuit(attestationIdBytes32, ethers.ZeroAddress)).to.be.reverted; // Should revert due to onlyOwner modifier - await expect( - nonOwnerHub.updateRegisterCircuitVerifier(attestationIdBytes32, 1, ethers.ZeroAddress) - ).to.be.reverted; // Should revert due to onlyOwner modifier + await expect(nonOwnerHub.updateRegisterCircuitVerifier(attestationIdBytes32, 1, ethers.ZeroAddress)).to.be + .reverted; // Should revert due to onlyOwner modifier - await expect( - nonOwnerHub.updateDscVerifier(attestationIdBytes32, 1, ethers.ZeroAddress) - ).to.be.reverted; // Should revert due to onlyOwner modifier + await expect(nonOwnerHub.updateDscVerifier(attestationIdBytes32, 1, ethers.ZeroAddress)).to.be.reverted; // Should revert due to onlyOwner modifier }); }); @@ -126,7 +101,7 @@ describe("Hub Other Functions Test", function () { it("should return correct register circuit verifier address", async () => { const registerVerifierAddress = await deployedActors.hub.registerCircuitVerifiers( attestationIdBytes32, - RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096 + RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096, ); expect(registerVerifierAddress).to.not.equal(ethers.ZeroAddress); }); @@ -134,30 +109,31 @@ describe("Hub Other Functions Test", function () { it("should return correct DSC circuit verifier address", async () => { const dscVerifierAddress = await deployedActors.hub.dscCircuitVerifiers( attestationIdBytes32, - DscVerifierId.dsc_sha256_rsa_65537_4096 + DscVerifierId.dsc_sha256_rsa_65537_4096, ); expect(dscVerifierAddress).to.not.equal(ethers.ZeroAddress); }); it("should return correct identity commitment merkle root", async () => { const merkleRoot = await deployedActors.hub.getIdentityCommitmentMerkleRoot(attestationIdBytes32); - expect(merkleRoot).to.be.a('bigint'); + expect(merkleRoot).to.be.a("bigint"); }); it("should fail getIdentityCommitmentMerkleRoot with InvalidAttestationId", async () => { const invalidAttestationId = ethers.zeroPadValue(ethers.toBeHex(999), 32); await expect( - deployedActors.hub.getIdentityCommitmentMerkleRoot(invalidAttestationId) + deployedActors.hub.getIdentityCommitmentMerkleRoot(invalidAttestationId), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidAttestationId"); }); it("should fail rootTimestamp with InvalidAttestationId", async () => { const invalidAttestationId = ethers.zeroPadValue(ethers.toBeHex(999), 32); - await expect( - deployedActors.hub.rootTimestamp(invalidAttestationId, 123) - ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidAttestationId"); + await expect(deployedActors.hub.rootTimestamp(invalidAttestationId, 123)).to.be.revertedWithCustomError( + deployedActors.hub, + "InvalidAttestationId", + ); }); }); @@ -168,14 +144,19 @@ describe("Hub Other Functions Test", function () { olderThan: 18, forbiddenCountriesEnabled: true, forbiddenCountriesListPacked: [840, 156, 0, 0] as [number, number, number, number], // USA, China - ofacEnabled: [true, false, false] as [boolean, boolean, boolean] + ofacEnabled: [true, false, false] as [boolean, boolean, boolean], }; const configId = await deployedActors.hub.setVerificationConfigV2.staticCall(config); - await expect( - deployedActors.hub.setVerificationConfigV2(config) - ).to.emit(deployedActors.hub, "VerificationConfigV2Set") - .withArgs(configId, [config.olderThanEnabled, config.olderThan, config.forbiddenCountriesEnabled, config.forbiddenCountriesListPacked, config.ofacEnabled]); + await expect(deployedActors.hub.setVerificationConfigV2(config)) + .to.emit(deployedActors.hub, "VerificationConfigV2Set") + .withArgs(configId, [ + config.olderThanEnabled, + config.olderThan, + config.forbiddenCountriesEnabled, + config.forbiddenCountriesListPacked, + config.ofacEnabled, + ]); const exists = await deployedActors.hub.verificationConfigV2Exists(configId); expect(exists).to.be.true; @@ -187,7 +168,7 @@ describe("Hub Other Functions Test", function () { olderThan: 21, forbiddenCountriesEnabled: false, forbiddenCountriesListPacked: [392, 0, 0, 0] as [number, number, number, number], // Japan - ofacEnabled: [false, false, false] as [boolean, boolean, boolean] + ofacEnabled: [false, false, false] as [boolean, boolean, boolean], }; const generatedId = await deployedActors.hub.generateConfigId(config); diff --git a/contracts/test/v2/registerId.test.ts b/contracts/test/v2/registerId.test.ts index 7a2bb20b8..1d43c6d06 100644 --- a/contracts/test/v2/registerId.test.ts +++ b/contracts/test/v2/registerId.test.ts @@ -6,7 +6,11 @@ import { DeployedActorsV2 } from "../utils/types"; import { generateDscProof, generateRegisterIdProof } from "../utils/generateProof"; import { DscVerifierId, RegisterVerifierId } from "@selfxyz/common/constants/constants"; import serialized_dsc_tree from "@selfxyz/common/pubkeys/serialized_dsc_tree.json"; -import { CIRCUIT_CONSTANTS, ID_CARD_ATTESTATION_ID, PASSPORT_ATTESTATION_ID } from "@selfxyz/common/constants/constants"; +import { + CIRCUIT_CONSTANTS, + ID_CARD_ATTESTATION_ID, + PASSPORT_ATTESTATION_ID, +} from "@selfxyz/common/constants/constants"; import { genMockIdDocAndInitDataParsing } from "@selfxyz/common/utils/passports/genMockIdDoc"; describe("ID Registration test", function () { @@ -43,13 +47,13 @@ describe("ID Registration test", function () { before(async () => { // Generate DSC proof once for all tests in this describe block idCardData = genMockIdDocAndInitDataParsing({ - idType: 'mock_id_card', - dgHashAlgo: 'sha256', - eContentHashAlgo: 'sha256', - signatureType: 'rsa_sha256_65537_2048', - nationality: 'USA', - birthDate: '900101', - expiryDate: '301231', + idType: "mock_id_card", + dgHashAlgo: "sha256", + eContentHashAlgo: "sha256", + signatureType: "rsa_sha256_65537_2048", + nationality: "USA", + birthDate: "900101", + expiryDate: "301231", }); dscProof = await generateDscProof(idCardData); @@ -63,11 +67,7 @@ describe("ID Registration test", function () { // Register the DSC key commitment await expect( - deployedActors.hub.registerDscKeyCommitment( - attestationIdBytes32, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(attestationIdBytes32, dscCircuitVerifierId, dscProof), ).to.emit(deployedActors.registryId, "DscKeyCommitmentRegistered"); // Verify DSC was added to tree @@ -79,7 +79,7 @@ describe("ID Registration test", function () { // Verify the commitment is registered const isRegistered = await deployedActors.registryId.isRegisteredDscKeyCommitment( - dscProof.pubSignals[CIRCUIT_CONSTANTS.DSC_TREE_LEAF_INDEX] + dscProof.pubSignals[CIRCUIT_CONSTANTS.DSC_TREE_LEAF_INDEX], ); expect(isRegistered).to.be.true; }); @@ -88,11 +88,7 @@ describe("ID Registration test", function () { const nonExistentVerifierId = 999999; // Non-existent verifier ID await expect( - deployedActors.hub.registerDscKeyCommitment( - attestationIdBytes32, - nonExistentVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(attestationIdBytes32, nonExistentVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -101,11 +97,7 @@ describe("ID Registration test", function () { const dscCircuitVerifierId = DscVerifierId.dsc_sha256_rsa_65537_4096; await expect( - deployedActors.hub.registerDscKeyCommitment( - invalidAttestationId, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(invalidAttestationId, dscCircuitVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -117,16 +109,12 @@ describe("ID Registration test", function () { await deployedActors.hub.updateDscVerifier( invalidAttestationId, dscCircuitVerifierId, - await deployedActors.dsc.getAddress() + await deployedActors.dsc.getAddress(), ); // Now the call should fail with InvalidAttestationId since verifier exists but attestation ID is not valid await expect( - deployedActors.hub.registerDscKeyCommitment( - invalidAttestationId, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(invalidAttestationId, dscCircuitVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidAttestationId"); }); @@ -137,16 +125,15 @@ describe("ID Registration test", function () { const invalidDscProof = { ...dscProof, a: ["0x1", "0x2"], // Invalid proof values - b: [["0x1", "0x2"], ["0x3", "0x4"]], - c: ["0x1", "0x2"] + b: [ + ["0x1", "0x2"], + ["0x3", "0x4"], + ], + c: ["0x1", "0x2"], }; await expect( - deployedActors.hub.registerDscKeyCommitment( - attestationIdBytes32, - dscCircuitVerifierId, - invalidDscProof - ) + deployedActors.hub.registerDscKeyCommitment(attestationIdBytes32, dscCircuitVerifierId, invalidDscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidDscProof"); }); @@ -157,11 +144,7 @@ describe("ID Registration test", function () { await deployedActors.registryId.updateCscaRoot(12345); // Invalid CSCA root await expect( - deployedActors.hub.registerDscKeyCommitment( - attestationIdBytes32, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(attestationIdBytes32, dscCircuitVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidCscaRoot"); }); }); @@ -172,7 +155,6 @@ describe("ID Registration test", function () { let idCardData: any; before(async () => { - const dscKeys = JSON.parse(serialized_dsc_tree); for (let i = 0; i < dscKeys[0].length; i++) { await deployedActors.registryId.devAddDscKeyCommitment(BigInt(dscKeys[0][i])); @@ -180,13 +162,13 @@ describe("ID Registration test", function () { // Generate identity commitment proof idCardData = genMockIdDocAndInitDataParsing({ - idType: 'mock_id_card', - dgHashAlgo: 'sha256', - eContentHashAlgo: 'sha256', - signatureType: 'rsa_sha256_65537_2048', - nationality: 'GBR', - birthDate: '920315', - expiryDate: '321231', + idType: "mock_id_card", + dgHashAlgo: "sha256", + eContentHashAlgo: "sha256", + signatureType: "rsa_sha256_65537_2048", + nationality: "GBR", + birthDate: "920315", + expiryDate: "321231", }); registerSecret = generateRandomFieldElement(); @@ -199,17 +181,13 @@ describe("ID Registration test", function () { // Register the identity commitment await expect( - deployedActors.hub.registerCommitment( - attestationIdBytes32, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(attestationIdBytes32, registerCircuitVerifierId, registerProof), ).to.emit(deployedActors.registryId, "CommitmentRegistered"); // Verify the commitment is registered by checking the nullifier const isRegistered = await deployedActors.registryId.nullifiers( attestationIdBytes32, - registerProof.pubSignals[CIRCUIT_CONSTANTS.REGISTER_NULLIFIER_INDEX] + registerProof.pubSignals[CIRCUIT_CONSTANTS.REGISTER_NULLIFIER_INDEX], ); expect(isRegistered).to.be.true; }); @@ -218,11 +196,7 @@ describe("ID Registration test", function () { const nonExistentVerifierId = 999999; // Non-existent verifier ID await expect( - deployedActors.hub.registerCommitment( - attestationIdBytes32, - nonExistentVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(attestationIdBytes32, nonExistentVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -231,11 +205,7 @@ describe("ID Registration test", function () { const registerCircuitVerifierId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096; await expect( - deployedActors.hub.registerCommitment( - invalidAttestationId, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(invalidAttestationId, registerCircuitVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -247,16 +217,12 @@ describe("ID Registration test", function () { await deployedActors.hub.updateRegisterCircuitVerifier( invalidAttestationId, registerCircuitVerifierId, - await deployedActors.register.getAddress() + await deployedActors.register.getAddress(), ); // Now the call should fail with InvalidAttestationId since verifier exists but attestation ID is not valid await expect( - deployedActors.hub.registerCommitment( - invalidAttestationId, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(invalidAttestationId, registerCircuitVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidAttestationId"); }); @@ -267,16 +233,15 @@ describe("ID Registration test", function () { const invalidRegisterProof = { ...registerProof, a: ["0x1", "0x2"], // Invalid proof values - b: [["0x1", "0x2"], ["0x3", "0x4"]], - c: ["0x1", "0x2"] + b: [ + ["0x1", "0x2"], + ["0x3", "0x4"], + ], + c: ["0x1", "0x2"], }; await expect( - deployedActors.hub.registerCommitment( - attestationIdBytes32, - registerCircuitVerifierId, - invalidRegisterProof - ) + deployedActors.hub.registerCommitment(attestationIdBytes32, registerCircuitVerifierId, invalidRegisterProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidRegisterProof"); }); @@ -291,11 +256,7 @@ describe("ID Registration test", function () { // The proof was generated with the original root, so it should fail await expect( - deployedActors.hub.registerCommitment( - attestationIdBytes32, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(attestationIdBytes32, registerCircuitVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidDscCommitmentRoot"); // Restore the snapshot diff --git a/contracts/test/v2/registerPassport.test.ts b/contracts/test/v2/registerPassport.test.ts index 20bb968b5..88d5b62b2 100644 --- a/contracts/test/v2/registerPassport.test.ts +++ b/contracts/test/v2/registerPassport.test.ts @@ -41,13 +41,13 @@ describe("Passport Registration test", function () { before(async () => { // Generate DSC proof once for all tests in this describe block passportData = genMockIdDocAndInitDataParsing({ - idType: 'mock_passport', - dgHashAlgo: 'sha256', - eContentHashAlgo: 'sha256', - signatureType: 'rsa_sha256_65537_2048', - nationality: 'USA', - birthDate: '900101', - expiryDate: '301231', + idType: "mock_passport", + dgHashAlgo: "sha256", + eContentHashAlgo: "sha256", + signatureType: "rsa_sha256_65537_2048", + nationality: "USA", + birthDate: "900101", + expiryDate: "301231", }); dscProof = await generateDscProof(passportData); @@ -61,11 +61,7 @@ describe("Passport Registration test", function () { // Register the DSC key commitment await expect( - deployedActors.hub.registerDscKeyCommitment( - ePassportAttestationIdBytes32, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(ePassportAttestationIdBytes32, dscCircuitVerifierId, dscProof), ).to.emit(deployedActors.registry, "DscKeyCommitmentRegistered"); // Verify DSC was added to tree @@ -77,7 +73,7 @@ describe("Passport Registration test", function () { // Verify the commitment is registered const isRegistered = await deployedActors.registry.isRegisteredDscKeyCommitment( - dscProof.pubSignals[CIRCUIT_CONSTANTS.DSC_TREE_LEAF_INDEX] + dscProof.pubSignals[CIRCUIT_CONSTANTS.DSC_TREE_LEAF_INDEX], ); expect(isRegistered).to.be.true; }); @@ -86,11 +82,7 @@ describe("Passport Registration test", function () { const nonExistentVerifierId = 999999; // Non-existent verifier ID await expect( - deployedActors.hub.registerDscKeyCommitment( - ePassportAttestationIdBytes32, - nonExistentVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(ePassportAttestationIdBytes32, nonExistentVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -99,11 +91,7 @@ describe("Passport Registration test", function () { const dscCircuitVerifierId = DscVerifierId.dsc_sha256_rsa_65537_4096; await expect( - deployedActors.hub.registerDscKeyCommitment( - invalidAttestationId, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(invalidAttestationId, dscCircuitVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -115,16 +103,12 @@ describe("Passport Registration test", function () { await deployedActors.hub.updateDscVerifier( invalidAttestationId, dscCircuitVerifierId, - await deployedActors.dsc.getAddress() + await deployedActors.dsc.getAddress(), ); // Now the call should fail with InvalidAttestationId since verifier exists but attestation ID is not valid await expect( - deployedActors.hub.registerDscKeyCommitment( - invalidAttestationId, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(invalidAttestationId, dscCircuitVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidAttestationId"); }); @@ -135,16 +119,19 @@ describe("Passport Registration test", function () { const invalidDscProof = { ...dscProof, a: ["0x1", "0x2"], // Invalid proof values - b: [["0x1", "0x2"], ["0x3", "0x4"]], - c: ["0x1", "0x2"] + b: [ + ["0x1", "0x2"], + ["0x3", "0x4"], + ], + c: ["0x1", "0x2"], }; await expect( deployedActors.hub.registerDscKeyCommitment( ePassportAttestationIdBytes32, dscCircuitVerifierId, - invalidDscProof - ) + invalidDscProof, + ), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidDscProof"); }); @@ -155,11 +142,7 @@ describe("Passport Registration test", function () { await deployedActors.registry.updateCscaRoot(12345); // Invalid CSCA root await expect( - deployedActors.hub.registerDscKeyCommitment( - ePassportAttestationIdBytes32, - dscCircuitVerifierId, - dscProof - ) + deployedActors.hub.registerDscKeyCommitment(ePassportAttestationIdBytes32, dscCircuitVerifierId, dscProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidCscaRoot"); }); }); @@ -170,7 +153,6 @@ describe("Passport Registration test", function () { let passportData: any; before(async () => { - const dscKeys = JSON.parse(serialized_dsc_tree); for (let i = 0; i < dscKeys[0].length; i++) { await deployedActors.registry.devAddDscKeyCommitment(BigInt(dscKeys[0][i])); @@ -178,13 +160,13 @@ describe("Passport Registration test", function () { // Generate passport identity commitment proof using passport-specific function passportData = genMockIdDocAndInitDataParsing({ - idType: 'mock_passport', - dgHashAlgo: 'sha256', - eContentHashAlgo: 'sha256', - signatureType: 'rsa_sha256_65537_2048', - nationality: 'GBR', - birthDate: '920315', - expiryDate: '321231', + idType: "mock_passport", + dgHashAlgo: "sha256", + eContentHashAlgo: "sha256", + signatureType: "rsa_sha256_65537_2048", + nationality: "GBR", + birthDate: "920315", + expiryDate: "321231", }); registerSecret = generateRandomFieldElement(); @@ -197,17 +179,13 @@ describe("Passport Registration test", function () { // Register the passport identity commitment await expect( - deployedActors.hub.registerCommitment( - ePassportAttestationIdBytes32, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(ePassportAttestationIdBytes32, registerCircuitVerifierId, registerProof), ).to.emit(deployedActors.registry, "CommitmentRegistered"); // Verify the commitment is registered by checking the nullifier const isRegistered = await deployedActors.registry.nullifiers( ePassportAttestationIdBytes32, - registerProof.pubSignals[CIRCUIT_CONSTANTS.REGISTER_NULLIFIER_INDEX] + registerProof.pubSignals[CIRCUIT_CONSTANTS.REGISTER_NULLIFIER_INDEX], ); expect(isRegistered).to.be.true; }); @@ -216,11 +194,7 @@ describe("Passport Registration test", function () { const nonExistentVerifierId = 999999; // Non-existent verifier ID await expect( - deployedActors.hub.registerCommitment( - ePassportAttestationIdBytes32, - nonExistentVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(ePassportAttestationIdBytes32, nonExistentVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -229,11 +203,7 @@ describe("Passport Registration test", function () { const registerCircuitVerifierId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096; await expect( - deployedActors.hub.registerCommitment( - invalidAttestationId, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(invalidAttestationId, registerCircuitVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "NoVerifierSet"); }); @@ -245,16 +215,12 @@ describe("Passport Registration test", function () { await deployedActors.hub.updateRegisterCircuitVerifier( invalidAttestationId, registerCircuitVerifierId, - await deployedActors.register.getAddress() + await deployedActors.register.getAddress(), ); // Now the call should fail with InvalidAttestationId since verifier exists but attestation ID is not valid await expect( - deployedActors.hub.registerCommitment( - invalidAttestationId, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(invalidAttestationId, registerCircuitVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidAttestationId"); }); @@ -265,16 +231,19 @@ describe("Passport Registration test", function () { const invalidRegisterProof = { ...registerProof, a: ["0x1", "0x2"], // Invalid proof values - b: [["0x1", "0x2"], ["0x3", "0x4"]], - c: ["0x1", "0x2"] + b: [ + ["0x1", "0x2"], + ["0x3", "0x4"], + ], + c: ["0x1", "0x2"], }; await expect( deployedActors.hub.registerCommitment( ePassportAttestationIdBytes32, registerCircuitVerifierId, - invalidRegisterProof - ) + invalidRegisterProof, + ), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidRegisterProof"); }); @@ -289,11 +258,7 @@ describe("Passport Registration test", function () { // The proof was generated with the original root, so it should fail await expect( - deployedActors.hub.registerCommitment( - ePassportAttestationIdBytes32, - registerCircuitVerifierId, - registerProof - ) + deployedActors.hub.registerCommitment(ePassportAttestationIdBytes32, registerCircuitVerifierId, registerProof), ).to.be.revertedWithCustomError(deployedActors.hub, "InvalidDscCommitmentRoot"); // Restore the snapshot