-
Notifications
You must be signed in to change notification settings - Fork 77
/
regex.circom
79 lines (63 loc) · 3.03 KB
/
regex.circom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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;
}