mirror of
https://github.com/zkemail/zk-email-verify.git
synced 2026-01-07 20:54:05 -05:00
feat: remove circuit dependent logic from circuit utils
This commit is contained in:
@@ -115,20 +115,6 @@ library CircuitUtils {
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Packs a public key (as bytes) into field elements
|
||||
* @param pubKeyBytes The public key bytes (encoded as uint256[17])
|
||||
* @return fields The packed field elements
|
||||
*/
|
||||
function packPubKey(bytes memory pubKeyBytes) internal pure returns (uint256[] memory fields) {
|
||||
uint256[17] memory pubKeyChunks = abi.decode(pubKeyBytes, (uint256[17]));
|
||||
fields = new uint256[](17);
|
||||
for (uint256 i = 0; i < 17; i++) {
|
||||
fields[i] = pubKeyChunks[i];
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Unpacks field elements back to bytes
|
||||
* @param _pucSignals Array of public signals
|
||||
@@ -223,108 +209,22 @@ library CircuitUtils {
|
||||
return pubSignals[startIndex] == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Extracts miscellaneous data from public signals
|
||||
* @param pubSignals Array of public signals
|
||||
* @param startIndex Starting index of miscellaneous data
|
||||
* @return miscellaneousData The miscellaneous data
|
||||
*/
|
||||
function unpackMiscellaneousData(
|
||||
uint256[] calldata pubSignals,
|
||||
uint256 startIndex
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory miscellaneousData)
|
||||
{
|
||||
uint256[17] memory pubKeyChunks;
|
||||
for (uint256 i = 0; i < pubKeyChunks.length; i++) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pubKeyChunks[i] = pubSignals[startIndex + i];
|
||||
}
|
||||
miscellaneousData = abi.encode(pubKeyChunks);
|
||||
return miscellaneousData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Extracts the parts of an email address, replacing '@' with '$' and splitting by '.'
|
||||
* @param email The email address to process
|
||||
* @return The parts of the email address as a string array
|
||||
*/
|
||||
function extractEmailParts(string memory email) internal pure returns (string[] memory) {
|
||||
bytes memory emailBytes = bytes(email);
|
||||
bytes memory modifiedEmail = new bytes(emailBytes.length);
|
||||
uint256 atIndex = 0;
|
||||
for (uint256 i = 0; i < emailBytes.length; i++) {
|
||||
if (emailBytes[i] == "@") {
|
||||
modifiedEmail[i] = "$";
|
||||
atIndex = i;
|
||||
} else {
|
||||
modifiedEmail[i] = emailBytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return _splitString(string(modifiedEmail), ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Verifies that the email parts are dot separated and match the claimed email
|
||||
* @param emailParts The parts of the email address dot separated
|
||||
* @param email The complete email address
|
||||
* @return True if the email parts are dot separated and match the claimed email, false otherwise
|
||||
*/
|
||||
function verifyEmailParts(string[] memory emailParts, string memory email) internal pure returns (bool) {
|
||||
string memory composedEmail = "";
|
||||
for (uint256 i = 0; i < emailParts.length; i++) {
|
||||
composedEmail = string.concat(composedEmail, emailParts[i]);
|
||||
if (i < emailParts.length - 1) {
|
||||
composedEmail = string.concat(composedEmail, ".");
|
||||
}
|
||||
}
|
||||
|
||||
bytes memory emailBytes = bytes(email);
|
||||
bytes memory composedEmailBytes = bytes(composedEmail);
|
||||
|
||||
// Ensure composedEmail and emailBytes have the same length
|
||||
if (composedEmailBytes.length != emailBytes.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if the email parts are dot separated and match the claimed email
|
||||
// note since @ sign is not in ens encoding valid char set, we are arbitrarily replacing it with a $
|
||||
for (uint256 i = 0; i < emailBytes.length; i++) {
|
||||
bytes1 currentByte = emailBytes[i];
|
||||
if (currentByte == "@") {
|
||||
if (composedEmailBytes[i] != "$") {
|
||||
return false;
|
||||
}
|
||||
} else if (currentByte != composedEmailBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Flattens multiple arrays of field elements into a single array of length 60
|
||||
* @param inputs The arrays of field elements to flatten
|
||||
* @return out The flattened array of length 60
|
||||
*/
|
||||
function flattenFields(uint256[][] memory inputs) internal pure returns (uint256[60] memory out) {
|
||||
function flattenFields(uint256[][] memory inputs, uint256 outLength) internal pure returns (uint256[] memory out) {
|
||||
out = new uint256[](outLength);
|
||||
uint256 k = 0;
|
||||
for (uint256 i = 0; i < inputs.length; i++) {
|
||||
uint256[] memory arr = inputs[i];
|
||||
for (uint256 j = 0; j < arr.length; j++) {
|
||||
if (k >= 60) revert InvalidPubSignalsLength();
|
||||
if (k >= outLength) revert InvalidPubSignalsLength();
|
||||
out[k++] = arr[j];
|
||||
}
|
||||
}
|
||||
if (k != 60) revert InvalidPubSignalsLength();
|
||||
if (k != outLength) revert InvalidPubSignalsLength();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.30;
|
||||
|
||||
import { Test } from "forge-std/Test.sol";
|
||||
import { CircuitUtilsHelper } from "./_CircuitUtilsHelper.sol";
|
||||
|
||||
contract ExtractEmailPartsTest is Test {
|
||||
CircuitUtilsHelper private _helper;
|
||||
|
||||
function setUp() public {
|
||||
_helper = new CircuitUtilsHelper();
|
||||
}
|
||||
|
||||
function test_simpleEmail() public view {
|
||||
string memory email = "user@gmail.com";
|
||||
string[] memory parts = _helper.callExtractEmailParts(email);
|
||||
assertEq(parts.length, 2);
|
||||
assertEq(parts[0], "user$gmail");
|
||||
assertEq(parts[1], "com");
|
||||
}
|
||||
|
||||
function test_emailWithSubdomain() public view {
|
||||
string memory email = "user@sub.domain.com";
|
||||
string[] memory parts = _helper.callExtractEmailParts(email);
|
||||
assertEq(parts.length, 3);
|
||||
assertEq(parts[0], "user$sub");
|
||||
assertEq(parts[1], "domain");
|
||||
assertEq(parts[2], "com");
|
||||
}
|
||||
|
||||
function test_emailWithMultipleDots() public view {
|
||||
string memory email = "user@domain.co.uk";
|
||||
string[] memory parts = _helper.callExtractEmailParts(email);
|
||||
assertEq(parts.length, 3);
|
||||
assertEq(parts[0], "user$domain");
|
||||
assertEq(parts[1], "co");
|
||||
assertEq(parts[2], "uk");
|
||||
}
|
||||
|
||||
function test_complexEmail() public view {
|
||||
string memory email = "user.name+tag@sub.domain.co.uk";
|
||||
string[] memory parts = _helper.callExtractEmailParts(email);
|
||||
assertEq(parts.length, 5);
|
||||
assertEq(parts[0], "user");
|
||||
assertEq(parts[1], "name+tag$sub");
|
||||
assertEq(parts[2], "domain");
|
||||
assertEq(parts[3], "co");
|
||||
assertEq(parts[4], "uk");
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ contract FlattenFieldsTest is Test {
|
||||
inputs[1][i] = i + 31;
|
||||
}
|
||||
vm.expectRevert(CircuitUtils.InvalidPubSignalsLength.selector);
|
||||
_helper.callFlattenFields(inputs);
|
||||
_helper.callFlattenFields(inputs, 60);
|
||||
}
|
||||
|
||||
function test_expectRevert_tooFewElements() public {
|
||||
@@ -37,13 +37,13 @@ contract FlattenFieldsTest is Test {
|
||||
inputs[1][i] = i + 31;
|
||||
}
|
||||
vm.expectRevert(CircuitUtils.InvalidPubSignalsLength.selector);
|
||||
_helper.callFlattenFields(inputs);
|
||||
_helper.callFlattenFields(inputs, 60);
|
||||
}
|
||||
|
||||
function test_zeroArrays() public {
|
||||
uint256[][] memory inputs = new uint256[][](0);
|
||||
vm.expectRevert(CircuitUtils.InvalidPubSignalsLength.selector);
|
||||
_helper.callFlattenFields(inputs);
|
||||
_helper.callFlattenFields(inputs, 60);
|
||||
}
|
||||
|
||||
function test_singleArray() public view {
|
||||
@@ -52,7 +52,7 @@ contract FlattenFieldsTest is Test {
|
||||
for (uint256 i = 0; i < 60; i++) {
|
||||
inputs[0][i] = i + 1;
|
||||
}
|
||||
uint256[60] memory result = _helper.callFlattenFields(inputs);
|
||||
uint256[] memory result = _helper.callFlattenFields(inputs, 60);
|
||||
for (uint256 i = 0; i < 60; i++) {
|
||||
assertEq(result[i], i + 1);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ contract FlattenFieldsTest is Test {
|
||||
inputs[1][i] = i + 21;
|
||||
inputs[2][i] = i + 41;
|
||||
}
|
||||
uint256[60] memory result = _helper.callFlattenFields(inputs);
|
||||
uint256[] memory result = _helper.callFlattenFields(inputs, 60);
|
||||
for (uint256 i = 0; i < 20; i++) {
|
||||
assertEq(result[i], i + 1);
|
||||
assertEq(result[i + 20], i + 21);
|
||||
@@ -82,7 +82,7 @@ contract FlattenFieldsTest is Test {
|
||||
inputs[i] = new uint256[](1);
|
||||
inputs[i][0] = i + 1;
|
||||
}
|
||||
uint256[60] memory result = _helper.callFlattenFields(inputs);
|
||||
uint256[] memory result = _helper.callFlattenFields(inputs, 60);
|
||||
for (uint256 i = 0; i < 60; i++) {
|
||||
assertEq(result[i], i + 1);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,8 @@ contract CircuitUtilsHelper {
|
||||
return CircuitUtils.extractCommandParamByIndex(template, command, index);
|
||||
}
|
||||
|
||||
function callExtractEmailParts(string memory email) external pure returns (string[] memory) {
|
||||
return CircuitUtils.extractEmailParts(email);
|
||||
}
|
||||
|
||||
function callFlattenFields(uint256[][] memory inputs) external pure returns (uint256[60] memory) {
|
||||
return CircuitUtils.flattenFields(inputs);
|
||||
function callFlattenFields(uint256[][] memory inputs, uint256 outLength) external pure returns (uint256[] memory) {
|
||||
return CircuitUtils.flattenFields(inputs, outLength);
|
||||
}
|
||||
|
||||
function callPackBytes2Fields(bytes memory data, uint256 paddedSize) external pure returns (uint256[] memory) {
|
||||
|
||||
Reference in New Issue
Block a user