mirror of
https://github.com/zkemail/zk-email-verify.git
synced 2026-01-09 21:48:14 -05:00
80 lines
3.0 KiB
Plaintext
80 lines
3.0 KiB
Plaintext
pragma circom 2.1.6;
|
|
|
|
include "circomlib/circuits/comparators.circom";
|
|
include "circomlib/circuits/bitify.circom";
|
|
include "./bytes.circom";
|
|
|
|
/// @title SelectRegexReveal
|
|
/// @notice Returns reveal bytes of a regex match from the input
|
|
/// @notice Verifies data before and after (maxRevealLen) reveal part is zero
|
|
/// @notice Assumes that there is only one consecutive sequence of non-zero bytes in `in`.
|
|
/// @param maxArrayLen Maximum length of the input array
|
|
/// @param maxRevealLen Maximum length of the reveal part
|
|
/// @input in Input array; assumes elements to be bytes
|
|
/// @input startIndex The index from which reveal part starts; assumes a valid index,
|
|
/// and `startIndex + maxRevealLen - 1` fits in `ceil(log2((maxArrayLen + maxRevealLen - 1))` bits.
|
|
/// @output out Revealed data array
|
|
template SelectRegexReveal(maxArrayLen, maxRevealLen) {
|
|
signal input in[maxArrayLen];
|
|
signal input startIndex;
|
|
|
|
signal output out[maxRevealLen];
|
|
|
|
var bitLength = log2Ceil(maxArrayLen + maxRevealLen - 1);
|
|
|
|
signal isStartIndex[maxArrayLen];
|
|
signal isZero[maxArrayLen];
|
|
signal isPreviousZero[maxArrayLen];
|
|
signal isAboveMaxRevealLen[maxArrayLen];
|
|
|
|
isPreviousZero[0] <== 1;
|
|
for(var i = 0; i < maxArrayLen; i++) {
|
|
isStartIndex[i] <== IsEqual()([i, startIndex]);
|
|
isZero[i] <== IsZero()(in[i]);
|
|
if(i > 0) {
|
|
isPreviousZero[i] <== IsZero()(in[i - 1]);
|
|
}
|
|
isAboveMaxRevealLen[i] <== GreaterThan(bitLength)([i, startIndex + maxRevealLen - 1]);
|
|
|
|
// Assert startIndex is not zero
|
|
isStartIndex[i] * isZero[i] === 0;
|
|
|
|
// Assert value before startIndex is zero
|
|
// ZK-Regex circuit contstrains that every byte before the reveal part is zero
|
|
// This is assuming matched data doesn't contain 0 (null) byte
|
|
isStartIndex[i] * (1 - isPreviousZero[i]) === 0;
|
|
|
|
// Assert all values after startIndex + maxRevealLen are zero (for extra safety)
|
|
isAboveMaxRevealLen[i] * (1 - isZero[i]) === 0;
|
|
}
|
|
|
|
out <== VarShiftLeft(maxArrayLen, maxRevealLen)(in, startIndex);
|
|
}
|
|
|
|
|
|
/// @title PackRegexReveal
|
|
/// @notice Packs reveal data from a regex match into int[]
|
|
/// @param maxArrayLen Maximum length of the input array
|
|
/// @param maxRevealLen Maximum length of the reveal part
|
|
/// @input in Input array; assumes elements to be bytes
|
|
/// @input startIndex Index of the start of the reveal part; assumes a valid index
|
|
/// @output out Packed int array
|
|
template PackRegexReveal(maxArrayLen, maxRevealLen) {
|
|
var chunkSize = computeIntChunkLength(maxRevealLen);
|
|
|
|
signal input in[maxArrayLen];
|
|
signal input startIndex;
|
|
|
|
signal output out[chunkSize];
|
|
|
|
component extractor = SelectRegexReveal(maxArrayLen, maxRevealLen);
|
|
extractor.in <== in;
|
|
extractor.startIndex <== startIndex;
|
|
|
|
// Items after reveal part and before maxRevealLen are already asserted to zero
|
|
// So we can safely pack without an additional `length` input
|
|
component packer = PackBytes(maxRevealLen);
|
|
packer.in <== extractor.out;
|
|
out <== packer.out;
|
|
}
|