-
Notifications
You must be signed in to change notification settings - Fork 77
/
remove-soft-line-breaks.circom
126 lines (109 loc) · 4.08 KB
/
remove-soft-line-breaks.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
pragma circom 2.1.6;
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/mux1.circom";
include "../utils/hash.circom";
/// @title RemoveSoftLineBreaks
/// @notice This template verifies the removal of soft line breaks from an encoded input string
/// @dev Soft line breaks are defined as "=\r\n" sequences in the encoded input
/// @param maxLength The maximum length of the input strings
/// @input encoded An array of ASCII values representing the input string with potential soft line breaks
/// @input decoded An array of ASCII values representing the expected output after removing soft line breaks
/// @output isValid A signal that is 1 if the decoded input correctly represents the encoded input with soft line breaks removed, 0 otherwise
template RemoveSoftLineBreaks(maxLength) {
signal input encoded[maxLength];
signal input decoded[maxLength];
signal output isValid;
// Helper signals
signal r;
signal processed[maxLength];
signal isEquals[maxLength];
signal isCr[maxLength];
signal isLf[maxLength];
signal tempSoftBreak[maxLength - 2];
signal isSoftBreak[maxLength];
signal shouldZero[maxLength];
signal rEnc[maxLength];
signal sumEnc[maxLength];
signal rDec[maxLength];
signal sumDec[maxLength];
// Helper components
component muxEnc[maxLength];
// Deriving r from Poseidon hash
component rHasher = PoseidonModular(2 * maxLength);
for (var i = 0; i < maxLength; i++) {
rHasher.in[i] <== encoded[i];
}
for (var i = 0; i < maxLength; i++) {
rHasher.in[maxLength + i] <== decoded[i];
}
r <== rHasher.out;
// Check for '=' (61 in ASCII)
for (var i = 0; i < maxLength; i++) {
isEquals[i] <== IsEqual()([encoded[i], 61]);
}
// Check for '\r' (13 in ASCII)
for (var i = 0; i < maxLength - 1; i++) {
isCr[i] <== IsEqual()([encoded[i + 1], 13]);
}
isCr[maxLength - 1] <== 0;
// Check for '\n' (10 in ASCII)
for (var i = 0; i < maxLength - 2; i++) {
isLf[i] <== IsEqual()([encoded[i + 2], 10]);
}
isLf[maxLength - 2] <== 0;
isLf[maxLength - 1] <== 0;
// Identify soft line breaks
for (var i = 0; i < maxLength - 2; i++) {
tempSoftBreak[i] <== isEquals[i] * isCr[i];
isSoftBreak[i] <== tempSoftBreak[i] * isLf[i];
}
// Handle the last two characters
isSoftBreak[maxLength - 2] <== 0;
isSoftBreak[maxLength - 1] <== 0;
// Determine which characters should be zeroed
for (var i = 0; i < maxLength; i++) {
if (i == 0) {
shouldZero[i] <== isSoftBreak[i];
} else if (i == 1) {
shouldZero[i] <== isSoftBreak[i] + isSoftBreak[i-1];
} else if (i == maxLength - 1) {
shouldZero[i] <== isSoftBreak[i-1] + isSoftBreak[i-2];
} else {
shouldZero[i] <== isSoftBreak[i] + isSoftBreak[i-1] + isSoftBreak[i-2];
}
}
// Process the encoded input
for (var i = 0; i < maxLength; i++) {
processed[i] <== (1 - shouldZero[i]) * encoded[i];
}
// Calculate powers of r for encoded
muxEnc[0] = Mux1();
muxEnc[0].c[0] <== r;
muxEnc[0].c[1] <== 1;
muxEnc[0].s <== shouldZero[0];
rEnc[0] <== muxEnc[0].out;
for (var i = 1; i < maxLength; i++) {
muxEnc[i] = Mux1();
muxEnc[i].c[0] <== rEnc[i - 1] * r;
muxEnc[i].c[1] <== rEnc[i - 1];
muxEnc[i].s <== shouldZero[i];
rEnc[i] <== muxEnc[i].out;
}
// Calculate powers of r for decoded
rDec[0] <== r;
for (var i = 1; i < maxLength; i++) {
rDec[i] <== rDec[i - 1] * r;
}
// Calculate rlc for processed
sumEnc[0] <== rEnc[0] * processed[0];
for (var i = 1; i < maxLength; i++) {
sumEnc[i] <== sumEnc[i - 1] + rEnc[i] * processed[i];
}
// Calculate rlc for decoded
sumDec[0] <== rDec[0] * decoded[0];
for (var i = 1; i < maxLength; i++) {
sumDec[i] <== sumDec[i - 1] + rDec[i] * decoded[i];
}
// Check if rlc for decoded is equal to rlc for encoded
isValid <== IsEqual()([sumEnc[maxLength - 1], sumDec[maxLength - 1]]);
}